tetratto-core 12.0.0

The core behind Tetratto
Documentation
use base64::{engine::general_purpose::URL_SAFE as base64url, Engine};
use serde::{Serialize, Deserialize};
use tetratto_shared::hash::hash;
use super::{Result, Error};

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct AuthGrant {
    /// The ID of the application associated with this grant.
    pub app: usize,
    /// The code challenge for PKCE verifiers associated with this grant.
    ///
    /// This challenge is *all* that is required to refresh this grant's auth token.
    /// While there can only be one token at a time, it can be refreshed whenever as long
    /// as the provided verifier matches that of the challenge.
    ///
    /// The challenge should never be changed. To change the challenge, the grant
    /// should be removed and recreated.
    pub challenge: String,
    /// The encoding method for the initial verifier in the challenge.
    pub method: PkceChallengeMethod,
    /// The access token associated with the account. This is **not** the same as
    /// regular account access tokens, as the token can only be used with the requested `scopes`.
    pub token: String,
    /// The time in which the token was last refreshed. Tokens should stop being
    /// accepted after a week has passed since this time.
    pub last_updated: usize,
    /// Scopes define what the grant's token is actually allowed to do.
    ///
    /// No scope shall ever be allowed to change scopes or manage grants on behalf of the user.
    /// A regular user token **must** be provided to manage grants.
    pub scopes: Vec<AppScope>,
}

#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub enum PkceChallengeMethod {
    S256,
}

#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub enum AppScope {
    /// Read the profile of other users on behalf of the user.
    UserReadProfiles,
    /// Read the user's profile (username, bio, etc).
    UserReadProfile,
    /// Read the user's settings.
    UserReadSettings,
    /// Read the user's sessions and info.
    UserReadSessions,
    /// Read posts as the user.
    UserReadPosts,
    /// Read messages as the user.
    UserReadMessages,
    /// Read drafts as the user.
    UserReadDrafts,
    /// Read the user's communities.
    UserReadCommunities,
    /// Connect to sockets on the user's behalf.
    UserReadSockets,
    /// Read the user's notifications.
    UserReadNotifications,
    /// Read the user's requests.
    UserReadRequests,
    /// Read questions as the user.
    UserReadQuestions,
    /// Read the user's stacks.
    UserReadStacks,
    /// Read the user's journals.
    UserReadJournals,
    /// Read the user's notes.
    UserReadNotes,
    /// Read the user's layouts.
    UserReadLayouts,
    /// Read the user's domains.
    UserReadDomains,
    /// Read the user's services.
    UserReadServices,
    /// Read the user's products.
    UserReadProducts,
    /// Create posts as the user.
    UserCreatePosts,
    /// Create messages as the user.
    UserCreateMessages,
    /// Ask questions as the user.
    UserCreateQuestions,
    /// Create IP blocks as the user.
    UserCreateIpBlock,
    /// Create drafts on behalf of the user.
    UserCreateDrafts,
    /// Create communities on behalf of the user.
    UserCreateCommunities,
    /// Create stacks on behalf of the user.
    UserCreateStacks,
    /// Create journals on behalf of the user.
    UserCreateJournals,
    /// Create notes on behalf of the user.
    UserCreateNotes,
    /// Create layouts on behalf of the user.
    UserCreateLayouts,
    /// Create domains on behalf of the user.
    UserCreateDomains,
    /// Create services on behalf of the user.
    UserCreateServices,
    /// Create products on behalf of the user.
    UserCreateProducts,
    /// Delete posts owned by the user.
    UserDeletePosts,
    /// Delete messages owned by the user.
    UserDeleteMessages,
    /// Delete questions as the user.
    UserDeleteQuestions,
    /// Delete drafts as the user.
    UserDeleteDrafts,
    /// Edit the user's settings and upload avatars/banners on behalf of the user.
    UserManageProfile,
    /// Manage stacks owned by the user.
    UserManageStacks,
    /// Manage the user's following/unfollowing.
    UserManageRelationships,
    /// Manage the user's community memberships.
    ///
    /// Also includes managing the membership of users in the user's communities.
    UserManageMemberships,
    /// Follow/unfollow users on behalf of the user.
    UserManageFollowing,
    /// Accept follow requests on behalf of the user.
    UserManageFollowers,
    /// Block/unblock users on behalf of the user.
    UserManageBlocks,
    /// Manage the user's notifications.
    UserManageNotifications,
    /// Manage the user's requests.
    UserManageRequests,
    /// Manage the user's uploads.
    UserManageUploads,
    /// Manage the user's journals.
    UserManageJournals,
    /// Manage the user's notes.
    UserManageNotes,
    /// Manage the user's layouts.
    UserManageLayouts,
    /// Manage the user's domains.
    UserManageDomains,
    /// Manage the user's services.
    UserManageServices,
    /// Manage the user's products.
    UserManageProducts,
    /// Manage the user's channel mutes.
    UserManageChannelMutes,
    /// Edit posts created by the user.
    UserEditPosts,
    /// Edit drafts created by the user.
    UserEditDrafts,
    /// Vote in polls as the user.
    UserVote,
    /// React to posts on behalf of the user. Also allows the removal of reactions.
    UserReact,
    /// Join communities on behalf of the user.
    UserJoinCommunities,
    /// Permanently delete posts.
    ModPurgePosts,
    /// Restore deleted posts.
    ModDeletePosts,
    /// Manage user warnings.
    ModManageWarnings,
    /// Get a list of all emojis available to the user.
    UserReadEmojis,
    /// Create emojis on behalf of the user.
    CommunityCreateEmojis,
    /// Manage emojis on behalf of the user.
    CommunityManageEmojis,
    /// Delete communities on behalf of the user.
    CommunityDelete,
    /// Manage communities on behalf of the user.
    CommunityManage,
    /// Transfer ownership of communities on behalf of the user.
    CommunityTransferOwnership,
    /// Read the membership of users in communities owned by the current user.
    CommunityReadMemberships,
    /// Create channels in the user's communities.
    CommunityCreateChannels,
    /// Manage channels in the user's communities.
    CommunityManageChannels,
}

impl AuthGrant {
    /// Check a verifier against the stored challenge (using the given [`PkceChallengeMethod`]).
    pub fn check_verifier(&self, verifier: &str) -> Result<()> {
        if self.method != PkceChallengeMethod::S256 {
            return Err(Error::MiscError("only S256 is supported".to_string()));
        }

        let decoded = match base64url.decode(self.challenge.as_bytes()) {
            Ok(hash) => hash,
            Err(e) => return Err(Error::MiscError(e.to_string())),
        };

        let hash = hash(verifier.to_string());

        if hash.as_bytes() != decoded {
            // the verifier we received does not match the verifier from the stored challenge
            return Err(Error::NotAllowed);
        }

        Ok(())
    }
}