forked from tools/josh
Move current user to environment variable
This commit is contained in:
parent
540a4f4ebe
commit
8e9747c5fe
|
@ -4,7 +4,7 @@ import {Directory, File, FileSystem, Path} from "./FileSystem"
|
||||||
import {IllegalStateError} from "./Shared";
|
import {IllegalStateError} from "./Shared";
|
||||||
import {Environment, InputArgs} from "./Shell";
|
import {Environment, InputArgs} from "./Shell";
|
||||||
import {EscapeCharacters} from "./Terminal";
|
import {EscapeCharacters} from "./Terminal";
|
||||||
import {UserSession} from "./UserSession";
|
import {UserList} from "./UserList";
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -18,7 +18,7 @@ export class Commands {
|
||||||
/**
|
/**
|
||||||
* The user session describing the user that executes commands.
|
* The user session describing the user that executes commands.
|
||||||
*/
|
*/
|
||||||
private readonly userSession: UserSession;
|
private readonly userSession: UserList;
|
||||||
/**
|
/**
|
||||||
* The file system to interact with.
|
* The file system to interact with.
|
||||||
*/
|
*/
|
||||||
|
@ -36,7 +36,7 @@ export class Commands {
|
||||||
* @param userSession the user session describing the user that executes commands
|
* @param userSession the user session describing the user that executes commands
|
||||||
* @param fileSystem the file system to interact with
|
* @param fileSystem the file system to interact with
|
||||||
*/
|
*/
|
||||||
constructor(environment: Environment, userSession: UserSession, fileSystem: FileSystem) {
|
constructor(environment: Environment, userSession: UserList, fileSystem: FileSystem) {
|
||||||
this.environment = environment;
|
this.environment = environment;
|
||||||
this.userSession = userSession;
|
this.userSession = userSession;
|
||||||
this.fileSystem = fileSystem;
|
this.fileSystem = fileSystem;
|
||||||
|
@ -225,8 +225,6 @@ export class Commands {
|
||||||
execute(input: InputArgs): string {
|
execute(input: InputArgs): string {
|
||||||
if (input.command === "factory-reset") {
|
if (input.command === "factory-reset") {
|
||||||
Cookies.remove("files");
|
Cookies.remove("files");
|
||||||
Cookies.remove("cwd");
|
|
||||||
Cookies.remove("user");
|
|
||||||
Cookies.remove("env");
|
Cookies.remove("env");
|
||||||
location.reload();
|
location.reload();
|
||||||
throw new Error("Goodbye");
|
throw new Error("Goodbye");
|
||||||
|
@ -324,7 +322,7 @@ export class Commands {
|
||||||
}
|
}
|
||||||
|
|
||||||
private exit(): string {
|
private exit(): string {
|
||||||
this.userSession.logOut();
|
this.environment["user"].value = "";
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -471,8 +469,8 @@ export class Commands {
|
||||||
}
|
}
|
||||||
|
|
||||||
private poweroff(): string {
|
private poweroff(): string {
|
||||||
const user = this.userSession.currentUser;
|
const userName = this.environment["user"].value;
|
||||||
if (user === undefined)
|
if (userName === "")
|
||||||
throw new IllegalStateError("Cannot execute `poweroff` while not logged in.");
|
throw new IllegalStateError("Cannot execute `poweroff` while not logged in.");
|
||||||
|
|
||||||
Cookies.set("poweroff", "true", {
|
Cookies.set("poweroff", "true", {
|
||||||
|
@ -484,7 +482,7 @@ export class Commands {
|
||||||
return "" +
|
return "" +
|
||||||
`Shutdown NOW!
|
`Shutdown NOW!
|
||||||
|
|
||||||
*** FINAL System shutdown message from ${user.name}@fwdekker.com ***
|
*** FINAL System shutdown message from ${userName}@fwdekker.com ***
|
||||||
|
|
||||||
System going down IMMEDIATELY
|
System going down IMMEDIATELY
|
||||||
|
|
||||||
|
@ -563,7 +561,7 @@ export class Commands {
|
||||||
}
|
}
|
||||||
|
|
||||||
private whoami(): string {
|
private whoami(): string {
|
||||||
const user = this.userSession.currentUser;
|
const user = this.userSession.get(this.environment["user"].value);
|
||||||
if (user === undefined)
|
if (user === undefined)
|
||||||
throw new IllegalStateError("Cannot execute `whoami` while not logged in.");
|
throw new IllegalStateError("Cannot execute `whoami` while not logged in.");
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,6 @@ addOnLoad(() => {
|
||||||
window.execute = (command: string) => window.terminal.processInput(command);
|
window.execute = (command: string) => window.terminal.processInput(command);
|
||||||
|
|
||||||
// @ts-ignore: Ugly hack to execute it anyway
|
// @ts-ignore: Ugly hack to execute it anyway
|
||||||
if (window.terminal.shell.userSession.isLoggedIn)
|
if (window.terminal.shell.environment["user"].value !== "")
|
||||||
window.terminal.processInput("ls");
|
window.terminal.processInput("ls");
|
||||||
});
|
});
|
||||||
|
|
|
@ -3,7 +3,7 @@ import {Commands} from "./Commands";
|
||||||
import {Directory, File, FileSystem, Node, Path} from "./FileSystem";
|
import {Directory, File, FileSystem, Node, Path} from "./FileSystem";
|
||||||
import {asciiHeaderHtml, IllegalStateError, stripHtmlTags} from "./Shared";
|
import {asciiHeaderHtml, IllegalStateError, stripHtmlTags} from "./Shared";
|
||||||
import {EscapeCharacters, InputHistory} from "./Terminal";
|
import {EscapeCharacters, InputHistory} from "./Terminal";
|
||||||
import {UserSession} from "./UserSession";
|
import {UserList} from "./UserList";
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -21,7 +21,7 @@ export class Shell {
|
||||||
/**
|
/**
|
||||||
* The user session describing the user that interacts with the shell.
|
* The user session describing the user that interacts with the shell.
|
||||||
*/
|
*/
|
||||||
private readonly userSession: UserSession;
|
private readonly userList: UserList;
|
||||||
/**
|
/**
|
||||||
* The file system.
|
* The file system.
|
||||||
*/
|
*/
|
||||||
|
@ -45,46 +45,12 @@ export class Shell {
|
||||||
*/
|
*/
|
||||||
constructor(inputHistory: InputHistory) {
|
constructor(inputHistory: InputHistory) {
|
||||||
this.inputHistory = inputHistory;
|
this.inputHistory = inputHistory;
|
||||||
|
this.userList = new UserList();
|
||||||
|
this.fileSystem = Shell.loadFileSystem();
|
||||||
|
this.environment = Shell.loadEnvironment(this.fileSystem, this.userList);
|
||||||
|
this.commands = new Commands(this.environment, this.userList, this.fileSystem);
|
||||||
|
|
||||||
// Read user from cookie
|
this.saveState();
|
||||||
const user = Cookies.get("user");
|
|
||||||
if (user === "")
|
|
||||||
this.userSession = new UserSession();
|
|
||||||
else if (user === undefined || !UserSession.userExists(user))
|
|
||||||
this.userSession = new UserSession("felix");
|
|
||||||
else
|
|
||||||
this.userSession = new UserSession(user);
|
|
||||||
|
|
||||||
// Read files from cookie
|
|
||||||
let files: Directory | undefined = undefined;
|
|
||||||
const filesJson = Cookies.get("files");
|
|
||||||
if (filesJson !== undefined) {
|
|
||||||
try {
|
|
||||||
const parsedFiles = Node.deserialize(filesJson);
|
|
||||||
if (parsedFiles instanceof Directory)
|
|
||||||
files = parsedFiles;
|
|
||||||
else
|
|
||||||
console.warn("`files` cookie contains non-directory.");
|
|
||||||
} catch (error) {
|
|
||||||
console.warn("Failed to deserialize `files` cookie.", error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.fileSystem = new FileSystem(files);
|
|
||||||
|
|
||||||
// Read environment from cookie
|
|
||||||
const environment = Cookies.get("env") || "{}";
|
|
||||||
try {
|
|
||||||
this.environment = JSON.parse(environment);
|
|
||||||
} catch (error) {
|
|
||||||
console.warn("Failed to set environment from cookie.");
|
|
||||||
this.environment = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check cwd in environment
|
|
||||||
if (this.environment["cwd"] === undefined || !this.fileSystem.has(new Path(this.environment["cwd"].value)))
|
|
||||||
this.environment["cwd"] = {value: "/", readonly: true};
|
|
||||||
|
|
||||||
this.commands = new Commands(this.environment, this.userSession, this.fileSystem);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -94,7 +60,7 @@ export class Shell {
|
||||||
* @return the header that is displayed when a user logs in
|
* @return the header that is displayed when a user logs in
|
||||||
*/
|
*/
|
||||||
generateHeader(): string {
|
generateHeader(): string {
|
||||||
if (!this.userSession.isLoggedIn)
|
if (this.environment["user"].value === "")
|
||||||
return "";
|
return "";
|
||||||
|
|
||||||
return "" +
|
return "" +
|
||||||
|
@ -115,30 +81,28 @@ export class Shell {
|
||||||
* @return the prefix based on the current state of the terminal
|
* @return the prefix based on the current state of the terminal
|
||||||
*/
|
*/
|
||||||
generatePrefix(): string {
|
generatePrefix(): string {
|
||||||
if (!this.userSession.isLoggedIn) {
|
const userName = this.environment["user"].value;
|
||||||
|
if (userName === "") {
|
||||||
if (this.attemptUser === undefined)
|
if (this.attemptUser === undefined)
|
||||||
return "login as: ";
|
return "login as: ";
|
||||||
else
|
else
|
||||||
return `Password for ${this.attemptUser}@fwdekker.com: `;
|
return `Password for ${this.attemptUser}@fwdekker.com: `;
|
||||||
} else {
|
|
||||||
if (this.userSession.currentUser === undefined)
|
|
||||||
throw new IllegalStateError("User is logged in as undefined.");
|
|
||||||
|
|
||||||
const cwd = new Path(this.environment["cwd"].value);
|
|
||||||
const parts = cwd.ancestors.reverse();
|
|
||||||
parts.push(cwd);
|
|
||||||
const link = parts
|
|
||||||
.map(part => {
|
|
||||||
const node = this.fileSystem.get(part);
|
|
||||||
if (node === undefined)
|
|
||||||
throw new IllegalStateError(`Ancestor '${part}' of cwd does not exist.`);
|
|
||||||
|
|
||||||
return node.nameString(part.fileName + "/", part);
|
|
||||||
})
|
|
||||||
.join("");
|
|
||||||
|
|
||||||
return `${this.userSession.currentUser.name}@fwdekker.com <span class="prefixPath">${link}</span>> `;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const cwd = new Path(this.environment["cwd"].value);
|
||||||
|
const parts = cwd.ancestors.reverse();
|
||||||
|
parts.push(cwd);
|
||||||
|
const link = parts
|
||||||
|
.map(part => {
|
||||||
|
const node = this.fileSystem.get(part);
|
||||||
|
if (node === undefined)
|
||||||
|
throw new IllegalStateError(`Ancestor '${part}' of cwd does not exist.`);
|
||||||
|
|
||||||
|
return node.nameString(part.fileName + "/", part);
|
||||||
|
})
|
||||||
|
.join("");
|
||||||
|
|
||||||
|
return `${userName}@fwdekker.com <span class="prefixPath">${link}</span>> `;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -148,19 +112,26 @@ export class Shell {
|
||||||
* @param inputString the input to process
|
* @param inputString the input to process
|
||||||
*/
|
*/
|
||||||
execute(inputString: string): string {
|
execute(inputString: string): string {
|
||||||
if (!this.userSession.isLoggedIn) {
|
if (this.environment["user"].value === "") {
|
||||||
if (this.attemptUser === undefined) {
|
if (this.attemptUser === undefined) {
|
||||||
this.attemptUser = inputString.trim();
|
this.attemptUser = inputString.trim() || undefined; // Set to undefined if empty string
|
||||||
|
|
||||||
this.saveState();
|
this.saveState();
|
||||||
return EscapeCharacters.Escape + EscapeCharacters.HideInput;
|
return EscapeCharacters.Escape + EscapeCharacters.HideInput;
|
||||||
} else {
|
} else {
|
||||||
const isLoggedIn = this.userSession.tryLogIn(this.attemptUser, inputString);
|
const attemptUser = this.userList.get(this.attemptUser);
|
||||||
this.attemptUser = undefined;
|
|
||||||
|
|
||||||
|
let resultString: string;
|
||||||
|
if (attemptUser !== undefined && attemptUser.password === inputString) {
|
||||||
|
this.environment["user"].value = this.attemptUser;
|
||||||
|
resultString = this.generateHeader();
|
||||||
|
} else {
|
||||||
|
resultString = "Access denied\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
this.attemptUser = undefined;
|
||||||
this.saveState();
|
this.saveState();
|
||||||
return EscapeCharacters.Escape + EscapeCharacters.ShowInput
|
return EscapeCharacters.Escape + EscapeCharacters.ShowInput + resultString;
|
||||||
+ (isLoggedIn ? this.generateHeader() : "Access denied\n");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,11 +154,12 @@ export class Shell {
|
||||||
output = this.writeToFile(path, output, input.redirectTarget[0] === "append");
|
output = this.writeToFile(path, output, input.redirectTarget[0] === "append");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.userSession.isLoggedIn) {
|
if (this.environment["user"].value === "") {
|
||||||
this.inputHistory.clear();
|
this.inputHistory.clear();
|
||||||
for (const key of Object.getOwnPropertyNames(this.environment))
|
for (const key of Object.getOwnPropertyNames(this.environment))
|
||||||
delete this.environment[key];
|
delete this.environment[key];
|
||||||
this.environment["cwd"] = {value: "/", readonly: true};
|
this.environment["cwd"] = {value: "/", readonly: true};
|
||||||
|
this.environment["user"] = {value: "", readonly: true};
|
||||||
}
|
}
|
||||||
this.saveState();
|
this.saveState();
|
||||||
|
|
||||||
|
@ -231,9 +203,70 @@ export class Shell {
|
||||||
"path": "/"
|
"path": "/"
|
||||||
});
|
});
|
||||||
Cookies.set("env", this.environment, {"path": "/"});
|
Cookies.set("env", this.environment, {"path": "/"});
|
||||||
|
}
|
||||||
|
|
||||||
const user = this.userSession.currentUser;
|
/**
|
||||||
Cookies.set("user", user === undefined ? "" : user.name, {"path": "/"});
|
* Returns the file system loaded from a cookie, or the default file system if no cookie is present or the cookie
|
||||||
|
* is invalid.
|
||||||
|
*
|
||||||
|
* @return the file system loaded from a cookie, or the default file system if no cookie is present or the cookie
|
||||||
|
* is invalid
|
||||||
|
*/
|
||||||
|
private static loadFileSystem(): FileSystem {
|
||||||
|
let files: Directory | undefined = undefined;
|
||||||
|
const filesString = Cookies.get("files");
|
||||||
|
if (filesString !== undefined) {
|
||||||
|
try {
|
||||||
|
const parsedFiles = Node.deserialize(filesString);
|
||||||
|
if (parsedFiles instanceof Directory)
|
||||||
|
files = parsedFiles;
|
||||||
|
else
|
||||||
|
console.warn("`files` cookie contains non-directory.");
|
||||||
|
} catch (error) {
|
||||||
|
console.warn("Failed to deserialize `files` cookie.", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new FileSystem(files);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the environment loaded from a cookie, or the default environment if no cookie is present or the cookie
|
||||||
|
* is invalid.
|
||||||
|
*
|
||||||
|
* @param fileSystem the file system used to validate the `cwd` environment variable
|
||||||
|
* @param userList the list of users used to validate the `user` environment variable
|
||||||
|
* @return the environment loaded from a cookie, or the default environment if no cookie is present or the cookie
|
||||||
|
* is invalid
|
||||||
|
*/
|
||||||
|
private static loadEnvironment(fileSystem: FileSystem, userList: UserList): Environment {
|
||||||
|
const environmentString = Cookies.get("env") || "{}";
|
||||||
|
let environment: Environment;
|
||||||
|
try {
|
||||||
|
environment = JSON.parse(environmentString);
|
||||||
|
} catch (error) {
|
||||||
|
console.warn("Failed to set environment from cookie.");
|
||||||
|
environment = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check cwd in environment
|
||||||
|
if (environment["cwd"] === undefined) {
|
||||||
|
environment["cwd"] = {value: "/", readonly: true};
|
||||||
|
} else if (!fileSystem.has(new Path(environment["cwd"].value))) {
|
||||||
|
console.warn(`Invalid cwd '${environment["cwd"].value}' in environment.`);
|
||||||
|
environment["cwd"] = {value: "/", readonly: true};
|
||||||
|
}
|
||||||
|
environment["cwd"].readonly = true;
|
||||||
|
|
||||||
|
// Check user in environment
|
||||||
|
if (environment["user"] === undefined) {
|
||||||
|
environment["user"] = {value: "felix", readonly: true};
|
||||||
|
} else if (environment["user"].value !== "" && !userList.has(environment["user"].value)) {
|
||||||
|
console.warn(`Invalid user '${environment["cwd"].value}' in environment.`);
|
||||||
|
environment["user"] = {value: "felix", readonly: true};
|
||||||
|
}
|
||||||
|
environment["user"].readonly = true;
|
||||||
|
|
||||||
|
return environment;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,89 @@
|
||||||
|
/**
|
||||||
|
* Manages a user session.
|
||||||
|
*/
|
||||||
|
export class UserList {
|
||||||
|
/**
|
||||||
|
* All users that exist in the system.
|
||||||
|
*/
|
||||||
|
private _users: User[];
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new list of users.
|
||||||
|
*
|
||||||
|
* @param users the list of users that are available, or `undefined` if the default users should be available
|
||||||
|
*/
|
||||||
|
constructor(users: User[] | undefined = undefined) {
|
||||||
|
if (users === undefined)
|
||||||
|
this._users = [
|
||||||
|
new User("felix", "password", "Why are you logged in on <i>my</i> account?"),
|
||||||
|
new User("root", "root", "Wait how did you get here?")
|
||||||
|
];
|
||||||
|
else
|
||||||
|
this._users = users;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a copy of the list of all users.
|
||||||
|
*
|
||||||
|
* @return a copy of the list of all users
|
||||||
|
*/
|
||||||
|
get users(): User[] {
|
||||||
|
return this._users.slice();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns `true` if and only if a user with the given name exists.
|
||||||
|
*
|
||||||
|
* @param name the name of the user to check
|
||||||
|
* @return `true` if and only if a user with the given name exists
|
||||||
|
*/
|
||||||
|
has(name: string): boolean {
|
||||||
|
return this.get(name) !== undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the user with the given name, or `undefined` if there is no such user.
|
||||||
|
*
|
||||||
|
* @param name the name of the user to return
|
||||||
|
* @return the user with the given name, or `undefined` if there is no such user
|
||||||
|
*/
|
||||||
|
get(name: string): User | undefined {
|
||||||
|
return this._users.find(it => it.name === name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A user that can be logged in to.
|
||||||
|
*/
|
||||||
|
export class User {
|
||||||
|
/**
|
||||||
|
* The name of the user.
|
||||||
|
*/
|
||||||
|
readonly name: string;
|
||||||
|
/**
|
||||||
|
* The password of the user.
|
||||||
|
*/
|
||||||
|
readonly password: string;
|
||||||
|
/**
|
||||||
|
* The description of the user.
|
||||||
|
*/
|
||||||
|
readonly description: string;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new user.
|
||||||
|
*
|
||||||
|
* @param name the name of the user
|
||||||
|
* @param password the password of the user
|
||||||
|
* @param description the description of the user
|
||||||
|
*/
|
||||||
|
constructor(name: string, password: string, description: string) {
|
||||||
|
this.name = name;
|
||||||
|
this.password = password;
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,167 +0,0 @@
|
||||||
import {IllegalStateError} from "./Shared";
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Manages a user session.
|
|
||||||
*/
|
|
||||||
export class UserSession {
|
|
||||||
/**
|
|
||||||
* All users that exist in the system.
|
|
||||||
*/
|
|
||||||
private static _users: User[];
|
|
||||||
/**
|
|
||||||
* The user that is currently logged in in this session, or `undefined` if no user is logged in.
|
|
||||||
*/
|
|
||||||
private _currentUser: User | undefined;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a new user.
|
|
||||||
*
|
|
||||||
* @param name the name of the user to be logged in as by default, or `undefined` if no user should be logged in at
|
|
||||||
* the start of the session
|
|
||||||
* @throws if a name is given and no user with that name exists
|
|
||||||
*/
|
|
||||||
constructor(name: string | undefined = undefined) {
|
|
||||||
if (name !== undefined) {
|
|
||||||
const user = UserSession.getUser(name);
|
|
||||||
if (user === undefined)
|
|
||||||
throw new Error(`Could not find user \`${name}\`.`);
|
|
||||||
this._currentUser = user;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a copy of the list of all users.
|
|
||||||
*
|
|
||||||
* @return a copy of the list of all users
|
|
||||||
*/
|
|
||||||
static get users(): User[] {
|
|
||||||
return UserSession._users.slice();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the user that is currently logged in in this session, or `undefined` if no user is logged in.
|
|
||||||
*
|
|
||||||
* @return the user that is currently logged in in this session, or `undefined` if no user is logged in
|
|
||||||
*/
|
|
||||||
get currentUser(): User | undefined {
|
|
||||||
return this._currentUser;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns `true` if and only if a user is currently logged in.
|
|
||||||
*
|
|
||||||
* @return `true` if and only if a user is currently logged in
|
|
||||||
*/
|
|
||||||
get isLoggedIn(): boolean {
|
|
||||||
return this.currentUser !== undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns `true` if and only if a user with the given name exists.
|
|
||||||
*
|
|
||||||
* @param name the name of the user to check
|
|
||||||
* @return `true` if and only if a user with the given name exists
|
|
||||||
*/
|
|
||||||
static userExists(name: string): boolean {
|
|
||||||
return this.getUser(name) !== undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the user with the given name, or `undefined` if there is no such user.
|
|
||||||
*
|
|
||||||
* @param name the name of the user to return
|
|
||||||
* @return the user with the given name, or `undefined` if there is no such user
|
|
||||||
*/
|
|
||||||
static getUser(name: string): User | undefined {
|
|
||||||
return UserSession._users.find(it => it.name === name);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Attempts to log in as the given user with the given password, and returns `true` if and only if the user was
|
|
||||||
* successfully logged in.
|
|
||||||
*
|
|
||||||
* If logging in was successful, the current user is updated to the user with the given name.
|
|
||||||
*
|
|
||||||
* @param name the name of the user to try to log in as
|
|
||||||
* @param password the password of the user to try to log in as
|
|
||||||
* @return `true` if and only if the user was successfully logged in
|
|
||||||
* @throws if a user is already logged in
|
|
||||||
*/
|
|
||||||
tryLogIn(name: string, password: string): boolean {
|
|
||||||
if (this.isLoggedIn)
|
|
||||||
throw new IllegalStateError("Cannot try to log in while already logged in.");
|
|
||||||
|
|
||||||
const user = UserSession.getUser(name);
|
|
||||||
if (user === undefined)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (user.password !== password)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
this._currentUser = user;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Logs out the current user.
|
|
||||||
*/
|
|
||||||
logOut(): void {
|
|
||||||
this._currentUser = undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes the array of users to the default array.
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
static _initialize(): void {
|
|
||||||
this._users = [
|
|
||||||
new User("felix", "password", "Why are you logged in on <i>my</i> account?"),
|
|
||||||
new User("root", "root", "Wait how did you get here?")
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A user that can be logged in to.
|
|
||||||
*/
|
|
||||||
export class User {
|
|
||||||
/**
|
|
||||||
* The name of the user.
|
|
||||||
*/
|
|
||||||
readonly name: string;
|
|
||||||
/**
|
|
||||||
* The password of the user.
|
|
||||||
*/
|
|
||||||
readonly password: string;
|
|
||||||
/**
|
|
||||||
* The description of the user.
|
|
||||||
*/
|
|
||||||
readonly description: string;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a new user.
|
|
||||||
*
|
|
||||||
* @param name the name of the user
|
|
||||||
* @param password the password of the user
|
|
||||||
* @param description the description of the user
|
|
||||||
*/
|
|
||||||
constructor(name: string, password: string, description: string) {
|
|
||||||
this.name = name;
|
|
||||||
this.password = password;
|
|
||||||
this.description = description;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Initialize default list of users
|
|
||||||
UserSession._initialize();
|
|
Loading…
Reference in New Issue