Line data Source code
1 : // Copyright (C) 2010 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.entities; 16 : 17 : import com.google.auto.value.AutoValue; 18 : 19 : @AutoValue 20 153 : public abstract class PermissionRule implements Comparable<PermissionRule> { 21 : public static final boolean DEF_FORCE = false; 22 : 23 153 : public enum Action { 24 153 : ALLOW, 25 153 : DENY, 26 153 : BLOCK, 27 : 28 153 : INTERACTIVE, 29 153 : BATCH 30 : } 31 : 32 : public abstract Action getAction(); 33 : 34 : public abstract boolean getForce(); 35 : 36 : public abstract int getMin(); 37 : 38 : public abstract int getMax(); 39 : 40 : public abstract GroupReference getGroup(); 41 : 42 : public static PermissionRule.Builder builder(GroupReference group) { 43 153 : return builder().setGroup(group); 44 : } 45 : 46 : public static PermissionRule create(GroupReference group) { 47 4 : return builder().setGroup(group).build(); 48 : } 49 : 50 : protected static Builder builder() { 51 153 : return new AutoValue_PermissionRule.Builder() 52 153 : .setMin(0) 53 153 : .setMax(0) 54 153 : .setAction(Action.ALLOW) 55 153 : .setForce(DEF_FORCE); 56 : } 57 : 58 : static PermissionRule merge(PermissionRule src, PermissionRule dest) { 59 1 : PermissionRule.Builder result = dest.toBuilder(); 60 1 : if (dest.getAction() != src.getAction()) { 61 1 : if (dest.getAction() == Action.BLOCK || src.getAction() == Action.BLOCK) { 62 1 : result.setAction(Action.BLOCK); 63 : 64 1 : } else if (dest.getAction() == Action.DENY || src.getAction() == Action.DENY) { 65 1 : result.setAction(Action.DENY); 66 : 67 1 : } else if (dest.getAction() == Action.BATCH || src.getAction() == Action.BATCH) { 68 1 : result.setAction(Action.BATCH); 69 : } 70 : } 71 : 72 1 : result.setForce(dest.getForce() || src.getForce()); 73 1 : result.setRange(Math.min(dest.getMin(), src.getMin()), Math.max(dest.getMax(), src.getMax())); 74 1 : return result.build(); 75 : } 76 : 77 : public boolean isDeny() { 78 119 : return getAction() == Action.DENY; 79 : } 80 : 81 : public boolean isBlock() { 82 119 : return getAction() == Action.BLOCK; 83 : } 84 : 85 : @Override 86 : public int compareTo(PermissionRule o) { 87 151 : int cmp = action(this) - action(o); 88 151 : if (cmp == 0) { 89 151 : cmp = range(o) - range(this); 90 : } 91 151 : if (cmp == 0) { 92 151 : cmp = group(this).compareTo(group(o)); 93 : } 94 151 : return cmp; 95 : } 96 : 97 : private static int action(PermissionRule a) { 98 151 : switch (a.getAction()) { 99 : case DENY: 100 3 : return 0; 101 : case ALLOW: 102 : case BATCH: 103 : case BLOCK: 104 : case INTERACTIVE: 105 : default: 106 151 : return 1 + a.getAction().ordinal(); 107 : } 108 : } 109 : 110 : private static int range(PermissionRule a) { 111 151 : return Math.abs(a.getMin()) + Math.abs(a.getMax()); 112 : } 113 : 114 : private static String group(PermissionRule a) { 115 151 : return a.getGroup().getName() != null ? a.getGroup().getName() : ""; 116 : } 117 : 118 : @Override 119 : public final String toString() { 120 0 : return asString(true); 121 : } 122 : 123 : public String asString(boolean canUseRange) { 124 152 : StringBuilder r = new StringBuilder(); 125 : 126 152 : switch (getAction()) { 127 : case ALLOW: 128 152 : break; 129 : 130 : case DENY: 131 7 : r.append("deny "); 132 7 : break; 133 : 134 : case BLOCK: 135 52 : r.append("block "); 136 52 : break; 137 : 138 : case INTERACTIVE: 139 1 : r.append("interactive "); 140 1 : break; 141 : 142 : case BATCH: 143 152 : r.append("batch "); 144 : break; 145 : } 146 : 147 152 : if (getForce()) { 148 152 : r.append("+force "); 149 : } 150 : 151 152 : if (canUseRange && (getMin() != 0 || getMax() != 0)) { 152 152 : if (0 <= getMin()) { 153 19 : r.append('+'); 154 : } 155 152 : r.append(getMin()); 156 152 : r.append(".."); 157 152 : if (0 <= getMax()) { 158 152 : r.append('+'); 159 : } 160 152 : r.append(getMax()); 161 152 : r.append(' '); 162 : } 163 : 164 152 : r.append(getGroup().toConfigValue()); 165 : 166 152 : return r.toString(); 167 : } 168 : 169 : public static PermissionRule fromString(String src, boolean mightUseRange) { 170 152 : final String orig = src; 171 152 : final PermissionRule.Builder rule = PermissionRule.builder(); 172 : 173 152 : src = src.trim(); 174 : 175 152 : if (src.startsWith("deny ")) { 176 7 : rule.setAction(Action.DENY); 177 7 : src = src.substring("deny ".length()).trim(); 178 : 179 152 : } else if (src.startsWith("block ")) { 180 52 : rule.setAction(Action.BLOCK); 181 52 : src = src.substring("block ".length()).trim(); 182 : 183 152 : } else if (src.startsWith("interactive ")) { 184 1 : rule.setAction(Action.INTERACTIVE); 185 1 : src = src.substring("interactive ".length()).trim(); 186 : 187 152 : } else if (src.startsWith("batch ")) { 188 152 : rule.setAction(Action.BATCH); 189 152 : src = src.substring("batch ".length()).trim(); 190 : } 191 : 192 152 : if (src.startsWith("+force ")) { 193 152 : rule.setForce(true); 194 152 : src = src.substring("+force ".length()).trim(); 195 : } 196 : 197 152 : if (mightUseRange && !GroupReference.isGroupReference(src)) { 198 152 : int sp = src.indexOf(' '); 199 152 : String range = src.substring(0, sp); 200 : 201 152 : if (range.matches("^([+-]?\\d+)\\.\\.([+-]?\\d+)$")) { 202 152 : int dotdot = range.indexOf(".."); 203 152 : int min = parseInt(range.substring(0, dotdot)); 204 152 : int max = parseInt(range.substring(dotdot + 2)); 205 152 : rule.setRange(min, max); 206 152 : } else { 207 0 : throw new IllegalArgumentException("Invalid range in rule: " + orig); 208 : } 209 : 210 152 : src = src.substring(sp + 1).trim(); 211 : } 212 : 213 152 : String groupName = GroupReference.extractGroupName(src); 214 152 : if (groupName != null) { 215 152 : GroupReference group = GroupReference.create(groupName); 216 152 : rule.setGroup(group); 217 152 : } else { 218 0 : throw new IllegalArgumentException("Rule must include group: " + orig); 219 : } 220 : 221 152 : return rule.build(); 222 : } 223 : 224 : public boolean hasRange() { 225 7 : return getMin() != 0 || getMax() != 0; 226 : } 227 : 228 : public static int parseInt(String value) { 229 152 : if (value.startsWith("+")) { 230 152 : value = value.substring(1); 231 : } 232 152 : return Integer.parseInt(value); 233 : } 234 : 235 : public abstract Builder toBuilder(); 236 : 237 : @AutoValue.Builder 238 153 : public abstract static class Builder { 239 : public Builder setDeny() { 240 1 : return setAction(Action.DENY); 241 : } 242 : 243 : public Builder setBlock() { 244 1 : return setAction(Action.BLOCK); 245 : } 246 : 247 : public Builder setRange(int newMin, int newMax) { 248 152 : if (newMax < newMin) { 249 0 : setMin(newMax); 250 0 : setMax(newMin); 251 : } else { 252 152 : setMin(newMin); 253 152 : setMax(newMax); 254 : } 255 152 : return this; 256 : } 257 : 258 : public abstract Builder setAction(Action action); 259 : 260 : public abstract Builder setGroup(GroupReference groupReference); 261 : 262 : public abstract Builder setForce(boolean newForce); 263 : 264 : public abstract Builder setMin(int min); 265 : 266 : public abstract Builder setMax(int max); 267 : 268 : public abstract GroupReference getGroup(); 269 : 270 : public abstract PermissionRule build(); 271 : } 272 : }