user.service.ts 8.6 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
import {MatTableDataSource} from '@angular/material';

Lukas Burgey's avatar
Lukas Burgey committed
5
import {Observable} from 'rxjs/Observable';
6
import {BehaviorSubject} from 'rxjs/BehaviorSubject';
Lukas Burgey's avatar
Lukas Burgey committed
7
8

import {CookieService} from 'ngx-cookie-service';
9
10
import {StompConfig, StompRService} from '@stomp/ng2-stompjs';
import {Message} from '@stomp/stompjs';
Lukas Burgey's avatar
Lukas Burgey committed
11

Lukas Burgey's avatar
Lukas Burgey committed
12
import {SnackBarService} from './snackbar.service';
13
import {IdpService} from './idp.service';
Lukas Burgey's avatar
Lukas Burgey committed
14
import * as t from './types/types.module';
Lukas Burgey's avatar
Lukas Burgey committed
15

Lukas Burgey's avatar
Lukas Burgey committed
16
17
18

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

  public user: t.User;
22
23
  user$ = <BehaviorSubject<t.User>> new BehaviorSubject(new Object);

Lukas Burgey's avatar
Lukas Burgey committed
24
  public userState: t.UserState;
25
  userState$ = <BehaviorSubject<t.UserState>> new BehaviorSubject(new Object);
Lukas Burgey's avatar
Lukas Burgey committed
26

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

33
  // TODO put in preferences cookie
Lukas Burgey's avatar
Lukas Burgey committed
34
  autoLogin = false;
35

Lukas Burgey's avatar
Lukas Burgey committed
36
37
38
39
40

  constructor(
    public cookieService: CookieService,
    public http: HttpClient,
    public snackBar: SnackBarService,
41
    public idpService: IdpService,
42
    private _stompService: StompRService,
Lukas Burgey's avatar
Lukas Burgey committed
43
  ) {
Lukas Burgey's avatar
Lukas Burgey committed
44
    this.update();
45
46
47
48
49
50
51
52
53
54
55
56
57
58

    // AUTO LOGIN
    this.subscribeUserState().subscribe(
      (state: t.UserState) => {
        console.log(JSON.stringify(state));

        if (!state) {
          this.idpService.subscribeIdps().subscribe(
            (idps: t.IdP[]) => {
              if (idps.length === 1 && this.autoLogin) {
                this.login(idps[0]);
              }
            }
          );
59
60
61
        }
      }
    );
62
63
64
65
66
67
68
69
70
  }

  // DATA SERVICE API
  public subscribeUserState(): Observable<t.UserState> {
    return this.userState$.asObservable();
  }

  public subscribeUser(): Observable<t.User> {
    return this.user$.asObservable();
Lukas Burgey's avatar
Lukas Burgey committed
71
72
  }

Lukas Burgey's avatar
Lukas Burgey committed
73
74
75
76
77
  // 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
78

Lukas Burgey's avatar
Lukas Burgey committed
79
80
    const stompConfig: StompConfig = {
      // Which server?
81
      url: 'wss://'+window.location.host+'/ws',
82

Lukas Burgey's avatar
Lukas Burgey committed
83
84
85
86
87
88
      // Headers
      // Typical keys: login, passcode, host
      headers: {
        login: 'webpage-client:' + login,
        passcode: passcode,
      },
Lukas Burgey's avatar
Lukas Burgey committed
89

Lukas Burgey's avatar
Lukas Burgey committed
90
91
92
93
94
95
      // 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
96
97
      // Typical value 15000 (15 seconds)
      reconnect_delay: 15000,
98

Lukas Burgey's avatar
Lukas Burgey committed
99
100
101
102
103
      // Will log diagnostics on console
      debug: false,
    };
    this._stompService.config = stompConfig;
    this._stompService.initAndConnect();
Lukas Burgey's avatar
Lukas Burgey committed
104
105
  }

Lukas Burgey's avatar
Lukas Burgey committed
106
107
108
  private connectLiveUpdates() {
    this.initStomp();
    let subscription = this._stompService.subscribe(
109
      '/exchange/users/' + this.user.id.toString()
Lukas Burgey's avatar
Lukas Burgey committed
110
    );
111

Lukas Burgey's avatar
Lukas Burgey committed
112
113
114
115
116
117
    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
118
        }
Lukas Burgey's avatar
Lukas Burgey committed
119
120
        if (update.user_state) {
          this.updateUserState(update.user_state);
Lukas Burgey's avatar
Lukas Burgey committed
121
        }
Lukas Burgey's avatar
Lukas Burgey committed
122
123
124
      },
      (error: any) => {
        console.log(error)
125
      }
Lukas Burgey's avatar
Lukas Burgey committed
126
    );
Lukas Burgey's avatar
Lukas Burgey committed
127
  }
128

Lukas Burgey's avatar
Lukas Burgey committed
129
130
  private updateUser(newUser: t.User) {
    this.user = newUser;
131
    this.user$.next(this.user);
Lukas Burgey's avatar
Lukas Burgey committed
132
133
  }

