Commit 01efaa5e authored by Chris Hines's avatar Chris Hines
Browse files

all sorts of changes

parent 4de33b31
import { TestBed, inject } from '@angular/core/testing';
import { AuthorisationService } from './authorisation.service';
describe('AuthorisationService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
providers: [AuthorisationService]
});
});
it('should be created', inject([AuthorisationService], (service: AuthorisationService) => {
expect(service).toBeTruthy();
}));
});
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class AuthorisationService {
constructor() { }
}
This diff is collapsed.
...@@ -12,29 +12,30 @@ ...@@ -12,29 +12,30 @@
}, },
"private": true, "private": true,
"dependencies": { "dependencies": {
"@angular/animations": "6.0.4", "@angular/animations": "7.1.1",
"@angular/cdk": "^6.0.0", "@angular/cdk": "^7.1.0",
"@angular/common": "6.0.4", "@angular/common": "7.1.1",
"@angular/compiler": "6.0.4", "@angular/compiler": "7.1.1",
"@angular/core": "6.0.4", "@angular/core": "7.1.1",
"@angular/forms": "6.0.4", "@angular/flex-layout": "^7.0.0-beta.19",
"@angular/http": "6.0.4", "@angular/forms": "7.1.1",
"@angular/material": "^6.0.0", "@angular/http": "7.1.1",
"@angular/platform-browser": "6.0.4", "@angular/material": "^7.1.0",
"@angular/platform-browser-dynamic": "6.0.4", "@angular/platform-browser": "7.1.1",
"@angular/router": "6.0.4", "@angular/platform-browser-dynamic": "7.1.1",
"@angular/router": "7.1.1",
"core-js": "^2.4.1", "core-js": "^2.4.1",
"hammerjs": "^2.0.8", "hammerjs": "^2.0.8",
"keypair": "^1.0.1", "keypair": "^1.0.1",
"node-forge": "^0.7.5", "node-forge": "^0.7.5",
"rxjs": "^6.2.0", "rxjs": "^6.3.3",
"rxjs-compat": "^6.2.0", "rxjs-compat": "^6.2.0",
"zone.js": "^0.8.26" "zone.js": "^0.8.26"
}, },
"devDependencies": { "devDependencies": {
"@angular/cli": "6.0.8", "@angular/cli": "6.0.8",
"@angular/compiler-cli": "6.0.4", "@angular/compiler-cli": "7.1.1",
"@angular/language-service": "6.0.4", "@angular/language-service": "7.1.1",
"@types/jasmine": "~2.8.3", "@types/jasmine": "~2.8.3",
"@types/jasminewd2": "~2.0.2", "@types/jasminewd2": "~2.0.2",
"@types/node": "~6.0.60", "@types/node": "~6.0.60",
...@@ -49,7 +50,7 @@ ...@@ -49,7 +50,7 @@
"protractor": "~5.1.2", "protractor": "~5.1.2",
"ts-node": "~4.1.0", "ts-node": "~4.1.0",
"tslint": "~5.9.1", "tslint": "~5.9.1",
"typescript": "2.7.2", "typescript": "3.1.6",
"@angular-devkit/build-angular": "~0.6.8" "@angular-devkit/build-angular": "~0.6.8"
} }
} }
...@@ -3,6 +3,9 @@ import { RouterModule, Routes } from '@angular/router'; ...@@ -3,6 +3,9 @@ import { RouterModule, Routes } from '@angular/router';
import { LauncherComponent } from './launcher/launcher.component'; import { LauncherComponent } from './launcher/launcher.component';
import { KeygenComponent } from './keygen/keygen.component'; import { KeygenComponent } from './keygen/keygen.component';
import { ConnectingComponent } from './connecting/connecting.component'; import { ConnectingComponent } from './connecting/connecting.component';
import { TransferComponent } from './transfer/transfer.component';
import { ShareconnectComponent } from './shareconnect/shareconnect.component';
// import { TokenextractorComponent } from './tokenextractor/tokenextractor.component'; // import { TokenextractorComponent } from './tokenextractor/tokenextractor.component';
...@@ -13,7 +16,10 @@ const routes: Routes = [ ...@@ -13,7 +16,10 @@ const routes: Routes = [
{ path: 'finishlaunch', component: LauncherComponent}, { path: 'finishlaunch', component: LauncherComponent},
{ path: 'cancellaunch', component: LauncherComponent}, { path: 'cancellaunch', component: LauncherComponent},
{ path: 'sshauthz_callback', component: KeygenComponent}, { path: 'sshauthz_callback', component: KeygenComponent},
{ path: 'connecting', component: ConnectingComponent } { path: 'connecting', component: ConnectingComponent },
{ path: 'transfer', component: TransferComponent },
{ path: 'shareconnect', component: ShareconnectComponent }
// { path: 'sshauthz_callback', component: LauncherComponent} // { path: 'sshauthz_callback', component: LauncherComponent}
......
.fill-remaining-space {
/* This fills the remaining space, by using flexbox.
Every toolbar row uses a flexbox row layout. */
flex: 1 1 auto;
}
.fill-horizontal-space {
/* This fills the remaining space, by using flexbox.
Every toolbar row uses a flexbox row layout. */
flex: 0 1 auto;
}
<!-- <router-outlet class="fill-remaining-space"></router-outlet> -->
<router-outlet></router-outlet>
<router-outlet class="fill-remaining-space"></router-outlet>
<!-- <app-teserrors></app-teserrors> -->
import { Component } from '@angular/core'; import { Component } from '@angular/core';
import { TesService } from './tes.service'; import { TesService } from './tes.service';
import { AuthorisationService} from './authorisation.service'; import { AuthorisationService} from './authorisation.service';
import { ComputesitesService} from './computesites.service';
import {BehaviorSubject} from 'rxjs/BehaviorSubject';
import { MatSnackBar } from '@angular/material';
@Component({ @Component({
selector: 'app-root', selector: 'app-root',
...@@ -12,16 +16,39 @@ export class AppComponent { ...@@ -12,16 +16,39 @@ export class AppComponent {
private loggedin: Boolean = false; private loggedin: Boolean = false;
private errmsg: string=''; private errmsg: string='';
public authorised: boolean; public authorised: boolean;
public statusMsg: BehaviorSubject<string>;
private snackBarRef: any;
// private testingAuth: boolean; // private testingAuth: boolean;
constructor(private tesService: TesService, private authService: AuthorisationService) { constructor(private tesService: TesService,
private authService: AuthorisationService,
private computesitesService: ComputesitesService,
public snackBar: MatSnackBar,) {
}; };
ngOnInit() { ngOnInit() {
// this.tesService.testingAuth.subscribe(testingAuth => { this.testingAuth = testingAuth; console.log('testingAuth updated'+this.testingAuth) }); // this.tesService.testingAuth.subscribe(testingAuth => { this.testingAuth = testingAuth; console.log('testingAuth updated'+this.testingAuth) });
// this.testingAuth = false; // this.testingAuth = false;
this.statusMsg = new BehaviorSubject<any>('');
this.tesService.setStatusMsg(this.statusMsg);
this.computesitesService.setStatusMsg(this.statusMsg);
this.authService.setStatusMsg(this.statusMsg);
this.statusMsg.subscribe(msg => this.displayMessage(msg));
} }
private displayMessage(msg) {
if (msg === null || msg == "") {
console.log('attempting to dismis snackbar');
if (this.snackBarRef != undefined) {
this.snackBarRef.dismiss()
}
} else {
this.snackBarRef = this.snackBar.open(msg,'Dismiss');
}
}
// login() { // login() {
// console.log("login"); // console.log("login");
// this.authService.login() // this.authService.login()
......
...@@ -17,17 +17,22 @@ import { MatToolbarModule } from '@angular/material'; ...@@ -17,17 +17,22 @@ import { MatToolbarModule } from '@angular/material';
import { MatDialogModule, MatDialog } from '@angular/material'; import { MatDialogModule, MatDialog } from '@angular/material';
import { MatSnackBarModule } from "@angular/material"; import { MatSnackBarModule } from "@angular/material";
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { MatProgressBarModule } from '@angular/material/progress-bar';
import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { ComputesitesService } from './computesites.service'; import { ComputesitesService } from './computesites.service';
import { StrudelappsService } from './strudelapps.service'; import { StrudelappsService } from './strudelapps.service';
import { AuthorisationService } from './authorisation.service'; import { AuthorisationService } from './authorisation.service';
import { FlexLayoutModule } from '@angular/flex-layout';
import { FileExplorerModule } from './file-explorer/file-explorer.module';
import { TesService} from './tes.service'; import { TesService} from './tes.service';
import { SubmitAppService } from './submit-app.service';
import { FormsModule } from '@angular/forms'; import { FormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http'; import { HttpClientModule } from '@angular/common/http';
import { JobComponent } from './job/job.component'; import { JobComponent } from './job/job.component';
// import { SiteselectionComponent } from './siteselection/siteselection.component'; // import { SiteselectionComponent } from './siteselection/siteselection.component';
import { TeserrorsComponent } from './teserrors/teserrors.component'; // import { TeserrorsComponent } from './teserrors/teserrors.component';
import { AppRoutingModule } from './/app-routing.module'; import { AppRoutingModule } from './/app-routing.module';
import { TokenextractorComponent } from './tokenextractor/tokenextractor.component'; import { TokenextractorComponent } from './tokenextractor/tokenextractor.component';
// import { LogindialogComponent } from './logindialog/logindialog.component'; // import { LogindialogComponent } from './logindialog/logindialog.component';
...@@ -39,6 +44,10 @@ import { MatSidenavModule, MatExpansionModule, MatIconModule } from '@angular/ma ...@@ -39,6 +44,10 @@ import { MatSidenavModule, MatExpansionModule, MatIconModule } from '@angular/ma
import { StrudelapplistComponent } from './strudelapplist/strudelapplist.component'; import { StrudelapplistComponent } from './strudelapplist/strudelapplist.component';
import { KeygenComponent } from './keygen/keygen.component'; import { KeygenComponent } from './keygen/keygen.component';
import { ConnectingComponent } from './connecting/connecting.component'; import { ConnectingComponent } from './connecting/connecting.component';
import { TransferComponent } from './transfer/transfer.component';
import { Sv2SideNavComponent } from './sv2-side-nav/sv2-side-nav.component';
import { ShareconnectComponent } from './shareconnect/shareconnect.component';
// import { FileExplorerModule } from './file-explorer/file-explorer.module';
...@@ -50,14 +59,17 @@ import { ConnectingComponent } from './connecting/connecting.component'; ...@@ -50,14 +59,17 @@ import { ConnectingComponent } from './connecting/connecting.component';
JoblistComponent, JoblistComponent,
JobComponent, JobComponent,
// SiteselectionComponent, // SiteselectionComponent,
TeserrorsComponent, // TeserrorsComponent,
TokenextractorComponent, TokenextractorComponent,
LogoutdialogComponent, LogoutdialogComponent,
ModaldialogComponent, ModaldialogComponent,
// LaunchdialogComponent, // LaunchdialogComponent,
StrudelapplistComponent, StrudelapplistComponent,
KeygenComponent, KeygenComponent,
ConnectingComponent ConnectingComponent,
TransferComponent,
Sv2SideNavComponent,
ShareconnectComponent
], ],
imports: [ imports: [
BrowserModule, BrowserModule,
...@@ -80,10 +92,14 @@ import { ConnectingComponent } from './connecting/connecting.component'; ...@@ -80,10 +92,14 @@ import { ConnectingComponent } from './connecting/connecting.component';
MatExpansionModule, MatExpansionModule,
MatIconModule, MatIconModule,
MatSnackBarModule, MatSnackBarModule,
FileExplorerModule,
FlexLayoutModule,
MatProgressBarModule,
], ],
entryComponents: [ ModaldialogComponent, LogoutdialogComponent, ], entryComponents: [ ModaldialogComponent, LogoutdialogComponent, ],
providers: [ StrudelappsService, ComputesitesService, TesService, MatDialog, AuthorisationService], providers: [ StrudelappsService, ComputesitesService, TesService, SubmitAppService, MatDialog, AuthorisationService],
bootstrap: [AppComponent] bootstrap: [AppComponent]
}) })
export class AppModule { } export class AppModule { }
...@@ -4,7 +4,7 @@ import { Observable } from 'rxjs/Observable'; ...@@ -4,7 +4,7 @@ import { Observable } from 'rxjs/Observable';
import { of } from 'rxjs/observable/of'; import { of } from 'rxjs/observable/of';
import { catchError, map, tap } from 'rxjs/operators'; import { catchError, map, tap } from 'rxjs/operators';
import { ActivatedRoute, Router } from '@angular/router'; import { ActivatedRoute, Router } from '@angular/router';
import {LocationStrategy} from '@angular/common'; import {LocationStrategy, Location} from '@angular/common';
// import { keypair } from 'keypair'; // import { keypair } from 'keypair';
import * as keypair from 'keypair'; import * as keypair from 'keypair';
import * as forge from "node-forge"; import * as forge from "node-forge";
...@@ -13,6 +13,8 @@ import {BehaviorSubject} from 'rxjs/BehaviorSubject'; ...@@ -13,6 +13,8 @@ import {BehaviorSubject} from 'rxjs/BehaviorSubject';
import {Subject} from 'rxjs/Subject'; import {Subject} from 'rxjs/Subject';
import {TesService} from './tes.service'; import {TesService} from './tes.service';
import { throwError } from 'rxjs'; import { throwError } from 'rxjs';
import { environment } from '../environments/environment';
export class SshauthzServer {} export class SshauthzServer {}
...@@ -24,26 +26,38 @@ export class AuthorisationService { ...@@ -24,26 +26,38 @@ export class AuthorisationService {
// public token: BehaviorSubject<AuthToken>; // public token: BehaviorSubject<AuthToken>;
public token: AuthToken public token: AuthToken
public SshAuthzServers: BehaviorSubject<SshAuthzServer[]>; public SshAuthzServers: BehaviorSubject<SshAuthzServer[]>;
public readyToNavigate: Subject<Boolean>; public readyToNavigate: Subject<[Boolean,string]>;
public progress: Subject<string>; public progress: Subject<string>;
// private keyCert: Subject<KeyCert>; // private keyCert: Subject<KeyCert>;
private backendURI: string;
public statusMsg: BehaviorSubject<string>;
public agentContents: BehaviorSubject<any>;
public keys: KeyCert[];
constructor(private http: HttpClient, constructor(private http: HttpClient,
private locationStrategy: LocationStrategy, private locationStrategy: LocationStrategy,
private route: ActivatedRoute, private route: ActivatedRoute,
private router: Router, private router: Router,
private tesService: TesService) { private location: Location) {
console.log('created AuthorisationService'); console.log('created AuthorisationService');
// this.token = new BehaviorSubject<AuthToken>(new AuthToken('','')); // this.token = new BehaviorSubject<AuthToken>(new AuthToken('',''));
this.readyToNavigate = new Subject<Boolean>(); this.readyToNavigate = new Subject<[Boolean,string]>();
this.readyToNavigate.next(false); this.readyToNavigate.next([false,'']);
this.progress = new Subject<string>(); this.progress = new Subject<string>();
this.progress.next(""); this.progress.next("");
// this.token.subscribe(token => this.getCert(token)); // this.token.subscribe(token => this.getCert(token));
this.route.fragment.subscribe(frag => this.storeToken(frag)); this.route.fragment.subscribe(frag => this.storeToken(frag));
this.SshAuthzServers = new BehaviorSubject<SshAuthzServer[]>([]); this.SshAuthzServers = new BehaviorSubject<SshAuthzServer[]>([]);
this.backendURI = environment.tesurl;
this.agentContents = new BehaviorSubject(null);
this.keys = [];
this.getSshAuthzServers(); this.getSshAuthzServers();
this.keys = [];
}
public setStatusMsg(statusMsg: BehaviorSubject<any>) {
this.statusMsg = statusMsg;
} }
getSshAuthzServers() { getSshAuthzServers() {
...@@ -56,6 +70,7 @@ export class AuthorisationService { ...@@ -56,6 +70,7 @@ export class AuthorisationService {
updateSshAuthzServers(resp) { updateSshAuthzServers(resp) {
this.SshAuthzServers.next(<SshAuthzServer[]>resp); this.SshAuthzServers.next(<SshAuthzServer[]>resp);
console.log('sshauthzservers set to',this.SshAuthzServers.value);
} }
storeToken(frag: string) { storeToken(frag: string) {
...@@ -109,60 +124,163 @@ export class AuthorisationService { ...@@ -109,60 +124,163 @@ export class AuthorisationService {
let data = {'token': token.token, 'pubkey': sshpub, 'signing_url': token.sshauthzservice.sign}; let data = {'token': token.token, 'pubkey': sshpub, 'signing_url': token.sshauthzservice.sign};
console.log('posting to getcert',this.tesService.Base); console.log('posting to getcert',this.backendURI);
this.http.post<any>(this.tesService.Base+'/getcert',data, options) this.http.post<any>(this.backendURI+'/getcert',data, options)
.pipe(catchError(this.handleError('getCert',[]))) // .pipe(catchError(this.handleError([])))
.subscribe(resp => this.makeKeyCert(newkeypair.private, resp, token.sshauthzservice), .subscribe(resp => this.makeKeyCert(newkeypair.private, resp, token.sshauthzservice),
error => this.httperrorLogout(error,token.sshauthzservice)); error => this.httperrorLogout(error,token.sshauthzservice));
console.log('getcert complete'); console.log('getcert complete');
} }
public getKeys(id?: Identity) {
try{
return JSON.parse(sessionStorage.getItem('keys'));
} catch {
return [];
}
}
makeKeyCert(key: string, resp, sshauthzservice: SshAuthzServer) { makeKeyCert(key: string, resp, sshauthzservice: SshAuthzServer) {
let keyCert = new KeyCert() let keyCert = new KeyCert()
keyCert.key = key; keyCert.key = key;
keyCert.cert = resp['cert']; keyCert.cert = resp['cert'];
console.log('in make KeyCert',resp);
console.log('updating keycert',keyCert); console.log('updating keycert',keyCert);
this.tesService.sshAdd(keyCert); var keys: KeyCert[] = [];
try{
keys = JSON.parse(sessionStorage.getItem('keys'));
} catch {
keys = [];
}
if (keys === null) {
keys = [];
}
keys.push(keyCert);
sessionStorage.setItem('keys',JSON.stringify(keys))
this.sshAdd(keyCert);
let path=localStorage.getItem('path');
console.log('authorisation complete, ready to navigate back to the correct view',path);
// this.tesService.keyCert.next(keyCert); // this.tesService.keyCert.next(keyCert);
// As soon as the certificate has been generated, we log back out of the signing server // As soon as the certificate has been generated, we log back out of the signing server
if (!(sshauthzservice.logout === null)) { if (!(sshauthzservice.logout === null)) {
window.open(sshauthzservice.logout); window.open(sshauthzservice.logout);
} }
this.readyToNavigate.next(true); this.readyToNavigate.next([true,path]);
}
public querySshAgentError(error: any) {
this.agentContents.next([]);
if (error.status == 0) {
this.statusMsg.next("A network error occured. Are you connected to the internet?")
}
}
public updateAgentContents() {
this.statusMsg.next("Updating the list of available accounts");
let headers = new HttpHeaders();
let options = { headers: headers, withCredentials: true};
var anyvar: any;
this.http.get<any>(this.backendURI+'/sshagent',options)
// .pipe(catchError(this.handleError(anyvar)))
.subscribe(resp => { console.log('sshagent returned',resp); this.agentContents.next(resp); this.statusMsg.next("") },
error => this.querySshAgentError(error));
// .subscribe(resp => this.computeSitesService.updateIdentities(resp),
// error => this.httperror(error))
}
private killAgent() {
this.statusMsg.next("Logging out")
let headers = new HttpHeaders();
let options = { headers: headers, withCredentials: true};
var anyvar: any;
this.http.delete<any>(this.backendURI+'/sshagent',options)
.pipe(catchError(this.handleError(anyvar)))
.subscribe(resp => this.updateAgentContents(),
error => this.httperror(error));
}
public logout(): Boolean {
this.killAgent();
return true;
}
public sshAdd(keyCert: KeyCert) {
console.log('in authorisation service sshAdd');
if (keyCert.key == undefined) {
return;
}
let headers = new HttpHeaders();
let options = { headers: headers, withCredentials: true};
var anyvar: any;
this.statusMsg.next("Authorising ...")
let data = {'key': keyCert.key, 'cert': keyCert.cert};
this.http.post<any>(this.backendURI+'/sshagent',data,options)
.pipe(catchError(this.handleError(anyvar)))
.subscribe(resp => this.updateAgentContents(),
error => this.httperror(error))
} }
public login(authservice: SshAuthzServer) { public login(authservice: SshAuthzServer) {
let redirect_uri = window.location.origin+this.locationStrategy.getBaseHref()+"sshauthz_callback"; let redirect_uri = window.location.origin+this.locationStrategy.getBaseHref()+"sshauthz_callback";
let nonce="asdfzxcv"; let nonce="asdfzxcv";
console.log(this.location.path());
localStorage.setItem('authservice', JSON.stringify([authservice,nonce])); localStorage.setItem('authservice', JSON.stringify([authservice,nonce]));
localStorage.setItem('path', this.location.path());
console.log('login activated, pathname stored as',window.location.pathname);
if (authservice.scope == null) { if (authservice.scope == null) {
window.location.assign(authservice.authorise+"?response_type=token&redirect_uri="+redirect_uri+"&state="+nonce+"&client_id="+authservice.client_id); window.location.assign(authservice.authorise+"?response_type=token&redirect_uri="+redirect_uri+"&state="+nonce+"&client_id="+authservice.client_id);
} else { } else {
window.location.assign(authservice.authorise+"?response_type=token&redirect_uri="+redirect_uri+"&state="+nonce+"&client_id="+authservice.client_id+"&scope="+authservice.scope); window.location.assign(authservice.authorise+"?response_type=token&redirect_uri="+redirect_uri+"&state="+nonce+"&client_id="+authservice.client_id+"&scope="+authservice.scope);
} }
} }
// private handleError(error: HttpErrorResponse) {
// if (error.error instanceof ErrorEvent) {
// console.log('instance of ErrorEvent');
// console.log(error);
// // A client-side or network error occurred. Handle it accordingly.
// return throwError("Hmm, that didn't work. If you're using a local connection, please make sure Strudel-TES is running.");
// } else {
// console.log('NOT an instance of ErrorEvent');
// console.log(error);
// // Not sure if this code works correctly. It should update identities in case the error is
// // that the user isn't allowed to run the job
//
// var re = /identity/gi;
// let searchresult = error.error.message.search(re);
// if (searchresult != -1) {
// // this.getIdentities();