Commit 8cb27251 authored by Lukas Burgey's avatar Lukas Burgey
Browse files

Rework the API towards the backend

parent 3bfb461d
<div *ngIf="(userService.subscribeSpecific(userService.userSelector) | async) as user" class="mat-typography" style="margin-bottom: 50px;">
<div *ngIf="(userService.subscribeUser() | async) as user" class="mat-typography" style="margin-bottom: 50px;">
<h2>User Info</h2>
<p>
You can inspect the user information we received about you.
......
......@@ -5,7 +5,7 @@
</h1>
<div class="header-bar">
<div *ngIf="(userService.subscribeLoggedIn() | async); else notLoggedIn">
<span *ngIf="(userService.subscribeSpecific(userService.userSelector) | async) as user">
<span *ngIf="(userService.subscribeUser() | async) as user">
<button mat-button mat-icon-button (click)="dialog.openAccount()">
<mat-icon>settings</mat-icon>
</button>
......
......@@ -105,19 +105,26 @@ export interface User {
profile_name: string;
userinfo: UserInfo;
ssh_keys: SSHKey[];
services: Service[];
groups: Group[];
// these are additions here
services: Service[];
deployments: Deployment[];
error?: string;
}
export interface UserState {
deployments: Deployment[];
deployment_state_items: DeploymentStateItem[];
//deployment_state_items: DeploymentStateItem[];
}
export interface StateAPIResult {
export interface State {
user: User;
user_state: UserState;
services: Service[];
error?: string;
}
export interface Update {
deployment?: Deployment;
error?: string;
}
......
......@@ -12,8 +12,8 @@ import {Message} from '@stomp/stompjs';
import {SnackBarService} from './snackbar.service';
import {IdpService} from './idp.service';
import * as t from './types/types.module';
import { StateAPIResult as SAR } from './types/types.module';
// import * as t from './types/types.module';
import { User, Update, State, Deployment, SSHKey, NewSSHKey, Group, IdP, Service } from './types/types.module';
@Injectable()
......@@ -22,20 +22,17 @@ export class UserService {
private loggedIn: boolean = false;
private loggedIn$ = new BehaviorSubject<boolean>(false);
private sar: SAR;
private sar$ = <BehaviorSubject<SAR>> new BehaviorSubject(new Object);
private user: User;
private user$ = <BehaviorSubject<User>> new BehaviorSubject(undefined);
private sshKeys: t.SSHKey[] = new Array<t.SSHKey>();
private sshKeys$ = new BehaviorSubject<t.SSHKey[]>(this.sshKeys);
private sshKeys: SSHKey[] = new Array<SSHKey>();
private sshKeys$ = new BehaviorSubject<SSHKey[]>(this.sshKeys);
private userState: t.UserState;
private userState$ = <BehaviorSubject<t.UserState>> new BehaviorSubject(new Object);
private deployments: Map<number, Deployment> = new Map([]);
private deployments$ = <BehaviorSubject<Deployment[]>> new BehaviorSubject([]);
private messages: string[] = [];
public groupSelector = (state: SAR) => state ? state.user ? state.user.groups : [] : [];
public userSelector = (state: SAR) => state ? state.user : null;
public serviceSelector = (state: SAR) => state ? state.services : [];
public groupSelector = (user: User) => user ? user.groups ? user.groups : [] : [];
public serviceSelector = (user: User) => user ? user.services ? user.services : [] : [];
constructor(
private cookieService: CookieService,
......@@ -56,21 +53,32 @@ export class UserService {
}
private connect(): void {
this.subscribeState().subscribe(
(state: SAR) => {
this.subscribeUser().subscribe(
(newUser: User) => {
// update users
const user = this.userSelector(state);
if (user) {
this.connectLiveUpdates(user);
this.sshKeys = user.ssh_keys;
} else {
this.sshKeys = [];
if (newUser != undefined) {
if (newUser.id) {
this.connectLiveUpdates(newUser.id);
}
if (newUser.ssh_keys) {
this.sshKeys = newUser.ssh_keys;
this.sshKeys$.next(this.sshKeys);
}
if (newUser.deployments) {
newUser.deployments.forEach(
(newDep: Deployment) => {
this.deployments.set(newDep.id, newDep);
}
);
this.deployments$.next(Array.from(this.deployments.values()));
}
}
this.sshKeys$.next(this.sshKeys);
},
this.logErrorAndFetch(),
() => console.log('sar$ is complete'),
this.logErrorAndFetch,
() => console.log('user$ is complete'),
);
this.subscribeLoggedIn().subscribe(
......@@ -87,14 +95,14 @@ export class UserService {
console.log('Logging out');
this._stompService.disconnect();
this.sar$.complete();
this.userState$.complete();
this.user$.complete();
this.deployments$.complete();
this.sshKeys$.complete();
this.snackBar.open('Logged out');
}
},
this.logErrorAndFetch(),
this.logErrorAndFetch,
() => console.log('loggedIn$ completed'),
);
......@@ -102,9 +110,9 @@ export class UserService {
this.fetch();
}
private connectLiveUpdates(user: t.User): void {
private connectLiveUpdates(userID: number): void {
// handle with care
let login = user.id
let login = userID
let passcode = this.cookieService.get('sessionid');
const stompConfig: StompConfig = {
......@@ -134,67 +142,57 @@ export class UserService {
this._stompService.initAndConnect();
let subscription = this._stompService.subscribe(
'/exchange/users/' + user.id.toString()
'/exchange/users/' + userID.toString()
);
subscription.subscribe(
(message: Message) => {
let update : t.StateAPIResult = JSON.parse(message.body);
let update: Update = JSON.parse(message.body);
console.log('update:', update);
if (update.error && update.error != '') {
console.log(update.error);
this.snackBar.open(update.error);
this.messages.push(update.error);
}
if (update.user_state) {
this.userStateUpdate(update.user_state);
if (update.deployment) {
this.updateDeployment(update.deployment);
}
},
this.logErrorAndFetch(),
this.logErrorAndFetch,
);
}
private userStateUpdate(newState: t.UserState): void {
console.log('userStateUpdate:', newState);
private updateState(update: State) {
console.log('updateState:', update);
// did a login occur?
let login = (!this.loggedIn && newState);
// did a logout occur?
let logout = (this.loggedIn && !newState);
// -- Value updating --
if (login) {
this.loggedIn = true;
this.loggedIn$.next(this.loggedIn);
}
if (logout) {
this.loggedIn = false;
this.loggedIn$.next(this.loggedIn);
return
}
if (newState) {
this.userState = newState;
this.userState$.next(newState);
}
}
private stateAPIUpdate(update: t.StateAPIResult) {
console.log('stateAPIUpdate:', update);
if (update) {
// report an occured error
if (update.error) {
this.logErrorAndFetch(update.error);
console.log(update.error);
this.snackBar.open(update.error);
}
if (!update.user) {
this.disconnect();
// did a login occur?
let login = (!this.loggedIn && update.user);
// did a logout occur?
let logout = (this.loggedIn && !update.user);
// -- Value updating --
if (logout) {
this.loggedIn = false;
this.loggedIn$.next(this.loggedIn);
return
}
this.userStateUpdate(update.user_state);
this.sar = update;
this.sar$.next(update);
if (login) {
this.loggedIn = true;
this.loggedIn$.next(this.loggedIn);
}
if (update.user) {
this.user = update.user;
this.user$.next(this.user);
}
} else {
this.disconnect();
......@@ -204,7 +202,7 @@ export class UserService {
private fetch(): void {
this.http.get('/backend/api/state').subscribe(
(data: t.StateAPIResult) => this.stateAPIUpdate(data),
(state: State) => this.updateState(state),
(err: any) => {
console.log('Error in fetch:', err);
this.snackBar.open('Error. Retry sometime later');
......@@ -212,17 +210,24 @@ export class UserService {
);
}
private updateDeployment(dep: Deployment): void {
if (dep) {
this.deployments.set(dep.id, dep);
this.deployments$.next(Array.from(this.deployments.values()));
}
}
// PUBLIC API
public serviceDescription(service: t.Service): string {
public serviceDescription(service: Service): string {
if (service.description != "") {
return service.description;
}
return "No description";
}
public getGroups(): t.Group[] {
if (this.sar.user.groups) {
return this.sar.user.groups.sort(
public getGroups(): Group[] {
if (this.user.groups) {
return this.user.groups.sort(
function(a,b) {
if (a.name < b.name) {
return -1;
......@@ -237,54 +242,53 @@ export class UserService {
return []
}
public getDeployment(service: t.Service): t.Deployment {
return this.sar.user_state.deployments.find(
public getDeployment(service: Service): Deployment {
return this.user.deployments.find(
dep => dep.service && dep.service.id === service.id
);
}
public getServices(group: t.Group): t.Service[] {
public getServices(group: Group): Service[] {
// TODO implement
//
return []
}
public logErrorAndFetch(msg?: string): ((any) => void) {
if (msg) {
return (error: any) => {
console.log(error);
this.snackBar.open('Error: '+msg);
this.fetch();
};
} else {
return (error: any) => {
console.log(error);
this.snackBar.open('Error');
this.fetch();
};
public logErrorAndFetch(error: any) {
if (error.status === 403) {
this.login();
}
console.log(error);
this.snackBar.open('Error');
this.fetch();
return Observable.throw(error);
}
public login(idp: t.IdP) {
this.idpService.setIdPPreference(idp);
public login(idp?: IdP): void {
if (idp) {
this.idpService.setIdPPreference(idp);
}
window.location.href = '/backend/auth/v1/request';
}
public logout() {
this.http.post('/backend/auth/v1/logout', {}).subscribe(
(data: t.StateAPIResult) => this.stateAPIUpdate(data),
this.logErrorAndFetch(),
(state: State) => this.updateState(state),
this.logErrorAndFetch,
);
}
public sentQuestionnaire(stateItemID: number, answers: Object) {
return this.http.post('/backend/api/questionnaire?id='+String(stateItemID), answers).subscribe(
(data: t.UserState) => {
(data: Deployment) => {
this.snackBar.open('Uploaded questionnaire');
this.userStateUpdate(data);
/* TODO fix
this.userUserUpdate(data);
*/
},
this.logErrorAndFetch(),
this.logErrorAndFetch,
);
}
......@@ -296,26 +300,26 @@ export class UserService {
this.snackBar.open('Deleted user from server');
}
},
this.logErrorAndFetch('Error deleting user from server'),
this.logErrorAndFetch,
);
}
public uploadSshKey(key: t.NewSSHKey) {
public uploadSshKey(key: NewSSHKey) {
console.log('uploading key:', key);
const body = {
'type': 'add',
'key': key,
};
return this.http.post('/backend/api/sshkey', body).subscribe(
(newKey: t.SSHKey) => {
(newKey: SSHKey) => {
this.sshKeys.push(newKey);
this.sshKeys$.next(this.sshKeys);
},
this.logErrorAndFetch(),
this.logErrorAndFetch,
);
}
public removeSshKey(key: t.SSHKey) {
public removeSshKey(key: SSHKey) {
console.log('deleting key:', key);
return this.http.post('/backend/api/sshkey', {
'type': 'remove',
......@@ -329,25 +333,23 @@ export class UserService {
this.sshKeys$.next(this.sshKeys);
}
},
this.logErrorAndFetch(),
this.logErrorAndFetch,
);
}
public changeDeployment(action: string, group: t.Group): Observable<t.Deployment> {
public changeDeployment(action: string, group: Group): Observable<Deployment> {
const body = {
'type': action,
'group': group.id,
};
return this.http.post('/backend/api/deployments', body).map(
(newDep: t.Deployment) => newDep,
this.logErrorAndFetch(),
return this.http.post<Deployment>('/backend/api/deployments', body).catch(
this.logErrorAndFetch,
);
}
// DATA SERVICE API
//
public subscribeSSHKeys(): Observable<t.SSHKey[]> {
public subscribeSSHKeys(): Observable<SSHKey[]> {
return this.sshKeys$.asObservable();
}
......@@ -355,39 +357,35 @@ export class UserService {
return this.loggedIn$.asObservable();
}
public subscribeState(): Observable<SAR> {
return this.sar$.asObservable();
public subscribeUser(): Observable<User> {
return this.user$.asObservable();
}
public subscribeUserState(): Observable<t.UserState> {
return this.userState$.asObservable();
public subscribeDeployments(): Observable<Deployment[]> {
return this.deployments$.asObservable();
}
public subscribeSpecific<T>(selector: (state: SAR) => T): Observable<T> {
return this.subscribeState().map(selector);
public subscribeSpecific<T>(selector: (user: User) => T): Observable<T> {
return this.subscribeUser().map(selector);
}
public subscribeServiceDeployment(service: t.Service): Observable<t.Deployment> {
return this.subscribeUserState().map(
(state: t.UserState) => {
if (state.deployments) {
return state.deployments.find(
(dep: t.Deployment) => dep.service ? dep.service.id == service.id : false
public subscribeServiceDeployment(service: Service): Observable<Deployment> {
return this.subscribeDeployments().map(
(deployments: Deployment[]) => {
return deployments.find(
(dep: Deployment) => dep.service ? dep.service.id == service.id : false
);
}
},
);
}
public subscribeGroupDeployment(group: t.Group): Observable<t.Deployment> {
return this.subscribeUserState().map(
(state: t.UserState) => {
if (state.deployments) {
return state.deployments.find(
(dep: t.Deployment) => dep.group == group.id
);
}
},
public subscribeGroupDeployment(group: Group): Observable<Deployment> {
return this.subscribeDeployments().map(
(deployments: Deployment[]) => {
return deployments.find(
(dep: Deployment) => dep.group == group.id
);
}
);
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment