Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New interface to generate/modify Private/Public key for SIDP Users only #1689 #1736

Merged
merged 2 commits into from
Aug 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import {PublicKeyJson} from '../../principal/PublicKeyJson';
import {Equitable} from '@enonic/lib-admin-ui/Equitable';
import {ObjectHelper} from '@enonic/lib-admin-ui/ObjectHelper';

export class PublicKey
implements Equitable {

private readonly kid: string;

private readonly publicKey: string;

private readonly creationTime: string;

private readonly label: string;

constructor(kid: string, publicKey: string, creationTime: string, label?: string) {
this.kid = kid;
this.publicKey = publicKey;
this.creationTime = creationTime;
this.label = label || '';
}

getKid(): string {
return this.kid;
}

getPublicKey(): string {
return this.publicKey;
}

getLabel(): string {
return this.label;
}

getCreationTime(): string {
return this.creationTime;
}

equals(o: Equitable): boolean {
if (!ObjectHelper.iFrameSafeInstanceOf(o, PublicKey)) {
return false;
}

let other = o as PublicKey;

if (!ObjectHelper.stringEquals(this.getKid(), other.getKid())) {
return false;
}
if (!ObjectHelper.stringEquals(this.getPublicKey(), other.getPublicKey())) {
return false;
}
if (!ObjectHelper.stringEquals(this.getCreationTime(), other.getCreationTime())) {
return false;
}
if (!ObjectHelper.stringEquals(this.getLabel(), other.getLabel())) {
return false;
}

return true;
}

static fromJson(json: PublicKeyJson): PublicKey {
return new PublicKey(json.kid, json.publicKey, json.creationTime, json.label);
}

}
6 changes: 6 additions & 0 deletions src/main/resources/assets/js/app/principal/PublicKeyJson.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export interface PublicKeyJson {
kid: string;
publicKey: string;
creationTime: string;
label?: string;
}
17 changes: 16 additions & 1 deletion src/main/resources/assets/js/app/principal/User.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {UserJson} from './UserJson';
import {assert} from '@enonic/lib-admin-ui/util/Assert';
import {Equitable} from '@enonic/lib-admin-ui/Equitable';
import {ObjectHelper} from '@enonic/lib-admin-ui/ObjectHelper';
import {PublicKey} from '../browse/serviceaccount/PublicKey';

