1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.mycore.user2;
20
21 import java.io.File;
22 import java.io.FileNotFoundException;
23 import java.io.FileOutputStream;
24 import java.io.IOException;
25 import java.io.OutputStream;
26 import java.text.MessageFormat;
27 import java.util.ArrayList;
28 import java.util.Arrays;
29 import java.util.Collection;
30 import java.util.Collections;
31 import java.util.HashSet;
32 import java.util.List;
33 import java.util.Locale;
34 import java.util.Optional;
35 import java.util.Set;
36
37 import org.apache.logging.log4j.LogManager;
38 import org.apache.logging.log4j.Logger;
39 import org.jdom2.Document;
40 import org.jdom2.Element;
41 import org.jdom2.output.Format;
42 import org.jdom2.output.XMLOutputter;
43 import org.mycore.common.MCRConstants;
44 import org.mycore.common.MCRException;
45 import org.mycore.common.MCRSession;
46 import org.mycore.common.MCRSessionMgr;
47 import org.mycore.common.config.MCRConfiguration2;
48 import org.mycore.common.content.MCRFileContent;
49 import org.mycore.common.xml.MCRXMLParserFactory;
50 import org.mycore.datamodel.classifications2.MCRLabel;
51 import org.mycore.frontend.cli.MCRAbstractCommands;
52 import org.mycore.frontend.cli.annotation.MCRCommand;
53 import org.mycore.frontend.cli.annotation.MCRCommandGroup;
54 import org.mycore.user2.utils.MCRRoleTransformer;
55 import org.mycore.user2.utils.MCRUserTransformer;
56 import org.xml.sax.SAXParseException;
57
58
59
60
61
62
63
64 @MCRCommandGroup(
65 name = "User Commands")
66 public class MCRUserCommands extends MCRAbstractCommands {
67
68 private static Logger LOGGER = LogManager.getLogger(MCRUserCommands.class.getName());
69
70 private static final String SYSTEM = MCRConfiguration2.getStringOrThrow("MCR.CommandLineInterface.SystemName")
71 + ":";
72
73
74
75
76
77
78
79
80
81 @MCRCommand(
82 syntax = "change to user {0} with {1}",
83 help = "Changes to the user {0} with the given password {1}.",
84 order = 10)
85 public static void changeToUser(String user, String password) {
86 MCRSession session = MCRSessionMgr.getCurrentSession();
87 System.out.println(SYSTEM + " The old user ID is " + session.getUserInformation().getUserID());
88 if (MCRUserManager.login(user, password) != null) {
89 System.out.println(SYSTEM + " The new user ID is " + session.getUserInformation().getUserID());
90 } else {
91 LOGGER.warn("Wrong password, no changes of user ID in session context!");
92 }
93 }
94
95
96
97
98
99
100
101 @MCRCommand(
102 syntax = "login {0}",
103 help = "Starts the login dialog for the user {0}.",
104 order = 20)
105 public static void login(String user) {
106 char[] password = {};
107 do {
108 password = System.console().readPassword("{0} Enter password for user {1} :> ", SYSTEM, user);
109 } while (password.length == 0);
110
111 changeToUser(user, String.valueOf(password));
112 }
113
114
115
116
117
118
119 @MCRCommand(
120 syntax = "init superuser",
121 help = "Initializes the user system. This command runs only if the user database does not exist.",
122 order = 30)
123 public static List<String> initSuperuser() {
124 final String suser = MCRConfiguration2.getStringOrThrow("MCR.Users.Superuser.UserName");
125 final String spasswd = MCRConfiguration2.getStringOrThrow("MCR.Users.Superuser.UserPasswd");
126 final Optional<String> semail = MCRConfiguration2.getString("MCR.Users.Superuser.UserEmail");
127 final String srole = MCRConfiguration2.getStringOrThrow("MCR.Users.Superuser.GroupName");
128
129 if (MCRUserManager.exists(suser)) {
130 LOGGER.error("The superuser already exists!");
131 return null;
132 }
133
134
135 try {
136 Set<MCRLabel> labels = new HashSet<>();
137 labels.add(new MCRLabel("en", "The superuser role", null));
138
139 MCRRole mcrRole = new MCRRole(srole, labels);
140 MCRRoleManager.addRole(mcrRole);
141 } catch (Exception e) {
142 throw new MCRException("Can't create the superuser role.", e);
143 }
144
145 LOGGER.info("The role {} is installed.", srole);
146
147
148 try {
149 MCRUser mcrUser = new MCRUser(suser);
150 mcrUser.setRealName("Superuser");
151 semail.ifPresent(mcrUser::setEMail);
152 mcrUser.assignRole(srole);
153 MCRUserManager.updatePasswordHashToSHA256(mcrUser, spasswd);
154 MCRUserManager.createUser(mcrUser);
155 } catch (Exception e) {
156 throw new MCRException("Can't create the superuser.", e);
157 }
158
159 LOGGER.info("The user {} with password {} is installed.", suser, spasswd);
160 return Collections.singletonList("change to user " + suser + " with " + spasswd);
161 }
162
163
164
165
166
167
168
169 @MCRCommand(
170 syntax = "delete role {0}",
171 help = "Deletes the role {0} from the user system, but only if it has no user assigned.",
172 order = 80)
173 public static void deleteRole(String roleID) {
174 MCRRoleManager.deleteRole(roleID);
175 }
176
177
178
179
180
181 @MCRCommand(
182 syntax = "export role {0} to directory {1}",
183 help = "Export the role {0} to the directory {1}. The filename will be {0}.xml")
184 public static void exportRole(String roleID, String directory) throws IOException {
185 MCRRole mcrRole = MCRRoleManager.getRole(roleID);
186 File targetFile = new File(directory, roleID + ".xml");
187 try (FileOutputStream fout = new FileOutputStream(targetFile)) {
188 XMLOutputter xout = new XMLOutputter(Format.getPrettyFormat().setEncoding(MCRConstants.DEFAULT_ENCODING));
189 xout.output(MCRRoleTransformer.buildExportableXML(mcrRole), fout);
190 }
191 }
192
193
194
195
196
197
198
199 @MCRCommand(
200 syntax = "import role from file {0}",
201 help = "Imports a role from file, if that role does not exist",
202 order = 90)
203 public static void addRole(String fileName) throws SAXParseException, IOException {
204 LOGGER.info("Reading file {} ...", fileName);
205 Document doc = MCRXMLParserFactory.getNonValidatingParser().parseXML(new MCRFileContent(fileName));
206 MCRRole role = MCRRoleTransformer.buildMCRRole(doc.getRootElement());
207 if (MCRRoleManager.getRole(role.getName()) == null) {
208 MCRRoleManager.addRole(role);
209 } else {
210 LOGGER.info("Role {} does already exist.", role.getName());
211 }
212 }
213
214
215
216
217
218
219
220 @MCRCommand(
221 syntax = "delete user {0}",
222 help = "Delete the user {0}.",
223 order = 110)
224 public static void deleteUser(String userID) throws Exception {
225 MCRUserManager.deleteUser(userID);
226 }
227
228
229
230
231
232
233
234 @MCRCommand(
235 syntax = "enable user {0}",
236 help = "Enables the user for the access.",
237 order = 60)
238 public static void enableUser(String userID) throws Exception {
239 MCRUser mcrUser = MCRUserManager.getUser(userID);
240 mcrUser.enableLogin();
241 MCRUserManager.updateUser(mcrUser);
242 }
243
244
245
246
247
248
249
250
251
252
253
254 @MCRCommand(
255 syntax = "encrypt passwords in user xml file {0} to file {1}",
256 help = "A migration tool to change old plain text password entries to encrpted entries.",
257 order = 40)
258 public static void encryptPasswordsInXMLFile(String oldFile, String newFile) throws SAXParseException, IOException {
259 File inputFile = getCheckedFile(oldFile);
260 if (inputFile == null) {
261 return;
262 }
263 LOGGER.info("Reading file {} ...", inputFile.getAbsolutePath());
264
265 Document doc = MCRXMLParserFactory.getNonValidatingParser().parseXML(new MCRFileContent(inputFile));
266 Element rootelm = doc.getRootElement();
267 MCRUser mcrUser = MCRUserTransformer.buildMCRUser(rootelm);
268
269 if (mcrUser == null) {
270 throw new MCRException("These data do not correspond to a user.");
271 }
272
273 MCRUserManager.updatePasswordHashToSHA256(mcrUser, mcrUser.getPassword());
274
275 FileOutputStream outFile = new FileOutputStream(newFile);
276 saveToXMLFile(mcrUser, outFile);
277 }
278
279
280
281
282
283
284
285 @MCRCommand(
286 syntax = "disable user {0}",
287 help = "Disables access of the user {0}",
288 order = 70)
289 public static void disableUser(String userID) throws Exception {
290 MCRUser mcrUser = MCRUserManager.getUser(userID);
291 mcrUser.disableLogin();
292 MCRUserManager.updateUser(mcrUser);
293 }
294
295
296
297
298
299 @MCRCommand(
300 syntax = "list all users",
301 help = "Lists all users.",
302 order = 160)
303 public static void listAllUsers() throws Exception {
304 List<MCRUser> users = MCRUserManager.listUsers(null, null, null, null);
305
306 for (MCRUser uid : users) {
307 listUser(uid);
308 }
309 }
310
311
312
313
314
315 @MCRCommand(
316 syntax = "list all roles",
317 help = "List all roles.",
318 order = 140)
319 public static void listAllRoles() throws Exception {
320 List<MCRRole> roles = MCRRoleManager.listSystemRoles();
321
322 for (MCRRole role : roles) {
323 listRole(role);
324 }
325 }
326
327
328
329
330
331
332
333
334
335
336 @MCRCommand(
337 syntax = "export user {0} to file {1}",
338 help = "Exports the data of user {0} to the file {1}.",
339 order = 180)
340 public static void exportUserToFile(String userID, String filename) throws IOException {
341 MCRUser user = MCRUserManager.getUser(userID);
342 if (user.getSystemRoleIDs().isEmpty()) {
343 LOGGER.warn("User {} has not any system roles.", user.getUserID());
344 }
345 FileOutputStream outFile = new FileOutputStream(filename);
346 LOGGER.info("Writing to file {} ...", filename);
347 saveToXMLFile(user, outFile);
348 }
349
350 @MCRCommand(
351 syntax = "export all users to directory {0}",
352 help = "Exports the data of all users to the directory {0}.")
353 public static List<String> exportAllUserToDirectory(String directory) throws IOException {
354 File dir = new File(directory);
355 if (!dir.exists() || !dir.isDirectory()) {
356 throw new MCRException("Directory does not exist: " + dir.getAbsolutePath());
357 }
358 List<MCRUser> users = MCRUserManager.listUsers(null, null, null, null);
359 ArrayList<String> commands = new ArrayList<>(users.size());
360 for (MCRUser user : users) {
361 File userFile = new File(dir, user.getUserID() + ".xml");
362 commands.add("export user " + user.getUserID() + " to file " + userFile.getAbsolutePath());
363 }
364 return commands;
365 }
366
367 @MCRCommand(
368 syntax = "import all users from directory {0}",
369 help = "Imports all users from directory {0}.")
370 public static List<String> importAllUsersFromDirectory(String directory) throws FileNotFoundException {
371 return batchLoadFromDirectory("import user from file", directory);
372 }
373
374 @MCRCommand(
375 syntax = "update all users from directory {0}",
376 help = "Updates all users from directory {0}.")
377 public static List<String> updateAllUsersFromDirectory(String directory) throws FileNotFoundException {
378 return batchLoadFromDirectory("update user from file", directory);
379 }
380
381 public static List<String> batchLoadFromDirectory(String cmd, String directory) throws FileNotFoundException {
382 File dir = new File(directory);
383 if (!dir.isDirectory()) {
384 throw new FileNotFoundException(dir.getAbsolutePath() + " is not a directory.");
385 }
386 File[] listFiles = dir
387 .listFiles(pathname -> pathname.isFile() && pathname.getName().endsWith(".xml"));
388 if (listFiles.length == 0) {
389 LOGGER.warn("Did not find any user files in {}", dir.getAbsolutePath());
390 return null;
391 }
392 Arrays.sort(listFiles);
393 ArrayList<String> cmds = new ArrayList<>(listFiles.length);
394 for (File file : listFiles) {
395 cmds.add(new MessageFormat("{0} {1}", Locale.ROOT).format(new Object[] { cmd, file.getAbsolutePath() }));
396 }
397 return cmds;
398 }
399
400
401
402
403
404
405
406
407 @MCRCommand(
408 syntax = "import user from file {0}",
409 help = "Imports a user from file {0}.")
410 public static void importUserFromFile(String filename) throws SAXParseException, IOException {
411 MCRUser user = getMCRUserFromFile(filename);
412 if (MCRUserManager.exists(user.getUserName(), user.getRealmID())) {
413 throw new MCRException("User already exists: " + user.getUserID());
414 }
415 MCRUserManager.createUser(user);
416 }
417
418
419
420
421
422
423
424
425 @MCRCommand(
426 syntax = "set password for user {0} to {1}",
427 help = "Sets a new password for the user. You must be this user or you must have administrator access.",
428 order = 50)
429 public static void setPassword(String userID, String password) throws MCRException {
430 MCRUser user = MCRUserManager.getUser(userID);
431 MCRUserManager.updatePasswordHashToSHA256(user, password);
432 MCRUserManager.updateUser(user);
433 }
434
435
436
437
438
439
440
441
442 @MCRCommand(
443 syntax = "list role {0}",
444 help = "Lists the role {0}.",
445 order = 150)
446 public static void listRole(String roleID) throws MCRException {
447 MCRRole role = MCRRoleManager.getRole(roleID);
448 listRole(role);
449 }
450
451 public static void listRole(MCRRole role) {
452 StringBuilder sb = new StringBuilder();
453 sb.append(" role=").append(role.getName());
454 for (MCRLabel label : role.getLabels()) {
455 sb.append("\n ").append(label);
456 }
457 Collection<String> userIds = MCRRoleManager.listUserIDs(role);
458 for (String userId : userIds) {
459 sb.append("\n user assigned to role=").append(userId);
460 }
461 LOGGER.info(sb.toString());
462 }
463
464
465
466
467
468
469
470
471 @MCRCommand(
472 syntax = "list user {0}",
473 help = "Lists the user {0}.",
474 order = 170)
475 public static void listUser(String userID) throws MCRException {
476 MCRUser user = MCRUserManager.getUser(userID);
477 listUser(user);
478 }
479
480 public static void listUser(MCRUser user) {
481 StringBuilder sb = new StringBuilder("\n");
482 sb.append(" user=").append(user.getUserName()).append(" real name=").append(user.getRealName())
483 .append('\n').append(" loginAllowed=").append(user.loginAllowed()).append('\n');
484 List<String> roles = new ArrayList<>(user.getSystemRoleIDs());
485 roles.addAll(user.getExternalRoleIDs());
486 for (String rid : roles) {
487 sb.append(" assigned to role=").append(rid).append('\n');
488 }
489 LOGGER.info(sb.toString());
490 }
491
492
493
494
495
496
497
498
499 private static File getCheckedFile(String filename) {
500 if (!filename.endsWith(".xml")) {
501 LOGGER.warn("{} ignored, does not end with *.xml", filename);
502
503 return null;
504 }
505
506 File file = new File(filename);
507 if (!file.isFile()) {
508 LOGGER.warn("{} ignored, is not a file.", filename);
509
510 return null;
511 }
512
513 return file;
514 }
515
516
517
518
519
520
521
522 public static void createUserFromFile(String filename) throws SAXParseException, IOException {
523 MCRUser user = getMCRUserFromFile(filename);
524 MCRUserManager.createUser(user);
525 }
526
527
528
529
530
531
532
533
534
535 @MCRCommand(
536 syntax = "update user from file {0}",
537 help = "Updates a user from file {0}.",
538 order = 200)
539 public static void updateUserFromFile(String filename) throws SAXParseException, IOException {
540 MCRUser user = getMCRUserFromFile(filename);
541 MCRUserManager.updateUser(user);
542 }
543
544 private static MCRUser getMCRUserFromFile(String filename) throws SAXParseException, IOException {
545 File inputFile = getCheckedFile(filename);
546 if (inputFile == null) {
547 return null;
548 }
549 LOGGER.info("Reading file {} ...", inputFile.getAbsolutePath());
550 Document doc = MCRXMLParserFactory.getNonValidatingParser().parseXML(new MCRFileContent(inputFile));
551 return MCRUserTransformer.buildMCRUser(doc.getRootElement());
552 }
553
554
555
556
557
558
559
560
561
562 @MCRCommand(
563 syntax = "assign user {0} to role {1}",
564 help = "Adds a user {0} as secondary member in the role {1}.",
565 order = 120)
566 public static void assignUserToRole(String userID, String roleID) throws MCRException {
567 try {
568 MCRUser user = MCRUserManager.getUser(userID);
569 user.assignRole(roleID);
570 MCRUserManager.updateUser(user);
571 } catch (Exception e) {
572 throw new MCRException("Error while assigning " + userID + " to role " + roleID + ".", e);
573 }
574 }
575
576
577
578
579
580
581
582
583
584 @MCRCommand(
585 syntax = "unassign user {0} from role {1}",
586 help = "Removes the user {0} as secondary member from the role {1}.",
587 order = 130)
588 public static void unassignUserFromRole(String userID, String roleID) throws MCRException {
589 try {
590 MCRUser user = MCRUserManager.getUser(userID);
591 user.unassignRole(roleID);
592 MCRUserManager.updateUser(user);
593 } catch (Exception e) {
594 throw new MCRException("Error while unassigning " + userID + " from role " + roleID + ".", e);
595 }
596 }
597
598
599
600
601
602
603
604
605
606
607
608 private static void saveToXMLFile(MCRUser mcrUser, FileOutputStream outFile) throws MCRException, IOException {
609
610 XMLOutputter outputter = new XMLOutputter(Format.getPrettyFormat().setEncoding(MCRConstants.DEFAULT_ENCODING));
611
612 try {
613 outputter.output(MCRUserTransformer.buildExportableXML(mcrUser), outFile);
614 } catch (Exception e) {
615 throw new MCRException("Error while save XML to file: " + e.getMessage());
616 } finally {
617 outFile.close();
618 }
619 }
620 }