user.service.ts 9.11 KB
Newer Older
Lukas Burgey's avatar
Lukas Burgey committed
1
2
import {Injectable} from '@angular/core';
import {HttpClient, HttpErrorResponse} from '@angular/common/http';
Lukas Burgey's avatar
Lukas Burgey committed
3
4
5
6
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/of';
Lukas Burgey's avatar
Lukas Burgey committed
7
8
9
10
11

import {CookieService} from 'ngx-cookie-service';
import {MatTableDataSource} from '@angular/material';

import {SnackBarService} from './snackbar.service';
12
13
import {StompConfig, StompRService} from '@stomp/ng2-stompjs';
import {Message} from '@stomp/stompjs';
Lukas Burgey's avatar
Lukas Burgey committed
14

Lukas Burgey's avatar
Lukas Burgey committed
15
import {environment} from '../environments/environment';
Lukas Burgey's avatar
Lukas Burgey committed
16
import * as t from './types/types.module';
Lukas Burgey's avatar
Lukas Burgey committed
17

Lukas Burgey's avatar
Lukas Burgey committed
18
19
20

@Injectable()
export class UserService {
Lukas Burgey's avatar
Lukas Burgey committed
21
22
23
24
  private _loggedIn: boolean = false;

  public user: t.User;
  public userState: t.UserState;
Lukas Burgey's avatar
Lukas Burgey committed
25

26
  public messages: string[] = [];
27
28
  // local copy of services
  public services: t.Service[] = [];
29
30
31
  public groupMap: Map<string, t.Service[]> = new Map();
  public groupsParsed: boolean = false;
  public idps: Observable<t.AuthInfo>;
Lukas Burgey's avatar
Lukas Burgey committed
32
33
34
35
36
37


