1
0
mirror of https://github.com/bitwarden/browser.git synced 2024-11-23 11:56:00 +01:00

Add support for collections with hide passwords

This commit is contained in:
hinton 2020-05-21 15:55:58 +02:00
parent ca43db8d93
commit 5bc01ea13e
10 changed files with 35 additions and 9 deletions

View File

@ -113,7 +113,7 @@ export class CollectionAddEditComponent implements OnInit {
request.name = (await this.cryptoService.encrypt(this.name, this.orgKey)).encryptedString; request.name = (await this.cryptoService.encrypt(this.name, this.orgKey)).encryptedString;
request.externalId = this.externalId; request.externalId = this.externalId;
request.groups = this.groups.filter((g) => (g as any).checked && !g.accessAll) request.groups = this.groups.filter((g) => (g as any).checked && !g.accessAll)
.map((g) => new SelectionReadOnlyRequest(g.id, !!(g as any).readOnly)); .map((g) => new SelectionReadOnlyRequest(g.id, !!(g as any).readOnly, !!(g as any).hidePasswords));
try { try {
if (this.editMode) { if (this.editMode) {

View File

@ -47,6 +47,8 @@
<th>{{'name' | i18n}}</th> <th>{{'name' | i18n}}</th>
<th *ngIf="entity === 'collection'">&nbsp;</th> <th *ngIf="entity === 'collection'">&nbsp;</th>
<th>{{'userType' | i18n}}</th> <th>{{'userType' | i18n}}</th>
<th width="100" class="text-center" *ngIf="entity === 'collection'">{{'hidePasswords' |
i18n}}</th>
<th width="100" class="text-center" *ngIf="entity === 'collection'">{{'readOnly' | <th width="100" class="text-center" *ngIf="entity === 'collection'">{{'readOnly' |
i18n}}</th> i18n}}</th>
</tr> </tr>
@ -85,6 +87,11 @@
<span *ngIf="u.type === organizationUserType.Manager">{{'manager' | i18n}}</span> <span *ngIf="u.type === organizationUserType.Manager">{{'manager' | i18n}}</span>
<span *ngIf="u.type === organizationUserType.User">{{'user' | i18n}}</span> <span *ngIf="u.type === organizationUserType.User">{{'user' | i18n}}</span>
</td> </td>
<td class="text-center" *ngIf="entity === 'collection'">
<input type="checkbox" [(ngModel)]="u.hidePasswords"
name="{{u.id.substr(0,8)}}_HidePasswords"
[disabled]="u.accessAll || !u.checked">
</td>
<td class="text-center" *ngIf="entity === 'collection'"> <td class="text-center" *ngIf="entity === 'collection'">
<input type="checkbox" [(ngModel)]="u.readOnly" name="{{u.id.substr(0,8)}}_ReadOnly" <input type="checkbox" [(ngModel)]="u.readOnly" name="{{u.id.substr(0,8)}}_ReadOnly"
[disabled]="u.accessAll || !u.checked"> [disabled]="u.accessAll || !u.checked">

View File

@ -78,6 +78,7 @@ export class EntityUsersComponent implements OnInit {
if (user != null && user.length > 0) { if (user != null && user.length > 0) {
(user[0] as any).checked = true; (user[0] as any).checked = true;
(user[0] as any).readOnly = s.readOnly; (user[0] as any).readOnly = s.readOnly;
(user[0] as any).hidePasswords = s.hidePasswords;
} }
}); });
} }
@ -107,6 +108,7 @@ export class EntityUsersComponent implements OnInit {
} else { } else {
if (this.entity === 'collection') { if (this.entity === 'collection') {
(u as any).readOnly = false; (u as any).readOnly = false;
(u as any).hidePasswords = false;
} }
this.selectedCount--; this.selectedCount--;
} }
@ -123,7 +125,7 @@ export class EntityUsersComponent implements OnInit {
this.formPromise = this.apiService.putGroupUsers(this.organizationId, this.entityId, selections); this.formPromise = this.apiService.putGroupUsers(this.organizationId, this.entityId, selections);
} else { } else {
const selections = this.users.filter((u) => (u as any).checked && !u.accessAll) const selections = this.users.filter((u) => (u as any).checked && !u.accessAll)
.map((u) => new SelectionReadOnlyRequest(u.id, !!(u as any).readOnly)); .map((u) => new SelectionReadOnlyRequest(u.id, !!(u as any).readOnly, !!(u as any).hidePasswords));
this.formPromise = this.apiService.putCollectionUsers(this.organizationId, this.entityId, selections); this.formPromise = this.apiService.putCollectionUsers(this.organizationId, this.entityId, selections);
} }
await this.formPromise; await this.formPromise;

