Line data Source code
1 : // Copyright (C) 2017 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.group.db;
16 :
17 : import com.google.common.base.Strings;
18 : import com.google.gerrit.entities.AccountGroup;
19 : import com.google.gerrit.entities.InternalGroup;
20 : import org.eclipse.jgit.errors.ConfigInvalidException;
21 : import org.eclipse.jgit.lib.Config;
22 :
23 : /**
24 : * A basic property of a group.
25 : *
26 : * <p>Each property knows how to read and write its value from/to a JGit {@link Config} file.
27 : *
28 : * <p><strong>Warning:</strong> This class is a low-level API for properties of groups in NoteDb. It
29 : * may only be used by {@link GroupConfig}. Other classes should use {@link GroupDelta} to modify
30 : * the properties of a group.
31 : */
32 152 : enum GroupConfigEntry {
33 : /**
34 : * The numeric ID of a group. This property is equivalent to {@link InternalGroup#getId()}.
35 : *
36 : * <p>This is a mandatory property which may not be changed.
37 : */
38 152 : ID("id") {
39 : @Override
40 : void readFromConfig(AccountGroup.UUID groupUuid, InternalGroup.Builder group, Config config)
41 : throws ConfigInvalidException {
42 152 : int id = config.getInt(SECTION_NAME, super.keyName, -1);
43 152 : if (id < 0) {
44 1 : throw new ConfigInvalidException(
45 1 : String.format(
46 1 : "ID of the group %s must not be negative, found %d", groupUuid.get(), id));
47 : }
48 152 : group.setId(AccountGroup.id(id));
49 152 : }
50 :
51 : @Override
52 : void initNewConfig(Config config, InternalGroupCreation group) {
53 152 : AccountGroup.Id id = group.getId();
54 :
55 : // Do not use config.setInt(...) to write the group ID because config.setInt(...) persists
56 : // integers that can be expressed in KiB as a unit strings, e.g. "1024" is stored as "1k".
57 : // Using config.setString(...) ensures that group IDs are human readable.
58 152 : config.setString(SECTION_NAME, null, super.keyName, Integer.toString(id.get()));
59 152 : }
60 :
61 : @Override
62 : void updateConfigValue(Config config, GroupDelta groupDelta) {
63 : // Updating the ID is not supported.
64 152 : }
65 : },
66 : /**
67 : * The name of a group. This property is equivalent to {@link InternalGroup#getNameKey()}.
68 : *
69 : * <p>This is a mandatory property.
70 : */
71 152 : NAME("name") {
72 : @Override
73 : void readFromConfig(AccountGroup.UUID groupUuid, InternalGroup.Builder group, Config config) {
74 152 : String name = config.getString(SECTION_NAME, null, super.keyName);
75 : // An empty name is invalid in NoteDb; GroupConfig will refuse to store it and it might be
76 : // unusable in permissions. But, it was technically valid in the ReviewDb storage layer, and
77 : // the NoteDb migration converted such groups faithfully, so we need to be able to read them
78 : // back here.
79 152 : name = Strings.nullToEmpty(name);
80 152 : group.setNameKey(AccountGroup.nameKey(name));
81 152 : }
82 :
83 : @Override
84 : void initNewConfig(Config config, InternalGroupCreation group) {
85 152 : AccountGroup.NameKey name = group.getNameKey();
86 152 : config.setString(SECTION_NAME, null, super.keyName, name.get());
87 152 : }
88 :
89 : @Override
90 : void updateConfigValue(Config config, GroupDelta groupDelta) {
91 152 : groupDelta
92 152 : .getName()
93 152 : .ifPresent(name -> config.setString(SECTION_NAME, null, super.keyName, name.get()));
94 152 : }
95 : },
96 : /**
97 : * The description of a group. This property is equivalent to {@link
98 : * InternalGroup#getDescription()}.
99 : *
100 : * <p>It defaults to {@code null} if not set.
101 : */
102 152 : DESCRIPTION("description") {
103 : @Override
104 : void readFromConfig(AccountGroup.UUID groupUuid, InternalGroup.Builder group, Config config) {
105 152 : String description = config.getString(SECTION_NAME, null, super.keyName);
106 152 : group.setDescription(Strings.emptyToNull(description));
107 152 : }
108 :
109 : @Override
110 : void initNewConfig(Config config, InternalGroupCreation group) {
111 152 : config.setString(SECTION_NAME, null, super.keyName, null);
112 152 : }
113 :
114 : @Override
115 : void updateConfigValue(Config config, GroupDelta groupDelta) {
116 152 : groupDelta
117 152 : .getDescription()
118 152 : .ifPresent(
119 : description ->
120 152 : config.setString(
121 152 : SECTION_NAME, null, super.keyName, Strings.emptyToNull(description)));
122 152 : }
123 : },
124 : /**
125 : * The owner of a group. This property is equivalent to {@link InternalGroup#getOwnerGroupUUID()}.
126 : *
127 : * <p>It defaults to the group itself if not set.
128 : */
129 152 : OWNER_GROUP_UUID("ownerGroupUuid") {
130 : @Override
131 : void readFromConfig(AccountGroup.UUID groupUuid, InternalGroup.Builder group, Config config)
132 : throws ConfigInvalidException {
133 152 : String ownerGroupUuid = config.getString(SECTION_NAME, null, super.keyName);
134 152 : if (Strings.isNullOrEmpty(ownerGroupUuid)) {
135 1 : throw new ConfigInvalidException(
136 1 : String.format("Owner UUID of the group %s must be defined", groupUuid.get()));
137 : }
138 152 : group.setOwnerGroupUUID(AccountGroup.uuid(ownerGroupUuid));
139 152 : }
140 :
141 : @Override
142 : void initNewConfig(Config config, InternalGroupCreation group) {
143 152 : config.setString(SECTION_NAME, null, super.keyName, group.getGroupUUID().get());
144 152 : }
145 :
146 : @Override
147 : void updateConfigValue(Config config, GroupDelta groupDelta) {
148 152 : groupDelta
149 152 : .getOwnerGroupUUID()
150 152 : .ifPresent(
151 : ownerGroupUuid ->
152 152 : config.setString(SECTION_NAME, null, super.keyName, ownerGroupUuid.get()));
153 152 : }
154 : },
155 : /**
156 : * A flag indicating the visibility of a group. This property is equivalent to {@link
157 : * InternalGroup#isVisibleToAll()}.
158 : *
159 : * <p>It defaults to {@code false} if not set.
160 : */
161 152 : VISIBLE_TO_ALL("visibleToAll") {
162 : @Override
163 : void readFromConfig(AccountGroup.UUID groupUuid, InternalGroup.Builder group, Config config) {
164 152 : boolean visibleToAll = config.getBoolean(SECTION_NAME, super.keyName, false);
165 152 : group.setVisibleToAll(visibleToAll);
166 152 : }
167 :
168 : @Override
169 : void initNewConfig(Config config, InternalGroupCreation group) {
170 152 : config.setBoolean(SECTION_NAME, null, super.keyName, false);
171 152 : }
172 :
173 : @Override
174 : void updateConfigValue(Config config, GroupDelta groupDelta) {
175 152 : groupDelta
176 152 : .getVisibleToAll()
177 152 : .ifPresent(
178 30 : visibleToAll -> config.setBoolean(SECTION_NAME, null, super.keyName, visibleToAll));
179 152 : }
180 : };
181 :
182 : private static final String SECTION_NAME = "group";
183 :
184 : private final String keyName;
185 :
186 152 : GroupConfigEntry(String keyName) {
187 152 : this.keyName = keyName;
188 152 : }
189 :
190 : /**
191 : * Reads the corresponding property of this {@code GroupConfigEntry} from the given {@code
192 : * Config}. The read value is written to the corresponding property of {@code
193 : * InternalGroup.Builder}.
194 : *
195 : * @param groupUuid the UUID of the group (necessary for helpful error messages)
196 : * @param group the {@code InternalGroup.Builder} whose property value should be set
197 : * @param config the {@code Config} from which the value of the property should be read
198 : * @throws ConfigInvalidException if the property has an unexpected value
199 : */
200 : abstract void readFromConfig(
201 : AccountGroup.UUID groupUuid, InternalGroup.Builder group, Config config)
202 : throws ConfigInvalidException;
203 :
204 : /**
205 : * Initializes the corresponding property of this {@code GroupConfigEntry} in the given {@code
206 : * Config}.
207 : *
208 : * <p>If the specified {@code InternalGroupCreation} has an entry for the property, that value is
209 : * used. If not, the default value for the property is set. In any case, an existing entry for the
210 : * property in the {@code Config} will be overwritten.
211 : *
212 : * @param config a new {@code Config}, typically without an entry for the property
213 : * @param group an {@code InternalGroupCreation} detailing the initial value of mandatory group
214 : * properties
215 : */
216 : abstract void initNewConfig(Config config, InternalGroupCreation group);
217 :
218 : /**
219 : * Updates the corresponding property of this {@code GroupConfigEntry} in the given {@code Config}
220 : * if the {@link GroupDelta} mentions a modification.
221 : *
222 : * <p>This call is a no-op if the {@link GroupDelta} doesn't contain a modification for the
223 : * property.
224 : *
225 : * @param config a {@code Config} for which the property should be updated
226 : * @param groupDelta a {@link GroupDelta} detailing the modifications on a group
227 : */
228 : abstract void updateConfigValue(Config config, GroupDelta groupDelta);
229 : }
|