  constructor(
    public cookieService: CookieService,
    public http: HttpClient,
    public snackBar: SnackBarService,
38
    private _stompService: StompRService,
Lukas Burgey's avatar
Lukas Burgey committed
39
  ) {
Lukas Burgey's avatar
Lukas Burgey committed
40
    this.update();
41
42
43
44
45
46
47
48
49
50
    this.idps = this.getIdPs();

    // if there is only one IdP immediately use it to login
    this.idps.subscribe(
      (authInfo: t.AuthInfo) => {
        if (authInfo.idps && authInfo.idps.length == 1) {
          this.login(authInfo.idps[0]);
        }
      }
    );
Lukas Burgey's avatar
Lukas Burgey committed
51
52
  }

Lukas Burgey's avatar
Lukas Burgey committed
53
54
55
56
57
  // PRIVATE API
  private initStomp() {
    // handle with care
    let login = this.user.id
    let passcode = this.cookieService.get('sessionid');
Lukas Burgey's avatar
Lukas Burgey committed
58

Lukas Burgey's avatar
Lukas Burgey committed
59
60
    const stompConfig: StompConfig = {
      // Which server?
61
      url: 'wss://'+window.location.host+'/ws',
62

Lukas Burgey's avatar
Lukas Burgey committed
63
64
65
66
67
68
      // Headers
      // Typical keys: login, passcode, host
      headers: {
        login: 'webpage-client:' + login,
        passcode: passcode,
      },
Lukas Burgey's avatar
Lukas Burgey committed
69

Lukas Burgey's avatar
Lukas Burgey committed
70
71
72
73
74
75
      // How often to heartbeat?
      // Interval in milliseconds, set to 0 to disable
      heartbeat_in: 0, // Typical value 0 - disabled
      heartbeat_out: 20000, // Typical value 20000 - every 20 seconds
      // Wait in milliseconds before attempting auto reconnect
      // Set to 0 to disable
76
77
      // Typical value 15000 (15 seconds)
      reconnect_delay: 15000,
78

Lukas Burgey's avatar
Lukas Burgey committed
79
80
81
82
83
      // Will log diagnostics on console
      debug: false,
    };
    this._stompService.config = stompConfig;
    this._stompService.initAndConnect();
Lukas Burgey's avatar
Lukas Burgey committed
84
85
  }

Lukas Burgey's avatar
Lukas Burgey committed
86
87
88
  private connectLiveUpdates() {
    this.initStomp();
    let subscription = this._stompService.subscribe(
89
      '/exchange/users/' + this.user.id.toString()
Lukas Burgey's avatar
Lukas Burgey committed
90
    );
91

Lukas Burgey's avatar
Lukas Burgey committed
92
93
94
95
96
97
    subscription.subscribe(
      (message: Message) => {
        let update : t.StateAPIResult = JSON.parse(message.body);
        if (update.error && update.error != '') {
          this.snackBar.open(update.error);
          this.messages.push(update.error);
Lukas Burgey's avatar
Lukas Burgey committed
98
        }
Lukas Burgey's avatar
Lukas Burgey committed
99
100
        if (update.user_state) {
          this.updateUserState(update.user_state);
Lukas Burgey's avatar
Lukas Burgey committed
101
        }
Lukas Burgey's avatar
Lukas Burgey committed
102
103
104
      },
      (error: any) => {
        console.log(error)
105
      }
Lukas Burgey's avatar
Lukas Burgey committed
106
    );
Lukas Burgey's avatar
Lukas Burgey committed
107
  }
108

Lukas Burgey's avatar
Lukas Burgey committed
109
110
  private updateUser(newUser: t.User) {
    this.user = newUser;
Lukas Burgey's avatar
Lukas Burgey committed
111
112
  }

113
114
115
  private updateServices(newServices: t.Service[]){
    if (this.services.length !== newServices.length) {
      this.services = [];
Lukas Burgey's avatar
wip    
Lukas Burgey committed
116

117
118
      for (let service of newServices) {
        this.services.push(service);
Lukas Burgey's avatar
Lukas Burgey committed
119
      }
Lukas Burgey's avatar
wip    
Lukas Burgey committed
120
121

      for (let group of this.user.groups) {
Lukas Burgey's avatar
Lukas Burgey committed
122
        this.groupMap.set(group.name, this._getServices(group.name));
Lukas Burgey's avatar
wip    
Lukas Burgey committed
123
124
      }
      this.groupsParsed = true;
Lukas Burgey's avatar
Lukas Burgey committed
125
126
127
    }
  }

Lukas Burgey's avatar
wip    
Lukas Burgey committed
128
129
130
131
132
133
134
135
136
137
138
  private _getServices(groupName: string) : t.Service[] {
    let services: t.Service[] = [];
    return this.services.filter(
      (service: t.Service) => {
        return service.groups.some(
          (group : t.Group) => {
            return group.name === groupName;
          }
        );
      }
    );
139
140
  }

Lukas Burgey's avatar
Lukas Burgey committed
141
142
143
  private updateUserState(newState: t.UserState) {
      // did a login occur?
    let login = (!this._loggedIn && newState);
Lukas Burgey's avatar
Lukas Burgey committed
144
    // did a logout occur?
Lukas Burgey's avatar
Lukas Burgey committed
145
    let logout = (this._loggedIn && !newState);
Lukas Burgey's avatar
Lukas Burgey committed
146
147
148

    // -- Value updating --
    if (login) {
Lukas Burgey's avatar
Lukas Burgey committed
149
      this._loggedIn = true;
150
      this.snackBar.open('Logged in');
151
152


Lukas Burgey's avatar
Lukas Burgey committed
153
      this.connectLiveUpdates();
154
    }
Lukas Burgey's avatar
Lukas Burgey committed
155
    if (logout) {
156
157
      this._logout()
      return
Lukas Burgey's avatar
Lukas Burgey committed
158
159
160
161
162
    }

    this.userState = newState;
  }

Lukas Burgey's avatar
wip    
Lukas Burgey committed
163
164
165
166
167
168
169
170
171
  private _logout() {
    this._loggedIn = false;
    this.snackBar.open('Logged out');
    this._stompService.disconnect();
    this.services = [];
    this.user = null;
    this.userState = null;
  }

Lukas Burgey's avatar
Lukas Burgey committed
172
  private stateAPIUpdate(update: t.StateAPIResult) {
173
174
175
176
177
178
179
180
181
182
183
    if (update) {
      this.updateUser(update.user)
      this.updateUserState(update.user_state);
      this.updateServices(update.services);

      // report an occured error
      if (update.error) {
        this.snackBar.open(update.error);
      }
    } else {
      console.log("Got null update");
Lukas Burgey's avatar
Lukas Burgey committed
184
    }
Lukas Burgey's avatar
Lukas Burgey committed
185
186
  }

Lukas Burgey's avatar
Lukas Burgey committed
187
188
189
190
191
  private setIdPPreference(idp: t.IdP) {
    this.cookieService.set(environment.idpCookieName, String(idp.id));
  }

