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

feat: magnus 允许 token 多次使用 #819

Merged
merged 2 commits into from
May 10, 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
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