View File

@ -59,6 +59,7 @@
<tr> <tr>
<th>&nbsp;</th> <th>&nbsp;</th>
<th>{{'name' | i18n}}</th> <th>{{'name' | i18n}}</th>
<th width="100" class="text-center">{{'hidePasswords' | i18n}}</th>
<th width="100" class="text-center">{{'readOnly' | i18n}}</th> <th width="100" class="text-center">{{'readOnly' | i18n}}</th>
</tr> </tr>
</thead> </thead>
@ -71,6 +72,10 @@
<td (click)="check(c)"> <td (click)="check(c)">
{{c.name}} {{c.name}}
</td> </td>
<td class="text-center">
<input type="checkbox" [(ngModel)]="c.hidePasswords"
name="Collection[{{i}}].HidePasswords" [disabled]="!c.checked">
</td>
<td class="text-center"> <td class="text-center">
<input type="checkbox" [(ngModel)]="c.readOnly" name="Collection[{{i}}].ReadOnly" <input type="checkbox" [(ngModel)]="c.readOnly" name="Collection[{{i}}].ReadOnly"
[disabled]="!c.checked"> [disabled]="!c.checked">

View File

@ -63,6 +63,7 @@ export class GroupAddEditComponent implements OnInit {
if (collection != null && collection.length > 0) { if (collection != null && collection.length > 0) {
(collection[0] as any).checked = true; (collection[0] as any).checked = true;
collection[0].readOnly = s.readOnly; collection[0].readOnly = s.readOnly;
collection[0].hidePasswords = s.hidePasswords;
} }
}); });
} }
@ -99,7 +100,7 @@ export class GroupAddEditComponent implements OnInit {
request.accessAll = this.access === 'all'; request.accessAll = this.access === 'all';
if (!request.accessAll) { if (!request.accessAll) {
request.collections = this.collections.filter((c) => (c as any).checked) request.collections = this.collections.filter((c) => (c as any).checked)
.map((c) => new SelectionReadOnlyRequest(c.id, !!c.readOnly)); .map((c) => new SelectionReadOnlyRequest(c.id, !!c.readOnly, !!c.hidePasswords));
} }
try { try {

View File

@ -94,6 +94,7 @@
<tr> <tr>
<th>&nbsp;</th> <th>&nbsp;</th>
<th>{{'name' | i18n}}</th> <th>{{'name' | i18n}}</th>
<th width="100" class="text-center">{{'hidePasswords' | i18n}}</th>
<th width="100" class="text-center">{{'readOnly' | i18n}}</th> <th width="100" class="text-center">{{'readOnly' | i18n}}</th>
</tr> </tr>
</thead> </thead>
@ -106,6 +107,10 @@
<td (click)="check(c)"> <td (click)="check(c)">
{{c.name}} {{c.name}}
</td> </td>
<td class="text-center">
<input type="checkbox" [(ngModel)]="c.hidePasswords"
name="Collection[{{i}}].HidePasswords" [disabled]="!c.checked">
</td>
<td class="text-center"> <td class="text-center">
<input type="checkbox" [(ngModel)]="c.readOnly" name="Collection[{{i}}].ReadOnly" <input type="checkbox" [(ngModel)]="c.readOnly" name="Collection[{{i}}].ReadOnly"
[disabled]="!c.checked"> [disabled]="!c.checked">

View File

@ -67,6 +67,7 @@ export class UserAddEditComponent implements OnInit {
if (collection != null && collection.length > 0) { if (collection != null && collection.length > 0) {
(collection[0] as any).checked = true; (collection[0] as any).checked = true;
collection[0].readOnly = s.readOnly; collection[0].readOnly = s.readOnly;
collection[0].hidePasswords = s.hidePasswords;
} }
}); });
} }
@ -100,7 +101,7 @@ export class UserAddEditComponent implements OnInit {
let collections: SelectionReadOnlyRequest[] = null; let collections: SelectionReadOnlyRequest[] = null;
if (this.access !== 'all') { if (this.access !== 'all') {
collections = this.collections.filter((c) => (c as any).checked) collections = this.collections.filter((c) => (c as any).checked)
.map((c) => new SelectionReadOnlyRequest(c.id, !!c.readOnly)); .map((c) => new SelectionReadOnlyRequest(c.id, !!c.readOnly, !!c.hidePasswords));
} }
try { try {

View File

@ -54,7 +54,8 @@
<label for="loginPassword">{{'password' | i18n}}</label> <label for="loginPassword">{{'password' | i18n}}</label>
<div class="ml-auto d-flex" *ngIf="!cipher.isDeleted"> <div class="ml-auto d-flex" *ngIf="!cipher.isDeleted">
<a href="#" class="d-block mr-2" appStopClick <a href="#" class="d-block mr-2" appStopClick
appA11yTitle="{{'generatePassword' | i18n}}" (click)="generatePassword()"> appA11yTitle="{{'generatePassword' | i18n}}" (click)="generatePassword()"
*ngIf="cipher.showPassword">
<i class="fa fa-lg fa-fw fa-refresh" aria-hidden="true"></i> <i class="fa fa-lg fa-fw fa-refresh" aria-hidden="true"></i>
</a> </a>
<a href="#" class="d-block" #checkPasswordBtn appStopClick <a href="#" class="d-block" #checkPasswordBtn appStopClick
@ -71,17 +72,18 @@
<input id="loginPassword" class="form-control text-monospace" <input id="loginPassword" class="form-control text-monospace"
type="{{showPassword ? 'text' : 'password'}}" name="Login.Password" type="{{showPassword ? 'text' : 'password'}}" name="Login.Password"
[(ngModel)]="cipher.login.password" appInputVerbatim autocomplete="new-password" [(ngModel)]="cipher.login.password" appInputVerbatim autocomplete="new-password"
[disabled]="cipher.isDeleted"> [disabled]="cipher.isDeleted || !cipher.showPassword">
<div class="input-group-append"> <div class="input-group-append">
<button type="button" class="btn btn-outline-secondary" <button type="button" class="btn btn-outline-secondary"
appA11yTitle="{{'toggleVisibility' | i18n}}" (click)="togglePassword()" appA11yTitle="{{'toggleVisibility' | i18n}}" (click)="togglePassword()"
tabindex="-1"> tabindex="-1" [disabled]="!cipher.showPassword">
<i class="fa fa-lg" aria-hidden="true" <i class="fa fa-lg" aria-hidden="true"
[ngClass]="{'fa-eye': !showPassword, 'fa-eye-slash': showPassword}"></i> [ngClass]="{'fa-eye': !showPassword, 'fa-eye-slash': showPassword}"></i>
</button> </button>
<button type="button" class="btn btn-outline-secondary" <button type="button" class="btn btn-outline-secondary"
appA11yTitle="{{'copyPassword' | i18n}}" appA11yTitle="{{'copyPassword' | i18n}}"
(click)="copy(cipher.login.password, 'password', 'Password')" tabindex="-1"> (click)="copy(cipher.login.password, 'password', 'Password')" tabindex="-1"
[disabled]="!cipher.showPassword">
<i class="fa fa-lg fa-clipboard" aria-hidden="true"></i> <i class="fa fa-lg fa-clipboard" aria-hidden="true"></i>
</button> </button>
</div> </div>

View File

@ -38,7 +38,7 @@
<div class="dropdown-menu dropdown-menu-right" aria-labelledby="dropdownMenuButton"> <div class="dropdown-menu dropdown-menu-right" aria-labelledby="dropdownMenuButton">
<ng-container *ngIf="c.type === cipherType.Login && !c.isDeleted"> <ng-container *ngIf="c.type === cipherType.Login && !c.isDeleted">
<a class="dropdown-item" href="#" appStopClick <a class="dropdown-item" href="#" appStopClick
(click)="copy(c, c.login.password, 'password', 'password')"> (click)="copy(c, c.login.password, 'password', 'password')" *ngIf="c.showPassword">
<i class="fa fa-fw fa-clipboard" aria-hidden="true"></i> <i class="fa fa-fw fa-clipboard" aria-hidden="true"></i>
{{'copyPassword' | i18n}} {{'copyPassword' | i18n}}
</a> </a>

View File

@ -3141,5 +3141,8 @@
}, },
"vaultTimeoutLogOutConfirmationTitle": { "vaultTimeoutLogOutConfirmationTitle": {
"message": "Timeout Action Confirmation" "message": "Timeout Action Confirmation"
},
"hidePasswords": {
"message": "Hide Passwords"
} }
} }