  // PUBLIC API
192
193
194
195
196
197
  public serviceDescription(service: t.Service): string {
    if (service.description != "") {
      return service.description;
    }
    return "No description";
  }
198
  public getDeployment(service: t.Service): t.Deployment {
Lukas Burgey's avatar
Lukas Burgey committed
199
200
    return this.userState.deployments.find(
      dep => {
201
202
203
204
        if (dep.service) {
          return dep.service.id === service.id;
        }
        return false
Lukas Burgey's avatar
Lukas Burgey committed
205
206
207
      }
    );
  }
Lukas Burgey's avatar
wip    
Lukas Burgey committed
208

209
210
211
212
213
214
215
  public getServices(group: t.Group): t.Service[] {
    let s = this.groupMap.get(group.name);
    if (s == undefined) {
      return []
    } else {
      return s
    }
Lukas Burgey's avatar
wip    
Lukas Burgey committed
216
217
  }

218
219
220
221
222
223
224
225
226
  private getDeploymentByGroup(group: t.Group): t.Deployment | undefined {
    let dep = this.userState.deployments.find(
      (d: t.Deployment) => {
        return d.group === group.id;
      }
    );
    return dep
  }

Lukas Burgey's avatar
Lukas Burgey committed
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
  public getGroups(): t.Group[] {
    if (this.user.groups) {
      return this.user.groups.sort(
        function(a,b) {
          if (a.name < b.name) {
            return -1;
          } else if (a.name > b.name) {
            return 1;
          } else if (a.name === b.name) {
            return 0;
          }
        }
      );
    }
    return []
  }

Lukas Burgey's avatar
Lukas Burgey committed
244
245
246
247
248
249
250
251
252
253
254
255
256
257
  public userInfo(): MatTableDataSource<any> {
      const userInfoList = [];
      for (const key in this.user.userinfo) {
        if (this.user.userinfo.hasOwnProperty(key)) {
          userInfoList.push({name: key, info: this.user.userinfo[key]});
        }
      }
      return new MatTableDataSource(userInfoList);
  }

