systemprompt-users 0.2.0

Core user management module for systemprompt.io
Documentation
use async_trait::async_trait;
use systemprompt_identifiers::UserId;
use systemprompt_traits::{AuthProviderError, AuthResult, AuthUser, UserProvider};

use crate::UserService;

#[derive(Debug, Clone)]
pub struct UserProviderImpl {
    user_service: UserService,
}

impl UserProviderImpl {
    pub const fn new(user_service: UserService) -> Self {
        Self { user_service }
    }
}

impl From<crate::User> for AuthUser {
    fn from(user: crate::User) -> Self {
        Self {
            id: UserId::new(user.id.to_string()),
            name: user.name,
            email: user.email,
            roles: user.roles,
            is_active: user.status.as_deref() == Some("active"),
        }
    }
}

#[async_trait]
impl UserProvider for UserProviderImpl {
    async fn find_by_id(&self, id: &UserId) -> AuthResult<Option<AuthUser>> {
        self.user_service
            .find_by_id(id)
            .await
            .map(|opt| opt.map(AuthUser::from))
            .map_err(|e| AuthProviderError::Internal(e.to_string()))
    }

    async fn find_by_email(&self, email: &str) -> AuthResult<Option<AuthUser>> {
        self.user_service
            .find_by_email(email)
            .await
            .map(|opt| opt.map(AuthUser::from))
            .map_err(|e| AuthProviderError::Internal(e.to_string()))
    }

    async fn find_by_name(&self, name: &str) -> AuthResult<Option<AuthUser>> {
        self.user_service
            .find_by_name(name)
            .await
            .map(|opt| opt.map(AuthUser::from))
            .map_err(|e| AuthProviderError::Internal(e.to_string()))
    }

    async fn create_user(
        &self,
        name: &str,
        email: &str,
        full_name: Option<&str>,
    ) -> AuthResult<AuthUser> {
        self.user_service
            .create(name, email, full_name, None)
            .await
            .map(AuthUser::from)
            .map_err(|e| AuthProviderError::Internal(e.to_string()))
    }

    async fn create_anonymous(&self, fingerprint: &str) -> AuthResult<AuthUser> {
        self.user_service
            .create_anonymous(fingerprint)
            .await
            .map(AuthUser::from)
            .map_err(|e| AuthProviderError::Internal(e.to_string()))
    }

    async fn assign_roles(&self, user_id: &UserId, roles: &[String]) -> AuthResult<()> {
        self.user_service
            .assign_roles(user_id, roles)
            .await
            .map(|_| ())
            .map_err(|e| AuthProviderError::Internal(e.to_string()))
    }
}