mirror of
https://github.com/bitwarden/browser
synced 2025-12-17 16:53:34 +00:00
Ps 976 moving of read only organization collection items to different folder not possible (#3474)
* PS-976 - when user has cipher readonly permissions, prevent user from editing cipher fields and make separate api call that only updates Favorite and Folder values * PS-976 - in the readonly edit cipher view, hide non-operable buttons and display select values as readonly input text * PS-976 - update failing test * PS-976 - split cipher saveWithServer call into Create and Update calls * PS-976 - replace property with function call to get the card expiration month for the readonly view * MM-976 - when user has readonly permissions hide "delete" button on View Item view, hide generate username/password buttons on Edit Item view * PS-976 - rename cipherPartialRequest file to align with new naming convention
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
appStopClick
|
||||
(click)="removeField(f)"
|
||||
appA11yTitle="{{ 'remove' | i18n }}"
|
||||
*ngIf="!(!cipher.edit && editMode)"
|
||||
>
|
||||
<i class="bwi bwi-minus-circle bwi-lg" aria-hidden="true"></i>
|
||||
</button>
|
||||
@@ -31,6 +32,7 @@
|
||||
class="row-label"
|
||||
placeholder="{{ 'name' | i18n }}"
|
||||
appInputVerbatim
|
||||
[readonly]="!cipher.edit && editMode"
|
||||
/>
|
||||
<!-- Text -->
|
||||
<input
|
||||
@@ -42,6 +44,7 @@
|
||||
placeholder="{{ 'value' | i18n }}"
|
||||
appInputVerbatim
|
||||
attr.aria-describedby="fieldName{{ i }}"
|
||||
[readonly]="!cipher.edit && editMode"
|
||||
/>
|
||||
<!-- Password -->
|
||||
<input
|
||||
@@ -55,6 +58,7 @@
|
||||
[disabled]="!cipher.viewPassword && !f.newField"
|
||||
appInputVerbatim
|
||||
attr.aria-describedby="fieldName{{ i }}"
|
||||
[readonly]="!cipher.edit && editMode"
|
||||
/>
|
||||
<!-- Linked -->
|
||||
<select
|
||||
@@ -78,6 +82,7 @@
|
||||
trueValue="true"
|
||||
falseValue="false"
|
||||
attr.aria-describedby="fieldName{{ i }}"
|
||||
[readonly]="!cipher.edit && editMode"
|
||||
/>
|
||||
<div
|
||||
class="action-buttons"
|
||||
@@ -99,13 +104,18 @@
|
||||
></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="drag-handle" appA11yTitle="{{ 'dragToSort' | i18n }}" cdkDragHandle>
|
||||
<div
|
||||
class="drag-handle"
|
||||
appA11yTitle="{{ 'dragToSort' | i18n }}"
|
||||
*ngIf="!(!cipher.edit && editMode)"
|
||||
cdkDragHandle
|
||||
>
|
||||
<i class="bwi bwi-hamburger" aria-hidden="true"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Add new custom field -->
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<div class="box-content-row" *ngIf="!(!cipher.edit && editMode)" appBoxRow>
|
||||
<button type="button" appStopClick (click)="addField()">
|
||||
<i class="bwi bwi-plus-circle bwi-fw bwi-lg" aria-hidden="true"></i>
|
||||
{{ "newCustomField" | i18n }}
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
name="Name"
|
||||
[(ngModel)]="cipher.name"
|
||||
[appAutofocus]="!editMode"
|
||||
[readonly]="!cipher.edit && editMode"
|
||||
/>
|
||||
</div>
|
||||
<!-- Login -->
|
||||
@@ -36,6 +37,7 @@
|
||||
name="Login.Username"
|
||||
[(ngModel)]="cipher.login.username"
|
||||
appInputVerbatim
|
||||
[readonly]="!cipher.edit && editMode"
|
||||
/>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
@@ -45,6 +47,7 @@
|
||||
appStopClick
|
||||
appA11yTitle="{{ 'generateUsername' | i18n }}"
|
||||
(click)="generateUsername()"
|
||||
*ngIf="!(!cipher.edit && editMode)"
|
||||
>
|
||||
<i class="bwi bwi-lg bwi-generate" aria-hidden="true"></i>
|
||||
</button>
|
||||
@@ -60,6 +63,7 @@
|
||||
name="Login.Password"
|
||||
[(ngModel)]="cipher.login.password"
|
||||
[disabled]="!cipher.viewPassword"
|
||||
[readonly]="!cipher.edit && editMode"
|
||||
appInputVerbatim
|
||||
/>
|
||||
</div>
|
||||
@@ -104,6 +108,7 @@
|
||||
appStopClick
|
||||
appA11yTitle="{{ 'generatePassword' | i18n }}"
|
||||
(click)="generatePassword()"
|
||||
*ngIf="!(!cipher.edit && editMode)"
|
||||
>
|
||||
<i class="bwi bwi-lg bwi-generate" aria-hidden="true"></i>
|
||||
</button>
|
||||
@@ -118,6 +123,7 @@
|
||||
class="monospaced"
|
||||
[(ngModel)]="cipher.login.totp"
|
||||
[disabled]="!cipher.viewPassword"
|
||||
[readonly]="!cipher.edit && editMode"
|
||||
appInputVerbatim
|
||||
/>
|
||||
</div>
|
||||
@@ -131,6 +137,7 @@
|
||||
type="text"
|
||||
name="Card.CardCardholderName"
|
||||
[(ngModel)]="cipher.card.cardholderName"
|
||||
[readonly]="!cipher.edit && editMode"
|
||||
/>
|
||||
</div>
|
||||
<div class="box-content-row box-content-row-flex" appBoxRow>
|
||||
@@ -143,6 +150,7 @@
|
||||
name="Card.Number"
|
||||
[(ngModel)]="cipher.card.number"
|
||||
appInputVerbatim
|
||||
[readonly]="!cipher.edit && editMode"
|
||||
/>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
@@ -164,17 +172,41 @@
|
||||
</div>
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="cardBrand">{{ "brand" | i18n }}</label>
|
||||
<select id="cardBrand" name="Card.Brand" [(ngModel)]="cipher.card.brand">
|
||||
<option *ngFor="let o of cardBrandOptions" [ngValue]="o.value">{{ o.name }}</option>
|
||||
</select>
|
||||
<span *ngIf="!(!cipher.edit && editMode); else readonlyCardBrand">
|
||||
<select id="cardBrand" name="Card.Brand" [(ngModel)]="cipher.card.brand">
|
||||
<option *ngFor="let o of cardBrandOptions" [ngValue]="o.value">
|
||||
{{ o.name }}
|
||||
</option>
|
||||
</select>
|
||||
</span>
|
||||
<ng-template #readonlyCardBrand>
|
||||
<input
|
||||
id="cardBrand"
|
||||
name="Card.Brand"
|
||||
type="text"
|
||||
[readonly]="true"
|
||||
[value]="cipher.card.brand"
|
||||
/>
|
||||
</ng-template>
|
||||
</div>
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="cardExpMonth">{{ "expirationMonth" | i18n }}</label>
|
||||
<select id="cardExpMonth" name="Card.ExpMonth" [(ngModel)]="cipher.card.expMonth">
|
||||
<option *ngFor="let o of cardExpMonthOptions" [ngValue]="o.value">
|
||||
{{ o.name }}
|
||||
</option>
|
||||
</select>
|
||||
<span *ngIf="!(!cipher.edit && editMode); else readonlyCardExpMonth">
|
||||
<select id="cardExpMonth" name="Card.ExpMonth" [(ngModel)]="cipher.card.expMonth">
|
||||
<option *ngFor="let o of cardExpMonthOptions" [ngValue]="o.value">
|
||||
{{ o.name }}
|
||||
</option>
|
||||
</select>
|
||||
</span>
|
||||
<ng-template #readonlyCardExpMonth>
|
||||
<input
|
||||
id="cardExpMonth"
|
||||
type="text"
|
||||
name="Card.ExpMonth"
|
||||
[readonly]="true"
|
||||
[value]="getCardExpMonthDisplay()"
|
||||
/>
|
||||
</ng-template>
|
||||
</div>
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="cardExpYear">{{ "expirationYear" | i18n }}</label>
|
||||
@@ -184,6 +216,7 @@
|
||||
name="Card.ExpYear"
|
||||
[(ngModel)]="cipher.card.expYear"
|
||||
placeholder="{{ 'ex' | i18n }} {{ currentDate | date: 'yyyy' }}"
|
||||
[readonly]="!cipher.edit && editMode"
|
||||
/>
|
||||
</div>
|
||||
<div class="box-content-row box-content-row-flex" appBoxRow>
|
||||
@@ -196,6 +229,7 @@
|
||||
name="Card.Code"
|
||||
[(ngModel)]="cipher.card.code"
|
||||
appInputVerbatim
|
||||
[readonly]="!cipher.edit && editMode"
|
||||
/>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
@@ -220,11 +254,22 @@
|
||||
<div *ngIf="cipher.type === cipherType.Identity">
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="idTitle">{{ "title" | i18n }}</label>
|
||||
<select id="idTitle" name="Identity.Title" [(ngModel)]="cipher.identity.title">
|
||||
<option *ngFor="let o of identityTitleOptions" [ngValue]="o.value">
|
||||
{{ o.name }}
|
||||
</option>
|
||||
</select>
|
||||
<span *ngIf="!(!cipher.edit && editMode); else readonlyIdTitle">
|
||||
<select id="idTitle" name="Identity.Title" [(ngModel)]="cipher.identity.title">
|
||||
<option *ngFor="let o of identityTitleOptions" [ngValue]="o.value">
|
||||
{{ o.name }}
|
||||
</option>
|
||||
</select>
|
||||
</span>
|
||||
<ng-template #readonlyIdTitle>
|
||||
<input
|
||||
id="idTitle"
|
||||
name="Identity.Title"
|
||||
type="text"
|
||||
[readonly]="true"
|
||||
[value]="cipher.identity.title"
|
||||
/>
|
||||
</ng-template>
|
||||
</div>
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="idFirstName">{{ "firstName" | i18n }}</label>
|
||||
@@ -233,6 +278,7 @@
|
||||
type="text"
|
||||
name="Identity.FirstName"
|
||||
[(ngModel)]="cipher.identity.firstName"
|
||||
[readonly]="!cipher.edit && editMode"
|
||||
/>
|
||||
</div>
|
||||
<div class="box-content-row" appBoxRow>
|
||||
@@ -242,6 +288,7 @@
|
||||
type="text"
|
||||
name="Identity.MiddleName"
|
||||
[(ngModel)]="cipher.identity.middleName"
|
||||
[readonly]="!cipher.edit && editMode"
|
||||
/>
|
||||
</div>
|
||||
<div class="box-content-row" appBoxRow>
|
||||
@@ -251,6 +298,7 @@
|
||||
type="text"
|
||||
name="Identity.LastName"
|
||||
[(ngModel)]="cipher.identity.lastName"
|
||||
[readonly]="!cipher.edit && editMode"
|
||||
/>
|
||||
</div>
|
||||
<div class="box-content-row" appBoxRow>
|
||||
@@ -261,6 +309,7 @@
|
||||
name="Identity.Username"
|
||||
[(ngModel)]="cipher.identity.username"
|
||||
appInputVerbatim
|
||||
[readonly]="!cipher.edit && editMode"
|
||||
/>
|
||||
</div>
|
||||
<div class="box-content-row" appBoxRow>
|
||||
@@ -270,6 +319,7 @@
|
||||
type="text"
|
||||
name="Identity.Company"
|
||||
[(ngModel)]="cipher.identity.company"
|
||||
[readonly]="!cipher.edit && editMode"
|
||||
/>
|
||||
</div>
|
||||
<div class="box-content-row" appBoxRow>
|
||||
@@ -280,6 +330,7 @@
|
||||
name="Identity.SSN"
|
||||
[(ngModel)]="cipher.identity.ssn"
|
||||
appInputVerbatim
|
||||
[readonly]="!cipher.edit && editMode"
|
||||
/>
|
||||
</div>
|
||||
<div class="box-content-row" appBoxRow>
|
||||
@@ -290,6 +341,7 @@
|
||||
name="Identity.PassportNumber"
|
||||
[(ngModel)]="cipher.identity.passportNumber"
|
||||
appInputVerbatim
|
||||
[readonly]="!cipher.edit && editMode"
|
||||
/>
|
||||
</div>
|
||||
<div class="box-content-row" appBoxRow>
|
||||
@@ -300,6 +352,7 @@
|
||||
name="Identity.LicenseNumber"
|
||||
[(ngModel)]="cipher.identity.licenseNumber"
|
||||
appInputVerbatim
|
||||
[readonly]="!cipher.edit && editMode"
|
||||
/>
|
||||
</div>
|
||||
<div class="box-content-row" appBoxRow>
|
||||
@@ -310,6 +363,7 @@
|
||||
name="Identity.Email"
|
||||
[(ngModel)]="cipher.identity.email"
|
||||
appInputVerbatim
|
||||
[readonly]="!cipher.edit && editMode"
|
||||
/>
|
||||
</div>
|
||||
<div class="box-content-row" appBoxRow>
|
||||
@@ -319,6 +373,7 @@
|
||||
type="text"
|
||||
name="Identity.Phone"
|
||||
[(ngModel)]="cipher.identity.phone"
|
||||
[readonly]="!cipher.edit && editMode"
|
||||
/>
|
||||
</div>
|
||||
<div class="box-content-row" appBoxRow>
|
||||
@@ -328,6 +383,7 @@
|
||||
type="text"
|
||||
name="Identity.Address1"
|
||||
[(ngModel)]="cipher.identity.address1"
|
||||
[readonly]="!cipher.edit && editMode"
|
||||
/>
|
||||
</div>
|
||||
<div class="box-content-row" appBoxRow>
|
||||
@@ -337,6 +393,7 @@
|
||||
type="text"
|
||||
name="Identity.Address2"
|
||||
[(ngModel)]="cipher.identity.address2"
|
||||
[readonly]="!cipher.edit && editMode"
|
||||
/>
|
||||
</div>
|
||||
<div class="box-content-row" appBoxRow>
|
||||
@@ -346,6 +403,7 @@
|
||||
type="text"
|
||||
name="Identity.Address3"
|
||||
[(ngModel)]="cipher.identity.address3"
|
||||
[readonly]="!cipher.edit && editMode"
|
||||
/>
|
||||
</div>
|
||||
<div class="box-content-row" appBoxRow>
|
||||
@@ -355,6 +413,7 @@
|
||||
type="text"
|
||||
name="Identity.City"
|
||||
[(ngModel)]="cipher.identity.city"
|
||||
[readonly]="!cipher.edit && editMode"
|
||||
/>
|
||||
</div>
|
||||
<div class="box-content-row" appBoxRow>
|
||||
@@ -364,6 +423,7 @@
|
||||
type="text"
|
||||
name="Identity.State"
|
||||
[(ngModel)]="cipher.identity.state"
|
||||
[readonly]="!cipher.edit && editMode"
|
||||
/>
|
||||
</div>
|
||||
<div class="box-content-row" appBoxRow>
|
||||
@@ -373,6 +433,7 @@
|
||||
type="text"
|
||||
name="Identity.PostalCode"
|
||||
[(ngModel)]="cipher.identity.postalCode"
|
||||
[readonly]="!cipher.edit && editMode"
|
||||
/>
|
||||
</div>
|
||||
<div class="box-content-row" appBoxRow>
|
||||
@@ -382,6 +443,7 @@
|
||||
type="text"
|
||||
name="Identity.Country"
|
||||
[(ngModel)]="cipher.identity.country"
|
||||
[readonly]="!cipher.edit && editMode"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -402,6 +464,7 @@
|
||||
appStopClick
|
||||
(click)="removeUri(u)"
|
||||
appA11yTitle="{{ 'remove' | i18n }}"
|
||||
[disabled]="!cipher.edit && editMode"
|
||||
>
|
||||
<i class="bwi bwi-minus-circle bwi-lg" aria-hidden="true"></i>
|
||||
</button>
|
||||
@@ -446,7 +509,13 @@
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
<button type="button" appStopClick (click)="addUri()" class="box-content-row">
|
||||
<button
|
||||
type="button"
|
||||
appStopClick
|
||||
(click)="addUri()"
|
||||
class="box-content-row"
|
||||
*ngIf="!(!cipher.edit && editMode)"
|
||||
>
|
||||
<i class="bwi bwi-plus-circle bwi-fw bwi-lg" aria-hidden="true"></i>
|
||||
{{ "newUri" | i18n }}
|
||||
</button>
|
||||
@@ -481,6 +550,7 @@
|
||||
name="PasswordPrompt"
|
||||
[ngModel]="reprompt"
|
||||
(change)="repromptChanged()"
|
||||
[disabled]="!cipher.edit && editMode"
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
@@ -511,11 +581,18 @@
|
||||
</h2>
|
||||
<div class="box-content">
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<textarea id="notes" name="Notes" rows="6" [(ngModel)]="cipher.notes"></textarea>
|
||||
<textarea
|
||||
id="notes"
|
||||
name="Notes"
|
||||
rows="6"
|
||||
[(ngModel)]="cipher.notes"
|
||||
[readonly]="!cipher.edit && editMode"
|
||||
></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<app-vault-add-edit-custom-fields
|
||||
*ngIf="!(!cipher.hasFields && !cipher.edit && editMode)"
|
||||
[cipher]="cipher"
|
||||
[thisCipherType]="cipher.type"
|
||||
[editMode]="editMode"
|
||||
|
||||
@@ -537,7 +537,7 @@
|
||||
>
|
||||
<i class="bwi bwi-files bwi-fw bwi-lg" aria-hidden="true"></i>
|
||||
</button>
|
||||
<div class="right">
|
||||
<div class="right" *ngIf="cipher.edit">
|
||||
<button
|
||||
type="button"
|
||||
(click)="delete()"
|
||||
|
||||
@@ -159,7 +159,7 @@ export class EncryptedMessageHandlerService {
|
||||
|
||||
try {
|
||||
const encrypted = await this.cipherService.encrypt(cipherView);
|
||||
await this.cipherService.saveWithServer(encrypted);
|
||||
await this.cipherService.createWithServer(encrypted);
|
||||
|
||||
// Notify other clients of new login
|
||||
await this.messagingService.send("addedCipher");
|
||||
@@ -198,7 +198,7 @@ export class EncryptedMessageHandlerService {
|
||||
cipherView.login.uris[0].uri = credentialUpdatePayload.uri;
|
||||
const encrypted = await this.cipherService.encrypt(cipherView);
|
||||
|
||||
await this.cipherService.saveWithServer(encrypted);
|
||||
await this.cipherService.updateWithServer(encrypted);
|
||||
|
||||
// Notify other clients of update
|
||||
await this.messagingService.send("editedCipher");
|
||||
|
||||
Reference in New Issue
Block a user