Skip to content
Snippets Groups Projects
Commit ff8703d1 authored by kbeyro's avatar kbeyro
Browse files

Add tokens to develop

parent 105963ed
No related branches found
No related tags found
2 merge requests!108Develop,!69Add tokens to develop
......@@ -60,6 +60,7 @@ import {SortableHeaderDirective} from '../service/sort-domain.directive';
import {InputTextModule} from 'primeng/inputtext';
import { DomainNamespaceAnnotationsComponent } from './domain-namespace-annotations/domain-namespace-annotations.component';
import { provideZxvbnServiceForPSM } from 'angular-password-strength-meter/zxcvbn';
import { AccessTokensComponent } from './users/access-token/access-tokens.component';
@NgModule({
......@@ -123,7 +124,8 @@ import { provideZxvbnServiceForPSM } from 'angular-password-strength-meter/zxcv
ContactComponent,
PreferencesComponent,
SortableHeaderDirective,
DomainNamespaceAnnotationsComponent
DomainNamespaceAnnotationsComponent,
AccessTokensComponent
],
providers: [
PasswordValidator,
......@@ -174,7 +176,8 @@ import { provideZxvbnServiceForPSM } from 'angular-password-strength-meter/zxcv
ModalProvideSshKeyComponent,
PreferencesComponent,
SortableHeaderDirective,
DomainNamespaceAnnotationsComponent
DomainNamespaceAnnotationsComponent,
AccessTokensComponent
]
})
export class SharedModule {
......
export class AccessToken {
public id: number
public name: string
public userId: number
public tokenValue: string
public valid: boolean
}
\ No newline at end of file
<div style="margin-bottom: 15px;" class="panel panel-default">
<div class="panel-heading">{{'TOKENS.HEADER' | translate}}</div>
<div class="panel-body">
<table class="table table-hover" aria-describedby="User access tokens table">
<thead>
<tr>
<th scope="col">{{'TOKENS.TABLE.ID' | translate}}</th>
<th scope="col">{{'TOKENS.TABLE.NAME' | translate}}</th>
<th scope="col">{{'TOKENS.TABLE.VALUE' | translate}}</th>
<th scope="col">{{'TOKENS.TABLE.VALID' | translate}}</th>
<th scope="col">{{'TOKENS.TABLE.ACTIONS' | translate}}</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let token of tokensList">
<td>{{token.id}}</td>
<td>{{token.name}}</td>
<td>{{token.tokenValue}}</td>
<td>{{token.valid}}</td>
<td>
<button type="button" class="btn btn-danger"
(click)="invalidate(token.id)">{{'TOKENS.BUTTON_INVALIDATE' | translate}}</button>
</td>
</tr>
<tr *ngIf="tokensList.length === 0">
<td colspan="3" style="text-align: center">{{'TOKENS.NO_TOKENS' | translate}}</td>
</tr>
</tbody>
</table>
<div>
<button type="button" class="btn btn-success"
(click)="modal.show()">{{'TOKENS.NEW_TOKEN' | translate}}</button>
</div>
</div>
</div>
<nmaas-modal styleModal="info">
<div class="nmaas-modal-header">{{'TOKENS.MODAL.HEADER' | translate}}</div>
<div class="nmaas-modal-body" style="height: 60%; max-height: 80vh;overflow-y: auto;">
<form [formGroup]="requestForm" (ngSubmit)="createNewToken()">
<div class="form-group">
<label class="control-label" for="new-token-name">
{{'TOKENS.MODAL.NAME' | translate}}:
</label>
<input id="new-token-name" type="text" class="form-control" formControlName="name">
</div>
<div *ngIf="name.invalid && (name.dirty || name.touched)" class="alert alert-danger">
<div *ngIf="name.errors.required">{{'SSH_KEYS.MODAL.ERROR.NAME_REQUIRED' | translate}}</div>
<div *ngIf="name.errors.minlength">{{'SSH_KEYS.MODAL.ERROR.NAME_MINLENGTH' | translate}}</div>
<div *ngIf="name.errors.maxlength">{{'SSH_KEYS.MODAL.ERROR.NAME_MAXLENGTH' | translate}}</div>
</div>
<input type="submit" class="btn btn-success" value="{{'SSH_KEYS.MODAL.BUTTON_ADD' | translate}}"
[disabled]="!requestForm.valid">
<button type="button" class="btn btn-primary pull-right"
(click)="modal.hide()">{{'SSH_KEYS.MODAL.BUTTON_CANCEL' | translate}}</button>
</form>
</div>
</nmaas-modal>
\ No newline at end of file
import {ComponentFixture, TestBed} from '@angular/core/testing';
import {AccessTokensComponent} from './access-tokens.component';
import {HttpClientTestingModule} from '@angular/common/http/testing';
import {TranslateFakeLoader, TranslateLoader, TranslateModule} from '@ngx-translate/core';
import {ReactiveFormsModule} from '@angular/forms';
import { CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from '@angular/core';
describe('AccessTokensComponent', () => {
let component: AccessTokensComponent;
let fixture: ComponentFixture<AccessTokensComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [AccessTokensComponent],
imports: [
HttpClientTestingModule,
ReactiveFormsModule,
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useClass: TranslateFakeLoader
}
}),
],
schemas: [CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA],
})
.compileComponents();
fixture = TestBed.createComponent(AccessTokensComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
\ No newline at end of file
import {Component, OnInit, ViewChild} from '@angular/core';
import {Observable} from 'rxjs';
import {AccessToken} from './access-token';
import {AccessTokenService} from './access-tokens.service';
import {ModalComponent} from '../../modal';
import {UntypedFormBuilder, UntypedFormGroup, Validators} from '@angular/forms';
@Component({
selector: 'app-access-tokens',
templateUrl: './access-tokens.component.html',
styleUrls: []
})
export class AccessTokensComponent implements OnInit {
public tokens: Observable<AccessToken[]> = undefined;
public tokensList: AccessToken[] = [];
public requestForm: UntypedFormGroup = undefined;
public newTokenName = '';
@ViewChild(ModalComponent, {static: true})
public readonly modal: ModalComponent;
constructor(private tokenService: AccessTokenService,
private formBuilder: UntypedFormBuilder) {
}
ngOnInit() {
this.requestForm = this.formBuilder.group({
name: ['', [Validators.required, Validators.minLength(1), Validators.maxLength(16)]],
})
this.tokens = this.tokenService.getAll();
this.getData();
}
getData() {
this.tokensList = [];
this.tokens.subscribe(
data => this.tokensList.push(...data),
error => console.error(error)
)
}
invalidate(id: number) {
this.tokenService.invalidate(id).subscribe(
(_) => this.getData(),
error => console.error(error)
);
}
public createNewToken() {
this.tokenService.createToken(this.requestForm.value.name.trim()).subscribe({
next: val => {
this.tokensList.push(val)
this.requestForm.reset();
this.modal.hide();
},
error: err => console.warn(err)
})
}
get name() {
return this.requestForm.get('name');
}
}
\ No newline at end of file
import {Observable} from 'rxjs';
import {AccessToken} from './access-token';
import {Injectable} from '@angular/core';
import {GenericDataService} from '../../../service/genericdata.service';
import {HttpClient} from '@angular/common/http';
import {AppConfigService} from '../../../service';
@Injectable({
providedIn: 'root'
})
export class AccessTokenService extends GenericDataService {
constructor(http: HttpClient, appConfig: AppConfigService) {
super(http, appConfig);
}
public getAll(): Observable<AccessToken[]> {
return this.http.get<AccessToken[]>(this.getUrl())
}
public invalidate(id: number): Observable<void> {
return this.http.put<void>(`${this.getUrl()}/${id}`, '')
}
public createToken(tokenName: string): Observable<AccessToken> {
return this.http.post<AccessToken>(this.getUrl(), tokenName)
}
private getUrl(): string {
return this.appConfig.getApiUrl() + '/tokens';
}
}
\ No newline at end of file
<div style="margin-bottom: 120px;" class="panel panel-default">
<div style="margin-bottom: 15px;" class="panel panel-default">
<div class="panel-heading">{{'SSH_KEYS.HEADER' | translate}}</div>
<div class="panel-body">
<div class="flex justify-content-end mb-4">
......
......@@ -34,5 +34,6 @@
[allowedModes]="[ComponentMode.PROFILVIEW, ComponentMode.EDIT]">
</nmaas-userprivileges>
<nmaas-ssh-keys></nmaas-ssh-keys>
<app-access-tokens></app-access-tokens>
</div>
</div>
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment