Limit the visible repositories in the sidebar. (#2421)

This commit is contained in:
Kasan
2020-01-18 10:34:43 +09:00
committed by Naoki Takezoe
parent 564e95d36e
commit 59d7a672b3
8 changed files with 75 additions and 8 deletions

View File

@@ -27,7 +27,12 @@ trait DashboardControllerBase extends ControllerBase {
self: IssuesService with PullRequestService with RepositoryService with AccountService with UsersAuthenticator => self: IssuesService with PullRequestService with RepositoryService with AccountService with UsersAuthenticator =>
get("/dashboard/repos")(usersOnly { get("/dashboard/repos")(usersOnly {
val repos = getVisibleRepositories(context.loginAccount, withoutPhysicalInfo = true) val repos = getVisibleRepositories(
context.loginAccount,
None,
withoutPhysicalInfo = true,
limit = context.settings.limitVisibleRepositories
)
html.repos(getGroupNames(context.loginAccount.get.userName), repos, repos) html.repos(getGroupNames(context.loginAccount.get.userName), repos, repos)
}) })
@@ -93,7 +98,12 @@ trait DashboardControllerBase extends ControllerBase {
}, },
filter, filter,
getGroupNames(userName), getGroupNames(userName),
getVisibleRepositories(context.loginAccount, withoutPhysicalInfo = true) getVisibleRepositories(
context.loginAccount,
None,
withoutPhysicalInfo = true,
limit = context.settings.limitVisibleRepositories
)
) )
} }
@@ -118,7 +128,12 @@ trait DashboardControllerBase extends ControllerBase {
}, },
filter, filter,
getGroupNames(userName), getGroupNames(userName),
getVisibleRepositories(context.loginAccount, withoutPhysicalInfo = true) getVisibleRepositories(
context.loginAccount,
None,
withoutPhysicalInfo = true,
limit = context.settings.limitVisibleRepositories
)
) )
} }

View File

