Update the way for generating new cli secret (#17744)

Update the way for refreshing cli-secret

Signed-off-by: AllForNothing <sshijun@vmware.com>

Signed-off-by: AllForNothing <sshijun@vmware.com>
This commit is contained in:
Shijun Sun 2022-11-03 21:04:04 +08:00 committed by GitHub
parent 93ac2e8111
commit 10cb2fd2c7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 54 additions and 158 deletions

View File

@ -12,7 +12,8 @@
// For developing // For developing
"start": "node --max_old_space_size=2048 ./node_modules/@angular/cli/bin/ng serve --ssl true --host 0.0.0.0 --proxy-config proxy.config.json", "start": "node --max_old_space_size=2048 ./node_modules/@angular/cli/bin/ng serve --ssl true --host 0.0.0.0 --proxy-config proxy.config.json",
"start:prod": "node --max_old_space_size=2048 ./node_modules/@angular/cli/bin/ng serve --ssl true --host 0.0.0.0 --proxy-config proxy.config.json --configuration production", "start:prod": "node --max_old_space_size=2048 ./node_modules/@angular/cli/bin/ng serve --ssl true --host 0.0.0.0 --proxy-config proxy.config.json --configuration production",
"start_default_port": "node --max_old_space_size=2048 ./node_modules/@angular/cli/bin/ng serve --ssl true --host 0.0.0.0 --port 443 --disable-host-check --proxy-config proxy.config.json",
// For code grammar checking // For code grammar checking
"lint": "tslint \"src/**/*.ts\"", "lint": "tslint \"src/**/*.ts\"",
"lint_fix": "tslint --fix \"src/**/*.ts\"", "lint_fix": "tslint --fix \"src/**/*.ts\"",

View File

@ -7,6 +7,7 @@
"postinstall": "node scripts/convert-yaml-to-json.js && ng-swagger-gen -i ng-swagger-gen/swagger.json -o ng-swagger-gen && node scripts/delete-swagger-json.js", "postinstall": "node scripts/convert-yaml-to-json.js && ng-swagger-gen -i ng-swagger-gen/swagger.json -o ng-swagger-gen && node scripts/delete-swagger-json.js",
"start": "node --max_old_space_size=2048 ./node_modules/@angular/cli/bin/ng serve --ssl true --host 0.0.0.0 --proxy-config proxy.config.json", "start": "node --max_old_space_size=2048 ./node_modules/@angular/cli/bin/ng serve --ssl true --host 0.0.0.0 --proxy-config proxy.config.json",
"start:prod": "node --max_old_space_size=2048 ./node_modules/@angular/cli/bin/ng serve --ssl true --host 0.0.0.0 --proxy-config proxy.config.json --configuration production", "start:prod": "node --max_old_space_size=2048 ./node_modules/@angular/cli/bin/ng serve --ssl true --host 0.0.0.0 --proxy-config proxy.config.json --configuration production",
"start_default_port": "node --max_old_space_size=2048 ./node_modules/@angular/cli/bin/ng serve --ssl true --host 0.0.0.0 --port 443 --disable-host-check --proxy-config proxy.config.json",
"lint": "ng lint", "lint": "ng lint",
"lint_fix": "ng lint --fix", "lint_fix": "ng lint --fix",
"lint:style": "npx stylelint \"**/*.scss\"", "lint:style": "npx stylelint \"**/*.scss\"",

View File

@ -1,19 +0,0 @@
import { TestBed } from '@angular/core/testing';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { AccountSettingsModalService } from './account-settings-modal-service.service';
describe('AccountSettingsModalServiceService', () => {
beforeEach(() =>
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
providers: [AccountSettingsModalService],
})
);
it('should be created', () => {
const service: AccountSettingsModalService = TestBed.get(
AccountSettingsModalService
);
expect(service).toBeTruthy();
});
});

View File

@ -1,20 +0,0 @@
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { catchError, map } from 'rxjs/operators';
import { throwError as observableThrowError, Observable } from 'rxjs';
import { CURRENT_BASE_HREF } from '../../shared/units/utils';
@Injectable({
providedIn: 'root',
})
export class AccountSettingsModalService {
constructor(private http: HttpClient) {}
saveNewCli(userId, secretObj): Observable<any> {
return this.http
.put(`${CURRENT_BASE_HREF}/users/${userId}/cli_secret`, secretObj)
.pipe(
map(response => response),
catchError(error => observableThrowError(error))
);
}
}

