(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 util.AdminAuthenticator
import jp.sf.amateras.scalatra.forms._
import ssh.SshServer
class SystemSettingsController extends SystemSettingsControllerBase
with SystemSettingsService with AccountService with AdminAuthenticator
@@ -16,6 +17,8 @@ trait SystemSettingsControllerBase extends ControllerBase {
"allowAccountRegistration" -> trim(label("Account registration", boolean())),
"gravatar" -> trim(label("Gravatar", boolean())),
"notification" -> trim(label("Notification", boolean())),
"ssh" -> trim(label("SSH access", boolean())),
"sshPort" -> trim(label("SSH port", optional(number()))),
"smtp" -> optionalIfNotChecked("notification", mapping(
"host" -> trim(label("SMTP Host", text(required))),
"port" -> trim(label("SMTP Port", optional(number()))),
@@ -47,6 +50,13 @@ trait SystemSettingsControllerBase extends ControllerBase {
post("/admin/system", form)(adminOnly { 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."
redirect("/admin/system")
})

View File

@@ -19,6 +19,8 @@ trait SystemSettingsService {
props.setProperty(AllowAccountRegistration, settings.allowAccountRegistration.toString)
props.setProperty(Gravatar, settings.gravatar.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) {
settings.smtp.foreach { smtp =>
props.setProperty(SmtpHost, smtp.host)
@@ -60,6 +62,8 @@ trait SystemSettingsService {
getValue(props, AllowAccountRegistration, false),
getValue(props, Gravatar, true),
getValue(props, Notification, false),
getValue(props, Ssh, false),
getOptionValue(props, SshPort, Some(DefaultSshPort)),
if(getValue(props, Notification, false)){
Some(Smtp(
getValue(props, SmtpHost, ""),
@@ -102,6 +106,8 @@ object SystemSettingsService {
allowAccountRegistration: Boolean,
gravatar: Boolean,
notification: Boolean,
ssh: Boolean,
sshPort: Option[Int],
smtp: Option[Smtp],
ldapAuthentication: Boolean,
ldap: Option[Ldap])
@@ -127,6 +133,7 @@ object SystemSettingsService {
fromAddress: Option[String],
fromName: Option[String])
val DefaultSshPort = 29418
val DefaultSmtpPort = 25
val DefaultLdapPort = 389
@@ -134,6 +141,8 @@ object SystemSettingsService {
private val AllowAccountRegistration = "allow_account_registration"
private val Gravatar = "gravatar"
private val Notification = "notification"
private val Ssh = "ssh"
private val SshPort = "ssh.port"
private val SmtpHost = "smtp.host"
private val SmtpPort = "smtp.port"
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 = {
using(Git.open(getRepositoryDir(owner, repositoryName))) {
@@ -119,7 +119,7 @@ class GitCommandFactory(context: ServletContext) extends CommandFactory {
override def createCommand(command: String): Command = {
logger.debug(s"command: $command")
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 _ => new UnknownCommand(command)
}

View File

@@ -4,53 +4,57 @@ import javax.servlet.{ServletContext, ServletContextEvent, ServletContextListene
import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider
import org.slf4j.LoggerFactory
import util.Directory
import service.SystemSettingsService
import java.util.concurrent.atomic.AtomicBoolean
object SshServer {
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 active = new AtomicBoolean(false);
private def configure(context: ServletContext) = {
server.setPort(DEFAULT_PORT) // TODO read from config
private def configure(context: ServletContext, port: Int) = {
server.setPort(port)
server.setKeyPairProvider(new SimpleGeneratorHostKeyProvider(s"${Directory.GitBucketHome}/gitbucket.ser"))
server.setPublickeyAuthenticator(new PublicKeyAuthenticator(context))
server.setCommandFactory(new GitCommandFactory(context))
}
def start(context: ServletContext) = this.synchronized {
if (SSH_SERVICE_ENABLE) {
configure(context)
def start(context: ServletContext, port: Int) = {
if(active.compareAndSet(false, true)){
configure(context, port)
server.start()
logger.info(s"Start SSH Server Listen on ${server.getPort}")
}
}
def stop() = {
if(active.compareAndSet(true, false)){
server.stop(true)
}
}
def isActive = active.get
}
/*
* Start a SSH Server Daemon
*
* How to use:
* 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 = {
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 = {
if(loadSystemSettings().ssh){
SshServer.stop()
}
}
}

View File

@@ -56,6 +56,26 @@
</label>
</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 -->
<!--====================================================================-->
<hr>
@@ -206,6 +226,10 @@
}
<script>
$(function(){
$('#ssh').change(function(){
$('.ssh input').prop('disabled', !$(this).prop('checked'));
}).change();
$('#notification').change(function(){
$('.notification input').prop('disabled', !$(this).prop('checked'));
}).change();