mirror of
https://github.com/bitwarden/browser.git
synced 2024-12-24 16:49:26 +01:00
deauth sessions
This commit is contained in:
parent
0599dd1525
commit
aed5db0a8c
@ -34,6 +34,7 @@ import { TwoFactorComponent } from './accounts/two-factor.component';
|
|||||||
import { AccountComponent } from './settings/account.component';
|
import { AccountComponent } from './settings/account.component';
|
||||||
import { ChangeEmailComponent } from './settings/change-email.component';
|
import { ChangeEmailComponent } from './settings/change-email.component';
|
||||||
import { ChangePasswordComponent } from './settings/change-password.component';
|
import { ChangePasswordComponent } from './settings/change-password.component';
|
||||||
|
import { DeauthorizeSessionsComponent } from './settings/deauthorize-sessions.component';
|
||||||
import { ProfileComponent } from './settings/profile.component';
|
import { ProfileComponent } from './settings/profile.component';
|
||||||
import { SettingsComponent } from './settings/settings.component';
|
import { SettingsComponent } from './settings/settings.component';
|
||||||
|
|
||||||
@ -102,6 +103,7 @@ import { SearchCiphersPipe } from 'jslib/angular/pipes/search-ciphers.pipe';
|
|||||||
ChangePasswordComponent,
|
ChangePasswordComponent,
|
||||||
CiphersComponent,
|
CiphersComponent,
|
||||||
CollectionsComponent,
|
CollectionsComponent,
|
||||||
|
DeauthorizeSessionsComponent,
|
||||||
ExportComponent,
|
ExportComponent,
|
||||||
FallbackSrcDirective,
|
FallbackSrcDirective,
|
||||||
FolderAddEditComponent,
|
FolderAddEditComponent,
|
||||||
@ -142,6 +144,7 @@ import { SearchCiphersPipe } from 'jslib/angular/pipes/search-ciphers.pipe';
|
|||||||
BulkMoveComponent,
|
BulkMoveComponent,
|
||||||
BulkShareComponent,
|
BulkShareComponent,
|
||||||
CollectionsComponent,
|
CollectionsComponent,
|
||||||
|
DeauthorizeSessionsComponent,
|
||||||
FolderAddEditComponent,
|
FolderAddEditComponent,
|
||||||
ModalComponent,
|
ModalComponent,
|
||||||
PasswordGeneratorHistoryComponent,
|
PasswordGeneratorHistoryComponent,
|
||||||
|
@ -17,3 +17,5 @@
|
|||||||
<button type="button" class="btn btn-outline-secondary" (click)="deauthorizeSessions()">{{'deauthorizeSessions' | i18n}}</button>
|
<button type="button" class="btn btn-outline-secondary" (click)="deauthorizeSessions()">{{'deauthorizeSessions' | i18n}}</button>
|
||||||
<button type="button" class="btn btn-outline-secondary" (click)="purgeVault()">{{'purgeVault' | i18n}}</button>
|
<button type="button" class="btn btn-outline-secondary" (click)="purgeVault()">{{'purgeVault' | i18n}}</button>
|
||||||
<button type="button" class="btn btn-outline-secondary" (click)="deleteAccount()">{{'deleteAccount' | i18n}}</button>
|
<button type="button" class="btn btn-outline-secondary" (click)="deleteAccount()">{{'deleteAccount' | i18n}}</button>
|
||||||
|
|
||||||
|
<ng-template #deauthorizeSessionsTemplate></ng-template>
|
||||||
|
@ -1,12 +1,36 @@
|
|||||||
import { Component } from '@angular/core';
|
import {
|
||||||
|
Component,
|
||||||
|
ComponentFactoryResolver,
|
||||||
|
ViewChild,
|
||||||
|
ViewContainerRef,
|
||||||
|
} from '@angular/core';
|
||||||
|
|
||||||
|
import { ModalComponent } from '../modal.component';
|
||||||
|
import { DeauthorizeSessionsComponent } from './deauthorize-sessions.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-account',
|
selector: 'app-account',
|
||||||
templateUrl: 'account.component.html',
|
templateUrl: 'account.component.html',
|
||||||
})
|
})
|
||||||
export class AccountComponent {
|
export class AccountComponent {
|
||||||
deauthorizeSessions() {
|
@ViewChild('deauthorizeSessionsTemplate', { read: ViewContainerRef }) deauthModalRef: ViewContainerRef;
|
||||||
|
|
||||||
|
private modal: ModalComponent = null;
|
||||||
|
|
||||||
|
constructor(private componentFactoryResolver: ComponentFactoryResolver) { }
|
||||||
|
|
||||||
|
deauthorizeSessions() {
|
||||||
|
if (this.modal != null) {
|
||||||
|
this.modal.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
const factory = this.componentFactoryResolver.resolveComponentFactory(ModalComponent);
|
||||||
|
this.modal = this.deauthModalRef.createComponent(factory).instance;
|
||||||
|
this.modal.show<DeauthorizeSessionsComponent>(DeauthorizeSessionsComponent, this.deauthModalRef);
|
||||||
|
|
||||||
|
this.modal.onClosed.subscribe(async () => {
|
||||||
|
this.modal = null;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
purgeVault() {
|
purgeVault() {
|
||||||
|
29
src/app/settings/deauthorize-sessions.component.html
Normal file
29
src/app/settings/deauthorize-sessions.component.html
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<div class="modal fade">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<form class="modal-content" #form (ngSubmit)="submit()" [appApiAction]="formPromise">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h2 class="modal-title">{{'deauthorizeSessions' | i18n}}</h2>
|
||||||
|
<button type="button" class="close" data-dismiss="modal" attr.aria-label="{{'close' | i18n}}">
|
||||||
|
<span aria-hidden="true">×</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<p>{{'deauthorizeSessionsDesc' | i18n}}</p>
|
||||||
|
<div class="alert alert-warning" role="alert">
|
||||||
|
<h4 class="alert-heading">{{'warning' | i18n}}</h4>
|
||||||
|
<p class="mb-0">{{'deauthorizeSessionsWarning' | i18n}}</p>
|
||||||
|
</div>
|
||||||
|
<label for="masterPassword">{{'masterPass' | i18n}}</label>
|
||||||
|
<input id="masterPassword" type="password" name="MasterPasswordHash" class="form-control" [(ngModel)]="masterPassword" required
|
||||||
|
appAutoFocus>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button appBlurClick type="submit" class="btn btn-primary btn-submit" [disabled]="form.loading">
|
||||||
|
<i class="fa fa-spinner fa-spin"></i>
|
||||||
|
<span>{{'submit' | i18n}}</span>
|
||||||
|
</button>
|
||||||
|
<button type="button" class="btn btn-outline-secondary" data-dismiss="modal">{{'close' | i18n}}</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
45
src/app/settings/deauthorize-sessions.component.ts
Normal file
45
src/app/settings/deauthorize-sessions.component.ts
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
import {
|
||||||
|
Component,
|
||||||
|
} from '@angular/core';
|
||||||
|
|
||||||
|
import { ToasterService } from 'angular2-toaster';
|
||||||
|
import { Angulartics2 } from 'angulartics2';
|
||||||
|
|
||||||
|
import { ApiService } from 'jslib/abstractions/api.service';
|
||||||
|
import { CryptoService } from 'jslib/abstractions/crypto.service';
|
||||||
|
import { I18nService } from 'jslib/abstractions/i18n.service';
|
||||||
|
import { MessagingService } from 'jslib/abstractions/messaging.service';
|
||||||
|
|
||||||
|
import { PasswordVerificationRequest } from 'jslib/models/request/passwordVerificationRequest';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-deauthorize-sessions',
|
||||||
|
templateUrl: 'deauthorize-sessions.component.html',
|
||||||
|
})
|
||||||
|
export class DeauthorizeSessionsComponent {
|
||||||
|
masterPassword: string;
|
||||||
|
formPromise: Promise<any>;
|
||||||
|
|
||||||
|
constructor(private apiService: ApiService, private i18nService: I18nService,
|
||||||
|
private analytics: Angulartics2, private toasterService: ToasterService,
|
||||||
|
private cryptoService: CryptoService, private messagingService: MessagingService) { }
|
||||||
|
|
||||||
|
async submit() {
|
||||||
|
if (this.masterPassword == null || this.masterPassword === '') {
|
||||||
|
this.toasterService.popAsync('error', this.i18nService.t('errorOccurred'),
|
||||||
|
this.i18nService.t('masterPassRequired'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const request = new PasswordVerificationRequest();
|
||||||
|
request.masterPasswordHash = await this.cryptoService.hashPassword(this.masterPassword, null);
|
||||||
|
try {
|
||||||
|
this.formPromise = this.apiService.postSecurityStamp(request);
|
||||||
|
await this.formPromise;
|
||||||
|
this.analytics.eventTrack.next({ action: 'Deauthorized Sessions' });
|
||||||
|
this.toasterService.popAsync('success', this.i18nService.t('sessionsDeauthorized'),
|
||||||
|
this.i18nService.t('logBackIn'));
|
||||||
|
this.messagingService.send('logout');
|
||||||
|
} catch { }
|
||||||
|
}
|
||||||
|
}
|
@ -818,6 +818,15 @@
|
|||||||
"deauthorizeSessions": {
|
"deauthorizeSessions": {
|
||||||
"message": "Deauthorize Sessions"
|
"message": "Deauthorize Sessions"
|
||||||
},
|
},
|
||||||
|
"deauthorizeSessionsDesc": {
|
||||||
|
"message": "Concerned your account is logged in on another device? Proceed below to deauthorize all computers or devices that you have previously used. This security step is recommended if you previously used a public PC or accidentally saved your password on a device that isn't yours. This step will also clear all previously remembered two-step login sessions."
|
||||||
|
},
|
||||||
|
"deauthorizeSessionsWarning": {
|
||||||
|
"message": "Proceeding will also log you out of your current session, requiring you to log back in. You will also be prompted for two-step login again, if enabled. Active sessions on other devices may continue to remain active for up to one hour."
|
||||||
|
},
|
||||||
|
"sessionsDeauthorized": {
|
||||||
|
"message": "All Sessions Deauthorized"
|
||||||
|
},
|
||||||
"purgeVault": {
|
"purgeVault": {
|
||||||
"message": "Purge Vault"
|
"message": "Purge Vault"
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user