diff --git a/src/main/scala/gitbucket/core/controller/ApiController.scala b/src/main/scala/gitbucket/core/controller/ApiController.scala index eb585fb..eddd941 100644 --- a/src/main/scala/gitbucket/core/controller/ApiController.scala +++ b/src/main/scala/gitbucket/core/controller/ApiController.scala @@ -35,7 +35,7 @@ with GroupManagerAuthenticator with ReferrerAuthenticator with ReadableUsersAuthenticator - with CollaboratorsAuthenticator + with WritableUsersAuthenticator trait ApiControllerBase extends ControllerBase { self: RepositoryService @@ -52,7 +52,7 @@ with GroupManagerAuthenticator with ReferrerAuthenticator with ReadableUsersAuthenticator - with CollaboratorsAuthenticator => + with WritableUsersAuthenticator => /** * https://developer.github.com/v3/#root-endpoint @@ -328,7 +328,7 @@ * Create a label * https://developer.github.com/v3/issues/labels/#create-a-label */ - post("/api/v3/repos/:owner/:repository/labels")(collaboratorsOnly { repository => + post("/api/v3/repos/:owner/:repository/labels")(writableUsersOnly { repository => (for{ data <- extractFromJsonBody[CreateALabel] if data.isValid } yield { @@ -353,7 +353,7 @@ * Update a label * https://developer.github.com/v3/issues/labels/#update-a-label */ - patch("/api/v3/repos/:owner/:repository/labels/:labelName")(collaboratorsOnly { repository => + patch("/api/v3/repos/:owner/:repository/labels/:labelName")(writableUsersOnly { repository => (for{ data <- extractFromJsonBody[CreateALabel] if data.isValid } yield { @@ -379,7 +379,7 @@ * Delete a label * https://developer.github.com/v3/issues/labels/#delete-a-label */ - delete("/api/v3/repos/:owner/:repository/labels/:labelName")(collaboratorsOnly { repository => + delete("/api/v3/repos/:owner/:repository/labels/:labelName")(writableUsersOnly { repository => LockUtil.lock(RepositoryName(repository).fullName) { getLabel(repository.owner, repository.name, params("labelName")).map { label => deleteLabel(repository.owner, repository.name, label.labelId) @@ -467,7 +467,7 @@ /** * https://developer.github.com/v3/repos/statuses/#create-a-status */ - post("/api/v3/repos/:owner/:repo/statuses/:sha")(collaboratorsOnly { repository => + post("/api/v3/repos/:owner/:repo/statuses/:sha")(writableUsersOnly { repository => (for{ ref <- params.get("sha") sha <- JGitUtil.getShaByRef(repository.owner, repository.name, ref) diff --git a/src/main/scala/gitbucket/core/controller/IssuesController.scala b/src/main/scala/gitbucket/core/controller/IssuesController.scala index a4b01f2..90aca13 100644 --- a/src/main/scala/gitbucket/core/controller/IssuesController.scala +++ b/src/main/scala/gitbucket/core/controller/IssuesController.scala @@ -15,11 +15,11 @@ class IssuesController extends IssuesControllerBase with IssuesService with RepositoryService with AccountService with LabelsService with MilestonesService with ActivityService with HandleCommentService - with ReadableUsersAuthenticator with ReferrerAuthenticator with CollaboratorsAuthenticator with PullRequestService with WebHookIssueCommentService + with ReadableUsersAuthenticator with ReferrerAuthenticator with WritableUsersAuthenticator with PullRequestService with WebHookIssueCommentService trait IssuesControllerBase extends ControllerBase { self: IssuesService with RepositoryService with AccountService with LabelsService with MilestonesService with ActivityService with HandleCommentService - with ReadableUsersAuthenticator with ReferrerAuthenticator with CollaboratorsAuthenticator with PullRequestService with WebHookIssueCommentService => + with ReadableUsersAuthenticator with ReferrerAuthenticator with WritableUsersAuthenticator with PullRequestService with WebHookIssueCommentService => case class IssueCreateForm(title: String, content: Option[String], assignedUserName: Option[String], milestoneId: Option[Int], labelNames: Option[String]) @@ -258,32 +258,32 @@ } getOrElse NotFound() }) - ajaxPost("/:owner/:repository/issues/new/label")(collaboratorsOnly { repository => + ajaxPost("/:owner/:repository/issues/new/label")(writableUsersOnly { repository => val labelNames = params("labelNames").split(",") val labels = getLabels(repository.owner, repository.name).filter(x => labelNames.contains(x.labelName)) html.labellist(labels) }) - ajaxPost("/:owner/:repository/issues/:id/label/new")(collaboratorsOnly { repository => + ajaxPost("/:owner/:repository/issues/:id/label/new")(writableUsersOnly { repository => defining(params("id").toInt){ issueId => registerIssueLabel(repository.owner, repository.name, issueId, params("labelId").toInt) html.labellist(getIssueLabels(repository.owner, repository.name, issueId)) } }) - ajaxPost("/:owner/:repository/issues/:id/label/delete")(collaboratorsOnly { repository => + ajaxPost("/:owner/:repository/issues/:id/label/delete")(writableUsersOnly { repository => defining(params("id").toInt){ issueId => deleteIssueLabel(repository.owner, repository.name, issueId, params("labelId").toInt) html.labellist(getIssueLabels(repository.owner, repository.name, issueId)) } }) - ajaxPost("/:owner/:repository/issues/:id/assign")(collaboratorsOnly { repository => + ajaxPost("/:owner/:repository/issues/:id/assign")(writableUsersOnly { repository => updateAssignedUserName(repository.owner, repository.name, params("id").toInt, assignedUserName("assignedUserName")) Ok("updated") }) - ajaxPost("/:owner/:repository/issues/:id/milestone")(collaboratorsOnly { repository => + ajaxPost("/:owner/:repository/issues/:id/milestone")(writableUsersOnly { repository => updateMilestoneId(repository.owner, repository.name, params("id").toInt, milestoneId("milestoneId")) milestoneId("milestoneId").map { milestoneId => getMilestonesWithIssueCount(repository.owner, repository.name) @@ -293,7 +293,7 @@ } getOrElse Ok() }) - post("/:owner/:repository/issues/batchedit/state")(collaboratorsOnly { repository => + post("/:owner/:repository/issues/batchedit/state")(writableUsersOnly { repository => defining(params.get("value")){ action => action match { case Some("open") => executeBatch(repository) { issueId => @@ -311,7 +311,7 @@ } }) - post("/:owner/:repository/issues/batchedit/label")(collaboratorsOnly { repository => + post("/:owner/:repository/issues/batchedit/label")(writableUsersOnly { repository => params("value").toIntOpt.map{ labelId => executeBatch(repository) { issueId => getIssueLabel(repository.owner, repository.name, issueId, labelId) getOrElse { @@ -321,7 +321,7 @@ } getOrElse NotFound() }) - post("/:owner/:repository/issues/batchedit/assign")(collaboratorsOnly { repository => + post("/:owner/:repository/issues/batchedit/assign")(writableUsersOnly { repository => defining(assignedUserName("value")){ value => executeBatch(repository) { updateAssignedUserName(repository.owner, repository.name, _, value) @@ -329,7 +329,7 @@ } }) - post("/:owner/:repository/issues/batchedit/milestone")(collaboratorsOnly { repository => + post("/:owner/:repository/issues/batchedit/milestone")(writableUsersOnly { repository => defining(milestoneId("value")){ value => executeBatch(repository) { updateMilestoneId(repository.owner, repository.name, _, value) diff --git a/src/main/scala/gitbucket/core/controller/LabelsController.scala b/src/main/scala/gitbucket/core/controller/LabelsController.scala index 9b17841..ab658eb 100644 --- a/src/main/scala/gitbucket/core/controller/LabelsController.scala +++ b/src/main/scala/gitbucket/core/controller/LabelsController.scala @@ -2,7 +2,7 @@ import gitbucket.core.issues.labels.html import gitbucket.core.service.{RepositoryService, AccountService, IssuesService, LabelsService} -import gitbucket.core.util.{ReferrerAuthenticator, CollaboratorsAuthenticator} +import gitbucket.core.util.{ReferrerAuthenticator, WritableUsersAuthenticator} import gitbucket.core.util.Implicits._ import io.github.gitbucket.scalatra.forms._ import org.scalatra.i18n.Messages @@ -10,11 +10,11 @@ class LabelsController extends LabelsControllerBase with LabelsService with IssuesService with RepositoryService with AccountService -with ReferrerAuthenticator with CollaboratorsAuthenticator +with ReferrerAuthenticator with WritableUsersAuthenticator trait LabelsControllerBase extends ControllerBase { self: LabelsService with IssuesService with RepositoryService - with ReferrerAuthenticator with CollaboratorsAuthenticator => + with ReferrerAuthenticator with WritableUsersAuthenticator => case class LabelForm(labelName: String, color: String) @@ -32,11 +32,11 @@ hasWritePermission(repository.owner, repository.name, context.loginAccount)) }) - ajaxGet("/:owner/:repository/issues/labels/new")(collaboratorsOnly { repository => + ajaxGet("/:owner/:repository/issues/labels/new")(writableUsersOnly { repository => html.edit(None, repository) }) - ajaxPost("/:owner/:repository/issues/labels/new", labelForm)(collaboratorsOnly { (form, repository) => + ajaxPost("/:owner/:repository/issues/labels/new", labelForm)(writableUsersOnly { (form, repository) => val labelId = createLabel(repository.owner, repository.name, form.labelName, form.color.substring(1)) html.label( getLabel(repository.owner, repository.name, labelId).get, @@ -46,13 +46,13 @@ hasWritePermission(repository.owner, repository.name, context.loginAccount)) }) - ajaxGet("/:owner/:repository/issues/labels/:labelId/edit")(collaboratorsOnly { repository => + ajaxGet("/:owner/:repository/issues/labels/:labelId/edit")(writableUsersOnly { repository => getLabel(repository.owner, repository.name, params("labelId").toInt).map { label => html.edit(Some(label), repository) } getOrElse NotFound() }) - ajaxPost("/:owner/:repository/issues/labels/:labelId/edit", labelForm)(collaboratorsOnly { (form, repository) => + ajaxPost("/:owner/:repository/issues/labels/:labelId/edit", labelForm)(writableUsersOnly { (form, repository) => updateLabel(repository.owner, repository.name, params("labelId").toInt, form.labelName, form.color.substring(1)) html.label( getLabel(repository.owner, repository.name, params("labelId").toInt).get, @@ -62,7 +62,7 @@ hasWritePermission(repository.owner, repository.name, context.loginAccount)) }) - ajaxPost("/:owner/:repository/issues/labels/:labelId/delete")(collaboratorsOnly { repository => + ajaxPost("/:owner/:repository/issues/labels/:labelId/delete")(writableUsersOnly { repository => deleteLabel(repository.owner, repository.name, params("labelId").toInt) Ok() }) diff --git a/src/main/scala/gitbucket/core/controller/MilestonesController.scala b/src/main/scala/gitbucket/core/controller/MilestonesController.scala index 323b114..f75ea60 100644 --- a/src/main/scala/gitbucket/core/controller/MilestonesController.scala +++ b/src/main/scala/gitbucket/core/controller/MilestonesController.scala @@ -2,17 +2,17 @@ import gitbucket.core.issues.milestones.html import gitbucket.core.service.{RepositoryService, MilestonesService, AccountService} -import gitbucket.core.util.{ReferrerAuthenticator, CollaboratorsAuthenticator} +import gitbucket.core.util.{ReferrerAuthenticator, WritableUsersAuthenticator} import gitbucket.core.util.Implicits._ import io.github.gitbucket.scalatra.forms._ class MilestonesController extends MilestonesControllerBase with MilestonesService with RepositoryService with AccountService - with ReferrerAuthenticator with CollaboratorsAuthenticator + with ReferrerAuthenticator with WritableUsersAuthenticator trait MilestonesControllerBase extends ControllerBase { self: MilestonesService with RepositoryService - with ReferrerAuthenticator with CollaboratorsAuthenticator => + with ReferrerAuthenticator with WritableUsersAuthenticator => case class MilestoneForm(title: String, description: Option[String], dueDate: Option[java.util.Date]) @@ -30,22 +30,22 @@ hasWritePermission(repository.owner, repository.name, context.loginAccount)) }) - get("/:owner/:repository/issues/milestones/new")(collaboratorsOnly { + get("/:owner/:repository/issues/milestones/new")(writableUsersOnly { html.edit(None, _) }) - post("/:owner/:repository/issues/milestones/new", milestoneForm)(collaboratorsOnly { (form, repository) => + post("/:owner/:repository/issues/milestones/new", milestoneForm)(writableUsersOnly { (form, repository) => createMilestone(repository.owner, repository.name, form.title, form.description, form.dueDate) redirect(s"/${repository.owner}/${repository.name}/issues/milestones") }) - get("/:owner/:repository/issues/milestones/:milestoneId/edit")(collaboratorsOnly { repository => + get("/:owner/:repository/issues/milestones/:milestoneId/edit")(writableUsersOnly { repository => params("milestoneId").toIntOpt.map{ milestoneId => html.edit(getMilestone(repository.owner, repository.name, milestoneId), repository) } getOrElse NotFound() }) - post("/:owner/:repository/issues/milestones/:milestoneId/edit", milestoneForm)(collaboratorsOnly { (form, repository) => + post("/:owner/:repository/issues/milestones/:milestoneId/edit", milestoneForm)(writableUsersOnly { (form, repository) => params("milestoneId").toIntOpt.flatMap{ milestoneId => getMilestone(repository.owner, repository.name, milestoneId).map { milestone => updateMilestone(milestone.copy(title = form.title, description = form.description, dueDate = form.dueDate)) @@ -54,7 +54,7 @@ } getOrElse NotFound() }) - get("/:owner/:repository/issues/milestones/:milestoneId/close")(collaboratorsOnly { repository => + get("/:owner/:repository/issues/milestones/:milestoneId/close")(writableUsersOnly { repository => params("milestoneId").toIntOpt.flatMap{ milestoneId => getMilestone(repository.owner, repository.name, milestoneId).map { milestone => closeMilestone(milestone) @@ -63,7 +63,7 @@ } getOrElse NotFound() }) - get("/:owner/:repository/issues/milestones/:milestoneId/open")(collaboratorsOnly { repository => + get("/:owner/:repository/issues/milestones/:milestoneId/open")(writableUsersOnly { repository => params("milestoneId").toIntOpt.flatMap{ milestoneId => getMilestone(repository.owner, repository.name, milestoneId).map { milestone => openMilestone(milestone) @@ -72,7 +72,7 @@ } getOrElse NotFound() }) - get("/:owner/:repository/issues/milestones/:milestoneId/delete")(collaboratorsOnly { repository => + get("/:owner/:repository/issues/milestones/:milestoneId/delete")(writableUsersOnly { repository => params("milestoneId").toIntOpt.flatMap{ milestoneId => getMilestone(repository.owner, repository.name, milestoneId).map { milestone => deleteMilestone(repository.owner, repository.name, milestone.milestoneId) diff --git a/src/main/scala/gitbucket/core/controller/PullRequestsController.scala b/src/main/scala/gitbucket/core/controller/PullRequestsController.scala index ae26bb0..548da42 100644 --- a/src/main/scala/gitbucket/core/controller/PullRequestsController.scala +++ b/src/main/scala/gitbucket/core/controller/PullRequestsController.scala @@ -25,14 +25,14 @@ class PullRequestsController extends PullRequestsControllerBase with RepositoryService with AccountService with IssuesService with PullRequestService with MilestonesService with LabelsService with CommitsService with ActivityService with WebHookPullRequestService - with ReadableUsersAuthenticator with ReferrerAuthenticator with CollaboratorsAuthenticator + with ReadableUsersAuthenticator with ReferrerAuthenticator with WritableUsersAuthenticator with CommitStatusService with MergeService with ProtectedBranchService trait PullRequestsControllerBase extends ControllerBase { self: RepositoryService with AccountService with IssuesService with MilestonesService with LabelsService with CommitsService with ActivityService with PullRequestService with WebHookPullRequestService - with ReadableUsersAuthenticator with ReferrerAuthenticator with CollaboratorsAuthenticator + with ReadableUsersAuthenticator with ReferrerAuthenticator with WritableUsersAuthenticator with CommitStatusService with MergeService with ProtectedBranchService => val pullRequestForm = mapping( @@ -141,7 +141,7 @@ } getOrElse NotFound() }) - get("/:owner/:repository/pull/:id/delete/*")(collaboratorsOnly { repository => + get("/:owner/:repository/pull/:id/delete/*")(writableUsersOnly { repository => params("id").toIntOpt.map { issueId => val branchName = multiParams("splat").head val userName = context.loginAccount.get.userName @@ -225,7 +225,7 @@ }) getOrElse NotFound() }) - post("/:owner/:repository/pull/:id/merge", mergeForm)(collaboratorsOnly { (form, repository) => + post("/:owner/:repository/pull/:id/merge", mergeForm)(writableUsersOnly { (form, repository) => params("id").toIntOpt.flatMap { issueId => val owner = repository.owner val name = repository.name @@ -389,7 +389,7 @@ }) getOrElse NotFound() }) - ajaxGet("/:owner/:repository/compare/*...*/mergecheck")(collaboratorsOnly { forkedRepository => + ajaxGet("/:owner/:repository/compare/*...*/mergecheck")(writableUsersOnly { forkedRepository => val Seq(origin, forked) = multiParams("splat") val (originOwner, tmpOriginBranch) = parseCompareIdentifie(origin, forkedRepository.owner) val (forkedOwner, tmpForkedBranch) = parseCompareIdentifie(forked, forkedRepository.owner) diff --git a/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala b/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala index 63b904e..d575c68 100644 --- a/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala +++ b/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala @@ -31,7 +31,7 @@ class RepositoryViewerController extends RepositoryViewerControllerBase with RepositoryService with AccountService with ActivityService with IssuesService with WebHookService with CommitsService - with ReadableUsersAuthenticator with ReferrerAuthenticator with CollaboratorsAuthenticator with PullRequestService with CommitStatusService + with ReadableUsersAuthenticator with ReferrerAuthenticator with WritableUsersAuthenticator with PullRequestService with CommitStatusService with WebHookPullRequestService with WebHookPullRequestReviewCommentService with ProtectedBranchService /** @@ -39,7 +39,7 @@ */ trait RepositoryViewerControllerBase extends ControllerBase { self: RepositoryService with AccountService with ActivityService with IssuesService with WebHookService with CommitsService - with ReadableUsersAuthenticator with ReferrerAuthenticator with CollaboratorsAuthenticator with PullRequestService with CommitStatusService + with ReadableUsersAuthenticator with ReferrerAuthenticator with WritableUsersAuthenticator with PullRequestService with CommitStatusService with WebHookPullRequestService with WebHookPullRequestReviewCommentService with ProtectedBranchService => ArchiveCommand.registerFormat("zip", new ZipFormat) @@ -157,7 +157,7 @@ } }) - get("/:owner/:repository/new/*")(collaboratorsOnly { repository => + get("/:owner/:repository/new/*")(writableUsersOnly { repository => val (branch, path) = repository.splitPath(multiParams("splat").head) val protectedBranch = getProtectedBranchInfo(repository.owner, repository.name, branch).needStatusCheck(context.loginAccount.get.userName) html.editor(branch, repository, if(path.length == 0) Nil else path.split("/").toList, @@ -165,7 +165,7 @@ protectedBranch) }) - get("/:owner/:repository/edit/*")(collaboratorsOnly { repository => + get("/:owner/:repository/edit/*")(writableUsersOnly { repository => val (branch, path) = repository.splitPath(multiParams("splat").head) val protectedBranch = getProtectedBranchInfo(repository.owner, repository.name, branch).needStatusCheck(context.loginAccount.get.userName) @@ -181,7 +181,7 @@ } }) - get("/:owner/:repository/remove/*")(collaboratorsOnly { repository => + get("/:owner/:repository/remove/*")(writableUsersOnly { repository => val (branch, path) = repository.splitPath(multiParams("splat").head) using(Git.open(getRepositoryDir(repository.owner, repository.name))){ git => val revCommit = JGitUtil.getRevCommitFromId(git, git.getRepository.resolve(branch)) @@ -194,7 +194,7 @@ } }) - post("/:owner/:repository/create", editorForm)(collaboratorsOnly { (form, repository) => + post("/:owner/:repository/create", editorForm)(writableUsersOnly { (form, repository) => commitFile( repository = repository, branch = form.branch, @@ -211,7 +211,7 @@ }") }) - post("/:owner/:repository/update", editorForm)(collaboratorsOnly { (form, repository) => + post("/:owner/:repository/update", editorForm)(writableUsersOnly { (form, repository) => commitFile( repository = repository, branch = form.branch, @@ -232,7 +232,7 @@ }") }) - post("/:owner/:repository/remove", deleteForm)(collaboratorsOnly { (form, repository) => + post("/:owner/:repository/remove", deleteForm)(writableUsersOnly { (form, repository) => commitFile(repository, form.branch, form.path, None, Some(form.fileName), "", "", form.message.getOrElse(s"Delete ${form.fileName}")) @@ -443,7 +443,7 @@ /** * Creates a branch. */ - post("/:owner/:repository/branches")(collaboratorsOnly { repository => + post("/:owner/:repository/branches")(writableUsersOnly { repository => val newBranchName = params.getOrElse("new", halt(400)) val fromBranchName = params.getOrElse("from", halt(400)) using(Git.open(getRepositoryDir(repository.owner, repository.name))){ git => @@ -461,7 +461,7 @@ /** * Deletes branch. */ - get("/:owner/:repository/delete/*")(collaboratorsOnly { repository => + get("/:owner/:repository/delete/*")(writableUsersOnly { repository => val branchName = multiParams("splat").head val userName = context.loginAccount.get.userName if(repository.repository.defaultBranch != branchName){ diff --git a/src/main/scala/gitbucket/core/controller/WikiController.scala b/src/main/scala/gitbucket/core/controller/WikiController.scala index beebfc2..64d0b27 100644 --- a/src/main/scala/gitbucket/core/controller/WikiController.scala +++ b/src/main/scala/gitbucket/core/controller/WikiController.scala @@ -14,10 +14,10 @@ class WikiController extends WikiControllerBase with WikiService with RepositoryService with AccountService with ActivityService - with ReadableUsersAuthenticator with CollaboratorsAuthenticator with ReferrerAuthenticator + with ReadableUsersAuthenticator with ReferrerAuthenticator trait WikiControllerBase extends ControllerBase { - self: WikiService with RepositoryService with ActivityService with ReadableUsersAuthenticator with CollaboratorsAuthenticator with ReferrerAuthenticator => + self: WikiService with RepositoryService with ActivityService with ReadableUsersAuthenticator with ReferrerAuthenticator => case class WikiPageEditForm(pageName: String, content: String, message: Option[String], currentPageName: String, id: String) diff --git a/src/main/scala/gitbucket/core/util/Authenticator.scala b/src/main/scala/gitbucket/core/util/Authenticator.scala index 6d82508..b4cfef5 100644 --- a/src/main/scala/gitbucket/core/util/Authenticator.scala +++ b/src/main/scala/gitbucket/core/util/Authenticator.scala @@ -89,32 +89,6 @@ } /** - * Allows only collaborators and administrators. - * - * TODO This authenticator should be renamed. - */ -trait CollaboratorsAuthenticator { self: ControllerBase with RepositoryService with AccountService => - protected def collaboratorsOnly(action: (RepositoryInfo) => Any) = { authenticate(action) } - protected def collaboratorsOnly[T](action: (T, RepositoryInfo) => Any) = (form: T) => { authenticate(action(form, _)) } - - private def authenticate(action: (RepositoryInfo) => Any) = { - { - defining(request.paths){ paths => - getRepository(paths(0), paths(1)).map { repository => - context.loginAccount match { - case Some(x) if(x.isAdmin) => action(repository) - case Some(x) if(paths(0) == x.userName) => action(repository) - case Some(x) if(getGroupMembers(repository.owner).exists(_.userName == x.userName)) => action(repository) - case Some(x) if(getCollaboratorUserNames(paths(0), paths(1), Seq(Permission.ADMIN, Permission.WRITE)).contains(x.userName)) => action(repository) - case _ => Unauthorized() - } - } getOrElse NotFound() - } - } - } -} - -/** * Allows only guests and signed in users who can access the repository. */ trait ReferrerAuthenticator { self: ControllerBase with RepositoryService with AccountService => @@ -143,7 +117,7 @@ } /** - * Allows only signed in users who can access the repository. + * Allows only signed in users who have read permission for the repository. */ trait ReadableUsersAuthenticator { self: ControllerBase with RepositoryService with AccountService => protected def readableUsersOnly(action: (RepositoryInfo) => Any) = { authenticate(action) } @@ -168,6 +142,30 @@ } /** + * Allows only signed in users who have write permission for the repository. + */ +trait WritableUsersAuthenticator { self: ControllerBase with RepositoryService with AccountService => + protected def writableUsersOnly(action: (RepositoryInfo) => Any) = { authenticate(action) } + protected def writableUsersOnly[T](action: (T, RepositoryInfo) => Any) = (form: T) => { authenticate(action(form, _)) } + + private def authenticate(action: (RepositoryInfo) => Any) = { + { + defining(request.paths){ paths => + getRepository(paths(0), paths(1)).map { repository => + context.loginAccount match { + case Some(x) if(x.isAdmin) => action(repository) + case Some(x) if(paths(0) == x.userName) => action(repository) + case Some(x) if(getGroupMembers(repository.owner).exists(_.userName == x.userName)) => action(repository) + case Some(x) if(getCollaboratorUserNames(paths(0), paths(1), Seq(Permission.ADMIN, Permission.WRITE)).contains(x.userName)) => action(repository) + case _ => Unauthorized() + } + } getOrElse NotFound() + } + } + } +} + +/** * Allows only the group managers. */ trait GroupManagerAuthenticator { self: ControllerBase with AccountService =>