orca/models/
auth_only.rs

1use crate::model::{self, ActorModel, Transition, TransitionAction, TransitionResult};
2
3use crate::error::Error;
4use crate::run::EventRecord;
5use crate::state::*;
6use kanidm_client::KanidmClient;
7
8use async_trait::async_trait;
9
10use std::time::Duration;
11
12enum State {
13    Unauthenticated,
14    Authenticated,
15}
16
17pub struct ActorAuthOnly {
18    state: State,
19}
20
21impl ActorAuthOnly {
22    pub fn new() -> Self {
23        ActorAuthOnly {
24            state: State::Unauthenticated,
25        }
26    }
27}
28
29#[async_trait]
30impl ActorModel for ActorAuthOnly {
31    async fn transition(
32        &mut self,
33        client: &KanidmClient,
34        person: &Person,
35    ) -> Result<Vec<EventRecord>, Error> {
36        let transition = self.next_transition();
37
38        if let Some(delay) = transition.delay {
39            tokio::time::sleep(delay).await;
40        }
41
42        // Once we get to here, we want the transition to go ahead.
43        let (result, event) = match transition.action {
44            TransitionAction::Login => model::login(client, person).await,
45            TransitionAction::Logout => model::logout(client, person).await,
46            _ => Err(Error::InvalidState),
47        }?;
48
49        self.next_state(transition.action, result);
50
51        Ok(event)
52    }
53}
54
55impl ActorAuthOnly {
56    fn next_transition(&mut self) -> Transition {
57        match self.state {
58            State::Unauthenticated => Transition {
59                delay: None,
60                action: TransitionAction::Login,
61            },
62            State::Authenticated => Transition {
63                delay: Some(Duration::from_millis(100)),
64                action: TransitionAction::Logout,
65            },
66        }
67    }
68
69    fn next_state(&mut self, action: TransitionAction, result: TransitionResult) {
70        match (&self.state, action, result) {
71            (State::Unauthenticated, TransitionAction::Login, TransitionResult::Ok) => {
72                self.state = State::Authenticated;
73            }
74            (State::Authenticated, TransitionAction::Logout, TransitionResult::Ok) => {
75                self.state = State::Unauthenticated;
76            }
77            // Shouldn't be reachable?
78            #[allow(clippy::unreachable)]
79            (_, _, TransitionResult::Ok) => {
80                unreachable!();
81            }
82            (_, _, TransitionResult::Error) => {
83                self.state = State::Unauthenticated;
84            }
85        }
86    }
87}