user.service.ts 8.5 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[] = [];
Lukas Burgey's avatar
wip    
Lukas Burgey committed
29
30
  public groupMap = new Map();
  public groupsParsed = false;
Lukas Burgey's avatar
Lukas Burgey committed
31
32
33
34
35
36


  constructor(
    public cookieService: CookieService,
    public http: HttpClient,
    public snackBar: SnackBarService,
37
    private _stompService: StompRService,
Lukas Burgey's avatar
Lukas Burgey committed
38
  ) {
Lukas Burgey's avatar
Lukas Burgey committed
39
    this.update();
Lukas Burgey's avatar
Lukas Burgey committed
40
41
  }

Lukas Burgey's avatar
Lukas Burgey committed
42
43
44
45
46
  // 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
47

Lukas Burgey's avatar
Lukas Burgey committed
48
49
    const stompConfig: StompConfig = {
      // Which server?
50
      url: 'wss://'+window.location.host+'/ws',
51

Lukas Burgey's avatar
Lukas Burgey committed
52
53
54
55
56
57
      // Headers
      // Typical keys: login, passcode, host
      headers: {
        login: 'webpage-client:' + login,
        passcode: passcode,
      },
Lukas Burgey's avatar
Lukas Burgey committed
58

Lukas Burgey's avatar
Lukas Burgey committed
59
60
61
62
63
64
      // 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
65
66
      // Typical value 15000 (15 seconds)
      reconnect_delay: 15000,
67

Lukas Burgey's avatar
Lukas Burgey committed
68
69
70
71
72
      // Will log diagnostics on console
      debug: false,
    };
    this._stompService.config = stompConfig;
    this._stompService.initAndConnect();
Lukas Burgey's avatar
Lukas Burgey committed
73
74
  }

Lukas Burgey's avatar
Lukas Burgey committed
75
76
77
  private connectLiveUpdates() {
    this.initStomp();
    let subscription = this._stompService.subscribe(
78
      '/exchange/users/' + this.user.id.toString()
Lukas Burgey's avatar
Lukas Burgey committed
79
    );
80

Lukas Burgey's avatar
Lukas Burgey committed
81
82
83
84
85
86
    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
87
        }
Lukas Burgey's avatar
Lukas Burgey committed
88
89
        if (update.user_state) {
          this.updateUserState(update.user_state);
Lukas Burgey's avatar
Lukas Burgey committed
90
        }
Lukas Burgey's avatar
Lukas Burgey committed
91
92
93
      },
      (error: any) => {
        console.log(error)
94
      }
Lukas Burgey's avatar
Lukas Burgey committed
95
    );
Lukas Burgey's avatar
Lukas Burgey committed
96
  }
97

Lukas Burgey's avatar
Lukas Burgey committed
98
99
  private updateUser(newUser: t.User) {
    this.user = newUser;
Lukas Burgey's avatar
Lukas Burgey committed
100
101
  }

102
103
104
  private updateServices(newServices: t.Service[]){
    if (this.services.length !== newServices.length) {
      this.services = [];
Lukas Burgey's avatar
wip    
Lukas Burgey committed
105

106
107
      for (let service of newServices) {
        this.services.push(service);
Lukas Burgey's avatar
Lukas Burgey committed
108
      }
Lukas Burgey's avatar
wip    
Lukas Burgey committed
109
110

      for (let group of this.user.groups) {
Lukas Burgey's avatar
Lukas Burgey committed
111
        this.groupMap.set(group.name, this._getServices(group.name));
Lukas Burgey's avatar
wip    
Lukas Burgey committed
112
113
      }
      this.groupsParsed = true;
Lukas Burgey's avatar
Lukas Burgey committed
114
115
116
    }
  }

Lukas Burgey's avatar
wip    
Lukas Burgey committed
117
118
119
120
121
122
123
124
125
126
127
  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;
          }
        );
      }
    );
128
129
  }

Lukas Burgey's avatar
Lukas Burgey committed
130
131
132
  private updateUserState(newState: t.UserState) {
      // did a login occur?
    let login = (!this._loggedIn && newState);
Lukas Burgey's avatar
Lukas Burgey committed
133
    // did a logout occur?
Lukas Burgey's avatar
Lukas Burgey committed
134
    let logout = (this._loggedIn && !newState);
Lukas Burgey's avatar
Lukas Burgey committed
135
136
137

    // -- Value updating --
    if (login) {
Lukas Burgey's avatar
Lukas Burgey committed
138
      this._loggedIn = true;
139
      this.snackBar.open('Logged in');
140
141


Lukas Burgey's avatar
Lukas Burgey committed
142
      this.connectLiveUpdates();
143
    }
Lukas Burgey's avatar
Lukas Burgey committed
144
    if (logout) {
145
146
      this._logout()
      return
Lukas Burgey's avatar
Lukas Burgey committed
147
148
149
150
151
    }

    this.userState = newState;
  }

