Skip to content

Commit

Permalink
feat: magnus 允许 token 多次使用
Browse files Browse the repository at this point in the history
  • Loading branch information
ibuler committed May 9, 2023
1 parent 3a19293 commit 9d73504
Show file tree
Hide file tree
Showing 11 changed files with 145 additions and 66 deletions.
35 changes: 23 additions & 12 deletions src/app/elements/connect/acl-dialog/acl-dialog.component.html
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
<div>
<h2 mat-dialog-title> {{ 'Login reminder' | translate }} </h2>

<div [ngSwitch]="code" >
<div [ngSwitch]="code">
<div *ngSwitchCase="'acl_reject'">
<mat-dialog-content>
<div class="error-message">{{ 'ACL reject login asset' | translate }}</div>
</mat-dialog-content>
<mat-dialog-actions>
<button mat-button color="primary" (click)="closeDialog()">{{ "Close" | translate }}</button>
<button (click)="closeDialog()" color="primary" mat-button>{{ "Close" | translate }}</button>
</mat-dialog-actions>
</div>

Expand All @@ -16,8 +16,8 @@ <h2 mat-dialog-title> {{ 'Login reminder' | translate }} </h2>
<div>{{ 'Need review for login asset' | translate }}</div>
</mat-dialog-content>
<mat-dialog-actions>
<button mat-raised-button (click)="onCancelReview()">{{ "Cancel" | translate }}</button>
<button mat-raised-button color="primary" (click)="onConfirmReview()">{{ "Confirm" | translate }}</button>
<button (click)="onCancelReview()" mat-raised-button>{{ "Cancel" | translate }}</button>
<button (click)="onConfirmReview()" color="primary" mat-raised-button>{{ "Confirm" | translate }}</button>
</mat-dialog-actions>
</div>

Expand All @@ -34,8 +34,10 @@ <h2 mat-dialog-title> {{ 'Login reminder' | translate }} </h2>
</div>
</mat-dialog-content>
<mat-dialog-actions>
<button mat-raised-button (click)="onCancelWait()">{{ "Cancel" | translate }}</button>
<button mat-raised-button color="primary" ngxClipboard [cbContent]="ticketDetailPageURL" (cbOnSuccess)="onCopySuccess($event)" >{{ "Copy link" | translate }}</button>
<button (click)="onCancelWait()" mat-raised-button>{{ "Cancel" | translate }}</button>
<button (cbOnSuccess)="onCopySuccess($event)" [cbContent]="ticketDetailPageURL" color="primary"
mat-raised-button
ngxClipboard>{{ "Copy link" | translate }}</button>
</mat-dialog-actions>
</div>

Expand All @@ -44,7 +46,7 @@ <h2 mat-dialog-title> {{ 'Login reminder' | translate }} </h2>
<div class="error-message">{{ 'Ticket review rejected for login asset' | translate }}</div>
</mat-dialog-content>
<mat-dialog-actions>
<button mat-raised-button (click)="closeDialog()">{{ "Close" | translate }}</button>
<button (click)="closeDialog()" mat-raised-button>{{ "Close" | translate }}</button>
</mat-dialog-actions>
</div>

Expand All @@ -53,7 +55,7 @@ <h2 mat-dialog-title> {{ 'Login reminder' | translate }} </h2>
<div class="error-message">{{ 'Ticket review closed for login asset' | translate }}</div>
</mat-dialog-content>
<mat-dialog-actions>
<button mat-raised-button (click)="closeDialog()">{{ "Close" | translate }}</button>
<button (click)="closeDialog()" mat-raised-button>{{ "Close" | translate }}</button>
</mat-dialog-actions>
</div>

Expand All @@ -62,18 +64,27 @@ <h2 mat-dialog-title> {{ 'Login reminder' | translate }} </h2>
<div class="error-message 11">{{ 'Account not found' | translate }}</div>
</mat-dialog-content>
<mat-dialog-actions>
<button mat-raised-button (click)="closeDialog()">{{ "Close" | translate }}</button>
<button (click)="closeDialog()" mat-raised-button>{{ "Close" | translate }}</button>
</mat-dialog-actions>
</div>

