//! Modifying the state of Foo objects on the server is done via the //! "Foo/set" method. This encompasses creating, updating, and //! destroying Foo records. This allows the server to sort out ordering //! and dependencies that may exist if doing multiple operations at once //! (for example, to ensure there is always a minimum number of a certain //! record type). use std::{borrow::Cow, collections::HashMap}; use serde::{Deserialize, Serialize}; use serde_json::Value; use serde_with::{serde_as, BorrowCow}; use crate::{common::Id, endpoints::object::ObjectState}; #[serde_as] #[derive(Serialize, Deserialize, Debug, Clone)] #[serde(rename_all = "camelCase")] pub struct SetParams<'a, T> { /// The id of the account to use. account_id: Id<'a>, /// This is a state string as returned by the "Foo/get" method /// (representing the state of all objects of this type in the /// account). If supplied, the string must match the current state; /// otherwise, the method will be aborted and a "stateMismatch" error /// returned. If null, any changes will be applied to the current /// state. #[serde(borrow)] if_in_state: Option>, /// A map of a *creation id* (a temporary id set by the client) to Foo /// objects, or null if no objects are to be created. /// /// The Foo object type definition may define default values for /// properties. Any such property may be omitted by the client. /// /// The client MUST omit any properties that may only be set by the /// server (for example, the "id" property on most object types). #[serde(default)] create: HashMap, T>, /// A map of an id to a Patch object to apply to the current Foo /// object with that id, or null if no objects are to be updated. #[serde(default)] update: HashMap, PatchObject<'a>>, /// A list of ids for Foo objects to permanently delete, or null if no /// objects are to be destroyed. #[serde(default)] destroy: Vec>, } /// A *PatchObject* is of type "String[*]" and represents an unordered /// set of patches. The keys are a path in JSON Pointer format /// [RFC6901], with an implicit leading "/" (i.e., prefix each key /// with "/" before applying the JSON Pointer evaluation algorithm). #[serde_as] #[derive(Serialize, Deserialize, Debug, Clone)] #[serde(rename_all = "camelCase")] pub struct PatchObject<'a>(#[serde_as(as = "HashMap")] HashMap, Value>); #[derive(Serialize, Deserialize, Debug, Clone)] #[serde(rename_all = "camelCase")] pub struct SetResult<'a, T> { /// The id of the account used for the call. #[serde(borrow)] account_id: Id<'a>, /// The state string that would have been returned by "Foo/get" before /// making the requested changes, or null if the server doesn't know /// what the previous state string was. #[serde(borrow)] old_state: Option>, /// The state string that will now be returned by "Foo/get". #[serde(borrow)] new_state: ObjectState<'a>, /// A map of the creation id to an object containing any properties of /// the created Foo object that were not sent by the client. This /// includes all server-set properties (such as the "id" in most /// object types) and any properties that were omitted by the client /// and thus set to a default by the server. /// /// This argument is null if no Foo objects were successfully created. #[serde(default, borrow)] created: HashMap, T>, /// The keys in this map are the ids of all Foos that were /// successfully updated. /// /// The value for each id is a Foo object containing any property that /// changed in a way *not* explicitly requested by the PatchObject /// sent to the server, or null if none. This lets the client know of /// any changes to server-set or computed properties. /// /// This argument is null if no Foo objects were successfully updated. #[serde(default, borrow)] updated: HashMap, Option>, /// A list of Foo ids for records that were successfully destroyed, or /// null if none. #[serde(default, borrow)] destroyed: Vec>, /// A map of the creation id to a SetError object for each record that /// failed to be created, or null if all successful. #[serde(default, borrow)] not_created: HashMap, SetError<'a>>, /// A map of the Foo id to a SetError object for each record that /// failed to be updated, or null if all successful. #[serde(default, borrow)] not_updated: HashMap, SetError<'a>>, /// A map of the Foo id to a SetError object for each record that /// failed to be destroyed, or null if all successful. #[serde(default, borrow)] not_destroyed: HashMap, SetError<'a>>, } #[derive(Serialize, Deserialize, Debug, Clone)] #[serde(rename_all = "camelCase")] pub struct SetError<'a> { /// The type of error. #[serde(rename = "type")] type_: SetErrorKind, /// A description of the error to help with debugging that includes an /// explanation of what the problem was. This is a non-localised /// string and is not intended to be shown directly to end users. #[serde(borrow)] description: Option>, /// The SetError object SHOULD also have a property called "properties" of /// type "String[]" that lists *all* the properties that were invalid. For /// type of `invalidProperties`. #[serde(borrow)] properties: Vec>, } #[derive(Serialize, Deserialize, Debug, Clone)] #[serde(rename_all = "camelCase")] pub enum SetErrorKind { /// (create; update; destroy). The create/update/destroy would violate /// an ACL or other permissions policy. Forbidden, /// (create; update). The create would exceed a server-defined limit /// on the number or total size of objects of this type. OverQuota, /// (create; update). The create/update would result in an object that /// exceeds a server-defined limit for the maximum size of a single object /// of this type. TooLarge, /// (create). Too many objects of this type have been created recently, /// and a server-defined rate limit has been reached. It may work if tried /// again later. RateLimit, /// (update; destroy). The id given to update/destroy cannot be found. NotFound, /// (update). The PatchObject given to update the record was not a valid /// patch (see the patch description). InvalidPatch, /// (update). The client requested that an object be both updated and /// destroyed in the same /set request, and the server has decided to /// therefore ignore the update. WillDestroy, /// (create; update). The record given is invalid in some way. For /// example: /// /// - It contains properties that are invalid according to the type specification of this /// record type. /// - It contains a property that may only be set by the server (e.g., "id") and is different /// to the current value. Note, to allow clients to pass whole objects back, it is not an /// error to include a server-set property in an update as long as the value is identical to /// the current value on the server. /// - There is a reference to another record (foreign key), and the given id does not /// correspond to a valid record. InvalidProperties, /// (create; destroy). This is a singleton type, so you cannot create /// another one or destroy the existing one. Singleton, }