From 722a11bb811eebaec230a95e200baa3aa236eafe Mon Sep 17 00:00:00 2001
From: William Brown <william@blackhats.net.au>
Date: Sat, 29 Mar 2025 12:22:26 +1000
Subject: [PATCH] Uhoh

---
 proto/src/internal/error.rs       |  2 ++
 server/core/src/actors/v1_scim.rs |  2 +-
 server/lib/src/entry.rs           |  5 +++++
 server/lib/src/server/scim.rs     | 27 +++++++++++++++++++++++----
 4 files changed, 31 insertions(+), 5 deletions(-)

diff --git a/proto/src/internal/error.rs b/proto/src/internal/error.rs
index 09f6cb144..0bdd890b1 100644
--- a/proto/src/internal/error.rs
+++ b/proto/src/internal/error.rs
@@ -213,6 +213,7 @@ pub enum OperationError {
     SC0024SshPublicKeySyntaxInvalid,
     SC0025UiHintSyntaxInvalid,
     SC0026Utf8SyntaxInvalid,
+    SC0027ClassSetInvalid,
     // Migration
     MG0001InvalidReMigrationLevel,
     MG0002RaiseDomainLevelExceedsMaximum,
@@ -492,6 +493,7 @@ impl OperationError {
             Self::SC0024SshPublicKeySyntaxInvalid => Some("A SCIM Ssh Public Key contained invalid syntax".into()),
             Self::SC0025UiHintSyntaxInvalid => Some("A SCIM UiHint contained invalid syntax".into()),
             Self::SC0026Utf8SyntaxInvalid => Some("A SCIM Utf8 String Scope Map contained invalid syntax".into()),
+            Self::SC0027ClassSetInvalid => Some("The internal set of class templates used in this create operation was invalid. THIS IS A BUG.".into()),
 
             Self::UI0001ChallengeSerialisation => Some("The WebAuthn challenge was unable to be serialised.".into()),
             Self::UI0002InvalidState => Some("The credential update process returned an invalid state transition.".into()),
diff --git a/server/core/src/actors/v1_scim.rs b/server/core/src/actors/v1_scim.rs
index e8326f317..6761ba1f2 100644
--- a/server/core/src/actors/v1_scim.rs
+++ b/server/core/src/actors/v1_scim.rs
@@ -202,7 +202,7 @@ impl QueryServerWriteV1 {
                 e
             })?;
 
-        let scim_create_event = ScimCreateEvent::try_from(ident, classes, entry, idms_prox_write)?;
+        let scim_create_event = ScimCreateEvent::try_from(ident, classes, entry, &mut idms_prox_write.qs_write)?;
 
         idms_prox_write
             .qs_write
diff --git a/server/lib/src/entry.rs b/server/lib/src/entry.rs
index 6ac88d3e0..4563fe5fd 100644
--- a/server/lib/src/entry.rs
+++ b/server/lib/src/entry.rs
@@ -488,6 +488,11 @@ impl Entry<EntryInit, EntryNew> {
         self.attrs.remove(attr);
     }
 
+    /// Set the content of this ava with this valueset, ignoring the previous data.
+    pub fn set_ava_set(&mut self, attr: &Attribute, vs: ValueSet) {
+        self.attrs.insert(attr.clone(), vs);
+    }
+
     /// Replace the existing content of an attribute set of this Entry, with a new set of Values.
     pub fn set_ava<T>(&mut self, attr: Attribute, iter: T)
     where
diff --git a/server/lib/src/server/scim.rs b/server/lib/src/server/scim.rs
index 4d3e48122..5f785777b 100644
--- a/server/lib/src/server/scim.rs
+++ b/server/lib/src/server/scim.rs
@@ -65,14 +65,24 @@ impl ScimCreateEvent {
         entry: ScimEntryPostGeneric,
         qs: &mut QueryServerWriteTransaction,
     ) -> Result<Self, OperationError> {
-        let entry = entry
+        let mut entry = entry
             .attrs
             .into_iter()
             .map(|(attr, json_value)| {
                 qs.resolve_scim_json_post(&attr, json_value)
                     .map(|kani_value| (attr, kani_value))
             })
-            .collect::<Result<_, _>>()?;
+            .collect::<Result<EntryInitNew, _>>()?;
+
+
+        let classes =
+            ValueSetIutf8::from_iter(
+                classes.iter()
+                    .map(|cls| cls.as_ref())
+            )
+            .ok_or(OperationError::SC0027ClassSetInvalid)?;
+
+        entry.set_ava_set(&Attribute::Class, classes);
 
         Ok(ScimCreateEvent { ident, entry })
     }
@@ -169,8 +179,17 @@ impl QueryServerWriteTransaction<'_> {
         }
     }
 
-    pub fn scim_create(&mut self, _scim_create: ScimCreateEvent) -> Result<(), OperationError> {
-        todo!();
+    pub fn scim_create(&mut self, scim_create: ScimCreateEvent) -> Result<(), OperationError> {
+        let ScimCreateEvent {
+            ident, entry
+        } = scim_create;
+
+        let create_event = CreateEvent {
+            ident,
+            entries: vec![entry],
+        };
+
+        self.create(&create_event)
     }
 
     pub fn scim_delete(&mut self, scim_delete: ScimDeleteEvent) -> Result<(), OperationError> {