• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

apache / iotdb / #10030

08 Sep 2023 01:34AM UTC coverage: 47.698%. First build
#10030

push

travis_ci

web-flow
[auth].fix cache info

37 of 37 new or added lines in 8 files covered. (100.0%)

80772 of 169340 relevant lines covered (47.7%)

0.48 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

83.44
/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/user/BasicUserManager.java
1
/*
2
 * Licensed to the Apache Software Foundation (ASF) under one
3
 * or more contributor license agreements.  See the NOTICE file
4
 * distributed with this work for additional information
5
 * regarding copyright ownership.  The ASF licenses this file
6
 * to you under the Apache License, Version 2.0 (the
7
 * "License"); you may not use this file except in compliance
8
 * with the License.  You may obtain a copy of the License at
9
 *
10
 *     http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing,
13
 * software distributed under the License is distributed on an
14
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
 * KIND, either express or implied.  See the License for the
16
 * specific language governing permissions and limitations
17
 * under the License.
18
 */
19
package org.apache.iotdb.commons.auth.user;
20

21
import org.apache.iotdb.commons.auth.AuthException;
22
import org.apache.iotdb.commons.auth.entity.PathPrivilege;
23
import org.apache.iotdb.commons.auth.entity.PrivilegeType;
24
import org.apache.iotdb.commons.auth.entity.User;
25
import org.apache.iotdb.commons.concurrent.HashLock;
26
import org.apache.iotdb.commons.conf.CommonDescriptor;
27
import org.apache.iotdb.commons.conf.IoTDBConstant;
28
import org.apache.iotdb.commons.exception.IllegalPathException;
29
import org.apache.iotdb.commons.path.PartialPath;
30
import org.apache.iotdb.commons.utils.AuthUtils;
31
import org.apache.iotdb.rpc.TSStatusCode;
32

33
import org.slf4j.Logger;
34
import org.slf4j.LoggerFactory;
35

36
import java.io.IOException;
37
import java.util.ArrayList;
38
import java.util.HashMap;
39
import java.util.List;
40
import java.util.Map;
41
import java.util.Map.Entry;
42

43
/**
44
 * This class stores information of each user in a separate file within a directory, and cache them
45
 * in memory when a user is accessed.
46
 */
