Line data Source code
1 : // Copyright (C) 2011 The Android Open Source Project 2 : // 3 : // Licensed under the Apache License, Version 2.0 (the "License"); 4 : // you may not use this file except in compliance with the License. 5 : // You may obtain a copy of the License at 6 : // 7 : // http://www.apache.org/licenses/LICENSE-2.0 8 : // 9 : // Unless required by applicable law or agreed to in writing, software 10 : // distributed under the License is distributed on an "AS IS" BASIS, 11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 : // See the License for the specific language governing permissions and 13 : // limitations under the License. 14 : 15 : package com.google.gerrit.server.account; 16 : 17 : import com.google.gerrit.common.Nullable; 18 : import com.google.gerrit.common.data.GlobalCapability; 19 : import com.google.gerrit.entities.PermissionRange; 20 : import com.google.gerrit.entities.PermissionRule; 21 : import com.google.gerrit.index.query.QueryProcessor; 22 : import com.google.gerrit.server.CurrentUser; 23 : import com.google.gerrit.server.git.QueueProvider; 24 : import com.google.gerrit.server.group.SystemGroupBackend; 25 : import com.google.gerrit.server.project.ProjectCache; 26 : import com.google.inject.Inject; 27 : import com.google.inject.Singleton; 28 : import java.util.ArrayList; 29 : import java.util.List; 30 : 31 : /** Limits which QoS a user runs as, and how many search results it can request. */ 32 : public class AccountLimits { 33 : @Singleton 34 : public static class Factory { 35 : private final ProjectCache projectCache; 36 : 37 : @Inject 38 151 : Factory(ProjectCache projectCache) { 39 151 : this.projectCache = projectCache; 40 151 : } 41 : 42 : public AccountLimits create(CurrentUser user) { 43 123 : return new AccountLimits(projectCache, user); 44 : } 45 : } 46 : 47 : private final CapabilityCollection capabilities; 48 : private final CurrentUser user; 49 : 50 123 : private AccountLimits(ProjectCache projectCache, CurrentUser currentUser) { 51 123 : capabilities = projectCache.getAllProjects().getCapabilityCollection(); 52 123 : user = currentUser; 53 123 : } 54 : 55 : /** Returns which priority queue the user's tasks should be submitted to. */ 56 : public QueueProvider.QueueType getQueueType() { 57 : // If a non-generic group (that is not Anonymous Users or Registered Users) 58 : // grants us INTERACTIVE permission, use the INTERACTIVE queue even if 59 : // BATCH was otherwise granted. This allows site administrators to grant 60 : // INTERACTIVE to Registered Users, and BATCH to 'CI Servers' and have 61 : // the 'CI Servers' actually use the BATCH queue while everyone else gets 62 : // to use the INTERACTIVE queue without additional grants. 63 : // 64 12 : GroupMembership groups = user.getEffectiveGroups(); 65 12 : boolean batch = false; 66 12 : for (PermissionRule r : capabilities.priority) { 67 12 : if (match(groups, r)) { 68 0 : switch (r.getAction()) { 69 : case INTERACTIVE: 70 0 : if (!SystemGroupBackend.isAnonymousOrRegistered(r.getGroup())) { 71 0 : return QueueProvider.QueueType.INTERACTIVE; 72 : } 73 : break; 74 : 75 : case BATCH: 76 0 : batch = true; 77 0 : break; 78 : 79 : case ALLOW: 80 : case BLOCK: 81 : case DENY: 82 : break; 83 : } 84 : } 85 12 : } 86 : 87 12 : if (batch) { 88 : // If any of our groups matched to the BATCH queue, use it. 89 0 : return QueueProvider.QueueType.BATCH; 90 : } 91 12 : return QueueProvider.QueueType.INTERACTIVE; 92 : } 93 : 94 : /** 95 : * Get the limit on a {@link QueryProcessor} for a given user. 96 : * 97 : * @return limit according to {@link GlobalCapability#QUERY_LIMIT}. 98 : */ 99 : public int getQueryLimit() { 100 122 : return getRange(GlobalCapability.QUERY_LIMIT).getMax(); 101 : } 102 : 103 : /** Returns true if the user has a permission rule specifying the range. */ 104 : public boolean hasExplicitRange(String permission) { 105 89 : return GlobalCapability.hasRange(permission) && !getRules(permission).isEmpty(); 106 : } 107 : 108 : /** The range of permitted values associated with a label permission. */ 109 : @Nullable 110 : public PermissionRange getRange(String permission) { 111 122 : if (GlobalCapability.hasRange(permission)) { 112 122 : return toRange(permission, getRules(permission)); 113 : } 114 0 : return null; 115 : } 116 : 117 : private static PermissionRange toRange(String permissionName, List<PermissionRule> ruleList) { 118 122 : int min = 0; 119 122 : int max = 0; 120 122 : if (ruleList.isEmpty()) { 121 22 : PermissionRange.WithDefaults defaultRange = GlobalCapability.getRange(permissionName); 122 22 : if (defaultRange != null) { 123 22 : min = defaultRange.getDefaultMin(); 124 22 : max = defaultRange.getDefaultMax(); 125 : } 126 22 : } else { 127 122 : for (PermissionRule rule : ruleList) { 128 122 : min = Math.min(min, rule.getMin()); 129 122 : max = Math.max(max, rule.getMax()); 130 122 : } 131 : } 132 122 : return new PermissionRange(permissionName, min, max); 133 : } 134 : 135 : private List<PermissionRule> getRules(String permissionName) { 136 122 : List<PermissionRule> rules = capabilities.getPermission(permissionName); 137 122 : GroupMembership groups = user.getEffectiveGroups(); 138 : 139 122 : List<PermissionRule> mine = new ArrayList<>(rules.size()); 140 122 : for (PermissionRule rule : rules) { 141 122 : if (match(groups, rule)) { 142 122 : mine.add(rule); 143 : } 144 122 : } 145 122 : return mine; 146 : } 147 : 148 : private static boolean match(GroupMembership groups, PermissionRule rule) { 149 123 : return groups.contains(rule.getGroup().getUUID()); 150 : } 151 : }