(refs #474)Add controller to maintain deploy keys

This commit is contained in:
Naoki Takezoe
2017-03-02 17:31:04 +09:00
parent 42d3585df5
commit 5a1ec385a8
6 changed files with 100 additions and 13 deletions

View File

@@ -2,7 +2,7 @@ package gitbucket.core.controller
import gitbucket.core.settings.html
import gitbucket.core.model.WebHook
import gitbucket.core.service.{RepositoryService, AccountService, WebHookService, ProtectedBranchService, CommitStatusService}
import gitbucket.core.service._
import gitbucket.core.service.WebHookService._
import gitbucket.core.util._
import gitbucket.core.util.JGitUtil._
@@ -19,11 +19,11 @@ import gitbucket.core.model.WebHookContentType
class RepositorySettingsController extends RepositorySettingsControllerBase
with RepositoryService with AccountService with WebHookService with ProtectedBranchService with CommitStatusService
with RepositoryService with AccountService with WebHookService with ProtectedBranchService with CommitStatusService with DeployKeyService
with OwnerAuthenticator with UsersAuthenticator
trait RepositorySettingsControllerBase extends ControllerBase {
self: RepositoryService with AccountService with WebHookService with ProtectedBranchService with CommitStatusService
self: RepositoryService with AccountService with WebHookService with ProtectedBranchService with CommitStatusService with DeployKeyService
with OwnerAuthenticator with UsersAuthenticator =>
// for repository options
@@ -37,7 +37,7 @@ trait RepositorySettingsControllerBase extends ControllerBase {
externalWikiUrl: Option[String],
allowFork: Boolean
)
val optionsForm = mapping(
"repositoryName" -> trim(label("Repository Name" , text(required, maxlength(100), identifier, renameRepositoryName))),
"description" -> trim(label("Description" , optional(text()))),
@@ -56,12 +56,14 @@ trait RepositorySettingsControllerBase extends ControllerBase {
"defaultBranch" -> trim(label("Default Branch" , text(required, maxlength(100))))
)(DefaultBranchForm.apply)
// // for collaborator addition
// case class CollaboratorForm(userName: String)
//
// val collaboratorForm = mapping(
// "userName" -> trim(label("Username", text(required, collaborator)))
// )(CollaboratorForm.apply)
// for deploy key
case class DeployKeyForm(title: String, publicKey: String)
val deployKeyForm = mapping(
"title" -> trim(label("Title", text(required, maxlength(100)))),
"publicKey" -> trim(label("Key" , text(required)))
)(DeployKeyForm.apply)
// for web hook url addition
case class WebHookForm(url: String, events: Set[WebHook.Event], ctype: WebHookContentType, token: Option[String])
@@ -382,6 +384,24 @@ trait RepositorySettingsControllerBase extends ControllerBase {
redirect(s"/${repository.owner}/${repository.name}/settings/danger")
})
/** List deploy keys */
get("/:owner/:repository/settings/deploykey")(ownerOnly { repository =>
html.deploykey(repository, getDeployKeys(repository.owner, repository.name))
})
/** Register a deploy key */
post("/:owner/:repository/settings/deploykey", deployKeyForm)(ownerOnly { (form, repository) =>
addDeployKey(repository.owner, repository.name, form.title, form.publicKey)
redirect(s"/${repository.owner}/${repository.name}/settings/deploykey")
})
/** Delete a deploy key */
get("/:owner/:repository/settings/deploykey/delete/:id")(ownerOnly { repository =>
val deployKeyId = params("id").toInt
deleteDeployKey(repository.owner, repository.name, deployKeyId)
redirect(s"/${repository.owner}/${repository.name}/settings/deploykey")
})
/**
* Provides duplication check for web hook url.
*/

View File

@@ -0,0 +1,22 @@
package gitbucket.core.service
import gitbucket.core.model.DeployKey
import gitbucket.core.model.Profile._
import gitbucket.core.model.Profile.profile.blockingApi._
trait DeployKeyService {
def addDeployKey(userName: String, repositoryName: String, title: String, publicKey: String)(implicit s: Session): Unit =
DeployKeys.insert(DeployKey(userName = userName, repositoryName = repositoryName, title = title, publicKey = publicKey))
def getDeployKeys(userName: String, repositoryName: String)(implicit s: Session): List[DeployKey] =
DeployKeys.filter(x => (x.userName === userName.bind) && (x.repositoryName === repositoryName.bind)).sortBy(_.deployKeyId).list
def getAllDeployKeys()(implicit s: Session): List[DeployKey] =
DeployKeys.filter(_.publicKey.trim =!= "").list
def deleteDeployKey(userName: String, repositoryName: String, deployKeyId: Int)(implicit s: Session): Unit =
DeployKeys.filter(_.byPrimaryKey(userName, repositoryName, deployKeyId)).delete
}

View File

@@ -7,7 +7,7 @@ import gitbucket.core.model.Profile.profile.blockingApi._
trait SshKeyService {
def addPublicKey(userName: String, title: String, publicKey: String)(implicit s: Session): Unit =
SshKeys insert SshKey(userName = userName, title = title, publicKey = publicKey)
SshKeys.insert(SshKey(userName = userName, title = title, publicKey = publicKey))
def getPublicKeys(userName: String)(implicit s: Session): List[SshKey] =
SshKeys.filter(_.userName === userName.bind).sortBy(_.sshKeyId).list
@@ -16,6 +16,6 @@ trait SshKeyService {
SshKeys.filter(_.publicKey.trim =!= "").list
def deletePublicKey(userName: String, sshKeyId: Int)(implicit s: Session): Unit =
SshKeys filter (_.byPrimaryKey(userName, sshKeyId)) delete
SshKeys.filter(_.byPrimaryKey(userName, sshKeyId)).delete
}

View File

@@ -20,7 +20,7 @@
</div>
<form method="POST" action="@context.path/@account.userName/_ssh" validate="true">
<div class="panel panel-default">
<div class="panel-heading strong">Add an SSH Key</div>
<div class="panel-heading strong">Add a SSH Key</div>
<div class="panel-body">
<fieldset class="form-group">
<label for="title" class="strong">Title</label>

View File

@@ -0,0 +1,42 @@
@(repository: gitbucket.core.service.RepositoryService.RepositoryInfo, deployKeys: List[gitbucket.core.model.DeployKey])(implicit context: gitbucket.core.controller.Context)
@import gitbucket.core.ssh.SshUtil
@import gitbucket.core.view.helpers
@gitbucket.core.html.main("Deploy keys", Some(repository)){
@gitbucket.core.html.menu("settings", repository){
@gitbucket.core.settings.html.menu("deploykeys", repository){
<div class="panel panel-default">
<div class="panel-heading strong">Deploy keys</div>
<div class="panel-body">
@if(deployKeys.isEmpty){
No keys
}
@deployKeys.zipWithIndex.map { case (key, i) =>
@if(i != 0){
<hr>
}
<strong style="line-height: 30px;">@key.title</strong> (@SshUtil.fingerPrint(key.publicKey).getOrElse("Key is invalid."))
<a href="@helpers.url(repository)/settings/deploykey/delete/@key.deployKeyId" class="btn btn-sm btn-danger pull-right">Delete</a>
}
</div>
</div>
<form method="POST" action="@helpers.url(repository)/settings/deploykey" validate="true">
<div class="panel panel-default">
<div class="panel-heading strong">Add a deploy key</div>
<div class="panel-body">
<fieldset class="form-group">
<label for="title" class="strong">Title</label>
<div><span id="error-title" class="error"></span></div>
<input type="text" name="title" id="title" class="form-control"/>
</fieldset>
<fieldset class="form-group">
<label for="publicKey" class="strong">Key</label>
<div><span id="error-publicKey" class="error"></span></div>
<textarea name="publicKey" id="publicKey" class="form-control" style="height: 250px;"></textarea>
</fieldset>
<input type="submit" class="btn btn-success" value="Add"/>
</div>
</div>
</form>
}
}
}

View File

@@ -15,6 +15,9 @@
<li@if(active=="hooks"){ class="active"}>
<a href="@helpers.url(repository)/settings/hooks">Service Hooks</a>
</li>
<li@if(active=="deploykeys"){ class="active"}>
<a href="@helpers.url(repository)/settings/deploykey">Deploy Keys</a>
</li>
<li@if(active=="danger"){ class="active"}>
<a href="@helpers.url(repository)/settings/danger">Danger Zone</a>
</li>