source: trunk/src/org/expeditee/auth/Actions.java@ 1266

Last change on this file since 1266 was 1263, checked in by bln4, 5 years ago

When starting Authenticator mode and the authadmin account has not been registered, have the user register it.

File size: 32.4 KB
Line 
1package org.expeditee.auth;
2
3import java.io.File;
4import java.io.FileNotFoundException;
5import java.io.FileWriter;
6import java.io.IOException;
7import java.nio.file.Files;
8import java.nio.file.Path;
9import java.nio.file.Paths;
10import java.nio.file.StandardCopyOption;
11import java.security.InvalidKeyException;
12import java.security.KeyFactory;
13import java.security.KeyPair;
14import java.security.KeyPairGenerator;
15import java.security.KeyStoreException;
16import java.security.NoSuchAlgorithmException;
17import java.security.PrivateKey;
18import java.security.PublicKey;
19import java.security.SecureRandom;
20import java.security.cert.CertificateException;
21import java.security.spec.InvalidKeySpecException;
22import java.security.spec.PKCS8EncodedKeySpec;
23import java.sql.Connection;
24import java.sql.DriverManager;
25import java.sql.SQLException;
26import java.sql.Statement;
27import java.util.Base64;
28import java.util.Collection;
29import java.util.HashMap;
30import java.util.List;
31import java.util.Map;
32import java.util.Optional;
33import java.util.Random;
34import java.util.stream.Collectors;
35
36import javax.crypto.BadPaddingException;
37import javax.crypto.IllegalBlockSizeException;
38import javax.crypto.NoSuchPaddingException;
39import javax.crypto.SecretKey;
40import javax.crypto.spec.SecretKeySpec;
41
42import org.apollo.io.AudioPathManager;
43import org.expeditee.agents.ExistingFramesetException;
44import org.expeditee.agents.InvalidFramesetNameException;
45import org.expeditee.auth.Mail.MailEntry;
46import org.expeditee.auth.gui.MailBay;
47import org.expeditee.auth.tags.AuthenticationTag;
48import org.expeditee.auth.tags.Constants;
49import org.expeditee.core.Colour;
50import org.expeditee.gui.Browser;
51import org.expeditee.gui.DisplayController;
52import org.expeditee.gui.Frame;
53import org.expeditee.gui.FrameIO;
54import org.expeditee.gui.MessageBay;
55import org.expeditee.items.Item;
56import org.expeditee.items.PermissionPair;
57import org.expeditee.items.Text;
58import org.expeditee.items.UserAppliedPermission;
59import org.expeditee.setting.GenericSetting;
60import org.expeditee.setting.Setting;
61import org.expeditee.setting.TextSetting;
62import org.expeditee.settings.Settings;
63import org.expeditee.settings.UserSettings;
64import org.expeditee.settings.folders.FolderSettings;
65import org.expeditee.settings.identity.secrets.KeyList;
66import org.ngikm.cryptography.CryptographyConstants;
67
68public class Actions implements CryptographyConstants {
69
70 public static void SendTestMessage(String colleagueName) throws InvalidKeySpecException, NoSuchAlgorithmException, FileNotFoundException, KeyStoreException, CertificateException, ClassNotFoundException, IOException, SQLException {
71 String time = org.expeditee.stats.Formatter.getDateTime();
72 String sender = UserSettings.UserName.get();
73 String topic = "Test Message";
74 String message = "This is a test message.";
75 Map<String, String> options = new HashMap<String, String>();
76 options.put("Neat", "Beep");
77 MailEntry mail = new MailEntry(time, sender, colleagueName, topic, message, options);
78 PublicKey publicKey = Authenticator.getInstance().getPublicKey(colleagueName);
79 Path outbox = Paths.get(FrameIO.PROFILE_PATH).resolve(sender).resolve(sender + "-credentials");
80 Mail.sendMail(mail, publicKey, outbox);
81 }
82
83 /**
84 * Display Expeditee Mail
85 * @throws IOException
86 * @throws SQLException
87 * @throws ClassNotFoundException
88 * @throws CertificateException
89 * @throws NoSuchAlgorithmException
90 * @throws FileNotFoundException
91 * @throws KeyStoreException
92 */
93 public static void MailMode() throws KeyStoreException, FileNotFoundException, NoSuchAlgorithmException, CertificateException, ClassNotFoundException, SQLException, IOException {
94 if (!DisplayController.isMailMode()) {
95 Mail.clear();
96 Authenticator.getInstance().loadMailDatabase();
97 }
98 DisplayController.ToggleMailMode();
99 }
100
101 /**
102 * Action used to navigate the authorised user back to their desktop.
103 */
104 public static void AuthGoToDesktop() {
105 DisplayController.setCurrentFrame(FrameIO.LoadFrame(UserSettings.HomeFrame.get()), true);
106 }
107
108 /**
109 * Action used to created a new user account.
110 * Attempts to use content from text items on frame, will default to java properties if they cannot be found.
111 * Will fail if it cannot find content from text items on frame and all required java properties are not present.
112 * @throws SQLException
113 * @throws IOException
114 * @throws ExistingFramesetException
115 * @throws InvalidFramesetNameException
116 * @throws ClassNotFoundException
117 * @throws FileNotFoundException
118 * @throws CertificateException
119 * @throws NoSuchAlgorithmException
120 * @throws KeyStoreException
121 * @throws BadPaddingException
122 * @throws IllegalBlockSizeException
123 * @throws NoSuchPaddingException
124 * @throws InvalidKeySpecException
125 * @throws InvalidKeyException
126 * @throws Exception
127 */
128 public static void AuthCreateAccount() throws KeyStoreException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, ClassNotFoundException, InvalidFramesetNameException, ExistingFramesetException, IOException, SQLException, InvalidKeyException, InvalidKeySpecException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException {
129 Collection<Text> textItems = DisplayController.getCurrentFrame().getTextItems();
130 Optional<Map<AuthenticationTag, String>> userdata =
131 AuthenticationTag.fetchUserData(textItems, false,
132 AuthenticationTag.Username,
133 AuthenticationTag.Password,
134 AuthenticationTag.PasswordAgain,
135 AuthenticationTag.Email,
136 AuthenticationTag.EmailAgain);
137
138 if (userdata.isPresent()) {
139 Map<AuthenticationTag, String> userData = userdata.get();
140
141 // A profile already existing with 'username' means an account cannot be created with that username.
142 if (FrameIO.LoadProfile(userData.get(AuthenticationTag.Username)) != null) {
143 MessageBay.errorMessage(Constants.ERROR_PROFILE_NAME_PREEXISTS);
144 return;
145 }
146
147 // The chosen username must be a valid frameset name.
148 if (!FrameIO.isValidFramesetName(userData.get(AuthenticationTag.Username))) {
149 MessageBay.errorMessage(Constants.ERROR_INVALID_USERNAME);
150 return;
151 }
152
153 // The passwords provided must match
154 if (userData.get(AuthenticationTag.Password).compareTo(userData.get(AuthenticationTag.PasswordAgain)) != 0) {
155 MessageBay.errorMessage(Constants.ERROR_MISMATCH_PASSWORDS);
156 return;
157 }
158
159 // The emails provided must match
160 if (userData.get(AuthenticationTag.Email).compareTo(userData.get(AuthenticationTag.EmailAgain)) != 0) {
161 MessageBay.errorMessage(Constants.ERROR_MISMATCH_EMAILS);
162 return;
163 }
164
165 createAccount(userData);
166 login(userData);
167 Authenticator.Authenticated = true;
168 } else {
169 MessageBay.errorMessage(Constants.ERROR_INSUFFICIENT_INFORMATION_PROVIDED);
170 }
171 }
172
173 /**
174 * Action used to start authentication as a specified user.
175 * Attempts to use content from text items on frame, will default to java properties if they cannot be found.
176 * Will fail if it cannot find content from text items on frame and all required java properties are not present.
177 * @throws Exception
178 */
179 public static void AuthLogin() throws Exception {
180 final Collection<Text> textItems = DisplayController.getCurrentFrame().getTextItems();
181 final Optional<Map<AuthenticationTag, String>> userdata = AuthenticationTag.fetchUserData(textItems, false, AuthenticationTag.Username, AuthenticationTag.Password);
182 if (userdata.isPresent()) {
183 login(userdata.get());
184 Authenticator.Authenticated = true;
185 }
186 else {
187 MessageBay.errorMessage(Constants.ERROR_INSUFFICIENT_INFORMATION_PROVIDED);
188 }
189 }
190
191 /**
192 * Action used to change the currently authenticated users password.
193 * Attempts to use content from text items on frame, will default to java properties if they cannot be found.
194 * Will fail if it cannot find content from text items on frame and all required java properties are not present.
195 * Will fail if no user is currently logged in.
196 * @throws IOException
197 * @throws CertificateException
198 * @throws FileNotFoundException
199 * @throws KeyStoreException
200 * @throws NoSuchAlgorithmException
201 * @throws SQLException
202 * @throws ClassNotFoundException
203 */
204 public static void AuthChangePassword() throws NoSuchAlgorithmException, KeyStoreException, FileNotFoundException, CertificateException, IOException, ClassNotFoundException, SQLException {
205 final Collection<Text> textItems = DisplayController.getCurrentFrame().getTextItems();
206
207 if (!Authenticator.Authenticated) {
208 MessageBay.errorMessage(Constants.ERROR_MUST_BE_LOGGED_IN);
209 } else {
210 final Optional<Map<AuthenticationTag, String>> userdata = AuthenticationTag.fetchUserData(textItems, false, AuthenticationTag.Password, AuthenticationTag.NewPassword, AuthenticationTag.NewPasswordAgain);
211 if (userdata.isPresent()) {
212 final Map<AuthenticationTag, String> userData = userdata.get();
213 if (userData.get(AuthenticationTag.NewPassword).compareTo(userData.get(AuthenticationTag.NewPasswordAgain)) != 0) {
214 MessageBay.errorMessage(Constants.ERROR_MISMATCH_PASSWORDS);
215 } else {
216 userData.put(AuthenticationTag.Username, UserSettings.UserName.get());
217 changePassword(userData);
218 }
219 } else {
220 MessageBay.errorMessage(Constants.ERROR_INSUFFICIENT_INFORMATION_PROVIDED);
221 }
222 }
223 }
224
225 public static void AuthGotoAccountManagement() {
226 if (Authenticator.Authenticated) {
227 DisplayController.setCurrentFrame(FrameIO.LoadFrame(Constants.FRAME_MULTIUSER1), false);
228 } else {
229 DisplayController.setCurrentFrame(FrameIO.LoadFrame(Constants.FRAME_AUTHENTICATION1), false);
230 }
231 }
232
233 public static void AuthShareFrameset() throws IOException {
234 Collection<Text> textItems = DisplayController.getCurrentFrame().getTextItems();
235
236 Optional<Map<AuthenticationTag, String>> userdata = AuthenticationTag.fetchUserData(textItems, false, AuthenticationTag.Frameset);
237 if (userdata.isPresent()) {
238 Map<AuthenticationTag, String> userData = userdata.get();
239 FrameIO.SuspendCache();
240 Frame toShare = FrameIO.LoadFrame(userData.get(AuthenticationTag.Frameset) + 1);
241 FrameIO.ResumeCache();
242
243 if (toShare == null) {
244 MessageBay.errorMessage(Constants.ERROR_INSUFFICIENT_INFORMATION);
245 return;
246 }
247
248 shareFrameset(toShare);
249 }
250 }
251
252 /**
253 * Navigation action for progressing the process of recruiting colleagues to assist in password recovery.
254 * Hides certain content that AuthSubmitPWCollegues goes onto show if it does not fail.
255 */
256 public static void AuthGotoColleagueSubmissionFrame() {
257 Frame destination = FrameIO.LoadFrame(Constants.FRAME_COLLEAGUE_SUBMISSION_FRAME);
258 DisplayController.setCurrentFrame(destination, true);
259 Collection<Item> toHide = getByData(destination, Constants.DATA_SHOW_ON_PROGRESS);
260 for (Item i: toHide) {
261 i.setVisible(false);
262 }
263 }
264
265 /**
266 * Action used to start the process of formalising the password recovery process.
267 * @throws SQLException
268 * @throws IOException
269 * @throws ClassNotFoundException
270 * @throws CertificateException
271 * @throws NoSuchAlgorithmException
272 * @throws FileNotFoundException
273 * @throws KeyStoreException
274 * @throws InvalidKeySpecException
275 */
276 public static void AuthSubmitPWColleagues() throws InvalidKeySpecException, NoSuchAlgorithmException, KeyStoreException, FileNotFoundException, CertificateException, ClassNotFoundException, IOException, SQLException {
277 Frame currentFrame = DisplayController.getCurrentFrame();
278 Collection<Text> textItems = currentFrame.getTextItems();
279
280 if (!Authenticator.Authenticated) {
281 MessageBay.errorMessage(Constants.ERROR_MUST_BE_LOGGED_IN);
282 return;
283 }
284
285 Optional<Map<AuthenticationTag, String>> userdata = AuthenticationTag.fetchUserData(textItems, false, AuthenticationTag.ColleagueOne, AuthenticationTag.ColleagueTwo);
286 if (userdata.isPresent()) {
287 Map<AuthenticationTag, String> userData = userdata.get();
288 String colleagueOne = userData.get(AuthenticationTag.ColleagueOne);
289 Path colleagueOnePath = Paths.get(FrameIO.CONTACTS_PATH).resolve(colleagueOne + "-credentials");
290 String colleagueTwo = userData.get(AuthenticationTag.ColleagueTwo);
291 Path colleagueTwoPath = Paths.get(FrameIO.CONTACTS_PATH).resolve(colleagueTwo + "-credentials");
292 if (!colleagueOnePath.toFile().exists()) {
293 MessageBay.errorMessage("Your nominated colleague: " + colleagueOne + " must exist in your contacts.");
294 } else if (!colleagueTwoPath.toFile().exists()) {
295 MessageBay.errorMessage("Your nominated colleague: " + colleagueTwo + " must exist in your contacts.");
296 } else {
297 userData.put(AuthenticationTag.Username, UserSettings.UserName.get());
298 boolean success = submitPWColleagues(userData);
299 if (success) {
300 Collection<Item> toShow = getByData(currentFrame, Constants.DATA_SHOW_ON_PROGRESS);
301 for (Item i: toShow) {
302 i.setVisible(true);
303 }
304 currentFrame.change();
305 MessageBay.displayMessage("-------Messages sent-------");
306 }
307 FrameIO.SaveFrame(currentFrame);
308 DisplayController.requestRefresh(false);
309 }
310 }
311 }
312
313// public static void AuthSetupPasswordRecovery() throws KeyStoreException, FileNotFoundException, NoSuchAlgorithmException, CertificateException, ClassNotFoundException, IOException, SQLException, UnrecoverableEntryException {
314// if (!UserSettings.Authenticated.get()) {
315// MessageBay.errorMessage("You must be logged in to perform this action.");
316// } else if (!Authenticator.getInstance().hasRegisteredEmail(UserSettings.UserName.get())) {
317// Frame registerEmailFrame = FrameIO.LoadFrame("authentication4");
318// DisplayController.setCurrentFrame(registerEmailFrame, true);
319// } else if (!Authenticator.getInstance().hasRequestedColleagues(UserSettings.UserName.get()) && Authenticator.getInstance().getColleagues(UserSettings.UserName.get()) == null) {
320// Frame submitColleaguesFrame = FrameIO.LoadFrame("authentication5");
321// DisplayController.setCurrentFrame(submitColleaguesFrame, true);
322// } else if (Authenticator.getInstance().hasRequestedColleagues(UserSettings.UserName.get()) && Authenticator.getInstance().getColleagues(UserSettings.UserName.get()) == null) {
323// MessageBay.displayMessage("You have already nominated two colleagues to assist you in the process of password recovery and are awaiting their response."
324// + " You will be alerted on Expeditee startup when they have both responded.");
325// } else if (Authenticator.getInstance().getColleagues(UserSettings.UserName.get()) != null) {
326// MessageBay.displayMessage("You have completed the Password Recovery Setup process, there is nothing more to do here.");
327// }
328// }
329
330 public static void AuthConfirmPasswordColleagueRelationship(String colleagueName) {
331
332 }
333
334 public static void AuthDenyPasswordColleagueRelationship(String colleagueName) throws InvalidKeySpecException, NoSuchAlgorithmException,
335 KeyStoreException, FileNotFoundException, CertificateException, ClassNotFoundException, IOException, SQLException {
336 denyPasswordColleagueRelationship(colleagueName);
337 }
338
339 public static void AuthClearPWColleaguesNominated() {
340
341 }
342
343 /**
344 * Create a user account using the specified information in userdata. Creates and stores user keys.
345 * @param userdata Should contain username, password and email.
346 */
347 private static void createAccount(Map<AuthenticationTag, String> userdata) throws InvalidFramesetNameException, ExistingFramesetException,
348 KeyStoreException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, ClassNotFoundException, IOException, SQLException {
349
350 // Track progress
351 String message = "Creating new user account...";
352 //Progress progress = MessageBay.displayProgress(message);
353
354 // Extract user details
355 String username = userdata.get(AuthenticationTag.Username);
356 String password = userdata.get(AuthenticationTag.Password);
357 String email = userdata.get(AuthenticationTag.Email);
358
359 System.out.println(message + "Generating Keys.");
360
361 // Generate keys
362 // Personal key
363 Random rand = new SecureRandom();
364 byte[] keyBytes = new byte[16];
365 rand.nextBytes(keyBytes);
366 SecretKey key = new SecretKeySpec(keyBytes, SymmetricAlgorithm);
367 Authenticator.getInstance().putKey(username, password, key);
368 String personalKey = Base64.getEncoder().encodeToString(key.getEncoded());
369 // Public and private keys
370 KeyPairGenerator keyGen = KeyPairGenerator.getInstance(AsymmetricAlgorithm);
371 keyGen.initialize(1024);
372 KeyPair keyPair = keyGen.generateKeyPair();
373 String publicKey = Base64.getEncoder().encodeToString(keyPair.getPublic().getEncoded());
374 String privateKey = Base64.getEncoder().encodeToString(keyPair.getPrivate().getEncoded());
375
376 System.out.println(message + "Creating Profile Frameset.");
377
378 // Update in memory settings
379 System.setProperty("user.name", username);
380 UserSettings.UserName.set(username);
381 UserSettings.ProfileName.set(username);
382 UserSettings.setupDefaultFolders();
383
384 // Establish the initial settings for the created user.
385 Map<String, Setting> initialSettings = new HashMap<String, Setting>();
386 initialSettings.put(Constants.SETTINGS_AUTH_SECRETS_PERSONAL_KEY, constructTextSetting(Constants.TOOLTIP_SETTING_PERSONAL_KEY, "PersonalKey", personalKey));
387 initialSettings.put(Constants.SETTINGS_AUTH_SECRETS_PRIVATE_KEY, constructTextSetting(Constants.TOOLTIP_SETTING_PRIVATE_KEY, "PrivateKey", privateKey));
388 initialSettings.put(Constants.SETTINGS_AUTH_PUBLIC_KEY, constructTextSetting(Constants.TOOLTIP_SETTING_PUBLIC_KEY, "PublicKey", publicKey));
389 initialSettings.put(Constants.SETTINGS_AUTH_EMAIL, constructGenericSetting(String.class, Constants.TOOLTIP_SETTING_EMAIL, "Email", email, username));
390 initialSettings.put(Constants.SETTINGS_USER_SETTINGS_USER_NAME, constructGenericSetting(String.class, Constants.LABEL_USERNAME, Constants.LABEL_USERNAME, username, username));
391 initialSettings.put(Constants.SETTINGS_USER_SETTINGS_PROFILE_NAME, constructGenericSetting(String.class, Constants.LABEL_PROFILENAME, Constants.LABEL_PROFILENAME, username, username));
392 initialSettings.put("org.expeditee.gui.folders.FolderSettings.FrameDirs", FolderSettings.FrameDirs);
393 initialSettings.put("org.expeditee.gui.folders.FolderSettings.ImageDirs", FolderSettings.ImageDirs);
394 initialSettings.put("org.expeditee.gui.folders.FolderSettings.AudioDirs", FolderSettings.AudioDirs);
395
396 // Create users profile
397 Frame profile = FrameIO.CreateNewProfile(username, initialSettings);
398 int lastNumber = FrameIO.getLastNumber(profile.getFramesetName());
399 for (int i = 1; i <= lastNumber; i++) {
400 Frame f = FrameIO.LoadFrame(profile.getFramesetName() + i);
401 Text titleItem = f.getTitleItem();
402 if (i == 1 && titleItem != null) {
403 titleItem.delete();
404 f.setBackgroundColor(new Colour(1, 1, 0.39f));
405 }
406 f.setOwner(username);
407 f.getAllItems().stream().forEach(item -> item.setOwner(username));
408 f.setChanged(true);
409 f.setEncryptionLabel("Profile");
410 Collection<Item> secretsLink = getByContent(f, "Secrets");
411 Collection<Item> publicKeyItem = getByContent(f, "PublicKey");
412 if (!secretsLink.isEmpty() && !publicKeyItem.isEmpty()) {
413 //Then we are on credentials frame
414 secretsLink.forEach(text -> text.setPermission(new PermissionPair(UserAppliedPermission.full, UserAppliedPermission.none)));
415 f.addToData("MultiuserCredentials");
416 }
417 Text backupPersonalKey = KeyList.PersonalKey.get();
418 Text tempPersonalKey = KeyList.PersonalKey.generateText();
419 tempPersonalKey.setData(personalKey);
420 KeyList.PersonalKey.setSetting(tempPersonalKey);
421 FrameIO.SaveFrame(f);
422 KeyList.PersonalKey.setSetting(backupPersonalKey);
423 }
424
425 System.out.println(message + "Establishing user credentials.");
426
427 // Create credentials
428 File credentialsDir = new File(profile.getFramesetPath() + username + "-credentials");
429 credentialsDir.mkdir();
430 // credentials.inf file.
431 String credentialsPath = credentialsDir.getAbsolutePath() + File.separator + "credentials.inf";
432 File credentialsFile = new File(credentialsPath);
433 credentialsFile.createNewFile();
434 FileWriter out = new FileWriter(credentialsFile);
435 out.write(Authenticator.CREDENTIALS_FRAME + ".exp");
436 out.flush();
437 out.close();
438 // outbox
439 Connection c = DriverManager.getConnection("jdbc:sqlite:" + credentialsDir.getAbsolutePath() + File.separator + "expmail.db");
440 Statement createTable = c.createStatement();
441 String sql = "CREATE TABLE EXPMAIL (" +
442 "TIME TEXT NOT NULL, " +
443 "SND TEXT NOT NULL, " +
444 "REC TEXT NOT NULL, " +
445 "MSG TEXT NOT NULL, " +
446 "MSG2 TEXT NOT NULL, " +
447 "OPTS ARRAY NOT NULL, " +
448 "OPTSVAL ARRAY NOT NULL)";
449 createTable.executeUpdate(sql);
450 createTable.close();
451 c.close();
452
453 System.out.println(message + "Creating Individual Space.");
454
455 // Copy private resources to personal area
456 Path personalResources = FrameIO.setupPersonalResources(username);
457
458 File contactsDir = new File(personalResources.resolve("contacts").toAbsolutePath().toString());
459 contactsDir.mkdir();
460
461 System.err.println("**** Hardwired call in Apollo's AuthioPathManager");
462 AudioPathManager.activateAndScanAudioDir(); // ****
463
464 System.out.println(message + "Done.");
465 }
466
467
468
469 /*
470 * Function used to authenticate as a specified user (via function arguments).
471 */
472 private static void login(Map<AuthenticationTag, String> userdata) throws NoSuchAlgorithmException, KeyStoreException, FileNotFoundException, CertificateException, ClassNotFoundException, IOException, SQLException, InvalidKeySpecException, InvalidKeyException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException {
473 String username = userdata.get(AuthenticationTag.Username);
474 String password = userdata.get(AuthenticationTag.Password);
475
476 if (username.equals(Browser.USER_NOBODY)) {
477 return;
478 }
479
480 SecretKey personalKey = Authenticator.getInstance().getSecretKey(username, password);
481 if (personalKey == null) {
482 // Incorrect username and password
483 MessageBay.errorMessage("The username + password combination was incorrect.");
484 return;
485 }
486
487 // **** DB
488 // Have not been able to test the following as auth + login not currently working
489 // 'out of the box'
490
491 // Currently causing a concurrent modification setting related to InputManager.distributeGesture (preGesture)
492
493 // initialize Apollo
494// EcosystemManager.getMiscManager().runOnGIOThread(new BlockingRunnable() {
495// public void execute() {
496// ApolloSystem.initialize();
497// }
498// });
499
500 Frame oneFrame = null;
501 if (!username.equals(Authenticator.ADMINACCOUNT)) {
502 // Load in and cache the profile frame using the personal key fetched from keystore.
503 // Reset the personal key once finished so that setting parsing can correctly set it.
504 FrameIO.ClearCache();
505 Text personalKeyText = KeyList.PersonalKey.generateText();
506 personalKeyText.setData(Base64.getEncoder().encodeToString(personalKey.getEncoded()));
507 KeyList.PersonalKey.setSetting(personalKeyText);
508 oneFrame = FrameIO.LoadProfile(username);
509 for (int i = 1; i <= FrameIO.getLastNumber(username); i++) {
510 Frame f = FrameIO.LoadFrame(oneFrame.getFramesetName() + i);
511 if (f.getData() != null && f.getData().contains("MultiuserCredentials")) {
512 Authenticator.CREDENTIALS_FRAME = f.getNumber();
513 }
514 }
515
516 // Parse the settings frame to update the settings datastructure.
517 Text fakeLink = new Text("settings");
518 fakeLink.setLink(oneFrame.getFramesetName() + "2");
519 Settings.parseSettings(fakeLink);
520
521 // Update default folders.
522 UserSettings.setupDefaultFolders();
523
524 // Check mail
525 MailBay.clear();
526 Authenticator.getInstance().loadMailDatabase();
527 Text keyItem = org.expeditee.settings.identity.secrets.KeyList.PrivateKey.get();
528 if (keyItem.getData() != null) {
529 String keyEncoded = keyItem.getData().get(0);
530 byte[] keyBytes = Base64.getDecoder().decode(keyEncoded);
531 PrivateKey key = KeyFactory.getInstance(AsymmetricAlgorithm).generatePrivate(new PKCS8EncodedKeySpec(keyBytes));
532 List<MailEntry> mailForLoggingInUser = Mail.getEntries(UserSettings.UserName.get(), key);
533 for (MailEntry mail: mailForLoggingInUser) {
534 MailBay.addMessage(mail.timestamp, mail.message, mail.message2, mail.options);
535 }
536 }
537 } else {
538 UserSettings.UserName.set(Authenticator.ADMINACCOUNT);
539 oneFrame = FrameIO.LoadFrame("multiuser1");
540 }
541
542 Collection<Item> usernameFields = getByData(FrameIO.LoadFrame(Constants.FRAME_MULTIUSER1), "txtUsername");
543 usernameFields.forEach(usernameField -> usernameField.setText(username));
544
545 Frame homeFrame = FrameIO.LoadFrame("home1");
546 DisplayController.setCurrentFrame(homeFrame == null ? oneFrame : homeFrame, false);
547 }
548
549 /*
550 * Function to share a specified frameset.
551 * Currently, this moves the frameset to the 'Shared By Me' directory and then relies on the user to use Google Drive functionality to share it appropriately.
552 */
553 private static void shareFrameset(Frame toShare) throws IOException {
554 File destinationDir = new File(FrameIO.SHARED_FRAMESETS_PATH + File.separator + toShare.getFramesetName());
555 File sourceDir = new File(toShare.getFramesetPath());
556
557 if (destinationDir.exists()) {
558 MessageBay.errorMessage("A frameset by this name already exists.");
559 return;
560 }
561
562 destinationDir.mkdir();
563 List<Path> files = Files.walk(sourceDir.toPath()).collect(Collectors.toList());
564 Files.move(files.get(0), destinationDir.toPath(), StandardCopyOption.ATOMIC_MOVE);
565
566 MessageBay.displayMessage("The frameset " + toShare.getFramesetName() + " has been moved to " + destinationDir + ". Google Drive functionality can now be used to share it with colleagues.");
567 }
568
569 private static void denyPasswordColleagueRelationship(String colleagueName) throws InvalidKeySpecException, NoSuchAlgorithmException, KeyStoreException, FileNotFoundException, CertificateException, ClassNotFoundException, IOException, SQLException {
570 String time = org.expeditee.stats.Formatter.getDateTime();
571 String sender = UserSettings.UserName.get();
572 String message = "You have received a reply from " + sender + " reguarding your request for assistance.";
573 String message2 = "Unfortunately " + sender + " has indicated that they are unable to help you with your potential password recovery.";
574 Map<String, String> options = new HashMap<String, String>();
575 options.put("Clear Preview Colleague Nominations", "AuthClearPWColleaguesNominated");
576 MailEntry mail = new MailEntry(time, sender, colleagueName, message, message2, options);
577 Mail.sendMail(mail, Authenticator.getInstance().getPublicKey(colleagueName), Paths.get(FrameIO.PROFILE_PATH).resolve(sender).resolve(sender + "-credentials"));
578 }
579
580 private static boolean submitPWColleagues(Map<AuthenticationTag, String> userData) throws InvalidKeySpecException, NoSuchAlgorithmException, KeyStoreException, FileNotFoundException, CertificateException, ClassNotFoundException, IOException, SQLException {
581 String colleagueOne = userData.get(AuthenticationTag.ColleagueOne);
582 String colleagueTwo = userData.get(AuthenticationTag.ColleagueTwo);
583 PublicKey colleagueOneKey = Authenticator.getInstance().getPublicKey(colleagueOne);
584 PublicKey colleagueTwoKey = Authenticator.getInstance().getPublicKey(colleagueTwo);
585 if (colleagueOneKey == null) {
586 MessageBay.errorMessage("Unable to get public key for colleague: " + colleagueOne);
587 return false;
588 } else if (colleagueTwoKey == null) {
589 MessageBay.errorMessage("Unable to get public key for colleague: " + colleagueTwo);
590 return false;
591 } else {
592 String time = org.expeditee.stats.Formatter.getDateTime();
593 String sender = userData.get(AuthenticationTag.Username);
594 String topic = "You have received a request for cooperation from your colleague " + sender;
595 String message = "Should " + sender + " forget their password, they would like your help recoverying it.";
596 Map<String, String> arguments = new HashMap<String, String>();
597 arguments.put("I agree to assist " + sender + " if they loose access to their account.", "AuthConfirmPasswordColleagueRelationship " + sender);
598 arguments.put("I wish to excuse myself from this responsibility.", "AuthDenyPasswordColleagueRelationship " + sender);
599 MailEntry mail = new MailEntry(time, sender, colleagueOne, topic, message, arguments);
600 Path outbox = Paths.get(FrameIO.PROFILE_PATH).resolve(sender).resolve(sender + "-credentials");
601 Mail.sendMail(mail, colleagueOneKey, outbox);
602 mail = new MailEntry(time, sender, colleagueTwo, topic, message, arguments);
603 Mail.sendMail(mail, colleagueTwoKey, outbox);
604 Authenticator.getInstance().markRequestedColleagues(UserSettings.UserName.get());
605 return true;
606 }
607 }
608
609
610 private static TextSetting constructTextSetting(String tooltip, String text, String data) {
611 return new TextSetting(tooltip, text) {
612 @Override
613 public Text generateText() {
614 Text t = new Text(text);
615 t.setData(data);
616 return t;
617 }
618 };
619 }
620
621 private static <T> GenericSetting<T> constructGenericSetting(Class<T> type, String tooltip, String name, T value, String frameset) {
622 return new GenericSetting<T>(type, tooltip, name, value) {
623 @Override
624 public Text generateRepresentation(String name, String frameset) {
625 Text t = new Text(name + ": " + value);
626 return t;
627 }
628 };
629 }
630
631 /*
632 * Changes the recorded password for a user in the key store.
633 */
634 private static void changePassword(final Map<AuthenticationTag, String> userdata) throws NoSuchAlgorithmException, KeyStoreException, FileNotFoundException, CertificateException, IOException, ClassNotFoundException, SQLException {
635 final String username = userdata.get(AuthenticationTag.Username);
636 final String password = userdata.get(AuthenticationTag.Password);
637 final String newpassword = userdata.get(AuthenticationTag.NewPassword);
638
639 final SecretKey key = Authenticator.getInstance().getSecretKey(username, password);
640 if (key == null) {
641 MessageBay.errorMessage("The username + existing password combination was incorrect.");
642 } else {
643 Authenticator.getInstance().putKey(username, newpassword, key);
644 MessageBay.displayMessage("Password changed successfully.");
645 }
646 }
647
648// // establish properties
649// final String from = "[email protected]";
650// final Properties properties = System.getProperties();
651//
652// properties.setProperty("mail.transport.protocol", "smtp");
653// properties.setProperty("mail.smtp.host", "smtp.gmail.com");
654// properties.setProperty("mail.smtp.port", "465");
655// properties.setProperty("mail.smtp.starttls.enable", "true");
656// properties.setProperty("mail.smtp.auth", "true");
657// properties.setProperty("mail.smtp.debug", "true");
658// properties.setProperty("mail.smtp.auth", "true");
659// properties.setProperty("mail.smtp.socketFactory.port", "465");
660// properties.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
661// properties.setProperty("mail.smtp.socketFactory.fallback", "false");
662//
663// final Session session = Session.getDefaultInstance(properties, new javax.mail.Authenticator() {
664// @Override
665// protected PasswordAuthentication getPasswordAuthentication() {
666// return new PasswordAuthentication("noreply.expeditee", "intergalacticnumber");
667// };
668// });
669
670// // construct email message
671// final MimeMessage message = new MimeMessage(session);
672// message.setFrom(new InternetAddress(from));
673// message.addRecipient(Message.RecipientType.TO, new InternetAddress(email));
674// message.setSubject("Expeditee Password Recovery");
675// message.setText(intergalacticNumber);
676//
677// // send email message
678// Transport.send(message);
679
680
681 public static void TickBox(final Text item) {
682 if (item.getBackgroundColor() != Colour.RED) {
683 item.setBackgroundColor(Colour.RED);
684 } else {
685 item.setBackgroundColor(Colour.GREEN);
686 }
687 }
688
689 /*
690 * Gets all items on a specified frame that contain the specified data.
691 */
692 public static Collection<Item> getByData(final Frame frame, final String data) {
693 final Collection<Item> allItems = frame.getAllItems();
694 allItems.removeIf(i -> i.getData() == null || !i.hasData(data));
695 return allItems;
696 }
697
698 public static Collection<Item> getByContent(final Frame frame, final String content) {
699 final Collection<Item> allItems = frame.getAllItems();
700 allItems.removeIf(i -> i.getText().compareTo(content) != 0);
701 return allItems;
702 }
703}
Note: See TracBrowser for help on using the repository browser.