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

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

On profile creation a new parameter has been introducted. By passing a map, the user is able to nominate settings frames for which to be notified of their construction.

The above functionalty has been used to programmatically establish the frame number for a users credentials frame.

On user account creation, the users credential frame is migrated to the <username>-credentials folder and a redirect is setup. Functionality for doing this has been generisised and placed in FrameIO.

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