import Cookies from "js-cookie"; import Vue from "vue"; type HTTPMethod = "GET" | "POST" | "PUT" | "PATCH"; export class APIError extends Error { constructor(message: string, public readonly errors: unknown) { super(message); } } async function api_request( method: HTTPMethod, endpoint: string, successStatus: number, data?: any, authToken?: string ) { const init = { headers: new Headers(), method: method, body: JSON.stringify(data), }; const csrfToken = Cookies.get("csrftoken"); if (csrfToken != undefined) { init.headers.set("X-CSRFToken", csrfToken); } if (authToken != undefined) { init.headers.set("Authorization", `Token ${authToken}`); } init.headers.set("Accept", "application/json"); init.headers.set("Content-Type", "application/json"); const response = await fetch(`/api/${endpoint}/`, init); if (response.status !== 204) { if (response.status === successStatus) { return await response.json(); } else { throw new APIError(response.statusText, await response.json()); } } } export class User { pk: number | undefined; password: string | undefined; username: string | null = null; isAuthenticated = false; isTrusted = false; /** * Activate the corresponding LDAP account. */ async activate(): Promise { await api_request("POST", `users/${this.pk}/activate`, 204, { password: this.password, }); } async login(): Promise { if (!this.username || !this.password) throw new APIError("", ""); // logout any existing sessions //await logout() // fetch the login endpoint we use for authentication const loginEndpoint = "/api-auth/login/"; // fetch the login page, so it sets csrf cookies await window.fetch(loginEndpoint); // authenticate us const body = new window.FormData(); body.append("username", this.username); body.append("password", this.password); const csrf_token = Cookies.get("csrftoken"); if (csrf_token) body.append("csrfmiddlewaretoken", csrf_token); const res = await window.fetch(loginEndpoint, { method: "post", body }); // successful logins are followed by a redirect if (res.redirected && res.status === 200) { this.isAuthenticated = true; await this.retrieve(); } else { throw new APIError("", ""); } } async retrieve(): Promise { const data = await api_request("GET", "users/me", 200); this.pk = data.pk; this.isTrusted = data.trust_bridge.is_trusted; } async signup(): Promise { await api_request("POST", "users", 201, { username: this.username, password: this.password, }); } } export const user = Vue.observable(new User());