Merge branch 'master' into improve-pullreq-comments

This commit is contained in:
Naoki Takezoe
2018-04-27 08:35:59 +09:00
12 changed files with 189 additions and 31 deletions

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<changeSet>
<createTable tableName="ACCOUNT_EXTRA_MAIL_ADDRESS">
<column name="USER_NAME" type="varchar(100)" nullable="false"/>
<column name="EXTRA_MAIL_ADDRESS" type="varchar(100)" nullable="false"/>
</createTable>
<addPrimaryKey constraintName="IDX_ACCOUNT_EXTRA_MAIL_ADDRESS_PK" tableName="ACCOUNT_EXTRA_MAIL_ADDRESS" columnNames="USER_NAME, EXTRA_MAIL_ADDRESS"/>
<addUniqueConstraint constraintName="IDX_ACCOUNT_EXTRA_MAIL_ADDRESS_1" tableName="ACCOUNT_EXTRA_MAIL_ADDRESS" columnNames="EXTRA_MAIL_ADDRESS"/>
</changeSet>

View File

@@ -51,5 +51,6 @@ object GitBucketCoreModule
new Version("4.21.2"),
new Version("4.22.0", new LiquibaseMigration("update/gitbucket-core_4.22.xml")),
new Version("4.23.0", new LiquibaseMigration("update/gitbucket-core_4.23.xml")),
new Version("4.23.1")
new Version("4.23.1"),
new Version("4.24.0", new LiquibaseMigration("update/gitbucket-core_4.24.xml"))
)

View File

