Commit f8714215 authored by Lukas Burgey's avatar Lukas Burgey

Add components

parent 7524c8ac
......@@ -41,3 +41,5 @@ yarn-error.log
# System Files
.DS_Store
Thumbs.db
deploy
{
"name": "fum",
"version": "0.0.0",
"name": "fum-webpage",
"version": "0.1.0",
"license": "MIT",
"scripts": {
"ng": "ng",
......@@ -12,42 +12,43 @@
},
"private": true,
"dependencies": {
"@angular/animations": "^4.4.6",
"@angular/cdk": "^2.0.0-beta.12",
"@angular/common": "^4.2.4",
"@angular/compiler": "^4.2.4",
"@angular/core": "^4.2.4",
"@angular/forms": "^4.2.4",
"@angular/http": "^4.2.4",
"@angular/material": "^2.0.0-beta.12",
"@angular/platform-browser": "^4.2.4",
"@angular/platform-browser-dynamic": "^4.2.4",
"@angular/router": "^4.2.4",
"angular-auth-oidc-client": "^2.0.0",
"@angular/animations": "^5.0.1",
"@angular/cdk": "^5.0.0-rc0",
"@angular/cli": "^1.5.3",
"@angular/common": "^5.0.0",
"@angular/compiler": "^5.0.0",
"@angular/core": "^5.0.0",
"@angular/forms": "^5.0.0",
"@angular/http": "^5.0.0",
"@angular/material": "^5.0.0-rc0",
"@angular/platform-browser": "^5.0.0",
"@angular/platform-browser-dynamic": "^5.0.0",
"@angular/router": "^5.0.0",
"core-js": "^2.4.1",
"hammerjs": "^2.0.8",
"rxjs": "^5.4.2",
"ngx-cookie-service": "^1.0.9",
"rxjs": "^5.5.2",
"typescript": "^2.4.2",
"zone.js": "^0.8.14"
},
"devDependencies": {
"@angular/cli": "1.3.2",
"@angular/compiler-cli": "^4.2.4",
"@angular/language-service": "^4.2.4",
"@types/jasmine": "~2.5.53",
"@angular/cli": "^1.5.4",
"@angular/compiler-cli": "^5.0.0",
"@angular/language-service": "^5.0.0",
"@types/jasmine": "~2.8.2",
"@types/jasminewd2": "~2.0.2",
"@types/node": "~6.0.60",
"codelyzer": "~3.1.1",
"jasmine-core": "~2.6.2",
"jasmine-spec-reporter": "~4.1.0",
"@types/node": "~8.0.53",
"jasmine-core": "~2.8.0",
"jasmine-spec-reporter": "~4.2.1",
"karma": "~1.7.0",
"karma-chrome-launcher": "~2.1.1",
"karma-chrome-launcher": "~2.2.0",
"karma-cli": "~1.0.1",
"karma-coverage-istanbul-reporter": "^1.2.1",
"karma-jasmine": "~1.1.0",
"karma-jasmine-html-reporter": "^0.2.2",
"protractor": "~5.1.2",
"ts-node": "~3.2.0",
"tslint": "~5.3.2",
"typescript": "~2.3.3"
"protractor": "~5.2.0",
"ts-node": "~3.3.0",
"tslint": "~5.8.0",
"typescript": "^2.4.2"
}
}
<div style="text-align: center">
<h3>Federated User Management</h3>
<mat-toolbar color="primary">
<span>Federated User Management</span>
<span class="toolbar-spacer"></span>
<app-login></app-login>
</mat-toolbar>
<div class="outer">
<div class="inner">
<router-outlet></router-outlet>
</div>
</div>
<router-outlet></router-outlet>
import { Component } from '@angular/core';
import { Subscription } from 'rxjs/Subscription';
@Component({
selector: 'app-root',
......@@ -7,4 +6,5 @@ import { Subscription } from 'rxjs/Subscription';
styleUrls: ['./app.component.css']
})
export class AppComponent {
constructor() { }
}
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { RouterModule } from '@angular/router';
import { JsonPipe } from '@angular/common';
import { HttpModule } from '@angular/http';
import { AuthModule, OidcSecurityService, OpenIDImplicitFlowConfiguration } from 'angular-auth-oidc-client';
import { HttpClientModule, HttpClientXsrfModule } from '@angular/common/http';
import { MatButtonModule } from '@angular/material';
import { MatToolbarModule } from '@angular/material';
import { MatTableModule } from '@angular/material/table';
import { MatSnackBarModule } from '@angular/material/snack-bar';
import { MatExpansionModule } from '@angular/material/expansion';
import { MatIconModule } from '@angular/material/icon';
import { MatDialogModule } from '@angular/material/dialog';
import {MatFormFieldModule} from '@angular/material/form-field';
import {MatSelectModule} from '@angular/material/select';
import {MatInputModule} from '@angular/material/input';
import { CookieService } from 'ngx-cookie-service';
import { AuthGuard } from './auth.guard';
import { UserService } from './user.service';
import { SnackBarService } from './snackbar.service';
import { AppComponent } from './app.component';
import { MgmtComponent } from './mgmt/mgmt.component';
import { LoginComponent } from './login/login.component';
import { ProfileComponent } from './profile/profile.component';
import { ServiceComponent } from './service/service.component';
import { SshKeysComponent } from './ssh-keys/ssh-keys.component';
const routes = [
{
path: '',
component: LoginComponent,
},
{
path: 'oidcredirect',
redirectTo: '/mgmt',
component: MgmtComponent,
},
{
path: 'mgmt',
component: MgmtComponent,
path: '*',
redirectTo: '/',
},
];
......@@ -34,45 +46,48 @@ const routes = [
AppComponent,
MgmtComponent,
LoginComponent,
ProfileComponent,
ServiceComponent,
SshKeysComponent,
],
imports: [
BrowserModule,
BrowserAnimationsModule,
FormsModule,
HttpModule,
HttpClientModule,
HttpClientXsrfModule.withOptions({
cookieName: 'csrftoken',
headerName: 'HTTP_X_CSRFTOKEN',
}),
RouterModule.forRoot(
routes,
),
AuthModule.forRoot(),
MatButtonModule,
MatToolbarModule,
MatTableModule,
MatSnackBarModule,
MatExpansionModule,
MatIconModule,
MatDialogModule,
MatFormFieldModule,
MatSelectModule,
MatInputModule,
],
providers: [
AuthGuard,
CookieService,
UserService,
SnackBarService,
JsonPipe,
],
bootstrap: [AppComponent],
entryComponents: [
ProfileComponent,
SshKeysComponent,
],
bootstrap: [AppComponent]
})
export class AppModule {
constructor(public oidcSecurityService: OidcSecurityService) {
const openIDImplicitFlowConfiguration = new OpenIDImplicitFlowConfiguration();
openIDImplicitFlowConfiguration.stsServer = 'https://iam-test.indigo-datacloud.eu';
openIDImplicitFlowConfiguration.redirect_url = 'http://localhost:4200/oidcredirect';
openIDImplicitFlowConfiguration.client_id = '46b352da-b75f-4375-b56b-5b0565fa9cf3';
openIDImplicitFlowConfiguration.response_type = 'id_token token';
openIDImplicitFlowConfiguration.scope = 'openid email profile';
openIDImplicitFlowConfiguration.post_logout_redirect_uri =
'http://localhost:44311/Unauthorized';
openIDImplicitFlowConfiguration.start_checksession = false;
openIDImplicitFlowConfiguration.silent_renew = true;
openIDImplicitFlowConfiguration.silent_renew_offset_in_seconds = 0;
openIDImplicitFlowConfiguration.post_login_route = '/mgmt';
openIDImplicitFlowConfiguration.forbidden_route = '/Forbidden';
openIDImplicitFlowConfiguration.unauthorized_route = '/Unauthorized';
openIDImplicitFlowConfiguration.auto_userinfo = true;
openIDImplicitFlowConfiguration.log_console_warning_active = true;
openIDImplicitFlowConfiguration.log_console_debug_active = true;
openIDImplicitFlowConfiguration.max_id_token_iat_offset_allowed_in_seconds = 10;
openIDImplicitFlowConfiguration.override_well_known_configuration = false;
this.oidcSecurityService.setupModule(openIDImplicitFlowConfiguration);
constructor() {
}
}
import { TestBed, async, inject } from '@angular/core/testing';
import { AuthGuard } from './auth.guard';
describe('AuthGuard', () => {
beforeEach(() => {
TestBed.configureTestingModule({
providers: [AuthGuard]
});
});
it('should ...', inject([AuthGuard], (guard: AuthGuard) => {
expect(guard).toBeTruthy();
}));
});
import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { Observable } from 'rxjs/Observable';
import { OidcSecurityService } from 'angular-auth-oidc-client';
@Injectable()
export class AuthGuard implements CanActivate {
constructor(public oidcSecurityService: OidcSecurityService) {}
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
return this.oidcSecurityService.getIsAuthorized();
}
}
<div style="text-align: center">
<button mat-raised-button (click)="login()">OIDC Login</button>
</div>
<span *ngIf="userService.loggedIn ? false : true">
<button mat-raised-button color="accent" (click)="userService.login()">Login</button>
</span>
<span *ngIf="userService.loggedIn">
<button mat-button mat-icon-button (click)="openSshKeys()">
<mat-icon>vpn_key</mat-icon>
</button>
<button mat-button (click)="openProfile()">
{{ userService.user?.username }}
</button>
<button mat-raised-button color="accent" (click)="userService.logout()">Logout</button>
</span>
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Subscription } from 'rxjs/Subscription';
import { OidcSecurityService } from 'angular-auth-oidc-client';
import { Component } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { ProfileComponent } from '../profile/profile.component';
import { SshKeysComponent } from '../ssh-keys/ssh-keys.component';
import { UserService } from '../user.service';
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit, OnDestroy {
constructor(public oidcSecurityService: OidcSecurityService) {
if (this.oidcSecurityService.moduleSetup) {
this.doCallbackLogicIfRequired();
} else {
this.oidcSecurityService.onModuleSetup.subscribe(() => {
this.doCallbackLogicIfRequired();
});
}
}
ngOnInit() {
}
ngOnDestroy(): void {
this.oidcSecurityService.onModuleSetup.unsubscribe();
}
export class LoginComponent {
private profileDialog;
login() {
this.oidcSecurityService.authorize();
}
constructor(
public userService: UserService,
public dialog: MatDialog,
) { }
logout() {
this.oidcSecurityService.logoff();
}
public openProfile() {
this.profileDialog = this.dialog.open(
ProfileComponent,
{
width: '80%',
}
);
}
private doCallbackLogicIfRequired() {
if (window.location.hash) {
this.oidcSecurityService.authorizedCallback();
}
}
public openSshKeys() {
this.profileDialog = this.dialog.open(
SshKeysComponent,
{
width: '80%',
}
);
}
}
<div *ngIf="isAuthorized">
You are authorized
</div>
<div *ngIf="!isAuthorized">
You are not authorized
<div *ngIf="userService.loggedIn">
<h4>Services</h4>
<div *ngIf="userService.state.services.length > 0">
<mat-accordion>
<app-service *ngFor="let service of userService.state.services"
[serviceData]="service"></app-service>
</mat-accordion>
</div>
<p *ngIf="userService.state.services?.length == 0">
You have no available services.<br/>
This is due services requiring users to be member of a certain group.
</p>
</div>
{{ userData }}
{{ oidcSecurityService.getToken() }}
<!--
<div style="margin-top: 100px">
{{ userService.state | json }}
</div>
<div style="margin-top: 100px">
{{ userService.user | json }}
</div>
-->
import { Component, OnInit } from '@angular/core';
import {OidcSecurityService } from 'angular-auth-oidc-client';
import { UserService } from '../user.service';
@Component({
selector: 'app-mgmt',
......@@ -8,27 +9,12 @@ import {OidcSecurityService } from 'angular-auth-oidc-client';
styleUrls: ['./mgmt.component.css']
})
export class MgmtComponent implements OnInit {
isAuthorized: boolean;
userData: any;
constructor(public oidcSecurityService: OidcSecurityService) {
this.isAuthorized = false;
this.userData = null;
constructor(
public userService: UserService
) {
}
ngOnInit() {
this.oidcSecurityService.getIsAuthorized().subscribe(
(isAuthorized: boolean) => {
console.log(JSON.stringify(isAuthorized));
this.isAuthorized = isAuthorized;
}
);
this.oidcSecurityService.getUserData().subscribe(
(userData: any) => {
console.log(JSON.stringify(userData));
this.userData = userData;
}
);
}
}
<div>
<mat-table [dataSource]="userService.userInfoData">
<ng-container matColumnDef="name">
<mat-header-cell *matHeaderCellDef>Name</mat-header-cell>
<mat-cell *matCellDef="let element">{{ element.name}}</mat-cell>
</ng-container>
<ng-container matColumnDef="info">
<mat-header-cell *matHeaderCellDef>Info</mat-header-cell>
<mat-cell *matCellDef="let element">{{ element.info }}</mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="columns"></mat-header-row>
<mat-row *matRowDef="let row; columns: columns;"></mat-row>
</mat-table>
</div>
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ProfileComponent } from './profile.component';
describe('ProfileComponent', () => {
let component: ProfileComponent;
let fixture: ComponentFixture<ProfileComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ProfileComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ProfileComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should be created', () => {
expect(component).toBeTruthy();
});
});
import { Component, OnInit } from '@angular/core';
import { MatTableDataSource } from '@angular/material';
import { UserService } from '../user.service';
@Component({
selector: 'app-profile',
templateUrl: './profile.component.html',
styleUrls: ['./profile.component.css']
})
export class ProfileComponent implements OnInit {
columns = ['name', 'info'];
constructor(
public userService: UserService,
) { }
ngOnInit() {
}
}
<mat-expansion-panel>
<mat-expansion-panel-header>
<mat-panel-title>{{ serviceData.name }}</mat-panel-title>
<mat-panel-description>{{ serviceData.description }}</mat-panel-description>
</mat-expansion-panel-header>
<p>
<mat-icon style="vertical-align: middle; padding-right: 35px;">storage</mat-icon>
Provided by: {{ serviceData.site.name }}
</p>
<span>
<mat-icon style="vertical-align: middle; padding-right: 35px;">lock outline</mat-icon>
</span>
Needs membership of one of the following groups:
<ul>
<li *ngFor="let group of serviceData.groups">
{{ group.name }}
</li>
</ul>
<mat-action-row>
<span style="padding-right: 20px;">
<mat-form-field>
<mat-select placeholder="SSH Public Key" [(ngModel)]="sshKeyName">
<mat-option *ngFor="let key of userService.user.ssh_keys" [value]="key.name">
{{ key.name }}
</mat-option>
</mat-select>
</mat-form-field>
</span>
<button mat-raised-button color="primary" [disabled]="requestDisabled()" (click)="request()">Request deployment</button>
</mat-action-row>
</mat-expansion-panel>
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ServiceComponent } from './service.component';
describe('ServiceComponent', () => {
let component: ServiceComponent;
let fixture: ComponentFixture<ServiceComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ServiceComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ServiceComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { Component, OnInit, Input } from '@angular/core';
import { SnackBarService } from '../snackbar.service';
import { UserService } from '../user.service';
@Component({
selector: 'app-service',
templateUrl: './service.component.html',
styleUrls: ['./service.component.css']
})
export class ServiceComponent implements OnInit {
@Input() serviceData: any;
sshKeyName = '';
constructor(
public userService: UserService,
public snackBar: SnackBarService,
) {
}
ngOnInit() {
}
public request() {
this.snackBar.open('Requesting with key ' + this.sshKeyName);
}
public requestDisabled(): boolean {
return this.sshKeyName === '';
}
}
import { Injectable } from '@angular/core';
import { MatSnackBar, MatSnackBarConfig } from '@angular/material';
@Injectable()
export class SnackBarService {
config = new MatSnackBarConfig()
constructor(
public snackBar: MatSnackBar,
) {
this.config.duration = 3000;
}
public open(message: string) {
return this.snackBar.open(message, '', this.config);
}
}
<div style="margin-bottom: 25px;">
<mat-table *ngIf="userService.user.ssh_keys" [dataSource]="userService.sshKeyData">
<ng-container matColumnDef="name">
<mat-header-cell *matHeaderCellDef>Name</mat-header-cell>
<mat-cell *matCellDef="let element">{{ element.name}}</mat-cell>
</ng-container>
<ng-container matColumnDef="key">
<mat-header-cell *matHeaderCellDef>Key</mat-header-cell>
<mat-cell *matCellDef="let element">{{ element.key }}</mat-cell>
</ng-container>
<ng-container matColumnDef="action">
<mat-header-cell *matHeaderCellDef>Action</mat-header-cell>
<mat-cell *matCellDef="let element">
<button mat-icon-button (click)="deleteKey(element.name)"><mat-icon>delete_forever</mat-icon></button>
</mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="columns"></mat-header-row>
<mat-row *matRowDef="let row; columns: columns;"></mat-row>
</mat-table>
<p *ngIf="!userService.user.ssh_keys">
You have no keys uploaded yet.
</p>
</div>
<div *ngIf="!upload">
<button mat-icon-button (click)="upload = true"><mat-icon>add</mat-icon></button>
</div>
<div *ngIf="upload" class="form-container">
<form (ngSubmit)="uploadKey()" #sshKeyForm="ngForm">
<mat-form-field>
<input matInput placeholder="Name" required [(ngModel)]="newKeyName" name="name">
</mat-form-field>
<mat-form-field>
<textarea matInput placeholder="Key" required [(ngModel)]="newKeyKey" name="key"></textarea>
</mat-form-field>
<button mat-raised-button color="primary" type="submit" [disabled]="!sshKeyForm.form.valid">Submit</button>
</form>
</div>
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { SshKeysComponent } from './ssh-keys.component';
describe('SshKeysComponent', () => {
let component: SshKeysComponent;
let fixture: ComponentFixture<SshKeysComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ SshKeysComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(SshKeysComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { Component, OnInit } from '@angular/core';
import { MatTableDataSource } from '@angular/material';
import { UserService } from '../user.service';
@Component({
selector: 'app-ssh-keys',
templateUrl: './ssh-keys.component.html',
styleUrls: ['./ssh-keys.component.css']
})
export class SshKeysComponent implements OnInit {
columns = ['name', 'key', 'action'];
// does the user want to update a key?
upload: boolean;
newKeyName: string;
newKeyKey: string;
constructor(
public userService: UserService
) { }
ngOnInit() {
this.upload = false;
this.newKeyName = '';
this.newKeyKey = '';
}
public uploadKey() {
this.userService.addSshKey({name: this.newKeyName, key: this.newKeyKey});