mirror of
https://github.com/gitbucket/gitbucket.git
synced 2026-01-03 22:30:06 +01:00
Reset password email by users themselves (#3023)
This commit is contained in:
@@ -128,6 +128,15 @@ trait AccountControllerBase extends AccountManagementControllerBase {
|
||||
"highlighterTheme" -> trim(label("Theme", text(required)))
|
||||
)(SyntaxHighlighterThemeForm.apply)
|
||||
|
||||
val resetPasswordEmailForm = mapping(
|
||||
"mailAddress" -> trim(label("Email", text(required)))
|
||||
)(ResetPasswordEmailForm.apply)
|
||||
|
||||
val resetPasswordForm = mapping(
|
||||
"token" -> trim(label("Token", text(required))),
|
||||
"password" -> trim(label("Password", text(required, maxlength(40))))
|
||||
)(ResetPasswordForm.apply)
|
||||
|
||||
case class NewGroupForm(
|
||||
groupName: String,
|
||||
description: Option[String],
|
||||
@@ -143,6 +152,13 @@ trait AccountControllerBase extends AccountManagementControllerBase {
|
||||
members: String,
|
||||
clearImage: Boolean
|
||||
)
|
||||
case class ResetPasswordEmailForm(
|
||||
mailAddress: String
|
||||
)
|
||||
case class ResetPasswordForm(
|
||||
token: String,
|
||||
password: String
|
||||
)
|
||||
|
||||
val newGroupForm = mapping(
|
||||
"groupName" -> trim(label("Group name", text(required, maxlength(100), identifier, uniqueUserName, reservedNames))),
|
||||
@@ -602,7 +618,7 @@ trait AccountControllerBase extends AccountManagementControllerBase {
|
||||
})
|
||||
|
||||
get("/register") {
|
||||
if (context.settings.allowAccountRegistration) {
|
||||
if (context.settings.basicBehavior.allowAccountRegistration) {
|
||||
if (context.loginAccount.isDefined) {
|
||||
redirect("/")
|
||||
} else {
|
||||
@@ -612,7 +628,7 @@ trait AccountControllerBase extends AccountManagementControllerBase {
|
||||
}
|
||||
|
||||
post("/register", newForm) { form =>
|
||||
if (context.settings.allowAccountRegistration) {
|
||||
if (context.settings.basicBehavior.allowAccountRegistration) {
|
||||
createAccount(
|
||||
form.userName,
|
||||
pbkdf2_sha256(form.password),
|
||||
@@ -628,6 +644,63 @@ trait AccountControllerBase extends AccountManagementControllerBase {
|
||||
} else NotFound()
|
||||
}
|
||||
|
||||
get("/reset") {
|
||||
if (context.settings.basicBehavior.allowResetPassword) {
|
||||
html.reset()
|
||||
} else NotFound()
|
||||
}
|
||||
|
||||
post("/reset", resetPasswordEmailForm) { form =>
|
||||
if (context.settings.basicBehavior.allowResetPassword) {
|
||||
getAccountByMailAddress(form.mailAddress).foreach { account =>
|
||||
val token = generateResetPasswordToken(form.mailAddress)
|
||||
val mailer = new Mailer(context.settings)
|
||||
mailer.send(
|
||||
form.mailAddress,
|
||||
"Reset password",
|
||||
s"""Hello, ${account.fullName}!
|
||||
|
|
||||
|You requested to reset the password for your GitBucket account.
|
||||
|If you are not sure about the request, you can ignore this email.
|
||||
|Otherwise, click the following link to set the new password:
|
||||
|${context.baseUrl}/reset/form/${token}
|
||||
|""".stripMargin
|
||||
)
|
||||
}
|
||||
redirect("/reset/sent")
|
||||
} else NotFound()
|
||||
}
|
||||
|
||||
get("/reset/sent") {
|
||||
if (context.settings.basicBehavior.allowResetPassword) {
|
||||
html.resetsent()
|
||||
} else NotFound()
|
||||
}
|
||||
|
||||
get("/reset/form/:token") {
|
||||
if (context.settings.basicBehavior.allowResetPassword) {
|
||||
val token = params("token")
|
||||
decodeResetPasswordToken(token)
|
||||
.map { _ =>
|
||||
html.resetform(token)
|
||||
}
|
||||
.getOrElse(NotFound())
|
||||
} else NotFound()
|
||||
}
|
||||
|
||||
post("/reset/form", resetPasswordForm) { form =>
|
||||
if (context.settings.basicBehavior.allowResetPassword) {
|
||||
decodeResetPasswordToken(form.token)
|
||||
.flatMap { mailAddress =>
|
||||
getAccountByMailAddress(mailAddress).map { account =>
|
||||
updateAccount(account.copy(password = form.password))
|
||||
html.resetcomplete()
|
||||
}
|
||||
}
|
||||
.getOrElse(NotFound())
|
||||
} else NotFound()
|
||||
}
|
||||
|
||||
get("/groups/new")(usersOnly {
|
||||
context.withLoginAccount { loginAccount =>
|
||||
html.creategroup(List(GroupMember("", loginAccount.userName, true)))
|
||||
@@ -713,7 +786,7 @@ trait AccountControllerBase extends AccountManagementControllerBase {
|
||||
*/
|
||||
get("/new")(usersOnly {
|
||||
context.withLoginAccount { loginAccount =>
|
||||
html.newrepo(getGroupsByUserName(loginAccount.userName), context.settings.isCreateRepoOptionPublic)
|
||||
html.newrepo(getGroupsByUserName(loginAccount.userName), context.settings.basicBehavior.isCreateRepoOptionPublic)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -723,7 +796,7 @@ trait AccountControllerBase extends AccountManagementControllerBase {
|
||||
post("/new", newRepositoryForm)(usersOnly { form =>
|
||||
context.withLoginAccount {
|
||||
loginAccount =>
|
||||
if (context.settings.repositoryOperation.create || loginAccount.isAdmin) {
|
||||
if (context.settings.basicBehavior.repositoryOperation.create || loginAccount.isAdmin) {
|
||||
LockUtil.lock(s"${form.owner}/${form.name}") {
|
||||
if (getRepository(form.owner, form.name).isDefined) {
|
||||
// redirect to the repository if repository already exists
|
||||
@@ -753,7 +826,7 @@ trait AccountControllerBase extends AccountManagementControllerBase {
|
||||
get("/:owner/:repository/fork")(readableUsersOnly { repository =>
|
||||
context.withLoginAccount {
|
||||
loginAccount =>
|
||||
if (repository.repository.options.allowFork && (context.settings.repositoryOperation.fork || loginAccount.isAdmin)) {
|
||||
if (repository.repository.options.allowFork && (context.settings.basicBehavior.repositoryOperation.fork || loginAccount.isAdmin)) {
|
||||
val loginUserName = loginAccount.userName
|
||||
val groups = getGroupsByUserName(loginUserName)
|
||||
groups match {
|
||||
@@ -780,7 +853,7 @@ trait AccountControllerBase extends AccountManagementControllerBase {
|
||||
post("/:owner/:repository/fork", accountForm)(readableUsersOnly { (form, repository) =>
|
||||
context.withLoginAccount {
|
||||
loginAccount =>
|
||||
if (repository.repository.options.allowFork && (context.settings.repositoryOperation.fork || loginAccount.isAdmin)) {
|
||||
if (repository.repository.options.allowFork && (context.settings.basicBehavior.repositoryOperation.fork || loginAccount.isAdmin)) {
|
||||
val loginUserName = loginAccount.userName
|
||||
val accountName = form.accountName
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ trait DashboardControllerBase extends ControllerBase {
|
||||
context.loginAccount,
|
||||
None,
|
||||
withoutPhysicalInfo = true,
|
||||
limit = context.settings.limitVisibleRepositories
|
||||
limit = context.settings.basicBehavior.limitVisibleRepositories
|
||||
)
|
||||
html.repos(getGroupNames(loginAccount.userName), repos, repos)
|
||||
}
|
||||
@@ -129,7 +129,7 @@ trait DashboardControllerBase extends ControllerBase {
|
||||
context.loginAccount,
|
||||
None,
|
||||
withoutPhysicalInfo = true,
|
||||
limit = context.settings.limitVisibleRepositories
|
||||
limit = context.settings.basicBehavior.limitVisibleRepositories
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -171,7 +171,7 @@ trait DashboardControllerBase extends ControllerBase {
|
||||
context.loginAccount,
|
||||
None,
|
||||
withoutPhysicalInfo = true,
|
||||
limit = context.settings.limitVisibleRepositories
|
||||
limit = context.settings.basicBehavior.limitVisibleRepositories
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ trait IndexControllerBase extends ControllerBase {
|
||||
Some(account),
|
||||
None,
|
||||
withoutPhysicalInfo = true,
|
||||
limit = context.settings.limitVisibleRepositories
|
||||
limit = context.settings.basicBehavior.limitVisibleRepositories
|
||||
),
|
||||
showBannerToCreatePersonalAccessToken = hasAccountFederation(account.userName) && !hasAccessToken(
|
||||
account.userName
|
||||
@@ -289,11 +289,11 @@ trait IndexControllerBase extends ControllerBase {
|
||||
context.loginAccount,
|
||||
None,
|
||||
withoutPhysicalInfo = true,
|
||||
limit = context.settings.limitVisibleRepositories
|
||||
limit = context.settings.basicBehavior.limitVisibleRepositories
|
||||
)
|
||||
|
||||
val repositories = {
|
||||
context.settings.limitVisibleRepositories match {
|
||||
context.settings.basicBehavior.limitVisibleRepositories match {
|
||||
case true =>
|
||||
getVisibleRepositories(
|
||||
context.loginAccount,
|
||||
|
||||
@@ -29,7 +29,7 @@ trait PreProcessControllerBase extends ControllerBase {
|
||||
* If anonymous access is allowed, pass all requests.
|
||||
* But if it's not allowed, demands authentication except some paths.
|
||||
*/
|
||||
get(!context.settings.allowAnonymousAccess, context.loginAccount.isEmpty) {
|
||||
get(!context.settings.basicBehavior.allowAnonymousAccess, context.loginAccount.isEmpty) {
|
||||
if (!context.currentPath.startsWith("/assets") && !context.currentPath.startsWith("/signin") &&
|
||||
!context.currentPath.startsWith("/register") && !context.currentPath.endsWith("/info/refs") &&
|
||||
!context.currentPath.startsWith("/plugin-assets") &&
|
||||
|
||||
@@ -390,7 +390,7 @@ trait RepositorySettingsControllerBase extends ControllerBase {
|
||||
post("/:owner/:repository/settings/rename", renameForm)(ownerOnly { (form, repository) =>
|
||||
context.withLoginAccount {
|
||||
loginAccount =>
|
||||
if (context.settings.repositoryOperation.rename || loginAccount.isAdmin) {
|
||||
if (context.settings.basicBehavior.repositoryOperation.rename || loginAccount.isAdmin) {
|
||||
if (repository.name != form.repositoryName) {
|
||||
// Update database and move git repository
|
||||
renameRepository(repository.owner, repository.name, repository.owner, form.repositoryName)
|
||||
@@ -414,7 +414,7 @@ trait RepositorySettingsControllerBase extends ControllerBase {
|
||||
post("/:owner/:repository/settings/transfer", transferForm)(ownerOnly { (form, repository) =>
|
||||
context.withLoginAccount {
|
||||
loginAccount =>
|
||||
if (context.settings.repositoryOperation.transfer || loginAccount.isAdmin) {
|
||||
if (context.settings.basicBehavior.repositoryOperation.transfer || loginAccount.isAdmin) {
|
||||
// Change repository owner
|
||||
if (repository.owner != form.newOwner) {
|
||||
// Update database and move git repository
|
||||
@@ -438,7 +438,7 @@ trait RepositorySettingsControllerBase extends ControllerBase {
|
||||
*/
|
||||
post("/:owner/:repository/settings/delete")(ownerOnly { repository =>
|
||||
context.withLoginAccount { loginAccount =>
|
||||
if (context.settings.repositoryOperation.delete || loginAccount.isAdmin) {
|
||||
if (context.settings.basicBehavior.repositoryOperation.delete || loginAccount.isAdmin) {
|
||||
// Delete the repository and related files
|
||||
deleteRepository(repository.repository)
|
||||
redirect(s"/${repository.owner}")
|
||||
|
||||
@@ -34,19 +34,22 @@ trait SystemSettingsControllerBase extends AccountManagementControllerBase {
|
||||
private val form = mapping(
|
||||
"baseUrl" -> trim(label("Base URL", optional(text()))),
|
||||
"information" -> trim(label("Information", optional(text()))),
|
||||
"allowAccountRegistration" -> trim(label("Account registration", boolean())),
|
||||
"allowAnonymousAccess" -> trim(label("Anonymous access", boolean())),
|
||||
"isCreateRepoOptionPublic" -> trim(label("Default visibility of new repository", boolean())),
|
||||
"repositoryOperation" -> mapping(
|
||||
"create" -> trim(label("Allow all users to create repository", boolean())),
|
||||
"delete" -> trim(label("Allow all users to delete repository", boolean())),
|
||||
"rename" -> trim(label("Allow all users to rename repository", boolean())),
|
||||
"transfer" -> trim(label("Allow all users to transfer repository", boolean())),
|
||||
"fork" -> trim(label("Allow all users to fork repository", boolean()))
|
||||
)(RepositoryOperation.apply),
|
||||
"gravatar" -> trim(label("Gravatar", boolean())),
|
||||
"notification" -> trim(label("Notification", boolean())),
|
||||
"limitVisibleRepositories" -> trim(label("limitVisibleRepositories", boolean())),
|
||||
"basicBehavior" -> mapping(
|
||||
"allowAccountRegistration" -> trim(label("Account registration", boolean())),
|
||||
"allowResetPassword" -> trim(label("Reset password", boolean())),
|
||||
"allowAnonymousAccess" -> trim(label("Anonymous access", boolean())),
|
||||
"isCreateRepoOptionPublic" -> trim(label("Default visibility of new repository", boolean())),
|
||||
"repositoryOperation" -> mapping(
|
||||
"create" -> trim(label("Allow all users to create repository", boolean())),
|
||||
"delete" -> trim(label("Allow all users to delete repository", boolean())),
|
||||
"rename" -> trim(label("Allow all users to rename repository", boolean())),
|
||||
"transfer" -> trim(label("Allow all users to transfer repository", boolean())),
|
||||
"fork" -> trim(label("Allow all users to fork repository", boolean()))
|
||||
)(RepositoryOperation.apply),
|
||||
"gravatar" -> trim(label("Gravatar", boolean())),
|
||||
"notification" -> trim(label("Notification", boolean())),
|
||||
"limitVisibleRepositories" -> trim(label("limitVisibleRepositories", boolean())),
|
||||
)(BasicBehavior.apply),
|
||||
"ssh" -> mapping(
|
||||
"enabled" -> trim(label("SSH access", boolean())),
|
||||
"bindAddress" -> mapping(
|
||||
@@ -334,7 +337,12 @@ trait SystemSettingsControllerBase extends AccountManagementControllerBase {
|
||||
|
||||
post("/admin/system/sendmail", sendMailForm)(adminOnly { form =>
|
||||
try {
|
||||
new Mailer(context.settings.copy(smtp = Some(form.smtp), notification = true)).send(
|
||||
new Mailer(
|
||||
context.settings.copy(
|
||||
smtp = Some(form.smtp),
|
||||
basicBehavior = context.settings.basicBehavior.copy(notification = true)
|
||||
)
|
||||
).send(
|
||||
to = form.testAddress,
|
||||
subject = "Test message from GitBucket",
|
||||
textMsg = "This is a test message from GitBucket.",
|
||||
|
||||
@@ -7,9 +7,14 @@ import gitbucket.core.model.Profile.profile.blockingApi._
|
||||
import gitbucket.core.model.Profile.dateColumnType
|
||||
import gitbucket.core.util.{LDAPUtil, StringUtil}
|
||||
import StringUtil._
|
||||
import com.nimbusds.jose.{Algorithm, JWSAlgorithm, JWSHeader}
|
||||
import com.nimbusds.jose.crypto.{MACSigner, MACVerifier}
|
||||
import com.nimbusds.jwt.{JWTClaimsSet, SignedJWT}
|
||||
import gitbucket.core.plugin.PluginRegistry
|
||||
import gitbucket.core.service.SystemSettingsService.SystemSettings
|
||||
|
||||
import java.security.SecureRandom
|
||||
|
||||
trait AccountService {
|
||||
|
||||
private val logger = LoggerFactory.getLogger(classOf[AccountService])
|
||||
@@ -337,6 +342,33 @@ trait AccountService {
|
||||
}
|
||||
}
|
||||
|
||||
def generateResetPasswordToken(mailAddress: String): String = {
|
||||
val claimsSet = new JWTClaimsSet.Builder()
|
||||
.claim("mailAddress", mailAddress)
|
||||
.expirationTime(new java.util.Date(System.currentTimeMillis() + 10 * 1000))
|
||||
.build()
|
||||
|
||||
val signedJWT = new SignedJWT(new JWSHeader(JWSAlgorithm.HS256), claimsSet)
|
||||
signedJWT.sign(new MACSigner(AccountService.jwtSecretKey))
|
||||
|
||||
signedJWT.serialize()
|
||||
}
|
||||
|
||||
def decodeResetPasswordToken(token: String): Option[String] = {
|
||||
try {
|
||||
val signedJWT = SignedJWT.parse(token)
|
||||
val verifier = new MACVerifier(AccountService.jwtSecretKey)
|
||||
if (signedJWT.verify(verifier) && new java.util.Date().before(signedJWT.getJWTClaimsSet().getExpirationTime())) {
|
||||
Some(signedJWT.getPayload.toJSONObject.get("mailAddress").toString)
|
||||
} else None
|
||||
} catch {
|
||||
case _: Exception => None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object AccountService extends AccountService
|
||||
object AccountService extends AccountService {
|
||||
// 256-bit key for HS256 which must be pre-shared
|
||||
val jwtSecretKey = new Array[Byte](32)
|
||||
new SecureRandom().nextBytes(jwtSecretKey)
|
||||
}
|
||||
|
||||
@@ -18,17 +18,18 @@ trait SystemSettingsService {
|
||||
val props = new java.util.Properties()
|
||||
settings.baseUrl.foreach(x => props.setProperty(BaseURL, x.replaceFirst("/\\Z", "")))
|
||||
settings.information.foreach(x => props.setProperty(Information, x))
|
||||
props.setProperty(AllowAccountRegistration, settings.allowAccountRegistration.toString)
|
||||
props.setProperty(AllowAnonymousAccess, settings.allowAnonymousAccess.toString)
|
||||
props.setProperty(IsCreateRepoOptionPublic, settings.isCreateRepoOptionPublic.toString)
|
||||
props.setProperty(RepositoryOperationCreate, settings.repositoryOperation.create.toString)
|
||||
props.setProperty(RepositoryOperationDelete, settings.repositoryOperation.delete.toString)
|
||||
props.setProperty(RepositoryOperationRename, settings.repositoryOperation.rename.toString)
|
||||
props.setProperty(RepositoryOperationTransfer, settings.repositoryOperation.transfer.toString)
|
||||
props.setProperty(RepositoryOperationFork, settings.repositoryOperation.fork.toString)
|
||||
props.setProperty(Gravatar, settings.gravatar.toString)
|
||||
props.setProperty(Notification, settings.notification.toString)
|
||||
props.setProperty(LimitVisibleRepositories, settings.limitVisibleRepositories.toString)
|
||||
props.setProperty(AllowAccountRegistration, settings.basicBehavior.allowAccountRegistration.toString)
|
||||
props.setProperty(AllowResetPassword, settings.basicBehavior.allowResetPassword.toString)
|
||||
props.setProperty(AllowAnonymousAccess, settings.basicBehavior.allowAnonymousAccess.toString)
|
||||
props.setProperty(IsCreateRepoOptionPublic, settings.basicBehavior.isCreateRepoOptionPublic.toString)
|
||||
props.setProperty(RepositoryOperationCreate, settings.basicBehavior.repositoryOperation.create.toString)
|
||||
props.setProperty(RepositoryOperationDelete, settings.basicBehavior.repositoryOperation.delete.toString)
|
||||
props.setProperty(RepositoryOperationRename, settings.basicBehavior.repositoryOperation.rename.toString)
|
||||
props.setProperty(RepositoryOperationTransfer, settings.basicBehavior.repositoryOperation.transfer.toString)
|
||||
props.setProperty(RepositoryOperationFork, settings.basicBehavior.repositoryOperation.fork.toString)
|
||||
props.setProperty(Gravatar, settings.basicBehavior.gravatar.toString)
|
||||
props.setProperty(Notification, settings.basicBehavior.notification.toString)
|
||||
props.setProperty(LimitVisibleRepositories, settings.basicBehavior.limitVisibleRepositories.toString)
|
||||
props.setProperty(SshEnabled, settings.ssh.enabled.toString)
|
||||
settings.ssh.bindAddress.foreach { bindAddress =>
|
||||
props.setProperty(SshBindAddressHost, bindAddress.host.trim())
|
||||
@@ -109,19 +110,22 @@ trait SystemSettingsService {
|
||||
SystemSettings(
|
||||
getOptionValue[String](props, BaseURL, None).map(x => x.replaceFirst("/\\Z", "")),
|
||||
getOptionValue(props, Information, None),
|
||||
getValue(props, AllowAccountRegistration, false),
|
||||
getValue(props, AllowAnonymousAccess, true),
|
||||
getValue(props, IsCreateRepoOptionPublic, true),
|
||||
RepositoryOperation(
|
||||
create = getValue(props, RepositoryOperationCreate, true),
|
||||
delete = getValue(props, RepositoryOperationDelete, true),
|
||||
rename = getValue(props, RepositoryOperationRename, true),
|
||||
transfer = getValue(props, RepositoryOperationTransfer, true),
|
||||
fork = getValue(props, RepositoryOperationFork, true)
|
||||
BasicBehavior(
|
||||
getValue(props, AllowAccountRegistration, false),
|
||||
getValue(props, AllowResetPassword, false),
|
||||
getValue(props, AllowAnonymousAccess, true),
|
||||
getValue(props, IsCreateRepoOptionPublic, true),
|
||||
RepositoryOperation(
|
||||
create = getValue(props, RepositoryOperationCreate, true),
|
||||
delete = getValue(props, RepositoryOperationDelete, true),
|
||||
rename = getValue(props, RepositoryOperationRename, true),
|
||||
transfer = getValue(props, RepositoryOperationTransfer, true),
|
||||
fork = getValue(props, RepositoryOperationFork, true)
|
||||
),
|
||||
getValue(props, Gravatar, false),
|
||||
getValue(props, Notification, false),
|
||||
getValue(props, LimitVisibleRepositories, false)
|
||||
),
|
||||
getValue(props, Gravatar, false),
|
||||
getValue(props, Notification, false),
|
||||
getValue(props, LimitVisibleRepositories, false),
|
||||
Ssh(
|
||||
enabled = getValue(props, SshEnabled, false),
|
||||
bindAddress = {
|
||||
@@ -214,13 +218,7 @@ object SystemSettingsService {
|
||||
case class SystemSettings(
|
||||
baseUrl: Option[String],
|
||||
information: Option[String],
|
||||
allowAccountRegistration: Boolean,
|
||||
allowAnonymousAccess: Boolean,
|
||||
isCreateRepoOptionPublic: Boolean,
|
||||
repositoryOperation: RepositoryOperation,
|
||||
gravatar: Boolean,
|
||||
notification: Boolean,
|
||||
limitVisibleRepositories: Boolean,
|
||||
basicBehavior: BasicBehavior,
|
||||
ssh: Ssh,
|
||||
useSMTP: Boolean,
|
||||
smtp: Option[Smtp],
|
||||
@@ -264,6 +262,17 @@ object SystemSettingsService {
|
||||
ssh.getUrl(owner: String, name: String)
|
||||
}
|
||||
|
||||
case class BasicBehavior(
|
||||
allowAccountRegistration: Boolean,
|
||||
allowResetPassword: Boolean,
|
||||
allowAnonymousAccess: Boolean,
|
||||
isCreateRepoOptionPublic: Boolean,
|
||||
repositoryOperation: RepositoryOperation,
|
||||
gravatar: Boolean,
|
||||
notification: Boolean,
|
||||
limitVisibleRepositories: Boolean,
|
||||
)
|
||||
|
||||
case class RepositoryOperation(
|
||||
create: Boolean,
|
||||
delete: Boolean,
|
||||
@@ -383,6 +392,7 @@ object SystemSettingsService {
|
||||
private val BaseURL = "base_url"
|
||||
private val Information = "information"
|
||||
private val AllowAccountRegistration = "allow_account_registration"
|
||||
private val AllowResetPassword = "allow_reset_password"
|
||||
private val AllowAnonymousAccess = "allow_anonymous_access"
|
||||
private val IsCreateRepoOptionPublic = "is_create_repository_option_public"
|
||||
private val RepositoryOperationCreate = "repository_operation_create"
|
||||
|
||||
@@ -98,29 +98,30 @@ class GitAuthenticationFilter extends Filter with RepositoryService with Account
|
||||
Database() withSession { implicit session =>
|
||||
getRepository(repositoryOwner, repositoryName.replaceFirst("(\\.wiki)?\\.git$", "")) match {
|
||||
case Some(repository) => {
|
||||
val execute = if (!isUpdating && !repository.repository.isPrivate && settings.allowAnonymousAccess) {
|
||||
// Authentication is not required
|
||||
true
|
||||
} else {
|
||||
// Authentication is required
|
||||
val passed = for {
|
||||
authorizationHeader <- Option(request.getHeader("Authorization"))
|
||||
account <- authenticateByHeader(authorizationHeader, settings)
|
||||
} yield
|
||||
if (isUpdating) {
|
||||
if (hasDeveloperRole(repository.owner, repository.name, Some(account))) {
|
||||
request.setAttribute(Keys.Request.UserName, account.userName)
|
||||
request.setAttribute(Keys.Request.RepositoryLockKey, s"${repository.owner}/${repository.name}")
|
||||
true
|
||||
} else false
|
||||
} else if (repository.repository.isPrivate) {
|
||||
if (hasGuestRole(repository.owner, repository.name, Some(account))) {
|
||||
request.setAttribute(Keys.Request.UserName, account.userName)
|
||||
true
|
||||
} else false
|
||||
} else true
|
||||
passed.getOrElse(false)
|
||||
}
|
||||
val execute =
|
||||
if (!isUpdating && !repository.repository.isPrivate && settings.basicBehavior.allowAnonymousAccess) {
|
||||
// Authentication is not required
|
||||
true
|
||||
} else {
|
||||
// Authentication is required
|
||||
val passed = for {
|
||||
authorizationHeader <- Option(request.getHeader("Authorization"))
|
||||
account <- authenticateByHeader(authorizationHeader, settings)
|
||||
} yield
|
||||
if (isUpdating) {
|
||||
if (hasDeveloperRole(repository.owner, repository.name, Some(account))) {
|
||||
request.setAttribute(Keys.Request.UserName, account.userName)
|
||||
request.setAttribute(Keys.Request.RepositoryLockKey, s"${repository.owner}/${repository.name}")
|
||||
true
|
||||
} else false
|
||||
} else if (repository.repository.isPrivate) {
|
||||
if (hasGuestRole(repository.owner, repository.name, Some(account))) {
|
||||
request.setAttribute(Keys.Request.UserName, account.userName)
|
||||
true
|
||||
} else false
|
||||
} else true
|
||||
passed.getOrElse(false)
|
||||
}
|
||||
|
||||
if (execute) { () =>
|
||||
chain.doFilter(request, response)
|
||||
|
||||
@@ -41,7 +41,7 @@ class Mailer(settings: SystemSettings) {
|
||||
htmlMsg: Option[String] = None,
|
||||
loginAccount: Option[Account] = None
|
||||
): Option[HtmlEmail] = {
|
||||
if (settings.notification) {
|
||||
if (settings.basicBehavior.notification) {
|
||||
settings.smtp.map { smtp =>
|
||||
val email = new HtmlEmail
|
||||
email.setHostName(smtp.host)
|
||||
|
||||
@@ -18,7 +18,7 @@ trait AvatarImageProvider { self: RequestCache =>
|
||||
val src = if (mailAddress.isEmpty) {
|
||||
// by user name
|
||||
getAccountByUserNameFromCache(userName).map { account =>
|
||||
if (account.image.isEmpty && context.settings.gravatar) {
|
||||
if (account.image.isEmpty && context.settings.basicBehavior.gravatar) {
|
||||
s"""https://www.gravatar.com/avatar/${StringUtil.md5(account.mailAddress.toLowerCase)}?s=${size}&d=retro&r=g"""
|
||||
} else {
|
||||
s"""${context.path}/${account.userName}/_avatar?${helpers.hashDate(account.updatedDate)}"""
|
||||
@@ -29,13 +29,13 @@ trait AvatarImageProvider { self: RequestCache =>
|
||||
} else {
|
||||
// by mail address
|
||||
getAccountByMailAddressFromCache(mailAddress).map { account =>
|
||||
if (account.image.isEmpty && context.settings.gravatar) {
|
||||
if (account.image.isEmpty && context.settings.basicBehavior.gravatar) {
|
||||
s"""https://www.gravatar.com/avatar/${StringUtil.md5(account.mailAddress.toLowerCase)}?s=${size}&d=retro&r=g"""
|
||||
} else {
|
||||
s"""${context.path}/${account.userName}/_avatar?${helpers.hashDate(account.updatedDate)}"""
|
||||
}
|
||||
} getOrElse {
|
||||
if (context.settings.gravatar) {
|
||||
if (context.settings.basicBehavior.gravatar) {
|
||||
s"""https://www.gravatar.com/avatar/${StringUtil.md5(mailAddress.toLowerCase)}?s=${size}&d=retro&r=g"""
|
||||
} else {
|
||||
s"""${context.path}/_unknown/_avatar"""
|
||||
|
||||
16
src/main/twirl/gitbucket/core/account/reset.scala.html
Normal file
16
src/main/twirl/gitbucket/core/account/reset.scala.html
Normal file
@@ -0,0 +1,16 @@
|
||||
@()(implicit context: gitbucket.core.controller.Context)
|
||||
@gitbucket.core.html.main("Reset your password"){
|
||||
<div class="content-wrapper main-center">
|
||||
<div class="content body">
|
||||
<h2>Reset your password</h2>
|
||||
<form action="@context.path/reset" method="POST" validate="true" autocomplete="off">
|
||||
<fieldset class="form-group">
|
||||
Enter your email address to reset your password.
|
||||
<input type="text" name="mailAddress" id="mailAddress" class="form-control" value="" value="" style="max-width: 400px;"/>
|
||||
<span id="error-mailAddress" class="error"></span>
|
||||
</fieldset>
|
||||
<input type="submit" class="btn btn-success" value="Submit"/>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
@()(implicit context: gitbucket.core.controller.Context)
|
||||
@gitbucket.core.html.main("Reset your password"){
|
||||
<div class="content-wrapper main-center">
|
||||
<div class="content body">
|
||||
<h2>Reset your password</h2>
|
||||
<p>
|
||||
Password has been updated. <a href="@context.path/signin">Sign-in</a> with new password.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
17
src/main/twirl/gitbucket/core/account/resetform.scala.html
Normal file
17
src/main/twirl/gitbucket/core/account/resetform.scala.html
Normal file
@@ -0,0 +1,17 @@
|
||||
@(token: String)(implicit context: gitbucket.core.controller.Context)
|
||||
@gitbucket.core.html.main("Reset your password"){
|
||||
<div class="content-wrapper main-center">
|
||||
<div class="content body">
|
||||
<h2>Reset your password</h2>
|
||||
<form action="@context.path/reset/form" method="POST" validate="true" autocomplete="off">
|
||||
<fieldset class="form-group">
|
||||
Enter new password:
|
||||
<input type="password" name="password" id="password" class="form-control" value="" style="max-width: 400px;"/>
|
||||
<span id="error-password" class="error"></span>
|
||||
</fieldset>
|
||||
<input type="submit" class="btn btn-success" value="Submit"/>
|
||||
<input type="hidden" name="token" id="token" value="@token"/>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
11
src/main/twirl/gitbucket/core/account/resetsent.scala.html
Normal file
11
src/main/twirl/gitbucket/core/account/resetsent.scala.html
Normal file
@@ -0,0 +1,11 @@
|
||||
@()(implicit context: gitbucket.core.controller.Context)
|
||||
@gitbucket.core.html.main("Reset your password"){
|
||||
<div class="content-wrapper main-center">
|
||||
<div class="content body">
|
||||
<h2>Reset your password</h2>
|
||||
<p>
|
||||
Send an email to you. Check your mailbox.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@@ -6,7 +6,7 @@
|
||||
<label class="strong">Services</label>
|
||||
<fieldset>
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" name="gravatar"@if(context.settings.gravatar){ checked}/>
|
||||
<input type="checkbox" name="basicBehavior.gravatar"@if(context.settings.basicBehavior.gravatar){ checked}/>
|
||||
Use Gravatar for profile images
|
||||
</label>
|
||||
</fieldset>
|
||||
@@ -132,7 +132,7 @@
|
||||
<label class="strong">Notifications</label>
|
||||
<fieldset>
|
||||
<label class="checkbox" for="notification">
|
||||
<input type="checkbox" id="notification" name="notification"@if(context.settings.notification){ checked}/>
|
||||
<input type="checkbox" id="notification" name="basicBehavior.notification"@if(context.settings.basicBehavior.notification){ checked}/>
|
||||
Send notifications
|
||||
</label>
|
||||
</fieldset>
|
||||
|
||||
@@ -108,15 +108,30 @@
|
||||
<label class="strong">Account registration</label>
|
||||
<fieldset>
|
||||
<label class="radio">
|
||||
<input type="radio" name="allowAccountRegistration" value="true"@if(context.settings.allowAccountRegistration){ checked}>
|
||||
<input type="radio" name="basicBehavior.allowAccountRegistration" value="true"@if(context.settings.basicBehavior.allowAccountRegistration){ checked}>
|
||||
<span class="strong">Allow</span> <span class="normal">- Users can create accounts by themselves.</span>
|
||||
</label>
|
||||
<label class="radio">
|
||||
<input type="radio" name="allowAccountRegistration" value="false"@if(!context.settings.allowAccountRegistration){ checked}>
|
||||
<input type="radio" name="basicBehavior.allowAccountRegistration" value="false"@if(!context.settings.basicBehavior.allowAccountRegistration){ checked}>
|
||||
<span class="strong">Deny</span> <span class="normal">- Only administrators can create accounts.</span>
|
||||
</label>
|
||||
</fieldset>
|
||||
<!--====================================================================-->
|
||||
<!-- Reset password -->
|
||||
<!--====================================================================-->
|
||||
<hr>
|
||||
<label class="strong">Reset password</label>
|
||||
<fieldset>
|
||||
<label class="radio">
|
||||
<input type="radio" name="basicBehavior.allowResetPassword" value="true"@if(context.settings.basicBehavior.allowResetPassword){ checked}>
|
||||
<span class="strong">Allow</span> <span class="normal">- Allow users to reset password. (SMTP setting is required)</span>
|
||||
</label>
|
||||
<label class="radio">
|
||||
<input type="radio" name="basicBehavior.allowResetPassword" value="false"@if(!context.settings.basicBehavior.allowResetPassword){ checked}>
|
||||
<span class="strong">Deny</span> <span class="normal">- Doesn't allow users to reset password.</span>
|
||||
</label>
|
||||
</fieldset>
|
||||
<!--====================================================================-->
|
||||
<!-- Repository operations -->
|
||||
<!--====================================================================-->
|
||||
<hr>
|
||||
@@ -126,11 +141,11 @@
|
||||
<label class="control-label col-md-2">Create</label>
|
||||
<div class="col-md-10">
|
||||
<label class="radio">
|
||||
<input type="radio" name="repositoryOperation.create" value="true"@if(context.settings.repositoryOperation.create){ checked}>
|
||||
<input type="radio" name="basicBehavior.repositoryOperation.create" value="true"@if(context.settings.basicBehavior.repositoryOperation.create){ checked}>
|
||||
<span class="strong">All users</span> <span class="normal">- All users can create repository.</span>
|
||||
</label>
|
||||
<label class="radio">
|
||||
<input type="radio" name="repositoryOperation.create" value="false"@if(!context.settings.repositoryOperation.create){ checked}>
|
||||
<input type="radio" name="basicBehavior.repositoryOperation.create" value="false"@if(!context.settings.basicBehavior.repositoryOperation.create){ checked}>
|
||||
<span class="strong">Admin only</span> <span class="normal">- Only administrators can create repository.</span>
|
||||
</label>
|
||||
</div>
|
||||
@@ -139,11 +154,11 @@
|
||||
<label class="control-label col-md-2">Delete</label>
|
||||
<div class="col-md-10">
|
||||
<label class="radio">
|
||||
<input type="radio" name="repositoryOperation.delete" value="true"@if(context.settings.repositoryOperation.delete){ checked}>
|
||||
<input type="radio" name="basicBehavior.repositoryOperation.delete" value="true"@if(context.settings.basicBehavior.repositoryOperation.delete){ checked}>
|
||||
<span class="strong">All users</span> <span class="normal">- All users can delete repository.</span>
|
||||
</label>
|
||||
<label class="radio">
|
||||
<input type="radio" name="repositoryOperation.delete" value="false"@if(!context.settings.repositoryOperation.delete){ checked}>
|
||||
<input type="radio" name="basicBehavior.repositoryOperation.delete" value="false"@if(!context.settings.basicBehavior.repositoryOperation.delete){ checked}>
|
||||
<span class="strong">Admin only</span> <span class="normal">- Only administrators can delete repository.</span>
|
||||
</label>
|
||||
</div>
|
||||
@@ -152,11 +167,11 @@
|
||||
<label class="control-label col-md-2">Rename</label>
|
||||
<div class="col-md-10">
|
||||
<label class="radio">
|
||||
<input type="radio" name="repositoryOperation.rename" value="true"@if(context.settings.repositoryOperation.rename){ checked}>
|
||||
<input type="radio" name="basicBehavior.repositoryOperation.rename" value="true"@if(context.settings.basicBehavior.repositoryOperation.rename){ checked}>
|
||||
<span class="strong">All users</span> <span class="normal">- All users can rename repository.</span>
|
||||
</label>
|
||||
<label class="radio">
|
||||
<input type="radio" name="repositoryOperation.rename" value="false"@if(!context.settings.repositoryOperation.rename){ checked}>
|
||||
<input type="radio" name="basicBehavior.repositoryOperation.rename" value="false"@if(!context.settings.basicBehavior.repositoryOperation.rename){ checked}>
|
||||
<span class="strong">Admin only</span> <span class="normal">- Only administrators can rename repository.</span>
|
||||
</label>
|
||||
</div>
|
||||
@@ -165,11 +180,11 @@
|
||||
<label class="control-label col-md-2">Transfer</label>
|
||||
<div class="col-md-10">
|
||||
<label class="radio">
|
||||
<input type="radio" name="repositoryOperation.transfer" value="true"@if(context.settings.repositoryOperation.transfer){ checked}>
|
||||
<input type="radio" name="basicBehavior.repositoryOperation.transfer" value="true"@if(context.settings.basicBehavior.repositoryOperation.transfer){ checked}>
|
||||
<span class="strong">All users</span> <span class="normal">- All users can transfer repository.</span>
|
||||
</label>
|
||||
<label class="radio">
|
||||
<input type="radio" name="repositoryOperation.transfer" value="false"@if(!context.settings.repositoryOperation.transfer){ checked}>
|
||||
<input type="radio" name="basicBehavior.repositoryOperation.transfer" value="false"@if(!context.settings.basicBehavior.repositoryOperation.transfer){ checked}>
|
||||
<span class="strong">Admin only</span> <span class="normal">- Only administrators can transfer repository.</span>
|
||||
</label>
|
||||
</div>
|
||||
@@ -178,11 +193,11 @@
|
||||
<label class="control-label col-md-2">Fork</label>
|
||||
<div class="col-md-10">
|
||||
<label class="radio">
|
||||
<input type="radio" name="repositoryOperation.fork" value="true"@if(context.settings.repositoryOperation.fork){ checked}>
|
||||
<input type="radio" name="basicBehavior.repositoryOperation.fork" value="true"@if(context.settings.basicBehavior.repositoryOperation.fork){ checked}>
|
||||
<span class="strong">All users</span> <span class="normal">- All users can fork repository.</span>
|
||||
</label>
|
||||
<label class="radio">
|
||||
<input type="radio" name="repositoryOperation.fork" value="false"@if(!context.settings.repositoryOperation.fork){ checked}>
|
||||
<input type="radio" name="basicBehavior.repositoryOperation.fork" value="false"@if(!context.settings.basicBehavior.repositoryOperation.fork){ checked}>
|
||||
<span class="strong">Admin only</span> <span class="normal">- Only administrators can fork repository.</span>
|
||||
</label>
|
||||
</div>
|
||||
@@ -192,11 +207,11 @@
|
||||
<label class="strong">Default visibility when creating a new repository</label>
|
||||
<fieldset>
|
||||
<label class="radio">
|
||||
<input type="radio" name="isCreateRepoOptionPublic" value="true"@if(context.settings.isCreateRepoOptionPublic){ checked}>
|
||||
<input type="radio" name="basicBehavior.isCreateRepoOptionPublic" value="true"@if(context.settings.basicBehavior.isCreateRepoOptionPublic){ checked}>
|
||||
<span class="strong">Public</span> <span class="normal">- All users and guests can read the repository.</span>
|
||||
</label>
|
||||
<label class="radio">
|
||||
<input type="radio" name="isCreateRepoOptionPublic" value="false"@if(!context.settings.isCreateRepoOptionPublic){ checked}>
|
||||
<input type="radio" name="basicBehavior.isCreateRepoOptionPublic" value="false"@if(!context.settings.basicBehavior.isCreateRepoOptionPublic){ checked}>
|
||||
<span class="strong">Private</span> <span class="normal">- Only collaborators can read the repository.</span>
|
||||
</label>
|
||||
</fieldset>
|
||||
@@ -207,11 +222,11 @@
|
||||
<label class="strong">Anonymous access</label>
|
||||
<fieldset>
|
||||
<label class="radio">
|
||||
<input type="radio" name="allowAnonymousAccess" value="true"@if(context.settings.allowAnonymousAccess){ checked}>
|
||||
<input type="radio" name="basicBehavior.allowAnonymousAccess" value="true"@if(context.settings.basicBehavior.allowAnonymousAccess){ checked}>
|
||||
<span class="strong">Allow</span> <span class="normal">- Anyone can view public repositories and user/group profiles.</span>
|
||||
</label>
|
||||
<label class="radio">
|
||||
<input type="radio" name="allowAnonymousAccess" value="false"@if(!context.settings.allowAnonymousAccess){ checked}>
|
||||
<input type="radio" name="basicBehavior.allowAnonymousAccess" value="false"@if(!context.settings.basicBehavior.allowAnonymousAccess){ checked}>
|
||||
<span class="strong">Deny</span> <span class="normal">- Users must authenticate before viewing any information.</span>
|
||||
</label>
|
||||
</fieldset>
|
||||
@@ -272,11 +287,11 @@
|
||||
<label><span class="strong">Show repositories in sidebar</span></label>
|
||||
<fieldset>
|
||||
<label class="radio">
|
||||
<input type="radio" name="limitVisibleRepositories" value="false"@if(!context.settings.limitVisibleRepositories){ checked}>
|
||||
<input type="radio" name="basicBehavior.limitVisibleRepositories" value="false"@if(!context.settings.basicBehavior.limitVisibleRepositories){ checked}>
|
||||
<span class="strong">All</span> <span class="normal">- Show all visible repositories in sidebar.</span>
|
||||
</label>
|
||||
<label class="radio">
|
||||
<input type="radio" name="limitVisibleRepositories" value="true"@if(context.settings.limitVisibleRepositories){ checked}>
|
||||
<input type="radio" name="basicBehavior.limitVisibleRepositories" value="true"@if(context.settings.basicBehavior.limitVisibleRepositories){ checked}>
|
||||
<span class="strong">Limited</span> <span class="normal">- Show only owned repositories in sidebar.</span>
|
||||
</label>
|
||||
</fieldset>
|
||||
|
||||
@@ -104,7 +104,7 @@
|
||||
<ul class="dropdown-menu pull-right" style="width: auto;">
|
||||
<li>
|
||||
<ul class="menu">
|
||||
@if(context.settings.repositoryOperation.create || context.loginAccount.get.isAdmin){
|
||||
@if(context.settings.basicBehavior.repositoryOperation.create || context.loginAccount.get.isAdmin){
|
||||
<li><a href="@context.path/new">New repository</a></li>
|
||||
}
|
||||
<li><a href="@context.path/groups/new">New group</a></li>
|
||||
|
||||
@@ -75,7 +75,7 @@
|
||||
@gitbucket.core.plugin.PluginRegistry().getRepositoryHeaders.map { repositoryHeaderComponent =>
|
||||
@repositoryHeaderComponent(repository, context)
|
||||
}
|
||||
@if(repository.repository.options.allowFork && (context.settings.repositoryOperation.fork || context.loginAccount.map(_.isAdmin).getOrElse(false))) {
|
||||
@if(repository.repository.options.allowFork && (context.settings.basicBehavior.repositoryOperation.fork || context.loginAccount.map(_.isAdmin).getOrElse(false))) {
|
||||
@if(context.loginAccount.isEmpty){
|
||||
<a class="btn btn-default btn-sm" href="@context.path/signin?redirect=@helpers.urlEncode(s"${context.path}/${repository.owner}/${repository.name}")">
|
||||
<span class="strong"><i class="octicon octicon-repo-forked"></i>Fork</span><span class="muted">: @repository.forkedCount</span>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
@if(context.settings.repositoryOperation.rename || context.loginAccount.get.isAdmin){
|
||||
@if(context.settings.basicBehavior.repositoryOperation.rename || context.loginAccount.get.isAdmin){
|
||||
<form id="rename-form" method="post" action="@helpers.url(repository)/settings/rename" validate="true" autocomplete="off">
|
||||
<fieldset class="border-top form-group">
|
||||
<label class="strong">Rename repository</label>
|
||||
@@ -33,7 +33,7 @@
|
||||
</fieldset>
|
||||
</form>
|
||||
}
|
||||
@if(context.settings.repositoryOperation.transfer || context.loginAccount.get.isAdmin){
|
||||
@if(context.settings.basicBehavior.repositoryOperation.transfer || context.loginAccount.get.isAdmin){
|
||||
<form id="transfer-form" method="post" action="@helpers.url(repository)/settings/transfer" validate="true" autocomplete="off">
|
||||
<fieldset class="border-top form-group">
|
||||
<label class="strong">Transfer Ownership</label>
|
||||
@@ -50,7 +50,7 @@
|
||||
</fieldset>
|
||||
</form>
|
||||
}
|
||||
@if(context.settings.repositoryOperation.delete || context.loginAccount.get.isAdmin){
|
||||
@if(context.settings.basicBehavior.repositoryOperation.delete || context.loginAccount.get.isAdmin){
|
||||
<form id="delete-form" method="post" action="@helpers.url(repository)/settings/delete">
|
||||
<fieldset class="border-top form-group">
|
||||
<label class="strong">Delete repository</label>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<div class="content-wrapper main-center">
|
||||
<div class="content body">
|
||||
<div class="signin-form">
|
||||
@if(context.settings.allowAnonymousAccess){
|
||||
@if(context.settings.basicBehavior.allowAnonymousAccess){
|
||||
@context.settings.information.map { information =>
|
||||
<div class="alert alert-info" style="background-color: white; color: #555; border-color: #4183c4; font-size: small; line-height: 120%;">
|
||||
<button type="button" class="close" data-dismiss="alert">×</button>
|
||||
|
||||
@@ -24,6 +24,9 @@
|
||||
<label for="password">Password:</label>
|
||||
<span id="error-password" class="error"></span>
|
||||
<input type="password" name="password" id="password" class="form-control" value="@password"/>
|
||||
@if(systemSettings.basicBehavior.allowResetPassword){
|
||||
<a href="@context.path/reset">Forgot password?</a>
|
||||
}
|
||||
</div>
|
||||
<input type="hidden" name="hash"/>
|
||||
<div>
|
||||
@@ -33,12 +36,12 @@
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
@if(systemSettings.allowAccountRegistration){
|
||||
@if(systemSettings.basicBehavior.allowAccountRegistration){
|
||||
<div class="panel panel-default">
|
||||
<ul class="list-group list-group-flush">
|
||||
<li class="list-group-item text-center">
|
||||
Don't have an account? <a href="@context.path/register">Create one.</a>
|
||||
<a href="@context.path/register">Create account</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,11 +8,18 @@ import liquibase.database.jvm.JdbcConnection
|
||||
import gitbucket.core.model._
|
||||
import gitbucket.core.model.Profile.profile.blockingApi._
|
||||
import org.apache.commons.io.FileUtils
|
||||
|
||||
import java.sql.DriverManager
|
||||
import java.io.File
|
||||
|
||||
import gitbucket.core.controller.Context
|
||||
import gitbucket.core.service.SystemSettingsService.{RepositoryOperation, RepositoryViewerSettings, Ssh, SystemSettings}
|
||||
import gitbucket.core.service.SystemSettingsService.{
|
||||
BasicBehavior,
|
||||
RepositoryOperation,
|
||||
RepositoryViewerSettings,
|
||||
Ssh,
|
||||
SystemSettings
|
||||
}
|
||||
|
||||
import javax.servlet.http.{HttpServletRequest, HttpSession}
|
||||
import org.mockito.Mockito._
|
||||
|
||||
@@ -32,19 +39,22 @@ trait ServiceSpecBase {
|
||||
SystemSettings(
|
||||
baseUrl = None,
|
||||
information = None,
|
||||
allowAccountRegistration = false,
|
||||
allowAnonymousAccess = true,
|
||||
isCreateRepoOptionPublic = true,
|
||||
repositoryOperation = RepositoryOperation(
|
||||
create = true,
|
||||
delete = true,
|
||||
rename = true,
|
||||
transfer = true,
|
||||
fork = true
|
||||
basicBehavior = BasicBehavior(
|
||||
allowAccountRegistration = false,
|
||||
allowResetPassword = false,
|
||||
allowAnonymousAccess = true,
|
||||
isCreateRepoOptionPublic = true,
|
||||
repositoryOperation = RepositoryOperation(
|
||||
create = true,
|
||||
delete = true,
|
||||
rename = true,
|
||||
transfer = true,
|
||||
fork = true
|
||||
),
|
||||
gravatar = false,
|
||||
notification = false,
|
||||
limitVisibleRepositories = false,
|
||||
),
|
||||
gravatar = false,
|
||||
notification = false,
|
||||
limitVisibleRepositories = false,
|
||||
ssh = Ssh(
|
||||
enabled = false,
|
||||
bindAddress = None,
|
||||
|
||||
@@ -2,12 +2,12 @@ package gitbucket.core.view
|
||||
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
|
||||
import javax.servlet.http.{HttpServletRequest, HttpSession}
|
||||
import gitbucket.core.controller.Context
|
||||
import gitbucket.core.model.Account
|
||||
import gitbucket.core.service.RequestCache
|
||||
import gitbucket.core.service.SystemSettingsService.{
|
||||
BasicBehavior,
|
||||
RepositoryOperation,
|
||||
RepositoryViewerSettings,
|
||||
Ssh,
|
||||
@@ -151,19 +151,22 @@ class AvatarImageProviderSpec extends AnyFunSpec {
|
||||
SystemSettings(
|
||||
baseUrl = None,
|
||||
information = None,
|
||||
allowAccountRegistration = false,
|
||||
allowAnonymousAccess = true,
|
||||
isCreateRepoOptionPublic = true,
|
||||
repositoryOperation = RepositoryOperation(
|
||||
create = true,
|
||||
delete = true,
|
||||
rename = true,
|
||||
transfer = true,
|
||||
fork = true
|
||||
basicBehavior = BasicBehavior(
|
||||
allowAccountRegistration = false,
|
||||
allowResetPassword = false,
|
||||
allowAnonymousAccess = true,
|
||||
isCreateRepoOptionPublic = true,
|
||||
repositoryOperation = RepositoryOperation(
|
||||
create = true,
|
||||
delete = true,
|
||||
rename = true,
|
||||
transfer = true,
|
||||
fork = true
|
||||
),
|
||||
gravatar = useGravatar,
|
||||
notification = false,
|
||||
limitVisibleRepositories = false
|
||||
),
|
||||
gravatar = useGravatar,
|
||||
notification = false,
|
||||
limitVisibleRepositories = false,
|
||||
ssh = Ssh(
|
||||
enabled = false,
|
||||
bindAddress = None,
|
||||
|
||||
Reference in New Issue
Block a user