All files / app/service debug.service.ts

20% Statements 7/35
17.24% Branches 5/29
20% Functions 1/5
10.71% Lines 3/28

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 611x             1x       1x                                                                                                  
import { Injectable, isDevMode } from '@angular/core';
import { from, of } from 'rxjs';
import { ConfigService } from './config.service';
 
@Injectable({
  providedIn: 'root'
})
export class DebugService {
  loading?: Promise<string>;
 
  constructor(
    private config: ConfigService,
  ) { }
 
  get init$() {
    if (location.search.includes('debug=')) {
      const debugRole = location.search.match(/debug=([^&]+)/)![1];
      const debugTag = location.search.match(/tag=([^&]+)/)?.[1] || '';
      if (debugRole.toLowerCase() === 'false') return of(null);
      return from(this.getDebugToken(debugTag, 'ROLE_' + debugRole.toUpperCase()).then(jwt => this.config.token = jwt));
    }
    if (isDevMode() && !location.search.includes('anon=')) {
      return from(this.getDebugToken('+user/chris', 'ROLE_ADMIN').then(jwt => this.config.token = jwt));
    }
    return of(null)
  }
 
  private async getDebugToken(tag: string, ...roles: string[]) {
    if (!tag.startsWith('_') && !tag.startsWith('+')) {
      tag = '+user/' + (tag || 'debug');
    }
    if (tag.startsWith('_') && !roles.includes('ROLE_PRIVATE')) {
      roles.push('ROLE_PRIVATE');
    }
    const header = {
      alg: 'HS256',
      typ: 'JWT'
    };
    const payload = {
      aud: '',
      verified_email: true,
      sub: '+user'.length === tag.length ? tag : tag.substring('+user/'.length),
      auth: roles.join(','),
    };
    const body = btoa(JSON.stringify(header)) + '.' + btoa(JSON.stringify(payload));
 
    const secret = atob('MjY0ZWY2ZTZhYmJhMTkyMmE5MTAxMTg3Zjc2ZDlmZWUwYjk0MDgzODA0MDJiOTgyNTk4MmNjYmQ4Yjg3MmVhYjk0MmE0OGFmNzE2YTQ5ZjliMTEyN2NlMWQ4MjA5OTczYjU2NzAxYTc4YThkMzYxNzdmOTk5MTIxODZhMTkwMDM=');
    const enc = new TextEncoder();
    const algorithm = { name: 'HMAC', hash: 'SHA-256' };
 
    const key = await crypto.subtle.importKey('raw', enc.encode(secret), algorithm, false, ['sign', 'verify']);
    const signature = await crypto.subtle.sign(algorithm.name, key, enc.encode(body));
    const digest = btoa(String.fromCharCode(...new Uint8Array(signature)));
 
    console.log('GENERATING DEBUG JWT (DO NOT USE IN PRODUCTION)');
    console.log(header);
    console.log(payload);
    return (body + '.' + digest).replace(/\+/g, '-').replace(/\//g, '_');
  }
}