-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(webapp): add ssh key authentication (#796)
- Loading branch information
1 parent
6e878d8
commit a884cbb
Showing
17 changed files
with
584 additions
and
37 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
28 changes: 20 additions & 8 deletions
28
webapp/src/client/app/modules/web-client/form/form-components/ssh/ssh-form.component.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,23 @@ | ||
<div [formGroup]="form"> | ||
<div class="col-12 gateway-form-group"> | ||
<web-client-username-control [parentForm]="form" | ||
[inputFormData]="inputFormData"></web-client-username-control> | ||
<div class="col-4 gateway-form-group col-pad-right-lg"> | ||
<label for="authSettings">Authentication</label> | ||
<div class="gateway-form-input"> | ||
<p-dropdown id="authSettings" appendTo="body" formControlName="authMode" [options]="authModeOptions"> | ||
</p-dropdown> | ||
</div> | ||
</div> | ||
|
||
<div class="col-12 gateway-form-group"> | ||
<web-client-password-control [parentForm]="form" | ||
[inputFormData]="inputFormData"></web-client-password-control> | ||
</div> | ||
</div> | ||
<div class="col-12 gateway-form-group" *ngIf="formInputVisibility.showUsernameInput"> | ||
<web-client-username-control [parentForm]="form" [inputFormData]="inputFormData"></web-client-username-control> | ||
</div> | ||
|
||
<div class="col-12 gateway-form-group" *ngIf="formInputVisibility.showPasswordInput"> | ||
<web-client-password-control [parentForm]="form" [inputFormData]="inputFormData" | ||
[isEnabled]="formInputVisibility.showPasswordInput"></web-client-password-control> | ||
</div> | ||
|
||
<div *ngIf="formInputVisibility.showPrivateKeyInput"> | ||
<app-file-control privateKeyFileForm ></app-file-control> | ||
</div> | ||
|
||
</div> |
117 changes: 110 additions & 7 deletions
117
webapp/src/client/app/modules/web-client/form/form-components/ssh/ssh-form.component.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,23 +1,126 @@ | ||
import {Component, Input, OnInit} from '@angular/core'; | ||
import {FormGroup} from "@angular/forms"; | ||
import { | ||
AfterViewInit, | ||
Component, | ||
Injectable, | ||
Input, | ||
OnDestroy, | ||
OnInit, | ||
} from '@angular/core'; | ||
import { FormControl, FormGroup } from '@angular/forms'; | ||
|
||
import {BaseComponent} from "@shared/bases/base.component"; | ||
import { BaseComponent } from '@shared/bases/base.component'; | ||
import { SelectItem } from 'primeng/api'; | ||
import { WebFormService } from '@gateway/shared/services/web-form.service'; | ||
import { map, startWith, switchMap, takeUntil, tap } from 'rxjs/operators'; | ||
import { SshAuthMode } from '@gateway/shared/enums/web-client-auth-mode.enum'; | ||
import { Observable, of } from 'rxjs'; | ||
import { SshKeyService } from '@gateway/shared/services/ssh-key.service'; | ||
|
||
interface FormInputVisibility { | ||
showUsernameInput?: boolean; | ||
showPasswordInput?: boolean; | ||
showPrivateKeyInput?: boolean; | ||
} | ||
|
||
@Injectable({ providedIn: 'root' }) | ||
@Component({ | ||
selector: 'ssh-form', | ||
templateUrl: 'ssh-form.component.html', | ||
styleUrls: ['ssh-form.component.scss'] | ||
styleUrls: ['ssh-form.component.scss'], | ||
}) | ||
export class SshFormComponent extends BaseComponent implements OnInit { | ||
|
||
export class SshFormComponent | ||
extends BaseComponent | ||
implements OnInit, OnDestroy, AfterViewInit | ||
{ | ||
@Input() form: FormGroup; | ||
@Input() inputFormData: any; | ||
|
||
constructor() { | ||
authModeOptions: SelectItem[]; | ||
|
||
formInputVisibility: FormInputVisibility = { | ||
showUsernameInput: true, | ||
showPasswordInput: true, | ||
showPrivateKeyInput: false, | ||
}; | ||
|
||
constructor( | ||
private formService: WebFormService, | ||
private sshKeyService: SshKeyService | ||
) { | ||
super(); | ||
} | ||
|
||
ngAfterViewInit(): void { | ||
this.formService.canConnectIfAlsoTrue(() => { | ||
if (!this.formInputVisibility.showPrivateKeyInput) { | ||
return true; | ||
} | ||
|
||
return this.sshKeyService.hasValidPrivateKey(); | ||
}); | ||
} | ||
|
||
ngOnInit(): void { | ||
this.initializeFormOptions(); | ||
this.addControlsToParentForm(this.inputFormData); | ||
} | ||
|
||
ngOnDestroy(): void { | ||
this.formService.resetCanConnectCallback(); | ||
} | ||
|
||
private addControlsToParentForm(inputFormData?: any): void { | ||
if (this.form) { | ||
this.form.addControl( | ||
'authMode', | ||
new FormControl( | ||
inputFormData?.authMode || SshAuthMode.Username_and_Password | ||
) | ||
); | ||
this.subscribeToAuthModeChanges(); | ||
} | ||
} | ||
|
||
private initializeFormOptions(): void { | ||
this.formService | ||
.getAuthModeOptions('ssh') | ||
.pipe(takeUntil(this.destroyed$)) | ||
.subscribe({ | ||
next: (authModeOptions) => { | ||
this.authModeOptions = authModeOptions; | ||
}, | ||
error: (error) => | ||
console.error('Error fetching dropdown options', error), | ||
}); | ||
} | ||
|
||
private subscribeToAuthModeChanges(): void { | ||
this.form | ||
.get('authMode') | ||
.valueChanges.pipe( | ||
takeUntil(this.destroyed$), | ||
startWith(this.form.get('authMode').value as SshAuthMode), | ||
switchMap((authMode) => this.getFormInputVisibility(authMode)) | ||
) | ||
.subscribe(() => {}); | ||
} | ||
|
||
private getFormInputVisibility( | ||
authMode: SshAuthMode | ||
): Observable<SshAuthMode> { | ||
return of(this.formInputVisibility).pipe( | ||
tap((visibility) => { | ||
visibility.showUsernameInput = | ||
authMode === SshAuthMode.Username_and_Password || | ||
authMode === SshAuthMode.Private_Key; | ||
visibility.showPasswordInput = | ||
authMode === SshAuthMode.Username_and_Password; | ||
visibility.showPrivateKeyInput = authMode === SshAuthMode.Private_Key; | ||
}), | ||
map(() => { | ||
return authMode; | ||
}) | ||
); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
47 changes: 47 additions & 0 deletions
47
...client/app/modules/web-client/form/form-controls/file-control/file-control.component.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
<div> | ||
<div class="gateway-form-group"> | ||
<label>Private Key Data</label> | ||
<div class="card flex justify-content-center"> | ||
<p-fileUpload | ||
name="myFiles" | ||
maxFileSize="10240" | ||
(onSelect)="onSelect($event)" | ||
customUpload="true" | ||
[multiple]="false" | ||
[showUploadButton]="false" | ||
[showCancelButton]="false" | ||
chooseLabel="Select File" | ||
cancelLabel="Clear" | ||
styleClass="private-key-file-upload" | ||
chooseStyleClass = "select-file-button" | ||
> | ||
<ng-template | ||
let-file | ||
pTemplate="file" | ||
> | ||
<!-- Need to leave this as empty --> | ||
</ng-template> | ||
<ng-template pTemplate="content"> | ||
<textarea | ||
cols="30" | ||
rows="5" | ||
class="private-key-textarea" | ||
name="privateKeyData" | ||
pInputTextarea | ||
[(ngModel)]="privateKeyContent" | ||
wrap="soft" | ||
> | ||
</textarea> | ||
</ng-template> | ||
</p-fileUpload> | ||
</div> | ||
</div> | ||
</div> | ||
<div class="gateway-form-input password-container"> | ||
<div | ||
class="form-helper-text" | ||
*ngIf="privateKeyContent !== '' && !isValidFile()" | ||
> | ||
{{ getErrorMessage() }} | ||
</div> | ||
</div> |
91 changes: 91 additions & 0 deletions
91
...client/app/modules/web-client/form/form-controls/file-control/file-control.component.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
@import '../../../../../../../assets/css/style/mixins'; | ||
@import "../../../../../../../assets/css/style/variables"; | ||
@import "../../../../../../../assets/css/theme/theme-mode-variables"; | ||
|
||
::ng-deep p-fileUpload .p-fileupload-content .p-progressbar { | ||
display: none !important; | ||
} | ||
|
||
.file-container { | ||
display: flex; | ||
align-items: center; | ||
justify-content: space-between; | ||
margin: 10px 5px 10px 5px; | ||
} | ||
|
||
.form-helper-text { | ||
line-height: 11px; | ||
word-wrap: break-word; | ||
color: var(--status-error-text-color); | ||
font-size: 11px; | ||
font-family: Open Sans; | ||
font-weight: 400; | ||
padding-left: 0px; | ||
justify-content: flex-start; | ||
align-items: flex-start; | ||
gap: 10px; | ||
display: inline-flex | ||
} | ||
|
||
.highlight { | ||
background-color: #f0f0f0; | ||
} | ||
|
||
.gateway-form-group { | ||
padding: 0px 0px 18px 0px; | ||
} | ||
|
||
.flex-row{ | ||
display: flex; | ||
align-items: center; | ||
} | ||
|
||
.justify-end { | ||
justify-content: end; | ||
} | ||
|
||
.private-key-textarea{ | ||
margin-top: 5px; | ||
margin-bottom: 5px; | ||
resize: none; | ||
font-family: monospace; | ||
font-size: xx-small; | ||
line-height: 15px; | ||
} | ||
|
||
.card { | ||
border-radius: 10px; | ||
margin-bottom: 1rem; | ||
} | ||
|
||
.card p-fileupload { | ||
width: 100%; | ||
} | ||
|
||
::ng-deep .card p-fileupload .p-fileupload-buttonbar { | ||
display: flex; | ||
justify-content: end; | ||
flex-direction: row !important; | ||
} | ||
|
||
::ng-deep .card p-fileupload div { | ||
display: flex; | ||
flex-direction: column-reverse; | ||
} | ||
|
||
.file-row { | ||
display: flex; | ||
align-items: center; | ||
justify-content: space-between; | ||
} | ||
|
||
::ng-deep .card p-fileupload .p-button { | ||
background-color: white; | ||
border : 1px solid var(--default-btn-bg-color); | ||
color: var(--default-btn-bg-color); | ||
} | ||
|
||
::ng-deep .card p-fileupload .p-button:hover { | ||
background-color: var(--default-btn-bg-color); | ||
color: white; | ||
} |
Oops, something went wrong.