export class User
extends Principal {
Expand All @@ -16,13 +17,16 @@ export class User

private readonly memberships: Principal[];

private readonly publicKeys: PublicKey[];

constructor(builder: UserBuilder) {
super(builder);
assert(this.getKey().isUser(), 'Expected PrincipalKey of type User');
this.email = builder.email || '';
this.login = builder.login || '';
this.loginDisabled = builder.loginDisabled || false;
this.memberships = builder.memberships || [];
this.publicKeys = builder.publicKeys || [];
}

getEmail(): string {
Expand All @@ -41,6 +45,10 @@ export class User
return this.memberships.slice(0);
}

getPublicKeys(): PublicKey[] {
return this.publicKeys.slice(0);
}

equals(o: Equitable): boolean {
if (!ObjectHelper.iFrameSafeInstanceOf(o, User)) {
return false;
Expand All @@ -52,7 +60,8 @@ export class User
this.loginDisabled === other.isDisabled() &&
this.email === other.getEmail() &&
this.login === other.getLogin() &&
ObjectHelper.arrayEquals(this.memberships, other.getMemberships());
ObjectHelper.arrayEquals(this.memberships, other.getMemberships()) &&
ObjectHelper.arrayEquals(this.publicKeys, other.getPublicKeys());
}

clone(): User {
Expand Down Expand Up @@ -84,6 +93,8 @@ export class UserBuilder

memberships: Principal[] = [];

publicKeys: PublicKey[] = [];

constructor(source?: User) {
super(source);
if (source) {
Expand All @@ -94,6 +105,7 @@ export class UserBuilder
this.loginDisabled = source.isDisabled();
this.modifiedTime = source.getModifiedTime();
this.memberships = source.getMemberships().slice(0);
this.publicKeys = source.getPublicKeys().slice(0);
}
}

Expand All @@ -107,6 +119,9 @@ export class UserBuilder
if (json.memberships) {
this.memberships = json.memberships.map((principalJson) => Principal.fromJson(principalJson));
}
if (json.publicKeys) {
this.publicKeys = json.publicKeys.map((publicKeyJson) => PublicKey.fromJson(publicKeyJson));
}
return this;
}

Expand Down
3 changes: 3 additions & 0 deletions src/main/resources/assets/js/app/principal/UserJson.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {PrincipalJson} from '@enonic/lib-admin-ui/security/PrincipalJson';
import {PublicKeyJson} from './PublicKeyJson';

export interface UserJson
extends PrincipalJson {
Expand All @@ -13,4 +14,6 @@ export interface UserJson

memberships?: PrincipalJson[];

publicKeys?: PublicKeyJson[];

}
142 changes: 142 additions & 0 deletions src/main/resources/assets/js/app/view/PublicKeysGrid.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
import {DivEl} from '@enonic/lib-admin-ui/dom/DivEl';
import {AEl} from '@enonic/lib-admin-ui/dom/AEl';
import {i18n} from '@enonic/lib-admin-ui/util/Messages';
import {ConfirmationDialog} from '@enonic/lib-admin-ui/ui/dialog/ConfirmationDialog';
import {PublicKey} from '../browse/serviceaccount/PublicKey';
import {User} from '../principal/User';
import {DeletePublicKeyRequest} from '../../graphql/principal/user/DeletePublicKeyRequest';
import {UserKeyDetailsDialog} from '../wizard/UserKeyDetailsDialog';
import {DateHelper} from '@enonic/lib-admin-ui/util/DateHelper';
import {DefaultErrorHandler} from '@enonic/lib-admin-ui/DefaultErrorHandler';

export class PublicKeysGrid
extends DivEl {

private static GRID_CSS_STYLE = 'public-keys-grid';

private readonly tbody: DivEl;

constructor(className ?: string) {
super(className || '');

this.getEl().addClass(PublicKeysGrid.GRID_CSS_STYLE);

const header = this.createHeaderRow();

this.tbody = this.createDivEl(`${PublicKeysGrid.GRID_CSS_STYLE}-body`);

const container: DivEl = this.createDivEl(`${PublicKeysGrid.GRID_CSS_STYLE}-container`, 'table');
container.appendChild(header);
container.appendChild(this.tbody);

this.appendChild(container);
}

setUser(user: User): void {
this.tbody.removeChildren();
user.getPublicKeys().forEach((publicKey: PublicKey) => {
this.addPublicKey(user, publicKey);
});
}

addPublicKey(user: User, publicKey: PublicKey): void {
const row = this.createRow();
row.appendChild(this.createKidCell(publicKey));
row.appendChild(this.createCell(publicKey.getLabel()));

const creationTime = new Date(Date.parse(publicKey.getCreationTime()));
row.appendChild(this.createCell(DateHelper.formatDateTime(creationTime)));

row.appendChild(this.createActionCell(user, publicKey, row));

this.tbody.appendChild(row);
}

private createHeaderRow(): DivEl {
const header = this.createRow();

header.appendChild(this.createHeader(i18n('field.userKeys.grid.kid.column')));
header.appendChild(this.createHeader(i18n('field.userKeys.grid.label.column')));
header.appendChild(this.createHeader(i18n('field.userKeys.grid.creationTime.column')));
header.appendChild(this.createHeader(i18n('field.userKeys.grid.actions.column')));

return header;
}

private createHeader(text: string): DivEl {
const header = this.createDivEl(`${PublicKeysGrid.GRID_CSS_STYLE}-header`, 'columnheader');
header.setHtml(text);
return header;
}

private createRow(): DivEl {
return this.createDivEl(`${PublicKeysGrid.GRID_CSS_STYLE}-row`, 'rowgroup');
}

private createCell(text?: string): DivEl {
return this.createDivEl(`${PublicKeysGrid.GRID_CSS_STYLE}-cell`, 'cell', text);
}

private createKidCell(publicKey: PublicKey): DivEl {
const cell = this.createCell();
const showKidLink = this.createShowButton(publicKey);
cell.appendChild(showKidLink);
return cell;
}

private createActionCell(user: User, publicKey: PublicKey, rowEl: DivEl): DivEl {
const actionCell = this.createCell();
const removeButton = this.createRemoveButton(user, publicKey, rowEl);
actionCell.appendChild(removeButton);
return actionCell;
}

private createShowButton(publicKey: PublicKey): AEl {
const showButton = new AEl('show-public-key');
showButton.setHtml(publicKey.getKid());
showButton.onClicked((event: MouseEvent) => {
event.stopPropagation();
event.preventDefault();
new UserKeyDetailsDialog(publicKey.getPublicKey()).open();
return false;
});
return showButton;
}

private createRemoveButton(user: User, publicKey: PublicKey, rowEl: DivEl): AEl {
const removeButton = new AEl('remove-public-key icon-close');
removeButton.onClicked((event: MouseEvent) => {
event.stopPropagation();
event.preventDefault();

const confirmation = new ConfirmationDialog()
.setQuestion(i18n('dialog.delete.question'))
.setNoCallback(null)
.setYesCallback(() => {
new DeletePublicKeyRequest().setKey(user.getKey()).setKid(publicKey.getKid()).sendAndParse().then((removed) => {
if (removed) {
rowEl.remove();
}
}).catch((reason: Error) => {
DefaultErrorHandler.handle(reason);
});
});
confirmation.open();

return false;
});
return removeButton;
}

private createDivEl(className?: string, role?: string, html?: string): DivEl {
const divEl = new DivEl(className || '');
if (role) {
divEl.getEl().setAttribute('role', role);
}
if (html) {
divEl.setHtml(html);
}
return divEl;
}

}
Loading