1use std::{fmt, rc::Rc};
3use futures::future::LocalBoxFuture;
4use lenso_kernel::{InvocationContext, NativeRequestEndpoint, NativeRequestFuture, NativeRequestHandle, PluginDependencies, RequestCapability, RuntimeFailure};
5
6use lenso_plugin_authoring::{BoundCapabilityClient, CapabilityClient, CapabilityClientMany};
7pub const CAPABILITY_ID: &str = "lenso.organization-admin@2";
8pub const DESCRIPTOR_VERSION: &str = "1.0.0";
9pub const PORTABLE: bool = true;
10pub const CROSS_LANE_TRANSFER: bool = true;
11pub const ORGANIZATION_ADMIN_CAPABILITY_ID: &str = CAPABILITY_ID;
12pub const ORGANIZATION_ADMIN_DESCRIPTOR_VERSION: &str = DESCRIPTOR_VERSION;
13
14#[doc(hidden)]
15#[macro_export]
16macro_rules! __lenso_provided_organization_admin { () => { "{\"capability_id\":\"lenso.organization-admin@2\",\"descriptor_version\":\"1.0.0\",\"operations\":[\"create_organization\"],\"operation_kinds\":{},\"default_admission\":{\"queue_capacity\":0,\"max_concurrency\":1},\"operation_admissions\":{},\"event_admission\":null,\"cross_lane_transfer\":true}" }; }
17
18#[doc(hidden)]
19#[macro_export]
20macro_rules! __lenso_required_organization_admin_client { () => { "{\"capability_id\":\"lenso.organization-admin@2\",\"descriptor_version\":\"1.0.0\",\"cardinality\":\"one\"}" }; }
21
22#[doc(hidden)]
23#[macro_export]
24macro_rules! __lenso_required_many_organization_admin_client { () => { "{\"capability_id\":\"lenso.organization-admin@2\",\"descriptor_version\":\"1.0.0\",\"cardinality\":\"many\"}" }; }
25
26pub const CREATE_ORGANIZATION_OPERATION: &str = "create_organization";
27
28pub use lenso_contract_runtime::{UnknownDomainError};
29use lenso_contract_runtime::{decode_portable_json, encode_portable_json};
30
31#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
32pub struct CreateOrganizationRequest {
33 #[serde(rename = "idempotency_key")]
34 #[serde(deserialize_with = "lenso_contract_runtime::serde::deserialize_required")]
35 pub idempotency_key: String,
36 #[serde(rename = "name")]
37 #[serde(deserialize_with = "lenso_contract_runtime::serde::deserialize_required")]
38 pub name: String,
39 #[serde(rename = "owner_subject")]
40 #[serde(deserialize_with = "lenso_contract_runtime::serde::deserialize_required")]
41 pub owner_subject: String,
42 #[serde(rename = "slug")]
43 #[serde(deserialize_with = "lenso_contract_runtime::serde::deserialize_required")]
44 pub slug: String,
45}
46
47#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
48pub struct CreateOrganizationResponse {
49 #[serde(rename = "created")]
50 #[serde(deserialize_with = "lenso_contract_runtime::serde::deserialize_required")]
51 pub created: bool,
52 #[serde(rename = "organization_id")]
53 #[serde(deserialize_with = "lenso_contract_runtime::serde::deserialize_required")]
54 pub organization_id: String,
55 #[serde(rename = "owner_membership_id")]
56 #[serde(deserialize_with = "lenso_contract_runtime::serde::deserialize_required")]
57 pub owner_membership_id: String,
58}
59
60#[derive(Clone, Debug, PartialEq)]
61pub enum CreateOrganizationError {
62 Forbidden,
63 IdempotencyConflict,
64 InvalidOrganization,
65 SlugConflict,
66 Unknown(UnknownDomainError),
67}
68
69#[derive(Debug)]
70pub struct OrganizationAdmin;
71impl RequestCapability for OrganizationAdmin {
72 type Request = CreateOrganizationRequest;
73 type Response = CreateOrganizationResponse;
74 type DomainError = CreateOrganizationError;
75 const ID: &'static str = CAPABILITY_ID;
76 const DESCRIPTOR_VERSION: &'static str = DESCRIPTOR_VERSION;
77
78 fn invoke_native(endpoint: &dyn NativeRequestEndpoint, operation: &str, request: Self::Request, context: InvocationContext) -> NativeRequestFuture<Self> {
79 if operation != CREATE_ORGANIZATION_OPERATION {
80 return lenso_kernel::invoke_typed_or_erased_native_request::<Self>(endpoint, operation, request, context);
81 }
82 let Some(typed_endpoint) = endpoint
83 .typed_endpoint()
84 .and_then(|endpoint| endpoint.downcast_ref::<OrganizationAdminRequestEndpoint>())
85 else {
86 return lenso_kernel::invoke_typed_or_erased_native_request::<Self>(endpoint, operation, request, context);
87 };
88 Rc::clone(&typed_endpoint.provider).create_organization(context, request)
89 }
90}
91
92impl serde::Serialize for CreateOrganizationError {
93 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
94 where
95 S: serde::Serializer,
96 {
97 use serde::ser::SerializeMap;
98 match self {
99 Self::Forbidden => serializer.serialize_str("forbidden"),
100 Self::IdempotencyConflict => serializer.serialize_str("idempotency_conflict"),
101 Self::InvalidOrganization => serializer.serialize_str("invalid_organization"),
102 Self::SlugConflict => serializer.serialize_str("slug_conflict"),
103 Self::Unknown(value) => {
104 let mut map = serializer.serialize_map(Some(1 + usize::from(value.payload.is_some()) + value.extra.len()))?;
105 map.serialize_entry("code", &value.code)?;
106 if let Some(payload) = &value.payload {
107 map.serialize_entry("payload", payload)?;
108 }
109 for (key, extra) in &value.extra {
110 map.serialize_entry(key, extra)?;
111 }
112 map.end()
113 },
114 }
115 }
116}
117
118impl<'de> serde::Deserialize<'de> for CreateOrganizationError {
119 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
120 where
121 D: serde::Deserializer<'de>,
122 {
123 let value = <serde_json::Value as serde::Deserialize>::deserialize(deserializer)?;
124 match value {
125 serde_json::Value::String(code) => match code.as_str() {
126 "forbidden" => Ok(Self::Forbidden),
127 "idempotency_conflict" => Ok(Self::IdempotencyConflict),
128 "invalid_organization" => Ok(Self::InvalidOrganization),
129 "slug_conflict" => Ok(Self::SlugConflict),
130 _ => Ok(Self::Unknown(UnknownDomainError { code, payload: None, extra: std::collections::BTreeMap::new() })),
131 },
132 serde_json::Value::Object(mut object) => {
133 let Some(code) = object.remove("code").and_then(|value| value.as_str().map(ToOwned::to_owned)) else {
134 return Err(serde::de::Error::custom("Domain Error object is missing a string code"));
135 };
136 let payload = object.remove("payload");
137 let extra = object.into_iter().collect::<std::collections::BTreeMap<_, _>>();
138 Ok(Self::Unknown(UnknownDomainError { code, payload, extra }))
139 }
140 other => Err(serde::de::Error::custom(format!("Domain Error must be a string or object, got {other}"))),
141 }
142 }
143}
144
145pub fn encode_create_organization_request(value: &CreateOrganizationRequest) -> Result<String, serde_json::Error> { encode_portable_json(value) }
146pub fn decode_create_organization_request(wire: &str) -> Result<CreateOrganizationRequest, serde_json::Error> { decode_portable_json(wire) }
147pub fn encode_create_organization_response(value: &CreateOrganizationResponse) -> Result<String, serde_json::Error> { encode_portable_json(value) }
148pub fn decode_create_organization_response(wire: &str) -> Result<CreateOrganizationResponse, serde_json::Error> { decode_portable_json(wire) }
149pub fn encode_create_organization_error(value: &CreateOrganizationError) -> Result<String, serde_json::Error> { encode_portable_json(value) }
150pub fn decode_create_organization_error(wire: &str) -> Result<CreateOrganizationError, serde_json::Error> { decode_portable_json(wire) }
151
152#[doc(hidden)]
153pub trait __LensoIntoOrganizationAdminCreateOrganizationResult {
154 fn __lenso_into_result(self) -> Result<Result<CreateOrganizationResponse, CreateOrganizationError>, RuntimeFailure>;
155}
156impl __LensoIntoOrganizationAdminCreateOrganizationResult for Result<CreateOrganizationResponse, CreateOrganizationError> {
157 fn __lenso_into_result(self) -> Result<Result<CreateOrganizationResponse, CreateOrganizationError>, RuntimeFailure> { Ok(self) }
158}
159impl __LensoIntoOrganizationAdminCreateOrganizationResult for Result<Result<CreateOrganizationResponse, CreateOrganizationError>, RuntimeFailure> {
160 fn __lenso_into_result(self) -> Result<Result<CreateOrganizationResponse, CreateOrganizationError>, RuntimeFailure> { self }
161}
162impl __LensoIntoOrganizationAdminCreateOrganizationResult for Result<CreateOrganizationResponse, lenso_plugin_authoring::PluginError<CreateOrganizationError, RuntimeFailure>> {
163 fn __lenso_into_result(self) -> Result<Result<CreateOrganizationResponse, CreateOrganizationError>, RuntimeFailure> {
164 match self {
165 Ok(value) => Ok(Ok(value)),
166 Err(lenso_plugin_authoring::PluginError::Domain(error)) => Ok(Err(error)),
167 Err(lenso_plugin_authoring::PluginError::Runtime(error)) => Err(error),
168 }
169 }
170}
171impl __LensoIntoOrganizationAdminCreateOrganizationResult for Result<CreateOrganizationResponse, OrganizationAdminInvocationError> {
172 fn __lenso_into_result(self) -> Result<Result<CreateOrganizationResponse, CreateOrganizationError>, RuntimeFailure> {
173 match self {
174 Ok(value) => Ok(Ok(value)),
175 Err(OrganizationAdminInvocationError::Domain(error)) => Ok(Err(error)),
176 Err(OrganizationAdminInvocationError::Runtime(error)) => Err(error),
177 }
178 }
179}
180
181pub trait OrganizationAdminProvider: fmt::Debug + 'static {
182 fn create_organization(&self, context: InvocationContext, request: CreateOrganizationRequest) -> NativeRequestFuture<OrganizationAdmin>;
183}
184
185#[doc(hidden)]
186#[macro_export]
187macro_rules! __lenso_native_lower_organization_admin {
188 ($plugin:ty, $support:path) => {
189 use $support as __LensoNativeSupportOrganizationAdmin;
190 impl $crate::OrganizationAdminProvider for $plugin {
191 fn create_organization(&self, context: __LensoNativeSupportOrganizationAdmin::InvocationContext, request: $crate::CreateOrganizationRequest) -> __LensoNativeSupportOrganizationAdmin::NativeRequestFuture<$crate::OrganizationAdmin> {
192 let plugin = self.clone();
193 ::std::boxed::Box::pin(async move {
194 let result = <$plugin>::create_organization(&plugin, context, request).await;
195 $crate::__LensoIntoOrganizationAdminCreateOrganizationResult::__lenso_into_result(result)
196 })
197 }
198 }
199 };
200}
201
202#[derive(Debug)]
203struct OrganizationAdminRequestEndpoint { provider: Rc<dyn OrganizationAdminProvider> }
204
205#[derive(Debug)]
206pub struct OrganizationAdminEndpoint<P: OrganizationAdminProvider> { provider: Rc<P>, request_endpoint: OrganizationAdminRequestEndpoint }
207impl<P: OrganizationAdminProvider> OrganizationAdminEndpoint<P> {
208 pub fn new(provider: P) -> Self {
209 let provider = Rc::new(provider);
210 let request_provider: Rc<dyn OrganizationAdminProvider> = provider.clone();
211 Self { provider, request_endpoint: OrganizationAdminRequestEndpoint { provider: request_provider } }
212 }
213}
214
215impl<P: OrganizationAdminProvider> NativeRequestEndpoint for OrganizationAdminEndpoint<P> {
216 fn capability_id(&self) -> &'static str { CAPABILITY_ID }
217 fn descriptor_version(&self) -> &'static str { DESCRIPTOR_VERSION }
218 fn operations(&self) -> &'static [&'static str] { &[
219 CREATE_ORGANIZATION_OPERATION,
220 ] }
221 fn typed_endpoint(&self) -> Option<&dyn std::any::Any> { Some(&self.request_endpoint) }
222 fn invoke(&self, operation: &str, request: Box<dyn std::any::Any>, context: InvocationContext) -> LocalBoxFuture<'static, Result<Result<Box<dyn std::any::Any>, Box<dyn std::any::Any>>, RuntimeFailure>> {
223 match operation {
224 CREATE_ORGANIZATION_OPERATION => {
225 let Ok(request) = request.downcast::<CreateOrganizationRequest>() else {
226 return Box::pin(futures::future::ready(Err(RuntimeFailure::ProtocolViolation { capability: CAPABILITY_ID })));
227 };
228 let invocation = Rc::clone(&self.provider).create_organization(context, *request);
229 Box::pin(async move {
230 invocation.await.map(|result| {
231 result
232 .map(|value| Box::new(value) as Box<dyn std::any::Any>)
233 .map_err(|error| Box::new(error) as Box<dyn std::any::Any>)
234 })
235 })
236 }
237 _ => Box::pin(futures::future::ready(Err(RuntimeFailure::UnknownOperation { capability: CAPABILITY_ID, operation: operation.to_owned() }))),
238 }
239 }
240}
241
242#[doc(hidden)]
243#[macro_export]
244macro_rules! __lenso_native_endpoints_organization_admin {
245 ($provider:expr, $support:path) => {{
246 use $support as __LensoNativeSupport;
247 let endpoint = ::std::rc::Rc::new($crate::OrganizationAdminEndpoint::new($provider));
248 (
249 vec![endpoint.clone() as ::std::rc::Rc<dyn __LensoNativeSupport::NativeRequestEndpoint>],
250 vec![],
251 vec![],
252 )
253 }};
254}
255
256#[doc(hidden)]
257#[macro_export]
258macro_rules! __lenso_native_provide_organization_admin {
259 ($provider:expr, $lifecycle:expr, $support:path) => {{
260 use $support as __LensoNativeSupport;
261 let (request_endpoints, stream_endpoints, event_endpoints) =
262 $crate::__lenso_native_endpoints_organization_admin!($provider, $support);
263 __LensoNativeSupport::NativePluginInstance::with_all_endpoints(
264 request_endpoints,
265 stream_endpoints,
266 event_endpoints,
267 $lifecycle,
268 )
269 }};
270}
271
272#[derive(Debug)]
273pub struct OrganizationAdminClient {
274 create_organization: NativeRequestHandle<OrganizationAdmin>,
275}
276impl OrganizationAdminClient {
277 pub fn new(handle: NativeRequestHandle<OrganizationAdmin>) -> Self {
278 Self { create_organization: handle }
279 }
280
281 pub fn from_dependencies(dependencies: &PluginDependencies) -> Result<Self, RuntimeFailure> {
282 <Self as CapabilityClient>::from_dependencies(dependencies)
283 }
284
285 pub async fn create_organization(&self, request: CreateOrganizationRequest) -> Result<CreateOrganizationResponse, OrganizationAdminInvocationError> {
286 self.create_organization.invoke(CREATE_ORGANIZATION_OPERATION, request).await
287 .map_err(OrganizationAdminInvocationError::Runtime)?
288 .map_err(OrganizationAdminInvocationError::Domain)
289 }
290
291 pub async fn create_organization_with_context(&self, context: InvocationContext, request: CreateOrganizationRequest) -> Result<CreateOrganizationResponse, OrganizationAdminInvocationError> {
292 self.create_organization.invoke_with_context(CREATE_ORGANIZATION_OPERATION, context, request).await
293 .map_err(OrganizationAdminInvocationError::Runtime)?
294 .map_err(OrganizationAdminInvocationError::Domain)
295 }
296}
297
298impl CapabilityClient for OrganizationAdminClient {
299 type Dependencies = PluginDependencies;
300 type Error = RuntimeFailure;
301
302 const CAPABILITY_ID: &'static str = CAPABILITY_ID;
303 const DESCRIPTOR_VERSION: &'static str = DESCRIPTOR_VERSION;
304
305 fn from_dependencies(dependencies: &PluginDependencies) -> Result<Self, RuntimeFailure> {
306 Ok(Self {
307 create_organization: dependencies.one::<OrganizationAdmin>()?,
308 })
309 }
310
311 fn already_connected() -> RuntimeFailure {
312 RuntimeFailure::PluginFailure {
313 detail: format!("Capability Port {CAPABILITY_ID} was connected more than once"),
314 }
315 }
316}
317
318impl CapabilityClientMany for OrganizationAdminClient {
319 fn many_from_dependencies(
320 dependencies: &PluginDependencies,
321 ) -> Result<Vec<BoundCapabilityClient<Self>>, RuntimeFailure> {
322 dependencies
323 .bindings()
324 .iter()
325 .filter(|binding| binding.capability_id() == CAPABILITY_ID)
326 .map(|binding| {
327 Ok(BoundCapabilityClient::new(
328 binding.provider_instance(),
329 Self {
330 create_organization: binding.handle().ok_or(RuntimeFailure::Unavailable { capability: CAPABILITY_ID })?.typed::<OrganizationAdmin>()?,
331 },
332 ))
333 })
334 .collect()
335 }
336}
337
338#[derive(Clone, Debug, PartialEq)]
339pub enum OrganizationAdminInvocationError {
340 Domain(CreateOrganizationError),
341 Runtime(RuntimeFailure),
342}