100 lines
2.7 KiB
TypeScript
100 lines
2.7 KiB
TypeScript
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<void> {
|
|
await api_request("POST", `users/${this.pk}/activate`, 204, {
|
|
password: this.password,
|
|
});
|
|
}
|
|
|
|
async login(): Promise<void> {
|
|
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<void> {
|
|
const data = await api_request("GET", "users/me", 200);
|
|
this.pk = data.pk;
|
|
this.isTrusted = data.trust_bridge.is_trusted;
|
|
}
|
|
|
|
async signup(): Promise<void> {
|
|
await api_request("POST", "users", 201, {
|
|
username: this.username,
|
|
password: this.password,
|
|
});
|
|
}
|
|
}
|
|
|
|
export const user = Vue.observable(new User());
|