<div *ngSwitchCase="'other'">
<mat-dialog-content>
<div class="error-message">{{ otherError }}</div>>
<div class="error-message">{{ otherError }}</div>
>
</mat-dialog-content>
<mat-dialog-actions>
<button mat-raised-button (click)="closeDialog()">{{ "Close" | translate }}</button>
<button (click)="closeDialog()" mat-raised-button>{{ "Close" | translate }}</button>
</mat-dialog-actions>
</div>
</div>

<div *ngSwitchDefault>
<mat-dialog-content>
<div class="error-message">{{ data.error.error | json }}</div>
</mat-dialog-content>
<mat-dialog-actions>
<button (click)="closeDialog()" mat-raised-button>{{ "Close" | translate }}</button>
</mat-dialog-actions>
</div>
</div>
</div>
34 changes: 18 additions & 16 deletions src/app/elements/connect/acl-dialog/acl-dialog.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {Asset, ConnectData, ConnectionToken} from '@app/model';
import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material';
import {HttpService, I18nService} from '@app/services';
import {ToastrService} from 'ngx-toastr';
import {HttpErrorResponse} from '@angular/common/http';

@Component({
selector: 'elements-acl-dialog',
Expand All @@ -14,34 +15,35 @@ export class ElementACLDialogComponent implements OnInit {
public connectInfo: ConnectData;
public code: string;
public connectionToken: ConnectionToken = null;
public error: HttpErrorResponse;
public otherError: string;
public ticketAssignees: string = '-';
// Token 的行为,创建或者兑换 Token, create, exchange
public tokenAction: string = 'create';
public tokenID: string;
private timerCheckTicket: number;

constructor(public dialogRef: MatDialogRef<ElementACLDialogComponent>,
private _i18n: I18nService,
private _toastr: ToastrService,
private _http: HttpService,
@Inject(MAT_DIALOG_DATA) public data: any
) {
}

constructor( public dialogRef: MatDialogRef<ElementACLDialogComponent>,
private _i18n: I18nService,
private _toastr: ToastrService,
private _http: HttpService,
@Inject(MAT_DIALOG_DATA) public data: any
) {}
get ticketDetailPageURL(): string {
return this.connectionToken.from_ticket_info.ticket_detail_page_url;
}

ngOnInit() {
// 创建 Token 的时候,需要传入 Asset 和 ConnectInfo
this.asset = this.data.asset;
this.connectInfo = this.data.connectInfo;
this.code = this.data.code;
// 兑换 Token 的时候,需要传入 Token ID
this.tokenID = this.data.tokenID
this.tokenID = this.data.tokenID;
// 控制 token 的行为, 创建还是兑换
this.tokenAction = this.data.tokenAction
}

get ticketDetailPageURL(): string {
return this.connectionToken.from_ticket_info.ticket_detail_page_url;
this.tokenAction = this.data.tokenAction;
}

async onCopySuccess(evt) {
Expand All @@ -60,19 +62,19 @@ export class ElementACLDialogComponent implements OnInit {
this.code = 'ticket_review_pending';
this.checkTicket();
}
}
};
const errorCallback = (error) => {
if (error.error.code.startsWith('acl_')) {
this.code = error.error.code;
} else {
this.code = 'other';
this.otherError = error.error.detail;
}
}
};
if (this.tokenAction === 'exchange') {
this._http.exchangeConnectToken(this.tokenID, true).subscribe(successCallback, errorCallback)
this._http.exchangeConnectToken(this.tokenID, true).subscribe(successCallback, errorCallback);
} else {
this._http.createConnectToken(this.asset, this.connectInfo, true).subscribe(successCallback, errorCallback)
this._http.createConnectToken(this.asset, this.connectInfo, true).subscribe(successCallback, errorCallback);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,36 @@
<div class="content" *ngIf="!loading">
<div *ngIf="!loading" class="content">
<div>
<h2 class="subject">{{ 'Database connect info' | translate }}</h2>
<table>
<tr *ngFor="let item of infoItems">
<td class="title">{{ item.label | async }} </td>
<td class="text-td"
<td
#tooltip="matTooltip"
[matTooltip]="'Click to copy' | translate"
matTooltipPosition="right"
ngxClipboard
(cbOnSuccess)="onCopySuccess($event)"
(mouseenter)="onHoverClipRef($event)"
[cbContent]="this.info[item.name]"
[matTooltip]="hoverClipTip"
class="text-td"
matTooltipPosition="right"
ngxClipboard
>
<span *ngIf="item.name === 'password'" (click)="showPassword($event)" class="show-password">
<span (click)="showPassword($event)" *ngIf="item.name === 'password'" class="show-password">
<span style="vertical-align: middle">
{{ passwordShow }}
</span>
<i class="fa fa-eye"></i>
</span>
<span *ngIf="item.name !== 'password'">
<span *ngIf="item.name !== 'password' && item.name !== 'set_reusable'">
{{ this.info[item.name] }}
</span>
<span *ngIf="item.name == 'set_reusable'" class="reusable-button">
<mat-slide-toggle
(change)="setReusable($event)"
[(ngModel)]="token.is_reusable"
>
{{ "Re-use for a long time after opening" | translate }}
</mat-slide-toggle>
</span>
<span class="btn">
<i class="fa fa-clone icon"></i>
</span>
Expand All @@ -34,19 +44,21 @@ <h2 class="subject">
</h2>
<div class="command">
<pre>$ {{ cliSafe }}</pre>
<span class="start btn"
#tooltip="matTooltip"
[matTooltip]="'Run it by client' | translate"
(click)="startClient()"
<span #tooltip="matTooltip"
(click)="startClient()"
[matTooltip]="'Run it by client' | translate"
class="start btn"
>
<i class="fa fa-caret-square-o-right icon"></i>
</span>
<span class="btn"
<span
#tooltip="matTooltip"
[matTooltip]="'Click to copy' | translate"
ngxClipboard
[cbContent]="cli"
(cbOnSuccess)="onCopySuccess($event)"
(mouseenter)="onHoverClipRef($event)"
[cbContent]="cli"
[matTooltip]="hoverClipTip"
class="btn"
ngxClipboard
>
<i class="fa fa-clone icon"></i>
</span>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,3 +98,15 @@ iframe {
width: 15px;
height: 15px;
}

.reusable-button ::ng-deep {
.mat-slide-toggle-bar {
background-color: gray;
}
.mat-slide-toggle.mat-checked .mat-slide-toggle-bar {
background-color: var(--primary-color) !important;
}
.mat-slide-toggle.mat-checked:not(.mat-disabled) .mat-slide-toggle-thumb {
background-color: white;
}
}
50 changes: 37 additions & 13 deletions src/app/elements/content/content-window/magnus/magnus.component.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import {Component, Input, OnInit} from '@angular/core';
import {View, Account, Endpoint, Asset, ConnectionToken} from '@app/model';
import {Component, Input, OnInit, ViewChild} from '@angular/core';
import {Account, Asset, ConnectionToken, Endpoint, View} from '@app/model';
import {ConnectTokenService, HttpService, I18nService, SettingService} from '@app/services';
import {User} from '@app/globals';
import {ToastrService} from 'ngx-toastr';
import {MatTooltip} from '@angular/material/tooltip';

interface InfoItem {
name: string;
Expand All @@ -18,6 +19,7 @@ interface InfoItem {

export class ElementConnectorMagnusComponent implements OnInit {
@Input() view: View;
@ViewChild(MatTooltip, {static: false}) tooltip: MatTooltip;

asset: Asset;
account: Account;
Expand All @@ -34,6 +36,8 @@ export class ElementConnectorMagnusComponent implements OnInit {
passwordMask = '******';
passwordShow = '******';
token: ConnectionToken;
showSetReusable: boolean;
hoverClipTip: string = this._i18n.instant('Click to copy');

constructor(private _http: HttpService,
private _i18n: I18nService,
Expand All @@ -42,10 +46,11 @@ export class ElementConnectorMagnusComponent implements OnInit {
private _settingSvc: SettingService
) {
this.globalSetting = this._settingSvc.globalSetting;
this.showSetReusable = this.globalSetting.CONNECTION_TOKEN_REUSABLE;
}

async ngOnInit() {
const {asset, account, protocol, smartEndpoint, connectToken } = this.view;
const {asset, account, protocol, smartEndpoint, connectToken} = this.view;
this.token = connectToken;
this.asset = asset;
this.account = account;
Expand All @@ -57,7 +62,7 @@ export class ElementConnectorMagnusComponent implements OnInit {
this.setDBInfo();
this.generateConnCli();
this.loading = false;
this.view.termComp = this
this.view.termComp = this;
}

setDBInfo() {
Expand All @@ -69,11 +74,14 @@ export class ElementConnectorMagnusComponent implements OnInit {
{name: 'host', value: host, label: this._i18n.t('Host')},
{name: 'port', value: port, label: this._i18n.t('Port')},
{name: 'username', value: this.token.id, label: this._i18n.t('Username')},
{name: 'password', value: this.token.value, label: this._i18n.t('Password')},
{name: 'password', value: this.token.value, label: this._i18n.t('Password')},
{name: 'database', value: database, label: this._i18n.t('Database')},
{name: 'protocol', value: this.protocol, label: this._i18n.t('Protocol')},
{name: 'expire_time', value: `${this.token.expire_time} s` , label: this._i18n.t('Expire time')},
{name: 'date_expired', value: `${this.token.date_expired}`, label: this._i18n.t('Expire time')},
];
if (this.showSetReusable) {
this.infoItems.push({name: 'set_reusable', value: '', label: this._i18n.t('Set reusable')});
}
this.info = this.infoItems.reduce((pre, current) => {
pre[current.name] = current.value;
return pre;
Expand Down Expand Up @@ -126,6 +134,19 @@ export class ElementConnectorMagnusComponent implements OnInit {
this.cli = cli.replace(passwordHolder, password);
}

setReusable(event) {
this._connectTokenSvc.setReusable(this.token, event.checked).subscribe(
res => {
this.token = Object.assign(this.token, res);
this.info['date_expired'] = `${this.token.date_expired}`;
},
error => {
this.token.is_reusable = false;
this._toastr.error(error.error.msg || error.error.is_reusable || error.message);
}
);
}

startClient() {
const {protocol} = this.info;
const data = {
Expand All @@ -149,19 +170,22 @@ export class ElementConnectorMagnusComponent implements OnInit {
}

async onCopySuccess(evt) {
const msg = await this._i18n.t('Copied');
this._toastr.success(msg);
this.hoverClipTip = this._i18n.instant('Copied');
}

onHoverClipRef(evt) {
this.hoverClipTip = this._i18n.instant('Click to copy');
}

async reconnect() {
const oldConnectToken = this.view.connectToken
const newConnectToken = await this._connectTokenSvc.exchange(oldConnectToken)
const oldConnectToken = this.view.connectToken;
const newConnectToken = await this._connectTokenSvc.exchange(oldConnectToken);
if (!newConnectToken) {
return
return;
}
// 更新当前 view 的 connectToken
this.view.connectToken = newConnectToken
await this.ngOnInit()
this.view.connectToken = newConnectToken;
await this.ngOnInit();
// 刷新完成隐藏密码
this.passwordShow = this.passwordMask;
}
Expand Down
3 changes: 3 additions & 0 deletions src/app/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@ export class GlobalSetting {
INTERFACE: any;
TERMINAL_OMNIDB_ENABLED: boolean;
TERMINAL_GRAPHICAL_RESOLUTION: string;
CONNECTION_TOKEN_REUSABLE: boolean;
}

export class Setting {
Expand Down Expand Up @@ -389,6 +390,8 @@ export class ConnectionToken {
account: string;
expire_time: number;
is_active: boolean;
date_expired: Date;
is_reusable: boolean;
from_ticket: {
id: string;
};
Expand Down
Loading

0 comments on commit 9d73504

Please sign in to comment.