47
public abstract class BasicUserManager implements IUserManager {
48

49
  private static final Logger logger = LoggerFactory.getLogger(BasicUserManager.class);
1✔
50
  private static final String NO_SUCH_USER_ERROR = "No such user %s";
51

52
  protected Map<String, User> userMap;
53
  protected IUserAccessor accessor;
54
  protected HashLock lock;
55

56
  /**
57
   * BasicUserManager Constructor.
58
   *
59
   * @param accessor user accessor
60
   * @throws AuthException Authentication Exception
61
   */
62
  protected BasicUserManager(IUserAccessor accessor) throws AuthException {
1✔
63
    this.userMap = new HashMap<>();
1✔
64
    this.accessor = accessor;
1✔
65
    this.lock = new HashLock();
1✔
66

67
    reset();
1✔
68
  }
1✔
69

70
  /**
71
   * Try to load admin. If it doesn't exist, automatically create one
72
   *
73
   * @throws AuthException if an exception is raised when interacting with the lower storage.
74
   */
75
  private void initAdmin() throws AuthException {
76
    User admin;
77
    try {
78
      admin = getUser(CommonDescriptor.getInstance().getConfig().getAdminName());
1✔
79
    } catch (AuthException e) {
×
80
      logger.warn("Cannot load admin, Creating a new one", e);
×
81
      admin = null;
×
82
    }
1✔
83

84
    if (admin == null) {
1✔
85
      createUser(
1✔
86
          CommonDescriptor.getInstance().getConfig().getAdminName(),
1✔
87
          CommonDescriptor.getInstance().getConfig().getAdminPassword(),
1✔
88
          true);
89
      setUserUseWaterMark(CommonDescriptor.getInstance().getConfig().getAdminName(), false);
1✔
90
    }
91
    admin = getUser(CommonDescriptor.getInstance().getConfig().getAdminName());
1✔
92
    try {
93
      PartialPath rootPath = new PartialPath(new String(IoTDBConstant.PATH_ROOT + ".**"));
1✔
94
      PathPrivilege pathPri = new PathPrivilege(rootPath);
1✔
95
      for (PrivilegeType item : PrivilegeType.values()) {
1✔
96
        if (!item.isPathRelevant()) {
1✔
97
          admin.getSysPrivilege().add(item.ordinal());
1✔
98
          admin.getSysPriGrantOpt().add(item.ordinal());
1✔
99
        } else {
100
          pathPri.grantPrivilege(item.ordinal(), true);
1✔
101
        }
102
      }
103
      admin.getPathPrivilegeList().add(pathPri);
1✔
104
    } catch (IllegalPathException e) {
×
105
      // This error only results in a lack of permissions for list.
106
      logger.warn("Got a wrong path for root to init");
×
107
    }
1✔
108
    logger.info("Admin initialized");
1✔
109
  }
1✔
110

111
  @Override
112
  public User getUser(String username) throws AuthException {
113
    lock.readLock(username);
1✔
114
    User user = userMap.get(username);
1✔
115
    lock.readUnlock(username);
1✔
116
    return user;
1✔
117
  }
118

119
  @Override
120
  public boolean createUser(String username, String password, boolean firstInit)
121
      throws AuthException {
122
    if (!firstInit) {
1✔
123
      AuthUtils.validateUsername(username);
1✔
124
      AuthUtils.validatePassword(password);
1✔
125
    }
126

127
    User user = getUser(username);
1✔
128
    if (user != null) {
1✔
129
      return false;
1✔
130
    }
131
    lock.writeLock(username);
1✔
132
    try {
133
      user = new User(username, AuthUtils.encryptPassword(password));
1✔
134
      userMap.put(username, user);
1✔
135
      return true;
1✔
136
    } finally {
137
      lock.writeUnlock(username);
1✔
138
    }
139
  }
140

141
  @Override
142
  public boolean deleteUser(String username) {
143
    lock.writeLock(username);
1✔
144
    userMap.remove(username);
1✔
145
    lock.writeUnlock(username);
1✔
146
    return true;
1✔
147
  }
148

149
  @Override
150
  public boolean grantPrivilegeToUser(
151
      String username, PartialPath path, int privilegeId, boolean grantOpt) throws AuthException {
152
    // AuthUtils.validatePrivilege(path, privilegeId);
153
    lock.writeLock(username);
1✔
154
    try {
155
      User user = getUser(username);
1✔
156
      if (user == null) {
1✔
157
        throw new AuthException(
1✔
158
            TSStatusCode.USER_NOT_EXIST, String.format(NO_SUCH_USER_ERROR, username));
1✔
159
      }
160
      if (path != null) {
1✔
161
        AuthUtils.validatePatternPath(path);
1✔
162
        user.addPathPrivilege(path, privilegeId, grantOpt);
1✔
163
      } else {
164
        user.addSysPrivilege(privilegeId);
1✔
165
        if (grantOpt) {
1✔
166
          user.getSysPriGrantOpt().add(privilegeId);
×
167
        }
168
      }
169
      return true;
1✔
170
    } finally {
171
      lock.writeUnlock(username);
1✔
172
    }
173
  }
174

175
  @Override
176
  public boolean revokePrivilegeFromUser(String username, PartialPath path, int privilegeId)
177
      throws AuthException {
178
    //    AuthUtils.validatePrivilege(path, privilegeId);
179
    lock.writeLock(username);
1✔
180
    try {
181
      User user = getUser(username);
1✔
182
      if (user == null) {
1✔
183
        throw new AuthException(
1✔
184
            TSStatusCode.USER_NOT_EXIST, String.format(NO_SUCH_USER_ERROR, username));
1✔
185
      }
186
      if (!user.hasPrivilegeToRevoke(path, privilegeId)) {
1✔
187
        return false;
1✔
188
      }
189
      if (path != null) {
1✔
190
        AuthUtils.validatePatternPath(path);
1✔
191
        user.removePathPrivilege(path, privilegeId);
1✔
192
      } else {
193
        user.removeSysPrivilege(privilegeId);
×
194
      }
195
      return true;
1✔
196
    } finally {
197
      lock.writeUnlock(username);
1✔
198
    }
199
  }
200

201
  @Override
202
  public boolean updateUserPassword(String username, String newPassword) throws AuthException {
203
    try {
204
      AuthUtils.validatePassword(newPassword);
1✔
205
    } catch (AuthException e) {
1✔
206
      logger.debug("An illegal password detected ", e);
1✔
207
      return false;
1✔
208
    }
1✔
209

210
    lock.writeLock(username);
1✔
211
    try {
212
      User user = getUser(username);
1✔
213
      if (user == null) {
1✔
214
        throw new AuthException(
1✔
215
            TSStatusCode.USER_NOT_EXIST, String.format(NO_SUCH_USER_ERROR, username));
1✔
216
      }
217
      user.setPassword(AuthUtils.encryptPassword(newPassword));
1✔
218
      return true;
1✔
219
    } finally {
220
      lock.writeUnlock(username);
1✔
221
    }
222
  }
223

224
  @Override
225
  public boolean grantRoleToUser(String roleName, String username) throws AuthException {
226
    lock.writeLock(username);
1✔
227
    try {
228
      User user = getUser(username);
1✔
229
      if (user == null) {
1✔
230
        throw new AuthException(
1✔
231
            TSStatusCode.USER_NOT_EXIST, String.format(NO_SUCH_USER_ERROR, username));
1✔
232
      }
233
      if (user.hasRole(roleName)) {
1✔
234
        return false;
1✔
235
      }
236
      user.getRoleList().add(roleName);
1✔
237
      return true;
1✔
238
    } finally {
239
      lock.writeUnlock(username);
1✔
240
    }
241
  }
242

243
  @Override
244
  public boolean revokeRoleFromUser(String roleName, String username) throws AuthException {
245
    lock.writeLock(username);
1✔
246
    try {
247
      User user = getUser(username);
1✔
248
      if (user == null) {
1✔
249
        throw new AuthException(
1✔
250
            TSStatusCode.USER_NOT_EXIST, String.format(NO_SUCH_USER_ERROR, username));
1✔
251
      }
252
      if (!user.hasRole(roleName)) {
1✔
253
        return false;
1✔
254
      }
255
      user.getRoleList().remove(roleName);
1✔
256
      return true;
1✔
257
    } finally {
258
      lock.writeUnlock(username);
1✔
259
    }
260
  }
261

262
  @Override
263
  public void reset() throws AuthException {
264
    accessor.reset();
1✔
265
    userMap.clear();
1✔
266
    for (String name : accessor.listAllUsers()) {
1✔
267
      try {
268
        userMap.put(name, accessor.loadUser(name));
1✔
269
      } catch (IOException e) {
×
270
        throw new AuthException(TSStatusCode.AUTH_IO_EXCEPTION, e);
×
271
      }
1✔
272
    }
1✔
273
    initAdmin();
1✔
274
  }
1✔
275

276
  @Override
277
  public List<String> listAllUsers() {
278
    List<String> rtlist = new ArrayList<>();
1✔
279
    userMap.forEach(
1✔
280
        (name, item) -> {
281
          rtlist.add(name);
1✔
282
        });
1✔
283
    rtlist.sort(null);
1✔
284
    return rtlist;
1✔
285
  }
286

287
  @Override
288
  public boolean isUserUseWaterMark(String username) throws AuthException {
289
    User user = getUser(username);
1✔
290
    if (user == null) {
1✔
291
      throw new AuthException(
×
292
          TSStatusCode.USER_NOT_EXIST, String.format(NO_SUCH_USER_ERROR, username));
×
293
    }
294
    return user.isUseWaterMark();
1✔
295
  }
296

297
  @Override
298
  public void setUserUseWaterMark(String username, boolean useWaterMark) throws AuthException {
299
    User user = getUser(username);
1✔
300
    if (user == null) {
1✔
301
      throw new AuthException(
×
302
          TSStatusCode.USER_NOT_EXIST, String.format(NO_SUCH_USER_ERROR, username));
×
303
    }
304
    boolean oldFlag = user.isUseWaterMark();
1✔
305
    if (oldFlag == useWaterMark) {
1✔
306
      return;
1✔
307
    }
308
    user.setUseWaterMark(useWaterMark);
1✔
309
  }
1✔
310

311
  @Override
312
  public void replaceAllUsers(Map<String, User> users) throws AuthException {
313
    synchronized (this) {
×
314
      reset();
×
315
      userMap = users;
×
316

317
      for (Entry<String, User> entry : userMap.entrySet()) {
×
318
        User user = entry.getValue();
×
319
        try {
320
          accessor.saveUser(user);
×
321
        } catch (IOException e) {
×
322
          throw new AuthException(TSStatusCode.AUTH_IO_EXCEPTION, e);
×
323
        }
×
324
      }
×
325
    }
×
326
  }
×
327
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc