diff --git a/.scalafmt.conf b/.scalafmt.conf index c8ace92..729819b 100644 --- a/.scalafmt.conf +++ b/.scalafmt.conf @@ -1,4 +1,4 @@ -version = "2.6.1" +version = "1.5.1" project.git = true maxColumn = 120 diff --git a/src/main/scala/gitbucket/core/controller/AccountController.scala b/src/main/scala/gitbucket/core/controller/AccountController.scala index 40bd892..f187e29 100644 --- a/src/main/scala/gitbucket/core/controller/AccountController.scala +++ b/src/main/scala/gitbucket/core/controller/AccountController.scala @@ -16,6 +16,7 @@ import org.scalatra.i18n.Messages import org.scalatra.BadRequest import org.scalatra.forms._ +import org.scalatra.Forbidden class AccountController extends AccountControllerBase @@ -691,27 +692,28 @@ * Create new repository. */ post("/new", newRepositoryForm)(usersOnly { form => - LockUtil.lock(s"${form.owner}/${form.name}") { - if (getRepository(form.owner, form.name).isEmpty) { - createRepository( - context.loginAccount.get, - form.owner, - form.name, - form.description, - form.isPrivate, - form.initOption, - form.sourceUrl - ) + if (context.settings.repositoryOperation.create || context.loginAccount.get.isAdmin) { + LockUtil.lock(s"${form.owner}/${form.name}") { + if (getRepository(form.owner, form.name).isEmpty) { + createRepository( + context.loginAccount.get, + form.owner, + form.name, + form.description, + form.isPrivate, + form.initOption, + form.sourceUrl + ) + } } - } - - // redirect to the repository - redirect(s"/${form.owner}/${form.name}") + // redirect to the repository + redirect(s"/${form.owner}/${form.name}") + } else Forbidden() }) get("/:owner/:repository/fork")(readableUsersOnly { repository => - if (repository.repository.options.allowFork) { - val loginAccount = context.loginAccount.get + val loginAccount = context.loginAccount.get + if (repository.repository.options.allowFork && (context.settings.repositoryOperation.fork || loginAccount.isAdmin)) { val loginUserName = loginAccount.userName val groups = getGroupsByUserName(loginUserName) groups match { @@ -735,8 +737,8 @@ }) post("/:owner/:repository/fork", accountForm)(readableUsersOnly { (form, repository) => - if (repository.repository.options.allowFork) { - val loginAccount = context.loginAccount.get + val loginAccount = context.loginAccount.get + if (repository.repository.options.allowFork && (context.settings.repositoryOperation.fork || loginAccount.isAdmin)) { val loginUserName = loginAccount.userName val accountName = form.accountName @@ -750,7 +752,7 @@ // redirect to the repository redirect(s"/${accountName}/${repository.name}") } - } else BadRequest() + } else Forbidden() }) private def existsAccount: Constraint = new Constraint() { diff --git a/src/main/scala/gitbucket/core/controller/RepositorySettingsController.scala b/src/main/scala/gitbucket/core/controller/RepositorySettingsController.scala index 7f22e24..0e34d94 100644 --- a/src/main/scala/gitbucket/core/controller/RepositorySettingsController.scala +++ b/src/main/scala/gitbucket/core/controller/RepositorySettingsController.scala @@ -20,6 +20,7 @@ import org.eclipse.jgit.lib.ObjectId import scala.util.Using +import org.scalatra.Forbidden class RepositorySettingsController extends RepositorySettingsControllerBase @@ -44,7 +45,6 @@ // for repository options case class OptionsForm( - repositoryName: String, description: Option[String], isPrivate: Boolean, issuesOption: String, @@ -57,9 +57,6 @@ ) val optionsForm = mapping( - "repositoryName" -> trim( - label("Repository Name", text(required, maxlength(100), repository, renameRepositoryName)) - ), "description" -> trim(label("Description", optional(text()))), "isPrivate" -> trim(label("Repository Type", boolean())), "issuesOption" -> trim(label("Issues Option", text(required, featureOption))), @@ -104,6 +101,15 @@ (url, events, ctype, token) => WebHookForm(url, events, WebHookContentType.valueOf(ctype), token) ) + // for rename repository + case class RenameRepositoryForm(repositoryName: String) + + val renameForm = mapping( + "repositoryName" -> trim( + label("New repository name", text(required, maxlength(100), repository, renameRepositoryName)) + ) + )(RenameRepositoryForm.apply) + // for transfer ownership case class TransferOwnerShipForm(newOwner: String) @@ -144,13 +150,8 @@ form.mergeOptions, form.defaultMergeOption ) - // Change repository name - if (repository.name != form.repositoryName) { - // Update database - renameRepository(repository.owner, repository.name, repository.owner, form.repositoryName) - } flash.update("info", "Repository settings has been updated.") - redirect(s"/${repository.owner}/${form.repositoryName}/settings/options") + redirect(s"/${repository.owner}/${repository.name}/settings/options") }) /** branch settings */ @@ -365,23 +366,39 @@ }) /** + * Rename repository. + */ + post("/:owner/:repository/settings/rename", renameForm)(ownerOnly { (form, repository) => + if (context.settings.repositoryOperation.rename || context.loginAccount.get.isAdmin) { + if (repository.name != form.repositoryName) { + renameRepository(repository.owner, repository.name, repository.owner, form.repositoryName) + } + redirect(s"/${repository.owner}/${form.repositoryName}") + } else Forbidden() + }) + + /** * Transfer repository ownership. */ post("/:owner/:repository/settings/transfer", transferForm)(ownerOnly { (form, repository) => - // Change repository owner - if (repository.owner != form.newOwner) { - renameRepository(repository.owner, repository.name, form.newOwner, repository.name) - } - redirect(s"/${form.newOwner}/${repository.name}") + if (context.settings.repositoryOperation.transfer || context.loginAccount.get.isAdmin) { + // Change repository owner + if (repository.owner != form.newOwner) { + renameRepository(repository.owner, repository.name, form.newOwner, repository.name) + } + redirect(s"/${form.newOwner}/${repository.name}") + } else Forbidden() }) /** * Delete the repository. */ post("/:owner/:repository/settings/delete")(ownerOnly { repository => - // Delete the repository and related files - deleteRepository(repository.repository) - redirect(s"/${repository.owner}") + if (context.settings.repositoryOperation.delete || context.loginAccount.get.isAdmin) { + // Delete the repository and related files + deleteRepository(repository.repository) + redirect(s"/${repository.owner}") + } else Forbidden() }) /** diff --git a/src/main/scala/gitbucket/core/controller/SystemSettingsController.scala b/src/main/scala/gitbucket/core/controller/SystemSettingsController.scala index 0039dc0..469ffdd 100644 --- a/src/main/scala/gitbucket/core/controller/SystemSettingsController.scala +++ b/src/main/scala/gitbucket/core/controller/SystemSettingsController.scala @@ -38,7 +38,14 @@ "information" -> trim(label("Information", optional(text()))), "allowAccountRegistration" -> trim(label("Account registration", boolean())), "allowAnonymousAccess" -> trim(label("Anonymous access", boolean())), - "isCreateRepoOptionPublic" -> trim(label("Default option to create a new repository", 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())), "activityLogLimit" -> trim(label("Limit of activity logs", optional(number()))), diff --git a/src/main/scala/gitbucket/core/service/SystemSettingsService.scala b/src/main/scala/gitbucket/core/service/SystemSettingsService.scala index 44bff3f..2d6dcbf 100644 --- a/src/main/scala/gitbucket/core/service/SystemSettingsService.scala +++ b/src/main/scala/gitbucket/core/service/SystemSettingsService.scala @@ -21,6 +21,11 @@ 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) settings.activityLogLimit.foreach(x => props.setProperty(ActivityLogLimit, x.toString)) @@ -98,6 +103,13 @@ 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) + ), getValue(props, Gravatar, false), getValue(props, Notification, false), getOptionValue[Int](props, ActivityLogLimit, None), @@ -185,6 +197,7 @@ allowAccountRegistration: Boolean, allowAnonymousAccess: Boolean, isCreateRepoOptionPublic: Boolean, + repositoryOperation: RepositoryOperation, gravatar: Boolean, notification: Boolean, activityLogLimit: Option[Int], @@ -226,6 +239,14 @@ } } + case class RepositoryOperation( + create: Boolean, + delete: Boolean, + rename: Boolean, + transfer: Boolean, + fork: Boolean + ) + case class Ssh( enabled: Boolean, sshHost: Option[String], @@ -291,6 +312,11 @@ private val AllowAccountRegistration = "allow_account_registration" private val AllowAnonymousAccess = "allow_anonymous_access" private val IsCreateRepoOptionPublic = "is_create_repository_option_public" + private val RepositoryOperationCreate = "repository_operation_create" + private val RepositoryOperationDelete = "repository_operation_delete" + private val RepositoryOperationRename = "repository_operation_rename" + private val RepositoryOperationTransfer = "repository_operation_transfer" + private val RepositoryOperationFork = "repository_operation_fork" private val Gravatar = "gravatar" private val Notification = "notification" private val ActivityLogLimit = "activity_log_limit" diff --git a/src/main/twirl/gitbucket/core/admin/settings_system.scala.html b/src/main/twirl/gitbucket/core/admin/settings_system.scala.html index 411463e..b2f7f0a 100644 --- a/src/main/twirl/gitbucket/core/admin/settings_system.scala.html +++ b/src/main/twirl/gitbucket/core/admin/settings_system.scala.html @@ -116,8 +116,80 @@ Deny - Only administrators can create accounts. + + +