1use objectstore_service::id::{ObjectContext, ObjectId};
2use objectstore_service::multipart::{
3 AbortMultipartResponse, CompleteMultipartResponse, CompletedPart, InitiateMultipartResponse,
4 ListPartsResponse, PartNumber, UploadId, UploadPartResponse,
5};
6use objectstore_service::service::{DeleteResponse, GetResponse, InsertResponse, MetadataResponse};
7use objectstore_service::{ClientStream, StorageService};
8use objectstore_types::auth::Permission;
9use objectstore_types::metadata::Metadata;
10
11use crate::auth::{AuthContext, AuthError};
12use crate::endpoints::common::ApiResult;
13
14#[derive(Debug)]
36pub struct AuthAwareService {
37 service: StorageService,
38 context: Option<AuthContext>,
39 enforce: bool,
40}
41
42impl AuthAwareService {
43 pub fn new(
52 service: StorageService,
53 context: Option<AuthContext>,
54 enforce: bool,
55 ) -> ApiResult<Self> {
56 if enforce && context.is_none() {
57 let err = AuthError::InternalError("Missing auth context".into());
58 err.log(None, None, enforce);
59 Err(err.into())
60 } else {
61 Ok(Self {
62 service,
63 context,
64 enforce,
65 })
66 }
67 }
68
69 fn assert_authorized(&self, perm: Permission, context: &ObjectContext) -> ApiResult<()> {
70 let auth_result = match &self.context {
71 Some(auth) => auth.assert_authorized(perm, context),
72 None => Ok(()),
73 }
74 .inspect_err(|err| err.log(Some(perm), Some(context.usecase.as_str()), self.enforce));
75
76 match self.enforce {
77 true => Ok(auth_result?),
78 false => Ok(()),
79 }
80 }
81
82 pub fn check_permission(&self, perm: Permission, context: &ObjectContext) -> ApiResult<()> {
88 self.assert_authorized(perm, context)
89 }
90
91 pub async fn insert_object(
93 &self,
94 context: ObjectContext,
95 key: Option<String>,
96 metadata: Metadata,
97 stream: ClientStream,
98 ) -> ApiResult<InsertResponse> {
99 self.assert_authorized(Permission::ObjectWrite, &context)?;
100 Ok(self
101 .service
102 .insert_object(context, key, metadata, stream)
103 .await?)
104 }
105
106 pub async fn get_metadata(&self, id: ObjectId) -> ApiResult<MetadataResponse> {
108 self.assert_authorized(Permission::ObjectRead, id.context())?;
109 Ok(self.service.get_metadata(id).await?)
110 }
111
112 pub async fn get_object(&self, id: ObjectId) -> ApiResult<GetResponse> {
114 self.assert_authorized(Permission::ObjectRead, id.context())?;
115 Ok(self.service.get_object(id).await?)
116 }
117
118 pub async fn delete_object(&self, id: ObjectId) -> ApiResult<DeleteResponse> {
120 self.assert_authorized(Permission::ObjectDelete, id.context())?;
121 Ok(self.service.delete_object(id).await?)
122 }
123
124 pub async fn initiate_multipart(
128 &self,
129 id: ObjectId,
130 metadata: Metadata,
131 ) -> ApiResult<InitiateMultipartResponse> {
132 self.assert_authorized(Permission::ObjectWrite, id.context())?;
133 Ok(self.service.initiate_multipart(id, metadata).await?)
134 }
135
136 pub async fn upload_part(
138 &self,
139 id: ObjectId,
140 upload_id: UploadId,
141 part_number: PartNumber,
142 content_length: u64,
143 content_md5: Option<String>,
144 body: ClientStream,
145 ) -> ApiResult<UploadPartResponse> {
146 self.assert_authorized(Permission::ObjectWrite, id.context())?;
147 Ok(self
148 .service
149 .upload_part(
150 id,
151 upload_id,
152 part_number,
153 content_length,
154 content_md5,
155 body,
156 )
157 .await?)
158 }
159
160 pub async fn list_parts(
162 &self,
163 id: ObjectId,
164 upload_id: UploadId,
165 max_parts: Option<u32>,
166 part_number_marker: Option<PartNumber>,
167 ) -> ApiResult<ListPartsResponse> {
168 self.assert_authorized(Permission::ObjectWrite, id.context())?;
169 Ok(self
170 .service
171 .list_parts(id, upload_id, max_parts, part_number_marker)
172 .await?)
173 }
174
175 pub async fn abort_multipart(
177 &self,
178 id: ObjectId,
179 upload_id: UploadId,
180 ) -> ApiResult<AbortMultipartResponse> {
181 self.assert_authorized(Permission::ObjectWrite, id.context())?;
182 Ok(self.service.abort_multipart(id, upload_id).await?)
183 }
184
185 pub async fn complete_multipart(
187 &self,
188 id: ObjectId,
189 upload_id: UploadId,
190 parts: Vec<CompletedPart>,
191 ) -> ApiResult<CompleteMultipartResponse> {
192 self.assert_authorized(Permission::ObjectWrite, id.context())?;
193 Ok(self
194 .service
195 .complete_multipart(id, upload_id, parts)
196 .await?)
197 }
198}