mirror of
https://github.com/stoatchat/for-legacy-web.git
synced 2026-03-07 09:25:27 +00:00
feat: make login functional again
This commit is contained in:
@@ -1,8 +1,10 @@
|
||||
import { detect } from "detect-browser";
|
||||
import { action, computed, makeAutoObservable, ObservableMap } from "mobx";
|
||||
import { Client, Nullable } from "revolt.js";
|
||||
import { API, Client, Nullable } from "revolt.js";
|
||||
|
||||
import { injectController } from "../../lib/window";
|
||||
|
||||
import { state } from "../../mobx/State";
|
||||
import Auth from "../../mobx/stores/Auth";
|
||||
|
||||
import { modalController } from "../modals/ModalController";
|
||||
@@ -14,6 +16,11 @@ class ClientController {
|
||||
*/
|
||||
private apiClient: Client;
|
||||
|
||||
/**
|
||||
* Server configuration
|
||||
*/
|
||||
private configuration: API.RevoltConfig | null;
|
||||
|
||||
/**
|
||||
* Map of user IDs to sessions
|
||||
*/
|
||||
@@ -29,45 +36,38 @@ class ClientController {
|
||||
apiURL: import.meta.env.VITE_API_URL,
|
||||
});
|
||||
|
||||
this.apiClient
|
||||
.fetchConfiguration()
|
||||
.then(() => (this.configuration = this.apiClient.configuration!));
|
||||
|
||||
this.configuration = null;
|
||||
this.sessions = new ObservableMap();
|
||||
this.current = null;
|
||||
|
||||
makeAutoObservable(this);
|
||||
|
||||
this.login = this.login.bind(this);
|
||||
this.logoutCurrent = this.logoutCurrent.bind(this);
|
||||
|
||||
// Inject globally
|
||||
injectController("client", this);
|
||||
}
|
||||
|
||||
@action pickNextSession() {
|
||||
this.current =
|
||||
this.current ?? this.sessions.keys().next().value ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hydrate sessions and start client lifecycles.
|
||||
* @param auth Authentication store
|
||||
*/
|
||||
@action hydrate(auth: Auth) {
|
||||
for (const entry of auth.getAccounts()) {
|
||||
const user_id = entry.session.user_id!;
|
||||
|
||||
const session = new Session();
|
||||
this.sessions.set(user_id, session);
|
||||
|
||||
session
|
||||
.emit({
|
||||
action: "LOGIN",
|
||||
session: entry.session,
|
||||
apiUrl: entry.apiUrl,
|
||||
})
|
||||
.catch((error) => {
|
||||
if (error === "Forbidden" || error === "Unauthorized") {
|
||||
this.sessions.delete(user_id);
|
||||
auth.removeSession(user_id);
|
||||
modalController.push({ type: "signed_out" });
|
||||
session.destroy();
|
||||
}
|
||||
});
|
||||
this.addSession(entry);
|
||||
}
|
||||
|
||||
this.current = this.sessions.keys().next().value ?? null;
|
||||
this.pickNextSession();
|
||||
}
|
||||
|
||||
@computed getActiveSession() {
|
||||
@@ -82,16 +82,134 @@ class ClientController {
|
||||
return this.getActiveSession()?.client ?? this.apiClient;
|
||||
}
|
||||
|
||||
@computed getServerConfig() {
|
||||
return this.configuration;
|
||||
}
|
||||
|
||||
@computed isLoggedIn() {
|
||||
return this.current === null;
|
||||
}
|
||||
|
||||
@action addSession(entry: { session: SessionPrivate; apiUrl?: string }) {
|
||||
const user_id = entry.session.user_id!;
|
||||
|
||||
const session = new Session();
|
||||
this.sessions.set(user_id, session);
|
||||
|
||||
session
|
||||
.emit({
|
||||
action: "LOGIN",
|
||||
session: entry.session,
|
||||
apiUrl: entry.apiUrl,
|
||||
configuration: this.configuration!,
|
||||
})
|
||||
.catch((error) => {
|
||||
if (error === "Forbidden" || error === "Unauthorized") {
|
||||
this.sessions.delete(user_id);
|
||||
state.auth.removeSession(user_id);
|
||||
modalController.push({ type: "signed_out" });
|
||||
session.destroy();
|
||||
}
|
||||
});
|
||||
|
||||
this.pickNextSession();
|
||||
}
|
||||
|
||||
async login(credentials: API.DataLogin) {
|
||||
const browser = detect();
|
||||
|
||||
// Generate a friendly name for this browser
|
||||
let friendly_name;
|
||||
if (browser) {
|
||||
let { name } = browser;
|
||||
const { os } = browser;
|
||||
let isiPad;
|
||||
if (window.isNative) {
|
||||
friendly_name = `Revolt Desktop on ${os}`;
|
||||
} else {
|
||||
if (name === "ios") {
|
||||
name = "safari";
|
||||
} else if (name === "fxios") {
|
||||
name = "firefox";
|
||||
} else if (name === "crios") {
|
||||
name = "chrome";
|
||||
}
|
||||
if (os === "Mac OS" && navigator.maxTouchPoints > 0)
|
||||
isiPad = true;
|
||||
friendly_name = `${name} on ${isiPad ? "iPadOS" : os}`;
|
||||
}
|
||||
} else {
|
||||
friendly_name = "Unknown Device";
|
||||
}
|
||||
|
||||
// Try to login with given credentials
|
||||
let session = await this.apiClient.api.post("/auth/session/login", {
|
||||
...credentials,
|
||||
friendly_name,
|
||||
});
|
||||
|
||||
// Prompt for MFA verificaiton if necessary
|
||||
if (session.result === "MFA") {
|
||||
const { allowed_methods } = session;
|
||||
const mfa_response: API.MFAResponse | undefined = await new Promise(
|
||||
(callback) =>
|
||||
modalController.push({
|
||||
type: "mfa_flow",
|
||||
state: "unknown",
|
||||
available_methods: allowed_methods,
|
||||
callback,
|
||||
}),
|
||||
);
|
||||
|
||||
if (typeof mfa_response === "undefined") {
|
||||
throw "Cancelled";
|
||||
}
|
||||
|
||||
session = await this.apiClient.api.post("/auth/session/login", {
|
||||
mfa_response,
|
||||
mfa_ticket: session.ticket,
|
||||
friendly_name,
|
||||
});
|
||||
|
||||
if (session.result === "MFA") {
|
||||
// unreachable code
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this.addSession({
|
||||
session,
|
||||
});
|
||||
|
||||
/*const s = session;
|
||||
|
||||
client.session = session;
|
||||
(client as any).$updateHeaders();
|
||||
|
||||
async function login() {
|
||||
state.auth.setSession(s);
|
||||
}
|
||||
|
||||
const { onboarding } = await client.api.get("/onboard/hello");
|
||||
|
||||
if (onboarding) {
|
||||
openScreen({
|
||||
id: "onboarding",
|
||||
callback: async (username: string) =>
|
||||
client.completeOnboarding({ username }, false).then(login),
|
||||
});
|
||||
} else {
|
||||
login();
|
||||
}*/
|
||||
}
|
||||
|
||||
@action logout(user_id: string) {
|
||||
const session = this.sessions.get(user_id);
|
||||
if (session) {
|
||||
this.sessions.delete(user_id);
|
||||
if (user_id === this.current) {
|
||||
this.current = this.sessions.keys().next().value ?? null;
|
||||
this.current = null;
|
||||
this.pickNextSession();
|
||||
}
|
||||
|
||||
session.destroy();
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
import { action, computed, makeAutoObservable } from "mobx";
|
||||
import { Client } from "revolt.js";
|
||||
import { API, Client } from "revolt.js";
|
||||
|
||||
type State = "Ready" | "Connecting" | "Online" | "Disconnected" | "Offline";
|
||||
|
||||
type Transition =
|
||||
| {
|
||||
action: "LOGIN";
|
||||
session: SessionPrivate;
|
||||
apiUrl?: string;
|
||||
session: SessionPrivate;
|
||||
configuration?: API.RevoltConfig;
|
||||
}
|
||||
| {
|
||||
action:
|
||||
@@ -113,6 +114,10 @@ export default class Session {
|
||||
this.state = "Connecting";
|
||||
this.createClient(data.apiUrl);
|
||||
|
||||
if (data.configuration) {
|
||||
this.client!.configuration = data.configuration;
|
||||
}
|
||||
|
||||
try {
|
||||
await this.client!.useExistingSession(data.session);
|
||||
this.user_id = this.client!.user!._id;
|
||||
|
||||
Reference in New Issue
Block a user