diff --git a/src/main/resources/update/gitbucket-core_4.11.xml b/src/main/resources/update/gitbucket-core_4.11.xml
new file mode 100644
index 0000000..1c41d88
--- /dev/null
+++ b/src/main/resources/update/gitbucket-core_4.11.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/scala/gitbucket/core/GitBucketCoreModule.scala b/src/main/scala/gitbucket/core/GitBucketCoreModule.scala
index 4b9c486..dd8665d 100644
--- a/src/main/scala/gitbucket/core/GitBucketCoreModule.scala
+++ b/src/main/scala/gitbucket/core/GitBucketCoreModule.scala
@@ -28,5 +28,8 @@
new Version("4.9.0",
new LiquibaseMigration("update/gitbucket-core_4.9.xml")
),
- new Version("4.10.0")
+ new Version("4.10.0"),
+ new Version("4.11.0",
+ new LiquibaseMigration("update/gitbucket-core_4.11.xml")
+ )
)
diff --git a/src/main/scala/gitbucket/core/controller/RepositorySettingsController.scala b/src/main/scala/gitbucket/core/controller/RepositorySettingsController.scala
index cd0371a..b396e4b 100644
--- a/src/main/scala/gitbucket/core/controller/RepositorySettingsController.scala
+++ b/src/main/scala/gitbucket/core/controller/RepositorySettingsController.scala
@@ -2,7 +2,7 @@
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 @@
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 @@
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,15 @@
"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, allowWrite: Boolean)
+
+ val deployKeyForm = mapping(
+ "title" -> trim(label("Title", text(required, maxlength(100)))),
+ "publicKey" -> trim(label("Key" , text(required))), // TODO duplication check in the repository?
+ "allowWrite" -> trim(label("Key" , boolean()))
+ )(DeployKeyForm.apply)
// for web hook url addition
case class WebHookForm(url: String, events: Set[WebHook.Event], ctype: WebHookContentType, token: Option[String])
@@ -382,6 +385,24 @@
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, form.allowWrite)
+ 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.
*/
diff --git a/src/main/scala/gitbucket/core/model/DeployKey.scala b/src/main/scala/gitbucket/core/model/DeployKey.scala
new file mode 100644
index 0000000..4f34e45
--- /dev/null
+++ b/src/main/scala/gitbucket/core/model/DeployKey.scala
@@ -0,0 +1,29 @@
+package gitbucket.core.model
+
+trait DeployKeyComponent { self: Profile =>
+ import profile.api._
+
+ lazy val DeployKeys = TableQuery[DeployKeys]
+
+ class DeployKeys(tag: Tag) extends Table[DeployKey](tag, "DEPLOY_KEY") {
+ val userName = column[String]("USER_NAME")
+ val repositoryName = column[String]("REPOSITORY_NAME")
+ val deployKeyId = column[Int]("DEPLOY_KEY_ID", O AutoInc)
+ val title = column[String]("TITLE")
+ val publicKey = column[String]("PUBLIC_KEY")
+ val allowWrite = column[Boolean]("ALLOW_WRITE")
+ def * = (userName, repositoryName, deployKeyId, title, publicKey, allowWrite) <> (DeployKey.tupled, DeployKey.unapply)
+
+ def byPrimaryKey(userName: String, repositoryName: String, deployKeyId: Int) =
+ (this.userName === userName.bind) && (this.repositoryName === repositoryName.bind) && (this.deployKeyId === deployKeyId.bind)
+ }
+}
+
+case class DeployKey(
+ userName: String,
+ repositoryName: String,
+ deployKeyId: Int = 0,
+ title: String,
+ publicKey: String,
+ allowWrite: Boolean
+)
diff --git a/src/main/scala/gitbucket/core/model/Profile.scala b/src/main/scala/gitbucket/core/model/Profile.scala
index ad01a4c..332e7ea 100644
--- a/src/main/scala/gitbucket/core/model/Profile.scala
+++ b/src/main/scala/gitbucket/core/model/Profile.scala
@@ -54,5 +54,6 @@
with WebHookComponent
with WebHookEventComponent
with ProtectedBranchComponent
+ with DeployKeyComponent
object Profile extends CoreProfile
diff --git a/src/main/scala/gitbucket/core/service/DeployKeyService.scala b/src/main/scala/gitbucket/core/service/DeployKeyService.scala
new file mode 100644
index 0000000..7313bc6
--- /dev/null
+++ b/src/main/scala/gitbucket/core/service/DeployKeyService.scala
@@ -0,0 +1,31 @@
+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, allowWrite: Boolean)
+ (implicit s: Session): Unit =
+ DeployKeys.insert(DeployKey(
+ userName = userName,
+ repositoryName = repositoryName,
+ title = title,
+ publicKey = publicKey,
+ allowWrite = allowWrite
+ ))
+
+ 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
+
+
+}
diff --git a/src/main/scala/gitbucket/core/service/SshKeyService.scala b/src/main/scala/gitbucket/core/service/SshKeyService.scala
index 477413f..5c7dc9d 100644
--- a/src/main/scala/gitbucket/core/service/SshKeyService.scala
+++ b/src/main/scala/gitbucket/core/service/SshKeyService.scala
@@ -7,7 +7,7 @@
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 @@
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
}
diff --git a/src/main/scala/gitbucket/core/service/SystemSettingsService.scala b/src/main/scala/gitbucket/core/service/SystemSettingsService.scala
index 0e1b677..a04f690 100644
--- a/src/main/scala/gitbucket/core/service/SystemSettingsService.scala
+++ b/src/main/scala/gitbucket/core/service/SystemSettingsService.scala
@@ -175,9 +175,9 @@
fromName: Option[String])
case class SshAddress(
- host:String,
- port:Int,
- genericUser:String)
+ host: String,
+ port: Int,
+ genericUser: String)
case class Lfs(
serverUrl: Option[String])
diff --git a/src/main/scala/gitbucket/core/ssh/GitCommand.scala b/src/main/scala/gitbucket/core/ssh/GitCommand.scala
index 9620dbd..ca1e021 100644
--- a/src/main/scala/gitbucket/core/ssh/GitCommand.scala
+++ b/src/main/scala/gitbucket/core/ssh/GitCommand.scala
@@ -2,7 +2,7 @@
import gitbucket.core.model.Profile.profile.blockingApi._
import gitbucket.core.plugin.{GitRepositoryRouting, PluginRegistry}
-import gitbucket.core.service.{AccountService, RepositoryService, SystemSettingsService}
+import gitbucket.core.service.{AccountService, DeployKeyService, RepositoryService, SystemSettingsService}
import gitbucket.core.servlet.{CommitLogHook, Database}
import gitbucket.core.util.{ControlUtil, Directory}
import org.apache.sshd.server.{Command, CommandFactory, Environment, ExitCallback, SessionAware}
@@ -13,6 +13,7 @@
import ControlUtil._
import org.eclipse.jgit.api.Git
import Directory._
+import gitbucket.core.ssh.PublicKeyAuthenticator.AuthType
import org.eclipse.jgit.transport.{ReceivePack, UploadPack}
import org.apache.sshd.server.scp.UnknownCommand
import org.eclipse.jgit.errors.RepositoryNotFoundException
@@ -25,34 +26,33 @@
abstract class GitCommand extends Command with SessionAware {
private val logger = LoggerFactory.getLogger(classOf[GitCommand])
+
@volatile protected var err: OutputStream = null
@volatile protected var in: InputStream = null
@volatile protected var out: OutputStream = null
@volatile protected var callback: ExitCallback = null
- @volatile private var authUser:Option[String] = None
+ @volatile private var authType: Option[AuthType] = None
- protected def runTask(authUser: String): Unit
+ protected def runTask(authType: AuthType): Unit
- private def newTask(): Runnable = new Runnable {
- override def run(): Unit = {
- authUser match {
- case Some(authUser) =>
- try {
- runTask(authUser)
- callback.onExit(0)
- } catch {
- case e: RepositoryNotFoundException =>
- logger.info(e.getMessage)
- callback.onExit(1, "Repository Not Found")
- case e: Throwable =>
- logger.error(e.getMessage, e)
- callback.onExit(1)
- }
- case None =>
- val message = "User not authenticated"
- logger.error(message)
- callback.onExit(1, message)
- }
+ private def newTask(): Runnable = () => {
+ authType match {
+ case Some(authType) =>
+ try {
+ runTask(authType)
+ callback.onExit(0)
+ } catch {
+ case e: RepositoryNotFoundException =>
+ logger.info(e.getMessage)
+ callback.onExit(1, "Repository Not Found")
+ case e: Throwable =>
+ logger.error(e.getMessage, e)
+ callback.onExit(1)
+ }
+ case None =>
+ val message = "User not authenticated"
+ logger.error(message)
+ callback.onExit(1, message)
}
}
@@ -79,32 +79,68 @@
this.in = in
}
- override def setSession(serverSession:ServerSession) {
- this.authUser = PublicKeyAuthenticator.getUserName(serverSession)
+ override def setSession(serverSession: ServerSession) {
+ this.authType = PublicKeyAuthenticator.getAuthType(serverSession)
}
}
abstract class DefaultGitCommand(val owner: String, val repoName: String) extends GitCommand {
- self: RepositoryService with AccountService =>
+ self: RepositoryService with AccountService with DeployKeyService =>
- protected def isWritableUser(username: String, repositoryInfo: RepositoryService.RepositoryInfo)
- (implicit session: Session): Boolean =
- getAccountByUserName(username) match {
- case Some(account) => hasDeveloperRole(repositoryInfo.owner, repositoryInfo.name, Some(account))
- case None => false
+ protected def userName(authType: AuthType): String = {
+ authType match {
+ case AuthType.UserAuthType(userName) => userName
+ case AuthType.DeployKeyType(_) => owner
}
+ }
+
+ protected def isReadableUser(authType: AuthType, repositoryInfo: RepositoryService.RepositoryInfo)
+ (implicit session: Session): Boolean = {
+ authType match {
+ case AuthType.UserAuthType(username) => {
+ getAccountByUserName(username) match {
+ case Some(account) => hasGuestRole(owner, repoName, Some(account))
+ case None => false
+ }
+ }
+ case AuthType.DeployKeyType(key) => {
+ getDeployKeys(owner, repoName).filter(sshKey => SshUtil.str2PublicKey(sshKey.publicKey).exists(_ == key)) match {
+ case List(_) => true
+ case _ => false
+ }
+ }
+ }
+ }
+
+ protected def isWritableUser(authType: AuthType, repositoryInfo: RepositoryService.RepositoryInfo)
+ (implicit session: Session): Boolean = {
+ authType match {
+ case AuthType.UserAuthType(username) => {
+ getAccountByUserName(username) match {
+ case Some(account) => hasDeveloperRole(owner, repoName, Some(account))
+ case None => false
+ }
+ }
+ case AuthType.DeployKeyType(key) => {
+ getDeployKeys(owner, repoName).filter(sshKey => SshUtil.str2PublicKey(sshKey.publicKey).exists(_ == key)) match {
+ case List(x) if x.allowWrite => true
+ case _ => false
+ }
+ }
+ }
+ }
}
class DefaultGitUploadPack(owner: String, repoName: String) extends DefaultGitCommand(owner, repoName)
- with RepositoryService with AccountService {
+ with RepositoryService with AccountService with DeployKeyService {
- override protected def runTask(user: String): Unit = {
+ override protected def runTask(authType: AuthType): Unit = {
val execute = Database() withSession { implicit session =>
getRepository(owner, repoName.replaceFirst("\\.wiki\\Z", "")).map { repositoryInfo =>
- !repositoryInfo.repository.isPrivate || isWritableUser(user, repositoryInfo)
+ !repositoryInfo.repository.isPrivate || isReadableUser(authType, repositoryInfo)
}.getOrElse(false)
}
@@ -119,12 +155,12 @@
}
class DefaultGitReceivePack(owner: String, repoName: String, baseUrl: String) extends DefaultGitCommand(owner, repoName)
- with RepositoryService with AccountService {
+ with RepositoryService with AccountService with DeployKeyService {
- override protected def runTask(user: String): Unit = {
+ override protected def runTask(authType: AuthType): Unit = {
val execute = Database() withSession { implicit session =>
getRepository(owner, repoName.replaceFirst("\\.wiki\\Z", "")).map { repositoryInfo =>
- isWritableUser(user, repositoryInfo)
+ isWritableUser(authType, repositoryInfo)
}.getOrElse(false)
}
@@ -133,7 +169,7 @@
val repository = git.getRepository
val receive = new ReceivePack(repository)
if (!repoName.endsWith(".wiki")) {
- val hook = new CommitLogHook(owner, repoName, user, baseUrl)
+ val hook = new CommitLogHook(owner, repoName, userName(authType), baseUrl)
receive.setPreReceiveHook(hook)
receive.setPostReceiveHook(hook)
}
@@ -143,12 +179,11 @@
}
}
-class PluginGitUploadPack(repoName: String, routing: GitRepositoryRouting) extends GitCommand
- with SystemSettingsService {
+class PluginGitUploadPack(repoName: String, routing: GitRepositoryRouting) extends GitCommand with SystemSettingsService {
- override protected def runTask(user: String): Unit = {
+ override protected def runTask(authType: AuthType): Unit = {
val execute = Database() withSession { implicit session =>
- routing.filter.filter("/" + repoName, Some(user), loadSystemSettings(), false)
+ routing.filter.filter("/" + repoName, AuthType.userName(authType), loadSystemSettings(), false)
}
if(execute){
@@ -162,13 +197,13 @@
}
}
-class PluginGitReceivePack(repoName: String, routing: GitRepositoryRouting) extends GitCommand
- with SystemSettingsService {
+class PluginGitReceivePack(repoName: String, routing: GitRepositoryRouting) extends GitCommand with SystemSettingsService {
- override protected def runTask(user: String): Unit = {
+ override protected def runTask(authType: AuthType): Unit = {
val execute = Database() withSession { implicit session =>
- routing.filter.filter("/" + repoName, Some(user), loadSystemSettings(), true)
+ routing.filter.filter("/" + repoName, AuthType.userName(authType), loadSystemSettings(), true)
}
+
if(execute){
val path = routing.urlPattern.r.replaceFirstIn(repoName, routing.localPath)
using(Git.open(new File(Directory.GitBucketHome, path))){ git =>
diff --git a/src/main/scala/gitbucket/core/ssh/PublicKeyAuthenticator.scala b/src/main/scala/gitbucket/core/ssh/PublicKeyAuthenticator.scala
index fa8d1ce..814e3e9 100644
--- a/src/main/scala/gitbucket/core/ssh/PublicKeyAuthenticator.scala
+++ b/src/main/scala/gitbucket/core/ssh/PublicKeyAuthenticator.scala
@@ -2,73 +2,102 @@
import java.security.PublicKey
-import gitbucket.core.service.SshKeyService
+import gitbucket.core.service.{DeployKeyService, SshKeyService}
import gitbucket.core.servlet.Database
import gitbucket.core.model.Profile.profile.blockingApi._
+import gitbucket.core.ssh.PublicKeyAuthenticator.AuthType
import org.apache.sshd.server.auth.pubkey.PublickeyAuthenticator
import org.apache.sshd.server.session.ServerSession
import org.apache.sshd.common.AttributeStore
import org.slf4j.LoggerFactory
object PublicKeyAuthenticator {
+
// put in the ServerSession here to be read by GitCommand later
- private val userNameSessionKey = new AttributeStore.AttributeKey[String]
+ private val authTypeSessionKey = new AttributeStore.AttributeKey[AuthType]
- def putUserName(serverSession:ServerSession, userName:String):Unit =
- serverSession.setAttribute(userNameSessionKey, userName)
+ def putAuthType(serverSession: ServerSession, authType: AuthType):Unit =
+ serverSession.setAttribute(authTypeSessionKey, authType)
- def getUserName(serverSession:ServerSession):Option[String] =
- Option(serverSession.getAttribute(userNameSessionKey))
+ def getAuthType(serverSession: ServerSession): Option[AuthType] =
+ Option(serverSession.getAttribute(authTypeSessionKey))
+
+ sealed trait AuthType
+
+ object AuthType {
+ case class UserAuthType(userName: String) extends AuthType
+ case class DeployKeyType(publicKey: PublicKey) extends AuthType
+
+ /**
+ * Retrieves username if authType is UserAuthType, otherwise None.
+ */
+ def userName(authType: AuthType): Option[String] = {
+ authType match {
+ case UserAuthType(userName) => Some(userName)
+ case _ => None
+ }
+ }
+ }
}
-class PublicKeyAuthenticator(genericUser:String) extends PublickeyAuthenticator with SshKeyService {
+class PublicKeyAuthenticator(genericUser: String) extends PublickeyAuthenticator with SshKeyService with DeployKeyService {
private val logger = LoggerFactory.getLogger(classOf[PublicKeyAuthenticator])
- override def authenticate(username: String, key: PublicKey, session: ServerSession): Boolean =
- if (username == genericUser) authenticateGenericUser(username, key, session, genericUser)
- else authenticateLoginUser(username, key, session)
-
- private def authenticateLoginUser(username: String, key: PublicKey, session: ServerSession): Boolean = {
- val authenticated =
- Database()
- .withSession { implicit dbSession => getPublicKeys(username) }
- .map(_.publicKey)
- .flatMap(SshUtil.str2PublicKey)
- .contains(key)
- if (authenticated) {
- logger.info(s"authentication as ssh user ${username} succeeded")
- PublicKeyAuthenticator.putUserName(session, username)
+ override def authenticate(username: String, key: PublicKey, session: ServerSession): Boolean = {
+ Database().withSession { implicit s =>
+ if (username == genericUser) {
+ authenticateGenericUser(username, key, session, genericUser)
+ } else {
+ authenticateLoginUser(username, key, session)
+ }
}
- else {
- logger.info(s"authentication as ssh user ${username} failed")
+ }
+
+ private def authenticateLoginUser(userName: String, key: PublicKey, session: ServerSession)(implicit s: Session): Boolean = {
+ val authenticated = getPublicKeys(userName).map(_.publicKey).flatMap(SshUtil.str2PublicKey).contains(key)
+
+ if (authenticated) {
+ logger.info(s"authentication as ssh user ${userName} succeeded")
+ PublicKeyAuthenticator.putAuthType(session, AuthType.UserAuthType(userName))
+ } else {
+ logger.info(s"authentication as ssh user ${userName} failed")
}
authenticated
}
- private def authenticateGenericUser(username: String, key: PublicKey, session: ServerSession, genericUser:String): Boolean = {
+ private def authenticateGenericUser(userName: String, key: PublicKey, session: ServerSession, genericUser: String)(implicit s: Session): Boolean = {
// find all users having the key we got from ssh
- val possibleUserNames =
- Database()
- .withSession { implicit dbSession => getAllKeys() }
- .filter { sshKey =>
+ val possibleUserNames = getAllKeys().filter { sshKey =>
+ SshUtil.str2PublicKey(sshKey.publicKey).exists(_ == key)
+ }.map(_.userName).distinct
+
+ // determine the user - if different accounts share the same key, tough luck
+ val uniqueUserName = possibleUserNames match {
+ case List(name) => Some(name)
+ case _ => None
+ }
+
+ uniqueUserName.map { userName =>
+ // found public key for user
+ logger.info(s"authentication as generic user ${genericUser} succeeded, identified ${userName}")
+ PublicKeyAuthenticator.putAuthType(session, AuthType.UserAuthType(userName))
+ true
+ }.getOrElse {
+ // search deploy keys
+ val existsDeployKey = getAllDeployKeys().exists { sshKey =>
SshUtil.str2PublicKey(sshKey.publicKey).exists(_ == key)
}
- .map(_.userName)
- .distinct
- // determine the user - if different accounts share the same key, tough luck
- val uniqueUserName =
- possibleUserNames match {
- case List() =>
- logger.info(s"authentication as generic user ${genericUser} failed, public key not found")
- None
- case List(name) =>
- logger.info(s"authentication as generic user ${genericUser} succeeded, identified ${name}")
- Some(name)
- case _ =>
- logger.info(s"authentication as generic user ${genericUser} failed, public key is ambiguous")
- None
+ if(existsDeployKey){
+ // found deploy key for repository
+ PublicKeyAuthenticator.putAuthType(session, AuthType.DeployKeyType(key))
+ logger.info(s"authentication as generic user ${genericUser} succeeded, deploy key was found")
+ true
+ } else {
+ // public key not found
+ logger.info(s"authentication by generic user ${genericUser} failed")
+ false
}
- uniqueUserName.foreach(PublicKeyAuthenticator.putUserName(session, _))
- uniqueUserName.isDefined
+ }
}
+
}
diff --git a/src/main/twirl/gitbucket/core/account/ssh.scala.html b/src/main/twirl/gitbucket/core/account/ssh.scala.html
index 2a87dfa..a8fe812 100644
--- a/src/main/twirl/gitbucket/core/account/ssh.scala.html
+++ b/src/main/twirl/gitbucket/core/account/ssh.scala.html
@@ -20,7 +20,7 @@