1use allowthem_core::AuthError;
2
3#[derive(Debug, thiserror::Error)]
4pub enum SaasError {
5 #[error("slug is already taken")]
6 SlugTaken,
7 #[error("slug is invalid: {0}")]
8 SlugInvalid(&'static str),
9 #[error("slug is reserved")]
10 SlugReserved,
11 #[error("tenant not found")]
12 TenantNotFound,
13 #[error("slug cannot be changed after first login")]
14 SlugChangeAfterFirstLogin,
15 #[error("provisioning failed: {0}")]
16 ProvisionFailed(String),
17 #[error("invalid tenant role: {0}")]
18 InvalidRole(String),
19 #[error("member already exists for that email")]
20 MemberAlreadyExists,
21 #[error("invite token not found or expired")]
22 InviteNotFoundOrExpired,
23 #[error("member not found")]
24 MemberNotFound,
25 #[error("cannot demote the only remaining owner")]
26 CannotDemoteLastOwner,
27 #[error("cannot remove the only remaining owner")]
28 CannotRemoveLastOwner,
29 #[error("domain already exists")]
30 DomainAlreadyExists,
31 #[error("domain not found")]
32 DomainNotFound,
33 #[error("invalid domain: {0}")]
34 DomainInvalid(&'static str),
35 #[error("dns error: {0}")]
36 Dns(String),
37 #[error(transparent)]
38 Auth(#[from] AuthError),
39 #[error(transparent)]
40 Db(#[from] sqlx::Error),
41 #[error(transparent)]
42 Io(#[from] std::io::Error),
43}
44
45fn is_unique_violation(e: &sqlx::Error) -> bool {
46 matches!(e, sqlx::Error::Database(db_err) if db_err.is_unique_violation())
47}
48
49pub(crate) fn map_slug_conflict(e: sqlx::Error) -> SaasError {
50 if is_unique_violation(&e) {
51 SaasError::SlugTaken
52 } else {
53 SaasError::Db(e)
54 }
55}