diff --git a/src/main/scala/gitbucket/core/controller/AccountController.scala b/src/main/scala/gitbucket/core/controller/AccountController.scala index 556c717..f861b40 100644 --- a/src/main/scala/gitbucket/core/controller/AccountController.scala +++ b/src/main/scala/gitbucket/core/controller/AccountController.scala @@ -725,7 +725,14 @@ post("/new", newRepositoryForm)(usersOnly { form => if (context.settings.repositoryOperation.create || context.loginAccount.get.isAdmin) { LockUtil.lock(s"${form.owner}/${form.name}") { - if (getRepository(form.owner, form.name).isEmpty) { + if (getRepository(form.owner, form.name).isDefined) { + // redirect to the repository if repository already exists + redirect(s"/${form.owner}/${form.name}") + } else if (!canCreateRepository(form.owner, context.loginAccount.get)) { + // Permission error + Forbidden() + } else { + // create repository asynchronously createRepository( context.loginAccount.get, form.owner, @@ -735,10 +742,10 @@ 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() }) @@ -773,10 +780,12 @@ val loginUserName = loginAccount.userName val accountName = form.accountName - if (getRepository(accountName, repository.name).isDefined || - (accountName != loginUserName && !getGroupsByUserName(loginUserName).contains(accountName))) { + if (getRepository(accountName, repository.name).isDefined) { // redirect to the repository if repository already exists redirect(s"/${accountName}/${repository.name}") + } else if (!canCreateRepository(accountName, loginAccount)) { + // Permission error + Forbidden() } else { // fork repository asynchronously forkRepository(accountName, repository, loginUserName) diff --git a/src/main/scala/gitbucket/core/controller/api/ApiRepositoryControllerBase.scala b/src/main/scala/gitbucket/core/controller/api/ApiRepositoryControllerBase.scala index f05623b..799474b 100644 --- a/src/main/scala/gitbucket/core/controller/api/ApiRepositoryControllerBase.scala +++ b/src/main/scala/gitbucket/core/controller/api/ApiRepositoryControllerBase.scala @@ -8,6 +8,7 @@ import gitbucket.core.util.Implicits._ import gitbucket.core.model.Profile.profile.blockingApi._ import org.eclipse.jgit.api.Git +import org.scalatra.Forbidden import scala.concurrent.Await import scala.concurrent.duration.Duration @@ -26,7 +27,7 @@ /** * i. List your repositories - * https://developer.github.com/v3/repos/#list-your-repositories + * https://docs.github.com/en/rest/reference/repos#list-repositories-for-the-authenticated-user */ get("/api/v3/user/repos")(usersOnly { JsonFormat(getVisibleRepositories(context.loginAccount, Option(context.loginAccount.get.userName)).map { r => @@ -36,7 +37,7 @@ /** * ii. List user repositories - * https://developer.github.com/v3/repos/#list-user-repositories + * https://docs.github.com/en/rest/reference/repos#list-repositories-for-a-user */ get("/api/v3/users/:userName/repos") { JsonFormat(getVisibleRepositories(context.loginAccount, Some(params("userName"))).map { r => @@ -46,7 +47,7 @@ /** * iii. List organization repositories - * https://developer.github.com/v3/repos/#list-organization-repositories + * https://docs.github.com/en/rest/reference/repos#list-organization-repositories */ get("/api/v3/orgs/:orgName/repos") { JsonFormat(getVisibleRepositories(context.loginAccount, Some(params("orgName"))).map { r => @@ -56,7 +57,7 @@ /** * iv. List all public repositories - * https://developer.github.com/v3/repos/#list-public-repositories + * https://docs.github.com/en/rest/reference/repos#list-public-repositories */ get("/api/v3/repositories") { JsonFormat(getPublicRepositories().map { r => @@ -66,13 +67,12 @@ /* * v. Create - * https://developer.github.com/v3/repos/#create * Implemented with two methods (user/orgs) */ /** * Create user repository - * https://developer.github.com/v3/repos/#create + * https://docs.github.com/en/rest/reference/repos#create-a-repository-for-the-authenticated-user */ post("/api/v3/user/repos")(usersOnly { val owner = context.loginAccount.get.userName @@ -80,7 +80,12 @@ data <- extractFromJsonBody[CreateARepository] if data.isValid } yield { LockUtil.lock(s"${owner}/${data.name}") { - if (getRepository(owner, data.name).isEmpty) { + if (getRepository(owner, data.name).isDefined) { + ApiError( + "A repository with this name already exists on this account", + Some("https://developer.github.com/v3/repos/#create") + ) + } else { val f = createRepository( context.loginAccount.get, owner, @@ -95,11 +100,6 @@ getRepository(owner, data.name)(session).get } JsonFormat(ApiRepository(repository, ApiUser(getAccountByUserName(owner).get))) - } else { - ApiError( - "A repository with this name already exists on this account", - Some("https://developer.github.com/v3/repos/#create") - ) } } }) getOrElse NotFound() @@ -107,15 +107,22 @@ /** * Create group repository - * https://developer.github.com/v3/repos/#create + * https://docs.github.com/en/rest/reference/repos#create-an-organization-repository */ - post("/api/v3/orgs/:org/repos")(managersOnly { + post("/api/v3/orgs/:org/repos")(usersOnly { val groupName = params("org") (for { data <- extractFromJsonBody[CreateARepository] if data.isValid } yield { LockUtil.lock(s"${groupName}/${data.name}") { - if (getRepository(groupName, data.name).isEmpty) { + if (getRepository(groupName, data.name).isDefined) { + ApiError( + "A repository with this name already exists for this group", + Some("https://developer.github.com/v3/repos/#create") + ) + } else if (!canCreateRepository(groupName, context.loginAccount.get)) { + Forbidden() + } else { val f = createRepository( context.loginAccount.get, groupName, @@ -129,11 +136,6 @@ getRepository(groupName, data.name).get } JsonFormat(ApiRepository(repository, ApiUser(getAccountByUserName(groupName).get))) - } else { - ApiError( - "A repository with this name already exists for this group", - Some("https://developer.github.com/v3/repos/#create") - ) } } }) getOrElse NotFound() @@ -141,7 +143,7 @@ /* * vi. Get - * https://developer.github.com/v3/repos/#get + * https://docs.github.com/en/rest/reference/repos#get-a-repository */ get("/api/v3/repos/:owner/:repository")(referrersOnly { repository => JsonFormat(ApiRepository(repository, ApiUser(getAccountByUserName(repository.owner).get))) @@ -149,32 +151,32 @@ /* * vii. Edit - * https://developer.github.com/v3/repos/#edit + * https://docs.github.com/en/rest/reference/repos#update-a-repository */ /* * viii. List all topics for a repository - * https://developer.github.com/v3/repos/#list-all-topics-for-a-repository + * https://docs.github.com/en/rest/reference/repos#get-all-repository-topics */ /* * ix. Replace all topics for a repository - * https://developer.github.com/v3/repos/#replace-all-topics-for-a-repository + * https://docs.github.com/en/rest/reference/repos#replace-all-repository-topics */ /* * x. List contributors - * https://developer.github.com/v3/repos/#list-contributors + * https://docs.github.com/en/rest/reference/repos#list-repository-contributors */ /* * xi. List languages - * https://developer.github.com/v3/repos/#list-languages + * https://docs.github.com/en/rest/reference/repos#list-repository-languages */ /* * xii. List teams - * https://developer.github.com/v3/repos/#list-teams + * https://docs.github.com/en/rest/reference/repos#list-repository-teams */ /* @@ -189,12 +191,12 @@ /* * xiv. Delete a repository - * https://developer.github.com/v3/repos/#delete-a-repository + * https://docs.github.com/en/rest/reference/repos#delete-a-repository */ /* * xv. Transfer a repository - * https://developer.github.com/v3/repos/#transfer-a-repository + * https://docs.github.com/en/rest/reference/repos#transfer-a-repository */ /** diff --git a/src/main/scala/gitbucket/core/service/RepositoryCreationService.scala b/src/main/scala/gitbucket/core/service/RepositoryCreationService.scala index e9a8096..85b79c7 100644 --- a/src/main/scala/gitbucket/core/service/RepositoryCreationService.scala +++ b/src/main/scala/gitbucket/core/service/RepositoryCreationService.scala @@ -53,6 +53,11 @@ with ActivityService with PrioritiesService => + def canCreateRepository(repositoryOwner: String, loginAccount: Account)(implicit session: Session): Boolean = { + repositoryOwner == loginAccount.userName || getGroupsByUserName(loginAccount.userName) + .contains(repositoryOwner) || loginAccount.isAdmin + } + def createRepository( loginAccount: Account, owner: String, @@ -76,7 +81,7 @@ RepositoryCreationService.startCreation(owner, name) try { Database() withTransaction { implicit session => - val ownerAccount = getAccountByUserName(owner).get + //val ownerAccount = getAccountByUserName(owner).get val loginUserName = loginAccount.userName val copyRepositoryDir = if (initOption == "COPY") { diff --git a/src/main/scala/gitbucket/core/util/Authenticator.scala b/src/main/scala/gitbucket/core/util/Authenticator.scala index b226509..80659be 100644 --- a/src/main/scala/gitbucket/core/util/Authenticator.scala +++ b/src/main/scala/gitbucket/core/util/Authenticator.scala @@ -113,13 +113,10 @@ val userName = params("owner") val repoName = params("repository") getRepository(userName, repoName).map { repository => - context.loginAccount match { - case Some(x) if (x.isAdmin) => action(repository) - case Some(x) if (!repository.repository.isPrivate) => action(repository) - case Some(x) if (userName == x.userName) => action(repository) - case Some(x) if (getGroupMembers(repository.owner).exists(_.userName == x.userName)) => action(repository) - case Some(x) if (getCollaboratorUserNames(userName, repoName).contains(x.userName)) => action(repository) - case _ => Unauthorized() + if (isReadable(repository.repository, context.loginAccount) || !repository.repository.isPrivate) { + action(repository) + } else { + Unauthorized() } } getOrElse NotFound() }