134
135
136
  private updateServices(newServices: t.Service[]){
    if (this.services.length !== newServices.length) {
      this.services = [];
Lukas Burgey's avatar
wip    
Lukas Burgey committed
137

138
139
      for (let service of newServices) {
        this.services.push(service);
Lukas Burgey's avatar
Lukas Burgey committed
140
      }
Lukas Burgey's avatar
wip    
Lukas Burgey committed
141
142

      for (let group of this.user.groups) {
Lukas Burgey's avatar
Lukas Burgey committed
143
        this.groupMap.set(group.name, this._getServices(group.name));
Lukas Burgey's avatar
wip    
Lukas Burgey committed
144
145
      }
      this.groupsParsed = true;
Lukas Burgey's avatar
Lukas Burgey committed
146
147
148
    }
  }

Lukas Burgey's avatar
Lukas Burgey committed
149
150
151
  private updateUserState(newState: t.UserState) {
      // did a login occur?
    let login = (!this._loggedIn && newState);
Lukas Burgey's avatar
Lukas Burgey committed
152
    // did a logout occur?
Lukas Burgey's avatar
Lukas Burgey committed
153
    let logout = (this._loggedIn && !newState);
Lukas Burgey's avatar
Lukas Burgey committed
154
155
156

    // -- Value updating --
    if (login) {
Lukas Burgey's avatar
Lukas Burgey committed
157
      this._loggedIn = true;
158
      this.snackBar.open('Logged in');
159
160


Lukas Burgey's avatar
Lukas Burgey committed
161
      this.connectLiveUpdates();
162
    }
Lukas Burgey's avatar
Lukas Burgey committed
163
    if (logout) {
164
165
      this._logout()
      return
Lukas Burgey's avatar
Lukas Burgey committed
166
167
168
    }

    this.userState = newState;
169
    this.userState$.next(this.userState);
Lukas Burgey's avatar
Lukas Burgey committed
170
171
  }

Lukas Burgey's avatar
wip    
Lukas Burgey committed
172
173
174
175
176
177
178
  private _logout() {
    this._loggedIn = false;
    this.snackBar.open('Logged out');
    this._stompService.disconnect();
    this.services = [];
    this.user = null;
    this.userState = null;
179
    this.userState$.complete();
Lukas Burgey's avatar
wip    
Lukas Burgey committed
180
181
  }

Lukas Burgey's avatar
Lukas Burgey committed
182
  private stateAPIUpdate(update: t.StateAPIResult) {
183
184
185
186
187
188
189
190
191
192
193
    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
194
    }
Lukas Burgey's avatar
Lukas Burgey committed
195
196
  }

197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
  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;
          }
        );
      }
    );
  }

  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
220
  // PUBLIC API
221
222
223
224
225
226
  public serviceDescription(service: t.Service): string {
    if (service.description != "") {
      return service.description;
    }
    return "No description";
  }
227
  public getDeployment(service: t.Service): t.Deployment {
Lukas Burgey's avatar
Lukas Burgey committed
228
229
    return this.userState.deployments.find(
      dep => {
230
231
232
233
        if (dep.service) {
          return dep.service.id === service.id;
        }
        return false
Lukas Burgey's avatar
Lukas Burgey committed
234
235
236
      }
    );
  }
Lukas Burgey's avatar
wip    
Lukas Burgey committed
237

238
239
240
241
242
  public getServices(group: t.Group): t.Service[] {
    let s = this.groupMap.get(group.name);
    if (s == undefined) {
      return []
    }
Lukas Burgey's avatar
Lukas Burgey committed
243
    return s
Lukas Burgey's avatar
wip    
Lukas Burgey committed
244
245
  }

Lukas Burgey's avatar
Lukas Burgey committed
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
  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
263
264
265
266
267
268
269
270
271
272
273
274
275
276
  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);
  }

277
  public loggedIn(): boolean {
Lukas Burgey's avatar
Lukas Burgey committed
278
279
280
281
282
283
    if (this.userState) {
      return true;
    }
    return false;
  }

284
285
  public update(): void {
    this.http.get('/backend/api/state').subscribe(
Lukas Burgey's avatar
Lukas Burgey committed
286
      (data: t.StateAPIResult) => this.stateAPIUpdate(data),
287
288
289
290
291
      (err: HttpErrorResponse) => {
        console.log('Error', err);
        this.snackBar.open('Error receiving data from the server');
      }
    );
Lukas Burgey's avatar
Lukas Burgey committed
292
293
  }

Lukas Burgey's avatar
Lukas Burgey committed
294
  public errorHandler(error: any): void {
295
296
    console.log(error);
    this.snackBar.open('Error');
Lukas Burgey's avatar
Lukas Burgey committed
297
298
299
  }

  public login(idp: t.IdP) {
300
    this.idpService.setIdPPreference(idp);
301
302
303
304

    if (!this.loggedIn()) {
      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(
309
      (data: t.StateAPIResult) => this.stateAPIUpdate(data),
Lukas Burgey's avatar
Lukas Burgey committed
310
      (err) => {
311
        this.errorHandler(err);
312
        this._logout();
313
314
315
316
      }
    );
  }

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

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