experimenting with sessions and stuff like that.
Changes: + Login Panel + Some Kernel Booting stuff
This commit is contained in:
@@ -1,103 +1,9 @@
|
||||
package com.rdesk;
|
||||
|
||||
import com.rdesk.applications.entertainment.comic.Xkcd;
|
||||
import com.rdesk.applications.productivity.Calculator;
|
||||
import com.rdesk.applications.productivity.browsing.TabbedBrowser;
|
||||
import com.rdesk.applications.productivity.code.CodeDesk;
|
||||
import com.rdesk.applications.system.Exit;
|
||||
import com.rdesk.applications.productivity.Notes;
|
||||
import com.rdesk.applications.system.TaskManager;
|
||||
import com.rdesk.applications.system.filehaj.FileExplorerApp;
|
||||
import com.rdesk.applications.system.rsys.KbChanger;
|
||||
import com.rdesk.kernel.*;
|
||||
import com.rdesk.kernel.launcher.AppLauncher;
|
||||
|
||||
import javax.swing.*;
|
||||
import com.rdesk.applications.system.login.Login;
|
||||
|
||||
public class Main {
|
||||
|
||||
private static final boolean RUN_IN_FS = false;
|
||||
private static final boolean USE_SYSDEFAULT_LAF = false;
|
||||
private static final boolean USE_FLATLAF = false;
|
||||
private static final boolean loadSettingsKernelFlag = true;
|
||||
|
||||
public static void main(String[] args) {
|
||||
SwingUtilities.invokeLater(Main::boot);
|
||||
}
|
||||
|
||||
private static void boot() {
|
||||
Kernel kernel = Kernel.get();
|
||||
kernel.initSettings(loadSettingsKernelFlag);
|
||||
kernel.boot();
|
||||
JFrame frame = new JFrame("rDesk");
|
||||
|
||||
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
|
||||
frame.addWindowListener(new java.awt.event.WindowAdapter() {
|
||||
@Override
|
||||
public void windowClosing(java.awt.event.WindowEvent e) {
|
||||
kernel.shutdown();
|
||||
}
|
||||
});
|
||||
|
||||
if (USE_FLATLAF) {
|
||||
try {
|
||||
UIManager.setLookAndFeel(
|
||||
"com.formdev.flatlaf.themes.FlatMacLightLaf"
|
||||
);
|
||||
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
|
||||
JOptionPane.showMessageDialog(
|
||||
null,
|
||||
ex.getMessage() + "@USE_FLATLAF"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (USE_SYSDEFAULT_LAF) {
|
||||
try {
|
||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
|
||||
JOptionPane.showMessageDialog(
|
||||
null,
|
||||
ex.getMessage() + "@USE_SYSDEFAULT_LAF"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (RUN_IN_FS) {
|
||||
frame.setUndecorated(true);
|
||||
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
|
||||
} else {
|
||||
frame.setSize(1200, 800);
|
||||
frame.setLocationRelativeTo(null);
|
||||
}
|
||||
|
||||
JDesktopPane desktop = new JDesktopPane();
|
||||
kernel.windows().attachDesktop(desktop);
|
||||
|
||||
AppLauncher launcher = new AppLauncher(kernel);
|
||||
|
||||
registerSystemApps(launcher);
|
||||
|
||||
JSplitPane split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, launcher, desktop);
|
||||
split.setDividerSize(0);
|
||||
split.setEnabled(false);
|
||||
|
||||
frame.setContentPane(split);
|
||||
frame.setVisible(true);
|
||||
}
|
||||
|
||||
private static void registerSystemApps(AppLauncher launcher) {
|
||||
// productivity
|
||||
launcher.addApp(new Notes(), "Productivity");
|
||||
launcher.addApp(new TabbedBrowser(), "Productivity");
|
||||
launcher.addApp(new CodeDesk(), "Productivity");
|
||||
launcher.addApp(new Calculator(), "Productivity");
|
||||
// entertainment
|
||||
launcher.addApp(new Xkcd(), "Entertainment");
|
||||
// System apps
|
||||
launcher.addApp(new Exit(), "System");
|
||||
launcher.addApp(new TaskManager(), "System");
|
||||
launcher.addApp(new FileExplorerApp(), "System");
|
||||
launcher.addApp(new KbChanger(), "System");
|
||||
Login.main(args);
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,13 @@
|
||||
package com.rdesk.applications.system;
|
||||
|
||||
import com.rdesk.applications.system.login.Login;
|
||||
import com.rdesk.kernel.DesktopApp;
|
||||
import com.rdesk.kernel.Kernel;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.io.IOException;
|
||||
import java.awt.Window;
|
||||
|
||||
public class Exit implements DesktopApp {
|
||||
|
||||
@@ -22,7 +24,7 @@ public class Exit implements DesktopApp {
|
||||
@Override
|
||||
public JInternalFrame createWindow(Kernel kernel) {
|
||||
JInternalFrame frame = new JInternalFrame("System Controls", true, true);
|
||||
frame.setSize(350, 180);
|
||||
frame.setSize(420, 240);
|
||||
frame.setResizable(false);
|
||||
|
||||
JPanel mainPanel = new JPanel(new GridBagLayout());
|
||||
@@ -30,7 +32,7 @@ public class Exit implements DesktopApp {
|
||||
GridBagConstraints gbc = new GridBagConstraints();
|
||||
gbc.gridwidth = GridBagConstraints.REMAINDER;
|
||||
gbc.fill = GridBagConstraints.HORIZONTAL;
|
||||
gbc.insets = new Insets(5, 5, 5, 5);
|
||||
gbc.insets = new Insets(6, 6, 6, 6);
|
||||
|
||||
JLabel label = new JLabel("Choose an action:");
|
||||
label.setFont(label.getFont().deriveFont(Font.BOLD));
|
||||
@@ -38,8 +40,11 @@ public class Exit implements DesktopApp {
|
||||
|
||||
JButton shutdownButton = new JButton("Shutdown rDesk");
|
||||
JButton shutdownOS = new JButton("Shutdown Host OS");
|
||||
JButton logoffButton = new JButton("Log off");
|
||||
|
||||
shutdownButton.setFocusPainted(false);
|
||||
shutdownButton.addActionListener(e -> confirmAndShutdown(kernel, frame));
|
||||
|
||||
shutdownOS.setFocusPainted(false);
|
||||
shutdownOS.addActionListener(e -> {
|
||||
try {
|
||||
@@ -48,8 +53,38 @@ public class Exit implements DesktopApp {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
});
|
||||
|
||||
logoffButton.setFocusPainted(false);
|
||||
|
||||
logoffButton.addActionListener(e -> {
|
||||
int choice = JOptionPane.showConfirmDialog(
|
||||
frame,
|
||||
"Log off and return to the login screen?"
|
||||
+ "This will end all running Tasks!",
|
||||
"Confirm Log off",
|
||||
JOptionPane.YES_NO_OPTION,
|
||||
JOptionPane.WARNING_MESSAGE
|
||||
);
|
||||
if (choice != JOptionPane.YES_OPTION) return;
|
||||
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
try {
|
||||
Login.main(null);
|
||||
} catch (Exception ex) {
|
||||
JOptionPane.showMessageDialog(frame,
|
||||
"Failed to launch login screen: " + ex.getMessage(),
|
||||
"Error",
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
return;
|
||||
}
|
||||
|
||||
kernel.logoff();
|
||||
});
|
||||
});
|
||||
|
||||
mainPanel.add(shutdownButton, gbc);
|
||||
mainPanel.add(shutdownOS, gbc);
|
||||
mainPanel.add(logoffButton, gbc);
|
||||
|
||||
JButton cancelButton = new JButton("Cancel");
|
||||
cancelButton.setFocusPainted(false);
|
||||
@@ -93,7 +128,7 @@ public class Exit implements DesktopApp {
|
||||
|
||||
if (choice == JOptionPane.YES_OPTION) {
|
||||
frame.dispose();
|
||||
performShutdownCmd(); // cause else the call wouldnt be called
|
||||
performShutdownCmd();
|
||||
kernel.shutdown();
|
||||
}
|
||||
}
|
||||
@@ -107,7 +142,7 @@ public class Exit implements DesktopApp {
|
||||
JOptionPane.WARNING_MESSAGE
|
||||
);
|
||||
if (choice == JOptionPane.YES_OPTION) {
|
||||
frame.dispose(); // close the confirmation window first
|
||||
frame.dispose();
|
||||
kernel.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
|
||||
package com.rdesk.applications.system.login;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
import javax.crypto.SecretKeyFactory;
|
||||
import javax.crypto.spec.PBEKeySpec;
|
||||
import java.awt.Window;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Base64;
|
||||
import java.util.List;
|
||||
|
||||
public class Handler {
|
||||
private static final String FILENAME = System.getProperty("user.home") + File.separator + "rsys_passwdstore.json";
|
||||
private static final SecureRandom RNG = new SecureRandom();
|
||||
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
|
||||
private static final int SALT_LEN = 16;
|
||||
private static final int KEY_LEN = 256; // bits
|
||||
private static final int ITERATIONS = 200_000;
|
||||
private static final String ALGO = "PBKDF2WithHmacSHA256";
|
||||
|
||||
|
||||
|
||||
public static boolean storeExists() {
|
||||
return new File(FILENAME).exists();
|
||||
}
|
||||
|
||||
public static UserRecord load() throws Exception {
|
||||
File f = new File(FILENAME);
|
||||
if (!f.exists()) return null;
|
||||
try (FileReader fr = new FileReader(f)) {
|
||||
return GSON.fromJson(fr, UserRecord.class);
|
||||
}
|
||||
}
|
||||
|
||||
public static void save(UserRecord u) throws Exception {
|
||||
try (FileWriter fw = new FileWriter(FILENAME)) {
|
||||
GSON.toJson(u, fw);
|
||||
}
|
||||
}
|
||||
|
||||
public static UserRecord createUser(String username, char[] password) throws Exception {
|
||||
byte[] salt = new byte[SALT_LEN];
|
||||
RNG.nextBytes(salt);
|
||||
byte[] hash = pbkdf2(password, salt, ITERATIONS, KEY_LEN);
|
||||
UserRecord u = new UserRecord();
|
||||
u.username = username;
|
||||
u.saltB64 = Base64.getEncoder().encodeToString(salt);
|
||||
u.hashB64 = Base64.getEncoder().encodeToString(hash);
|
||||
u.iterations = ITERATIONS;
|
||||
return u;
|
||||
}
|
||||
|
||||
public static boolean verifyPassword(char[] password, UserRecord stored) throws Exception {
|
||||
byte[] salt = Base64.getDecoder().decode(stored.saltB64);
|
||||
byte[] expected = Base64.getDecoder().decode(stored.hashB64);
|
||||
byte[] computed = pbkdf2(password, salt, stored.iterations, expected.length * 8);
|
||||
return slowEquals(expected, computed);
|
||||
}
|
||||
|
||||
public static boolean verifyAndClose(Window window, char[] password, UserRecord stored) throws Exception {
|
||||
try {
|
||||
boolean ok = verifyPassword(password, stored);
|
||||
if (ok && window != null) {
|
||||
window.dispose();
|
||||
}
|
||||
return ok;
|
||||
} finally {
|
||||
clearPassword(password);
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] pbkdf2(char[] password, byte[] salt, int iterations, int keyLengthBits) throws Exception {
|
||||
PBEKeySpec spec = new PBEKeySpec(password, salt, iterations, keyLengthBits);
|
||||
SecretKeyFactory skf = SecretKeyFactory.getInstance(ALGO);
|
||||
return skf.generateSecret(spec).getEncoded();
|
||||
}
|
||||
|
||||
private static boolean slowEquals(byte[] a, byte[] b) {
|
||||
if (a == null || b == null || a.length != b.length) return false;
|
||||
int diff = 0;
|
||||
for (int i = 0; i < a.length; i++) diff |= a[i] ^ b[i];
|
||||
return diff == 0;
|
||||
}
|
||||
|
||||
public static void clearPassword(char[] p) {
|
||||
if (p == null) return;
|
||||
Arrays.fill(p, (char) 0);
|
||||
}
|
||||
|
||||
public static String[] listUsers() {
|
||||
File f = new File(FILENAME);
|
||||
if (!f.exists()) return new String[0];
|
||||
try (FileReader fr = new FileReader(f)) {
|
||||
JsonElement root = JsonParser.parseReader(fr);
|
||||
List<String> users = new ArrayList<>();
|
||||
if (root.isJsonArray()) {
|
||||
JsonArray arr = root.getAsJsonArray();
|
||||
for (JsonElement el : arr) {
|
||||
try {
|
||||
UserRecord ur = GSON.fromJson(el, UserRecord.class);
|
||||
if (ur != null && ur.username != null) users.add(ur.username);
|
||||
} catch (Throwable ignore) { /* skip malformed entry */ }
|
||||
}
|
||||
} else if (root.isJsonObject()) {
|
||||
try {
|
||||
UserRecord ur = GSON.fromJson(root, UserRecord.class);
|
||||
if (ur != null && ur.username != null) users.add(ur.username);
|
||||
} catch (Throwable ignore) { /* malformed object -> no users */ }
|
||||
}
|
||||
return users.toArray(new String[0]);
|
||||
} catch (Exception e) {
|
||||
return new String[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,267 @@
|
||||
package com.rdesk.applications.system.login;
|
||||
|
||||
import com.rdesk.kernel.BootMgr;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class Login {
|
||||
private JFrame frame;
|
||||
private JComboBox<String> userCombo;
|
||||
private JTextField userFieldFallback;
|
||||
private JPasswordField passField;
|
||||
private JLabel statusLabel;
|
||||
private UserRecord stored;
|
||||
private JButton loginBtn;
|
||||
private JButton closeBtn;
|
||||
|
||||
public static void main(String[] args) {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
try {
|
||||
new Login().start();
|
||||
} catch (Exception e) {
|
||||
JOptionPane.showMessageDialog(null, e);
|
||||
System.exit(1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void start() throws Exception {
|
||||
log("start(): checking store existence");
|
||||
if (!Handler.storeExists()) {
|
||||
showCreateUserDialog();
|
||||
}
|
||||
stored = Handler.load();
|
||||
log("start(): loaded user record: " + (stored != null ? stored.username : "null"));
|
||||
buildAndShowGui();
|
||||
}
|
||||
|
||||
private void buildAndShowGui() {
|
||||
log("buildAndShowGui(): building GUI");
|
||||
frame = new JFrame("rDesk Login");
|
||||
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
frame.setResizable(false);
|
||||
|
||||
Image icon = createImageFromSwingIcon(UIManager.getIcon("FileView.computerIcon"));
|
||||
if (icon != null) frame.setIconImage(icon);
|
||||
|
||||
JPanel panel = new JPanel(new GridBagLayout());
|
||||
GridBagConstraints c = new GridBagConstraints();
|
||||
c.insets = new Insets(6, 6, 6, 6);
|
||||
c.anchor = GridBagConstraints.WEST;
|
||||
c.fill = GridBagConstraints.HORIZONTAL;
|
||||
|
||||
int row = 0;
|
||||
|
||||
if (icon != null) {
|
||||
JLabel iconLabel = new JLabel(new ImageIcon(icon.getScaledInstance(64, 64, Image.SCALE_SMOOTH)));
|
||||
GridBagConstraints ic = (GridBagConstraints) c.clone();
|
||||
ic.gridx = 0;
|
||||
ic.gridy = row;
|
||||
ic.gridheight = 2;
|
||||
ic.anchor = GridBagConstraints.CENTER;
|
||||
panel.add(iconLabel, ic);
|
||||
}
|
||||
|
||||
int colOffset = (icon != null) ? 1 : 0;
|
||||
|
||||
c.gridx = colOffset;
|
||||
c.gridy = row;
|
||||
c.gridwidth = 1;
|
||||
panel.add(new JLabel("Username:"), c);
|
||||
|
||||
c.gridx = colOffset + 1;
|
||||
c.gridy = row++;
|
||||
c.weightx = 1.0;
|
||||
String[] users = fetchUserList();
|
||||
if (users.length > 0) {
|
||||
userCombo = new JComboBox<>(users);
|
||||
userCombo.setEditable(false);
|
||||
userCombo.setPreferredSize(new Dimension(160, 24));
|
||||
panel.add(userCombo, c);
|
||||
} else {
|
||||
userFieldFallback = new JTextField(16);
|
||||
userFieldFallback.setPreferredSize(new Dimension(160, 24));
|
||||
panel.add(userFieldFallback, c);
|
||||
}
|
||||
|
||||
c.gridx = colOffset;
|
||||
c.gridy = row;
|
||||
c.weightx = 0;
|
||||
panel.add(new JLabel("Password:"), c);
|
||||
|
||||
c.gridx = colOffset + 1;
|
||||
c.gridy = row++;
|
||||
c.weightx = 1.0;
|
||||
passField = new JPasswordField(16);
|
||||
passField.setPreferredSize(new Dimension(160, 24));
|
||||
panel.add(passField, c);
|
||||
|
||||
closeBtn = new JButton("Close");
|
||||
closeBtn.addActionListener(e -> frame.dispose());
|
||||
loginBtn = new JButton("Login");
|
||||
loginBtn.addActionListener(e -> onLogin());
|
||||
|
||||
c.gridx = colOffset;
|
||||
c.gridy = row;
|
||||
c.gridwidth = 1;
|
||||
c.weightx = 0.5;
|
||||
c.fill = GridBagConstraints.HORIZONTAL;
|
||||
panel.add(closeBtn, c);
|
||||
|
||||
c.gridx = colOffset + 1;
|
||||
c.gridy = row++;
|
||||
c.weightx = 0.5;
|
||||
panel.add(loginBtn, c);
|
||||
|
||||
statusLabel = new JLabel(" ");
|
||||
statusLabel.setForeground(Color.BLUE);
|
||||
c.gridx = colOffset;
|
||||
c.gridy = row;
|
||||
c.gridwidth = 2;
|
||||
c.weightx = 1.0;
|
||||
c.fill = GridBagConstraints.HORIZONTAL;
|
||||
panel.add(statusLabel, c);
|
||||
|
||||
frame.getContentPane().add(panel);
|
||||
frame.getRootPane().setDefaultButton(loginBtn);
|
||||
|
||||
passField.addActionListener(e -> onLogin());
|
||||
if (userFieldFallback != null) userFieldFallback.addActionListener(e -> onLogin());
|
||||
if (userCombo != null) {
|
||||
userCombo.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke("ENTER"), "login");
|
||||
userCombo.getActionMap().put("login", new AbstractAction() {
|
||||
@Override public void actionPerformed(ActionEvent e) { onLogin(); }
|
||||
});
|
||||
}
|
||||
|
||||
frame.pack();
|
||||
Dimension total = frame.getContentPane().getSize();
|
||||
int gap = 12;
|
||||
int buttonWidth = Math.max(90, (total.width - gap) / 2);
|
||||
closeBtn.setPreferredSize(new Dimension(buttonWidth, 28));
|
||||
loginBtn.setPreferredSize(new Dimension(buttonWidth, 28));
|
||||
frame.pack();
|
||||
|
||||
frame.setLocationRelativeTo(null);
|
||||
frame.setVisible(true);
|
||||
log("buildAndShowGui(): GUI visible");
|
||||
}
|
||||
|
||||
private Image createImageFromSwingIcon(Icon icon) {
|
||||
if (icon == null) return null;
|
||||
int w = Math.max(1, icon.getIconWidth());
|
||||
int h = Math.max(1, icon.getIconHeight());
|
||||
BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
|
||||
Graphics2D g = img.createGraphics();
|
||||
try {
|
||||
icon.paintIcon(null, g, 0, 0);
|
||||
} finally {
|
||||
g.dispose();
|
||||
}
|
||||
return img;
|
||||
}
|
||||
|
||||
private void onLogin() {
|
||||
String userAttempt = (userCombo != null)
|
||||
? String.valueOf(userCombo.getSelectedItem()).trim()
|
||||
: userFieldFallback.getText().trim();
|
||||
char[] passAttempt = passField.getPassword();
|
||||
|
||||
log("onLogin(): attempt for user='" + userAttempt + "'");
|
||||
|
||||
if (stored == null) {
|
||||
statusLabel.setText("No user record found.");
|
||||
Handler.clearPassword(passAttempt);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!stored.username.equals(userAttempt)) {
|
||||
statusLabel.setText("Invalid username or password.");
|
||||
Handler.clearPassword(passAttempt);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
boolean ok = Handler.verifyAndClose(frame, passAttempt, stored);
|
||||
if (ok) {
|
||||
log("onLogin(): authentication successful for user='" + userAttempt + "'");
|
||||
statusLabel.setText(" ");
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
new SwingWorker<Void, Void>() {
|
||||
@Override protected Void doInBackground() {
|
||||
try {
|
||||
BootMgr.launchOrShow();
|
||||
log("[Login]: BootManager.launchOrShow() completed");
|
||||
} catch (Exception e) {
|
||||
log("onLogin(): BootManager error: " + e.getMessage());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}.execute();
|
||||
});
|
||||
} else {
|
||||
statusLabel.setText("Invalid username or password.");
|
||||
log("onLogin(): password verification failed for user='" + userAttempt + "'");
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
statusLabel.setText("Error during verification.");
|
||||
log("onLogin(): exception during verification: " + ex.getMessage());
|
||||
} finally {
|
||||
Handler.clearPassword(passAttempt);
|
||||
passField.setText("");
|
||||
}
|
||||
}
|
||||
|
||||
private void showCreateUserDialog() throws Exception {
|
||||
log("showCreateUserDialog(): creating user dialog");
|
||||
JPanel p = new JPanel(new GridLayout(3,2,6,6));
|
||||
JTextField user = new JTextField(16);
|
||||
JPasswordField pass = new JPasswordField(16);
|
||||
JPasswordField pass2 = new JPasswordField(16);
|
||||
p.add(new JLabel("Username:")); p.add(user);
|
||||
p.add(new JLabel("Password:")); p.add(pass);
|
||||
p.add(new JLabel("Confirm:")); p.add(pass2);
|
||||
|
||||
int res = JOptionPane.showConfirmDialog(null, p, "Create User", JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE);
|
||||
if (res != JOptionPane.OK_OPTION) {
|
||||
log("showCreateUserDialog(): user cancelled creation, exiting");
|
||||
System.exit(0);
|
||||
}
|
||||
if (!String.valueOf(pass.getPassword()).equals(String.valueOf(pass2.getPassword()))) {
|
||||
JOptionPane.showMessageDialog(null, "Passwords do not match.", "Error", JOptionPane.ERROR_MESSAGE);
|
||||
log("showCreateUserDialog(): passwords did not match");
|
||||
showCreateUserDialog();
|
||||
return;
|
||||
}
|
||||
UserRecord u = Handler.createUser(user.getText().trim(), pass.getPassword());
|
||||
Handler.save(u);
|
||||
log("showCreateUserDialog(): created and saved user '" + u.username + "'");
|
||||
JOptionPane.showMessageDialog(null, "User created.", "Success", JOptionPane.INFORMATION_MESSAGE);
|
||||
}
|
||||
|
||||
private String[] fetchUserList() {
|
||||
try {
|
||||
log("fetchUserList(): attempting to retrieve user list from Handler");
|
||||
String[] users = Handler.listUsers();
|
||||
if (users == null || users.length == 0) {
|
||||
if (stored != null) {
|
||||
return new String[]{stored.username};
|
||||
}
|
||||
return new String[0];
|
||||
}
|
||||
return users;
|
||||
} catch (Exception t) {
|
||||
if (stored != null) return new String[]{stored.username};
|
||||
return new String[0];
|
||||
}
|
||||
}
|
||||
|
||||
private void log(String msg) {
|
||||
System.out.println("[Login]: " + msg);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.rdesk.applications.system.login;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
public class UserRecord {
|
||||
@SerializedName("username") public String username;
|
||||
@SerializedName("salt_b64") public String saltB64;
|
||||
@SerializedName("hash_b64") public String hashB64;
|
||||
@SerializedName("iterations") public int iterations;
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.rdesk.kernel;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
public final class BootMgr {
|
||||
private static JFrame desktopFrame;
|
||||
private BootMgr() {}
|
||||
|
||||
public static synchronized void launchOrShow() {
|
||||
if (desktopFrame == null) {
|
||||
JFrame f = BootProc.boot();
|
||||
if (f != null) desktopFrame = f;
|
||||
else {
|
||||
desktopFrame = new JFrame();
|
||||
desktopFrame.setContentPane(f);
|
||||
desktopFrame.pack();
|
||||
}
|
||||
desktopFrame.setVisible(true);
|
||||
desktopFrame.toFront();
|
||||
} else {
|
||||
if (!desktopFrame.isVisible()) desktopFrame.setVisible(true);
|
||||
desktopFrame.toFront();
|
||||
desktopFrame.requestFocus();
|
||||
}
|
||||
}
|
||||
|
||||
public static synchronized void hideDesktopOnLogout() {
|
||||
if (desktopFrame != null) {
|
||||
desktopFrame.setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
public static synchronized void disposeDesktop() {
|
||||
if (desktopFrame != null) {
|
||||
desktopFrame.dispose();
|
||||
desktopFrame = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
package com.rdesk.kernel;
|
||||
|
||||
import com.rdesk.applications.entertainment.comic.Xkcd;
|
||||
import com.rdesk.applications.productivity.Calculator;
|
||||
import com.rdesk.applications.productivity.Notes;
|
||||
import com.rdesk.applications.productivity.browsing.TabbedBrowser;
|
||||
import com.rdesk.applications.productivity.code.CodeDesk;
|
||||
import com.rdesk.applications.system.Exit;
|
||||
import com.rdesk.applications.system.TaskManager;
|
||||
import com.rdesk.applications.system.filehaj.FileExplorerApp;
|
||||
import com.rdesk.applications.system.rsys.KbChanger;
|
||||
import com.rdesk.kernel.launcher.AppLauncher;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
public class BootProc {
|
||||
private static final boolean RUN_IN_FS = true;
|
||||
private static final boolean USE_SYSDEFAULT_LAF = false;
|
||||
private static final boolean USE_FLATLAF = false;
|
||||
private static final boolean loadSettingsKernelFlag = true;
|
||||
|
||||
private static JFrame mainFrame;
|
||||
private static JDesktopPane desktopPane;
|
||||
|
||||
public static synchronized JFrame boot() {
|
||||
if (mainFrame != null) {
|
||||
if (!mainFrame.isVisible()) mainFrame.setVisible(true);
|
||||
mainFrame.toFront();
|
||||
mainFrame.requestFocus();
|
||||
return mainFrame;
|
||||
}
|
||||
|
||||
Kernel kernel = Kernel.get();
|
||||
kernel.initSettings(loadSettingsKernelFlag);
|
||||
kernel.boot();
|
||||
|
||||
mainFrame = new JFrame("rDesk");
|
||||
mainFrame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
|
||||
mainFrame.addWindowListener(new java.awt.event.WindowAdapter() {
|
||||
@Override
|
||||
public void windowClosing(java.awt.event.WindowEvent e) {
|
||||
kernel.shutdown();
|
||||
}
|
||||
});
|
||||
|
||||
if (USE_FLATLAF) {
|
||||
try {
|
||||
UIManager.setLookAndFeel("com.formdev.flatlaf.themes.FlatMacLightLaf");
|
||||
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
|
||||
JOptionPane.showMessageDialog(null, ex.getMessage() + "@USE_FLATLAF");
|
||||
}
|
||||
}
|
||||
|
||||
if (USE_SYSDEFAULT_LAF) {
|
||||
try {
|
||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
|
||||
JOptionPane.showMessageDialog(null, ex.getMessage() + "@USE_SYSDEFAULT_LAF");
|
||||
}
|
||||
}
|
||||
|
||||
if (RUN_IN_FS) {
|
||||
mainFrame.setUndecorated(true);
|
||||
mainFrame.setExtendedState(JFrame.MAXIMIZED_BOTH);
|
||||
} else {
|
||||
mainFrame.setSize(1200, 800);
|
||||
mainFrame.setLocationRelativeTo(null);
|
||||
}
|
||||
|
||||
desktopPane = new JDesktopPane();
|
||||
kernel.windows().attachDesktop(desktopPane);
|
||||
kernel.attachFrame(mainFrame);
|
||||
|
||||
AppLauncher launcher = new AppLauncher(kernel);
|
||||
registerSystemApps(launcher);
|
||||
|
||||
JSplitPane split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, launcher, desktopPane);
|
||||
split.setDividerSize(0);
|
||||
split.setEnabled(false);
|
||||
|
||||
mainFrame.setContentPane(split);
|
||||
mainFrame.setVisible(true);
|
||||
|
||||
return mainFrame;
|
||||
}
|
||||
|
||||
public static synchronized JFrame getMainFrame() {
|
||||
return mainFrame;
|
||||
}
|
||||
|
||||
public static synchronized JDesktopPane getDesktopPane() {
|
||||
return desktopPane;
|
||||
}
|
||||
|
||||
private static void registerSystemApps(AppLauncher launcher) {
|
||||
// productivity
|
||||
launcher.addApp(new Notes(), "Productivity");
|
||||
launcher.addApp(new TabbedBrowser(), "Productivity");
|
||||
launcher.addApp(new CodeDesk(), "Productivity");
|
||||
launcher.addApp(new Calculator(), "Productivity");
|
||||
// entertainment
|
||||
launcher.addApp(new Xkcd(), "Entertainment");
|
||||
// System apps
|
||||
launcher.addApp(new Exit(), "System");
|
||||
launcher.addApp(new TaskManager(), "System");
|
||||
launcher.addApp(new FileExplorerApp(), "System");
|
||||
launcher.addApp(new KbChanger(), "System");
|
||||
}
|
||||
}
|
||||
@@ -64,6 +64,14 @@ public class Kernel {
|
||||
this.desktopFrame = frame;
|
||||
}
|
||||
|
||||
|
||||
public void logoff() {
|
||||
if (running) SwingUtilities.invokeLater(() -> {
|
||||
desktopFrame.setVisible(false);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public void shutdown() {
|
||||
if (!running) return;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user