1use parse_rust_core::{new_object_id, ErrorCode, ParseDate, ParseError, ParseMap, ParseValue};
14use parse_rust_schema::{apply, default_schema, validate_write};
15use parse_rust_storage::{ClassSchema, Constraint, QueryOptions, StorageAdapter};
16
17use crate::acl::{lower_acl, raise_acl, AclScope};
18
19#[derive(Debug, Clone)]
21pub struct CreateResponse {
22 pub object_id: String,
23 pub created_at: ParseDate,
24}
25
26#[derive(Debug, Clone)]
28pub struct UpdateResponse {
29 pub updated_at: ParseDate,
30}
31
32async fn load_schema<S: StorageAdapter>(
34 storage: &S,
35 class_name: &str,
36) -> Result<ClassSchema, ParseError> {
37 let all = storage.all_schemas().await?;
38 Ok(all
39 .into_iter()
40 .find(|s| s.class_name == class_name)
41 .unwrap_or_else(|| default_schema(class_name)))
42}
43
44pub async fn create<S: StorageAdapter>(
50 storage: &S,
51 class_name: &str,
52 body: ParseMap,
53 scope: &AclScope,
54) -> Result<CreateResponse, ParseError> {
55 let mut schema = load_schema(storage, class_name).await?;
56
57 let object_id = match body.get("objectId") {
61 Some(ParseValue::String(id)) => id.clone(),
62 _ => new_object_id(),
63 };
64 let now = ParseDate::now();
65
66 let mut row = body;
67 row.insert(
68 "objectId".to_string(),
69 ParseValue::String(object_id.clone()),
70 );
71 row.insert("createdAt".to_string(), ParseValue::Date(now));
72 row.insert("updatedAt".to_string(), ParseValue::Date(now));
73
74 let delta = validate_write(&schema, &row)?;
75
76 let stored = lower_acl(row);
79
80 apply(&mut schema, &delta);
81 storage.create(&schema, &stored).await?;
82 if !delta.is_empty() {
83 storage.upsert_schema(&schema).await?;
84 }
85
86 let _ = scope; Ok(CreateResponse {
88 object_id,
89 created_at: now,
90 })
91}
92
93pub async fn find<S: StorageAdapter>(
95 storage: &S,
96 class_name: &str,
97 mut constraints: Vec<Constraint>,
98 options: QueryOptions,
99 scope: &AclScope,
100) -> Result<Vec<ParseMap>, ParseError> {
101 let schema = load_schema(storage, class_name).await?;
102 if let Some(acl) = scope.read_constraint() {
103 constraints.push(acl);
104 }
105 let rows = storage.find(&schema, &constraints, &options).await?;
106 Ok(rows.into_iter().map(raise_acl).collect())
107}
108
109pub async fn get<S: StorageAdapter>(
115 storage: &S,
116 class_name: &str,
117 object_id: &str,
118 scope: &AclScope,
119) -> Result<ParseMap, ParseError> {
120 let rows = find(
121 storage,
122 class_name,
123 vec![Constraint::equal(
124 "objectId",
125 ParseValue::String(object_id.to_string()),
126 )],
127 QueryOptions {
128 limit: Some(1),
129 ..Default::default()
130 },
131 scope,
132 )
133 .await?;
134
135 rows.into_iter().next().ok_or_else(object_not_found)
136}
137
138pub async fn count<S: StorageAdapter>(
139 storage: &S,
140 class_name: &str,
141 mut constraints: Vec<Constraint>,
142 scope: &AclScope,
143) -> Result<u64, ParseError> {
144 let schema = load_schema(storage, class_name).await?;
145 if let Some(acl) = scope.read_constraint() {
146 constraints.push(acl);
147 }
148 storage.count(&schema, &constraints).await
149}
150
151pub async fn update<S: StorageAdapter>(
153 storage: &S,
154 class_name: &str,
155 object_id: &str,
156 body: ParseMap,
157 scope: &AclScope,
158) -> Result<UpdateResponse, ParseError> {
159 let mut schema = load_schema(storage, class_name).await?;
160
161 let now = ParseDate::now();
162 let mut row = body;
163 row.shift_remove("objectId");
165 row.shift_remove("createdAt");
166 row.insert("updatedAt".to_string(), ParseValue::Date(now));
167
168 let delta = validate_write(&schema, &row)?;
169 let values = lower_acl(row);
170
171 let mut constraints = vec![Constraint::equal(
172 "objectId",
173 ParseValue::String(object_id.to_string()),
174 )];
175 if let Some(acl) = scope.write_constraint() {
176 constraints.push(acl);
177 }
178
179 apply(&mut schema, &delta);
180 let matched = storage.update(&schema, &constraints, &values).await?;
181 if matched == 0 {
182 return Err(object_not_found());
183 }
184 if !delta.is_empty() {
185 storage.upsert_schema(&schema).await?;
186 }
187
188 Ok(UpdateResponse { updated_at: now })
189}
190
191pub async fn delete<S: StorageAdapter>(
193 storage: &S,
194 class_name: &str,
195 object_id: &str,
196 scope: &AclScope,
197) -> Result<(), ParseError> {
198 let schema = load_schema(storage, class_name).await?;
199 let mut constraints = vec![Constraint::equal(
200 "objectId",
201 ParseValue::String(object_id.to_string()),
202 )];
203 if let Some(acl) = scope.write_constraint() {
204 constraints.push(acl);
205 }
206 let deleted = storage.delete(&schema, &constraints).await?;
207 if deleted == 0 {
208 return Err(object_not_found());
209 }
210 Ok(())
211}
212
213fn object_not_found() -> ParseError {
215 ParseError::new(ErrorCode::ObjectNotFound, "Object not found.")
216}