  public sshKeyTable(): MatTableDataSource<any> {
      return new MatTableDataSource(this.user.ssh_keys);
  }

258
  public loggedIn(): boolean {
Lukas Burgey's avatar
Lukas Burgey committed
259
260
261
262
263
264
    if (this.userState) {
      return true;
    }
    return false;
  }

265
266
267
268
269
270
271
272
273
274
  public update(): void {
    this.http.get('/backend/api/state').subscribe(
      (data: t.StateAPIResult) => {
        this.stateAPIUpdate(data);
      },
      (err: HttpErrorResponse) => {
        console.log('Error', err);
        this.snackBar.open('Error receiving data from the server');
      }
    );
Lukas Burgey's avatar
Lukas Burgey committed
275
276
  }

Lukas Burgey's avatar
Lukas Burgey committed
277
278
279
280
281
282
  public errorHandler(error: any): void {
    if (error.status === 500) {
      this.snackBar.open('Server Error');
    }
  }

283
284
285
286
287
288
289
290
291
292
293
294
295
  public getIdPs(): Observable<t.AuthInfo> {
    return this.http.get('/backend/auth/v1/info').map(
      (authInfo: t.AuthInfo) => {
        return authInfo;
      }
    ).catch(
      (error: any) => {
        this.errorHandler(error);
        return Observable.of(null);
      }
    );
  }

Lukas Burgey's avatar
Lukas Burgey committed
296
297
298
  public getIdPPreference(): Observable<t.AllAuthInfo> {
    let idpID = Number(this.cookieService.get(environment.idpCookieName));

299
    return this.idps.map(
Lukas Burgey's avatar
Lukas Burgey committed
300
      (authInfo: t.AuthInfo) => {
301
        let selected = authInfo.idps[0];
Lukas Burgey's avatar
Lukas Burgey committed
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322

        if (!idpID) {
          idpID = authInfo.default;
        }
        for (const idp of authInfo.idps) {
          if (idp.id === idpID) {
            selected = idp;
          }
        }
        return {
          idps: authInfo.idps,
          selected: selected,
        };
      }
    ).catch(
      (error: any) => {
        this.errorHandler(error);
        return Observable.of(null);
      }
    );
  }
Lukas Burgey's avatar
Lukas Burgey committed
323

Lukas Burgey's avatar
Lukas Burgey committed
324
  public login(idp: t.IdP) {
325
    this.setIdPPreference(idp);
326
327
328
329

    if (!this.loggedIn()) {
      window.location.href = '/backend/auth/v1/request';
    }
330
331
  }

Lukas Burgey's avatar
Lukas Burgey committed
332
  public logout() {
333
    this.http.post('/backend/auth/v1/logout', {}).subscribe(
Lukas Burgey's avatar
Lukas Burgey committed
334
335
      (data: t.StateAPIResult) => {
        this.stateAPIUpdate(data);
Lukas Burgey's avatar
Lukas Burgey committed
336
337
338
      },
      (err) => {
        console.log(err);
339
        this._logout();
340
341
342
343
      }
    );
  }

344
  public sentQuestionnaire(stateItemID: number, answers: Object) {
345
    return this.http.post('/backend/api/questionnaire?id='+String(stateItemID), answers).subscribe(
Lukas Burgey's avatar
Lukas Burgey committed
346
      (data: t.UserState) => {
Lukas Burgey's avatar
Lukas Burgey committed
347
        this.snackBar.open('Uploaded questionnaire');
Lukas Burgey's avatar
Lukas Burgey committed
348
        this.updateUserState(data);
Lukas Burgey's avatar
Lukas Burgey committed
349
350
351
352
      },
      (err) => {
        this.snackBar.open('Error uploading questionnaire');
        console.log(err);
Lukas Burgey's avatar
Lukas Burgey committed
353
        this.update();
Lukas Burgey's avatar
Lukas Burgey committed
354
355
356
357
      }
    );
  }

Lukas Burgey's avatar
Lukas Burgey committed
358
  public deleteUser() {
Lukas Burgey's avatar
Lukas Burgey committed
359
360
361
362
363
364
    return this.http.delete('/backend/api/delete_user').subscribe(
      (data: {deleted: boolean}) => {
        if (data && data.deleted) {
          this._logout();
          this.snackBar.open('Deleted user from server');
        }
Lukas Burgey's avatar
Lukas Burgey committed
365
366
367
368
      },
      (err) => {
        this.snackBar.open('Error deleting user from server');
        console.log(err);
Lukas Burgey's avatar
Lukas Burgey committed
369
        this.update();
Lukas Burgey's avatar
Lukas Burgey committed
370
371
372
      }
    );
  }
Lukas Burgey's avatar
Lukas Burgey committed
373
}