View File

@ -346,4 +346,4 @@
</clr-modal> </clr-modal>
<confirmation-dialog <confirmation-dialog
#confirmationDialog #confirmationDialog
(confirmAction)="confirmGenerate($event)"></confirmation-dialog> (confirmAction)="confirmGenerate()"></confirmation-dialog>

View File

@ -4,7 +4,6 @@ import { AccountSettingsModalComponent } from './account-settings-modal.componen
import { SessionService } from '../../shared/services/session.service'; import { SessionService } from '../../shared/services/session.service';
import { MessageHandlerService } from '../../shared/services/message-handler.service'; import { MessageHandlerService } from '../../shared/services/message-handler.service';
import { SearchTriggerService } from '../../shared/components/global-search/search-trigger.service'; import { SearchTriggerService } from '../../shared/components/global-search/search-trigger.service';
import { AccountSettingsModalService } from './account-settings-modal-service.service';
import { CUSTOM_ELEMENTS_SCHEMA, ChangeDetectorRef } from '@angular/core'; import { CUSTOM_ELEMENTS_SCHEMA, ChangeDetectorRef } from '@angular/core';
import { ClarityModule } from '@clr/angular'; import { ClarityModule } from '@clr/angular';
import { TranslateModule, TranslateService } from '@ngx-translate/core'; import { TranslateModule, TranslateService } from '@ngx-translate/core';
@ -18,6 +17,7 @@ import { ConfirmationDialogComponent } from '../../shared/components/confirmatio
import { InlineAlertComponent } from '../../shared/components/inline-alert/inline-alert.component'; import { InlineAlertComponent } from '../../shared/components/inline-alert/inline-alert.component';
import { ConfirmationDialogService } from '../global-confirmation-dialog/confirmation-dialog.service'; import { ConfirmationDialogService } from '../global-confirmation-dialog/confirmation-dialog.service';
import { ConfirmationMessage } from '../global-confirmation-dialog/confirmation-message'; import { ConfirmationMessage } from '../global-confirmation-dialog/confirmation-message';
import { UserService } from '../../../../ng-swagger-gen/services/user.service';
describe('AccountSettingsModalComponent', () => { describe('AccountSettingsModalComponent', () => {
let component: AccountSettingsModalComponent; let component: AccountSettingsModalComponent;
@ -54,9 +54,6 @@ describe('AccountSettingsModalComponent', () => {
let fakeSearchTriggerService = { let fakeSearchTriggerService = {
closeSearch: () => {}, closeSearch: () => {},
}; };
let fakeAccountSettingsModalService = {
saveNewCli: () => of(null),
};
let fakeConfirmationDialogService = { let fakeConfirmationDialogService = {
cancel: () => of(null), cancel: () => of(null),
confirm: () => of(null), confirm: () => of(null),
@ -68,6 +65,15 @@ describe('AccountSettingsModalComponent', () => {
navigate: () => {}, navigate: () => {},
}; };
const fakedUserService = {
getCurrentUserInfo() {
return of({});
},
setCliSecret() {
return of(null);
},
};
beforeEach(async () => { beforeEach(async () => {
await TestBed.configureTestingModule({ await TestBed.configureTestingModule({
declarations: [ declarations: [
@ -96,8 +102,8 @@ describe('AccountSettingsModalComponent', () => {
useValue: fakeSearchTriggerService, useValue: fakeSearchTriggerService,
}, },
{ {
provide: AccountSettingsModalService, provide: UserService,
useValue: fakeAccountSettingsModalService, useValue: fakedUserService,
}, },
{ provide: Router, useValue: fakeRouter }, { provide: Router, useValue: fakeRouter },
{ {
@ -261,7 +267,7 @@ describe('AccountSettingsModalComponent', () => {
ConfirmationDialogComponent ConfirmationDialogComponent
).componentInstance; ).componentInstance;
generateCliButton.dispatchEvent(new Event('click')); generateCliButton.dispatchEvent(new Event('click'));
component.confirmGenerate(null); component.confirmGenerate();
await fixture.whenStable(); await fixture.whenStable();
expect(component.showGenerateCli).toEqual(false); expect(component.showGenerateCli).toEqual(false);
}); });

View File

@ -19,8 +19,6 @@ import { SessionUser } from '../../shared/entities/session-user';
import { SessionService } from '../../shared/services/session.service'; import { SessionService } from '../../shared/services/session.service';
import { MessageHandlerService } from '../../shared/services/message-handler.service'; import { MessageHandlerService } from '../../shared/services/message-handler.service';
import { SearchTriggerService } from '../../shared/components/global-search/search-trigger.service'; import { SearchTriggerService } from '../../shared/components/global-search/search-trigger.service';
import { AccountSettingsModalService } from './account-settings-modal-service.service';
import { randomWord } from '../../shared/units/shared.utils';
import { ResetSecret } from './account'; import { ResetSecret } from './account';
import { CopyInputComponent } from '../../shared/components/push-image/copy-input.component'; import { CopyInputComponent } from '../../shared/components/push-image/copy-input.component';
import { import {
@ -31,6 +29,7 @@ import {
import { ConfirmationDialogComponent } from '../../shared/components/confirmation-dialog'; import { ConfirmationDialogComponent } from '../../shared/components/confirmation-dialog';
import { InlineAlertComponent } from '../../shared/components/inline-alert/inline-alert.component'; import { InlineAlertComponent } from '../../shared/components/inline-alert/inline-alert.component';
import { ConfirmationMessage } from '../global-confirmation-dialog/confirmation-message'; import { ConfirmationMessage } from '../global-confirmation-dialog/confirmation-message';
import { UserService } from 'ng-swagger-gen/services/user.service';
@Component({ @Component({
selector: 'account-settings-modal', selector: 'account-settings-modal',
@ -73,7 +72,7 @@ export class AccountSettingsModalComponent implements OnInit, AfterViewChecked {
private msgHandler: MessageHandlerService, private msgHandler: MessageHandlerService,
private router: Router, private router: Router,
private searchTrigger: SearchTriggerService, private searchTrigger: SearchTriggerService,
private accountSettingsService: AccountSettingsModalService private userService: UserService
) {} ) {}
private validationStateMap: any = { private validationStateMap: any = {
@ -392,29 +391,41 @@ export class AccountSettingsModalComponent implements OnInit, AfterViewChecked {
this.showGenerateCli = !this.showGenerateCli; this.showGenerateCli = !this.showGenerateCli;
} }
confirmGenerate(event): void { confirmGenerate(): void {
this.account.oidc_user_meta.secret = randomWord(9); this.resetCliSecret(null);
this.resetCliSecret(this.account.oidc_user_meta.secret);
} }
resetCliSecret(secret) { resetCliSecret(secret) {
let userId = this.account.user_id; this.userService
this.accountSettingsService .setCliSecret({
.saveNewCli(userId, { secret: secret }) userId: this.account.user_id,
.subscribe( secret: secret
cliSecret => { ? {
this.account.oidc_user_meta.secret = secret; secret: secret,
}
: {},
})
.subscribe({
next: res => {
if (secret) {
this.account.oidc_user_meta.secret = secret;
} else {
this.userService.getCurrentUserInfo().subscribe(res => {
this.account.oidc_user_meta.secret =
res?.oidc_user_meta?.secret;
});
}
this.closeReset(); this.closeReset();
this.inlineAlert.showInlineSuccess({ this.inlineAlert.showInlineSuccess({
message: 'PROFILE.GENERATE_SUCCESS', message: 'PROFILE.GENERATE_SUCCESS',
}); });
}, },
error => { error: err => {
this.resetSecretInlineAlert.showInlineError({ this.resetSecretInlineAlert.showInlineError({
message: 'PROFILE.GENERATE_ERROR', message: 'PROFILE.GENERATE_ERROR',
}); });
} },
); });
} }
disableChangeCliSecret() { disableChangeCliSecret() {

View File

@ -19,11 +19,11 @@ import { AppConfigService } from '../../services/app-config.service';
import { ErrorHandler } from '../../shared/units/error-handler'; import { ErrorHandler } from '../../shared/units/error-handler';
import { AccountSettingsModalComponent } from '../account-settings/account-settings-modal.component'; import { AccountSettingsModalComponent } from '../account-settings/account-settings-modal.component';
import { InlineAlertComponent } from '../../shared/components/inline-alert/inline-alert.component'; import { InlineAlertComponent } from '../../shared/components/inline-alert/inline-alert.component';
import { AccountSettingsModalService } from '../account-settings/account-settings-modal-service.service';
import { ScannerService } from '../../../../ng-swagger-gen/services/scanner.service'; import { ScannerService } from '../../../../ng-swagger-gen/services/scanner.service';
import { HttpHeaders, HttpResponse } from '@angular/common/http'; import { HttpHeaders, HttpResponse } from '@angular/common/http';
import { Registry } from '../../../../ng-swagger-gen/models/registry'; import { Registry } from '../../../../ng-swagger-gen/models/registry';
import { delay } from 'rxjs/operators'; import { delay } from 'rxjs/operators';
import { UserService } from '../../../../ng-swagger-gen/services/user.service';
describe('HarborShellComponent', () => { describe('HarborShellComponent', () => {
let component: HarborShellComponent; let component: HarborShellComponent;
@ -38,7 +38,6 @@ describe('HarborShellComponent', () => {
searchCloseChan$: of(null), searchCloseChan$: of(null),
}; };
let mockMessageHandlerService = null; let mockMessageHandlerService = null;
let mockAccountSettingsModalService = null;
let mockPasswordSettingService = null; let mockPasswordSettingService = null;
let mockSkinableConfig = { let mockSkinableConfig = {
getSkinConfig: function () { getSkinConfig: function () {
@ -89,6 +88,14 @@ describe('HarborShellComponent', () => {
return of([]).pipe(delay(0)); return of([]).pipe(delay(0));
}, },
}; };
const fakedUserService = {
getCurrentUserInfo() {
return of({});
},
setCliSecret() {
return of(null);
},
};
beforeEach(async () => { beforeEach(async () => {
await TestBed.configureTestingModule({ await TestBed.configureTestingModule({
imports: [ imports: [
@ -119,8 +126,8 @@ describe('HarborShellComponent', () => {
useValue: mockMessageHandlerService, useValue: mockMessageHandlerService,
}, },
{ {
provide: AccountSettingsModalService, provide: UserService,
useValue: mockAccountSettingsModalService, useValue: fakedUserService,
}, },
{ {
provide: PasswordSettingService, provide: PasswordSettingService,

View File

@ -99,97 +99,6 @@ export const maintainUrlQueryParmas = function (
} }
} }
}; };
/**
* the password or secret must longer than 8 chars with at least 1 uppercase letter, 1 lowercase letter and 1 number
* @param randomFlag
* @param min
* @param max
* @returns {string}
*/
export function randomWord(max) {
let str = '';
let contentArray = [
['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'],
[
'a',
'b',
'c',
'd',
'e',
'f',
'g',
'h',
'i',
'j',
'k',
'l',
'm',
'n',
'o',
'p',
'q',
'r',
's',
't',
'u',
'v',
'w',
'x',
'y',
'z',
],
[
'A',
'B',
'C',
'D',
'E',
'F',
'G',
'H',
'I',
'J',
'K',
'L',
'M',
'N',
'O',
'P',
'Q',
'R',
'S',
'T',
'U',
'V',
'W',
'X',
'Y',
'Z',
],
];
for (let i = 0; i < max; i++) {
let randomNumber = getRandomInt(contentArray.length);
str +=
contentArray[randomNumber][
getRandomInt(contentArray[randomNumber].length)
];
}
if (!str.match(/\d+/g)) {
str += contentArray[0][getRandomInt(contentArray[0].length)];
}
if (!str.match(/[a-z]+/g)) {
str += contentArray[1][getRandomInt(contentArray[1].length)];
}
if (!str.match(/[A-Z]+/g)) {
str += contentArray[2][getRandomInt(contentArray[2].length)];
}
return str;
}
function getRandomInt(max) {
return Math.floor(Math.random() * Math.floor(max));
}
/** /**
* handle docker client response error * handle docker client response error