diff --git a/src/main/resources/update/gitbucket-core_4.9.xml b/src/main/resources/update/gitbucket-core_4.9.xml
new file mode 100644
index 0000000..afeffc2
--- /dev/null
+++ b/src/main/resources/update/gitbucket-core_4.9.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/scala/gitbucket/core/GitBucketCoreModule.scala b/src/main/scala/gitbucket/core/GitBucketCoreModule.scala
index 3fadd2d..66b35aa 100644
--- a/src/main/scala/gitbucket/core/GitBucketCoreModule.scala
+++ b/src/main/scala/gitbucket/core/GitBucketCoreModule.scala
@@ -24,5 +24,8 @@
new SqlMigration("update/gitbucket-core_4.7.sql")
),
new Version("4.7.1"),
- new Version("4.8")
+ new Version("4.8"),
+ new Version("4.9",
+ new LiquibaseMigration("update/gitbucket-core_4.9.xml")
+ )
)
diff --git a/src/main/scala/gitbucket/core/controller/AccountController.scala b/src/main/scala/gitbucket/core/controller/AccountController.scala
index bfb9ccd..b16c747 100644
--- a/src/main/scala/gitbucket/core/controller/AccountController.scala
+++ b/src/main/scala/gitbucket/core/controller/AccountController.scala
@@ -29,10 +29,10 @@
with AccessTokenService with WebHookService with RepositoryCreationService =>
case class AccountNewForm(userName: String, password: String, fullName: String, mailAddress: String,
- url: Option[String], fileId: Option[String])
+ description: Option[String], url: Option[String], fileId: Option[String])
case class AccountEditForm(password: Option[String], fullName: String, mailAddress: String,
- url: Option[String], fileId: Option[String], clearImage: Boolean)
+ description: Option[String], url: Option[String], fileId: Option[String], clearImage: Boolean)
case class SshKeyForm(title: String, publicKey: String)
@@ -43,6 +43,7 @@
"password" -> trim(label("Password" , text(required, maxlength(20)))),
"fullName" -> trim(label("Full Name" , text(required, maxlength(100)))),
"mailAddress" -> trim(label("Mail Address" , text(required, maxlength(100), uniqueMailAddress()))),
+ "description" -> trim(label("bio" , optional(text()))),
"url" -> trim(label("URL" , optional(text(maxlength(200))))),
"fileId" -> trim(label("File ID" , optional(text())))
)(AccountNewForm.apply)
@@ -51,6 +52,7 @@
"password" -> trim(label("Password" , optional(text(maxlength(20))))),
"fullName" -> trim(label("Full Name" , text(required, maxlength(100)))),
"mailAddress" -> trim(label("Mail Address" , text(required, maxlength(100), uniqueMailAddress("userName")))),
+ "description" -> trim(label("bio" , optional(text()))),
"url" -> trim(label("URL" , optional(text(maxlength(200))))),
"fileId" -> trim(label("File ID" , optional(text()))),
"clearImage" -> trim(label("Clear image" , boolean()))
@@ -65,11 +67,12 @@
"note" -> trim(label("Token", text(required, maxlength(100))))
)(PersonalTokenForm.apply)
- case class NewGroupForm(groupName: String, url: Option[String], fileId: Option[String], members: String)
- case class EditGroupForm(groupName: String, url: Option[String], fileId: Option[String], members: String, clearImage: Boolean)
+ case class NewGroupForm(groupName: String, description: Option[String], url: Option[String], fileId: Option[String], members: String)
+ case class EditGroupForm(groupName: String, description: Option[String], url: Option[String], fileId: Option[String], members: String, clearImage: Boolean)
val newGroupForm = mapping(
"groupName" -> trim(label("Group name" ,text(required, maxlength(100), identifier, uniqueUserName, reservedNames))),
+ "description" -> trim(label("Group description", optional(text()))),
"url" -> trim(label("URL" ,optional(text(maxlength(200))))),
"fileId" -> trim(label("File ID" ,optional(text()))),
"members" -> trim(label("Members" ,text(required, members)))
@@ -77,6 +80,7 @@
val editGroupForm = mapping(
"groupName" -> trim(label("Group name" ,text(required, maxlength(100), identifier))),
+ "description" -> trim(label("Group description", optional(text()))),
"url" -> trim(label("URL" ,optional(text(maxlength(200))))),
"fileId" -> trim(label("File ID" ,optional(text()))),
"members" -> trim(label("Members" ,text(required, members))),
@@ -167,6 +171,7 @@
password = form.password.map(sha1).getOrElse(account.password),
fullName = form.fullName,
mailAddress = form.mailAddress,
+ description = form.description,
url = form.url))
updateImage(userName, form.fileId, form.clearImage)
@@ -266,7 +271,7 @@
post("/register", newForm){ form =>
if(context.settings.allowAccountRegistration){
- createAccount(form.userName, sha1(form.password), form.fullName, form.mailAddress, false, form.url)
+ createAccount(form.userName, sha1(form.password), form.fullName, form.mailAddress, false, form.description, form.url)
updateImage(form.userName, form.fileId, false)
redirect("/signin")
} else NotFound()
@@ -277,7 +282,7 @@
})
post("/groups/new", newGroupForm)(usersOnly { form =>
- createGroup(form.groupName, form.url)
+ createGroup(form.groupName, form.description, form.url)
updateGroupMembers(form.groupName, form.members.split(",").map {
_.split(":") match {
case Array(userName, isManager) => (userName, isManager.toBoolean)
@@ -315,7 +320,7 @@
}
}.toList){ case (groupName, members) =>
getAccountByUserName(groupName, true).map { account =>
- updateGroup(groupName, form.url, false)
+ updateGroup(groupName, form.description, form.url, false)
// Update GROUP_MEMBER
updateGroupMembers(form.groupName, members)
diff --git a/src/main/scala/gitbucket/core/controller/SystemSettingsController.scala b/src/main/scala/gitbucket/core/controller/SystemSettingsController.scala
index f19fc90..801b873 100644
--- a/src/main/scala/gitbucket/core/controller/SystemSettingsController.scala
+++ b/src/main/scala/gitbucket/core/controller/SystemSettingsController.scala
@@ -91,16 +91,16 @@
case class NewUserForm(userName: String, password: String, fullName: String,
mailAddress: String, isAdmin: Boolean,
- url: Option[String], fileId: Option[String])
+ description: Option[String], url: Option[String], fileId: Option[String])
case class EditUserForm(userName: String, password: Option[String], fullName: String,
- mailAddress: String, isAdmin: Boolean, url: Option[String],
+ mailAddress: String, isAdmin: Boolean, description: Option[String], url: Option[String],
fileId: Option[String], clearImage: Boolean, isRemoved: Boolean)
- case class NewGroupForm(groupName: String, url: Option[String], fileId: Option[String],
+ case class NewGroupForm(groupName: String, description: Option[String], url: Option[String], fileId: Option[String],
members: String)
- case class EditGroupForm(groupName: String, url: Option[String], fileId: Option[String],
+ case class EditGroupForm(groupName: String, description: Option[String], url: Option[String], fileId: Option[String],
members: String, clearImage: Boolean, isRemoved: Boolean)
@@ -110,6 +110,7 @@
"fullName" -> trim(label("Full Name" ,text(required, maxlength(100)))),
"mailAddress" -> trim(label("Mail Address" ,text(required, maxlength(100), uniqueMailAddress()))),
"isAdmin" -> trim(label("User Type" ,boolean())),
+ "description" -> trim(label("bio" ,optional(text()))),
"url" -> trim(label("URL" ,optional(text(maxlength(200))))),
"fileId" -> trim(label("File ID" ,optional(text())))
)(NewUserForm.apply)
@@ -120,6 +121,7 @@
"fullName" -> trim(label("Full Name" ,text(required, maxlength(100)))),
"mailAddress" -> trim(label("Mail Address" ,text(required, maxlength(100), uniqueMailAddress("userName")))),
"isAdmin" -> trim(label("User Type" ,boolean())),
+ "description" -> trim(label("bio" ,optional(text()))),
"url" -> trim(label("URL" ,optional(text(maxlength(200))))),
"fileId" -> trim(label("File ID" ,optional(text()))),
"clearImage" -> trim(label("Clear image" ,boolean())),
@@ -128,6 +130,7 @@
val newGroupForm = mapping(
"groupName" -> trim(label("Group name" ,text(required, maxlength(100), identifier, uniqueUserName, reservedNames))),
+ "description" -> trim(label("Group description", optional(text()))),
"url" -> trim(label("URL" ,optional(text(maxlength(200))))),
"fileId" -> trim(label("File ID" ,optional(text()))),
"members" -> trim(label("Members" ,text(required, members)))
@@ -135,6 +138,7 @@
val editGroupForm = mapping(
"groupName" -> trim(label("Group name" ,text(required, maxlength(100), identifier))),
+ "description" -> trim(label("Group description", optional(text()))),
"url" -> trim(label("URL" ,optional(text(maxlength(200))))),
"fileId" -> trim(label("File ID" ,optional(text()))),
"members" -> trim(label("Members" ,text(required, members))),
@@ -196,7 +200,7 @@
})
post("/admin/users/_newuser", newUserForm)(adminOnly { form =>
- createAccount(form.userName, sha1(form.password), form.fullName, form.mailAddress, form.isAdmin, form.url)
+ createAccount(form.userName, sha1(form.password), form.fullName, form.mailAddress, form.isAdmin, form.description, form.url)
updateImage(form.userName, form.fileId, false)
redirect("/admin/users")
})
@@ -230,6 +234,7 @@
fullName = form.fullName,
mailAddress = form.mailAddress,
isAdmin = form.isAdmin,
+ description = form.description,
url = form.url,
isRemoved = form.isRemoved))
@@ -244,7 +249,7 @@
})
post("/admin/users/_newgroup", newGroupForm)(adminOnly { form =>
- createGroup(form.groupName, form.url)
+ createGroup(form.groupName, form.description, form.url)
updateGroupMembers(form.groupName, form.members.split(",").map {
_.split(":") match {
case Array(userName, isManager) => (userName, isManager.toBoolean)
@@ -267,7 +272,7 @@
}
}.toList){ case (groupName, members) =>
getAccountByUserName(groupName, true).map { account =>
- updateGroup(groupName, form.url, form.isRemoved)
+ updateGroup(groupName, form.url, form.description, form.isRemoved)
if(form.isRemoved){
// Remove from GROUP_MEMBER
diff --git a/src/main/scala/gitbucket/core/model/Account.scala b/src/main/scala/gitbucket/core/model/Account.scala
index cd2190a..aa0d553 100644
--- a/src/main/scala/gitbucket/core/model/Account.scala
+++ b/src/main/scala/gitbucket/core/model/Account.scala
@@ -19,7 +19,8 @@
val image = column[String]("IMAGE")
val groupAccount = column[Boolean]("GROUP_ACCOUNT")
val removed = column[Boolean]("REMOVED")
- def * = (userName, fullName, mailAddress, password, isAdmin, url.?, registeredDate, updatedDate, lastLoginDate.?, image.?, groupAccount, removed) <> (Account.tupled, Account.unapply)
+ val description = column[String]("DESCRIPTION")
+ def * = (userName, fullName, mailAddress, password, isAdmin, url.?, registeredDate, updatedDate, lastLoginDate.?, image.?, groupAccount, removed, description.?) <> (Account.tupled, Account.unapply)
}
}
@@ -35,5 +36,6 @@
lastLoginDate: Option[java.util.Date],
image: Option[String],
isGroupAccount: Boolean,
- isRemoved: Boolean
+ isRemoved: Boolean,
+ description: Option[String]
)
diff --git a/src/main/scala/gitbucket/core/service/AccountService.scala b/src/main/scala/gitbucket/core/service/AccountService.scala
index d583255..0032cea 100644
--- a/src/main/scala/gitbucket/core/service/AccountService.scala
+++ b/src/main/scala/gitbucket/core/service/AccountService.scala
@@ -61,7 +61,7 @@
defaultAuthentication(userName, password)
}
case None => {
- createAccount(ldapUserInfo.userName, "", ldapUserInfo.fullName, ldapUserInfo.mailAddress, false, None)
+ createAccount(ldapUserInfo.userName, "", ldapUserInfo.fullName, ldapUserInfo.mailAddress, false, None, None)
getAccountByUserName(ldapUserInfo.userName)
}
}
@@ -103,7 +103,7 @@
} else false
}
- def createAccount(userName: String, password: String, fullName: String, mailAddress: String, isAdmin: Boolean, url: Option[String])
+ def createAccount(userName: String, password: String, fullName: String, mailAddress: String, isAdmin: Boolean, description: Option[String], url: Option[String])
(implicit s: Session): Unit =
Accounts insert Account(
userName = userName,
@@ -117,12 +117,13 @@
lastLoginDate = None,
image = None,
isGroupAccount = false,
- isRemoved = false)
+ isRemoved = false,
+ description = description)
def updateAccount(account: Account)(implicit s: Session): Unit =
Accounts
.filter { a => a.userName === account.userName.bind }
- .map { a => (a.password, a.fullName, a.mailAddress, a.isAdmin, a.url.?, a.registeredDate, a.updatedDate, a.lastLoginDate.?, a.removed) }
+ .map { a => (a.password, a.fullName, a.mailAddress, a.isAdmin, a.url.?, a.registeredDate, a.updatedDate, a.lastLoginDate.?, a.removed, a.description.?) }
.update (
account.password,
account.fullName,
@@ -132,7 +133,8 @@
account.registeredDate,
currentDate,
account.lastLoginDate,
- account.isRemoved)
+ account.isRemoved,
+ account.description)
def updateAvatarImage(userName: String, image: Option[String])(implicit s: Session): Unit =
Accounts.filter(_.userName === userName.bind).map(_.image.?).update(image)
@@ -140,7 +142,7 @@
def updateLastLoginDate(userName: String)(implicit s: Session): Unit =
Accounts.filter(_.userName === userName.bind).map(_.lastLoginDate).update(currentDate)
- def createGroup(groupName: String, url: Option[String])(implicit s: Session): Unit =
+ def createGroup(groupName: String, description: Option[String], url: Option[String])(implicit s: Session): Unit =
Accounts insert Account(
userName = groupName,
password = "",
@@ -153,10 +155,13 @@
lastLoginDate = None,
image = None,
isGroupAccount = true,
- isRemoved = false)
+ isRemoved = false,
+ description = description)
- def updateGroup(groupName: String, url: Option[String], removed: Boolean)(implicit s: Session): Unit =
- Accounts.filter(_.userName === groupName.bind).map(t => t.url.? -> t.removed).update(url, removed)
+ def updateGroup(groupName: String, description: Option[String], url: Option[String], removed: Boolean)(implicit s: Session): Unit =
+ Accounts.filter(_.userName === groupName.bind)
+ .map(t => (t.url.?, t.description.?, t.removed))
+ .update(url, description, removed)
def updateGroupMembers(groupName: String, members: List[(String, Boolean)])(implicit s: Session): Unit = {
GroupMembers.filter(_.groupName === groupName.bind).delete
diff --git a/src/main/twirl/gitbucket/core/account/edit.scala.html b/src/main/twirl/gitbucket/core/account/edit.scala.html
index 21377e5..757e068 100644
--- a/src/main/twirl/gitbucket/core/account/edit.scala.html
+++ b/src/main/twirl/gitbucket/core/account/edit.scala.html
@@ -37,6 +37,11 @@
+
+
diff --git a/src/main/twirl/gitbucket/core/account/main.scala.html b/src/main/twirl/gitbucket/core/account/main.scala.html
index 8d68399..4cdd5e5 100644
--- a/src/main/twirl/gitbucket/core/account/main.scala.html
+++ b/src/main/twirl/gitbucket/core/account/main.scala.html
@@ -12,6 +12,9 @@
+ @account.description.map{ description =>
+
@description
+ }
@if(account.url.isDefined){
@account.url
diff --git a/src/main/twirl/gitbucket/core/account/register.scala.html b/src/main/twirl/gitbucket/core/account/register.scala.html
index e54b5d8..169102e 100644
--- a/src/main/twirl/gitbucket/core/account/register.scala.html
+++ b/src/main/twirl/gitbucket/core/account/register.scala.html
@@ -33,6 +33,11 @@
+
+
+
diff --git a/src/test/scala/gitbucket/core/service/AccountServiceSpec.scala b/src/test/scala/gitbucket/core/service/AccountServiceSpec.scala
index 7516256..a4730cb 100644
--- a/src/test/scala/gitbucket/core/service/AccountServiceSpec.scala
+++ b/src/test/scala/gitbucket/core/service/AccountServiceSpec.scala
@@ -10,7 +10,7 @@
test("getAllUsers") { withTestDB { implicit session =>
assert(AccountService.getAllUsers() match {
- case List(Account("root", "root", RootMailAddress, _, true, _, _, _, None, None, false, false)) => true
+ case List(Account("root", "root", RootMailAddress, _, true, _, _, _, None, None, false, false, None)) => true
case _ => false
})
}}
@@ -47,12 +47,20 @@
val newAddress = "new mail address"
AccountService.updateAccount(user().copy(mailAddress = newAddress))
assert(user().mailAddress == newAddress)
+
+ val newUrl = Some("http://new.url.example/path")
+ AccountService.updateAccount(user().copy(url = newUrl))
+ assert(user().url == newUrl)
+
+ val newDescription = Some("http://new.url.example/path")
+ AccountService.updateAccount(user().copy(description = newDescription))
+ assert(user().description == newDescription)
}}
test("group") { withTestDB { implicit session =>
val group1 = "group1"
val user1 = "root"
- AccountService.createGroup(group1, None)
+ AccountService.createGroup(group1, None, None)
assert(AccountService.getGroupMembers(group1) == Nil)
assert(AccountService.getGroupsByUserName(user1) == Nil)
@@ -67,5 +75,20 @@
assert(AccountService.getGroupMembers(group1) == Nil)
assert(AccountService.getGroupsByUserName(user1) == Nil)
}}
-}
+ test("createGroup save description") { withTestDB { implicit session =>
+ AccountService.createGroup("some-group", Some("some clever description"), None)
+ val maybeGroup = AccountService.getAccountByUserName("some-group")
+
+ assert(maybeGroup.flatMap(_.description) == Some("some clever description"))
+ }}
+
+ test("updateGroup save description") { withTestDB { implicit session =>
+ AccountService.createGroup("a-group", None, None)
+
+ AccountService.updateGroup("a-group", Some("new description"), None, false)
+
+ val group = AccountService.getAccountByUserName("a-group")
+ assert(group.flatMap(_.description) == Some("new description"))
+ }}
+}
diff --git a/src/test/scala/gitbucket/core/service/ProtectedBranchServiceSpec.scala b/src/test/scala/gitbucket/core/service/ProtectedBranchServiceSpec.scala
index a2c2edf..8265950 100644
--- a/src/test/scala/gitbucket/core/service/ProtectedBranchServiceSpec.scala
+++ b/src/test/scala/gitbucket/core/service/ProtectedBranchServiceSpec.scala
@@ -134,7 +134,7 @@
it("administrator is manager") {
withTestDB { implicit session =>
val x = ProtectedBranchInfo("grp1", "repo1", true, Nil, false)
- x.createGroup("grp1", None)
+ x.createGroup("grp1", None, None)
generateNewAccount("user1")
generateNewAccount("user2")
generateNewAccount("user3")
diff --git a/src/test/scala/gitbucket/core/service/ServiceSpecBase.scala b/src/test/scala/gitbucket/core/service/ServiceSpecBase.scala
index cfb3a3e..037a098 100644
--- a/src/test/scala/gitbucket/core/service/ServiceSpecBase.scala
+++ b/src/test/scala/gitbucket/core/service/ServiceSpecBase.scala
@@ -37,7 +37,7 @@
}
def generateNewAccount(name:String)(implicit s:Session):Account = {
- AccountService.createAccount(name, name, name, s"${name}@example.com", false, None)
+ AccountService.createAccount(name, name, name, s"${name}@example.com", false, None, None)
user(name)
}
diff --git a/src/test/scala/gitbucket/core/view/AvatarImageProviderSpec.scala b/src/test/scala/gitbucket/core/view/AvatarImageProviderSpec.scala
index d30eb7f..176807b 100644
--- a/src/test/scala/gitbucket/core/view/AvatarImageProviderSpec.scala
+++ b/src/test/scala/gitbucket/core/view/AvatarImageProviderSpec.scala
@@ -94,7 +94,8 @@
lastLoginDate = None,
image = image,
isGroupAccount = false,
- isRemoved = false)
+ isRemoved = false,
+ description = None)
private def createSystemSettings(useGravatar: Boolean) =
SystemSettings(