Skip to main content

kanidmd_lib/idm/
account_signup.rs

1use crate::idm::server::IdmServerProxyWriteTransaction;
2use crate::prelude::*;
3
4pub struct AccountSignupRequestEvent {
5    // Who initiated this? By default I think
6    // this will be an internal identity?
7    pub ident: Identity,
8    username: String,
9    display_name: String,
10    email: String,
11}
12
13impl IdmServerProxyWriteTransaction<'_> {
14    pub fn account_signup_request(
15        &mut self,
16        asre: AccountSignupRequestEvent,
17    ) -> Result<(), OperationError> {
18        // If the feature is not enabled, error.
19        if !self.qs_write.get_feature_account_signup_config().enabled {
20            warn!("Attempt to perform account signup while feature is disabled.");
21            return Err(OperationError::AS0001FeatureDisabled);
22        }
23
24        // Generates a new account signup request entry that needs further processing.
25        // It needs a "delete after" tag.
26
27        let AccountSignupRequestEvent {
28            ident,
29            username,
30            display_name,
31            email,
32        } = asre;
33
34        let account_signup_entry = EntryInitNew::from_iter([
35            (
36                Attribute::Class,
37                ValueSetIutf8::new(EntryClass::AccountSignupRequest.into()) as ValueSet,
38            ),
39            (Attribute::Name, ValueSetIname::new(&username) as ValueSet),
40            (
41                Attribute::DisplayName,
42                ValueSetUtf8::new(display_name) as ValueSet,
43            ),
44            (
45                Attribute::Mail,
46                ValueSetEmailAddress::new(email) as ValueSet,
47            ),
48        ]);
49
50        // Create
51        let ce = CreateEvent {
52            ident,
53            entries: vec![account_signup_entry],
54            return_created_uuids: true,
55        };
56
57        self.qs_write.create(&ce)?;
58
59        // TODO: Perform the post process on the request.
60
61        Ok(())
62    }
63
64    // We need a post-process handler for any events on the signup request. In a way this
65    // is kind of similar to a plugin but it doesn't have access to send emails via
66    // the delayed event queue.
67
68    /*
69    fn account_signup_validate_request_state(
70        &mut self,
71
72    ) -> Result<(), OperationError> {
73        // This processes the request and determines if it has passed the needed steps and should
74        // be allowed to continue to a creation.
75    }
76    */
77}
78
79#[cfg(test)]
80mod tests {
81    use super::AccountSignupRequestEvent;
82    use crate::prelude::*;
83
84    const TESTPERSON_NAME: &str = "testperson";
85    const TESTPERSON_DISPLAY_NAME: &str = "Test Personington";
86    const TESTPERSON_EMAIL: &str = "testperson@example.com";
87
88    #[idm_test]
89    async fn test_account_signup_request_feature_disable(
90        idms: &IdmServer,
91        _idms_delayed: &mut IdmServerDelayed,
92    ) {
93        // If the feature is disabled, the request implicitly fails.
94        let ct = duration_from_epoch_now();
95        let mut write_txn = idms.proxy_write(ct).await.unwrap();
96
97        let account_signup_req = AccountSignupRequestEvent {
98            ident: Identity::account_request(),
99            username: TESTPERSON_NAME.into(),
100            display_name: TESTPERSON_DISPLAY_NAME.into(),
101            email: TESTPERSON_EMAIL.into(),
102        };
103
104        let result = write_txn
105            .account_signup_request(account_signup_req)
106            .unwrap_err();
107
108        assert_eq!(result, OperationError::AS0001FeatureDisabled);
109    }
110
111    #[idm_test]
112    async fn test_account_signup_request_basic(
113        idms: &IdmServer,
114        _idms_delayed: &mut IdmServerDelayed,
115    ) {
116        // Enable the feature.
117        let ct = duration_from_epoch_now();
118        let mut write_txn = idms.proxy_write(ct).await.unwrap();
119
120        write_txn
121            .qs_write
122            .internal_batch_modify(
123                [(
124                    UUID_ACCOUNT_SIGNUP_FEATURE,
125                    ModifyList::from_iter([(Attribute::Enabled, Some(vs_bool!(true) as ValueSet))]),
126                )]
127                .into_iter(),
128            )
129            .unwrap();
130
131        write_txn.qs_write.reload().unwrap();
132
133        // Create a new request.
134        let account_signup_req = AccountSignupRequestEvent {
135            ident: Identity::account_request(),
136            username: TESTPERSON_NAME.into(),
137            display_name: TESTPERSON_DISPLAY_NAME.into(),
138            email: TESTPERSON_EMAIL.into(),
139        };
140
141        write_txn
142            .account_signup_request(account_signup_req)
143            .unwrap();
144
145        // Since there are no validation rules in place, it should immediately succeed.
146
147        // Validate the person
148
149        // TODO: Validate the message in the delayed queue
150    }
151}