(refs #115)Start and stop sshd at the system settings

This commit is contained in:
takezoe
2014-03-10 00:44:25 +09:00
parent 525edbab80
commit 845f2d6faa
5 changed files with 66 additions and 19 deletions

View File

@@ -4,6 +4,7 @@ import service.{AccountService, SystemSettingsService}
import SystemSettingsService._ import SystemSettingsService._
import util.AdminAuthenticator import util.AdminAuthenticator
import jp.sf.amateras.scalatra.forms._ import jp.sf.amateras.scalatra.forms._
import ssh.SshServer
class SystemSettingsController extends SystemSettingsControllerBase class SystemSettingsController extends SystemSettingsControllerBase
with SystemSettingsService with AccountService with AdminAuthenticator with SystemSettingsService with AccountService with AdminAuthenticator
@@ -16,6 +17,8 @@ trait SystemSettingsControllerBase extends ControllerBase {
"allowAccountRegistration" -> trim(label("Account registration", boolean())), "allowAccountRegistration" -> trim(label("Account registration", boolean())),
"gravatar" -> trim(label("Gravatar", boolean())), "gravatar" -> trim(label("Gravatar", boolean())),
"notification" -> trim(label("Notification", boolean())), "notification" -> trim(label("Notification", boolean())),
"ssh" -> trim(label("SSH access", boolean())),
"sshPort" -> trim(label("SSH port", optional(number()))),
"smtp" -> optionalIfNotChecked("notification", mapping( "smtp" -> optionalIfNotChecked("notification", mapping(
"host" -> trim(label("SMTP Host", text(required))), "host" -> trim(label("SMTP Host", text(required))),
"port" -> trim(label("SMTP Port", optional(number()))), "port" -> trim(label("SMTP Port", optional(number()))),
@@ -47,6 +50,13 @@ trait SystemSettingsControllerBase extends ControllerBase {
post("/admin/system", form)(adminOnly { form => post("/admin/system", form)(adminOnly { form =>
saveSystemSettings(form) saveSystemSettings(form)
if(form.ssh && !SshServer.isActive){
SshServer.start(request.getServletContext, form.sshPort.getOrElse(SystemSettingsService.DefaultSshPort))
} else if(!form.ssh && SshServer.isActive){
SshServer.stop()
}
flash += "info" -> "System settings has been updated." flash += "info" -> "System settings has been updated."
redirect("/admin/system") redirect("/admin/system")
}) })

View File

@@ -19,6 +19,8 @@ trait SystemSettingsService {
props.setProperty(AllowAccountRegistration, settings.allowAccountRegistration.toString) props.setProperty(AllowAccountRegistration, settings.allowAccountRegistration.toString)
props.setProperty(Gravatar, settings.gravatar.toString) props.setProperty(Gravatar, settings.gravatar.toString)
props.setProperty(Notification, settings.notification.toString) props.setProperty(Notification, settings.notification.toString)
props.setProperty(Ssh, settings.ssh.toString)
settings.sshPort.foreach(x => props.setProperty(SshPort, x.toString))
if(settings.notification) { if(settings.notification) {
settings.smtp.foreach { smtp => settings.smtp.foreach { smtp =>
props.setProperty(SmtpHost, smtp.host) props.setProperty(SmtpHost, smtp.host)
@@ -60,6 +62,8 @@ trait SystemSettingsService {
getValue(props, AllowAccountRegistration, false), getValue(props, AllowAccountRegistration, false),
getValue(props, Gravatar, true), getValue(props, Gravatar, true),
getValue(props, Notification, false), getValue(props, Notification, false),
getValue(props, Ssh, false),
getOptionValue(props, SshPort, Some(DefaultSshPort)),
if(getValue(props, Notification, false)){ if(getValue(props, Notification, false)){
Some(Smtp( Some(Smtp(
getValue(props, SmtpHost, ""), getValue(props, SmtpHost, ""),
@@ -102,6 +106,8 @@ object SystemSettingsService {
allowAccountRegistration: Boolean, allowAccountRegistration: Boolean,
gravatar: Boolean, gravatar: Boolean,
notification: Boolean, notification: Boolean,
ssh: Boolean,
sshPort: Option[Int],
smtp: Option[Smtp], smtp: Option[Smtp],
ldapAuthentication: Boolean, ldapAuthentication: Boolean,
ldap: Option[Ldap]) ldap: Option[Ldap])
@@ -127,6 +133,7 @@ object SystemSettingsService {
fromAddress: Option[String], fromAddress: Option[String],
fromName: Option[String]) fromName: Option[String])
val DefaultSshPort = 29418
val DefaultSmtpPort = 25 val DefaultSmtpPort = 25
val DefaultLdapPort = 389 val DefaultLdapPort = 389
@@ -134,6 +141,8 @@ object SystemSettingsService {
private val AllowAccountRegistration = "allow_account_registration" private val AllowAccountRegistration = "allow_account_registration"
private val Gravatar = "gravatar" private val Gravatar = "gravatar"
private val Notification = "notification" private val Notification = "notification"
private val Ssh = "ssh"
private val SshPort = "ssh.port"
private val SmtpHost = "smtp.host" private val SmtpHost = "smtp.host"
private val SmtpPort = "smtp.port" private val SmtpPort = "smtp.port"
private val SmtpUser = "smtp.user" private val SmtpUser = "smtp.user"

View File

@@ -82,7 +82,7 @@ abstract class GitCommand(val command: String) extends Command {
} }
} }
class GitUploadPack(override val command: String) extends GitCommand(command: String) { class GitUploadPack(context: ServletContext, override val command: String) extends GitCommand(command: String) {
override protected def runTask(user: String): Unit = { override protected def runTask(user: String): Unit = {
using(Git.open(getRepositoryDir(owner, repositoryName))) { using(Git.open(getRepositoryDir(owner, repositoryName))) {
@@ -119,7 +119,7 @@ class GitCommandFactory(context: ServletContext) extends CommandFactory {
override def createCommand(command: String): Command = { override def createCommand(command: String): Command = {
logger.debug(s"command: $command") logger.debug(s"command: $command")
command match { command match {
case GitCommand.CommandRegex("upload", owner, repoName) => new GitUploadPack(command) case GitCommand.CommandRegex("upload", owner, repoName) => new GitUploadPack(context, command)
case GitCommand.CommandRegex("receive", owner, repoName) => new GitReceivePack(context, command) case GitCommand.CommandRegex("receive", owner, repoName) => new GitReceivePack(context, command)
case _ => new UnknownCommand(command) case _ => new UnknownCommand(command)
} }

View File

@@ -4,36 +4,36 @@ import javax.servlet.{ServletContext, ServletContextEvent, ServletContextListene
import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import util.Directory import util.Directory
import service.SystemSettingsService
import java.util.concurrent.atomic.AtomicBoolean
object SshServer { object SshServer {
private val logger = LoggerFactory.getLogger(SshServer.getClass) private val logger = LoggerFactory.getLogger(SshServer.getClass)
val DEFAULT_PORT: Int = 29418
// TODO read from config
val SSH_SERVICE_ENABLE = true // TODO read from config
private val server = org.apache.sshd.SshServer.setUpDefaultServer() private val server = org.apache.sshd.SshServer.setUpDefaultServer()
private val active = new AtomicBoolean(false);
private def configure(context: ServletContext) = { private def configure(context: ServletContext, port: Int) = {
server.setPort(DEFAULT_PORT) // TODO read from config server.setPort(port)
server.setKeyPairProvider(new SimpleGeneratorHostKeyProvider(s"${Directory.GitBucketHome}/gitbucket.ser")) server.setKeyPairProvider(new SimpleGeneratorHostKeyProvider(s"${Directory.GitBucketHome}/gitbucket.ser"))
server.setPublickeyAuthenticator(new PublicKeyAuthenticator(context)) server.setPublickeyAuthenticator(new PublicKeyAuthenticator(context))
server.setCommandFactory(new GitCommandFactory(context)) server.setCommandFactory(new GitCommandFactory(context))
} }
def start(context: ServletContext) = this.synchronized { def start(context: ServletContext, port: Int) = {
if (SSH_SERVICE_ENABLE) { if(active.compareAndSet(false, true)){
configure(context, port)
configure(context)
server.start() server.start()
logger.info(s"Start SSH Server Listen on ${server.getPort}") logger.info(s"Start SSH Server Listen on ${server.getPort}")
} }
} }
def stop() = { def stop() = {
server.stop(true) if(active.compareAndSet(true, false)){
server.stop(true)
}
} }
def isActive = active.get
} }
/* /*
@@ -41,16 +41,20 @@ object SshServer {
* *
* How to use: * How to use:
* git clone ssh://username@host_or_ip:29418/owner/repository_name.git * git clone ssh://username@host_or_ip:29418/owner/repository_name.git
*
*/ */
class SshServerListener extends ServletContextListener { class SshServerListener extends ServletContextListener with SystemSettingsService {
override def contextInitialized(sce: ServletContextEvent): Unit = { override def contextInitialized(sce: ServletContextEvent): Unit = {
SshServer.start(sce.getServletContext) val settings = loadSystemSettings()
if(settings.ssh){
SshServer.start(sce.getServletContext, settings.sshPort.getOrElse(SystemSettingsService.DefaultSshPort))
}
} }
override def contextDestroyed(sce: ServletContextEvent): Unit = { override def contextDestroyed(sce: ServletContextEvent): Unit = {
SshServer.stop() if(loadSystemSettings().ssh){
SshServer.stop()
}
} }
} }

View File

@@ -56,6 +56,26 @@
</label> </label>
</fieldset> </fieldset>
<!--====================================================================--> <!--====================================================================-->
<!-- SSH access -->
<!--====================================================================-->
<hr>
<label class="strong">SSH access</label>
<fieldset>
<label class="checkbox">
<input type="checkbox" id="ssh" name="ssh"@if(settings.ssh){ checked}/>
Enable SSH access to git repository
</label>
</fieldset>
<div class="form-horizontal ssh">
<div class="control-group">
<label class="control-label" for="sshPort">SSH Port</label>
<div class="controls">
<input type="text" id="sshPort" name="sshPort" value="@settings.sshPort"/>
<span id="error-sshPort" class="error"></span>
</div>
</div>
</div>
<!--====================================================================-->
<!-- Authentication --> <!-- Authentication -->
<!--====================================================================--> <!--====================================================================-->
<hr> <hr>
@@ -206,6 +226,10 @@
} }
<script> <script>
$(function(){ $(function(){
$('#ssh').change(function(){
$('.ssh input').prop('disabled', !$(this).prop('checked'));
}).change();
$('#notification').change(function(){ $('#notification').change(function(){
$('.notification input').prop('disabled', !$(this).prop('checked')); $('.notification input').prop('disabled', !$(this).prop('checked'));
}).change(); }).change();