@@ -2,7 +2,7 @@ package gitbucket.core.controller
import gitbucket.core.account.html
import gitbucket.core.helper
import gitbucket.core.model.{AccountWebHook, GroupMember, RepositoryWebHook, Role, WebHook, WebHookContentType}
import gitbucket.core.model._
import gitbucket.core.plugin.PluginRegistry
import gitbucket.core.service._
import gitbucket.core.service.WebHookService._
@@ -54,6 +54,7 @@ trait AccountControllerBase extends AccountManagementControllerBase {
password: String,
fullName: String,
mailAddress: String,
extraMailAddresses: List[String],
description: Option[String],
url: Option[String],
fileId: Option[String]
@@ -63,6 +64,7 @@ trait AccountControllerBase extends AccountManagementControllerBase {
password: Option[String],
fullName: String,
mailAddress: String,
extraMailAddresses: List[String],
description: Option[String],
url: Option[String],
fileId: Option[String],
@@ -78,6 +80,9 @@ trait AccountControllerBase extends AccountManagementControllerBase {
"password" -> trim(label("Password", text(required, maxlength(20), password))),
"fullName" -> trim(label("Full Name", text(required, maxlength(100)))),
"mailAddress" -> trim(label("Mail Address", text(required, maxlength(100), uniqueMailAddress()))),
"extraMailAddresses" -> list(
trim(label("Additional Mail Address", text(maxlength(100), uniqueExtraMailAddress())))
),
"description" -> trim(label("bio", optional(text()))),
"url" -> trim(label("URL", optional(text(maxlength(200))))),
"fileId" -> trim(label("File ID", optional(text())))
@@ -87,6 +92,9 @@ trait AccountControllerBase extends AccountManagementControllerBase {
"password" -> trim(label("Password", optional(text(maxlength(20), password)))),
"fullName" -> trim(label("Full Name", text(required, maxlength(100)))),
"mailAddress" -> trim(label("Mail Address", text(required, maxlength(100), uniqueMailAddress("userName")))),
"extraMailAddresses" -> list(
trim(label("Additional Mail Address", text(maxlength(100), uniqueExtraMailAddress("userName"))))
),
"description" -> trim(label("bio", optional(text()))),
"url" -> trim(label("URL", optional(text(maxlength(200))))),
"fileId" -> trim(label("File ID", optional(text()))),
@@ -295,26 +303,29 @@ trait AccountControllerBase extends AccountManagementControllerBase {
get("/:userName/_edit")(oneselfOnly {
val userName = params("userName")
getAccountByUserName(userName).map { x =>
html.edit(x, flash.get("info"), flash.get("error"))
val extraMails = getAccountExtraMailAddresses(userName)
html.edit(x, extraMails, flash.get("info"), flash.get("error"))
} getOrElse NotFound()
})
post("/:userName/_edit", editForm)(oneselfOnly { form =>
val userName = params("userName")
getAccountByUserName(userName).map { account =>
updateAccount(
account.copy(
password = form.password.map(sha1).getOrElse(account.password),
fullName = form.fullName,
mailAddress = form.mailAddress,
description = form.description,
url = form.url
getAccountByUserName(userName).map {
account =>
updateAccount(
account.copy(
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)
flash += "info" -> "Account information has been updated."
redirect(s"/${userName}/_edit")
updateImage(userName, form.fileId, form.clearImage)
updateAccountExtraMailAddresses(userName, form.extraMailAddresses.filter(_ != ""))
flash += "info" -> "Account information has been updated."
redirect(s"/${userName}/_edit")
} getOrElse NotFound()
})
@@ -552,6 +563,7 @@ trait AccountControllerBase extends AccountManagementControllerBase {
form.url
)
updateImage(form.userName, form.fileId, false)
updateAccountExtraMailAddresses(form.userName, form.extraMailAddresses)
redirect("/signin")
} else NotFound()
}

View File

@@ -359,13 +359,42 @@ trait AccountManagementControllerBase extends ControllerBase {
params: Map[String, Seq[String]],
messages: Messages
): Option[String] = {
getAccountByMailAddress(value, true)
.filter { x =>
if (paramName.isEmpty) true else Some(x.userName) != params.optionValue(paramName)
}
.map { _ =>
"Mail address is already registered."
}
val extraMailAddresses = params.filterKeys(k => k.startsWith("extraMailAddresses"))
if (extraMailAddresses.exists {
case (k, v) =>
v.contains(value)
}) {
Some("These mail addresses are duplicated.")
} else {
getAccountByMailAddress(value, true)
.collect {
case x if paramName.isEmpty || Some(x.userName) != params.optionValue(paramName) =>
"Mail address is already registered."
}
}
}
}
protected def uniqueExtraMailAddress(paramName: String = ""): Constraint = new Constraint() {
override def validate(
name: String,
value: String,
params: Map[String, Seq[String]],
messages: Messages
): Option[String] = {
val extraMailAddresses = params.filterKeys(k => k.startsWith("extraMailAddresses"))
if (Some(value) == params.optionValue("mailAddress") || extraMailAddresses.count {
case (k, v) =>
v.contains(value)
} > 1) {
Some("These mail addresses are duplicated.")
} else {
getAccountByMailAddress(value, true)
.collect {
case x if paramName.isEmpty || Some(x.userName) != params.optionValue(paramName) =>
"Mail address is already registered."
}
}
}
}

View File

@@ -124,6 +124,7 @@ trait SystemSettingsControllerBase extends AccountManagementControllerBase {
password: String,
fullName: String,
mailAddress: String,
extraMailAddresses: List[String],
isAdmin: Boolean,
description: Option[String],
url: Option[String],
@@ -135,6 +136,7 @@ trait SystemSettingsControllerBase extends AccountManagementControllerBase {
password: Option[String],
fullName: String,
mailAddress: String,
extraMailAddresses: List[String],
isAdmin: Boolean,
description: Option[String],
url: Option[String],
@@ -166,6 +168,9 @@ trait SystemSettingsControllerBase extends AccountManagementControllerBase {
"password" -> trim(label("Password", text(required, maxlength(20), password))),
"fullName" -> trim(label("Full Name", text(required, maxlength(100)))),
"mailAddress" -> trim(label("Mail Address", text(required, maxlength(100), uniqueMailAddress()))),
"extraMailAddresses" -> list(
trim(label("Additional Mail Address", text(maxlength(100), uniqueExtraMailAddress("userName"))))
),
"isAdmin" -> trim(label("User Type", boolean())),
"description" -> trim(label("bio", optional(text()))),
"url" -> trim(label("URL", optional(text(maxlength(200))))),
@@ -177,6 +182,9 @@ trait SystemSettingsControllerBase extends AccountManagementControllerBase {
"password" -> trim(label("Password", optional(text(maxlength(20), password)))),
"fullName" -> trim(label("Full Name", text(required, maxlength(100)))),
"mailAddress" -> trim(label("Mail Address", text(required, maxlength(100), uniqueMailAddress("userName")))),
"extraMailAddresses" -> list(
trim(label("Additional Mail Address", text(maxlength(100), uniqueExtraMailAddress("userName"))))
),
"isAdmin" -> trim(label("User Type", boolean())),
"description" -> trim(label("bio", optional(text()))),
"url" -> trim(label("URL", optional(text(maxlength(200))))),
@@ -400,7 +408,7 @@ trait SystemSettingsControllerBase extends AccountManagementControllerBase {
})
get("/admin/users/_newuser")(adminOnly {
html.user(None)
html.user(None, Nil)
})
post("/admin/users/_newuser", newUserForm)(adminOnly { form =>
@@ -414,12 +422,14 @@ trait SystemSettingsControllerBase extends AccountManagementControllerBase {
form.url
)
updateImage(form.userName, form.fileId, false)
updateAccountExtraMailAddresses(form.userName, form.extraMailAddresses.filter(_ != ""))
redirect("/admin/users")
})
get("/admin/users/:userName/_edituser")(adminOnly {
val userName = params("userName")
html.user(getAccountByUserName(userName, true), flash.get("error"))
val extraMails = getAccountExtraMailAddresses(userName)
html.user(getAccountByUserName(userName, true), extraMails, flash.get("error"))
})
post("/admin/users/:name/_edituser", editUserForm)(adminOnly { form =>
@@ -455,6 +465,7 @@ trait SystemSettingsControllerBase extends AccountManagementControllerBase {
)
updateImage(userName, form.fileId, form.clearImage)
updateAccountExtraMailAddresses(userName, form.extraMailAddresses.filter(_ != ""))
// call hooks
if (form.isRemoved) PluginRegistry().getAccountHooks.foreach(_.deleted(userName))

View File

@@ -0,0 +1,19 @@
package gitbucket.core.model
trait AccountExtraMailAddressComponent { self: Profile =>
import profile.api._
lazy val AccountExtraMailAddresses = TableQuery[AccountExtraMailAddresses]
class AccountExtraMailAddresses(tag: Tag) extends Table[AccountExtraMailAddress](tag, "ACCOUNT_EXTRA_MAIL_ADDRESS") {
val userName = column[String]("USER_NAME", O PrimaryKey)
val extraMailAddress = column[String]("EXTRA_MAIL_ADDRESS", O PrimaryKey)
def * =
(userName, extraMailAddress) <> (AccountExtraMailAddress.tupled, AccountExtraMailAddress.unapply)
}
}
case class AccountExtraMailAddress(
userName: String,
extraMailAddress: String
)

View File

@@ -68,5 +68,6 @@ trait CoreProfile
with DeployKeyComponent
with ReleaseTagComponent
with ReleaseAssetComponent
with AccountExtraMailAddressComponent
object Profile extends CoreProfile

View File

@@ -1,11 +1,11 @@
package gitbucket.core.service
import org.slf4j.LoggerFactory
import gitbucket.core.model.{GroupMember, Account}
import gitbucket.core.model.{Account, AccountExtraMailAddress, GroupMember}
import gitbucket.core.model.Profile._
import gitbucket.core.model.Profile.profile.blockingApi._
import gitbucket.core.model.Profile.dateColumnType
import gitbucket.core.util.{StringUtil, LDAPUtil}
import gitbucket.core.util.{LDAPUtil, StringUtil}
import StringUtil._
import gitbucket.core.service.SystemSettingsService.SystemSettings
@@ -121,9 +121,16 @@ trait AccountService {
def getAccountByMailAddress(mailAddress: String, includeRemoved: Boolean = false)(
implicit s: Session
): Option[Account] =
Accounts filter (
t => (t.mailAddress.toLowerCase === mailAddress.toLowerCase.bind) && (t.removed === false.bind, !includeRemoved)
) firstOption
(Accounts joinLeft AccountExtraMailAddresses on { case (a, e) => a.userName === e.userName })
.filter {
case (a, x) =>
((a.mailAddress.toLowerCase === mailAddress.toLowerCase.bind) ||
(x.map { e =>
e.extraMailAddress.toLowerCase === mailAddress.toLowerCase.bind
}
.getOrElse(false.bind))) && (a.removed === false.bind, !includeRemoved)
}
.map { case (a, e) => a } firstOption
def getAllUsers(includeRemoved: Boolean = true, includeGroups: Boolean = true)(implicit s: Session): List[Account] = {
Accounts filter { t =>
@@ -199,6 +206,15 @@ trait AccountService {
def updateAvatarImage(userName: String, image: Option[String])(implicit s: Session): Unit =
Accounts.filter(_.userName === userName.bind).map(_.image.?).update(image)
def getAccountExtraMailAddresses(userName: String)(implicit s: Session): List[String] = {
AccountExtraMailAddresses.filter(_.userName === userName.bind).map(_.extraMailAddress) list
}
def updateAccountExtraMailAddresses(userName: String, mails: List[String])(implicit s: Session): Unit = {
AccountExtraMailAddresses.filter(_.userName === userName.bind).delete
mails.map(AccountExtraMailAddresses insert AccountExtraMailAddress(userName, _))
}
def updateLastLoginDate(userName: String)(implicit s: Session): Unit =
Accounts.filter(_.userName === userName.bind).map(_.lastLoginDate).update(currentDate)

View File

@@ -1,4 +1,4 @@
@(account: gitbucket.core.model.Account, info: Option[Any], error: Option[Any])(implicit context: gitbucket.core.controller.Context)
@(account: gitbucket.core.model.Account, extraMailAddresses: List[String], info: Option[Any], error: Option[Any])(implicit context: gitbucket.core.controller.Context)
@import gitbucket.core.util.LDAPUtil
@import gitbucket.core.view.helpers
@gitbucket.core.html.main("Edit your profile"){
@@ -31,6 +31,13 @@
<input type="text" name="mailAddress" id="mailAddress" class="form-control" value="@if(!LDAPUtil.isDummyMailAddress(account)){@account.mailAddress}"/>
<span id="error-mailAddress" class="error"></span>
</fieldset>
<fieldset class="form-group" id="extraMailAddresses">
<span class="strong">Additional Mail Address:</span>
@extraMailAddresses.zipWithIndex.map { case (mail, idx) =>
<input type="text" name="extraMailAddresses[@idx]" id="extraMailAddresses[@idx]" class="form-control extraMailAddress" value="@mail"/>
<span id="error-extraMailAddresses_@idx" class="error"></span>
}
</fieldset>
<fieldset class="form-group">
<label for="url" class="strong">URL (optional):</label>
<input type="text" name="url" id="url" class="form-control" value="@account.url"/>
@@ -62,6 +69,8 @@
}
<script>
$(function(){
addExtraMailAddress();
$('#extraMailAddresses').on('change', '.extraMailAddress', checkExtraMailAddress);
$('#save').click(function(){
if($('#password').val() != ''){
return confirm('Are you sure you want to change password?');

View File

@@ -28,6 +28,9 @@
<input type="text" name="mailAddress" id="mailAddress" class="form-control" value=""/>
<span id="error-mailAddress" class="error"></span>
</fieldset>
<div id="extraMailAddresses">
<span class="strong">Additional Mail Address:</span>
</div>
<fieldset>
<label for="url" class="strong">URL (optional):</label>
<input type="text" name="url" id="url" class="form-control" value=""/>
@@ -52,4 +55,10 @@
</form>
</div>
</div>
<script>
$(function() {
addExtraMailAddress();
$('#extraMailAddresses').on('change', '.extraMailAddress', checkExtraMailAddress);
});
</script>
}

View File

@@ -1,4 +1,4 @@
@(account: Option[gitbucket.core.model.Account], error: Option[Any] = None)(implicit context: gitbucket.core.controller.Context)
@(account: Option[gitbucket.core.model.Account], extraMailAddresses: List[String], error: Option[Any] = None)(implicit context: gitbucket.core.controller.Context)
@gitbucket.core.html.main(if(account.isEmpty) "New user" else "Update user"){
@gitbucket.core.admin.html.menu("users"){
@gitbucket.core.helper.html.error(error)
@@ -50,6 +50,13 @@
</div>
<input type="text" name="mailAddress" id="mailAddress" class="form-control" value="@account.map(_.mailAddress)"/>
</fieldset>
<fieldset class="form-group" id="extraMailAddresses">
<span class="strong">Additional Mail Address:</span>
@extraMailAddresses.zipWithIndex.map { case (mail, idx) =>
<input type="text" name="extraMailAddresses[@idx]" id="extraMailAddresses[@idx]" class="form-control extraMailAddress" value="@mail"/>
<span id="error-extraMailAddresses_@idx" class="error"></span>
}
</fieldset>
<fieldset class="form-group">
<label class="strong">User Type:</label>
<label class="radio" for="userType_Normal">
@@ -94,6 +101,8 @@
}
<script>
$(function(){
addExtraMailAddress();
$('#extraMailAddresses').on('change', '.extraMailAddress', checkExtraMailAddress);
$('#update').click(function(){
if($('#password').val() != ''){
return confirm('Are you sure you want to change password of this user?');

View File

@@ -694,3 +694,35 @@ var imageDiff ={
}
};
/**
* function for account extra mail address form control.
*/
function addExtraMailAddress() {
var fieldset = $('#extraMailAddresses');
var count = $('.extraMailAddress').length;
var html = '<input type="text" name="extraMailAddresses[' + count + ']" id="extraMailAddresses[' + count + ']" class="form-control extraMailAddress"/>'
+ '<span id="error-extraMailAddresses_' + count + '" class="error"></span>';
fieldset.append(html);
}
/**
* function for check account extra mail address form control.
*/
function checkExtraMailAddress(){
if ($(this).val() != ""){
var needAdd = true;
$('.extraMailAddress').each(function(){
if($(this).val() == ""){
needAdd = false;
return false;
}
return true;
});
if (needAdd){
addExtraMailAddress();
}
}
else {
$(this).remove();
}
}