allerta-vvf/frontend/src/app/_services/auth.service.ts

189 lines
6.4 KiB
TypeScript

import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
import { ApiClientService } from './api-client.service';
import { AuthTokenService } from './auth-token.service';
import { Subject } from "rxjs";
import * as Sentry from "@sentry/angular-ivy";
export interface LoginResponse {
loginOk: boolean;
message: string;
}
@Injectable({
providedIn: 'root'
})
export class AuthService {
private defaultPlaceholderProfile: any = {
id: undefined,
impersonating: false,
can: (permission: string) => false
};
public profile: any = this.defaultPlaceholderProfile;
public authChanged = new Subject<void>();
public _authLoaded = false;
public loadProfile() {
console.log("Loading profile data...");
return new Promise<void>((resolve, reject) => {
this.api.post("me").then((data: any) => {
this.profile = data;
this.profile.can = (permission: string) => {
return this.profile.permissions.includes(permission);
}
this.profile.profilePageLink = "/users/" + this.profile.id;
Sentry.setUser({
id: this.profile.id,
name: this.profile.name
});
resolve();
}).catch((e) => {
console.error(e);
this.profile = this.defaultPlaceholderProfile;
reject();
}).finally(() => {
this.authChanged.next();
});
});
}
authLoaded() {
return this._authLoaded;
}
constructor(
private api: ApiClientService,
private authToken: AuthTokenService,
private router: Router
) {
this.loadProfile().then(() => {
console.log("User is authenticated");
}).catch(() => {
console.log("User is not logged in");
}).finally(() => {
this._authLoaded = true;
});
}
public isAuthenticated() {
return this.profile.id !== undefined;
}
public login(username: string, password: string) {
return new Promise<LoginResponse>((resolve) => {
this.api.get("csrf-cookie").then((data: any) => {
this.api.post("login", {
username: username,
password: password,
// use_sessions: true //Disabled because on cheap hosting it can cause problems
}).then((data: any) => {
this.authToken.updateToken(data.access_token);
this.loadProfile().then(() => {
resolve({
loginOk: true,
message: data.message
});
}).catch(() => {
resolve({
loginOk: false,
message: "Unknown error"
});
});
}).catch((err) => {
let error_message = "";
if(err.status === 401 || err.status === 422) {
error_message = err.error.message;
} else if (err.status === 400) {
let error_messages = err.error.errors;
error_message = error_messages.map((val: any) => {
return `${val.msg} in ${val.param}`;
}).join(" & ");
} else if (err.status === 500) {
error_message = "Server error";
} else {
error_message = "Unknown error";
}
resolve({
loginOk: false,
message: error_message
});
});
}).catch((err) => {
if(err.status = 500) {
resolve({
loginOk: false,
message: "Server error"
});
} else {
resolve({
loginOk: false,
message: "Unknown error"
});
}
});
})
}
public impersonate(user_id: number): Promise<void|string> {
return new Promise((resolve, reject) => {
this.api.post(`impersonate/${user_id}`).then((data) => {
this.authToken.updateToken(data.access_token);
this.loadProfile().then(() => {
resolve();
}).catch((err) => {
console.error(err);
this.logout();
this.profile.impersonating_user = false;
this.logout();
});
}).catch((err) => {
console.error(err);
reject(err.error.message);
});
});
}
public stop_impersonating(): Promise<void> {
return new Promise((resolve, reject) => {
this.api.post("stop_impersonating").then((data) => {
this.authToken.updateToken(data.access_token);
this.api.post("refresh_token").then((data) => {
this.authToken.updateToken(data.access_token);
Sentry.setUser(null);
resolve();
}).catch((err) => {
this.logout(undefined, true);
reject();
});
}).catch((err) => {
this.logout(undefined, true);
reject();
});
});
}
public logout(routerDestination?: string[] | undefined, forceLogout: boolean = false) {
if(!forceLogout && this.profile.impersonating_user) {
this.stop_impersonating().then(() => {
this.loadProfile();
}).catch((err) => {
console.error(err);
});
} else {
this.api.post("logout").then((data: any) => {
this.profile = this.defaultPlaceholderProfile;
if(routerDestination === undefined) {
routerDestination = ["login", "list"];
}
this.authToken.clearToken();
Sentry.setUser(null);
this.router.navigate(routerDestination);
});
}
}
}