-
Notifications
You must be signed in to change notification settings - Fork 18
[PM-25818] Migrate Basic Cipher Create, Edit, and Get Operations to SDK #455
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
base: main
Are you sure you want to change the base?
Conversation
Great job! No new security vulnerabilities introduced in this pull request |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a handful of questions from me. I'm following this and the implementation but I would say that my rust experience is a little lack luster on if there are improvements to be made on that thread. I will hold off on approving to hopefully solicit some more impactful feedback, but I can if I'm the gateway between moving this forward.
organization_use_totp: cipher.organization_use_totp.unwrap_or(true), | ||
edit: cipher.edit.unwrap_or(true), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
❓ Probably an edge case, the current CipherView defaults these values to false
rather than true
. Should this logic follow suit or is the deviation intentional?
list_ciphers(key_store, repository.as_ref()).await | ||
} | ||
|
||
/// Get [Cipher] by ID from state and decrypt it to a [CipherView]. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did not know you could link to other entities in a comment with [...]
, TIL!
## 🎟️ Tracking <!-- Paste the link to the Jira or GitHub issue or otherwise describe / point to where this change is coming from. --> ## 📔 Objective These crates had some missing features, which caused compilation errors when trying to run the tests from VSCode. The reason that CI kept building was that rust unifies all the workspace features, so as long as one crate has them enabled it's fine. On the other hand, when running a test from VSCode, it will only have that crates features in mind. Note that the uniffi feature of core requires internal because of these two types: https://github.com/bitwarden/sdk-internal/blob/main/crates/bitwarden-core/src/uniffi_support.rs#L30-L42 ## ⏰ Reminders before review - Contributor guidelines followed - All formatters and local linters executed and passed - Written new unit and / or integration tests where applicable - Protected functional changes with optionality (feature flags) - Used internationalization (i18n) for all UI strings - CI builds passed - Communicated to DevOps any deployment requirements - Updated any necessary documentation (Confluence, contributing docs) or informed the documentation team ## 🦮 Reviewer guidelines <!-- Suggested interactions but feel free to use (or not) as you desire! --> - 👍 (`:+1:`) or similar for great changes - 📝 (`:memo:`) or ℹ️ (`:information_source:`) for notes or general info - ❓ (`:question:`) for questions - 🤔 (`:thinking:`) or 💭 (`:thought_balloon:`) for more open inquiry that's not quite a confirmed issue and could potentially benefit from discussion - 🎨 (`:art:`) for suggestions / improvements - ❌ (`:x:`) or⚠️ (`:warning:`) for more significant problems or concerns needing attention - 🌱 (`:seedling:`) or ♻️ (`:recycle:`) for future improvements or indications of technical debt - ⛏ (`:pick:`) for minor or nitpick changes
Scaffolds a new workflow for updating API bindings.
Updated SDK to use an `archivedDate` in the ciphers.
This PR contains the following updates: | Package | Change | Age | Confidence | |---|---|---|---| | [@openapitools/openapi-generator-cli](https://redirect.github.com/OpenAPITools/openapi-generator-cli) | [`2.20.2` -> `2.23.1`](https://renovatebot.com/diffs/npm/@openapitools%2fopenapi-generator-cli/2.20.2/2.23.1) | [](https://docs.renovatebot.com/merge-confidence/) | [](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes <details> <summary>OpenAPITools/openapi-generator-cli (@​openapitools/openapi-generator-cli)</summary> ### [`v2.23.1`](https://redirect.github.com/OpenAPITools/openapi-generator-cli/releases/tag/v2.23.1) [Compare Source](https://redirect.github.com/OpenAPITools/openapi-generator-cli/compare/v2.23.0...v2.23.1) ##### Bug Fixes - **deps:** update dependency concurrently to v9.2.1 ([#​978](https://redirect.github.com/OpenAPITools/openapi-generator-cli/issues/978)) ([4847fe0](https://redirect.github.com/OpenAPITools/openapi-generator-cli/commit/4847fe0117995db49017c5943e18a6771a88929a)) ### [`v2.23.0`](https://redirect.github.com/OpenAPITools/openapi-generator-cli/releases/tag/v2.23.0) [Compare Source](https://redirect.github.com/OpenAPITools/openapi-generator-cli/compare/v2.22.0...v2.23.0) ##### Features - **release:** v7.15.0 release ([#​973](https://redirect.github.com/OpenAPITools/openapi-generator-cli/issues/973)) ([24443a5](https://redirect.github.com/OpenAPITools/openapi-generator-cli/commit/24443a5ff0b1d201b1ecef2299d82b96ffefd10c)) ### [`v2.22.0`](https://redirect.github.com/OpenAPITools/openapi-generator-cli/releases/tag/v2.22.0) [Compare Source](https://redirect.github.com/OpenAPITools/openapi-generator-cli/compare/v2.21.5...v2.22.0) ##### Features - **release:** trigger a release ([#​963](https://redirect.github.com/OpenAPITools/openapi-generator-cli/issues/963)) ([7ce2ed9](https://redirect.github.com/OpenAPITools/openapi-generator-cli/commit/7ce2ed95eb0bc3fb03bbe7c6f7bdcecd0091794b)) ### [`v2.21.5`](https://redirect.github.com/OpenAPITools/openapi-generator-cli/releases/tag/v2.21.5) [Compare Source](https://redirect.github.com/OpenAPITools/openapi-generator-cli/compare/v2.21.4...v2.21.5) ##### Bug Fixes - **deps:** update dependency fs-extra to v11.3.1 ([#​962](https://redirect.github.com/OpenAPITools/openapi-generator-cli/issues/962)) ([e0ce66f](https://redirect.github.com/OpenAPITools/openapi-generator-cli/commit/e0ce66f36f3dc54539425ff58ddb0d8fd730dc98)) ### [`v2.21.4`](https://redirect.github.com/OpenAPITools/openapi-generator-cli/releases/tag/v2.21.4) [Compare Source](https://redirect.github.com/OpenAPITools/openapi-generator-cli/compare/v2.21.3...v2.21.4) ##### Bug Fixes - **deps:** update dependency axios to v1.11.0 \[security] ([#​956](https://redirect.github.com/OpenAPITools/openapi-generator-cli/issues/956)) ([e517c31](https://redirect.github.com/OpenAPITools/openapi-generator-cli/commit/e517c31ce8697225329e630c03697c147952b660)) ### [`v2.21.3`](https://redirect.github.com/OpenAPITools/openapi-generator-cli/releases/tag/v2.21.3) [Compare Source](https://redirect.github.com/OpenAPITools/openapi-generator-cli/compare/v2.21.2...v2.21.3) ##### Bug Fixes - **deps:** update nest monorepo to v11.1.5 ([#​950](https://redirect.github.com/OpenAPITools/openapi-generator-cli/issues/950)) ([28c5f0d](https://redirect.github.com/OpenAPITools/openapi-generator-cli/commit/28c5f0d8b937bee531a16efb4d6c51017d0ac16c)) ### [`v2.21.2`](https://redirect.github.com/OpenAPITools/openapi-generator-cli/releases/tag/v2.21.2) [Compare Source](https://redirect.github.com/OpenAPITools/openapi-generator-cli/compare/v2.21.1...v2.21.2) ##### Bug Fixes - **deps:** update dependency [@​nestjs/axios](https://redirect.github.com/nestjs/axios) to v4.0.1 ([#​947](https://redirect.github.com/OpenAPITools/openapi-generator-cli/issues/947)) ([9f16faf](https://redirect.github.com/OpenAPITools/openapi-generator-cli/commit/9f16fafa0f757650c423567b2057683b284a88ec)) ### [`v2.21.1`](https://redirect.github.com/OpenAPITools/openapi-generator-cli/releases/tag/v2.21.1) [Compare Source](https://redirect.github.com/OpenAPITools/openapi-generator-cli/compare/v2.21.0...v2.21.1) ##### Bug Fixes - **deps:** update dependency concurrently to v9 ([#​848](https://redirect.github.com/OpenAPITools/openapi-generator-cli/issues/848)) ([5a52eaf](https://redirect.github.com/OpenAPITools/openapi-generator-cli/commit/5a52eaf77db3403b249a1cf30c0eb1bbc1f10671)) ### [`v2.21.0`](https://redirect.github.com/OpenAPITools/openapi-generator-cli/releases/tag/v2.21.0) [Compare Source](https://redirect.github.com/OpenAPITools/openapi-generator-cli/compare/v2.20.6...v2.21.0) ##### Features - **release:** v7.14.0 release ([#​942](https://redirect.github.com/OpenAPITools/openapi-generator-cli/issues/942)) ([cd3c9a4](https://redirect.github.com/OpenAPITools/openapi-generator-cli/commit/cd3c9a4b86de43000ff0f915eb5abb8fc5e86915)) ### [`v2.20.6`](https://redirect.github.com/OpenAPITools/openapi-generator-cli/releases/tag/v2.20.6) [Compare Source](https://redirect.github.com/OpenAPITools/openapi-generator-cli/compare/v2.20.5...v2.20.6) ##### Bug Fixes - **deps:** update dependency axios to v1.10.0 ([#​939](https://redirect.github.com/OpenAPITools/openapi-generator-cli/issues/939)) ([0f623cc](https://redirect.github.com/OpenAPITools/openapi-generator-cli/commit/0f623ccd9de6751b9ae8a7fcdd0bd491807baeac)) ### [`v2.20.5`](https://redirect.github.com/OpenAPITools/openapi-generator-cli/releases/tag/v2.20.5) [Compare Source](https://redirect.github.com/OpenAPITools/openapi-generator-cli/compare/v2.20.4...v2.20.5) ##### Bug Fixes - **deps:** update nest monorepo to v11.1.3 ([#​935](https://redirect.github.com/OpenAPITools/openapi-generator-cli/issues/935)) ([2575f55](https://redirect.github.com/OpenAPITools/openapi-generator-cli/commit/2575f55752012d8442095e76fbea0cfe35a258e8)) ### [`v2.20.4`](https://redirect.github.com/OpenAPITools/openapi-generator-cli/releases/tag/v2.20.4) [Compare Source](https://redirect.github.com/OpenAPITools/openapi-generator-cli/compare/v2.20.3...v2.20.4) ##### Bug Fixes - **deps:** update dependency glob to v11 ([#​904](https://redirect.github.com/OpenAPITools/openapi-generator-cli/issues/904)) ([7b8ac55](https://redirect.github.com/OpenAPITools/openapi-generator-cli/commit/7b8ac55ace0f2d803f80ee125ff301735a0dcb7f)) ### [`v2.20.3`](https://redirect.github.com/OpenAPITools/openapi-generator-cli/releases/tag/v2.20.3) [Compare Source](https://redirect.github.com/OpenAPITools/openapi-generator-cli/compare/v2.20.2...v2.20.3) ##### Bug Fixes - **deps:** update dependency glob to v10 ([#​933](https://redirect.github.com/OpenAPITools/openapi-generator-cli/issues/933)) ([a6b3d6c](https://redirect.github.com/OpenAPITools/openapi-generator-cli/commit/a6b3d6c93be95eb3fedfaa5789b5556a64fb2c5a)) </details> --- ### Configuration 📅 **Schedule**: Branch creation - "every 2nd week starting on the 2 week of the year before 4am on Monday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/bitwarden/sdk-internal). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MS43MS4xIiwidXBkYXRlZEluVmVyIjoiNDEuOTcuMTAiLCJ0YXJnZXRCcmFuY2giOiJtYWluIiwibGFiZWxzIjpbXX0=--> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Daniel García <dani-garcia@users.noreply.github.com>
This adds two custom dylint lint. - `error_suffix`: Requires all types that implements `Error` ends with an `Error` suffix. - `error_enum`: Forbids ending enum error variants with `Error`.
Wraps up the b64 migration.
We removed the ability to throw `VaultLocked` a while back. This removes the actual error struct and any place it's used in.
repository: &dyn Repository<Cipher>, | ||
) -> Result<Vec<CipherView>, GetCipherError> { | ||
let ciphers = repository.list().await?; | ||
let views = store.decrypt_list(&ciphers)?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be better to use decrypt_list_failures
here to avoid blocking when only some of them fail to decrypt?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for adding list_ciphers_with_failures
! Do you think we still need the list_ciphers
for any use cases, or could we remove it altogether?
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #455 +/- ##
=========================================
Coverage 78.48% 78.48%
=========================================
Files 276 280 +4
Lines 27435 28631 +1196
=========================================
+ Hits 21531 22472 +941
- Misses 5904 6159 +255 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
… vault/migrate-ciphers
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall good, there are a couple of things we should consider.
ctx: &mut KeyStoreContext<KeyIds>, | ||
key: SymmetricKeyId, | ||
) -> Result<(), CryptoError> { | ||
let old_key = Cipher::decrypt_cipher_key(ctx, key, &self.key)?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
question: Since we're creating a cipher key will never exist right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It shouldn't, in which case decrypt_cipher_key
will return the existing key. I included this just in case we do get a CipherCreateRequest
that already has a key, which would imply the Fido2 credentials were already encrypted with that key. Happy to remove if we're making the assumption that won't happen.
self.type_data | ||
.as_login_view_mut() | ||
.map(|l| l.reencrypt_fido2_credentials(ctx, old_key, new_key)) | ||
.transpose()?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thought: This raises a good question, how would we create a new cipher with a passkey? They are intentionally encrypted but would that even be viable generally?
I think temporarily we can pass in already encrypted data in the web clients, but this might not work on mobile. Long term having a different flow for creating items with passkeys might be required? CC @coroiu since you have more insight into our sdk passkey flows.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On clients
we don't create ciphers with passkeys. The cipher is created first by the popout, which returns the new cipherId
to background
which then reads out the cipher and attaches a new passkey to it. It's a bad way of doing it but I think it saves us from having to worry about creation with passkeys in this PR.
mobile
on the other hand does create ciphers with passkeys but creation and encryption is encapsulated in the SDK and could use the Repository<Cipher>
instead of going through the CipherClient
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think with the new APIs you would need to create the cipher first before adding passkeys. We'll see what troubles appears when we start migrating mobile to use it.
impl TryFrom<CipherView> for CipherEditRequest { | ||
type Error = MissingFieldError; | ||
|
||
fn try_from(value: CipherView) -> Result<Self, Self::Error> { | ||
let type_data = match value.r#type { | ||
CipherType::Login => value.login.map(CipherViewType::Login), | ||
CipherType::SecureNote => value.secure_note.map(CipherViewType::SecureNote), | ||
CipherType::Card => value.card.map(CipherViewType::Card), | ||
CipherType::Identity => value.identity.map(CipherViewType::Identity), | ||
CipherType::SshKey => value.ssh_key.map(CipherViewType::SshKey), | ||
}; | ||
Ok(Self { | ||
id: value.id.ok_or(MissingFieldError("id"))?, | ||
r#type: value.r#type, | ||
organization_id: value.organization_id, | ||
folder_id: value.folder_id, | ||
favorite: value.favorite, | ||
reprompt: value.reprompt, | ||
key: value.key, | ||
name: value.name, | ||
notes: value.notes, | ||
fields: value.fields.unwrap_or_default(), | ||
password_history: value.password_history, | ||
attachments: value.attachments, | ||
type_data, | ||
revision_date: value.revision_date, | ||
archived_date: value.archived_date, | ||
}) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
question: It seems a bit weird going from CipherView
to CipherEditRequest
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The intent here was that a client will have a CipherView locally, make changes to it, and then go to save those changes by converting it into an Edit request.
Something along the lines of:
// Start with a decrypted cipher
let cipher_view: CipherView = ciphers_client.decrypt(cipher)?;
// Make some local changes to the CipherView
cipher_view.name = "New Cipher Name";
cipher_view.login = Some(LoginView {
username: Some("new_login".to_string()),
password: Some("password".to_string()),
..Default::default(),
});
// Send the changes upstream
ciphers_client.edit(cipher_view.into());
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, that does seem like a nicer rust interface although I'd caution against modifying a CipherView
ever, and you should probably convert to a CipherEditRequest
before modifying it. The conversion to CipherEditRequest
is lossly and might not save passkeys for example.
… vault/migrate-ciphers
Co-authored-by: Oscar Hinton <Hinton@users.noreply.github.com>
Co-authored-by: Oscar Hinton <Hinton@users.noreply.github.com>
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is mostly looking great. There are some last comments, and some previous comments that were missed.
/// Get all ciphers from state and decrypt them, returning both successes and failures. | ||
/// This method will not fail when some ciphers fail to decrypt, allowing for graceful | ||
/// handling of corrupted or problematic cipher data. | ||
pub async fn list_with_failures(&self) -> Result<DecryptCipherListResult, GetCipherError> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion (non blocking): I think we can just call this list
?
impl TryFrom<CipherView> for CipherEditRequest { | ||
type Error = MissingFieldError; | ||
|
||
fn try_from(value: CipherView) -> Result<Self, Self::Error> { | ||
let type_data = match value.r#type { | ||
CipherType::Login => value.login.map(CipherViewType::Login), | ||
CipherType::SecureNote => value.secure_note.map(CipherViewType::SecureNote), | ||
CipherType::Card => value.card.map(CipherViewType::Card), | ||
CipherType::Identity => value.identity.map(CipherViewType::Identity), | ||
CipherType::SshKey => value.ssh_key.map(CipherViewType::SshKey), | ||
}; | ||
Ok(Self { | ||
id: value.id.ok_or(MissingFieldError("id"))?, | ||
r#type: value.r#type, | ||
organization_id: value.organization_id, | ||
folder_id: value.folder_id, | ||
favorite: value.favorite, | ||
reprompt: value.reprompt, | ||
key: value.key, | ||
name: value.name, | ||
notes: value.notes, | ||
fields: value.fields.unwrap_or_default(), | ||
password_history: value.password_history, | ||
attachments: value.attachments, | ||
type_data, | ||
revision_date: value.revision_date, | ||
archived_date: value.archived_date, | ||
}) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, that does seem like a nicer rust interface although I'd caution against modifying a CipherView
ever, and you should probably convert to a CipherEditRequest
before modifying it. The conversion to CipherEditRequest
is lossly and might not save passkeys for example.
self.type_data | ||
.as_login_view_mut() | ||
.map(|l| l.reencrypt_fido2_credentials(ctx, old_key, new_key)) | ||
.transpose()?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think with the new APIs you would need to create the cipher first before adding passkeys. We'll see what troubles appears when we start migrating mobile to use it.
pub notes: Option<String>, | ||
pub favorite: bool, | ||
pub reprompt: CipherRepromptType, | ||
pub type_data: Option<CipherViewType>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
question: Is this actually optional? I don't think you can create ciphers without a type.
pub type_data: Option<CipherViewType>, | |
pub type_data: CipherViewType, |
pub notes: Option<String>, | ||
pub favorite: bool, | ||
pub reprompt: CipherRepromptType, | ||
pub type_data: Option<CipherViewType>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
question (non blocking): Should we rename this to type
?
pub name: String, | ||
pub notes: Option<String>, | ||
pub fields: Vec<FieldView>, | ||
pub password_history: Option<Vec<PasswordHistoryView>>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
question: I think we can drop this field? It should be calculated by the SDK.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed! We should be able to remove it at let it be calculated internally.
pub notes: Option<String>, | ||
pub fields: Vec<FieldView>, | ||
pub password_history: Option<Vec<PasswordHistoryView>>, | ||
pub attachments: Option<Vec<AttachmentView>>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I want to say we should drop this as well and refer people to dedicated functions but maybe we want to keep it around for now until we have those APIs?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should be able to remove it now and avoid the possibility of mistakenly trying to update attachments directly. At least for the TS clients, attachment creation/management is through its own methods that can be migrated to the SDK at a later time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changes really good from my perspective, nice work on this! I wanted to echo/agree with a few of Oscar's comments that I think we should address before merge.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 Thanks for moving the uri checksum generation and fido2 re-encryption logic to Login
!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 Very nice!
pub name: String, | ||
pub notes: Option<String>, | ||
pub fields: Vec<FieldView>, | ||
pub password_history: Option<Vec<PasswordHistoryView>>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed! We should be able to remove it at let it be calculated internally.
pub notes: Option<String>, | ||
pub fields: Vec<FieldView>, | ||
pub password_history: Option<Vec<PasswordHistoryView>>, | ||
pub attachments: Option<Vec<AttachmentView>>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should be able to remove it now and avoid the possibility of mistakenly trying to update attachments directly. At least for the TS clients, attachment creation/management is through its own methods that can be migrated to the SDK at a later time.
🎟️ Tracking
https://bitwarden.atlassian.net/browse/PM-25818
📔 Objective
⏰ Reminders before review
team
🦮 Reviewer guidelines
:+1:
) or similar for great changes:memo:
) or ℹ️ (:information_source:
) for notes or general info:question:
) for questions:thinking:
) or 💭 (:thought_balloon:
) for more open inquiry that's not quite a confirmedissue and could potentially benefit from discussion
:art:
) for suggestions / improvements:x:
) or:warning:
) for more significant problems or concerns needing attention:seedling:
) or ♻️ (:recycle:
) for future improvements or indications of technical debt:pick:
) for minor or nitpick changes