diff --git a/src/main/scala/ScalatraBootstrap.scala b/src/main/scala/ScalatraBootstrap.scala index c8e617a..41bb103 100644 --- a/src/main/scala/ScalatraBootstrap.scala +++ b/src/main/scala/ScalatraBootstrap.scala @@ -6,7 +6,8 @@ override def init(context: ServletContext) { context.mount(new IndexController, "/") context.mount(new SignInController, "/*") - context.mount(new UsersController, "/*") + context.mount(new UserManagementController, "/*") + context.mount(new SystemSettingsController, "/*") context.mount(new CreateRepositoryController, "/*") context.mount(new AccountController, "/*") context.mount(new RepositoryViewerController, "/*") diff --git a/src/main/scala/app/SystemSettingsController.scala b/src/main/scala/app/SystemSettingsController.scala new file mode 100644 index 0000000..1518544 --- /dev/null +++ b/src/main/scala/app/SystemSettingsController.scala @@ -0,0 +1,30 @@ +package app + +import service.{AccountService, SystemSettingsService} +import SystemSettingsService._ +import util.AdminOnlyAuthenticator +import jp.sf.amateras.scalatra.forms._ + +class SystemSettingsController extends SystemSettingsControllerBase + with SystemSettingsService with AccountService with AdminOnlyAuthenticator + +trait SystemSettingsControllerBase extends ControllerBase { + self: SystemSettingsService with AccountService with AdminOnlyAuthenticator => + + private case class SystemSettingsForm(allowAccountRegistration: Boolean) + + private val form = mapping( + "allowAccountRegistration" -> trim(label("Account registration", boolean())) + )(SystemSettingsForm.apply) + + + get("/admin/system")(adminOnly { + admin.html.system(loadSystemSettings()) + }) + + post("/admin/system", form)(adminOnly { form => + saveSystemSettings(SystemSettings(form.allowAccountRegistration)) + redirect("/admin/system") + }) + +} diff --git a/src/main/scala/app/UserManagementController.scala b/src/main/scala/app/UserManagementController.scala new file mode 100644 index 0000000..9b30b2d --- /dev/null +++ b/src/main/scala/app/UserManagementController.scala @@ -0,0 +1,64 @@ +package app + +import model._ +import service._ +import util.AdminOnlyAuthenticator +import jp.sf.amateras.scalatra.forms._ + +class UserManagementController extends UserManagementControllerBase with AccountService with AdminOnlyAuthenticator + +trait UserManagementControllerBase extends ControllerBase { self: AccountService with AdminOnlyAuthenticator => + + case class UserForm(userName: String, password: String, mailAddress: String, isAdmin: Boolean, url: Option[String]) + + val newForm = mapping( + "userName" -> trim(label("Username" , text(required, maxlength(100), identifier, unique))), + "password" -> trim(label("Password" , text(required, maxlength(100)))), + "mailAddress" -> trim(label("Mail Address" , text(required, maxlength(100)))), + "isAdmin" -> trim(label("User Type" , boolean())), + "url" -> trim(label("URL" , optional(text(maxlength(200))))) + )(UserForm.apply) + + val editForm = mapping( + "userName" -> trim(label("Username" , text(required, maxlength(100), identifier))), + "password" -> trim(label("Password" , text(required, maxlength(100)))), + "mailAddress" -> trim(label("Mail Address" , text(required, maxlength(100)))), + "isAdmin" -> trim(label("User Type" , boolean())), + "url" -> trim(label("URL" , optional(text(maxlength(200))))) + )(UserForm.apply) + + get("/admin/users")(adminOnly { + admin.html.userlist(getAllUsers()) + }) + + get("/admin/users/_new")(adminOnly { + admin.html.useredit(None) + }) + + post("/admin/users/_new", newForm)(adminOnly { form => + createAccount(form.userName, form.password, form.mailAddress, form.isAdmin, form.url) + redirect("/admin/users") + }) + + get("/admin/users/:userName/_edit")(adminOnly { + val userName = params("userName") + admin.html.useredit(getAccountByUserName(userName)) + }) + + post("/admin/users/:name/_edit", editForm)(adminOnly { form => + val userName = params("userName") + updateAccount(getAccountByUserName(userName).get.copy( + password = form.password, + mailAddress = form.mailAddress, + isAdmin = form.isAdmin, + url = form.url)) + + redirect("/admin/users") + }) + + private def unique: Constraint = new Constraint(){ + def validate(name: String, value: String): Option[String] = + getAccountByUserName(value).map { _ => "User already exists." } + } + +} \ No newline at end of file diff --git a/src/main/scala/app/UsersController.scala b/src/main/scala/app/UsersController.scala deleted file mode 100644 index a0acb63..0000000 --- a/src/main/scala/app/UsersController.scala +++ /dev/null @@ -1,64 +0,0 @@ -package app - -import model._ -import service._ -import util.AdminOnlyAuthenticator -import jp.sf.amateras.scalatra.forms._ - -class UsersController extends UsersControllerBase with AccountService with AdminOnlyAuthenticator - -trait UsersControllerBase extends ControllerBase { self: AccountService with AdminOnlyAuthenticator => - - case class UserForm(userName: String, password: String, mailAddress: String, isAdmin: Boolean, url: Option[String]) - - val newForm = mapping( - "userName" -> trim(label("Username" , text(required, maxlength(100), identifier, unique))), - "password" -> trim(label("Password" , text(required, maxlength(100)))), - "mailAddress" -> trim(label("Mail Address" , text(required, maxlength(100)))), - "isAdmin" -> trim(label("User Type" , boolean())), - "url" -> trim(label("URL" , optional(text(maxlength(200))))) - )(UserForm.apply) - - val editForm = mapping( - "userName" -> trim(label("Username" , text(required, maxlength(100), identifier))), - "password" -> trim(label("Password" , text(required, maxlength(100)))), - "mailAddress" -> trim(label("Mail Address" , text(required, maxlength(100)))), - "isAdmin" -> trim(label("User Type" , boolean())), - "url" -> trim(label("URL" , optional(text(maxlength(200))))) - )(UserForm.apply) - - get("/admin/users")(adminOnly { - admin.html.userlist(getAllUsers()) - }) - - get("/admin/users/_new")(adminOnly { - admin.html.useredit(None) - }) - - post("/admin/users/_new", newForm)(adminOnly { form => - createAccount(form.userName, form.password, form.mailAddress, form.isAdmin, form.url) - redirect("/admin/users") - }) - - get("/admin/users/:userName/_edit")(adminOnly { - val userName = params("userName") - admin.html.useredit(getAccountByUserName(userName)) - }) - - post("/admin/users/:name/_edit", editForm)(adminOnly { form => - val userName = params("userName") - updateAccount(getAccountByUserName(userName).get.copy( - password = form.password, - mailAddress = form.mailAddress, - isAdmin = form.isAdmin, - url = form.url)) - - redirect("/admin/users") - }) - - private def unique: Constraint = new Constraint(){ - def validate(name: String, value: String): Option[String] = - getAccountByUserName(value).map { _ => "User already exists." } - } - -} \ No newline at end of file diff --git a/src/main/scala/service/SystemSettingsService.scala b/src/main/scala/service/SystemSettingsService.scala new file mode 100644 index 0000000..b425b34 --- /dev/null +++ b/src/main/scala/service/SystemSettingsService.scala @@ -0,0 +1,40 @@ +package service + +import util.Directory._ +import SystemSettingsService._ + +trait SystemSettingsService { + + def saveSystemSettings(settings: SystemSettings): Unit = { + val props = new java.util.Properties() + props.setProperty(AllowAccountRegistration, settings.allowAccountRegistration.toString) + props.store(new java.io.FileOutputStream(GitBucketConf), null) + } + + + def loadSystemSettings(): SystemSettings = { + val props = new java.util.Properties() + if(GitBucketConf.exists){ + props.load(new java.io.FileInputStream(GitBucketConf)) + } + SystemSettings(getBoolean(props, "allow_account_registration")) + } + +} + +object SystemSettingsService { + + case class SystemSettings(allowAccountRegistration: Boolean) + + private val AllowAccountRegistration = "allow_account_registration" + + private def getBoolean(props: java.util.Properties, key: String, default: Boolean = false): Boolean = { + val value = props.getProperty(key) + if(value == null || value.isEmpty){ + default + } else { + value.toBoolean + } + } + +} diff --git a/src/main/scala/util/Directory.scala b/src/main/scala/util/Directory.scala index e9c7567..6742528 100644 --- a/src/main/scala/util/Directory.scala +++ b/src/main/scala/util/Directory.scala @@ -10,6 +10,8 @@ object Directory { val GitBucketHome = new File(System.getProperty("user.home"), "gitbucket").getAbsolutePath + + val GitBucketConf = new File(GitBucketHome, "gitbucket.conf") val RepositoryHome = "%s/repositories".format(GitBucketHome) diff --git a/src/main/twirl/admin/menu.scala.html b/src/main/twirl/admin/menu.scala.html new file mode 100644 index 0000000..eec5ecb --- /dev/null +++ b/src/main/twirl/admin/menu.scala.html @@ -0,0 +1,17 @@ +@(active: String)(body: Html)(implicit context: app.Context) +@import context._ +
+
+ +
+
+ @body +
+
diff --git a/src/main/twirl/admin/system.scala.html b/src/main/twirl/admin/system.scala.html new file mode 100644 index 0000000..a0500cf --- /dev/null +++ b/src/main/twirl/admin/system.scala.html @@ -0,0 +1,28 @@ +@(settings: service.SystemSettingsService.SystemSettings)(implicit context: app.Context) +@import context._ +@import view.helpers._ +@html.main("System Settings"){ + @menu("system"){ +
+
+
System Settings
+
+ +
+ + +
+
+
+
+ +
+
+ } +} \ No newline at end of file diff --git a/src/main/twirl/admin/useredit.scala.html b/src/main/twirl/admin/useredit.scala.html index 729cc98..c8aa1d7 100644 --- a/src/main/twirl/admin/useredit.scala.html +++ b/src/main/twirl/admin/useredit.scala.html @@ -1,39 +1,41 @@ @(account: Option[model.Account])(implicit context: app.Context) @import context._ @html.main(if(account.isEmpty) "New User" else "Update User"){ -
-
- - - -
-
- - - -
-
- - - -
-
- - - -
-
- - - -
-
- - Cancel -
-
+ @menu("users"){ +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + Cancel +
+
+ } } \ No newline at end of file diff --git a/src/main/twirl/admin/userlist.scala.html b/src/main/twirl/admin/userlist.scala.html index e72dd73..28a7700 100644 --- a/src/main/twirl/admin/userlist.scala.html +++ b/src/main/twirl/admin/userlist.scala.html @@ -1,36 +1,41 @@ @(users: List[model.Account])(implicit context: app.Context) @import context._ -@import view.helpers +@import view.helpers._ @html.main("Manage Users"){ -
- New User -
- - - - - - - - - - - @users.map { account => - - - - - - - - - - } -
UsernameMail AddressTypeURLRegisteredUpdatedLast Login
@account.userName@account.mailAddress - @if(account.isAdmin){ - Administrator - } else { - Normal - } - @account.url@helpers.datetime(account.registeredDate)@helpers.datetime(account.updatedDate)@account.lastLoginDate.map(helpers.datetime)
+ @menu("users"){ +
+ New User +
+ + @users.map { account => + + + + } +
+
+ Edit +
+
+ @account.userName + @if(account.isAdmin){ + (Administrator) + } else { + (Normal) + } +
+
+
+ @account.mailAddress + @account.url.map { url => + @url + } +
+
+ Registered: @datetime(account.registeredDate) + Updated: @datetime(account.updatedDate) + Last Login: @account.lastLoginDate.map(datetime) +
+
+ } } \ No newline at end of file