mirror of
https://github.com/gitbucket/gitbucket.git
synced 2025-11-05 04:56:02 +01:00
Merge branch 'master' into improve-pullreq-comments
This commit is contained in:
10
src/main/resources/update/gitbucket-core_4.24.xml
Normal file
10
src/main/resources/update/gitbucket-core_4.24.xml
Normal 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>
|
||||
@@ -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"))
|
||||
)
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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
|
||||
)
|
||||
@@ -68,5 +68,6 @@ trait CoreProfile
|
||||
with DeployKeyComponent
|
||||
with ReleaseTagComponent
|
||||
with ReleaseAssetComponent
|
||||
with AccountExtraMailAddressComponent
|
||||
|
||||
object Profile extends CoreProfile
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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?');
|
||||
|
||||
@@ -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>
|
||||
}
|
||||
|
||||
@@ -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?');
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user