@@ -65,7 +65,12 @@ trait IndexControllerBase extends ControllerBase {
val visibleOwnerSet: Set[String] = Set(account.userName) ++ getGroupsByUserName(account.userName) val visibleOwnerSet: Set[String] = Set(account.userName) ++ getGroupsByUserName(account.userName)
gitbucket.core.html.index( gitbucket.core.html.index(
getRecentActivitiesByOwners(visibleOwnerSet), getRecentActivitiesByOwners(visibleOwnerSet),
getVisibleRepositories(Some(account), withoutPhysicalInfo = true), getVisibleRepositories(
Some(account),
None,
withoutPhysicalInfo = true,
limit = context.settings.limitVisibleRepositories
),
showBannerToCreatePersonalAccessToken = hasAccountFederation(account.userName) && !hasAccessToken( showBannerToCreatePersonalAccessToken = hasAccountFederation(account.userName) && !hasAccessToken(
account.userName account.userName
) )
@@ -279,7 +284,12 @@ trait IndexControllerBase extends ControllerBase {
get("/search") { get("/search") {
val query = params.getOrElse("query", "").trim.toLowerCase val query = params.getOrElse("query", "").trim.toLowerCase
val visibleRepositories = val visibleRepositories =
getVisibleRepositories(context.loginAccount, repositoryUserName = None, withoutPhysicalInfo = true) getVisibleRepositories(
context.loginAccount,
None,
withoutPhysicalInfo = true,
limit = context.settings.limitVisibleRepositories
)
val repositories = visibleRepositories.filter { repository => val repositories = visibleRepositories.filter { repository =>
repository.name.toLowerCase.indexOf(query) >= 0 || repository.owner.toLowerCase.indexOf(query) >= 0 repository.name.toLowerCase.indexOf(query) >= 0 || repository.owner.toLowerCase.indexOf(query) >= 0
} }

View File

@@ -42,6 +42,7 @@ trait SystemSettingsControllerBase extends AccountManagementControllerBase {
"gravatar" -> trim(label("Gravatar", boolean())), "gravatar" -> trim(label("Gravatar", boolean())),
"notification" -> trim(label("Notification", boolean())), "notification" -> trim(label("Notification", boolean())),
"activityLogLimit" -> trim(label("Limit of activity logs", optional(number()))), "activityLogLimit" -> trim(label("Limit of activity logs", optional(number()))),
"limitVisibleRepositories" -> trim(label("limitVisibleRepositories", boolean())),
"ssh" -> mapping( "ssh" -> mapping(
"enabled" -> trim(label("SSH access", boolean())), "enabled" -> trim(label("SSH access", boolean())),
"host" -> trim(label("SSH host", optional(text()))), "host" -> trim(label("SSH host", optional(text()))),

View File

@@ -459,6 +459,7 @@ trait RepositoryService {
/** /**
* Returns the list of visible repositories for the specified user. * Returns the list of visible repositories for the specified user.
* If repositoryUserName is given then filters results by repository owner. * If repositoryUserName is given then filters results by repository owner.
* This function is for plugin compatibility.
* *
* @param loginAccount the logged in account * @param loginAccount the logged in account
* @param repositoryUserName the repository owner (if None then returns all repositories which are visible for logged in user) * @param repositoryUserName the repository owner (if None then returns all repositories which are visible for logged in user)
@@ -470,23 +471,42 @@ trait RepositoryService {
loginAccount: Option[Account], loginAccount: Option[Account],
repositoryUserName: Option[String] = None, repositoryUserName: Option[String] = None,
withoutPhysicalInfo: Boolean = false withoutPhysicalInfo: Boolean = false
)(implicit s: Session): List[RepositoryInfo] =
getVisibleRepositories(loginAccount, repositoryUserName, withoutPhysicalInfo, false)
/**
* Returns the list of visible repositories for the specified user.
* If repositoryUserName is given then filters results by repository owner.
*
* @param loginAccount the logged in account
* @param repositoryUserName the repository owner (if None then returns all repositories which are visible for logged in user)
* @param withoutPhysicalInfo if true then the result does not include physical repository information such as commit count,
* branches and tags
* @param limit if true then result will include only repositories associated with the login account.
* @return the repository information which is sorted in descending order of lastActivityDate.
*/
def getVisibleRepositories(
loginAccount: Option[Account],
repositoryUserName: Option[String],
withoutPhysicalInfo: Boolean,
limit: Boolean
)(implicit s: Session): List[RepositoryInfo] = { )(implicit s: Session): List[RepositoryInfo] = {
(loginAccount match { (loginAccount match {
// for Administrators // for Administrators
case Some(x) if (x.isAdmin) => case Some(x) if (x.isAdmin && !limit) =>
Repositories Repositories
.join(Accounts) .join(Accounts)
.on(_.userName === _.userName) .on(_.userName === _.userName)
.filter { case (t1, t2) => t2.removed === false.bind } .filter { case (t1, t2) => t2.removed === false.bind }
.map { case (t1, t2) => t1 } .map { case (t1, t2) => t1 }
// for Normal Users // for Normal Users
case Some(x) if (!x.isAdmin) => case Some(x) if (!x.isAdmin || limit) =>
Repositories Repositories
.join(Accounts) .join(Accounts)
.on(_.userName === _.userName) .on(_.userName === _.userName)
.filter { .filter {
case (t1, t2) => case (t1, t2) =>
(t2.removed === false.bind) && ((t1.isPrivate === false.bind) || (t1.userName === x.userName) || (t2.removed === false.bind) && ((t1.isPrivate === false.bind && !limit.bind) || (t1.userName === x.userName) ||
(t1.userName in GroupMembers.filter(_.userName === x.userName.bind).map(_.groupName)) || (t1.userName in GroupMembers.filter(_.userName === x.userName.bind).map(_.groupName)) ||
(Collaborators.filter { t3 => (Collaborators.filter { t3 =>
t3.byRepository(t1.userName, t1.repositoryName) && t3.byRepository(t1.userName, t1.repositoryName) &&

View File

@@ -24,6 +24,7 @@ trait SystemSettingsService {
props.setProperty(Gravatar, settings.gravatar.toString) props.setProperty(Gravatar, settings.gravatar.toString)
props.setProperty(Notification, settings.notification.toString) props.setProperty(Notification, settings.notification.toString)
settings.activityLogLimit.foreach(x => props.setProperty(ActivityLogLimit, x.toString)) settings.activityLogLimit.foreach(x => props.setProperty(ActivityLogLimit, x.toString))
props.setProperty(LimitVisibleRepositories, settings.limitVisibleRepositories.toString)
props.setProperty(SshEnabled, settings.ssh.enabled.toString) props.setProperty(SshEnabled, settings.ssh.enabled.toString)
settings.ssh.sshHost.foreach(x => props.setProperty(SshHost, x.trim)) settings.ssh.sshHost.foreach(x => props.setProperty(SshHost, x.trim))
settings.ssh.sshPort.foreach(x => props.setProperty(SshPort, x.toString)) settings.ssh.sshPort.foreach(x => props.setProperty(SshPort, x.toString))
@@ -99,6 +100,7 @@ trait SystemSettingsService {
getValue(props, Gravatar, false), getValue(props, Gravatar, false),
getValue(props, Notification, false), getValue(props, Notification, false),
getOptionValue[Int](props, ActivityLogLimit, None), getOptionValue[Int](props, ActivityLogLimit, None),
getValue(props, LimitVisibleRepositories, false),
Ssh( Ssh(
getValue(props, SshEnabled, false), getValue(props, SshEnabled, false),
getOptionValue[String](props, SshHost, None).map(_.trim), getOptionValue[String](props, SshHost, None).map(_.trim),
@@ -180,6 +182,7 @@ object SystemSettingsService {
gravatar: Boolean, gravatar: Boolean,
notification: Boolean, notification: Boolean,
activityLogLimit: Option[Int], activityLogLimit: Option[Int],
limitVisibleRepositories: Boolean,
ssh: Ssh, ssh: Ssh,
useSMTP: Boolean, useSMTP: Boolean,
smtp: Option[Smtp], smtp: Option[Smtp],
@@ -283,6 +286,7 @@ object SystemSettingsService {
private val Gravatar = "gravatar" private val Gravatar = "gravatar"
private val Notification = "notification" private val Notification = "notification"
private val ActivityLogLimit = "activity_log_limit" private val ActivityLogLimit = "activity_log_limit"
private val LimitVisibleRepositories = "limitVisibleRepositories"
private val SshEnabled = "ssh" private val SshEnabled = "ssh"
private val SshHost = "ssh.host" private val SshHost = "ssh.host"
private val SshPort = "ssh.port" private val SshPort = "ssh.port"

View File

@@ -199,6 +199,21 @@
</div> </div>
</div> </div>
</fieldset> </fieldset>
<!--====================================================================-->
<!-- Sidebar -->
<!--====================================================================-->
<hr>
<label><span class="strong">Show Repositories in Sidebar</span></label>
<fieldset>
<label class="radio">
<input type="radio" name="limitVisibleRepositories" value="false"@if(!context.settings.limitVisibleRepositories){ checked}>
<span class="strong">All</span> <span class="normal">- Show all repositories in sidebar.</span>
</label>
<label class="radio">
<input type="radio" name="limitVisibleRepositories" value="true"@if(context.settings.limitVisibleRepositories){ checked}>
<span class="strong">Limited</span> <span class="normal">- Limit the visible repositories in sidebar.</span>
</label>
</fieldset>
<script> <script>
$(function(){ $(function(){
$('#skinName').change(function(evt) { $('#skinName').change(function(evt) {

View File

@@ -39,6 +39,7 @@ trait ServiceSpecBase extends MockitoSugar {
gravatar = false, gravatar = false,
notification = false, notification = false,
activityLogLimit = None, activityLogLimit = None,
limitVisibleRepositories = false,
ssh = Ssh( ssh = Ssh(
enabled = false, enabled = false,
sshHost = None, sshHost = None,

View File

@@ -125,6 +125,7 @@ class AvatarImageProviderSpec extends FunSpec with MockitoSugar {
gravatar = useGravatar, gravatar = useGravatar,
notification = false, notification = false,
activityLogLimit = None, activityLogLimit = None,
limitVisibleRepositories = false,
ssh = Ssh( ssh = Ssh(
enabled = false, enabled = false,
sshHost = None, sshHost = None,