Adds check if the user is authorized to use the gitlab service

parent 1abd569d
......@@ -4,8 +4,10 @@
<span class="d-inline-flex mx-2 align-items-center">Current Project:</span>
<select class="border-0 bg-transparent text-light"
(change)="setProject($event.target.value)">
<option [value]="projectLoaderService.projects.FRONTEND">Frontend</option>
<option [value]="projectLoaderService.projects.BACKEND">Backend</option>
<option [value]="projectLoaderService.projects.FRONTEND">Frontend
</option>
<option [value]="projectLoaderService.projects.BACKEND">Backend
</option>
</select>
<span class="d-inline-flex mx-2 align-items-center"
......@@ -28,62 +30,65 @@
</div>
</div>
<div *ngIf="this.projectLoaderService.connected;else loading"
class="row mh-100 text-light">
<div class="d-flex sticky-top col-12 mb-2">
<div class="bg-white d-flex w-100 py-1">
<select class="border-0 bg-transparent mr-2"
(change)="changeFilter($event.target.value)">
<option [value]="filters.NONE"
[selected]="filter === filters.NONE">No Filter
</option>
<option [value]="filters.UNUSED"
[selected]="filter === filters.UNUSED">Unused Keys
</option>
<option [value]="filters.INVALID_KEYS"
[selected]="filter === filters.INVALID_KEYS">Empty Keys
</option>
<option [value]="filters.INVALID_DE"
[selected]="filter === filters.INVALID_DE">Empty DE Keys
</option>
<option [value]="filters.INVALID_EN"
[selected]="filter === filters.INVALID_EN">Empty EN Keys
</option>
<option [value]="filters.INVALID_ES"
[selected]="filter === filters.INVALID_ES">Empty ES Keys
</option>
<option [value]="filters.INVALID_FR"
[selected]="filter === filters.INVALID_FR">Empty FR Keys
</option>
<option [value]="filters.INVALID_IT"
[selected]="filter === filters.INVALID_IT">Empty IT Keys
</option>
</select>
<input type="text"
class="d-flex flex-grow-1 border-0"
#searchBox
[value]="searchFilter"
(keyup)="searchFilter = (searchBox.value)"
placeholder="Search..."/>
<ng-container *ngIf="this.projectLoaderService.isAuthorized;else unauthorized">
<div *ngIf="this.projectLoaderService.connected;else loading"
class="row mh-100 text-light">
<div class="d-flex sticky-top col-12 mb-2">
<div class="bg-white d-flex w-100 py-1">
<select class="border-0 bg-transparent mr-2"
(change)="changeFilter($event.target.value)">
<option [value]="filters.NONE"
[selected]="filter === filters.NONE">No Filter
</option>
<option [value]="filters.UNUSED"
[selected]="filter === filters.UNUSED">Unused Keys
</option>
<option [value]="filters.INVALID_KEYS"
[selected]="filter === filters.INVALID_KEYS">Empty Keys
</option>
<option [value]="filters.INVALID_DE"
[selected]="filter === filters.INVALID_DE">Empty DE Keys
</option>
<option [value]="filters.INVALID_EN"
[selected]="filter === filters.INVALID_EN">Empty EN Keys
</option>
<option [value]="filters.INVALID_ES"
[selected]="filter === filters.INVALID_ES">Empty ES Keys
</option>
<option [value]="filters.INVALID_FR"
[selected]="filter === filters.INVALID_FR">Empty FR Keys
</option>
<option [value]="filters.INVALID_IT"
[selected]="filter === filters.INVALID_IT">Empty IT Keys
</option>
</select>
<input type="text"
class="d-flex flex-grow-1 border-0"
#searchBox
[value]="searchFilter"
(keyup)="searchFilter = (searchBox.value)"
placeholder="Search..."/>
</div>
</div>
</div>
<div class="col-12 key-list overflow-auto"
[class.col-sm-6]="!!selectedKey">
<app-key-output [filter]="filter"
[searchFilter]="searchFilter"
[changedData]="changedData"
(changeEmitter)="dataChanged($event)"></app-key-output>
</div>
<div class="col-12 col-sm-6"
*ngIf="!!selectedKey">
<div *ngFor="let langKey of getKeys(languageLoaderService.LANGUAGE)">
<p class="mb-0">{{langKey.toUpperCase()}}</p>
<textarea class="w-100 key-textarea"
(keyup)="updateKey($event, langKey, selectedKey)"
[value]="selectedKey?.value[langKey] || ''"></textarea>
<div class="col-12 key-list overflow-auto"
[class.col-sm-6]="!!selectedKey">
<app-key-output [filter]="filter"
[searchFilter]="searchFilter"
[changedData]="changedData"
(changeEmitter)="dataChanged($event)"></app-key-output>
</div>
<div class="col-12 col-sm-6"
*ngIf="!!selectedKey">
<div *ngFor="let langKey of getKeys(languageLoaderService.LANGUAGE)">
<p class="mb-0">{{langKey.toUpperCase()}}</p>
<textarea class="w-100 key-textarea"
(keyup)="updateKey($event, langKey, selectedKey)"
[value]="selectedKey?.value[langKey] || ''"></textarea>
</div>
</div>
</div>
</div>
</ng-container>
<ng-template #unauthorized><h4 class="text-danger text-center mt-5">Not authorized to view this project</h4></ng-template>
<ng-template #loading><h4 class="text-light text-center mt-5">Loading...</h4></ng-template>
......@@ -4,7 +4,6 @@ import { Observable, of } from 'rxjs/index';
import { FooterBarService } from '../../service/footer-bar/footer-bar.service';
import { HeaderLabelService } from '../../service/header-label/header-label.service';
import { LanguageLoaderService } from '../../service/language-loader/language-loader.service';
import { CasLoginService } from '../../service/login/cas-login.service';
import { ModalOrganizerService } from '../../service/modal-organizer/modal-organizer.service';
import { ProjectLoaderService } from '../../service/project-loader/project-loader.service';
import { FILTER, PROJECT } from '../../shared/enums';
......@@ -99,12 +98,10 @@ export class I18nManagerOverviewComponent implements OnInit, OnDestroy {
@Inject(PLATFORM_ID) private platformId: Object,
private footerBarService: FooterBarService,
private headerLabelService: HeaderLabelService,
private languageLoaderService: LanguageLoaderService,
public modalOrganizerService: ModalOrganizerService,
public projectLoaderService: ProjectLoaderService,
private languageLoaderService: LanguageLoaderService,
private casService: CasLoginService,
) {
this.casService.casLoginRequired = true;
this.headerLabelService.headerLabel = 'I18Nator';
this.footerBarService.replaceFooterElements([]);
}
......@@ -143,11 +140,14 @@ export class I18nManagerOverviewComponent implements OnInit, OnDestroy {
this._selectedKey = null;
}
public setProject(value: PROJECT): void {
public async setProject(value: PROJECT): void {
this._selectedKey = undefined;
this.languageLoaderService.reset();
this.projectLoaderService.currentProject = value;
this.reloadLanguageData();
if (await this.projectLoaderService.isAuthorizedForProject(value)) {
this.reloadLanguageData();
}
}
public dataChanged(key): void {
......@@ -179,5 +179,4 @@ export class I18nManagerOverviewComponent implements OnInit, OnDestroy {
private reloadLanguageData(): void {
this.languageLoaderService.getLangData();
}
}
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { async, TestBed } from '@angular/core/testing';
import { I18nManagerService } from '../../service/api/i18n-manager/i18n-manager.service';
import { I18nManagerApiService } from '../../service/api/i18n-manager/i18n-manager-api.service';
import { LanguageLoaderService } from '../../service/language-loader/language-loader.service';
import { ProjectLoaderService } from '../../service/project-loader/project-loader.service';
import { FilterKeysPipe } from './filter-keys.pipe';
......@@ -12,9 +12,11 @@ describe('FilterKeysPipe', () => {
TestBed.configureTestingModule({
imports: [
HttpClientTestingModule,
], providers: [
LanguageLoaderService, I18nManagerService, ProjectLoaderService,
], declarations: [
],
providers: [
LanguageLoaderService, I18nManagerApiService, ProjectLoaderService,
],
declarations: [
FilterKeysPipe,
],
}).compileComponents();
......
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { inject, TestBed } from '@angular/core/testing';
import { I18nManagerService } from './i18n-manager.service';
import { I18nManagerApiService } from './i18n-manager-api.service';
describe('I18nManagerService', () => {
let backend: HttpTestingController;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule], providers: [I18nManagerService],
imports: [HttpClientTestingModule],
providers: [I18nManagerApiService],
});
backend = TestBed.get(HttpTestingController);
});
......@@ -17,11 +18,11 @@ describe('I18nManagerService', () => {
backend.verify();
});
it('should be created', inject([I18nManagerService], (service: I18nManagerService) => {
it('should be created', inject([I18nManagerApiService], (service: I18nManagerApiService) => {
expect(service).toBeTruthy();
}));
it('should get the language file for the frontend project', inject([I18nManagerService], (service: I18nManagerService) => {
it('should get the language file for the frontend project', inject([I18nManagerApiService], (service: I18nManagerApiService) => {
service.getLangFileForFE().subscribe();
backend.expectOne(service.GET_LANG_FILE_URL(service.GET_FE_PROJECT_URL()));
......@@ -29,7 +30,7 @@ describe('I18nManagerService', () => {
expect(service).toBeTruthy();
}));
it('should get the language file for the backend project', inject([I18nManagerService], (service: I18nManagerService) => {
it('should get the language file for the backend project', inject([I18nManagerApiService], (service: I18nManagerApiService) => {
service.getLangFileForBE().subscribe();
backend.expectOne(service.GET_LANG_FILE_URL(service.GET_BE_PROJECT_URL()));
......@@ -37,7 +38,7 @@ describe('I18nManagerService', () => {
expect(service).toBeTruthy();
}));
it('should post the updated language file for the frontend project', inject([I18nManagerService], (service: I18nManagerService) => {
it('should post the updated language file for the frontend project', inject([I18nManagerApiService], (service: I18nManagerApiService) => {
const data = [];
......@@ -47,7 +48,7 @@ describe('I18nManagerService', () => {
expect(service).toBeTruthy();
}));
it('should post the updated language file for the backend project', inject([I18nManagerService], (service: I18nManagerService) => {
it('should post the updated language file for the backend project', inject([I18nManagerApiService], (service: I18nManagerApiService) => {
const data = [];
......
......@@ -8,7 +8,7 @@ import { PROJECT } from '../../../shared/enums';
@Injectable({
providedIn: 'root',
})
export class I18nManagerService {
export class I18nManagerApiService {
private readonly BE_BASE_URL = 'arsnova-click-v2-backend';
private readonly FE_BASE_URL = 'arsnova-click-v2-frontend';
......@@ -35,6 +35,10 @@ export class I18nManagerService {
return `${baseUrl}/updateLang`;
}
public IS_AUTHORIZED_PROJECT_URL(baseUrl: string): string {
return `${baseUrl}/authorized`;
}
public getLangFileForFE(): Observable<IMessage> {
return this.http.get<IMessage>(this.GET_LANG_FILE_URL(this.GET_FE_PROJECT_URL()));
}
......@@ -68,4 +72,21 @@ export class I18nManagerService {
return this.postUpdateLangForBE(data);
}
}
public isAuthorizedForProject(currentProject: PROJECT, data: object): Observable<IMessage> {
switch (currentProject) {
case PROJECT.FRONTEND:
return this.isAuthorizedForFE(data);
case PROJECT.BACKEND:
return this.isAuthorizedForBE(data);
}
}
private isAuthorizedForFE(data: object): Observable<IMessage> {
return this.http.post<IMessage>(this.IS_AUTHORIZED_PROJECT_URL(this.GET_FE_PROJECT_URL()), data);
}
private isAuthorizedForBE(data: object): Observable<IMessage> {
return this.http.post<IMessage>(this.IS_AUTHORIZED_PROJECT_URL(this.GET_BE_PROJECT_URL()), data);
}
}
import { Injectable } from '@angular/core';
import { LANGUAGE } from '../../shared/enums';
import { I18nManagerService } from '../api/i18n-manager/i18n-manager.service';
import { I18nManagerApiService } from '../api/i18n-manager/i18n-manager-api.service';
import { ProjectLoaderService } from '../project-loader/project-loader.service';
@Injectable({
......@@ -21,7 +21,7 @@ export class LanguageLoaderService {
return this._unusedKeys;
}
constructor(private i18nManagerService: I18nManagerService, private projectLoaderService: ProjectLoaderService) {
constructor(private i18nManagerService: I18nManagerApiService, private projectLoaderService: ProjectLoaderService) {
}
public reset(): void {
......
import { Injectable } from '@angular/core';
import { PROJECT } from '../../shared/enums';
import { I18nManagerApiService } from '../api/i18n-manager/i18n-manager-api.service';
import { UserService } from '../user/user.service';
@Injectable({
providedIn: 'root',
......@@ -17,6 +19,12 @@ export class ProjectLoaderService {
this._connected = value;
}
private _isAuthorized = false;
get isAuthorized(): boolean {
return this._isAuthorized;
}
private _currentProject = PROJECT.FRONTEND;
get currentProject(): PROJECT {
......@@ -38,5 +46,28 @@ export class ProjectLoaderService {
this._currentBranch = value;
}
constructor() { }
constructor(private i18nManagerApiService: I18nManagerApiService, private userService: UserService) { }
public async isAuthorizedForProject(project: PROJECT): boolean {
if (!this.userService.isLoggedIn) {
this._isAuthorized = false;
return false;
}
try {
const isAuthorized = (
await this.i18nManagerApiService.isAuthorizedForProject(project, {
username: this.userService.username,
token: this.userService.staticLoginToken,
}).toPromise()
).status === 'STATUS_SUCCESSFUL';
this._isAuthorized = isAuthorized;
return isAuthorized;
} catch (e) {
this._isAuthorized = false;
return false;
}
}
}
......@@ -15,7 +15,7 @@ export class UserService {
this._casTicket = null;
this._staticLoginToken = null;
this._username = null;
this.persistTokensToSessionStorage();
this.persistTokens();
this._isLoggedIn = value;
}
......@@ -33,6 +33,10 @@ export class UserService {
private _staticLoginToken: string;
get staticLoginToken(): string {
return this._staticLoginToken;
}
constructor(private authorizeApiService: AuthorizeApiService, private storageService: StorageService) {
}
......@@ -67,7 +71,7 @@ export class UserService {
if (data.status === 'STATUS:SUCCESSFUL') {
this._isLoggedIn = true;
this._casTicket = data.payload.casTicket;
this.persistTokensToSessionStorage();
this.persistTokens();
resolve(true);
} else {
this._isLoggedIn = false;
......@@ -89,7 +93,7 @@ export class UserService {
this._isLoggedIn = true;
this._staticLoginToken = data.payload.token;
this._username = username;
this.persistTokensToSessionStorage();
this.persistTokens();
resolve(true);
} else {
this._isLoggedIn = false;
......@@ -102,7 +106,7 @@ export class UserService {
return this.sha1(`${username}|${password}`);
}
private persistTokensToSessionStorage(): void {
private persistTokens(): void {
this.storageService.create(DB_TABLE.CONFIG, STORAGE_KEY.TOKEN, {
casTicket: this._casTicket,
staticLoginToken: this._staticLoginToken,
......@@ -110,20 +114,22 @@ export class UserService {
}).subscribe();
}
private sha1(msg): string {
function rotl(n, s): number { return n << s | n >>> 32 - s; }
function tohex(i2: number): string {
for (let h = '', s = 28; ; s -= 4) {
h += (
i2 >>> s & 0xf
).toString(16);
if (!s) {
return h;
}
private rotl(n, s): number {
return n << s | n >>> 32 - s;
}
private tohex(i2: number): string {
for (let h = '', s = 28; ; s -= 4) {
h += (
i2 >>> s & 0xf
).toString(16);
if (!s) {
return h;
}
}
}
private sha1(msg): string {
let H0 = 0x67452301, H1 = 0xEFCDAB89, H2 = 0x98BADCFE, H3 = 0x10325476, H4 = 0xC3D2E1F0;
let i, t;
const M = 0x0ffffffff, W = new Array(80), ml = msg.length, wa = [];
......@@ -146,36 +152,36 @@ export class UserService {
W[i] = wa[bo + i];
}
for (i = 16; i <= 79; i++) {
W[i] = rotl(W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16], 1);
W[i] = this.rotl(W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16], 1);
}
let A = H0, B = H1, C = H2, D = H3, E = H4;
for (i = 0; i <= 19; i++) {
t = (
rotl(A, 5) + (
this.rotl(A, 5) + (
B & C | ~B & D
) + E + W[i] + 0x5A827999
) & M, E = D, D = C, C = rotl(B, 30), B = A, A = t;
) & M, E = D, D = C, C = this.rotl(B, 30), B = A, A = t;
}
for (i = 20; i <= 39; i++) {
t = (
rotl(A, 5) + (
this.rotl(A, 5) + (
B ^ C ^ D
) + E + W[i] + 0x6ED9EBA1
) & M, E = D, D = C, C = rotl(B, 30), B = A, A = t;
) & M, E = D, D = C, C = this.rotl(B, 30), B = A, A = t;
}
for (i = 40; i <= 59; i++) {
t = (
rotl(A, 5) + (
this.rotl(A, 5) + (
B & C | B & D | C & D
) + E + W[i] + 0x8F1BBCDC
) & M, E = D, D = C, C = rotl(B, 30), B = A, A = t;
) & M, E = D, D = C, C = this.rotl(B, 30), B = A, A = t;
}
for (i = 60; i <= 79; i++) {
t = (
rotl(A, 5) + (
this.rotl(A, 5) + (
B ^ C ^ D
) + E + W[i] + 0xCA62C1D6
) & M, E = D, D = C, C = rotl(B, 30), B = A, A = t;
) & M, E = D, D = C, C = this.rotl(B, 30), B = A, A = t;
}
H0 = H0 + A & M;
H1 = H1 + B & M;
......@@ -183,6 +189,6 @@ export class UserService {
H3 = H3 + D & M;
H4 = H4 + E & M;
}
return tohex(H0) + tohex(H1) + tohex(H2) + tohex(H3) + tohex(H4);
return this.tohex(H0) + this.tohex(H1) + this.tohex(H2) + this.tohex(H3) + this.tohex(H4);
}
}
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