Use-defined CSS (#2458)

This commit is contained in:
Naoki Takezoe
2020-06-08 15:50:37 +09:00
committed by GitHub
parent eebabf9b08
commit 2a1edeaca3
6 changed files with 55 additions and 27 deletions

View File

@@ -46,7 +46,7 @@ trait SystemSettingsControllerBase extends AccountManagementControllerBase {
"ssh" -> mapping(
"enabled" -> trim(label("SSH access", boolean())),
"host" -> trim(label("SSH host", optional(text()))),
"port" -> trim(label("SSH port", optional(number()))),
"port" -> trim(label("SSH port", optional(number())))
)(Ssh.apply),
"useSMTP" -> trim(label("SMTP", boolean())),
"smtp" -> optionalIfNotChecked(
@@ -91,6 +91,7 @@ trait SystemSettingsControllerBase extends AccountManagementControllerBase {
)(OIDC.apply)
),
"skinName" -> trim(label("AdminLTE skin name", text(required))),
"userDefinedCss" -> trim(label("User-defined CSS", optional(text()))),
"showMailAddress" -> trim(label("Show mail address", boolean())),
"webhook" -> mapping(
"blockPrivateAddress" -> trim(label("Block private address", boolean())),
@@ -536,24 +537,26 @@ trait SystemSettingsControllerBase extends AccountManagementControllerBase {
}
}
private def members: Constraint = new Constraint() {
override def validate(name: String, value: String, messages: Messages): Option[String] = {
if (value.split(",").exists {
_.split(":") match { case Array(userName, isManager) => isManager.toBoolean }
}) None
else Some("Must select one manager at least.")
}
}
protected def disableByNotYourself(paramName: String): Constraint = new Constraint() {
override def validate(name: String, value: String, messages: Messages): Option[String] = {
params.get(paramName).flatMap { userName =>
if (userName == context.loginAccount.get.userName && params.get("removed") == Some("true"))
Some("You can't disable your account yourself")
else
None
private def members: Constraint =
new Constraint() {
override def validate(name: String, value: String, messages: Messages): Option[String] = {
if (value.split(",").exists {
_.split(":") match { case Array(userName, isManager) => isManager.toBoolean }
}) None
else Some("Must select one manager at least.")
}
}
protected def disableByNotYourself(paramName: String): Constraint =
new Constraint() {
override def validate(name: String, value: String, messages: Messages): Option[String] = {
params.get(paramName).flatMap { userName =>
if (userName == context.loginAccount.get.userName && params.get("removed") == Some("true"))
Some("You can't disable your account yourself")
else
None
}
}
}
}
}

View File

@@ -70,6 +70,7 @@ trait SystemSettingsService {
}
}
props.setProperty(SkinName, settings.skinName.toString)
settings.userDefinedCss.foreach(x => props.setProperty(UserDefinedCss, x))
props.setProperty(ShowMailAddress, settings.showMailAddress.toString)
props.setProperty(WebHookBlockPrivateAddress, settings.webHook.blockPrivateAddress.toString)
props.setProperty(WebHookWhitelist, settings.webHook.whitelist.mkString("\n"))
@@ -106,7 +107,11 @@ trait SystemSettingsService {
getOptionValue[String](props, SshHost, None).map(_.trim),
getOptionValue(props, SshPort, Some(DefaultSshPort))
),
getValue(props, UseSMTP, getValue(props, Notification, false)), // handle migration scenario from only notification to useSMTP
getValue(
props,
UseSMTP,
getValue(props, Notification, false)
), // handle migration scenario from only notification to useSMTP
if (getValue(props, UseSMTP, getValue(props, Notification, false))) {
Some(
Smtp(
@@ -154,6 +159,7 @@ trait SystemSettingsService {
None
},
getValue(props, SkinName, "skin-blue"),
getOptionValue(props, UserDefinedCss, None),
getValue(props, ShowMailAddress, false),
WebHook(getValue(props, WebHookBlockPrivateAddress, false), getSeqValue(props, WebHookWhitelist, "")),
Upload(
@@ -191,6 +197,7 @@ object SystemSettingsService {
oidcAuthentication: Boolean,
oidc: Option[OIDC],
skinName: String,
userDefinedCss: Option[String],
showMailAddress: Boolean,
webHook: WebHook,
upload: Upload
@@ -212,10 +219,11 @@ object SystemSettingsService {
.fold(base)(_ + base.dropWhile(_ != ':'))
}
def sshAddress: Option[SshAddress] = ssh.sshHost.collect {
case host if ssh.enabled =>
SshAddress(host, ssh.sshPort.getOrElse(DefaultSshPort), "git")
}
def sshAddress: Option[SshAddress] =
ssh.sshHost.collect {
case host if ssh.enabled =>
SshAddress(host, ssh.sshPort.getOrElse(DefaultSshPort), "git")
}
}
case class Ssh(
@@ -265,7 +273,7 @@ object SystemSettingsService {
host: String,
port: Int,
user: Option[String],
password: Option[String],
password: Option[String]
)
case class SshAddress(host: String, port: Int, genericUser: String)
@@ -318,6 +326,7 @@ object SystemSettingsService {
private val OidcClientSecret = "oidc.client_secret"
private val OidcJwsAlgorithm = "oidc.jws_algorithm"
private val SkinName = "skinName"
private val UserDefinedCss = "userDefinedCss"
private val ShowMailAddress = "showMailAddress"
private val WebHookBlockPrivateAddress = "webhook.block_private_address"
private val WebHookWhitelist = "webhook.whitelist"

View File

@@ -94,6 +94,14 @@
</div>
</div>
<!--====================================================================-->
<!-- User-defined CSS -->
<!--====================================================================-->
<hr>
<label><span class="strong">User-defined CSS</span></label>
<fieldset>
<textarea name="userDefinedCss" class="form-control" style="height: 100px;">@context.settings.userDefinedCss</textarea>
</fieldset>
<!--====================================================================-->
<!-- Account registration -->
<!--====================================================================-->
<hr>

View File

@@ -55,6 +55,9 @@
<meta name="go-import" content="@context.baseUrl.replaceFirst("^https?://", "")/@repository.owner/@repository.name git @repository.httpUrl" />
}
<script src="@helpers.assets("/vendors/AdminLTE-2.4.2/js/adminlte.min.js")" type="text/javascript"></script>
@context.settings.userDefinedCss.map { css =>
<style type="text/css">@css</style>
}
</head>
<body class="@context.settings.skinName page-load @if(body.toString.contains("menu-item-hover")){sidebar-mini} @if(context.sidebarCollapse){sidebar-collapse}">
<div class="wrapper">

View File

@@ -52,6 +52,7 @@ trait ServiceSpecBase extends MockitoSugar {
oidcAuthentication = false,
oidc = None,
skinName = "skin-blue",
userDefinedCss = None,
showMailAddress = false,
webHook = SystemSettingsService.WebHook(
blockPrivateAddress = false,
@@ -114,7 +115,8 @@ trait ServiceSpecBase extends MockitoSugar {
}
def generateNewIssue(userName: String, repositoryName: String, loginUser: String = "root")(
implicit s: Session
implicit
s: Session
): Int = {
dummyService.insertIssue(
owner = userName,
@@ -130,7 +132,8 @@ trait ServiceSpecBase extends MockitoSugar {
}
def generateNewPullRequest(base: String, request: String, loginUser: String)(
implicit s: Session
implicit
s: Session
): (Issue, PullRequest) = {
implicit val context = Context(createSystemSettings(), None, this.request)
val Array(baseUserName, baseRepositoryName, baesBranch) = base.split("/")

View File

@@ -138,6 +138,7 @@ class AvatarImageProviderSpec extends FunSpec with MockitoSugar {
oidcAuthentication = false,
oidc = None,
skinName = "skin-blue",
userDefinedCss = None,
showMailAddress = false,
webHook = WebHook(
blockPrivateAddress = false,
@@ -157,7 +158,8 @@ class AvatarImageProviderSpec extends FunSpec with MockitoSugar {
class AvatarImageProviderImpl(account: Option[Account]) extends AvatarImageProvider with RequestCache {
def toHtml(userName: String, size: Int, mailAddress: String = "", tooltip: Boolean = false)(
implicit context: Context
implicit
context: Context
): Html = getAvatarImageHtml(userName, size, mailAddress, tooltip)
override def getAccountByMailAddress(mailAddress: String)(implicit context: Context): Option[Account] = account