Lukas Burgey's avatar
wip    
Lukas Burgey committed
152
153
154
155
156
157
158
159
160
  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
161
  private stateAPIUpdate(update: t.StateAPIResult) {
162
163
164
165
166
167
168
169
170
171
172
    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
173
    }
Lukas Burgey's avatar
Lukas Burgey committed
174
175
  }

Lukas Burgey's avatar
Lukas Burgey committed
176
177
178
179
180
  private setIdPPreference(idp: t.IdP) {
    this.cookieService.set(environment.idpCookieName, String(idp.id));
  }

  // PUBLIC API
181
182
183
184
185
186
  public serviceDescription(service: t.Service): string {
    if (service.description != "") {
      return service.description;
    }
    return "No description";
  }
187
  public getDeployment(service: t.Service): t.Deployment {
Lukas Burgey's avatar
Lukas Burgey committed
188
189
    return this.userState.deployments.find(
      dep => {
190
191
192
193
        if (dep.service) {
          return dep.service.id === service.id;
        }
        return false
Lukas Burgey's avatar
Lukas Burgey committed
194
195
196
      }
    );
  }
Lukas Burgey's avatar
wip    
Lukas Burgey committed
197

198
199
200
201
202
203
204
  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
205
206
  }

207
208
209
210
211
212
213
214
215
  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
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
  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
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
  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);
  }

  public loggedIn():boolean {
    if (this.userState) {
      return true;
    }
    return false;
  }

  public update() {
Lukas Burgey's avatar
Lukas Burgey committed
255
    this.http
256
      .get('/backend/api/state')
Lukas Burgey's avatar
Lukas Burgey committed
257
      .subscribe(
Lukas Burgey's avatar
Lukas Burgey committed
258
259
        (data: t.StateAPIResult) => {
          this.stateAPIUpdate(data);
Lukas Burgey's avatar
Lukas Burgey committed
260
261
262
263
264
265
266
267
        },
        (err: HttpErrorResponse) => {
          console.log('Error', err);
          this.snackBar.open('Error receiving data from the server');
        }
      );
  }

Lukas Burgey's avatar
Lukas Burgey committed
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
  public errorHandler(error: any): void {
    if (error.status === 500) {
      this.snackBar.open('Server Error');
    }
  }

  public getIdPPreference(): Observable<t.AllAuthInfo> {
    let idpID = Number(this.cookieService.get(environment.idpCookieName));

    return this.http.get('/backend/auth/v1/info').map(
      (authInfo: t.AuthInfo) => {
        let selected = authInfo.idps[1];

        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
301

Lukas Burgey's avatar
Lukas Burgey committed
302
  public login(idp: t.IdP) {
303
    this.setIdPPreference(idp);
304
    window.location.href = '/backend/auth/v1/request';
305
306
  }

Lukas Burgey's avatar
Lukas Burgey committed
307
  public logout() {
308
    this.http.post('/backend/auth/v1/logout', {}).subscribe(
Lukas Burgey's avatar
Lukas Burgey committed
309
310
      (data: t.StateAPIResult) => {
        this.stateAPIUpdate(data);
Lukas Burgey's avatar
Lukas Burgey committed
311
312
313
      },
      (err) => {
        console.log(err);
314
        this._logout();
315
316
317
318
      }
    );
  }

319
320
  public sentQuestionnaire(stateItemID: number, answers: any) {
    return this.http.post('/backend/api/questionnaire?id='+String(stateItemID), answers).subscribe(
Lukas Burgey's avatar
Lukas Burgey committed
321
      (data: t.UserState) => {
Lukas Burgey's avatar
Lukas Burgey committed
322
        this.snackBar.open('Uploaded questionnaire');
Lukas Burgey's avatar
Lukas Burgey committed
323
        this.updateUserState(data);
Lukas Burgey's avatar
Lukas Burgey committed
324
325
326
327
      },
      (err) => {
        this.snackBar.open('Error uploading questionnaire');
        console.log(err);
Lukas Burgey's avatar
Lukas Burgey committed
328
        this.update();
Lukas Burgey's avatar
Lukas Burgey committed
329
330
331
332
      }
    );
  }

Lukas Burgey's avatar
Lukas Burgey committed
333
  public deleteUser() {
Lukas Burgey's avatar
Lukas Burgey committed
334
335
336
337
338
339
    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
340
341
342
343
      },
      (err) => {
        this.snackBar.open('Error deleting user from server');
        console.log(err);
Lukas Burgey's avatar
Lukas Burgey committed
344
        this.update();
Lukas Burgey's avatar
Lukas Burgey committed
345
346
347
      }
    );
  }
Lukas Burgey's avatar
Lukas Burgey committed
348
}