1use super::*;
2use crate::StudyDuoRestrictionInput;
3
4pub struct GovernedAssetDuo {
7 pub study: StudyRecord,
8 pub catalog: AssetVersionCatalog,
9 pub version: ahri_tre_types::AssetVersionRecord,
10 pub effective: bool,
11 pub restrictions: Vec<EffectiveAssetVersionDuoRestriction>,
12}
13
14impl AppService {
15 async fn asset_duo_scope(
16 &self,
17 selector: ahri_tre_protocol::asset::AssetSelector,
18 version: Option<&str>,
19 ) -> Result<GovernedAssetDuo, AppError> {
20 let (study, catalog, pinned) = self.resolve_catalogue_asset(selector).await?;
21 let version = self.catalogue_version(&catalog, pinned, version)?;
22 Ok(GovernedAssetDuo {
23 study,
24 catalog,
25 version,
26 effective: false,
27 restrictions: Vec::new(),
28 })
29 }
30
31 pub async fn list_governed_asset_duo(
32 &self,
33 request: ahri_tre_protocol::asset::AssetDuoListRequest,
34 ) -> Result<GovernedAssetDuo, AppError> {
35 let mut result = self
36 .asset_duo_scope(request.asset, request.version.as_deref())
37 .await?;
38 result.effective = request.effective;
39 result.restrictions = if request.effective {
40 self.list_effective_asset_version_duo_restrictions(
41 ListEffectiveAssetVersionDuoRestrictionsRequest {
42 study_id: result.study.study_id,
43 version_id: result.version.version_id,
44 },
45 )
46 .await?
47 .restrictions
48 } else {
49 self.list_asset_version_duo_restrictions(ListAssetVersionDuoRestrictionsRequest {
50 version_id: result.version.version_id,
51 })
52 .await?
53 .restrictions
54 .into_iter()
55 .map(explicit_duo_value)
56 .collect()
57 };
58 Ok(result)
59 }
60
61 pub async fn clear_governed_asset_duo(
62 &self,
63 request: ahri_tre_protocol::asset::AssetDuoClearRequest,
64 ) -> Result<GovernedAssetDuo, AppError> {
65 let mut result = self
66 .asset_duo_scope(request.asset, request.version.as_deref())
67 .await?;
68 result.restrictions = self
69 .clear_asset_version_duo_restrictions(ClearAssetVersionDuoRestrictionsRequest {
70 version_id: result.version.version_id,
71 })
72 .await?
73 .restrictions
74 .into_iter()
75 .map(explicit_duo_value)
76 .collect();
77 Ok(result)
78 }
79
80 pub async fn replace_governed_asset_duo(
81 &self,
82 request: ahri_tre_protocol::asset::AssetDuoReplaceRequest,
83 ) -> Result<GovernedAssetDuo, AppError> {
84 let mut result = self
85 .asset_duo_scope(request.asset, request.version.as_deref())
86 .await?;
87 let restrictions = request
88 .restrictions
89 .into_iter()
90 .map(|input| crate::AssetVersionDuoRestrictionInput {
91 code: input.code,
92 duo_id: input.duo_id,
93 qualifier_ontology_namespace: input.qualifier_ontology_namespace,
94 qualifier_ontology_id: input.qualifier_ontology_id,
95 qualifier_text: input.qualifier_text,
96 qualifier_date: input.qualifier_date,
97 qualifier_integer: input.qualifier_integer,
98 })
99 .collect();
100 result.restrictions = self
101 .replace_asset_version_duo_restrictions(ReplaceAssetVersionDuoRestrictionsRequest {
102 version_id: result.version.version_id,
103 restrictions,
104 })
105 .await?
106 .restrictions
107 .into_iter()
108 .map(explicit_duo_value)
109 .collect();
110 Ok(result)
111 }
112}
113
114fn explicit_duo_value(
115 restriction: ahri_tre_types::AssetVersionDuoRestrictionRecord,
116) -> EffectiveAssetVersionDuoRestriction {
117 EffectiveAssetVersionDuoRestriction {
118 source: AssetDuoRestrictionSource::AssetVersion,
119 duo_id: restriction.duo_id,
120 qualifier_ontology_namespace: restriction.qualifier_ontology_namespace,
121 qualifier_ontology_id: restriction.qualifier_ontology_id,
122 qualifier_text: restriction.qualifier_text,
123 qualifier_date: restriction.qualifier_date,
124 qualifier_integer: restriction.qualifier_integer,
125 }
126}
127
128impl AppService {
129 async fn governance_study(
130 &self,
131 selector: ahri_tre_protocol::study::StudySelector,
132 ) -> Result<StudyRecord, AppError> {
133 self.resolve_study_selector(self.catalogue_study_selector(selector)?, "governance Study")
134 .await
135 }
136
137 pub async fn grant_governed_study_access(
138 &self,
139 request: ahri_tre_protocol::study::StudyAccessGrantRequest,
140 ) -> Result<(StudyRecord, StudyAccessGrant), AppError> {
141 let study = self.governance_study(request.study).await?;
142 let grant = self
143 .grant_study_access(GrantStudyAccessRequest {
144 study_id: study.study_id,
145 target_user_id: request.target_user,
146 })
147 .await?;
148 Ok((study, grant))
149 }
150
151 pub async fn add_governed_study_domain(
154 &self,
155 request: ahri_tre_protocol::study::AddStudyDomainRequest,
156 ) -> Result<StudyRegistration, AppError> {
157 self.add_study_domain(AddStudyDomainRequest {
158 study: self.catalogue_study_selector(request.study)?,
159 domain: self.catalogue_domain_selector(request.domain)?,
160 })
161 .await
162 }
163}
164
165impl AppService {
166 pub async fn list_governed_study_access(
167 &self,
168 request: ahri_tre_protocol::study::StudyAccessListRequest,
169 ) -> Result<(StudyRecord, crate::StudyAccessGrantList), AppError> {
170 let study = self.governance_study(request.study).await?;
171 let result = self
172 .list_study_access_grants(ListStudyAccessGrantsRequest {
173 study_id: study.study_id,
174 })
175 .await?;
176 Ok((study, result))
177 }
178}
179
180impl AppService {
181 pub async fn revoke_governed_study_access(
182 &self,
183 request: ahri_tre_protocol::study::StudyAccessRevokeRequest,
184 ) -> Result<(StudyRecord, crate::StudyAccessRevocation), AppError> {
185 let study = self.governance_study(request.study).await?;
186 let result = self
187 .revoke_study_access(RevokeStudyAccessRequest {
188 study_id: study.study_id,
189 target_user_id: request.target_user,
190 })
191 .await?;
192 Ok((study, result))
193 }
194}
195
196impl AppService {
197 pub async fn list_governed_study_custodians(
198 &self,
199 request: ahri_tre_protocol::study::StudyCustodiansListRequest,
200 ) -> Result<(StudyRecord, crate::StudyCustodianList), AppError> {
201 let study = self.governance_study(request.study).await?;
202 let result = self
203 .list_study_custodians(ListStudyCustodiansRequest {
204 study_id: study.study_id,
205 })
206 .await?;
207 Ok((study, result))
208 }
209}
210
211impl AppService {
212 pub async fn add_governed_delegate_custodian(
213 &self,
214 request: ahri_tre_protocol::study::StudyCustodianMutationRequest,
215 ) -> Result<(StudyRecord, crate::StudyCustodian), AppError> {
216 let study = self.governance_study(request.study).await?;
217 let result = self
218 .add_delegate_custodian(AddDelegateCustodianRequest {
219 study_id: study.study_id,
220 target_user_id: request.target_user,
221 })
222 .await?;
223 Ok((study, result))
224 }
225}
226
227impl AppService {
228 pub async fn transfer_governed_primary_custodian(
229 &self,
230 request: ahri_tre_protocol::study::StudyCustodianMutationRequest,
231 ) -> Result<(StudyRecord, crate::StudyPrimaryCustodianshipTransfer), AppError> {
232 let study = self.governance_study(request.study).await?;
233 let result = self
234 .transfer_primary_custodianship(TransferPrimaryCustodianshipRequest {
235 study_id: study.study_id,
236 target_user_id: request.target_user,
237 })
238 .await?;
239 Ok((study, result))
240 }
241}
242
243impl AppService {
244 pub async fn remove_governed_delegate_custodian(
245 &self,
246 request: ahri_tre_protocol::study::StudyCustodianMutationRequest,
247 ) -> Result<(StudyRecord, crate::StudyDelegateCustodianRemoval), AppError> {
248 let study = self.governance_study(request.study).await?;
249 let result = self
250 .remove_delegate_custodian(RemoveDelegateCustodianRequest {
251 study_id: study.study_id,
252 target_user_id: request.target_user,
253 })
254 .await?;
255 Ok((study, result))
256 }
257}
258
259impl AppService {
260 pub async fn list_governed_study_duo(
261 &self,
262 request: ahri_tre_protocol::study::StudyDuoListRequest,
263 ) -> Result<(StudyRecord, crate::StudyDuoRestrictionList), AppError> {
264 let study = self.governance_study(request.study).await?;
265 let result = self
266 .list_study_duo_restrictions(ListStudyDuoRestrictionsRequest {
267 study_id: study.study_id,
268 })
269 .await?;
270 Ok((study, result))
271 }
272}
273
274impl AppService {
275 pub async fn replace_governed_study_duo(
276 &self,
277 request: ahri_tre_protocol::study::StudyDuoReplaceRequest,
278 ) -> Result<(StudyRecord, crate::StudyDuoRestrictionReplacement), AppError> {
279 let study = self.governance_study(request.study).await?;
280 let result = self
281 .replace_study_duo_restrictions(ReplaceStudyDuoRestrictionsRequest {
282 study_id: study.study_id,
283 restrictions: request
284 .restrictions
285 .into_iter()
286 .map(study_duo_input)
287 .collect(),
288 })
289 .await?;
290 Ok((study, result))
291 }
292}
293
294fn study_duo_input(
295 input: ahri_tre_protocol::study::StudyDuoRestrictionInput,
296) -> StudyDuoRestrictionInput {
297 StudyDuoRestrictionInput {
298 code: input.code,
299 duo_id: input.duo_id,
300 qualifier_ontology_namespace: input.qualifier_ontology_namespace,
301 qualifier_ontology_id: input.qualifier_ontology_id,
302 qualifier_text: input.qualifier_text,
303 qualifier_date: input.qualifier_date,
304 qualifier_integer: input.qualifier_integer,
305 }
306}