summaryrefslogtreecommitdiff
path: root/src/models
diff options
context:
space:
mode:
Diffstat (limited to 'src/models')
-rw-r--r--src/models/client.rs330
-rw-r--r--src/models/mod.rs4
-rw-r--r--src/models/user.rs98
3 files changed, 216 insertions, 216 deletions
diff --git a/src/models/client.rs b/src/models/client.rs
index 38be37f..6d0c909 100644
--- a/src/models/client.rs
+++ b/src/models/client.rs
@@ -1,165 +1,165 @@
-use std::{hash::Hash, marker::PhantomData};
-
-use actix_web::{http::StatusCode, ResponseError};
-use exun::{Expect, RawUnexpected};
-use raise::yeet;
-use serde::{Deserialize, Serialize};
-use thiserror::Error;
-use url::Url;
-use uuid::Uuid;
-
-use crate::services::crypto::PasswordHash;
-
-/// There are two types of clients, based on their ability to maintain the
-/// security of their client credentials.
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, sqlx::Type)]
-#[sqlx(rename_all = "lowercase")]
-#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
-pub enum ClientType {
- /// A client that is capable of maintaining the confidentiality of their
- /// credentials, or capable of secure client authentication using other
- /// means. An example would be a secure server with restricted access to
- /// the client credentials.
- Confidential,
- /// A client that is incapable of maintaining the confidentiality of their
- /// credentials and cannot authenticate securely by any other means, such
- /// as an installed application, or a web-browser based application.
- Public,
-}
-
-#[derive(Debug, Clone)]
-pub struct Client {
- id: Uuid,
- ty: ClientType,
- alias: Box<str>,
- secret: Option<PasswordHash>,
- allowed_scopes: Box<[Box<str>]>,
- default_scopes: Option<Box<[Box<str>]>>,
- redirect_uris: Box<[Url]>,
- trusted: bool,
-}
-
-impl PartialEq for Client {
- fn eq(&self, other: &Self) -> bool {
- self.id == other.id
- }
-}
-
-impl Eq for Client {}
-
-impl Hash for Client {
- fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
- state.write_u128(self.id.as_u128())
- }
-}
-
-#[derive(Debug, Clone, Copy, Error)]
-#[error("Confidential clients must have a secret, but it was not provided")]
-pub enum CreateClientError {
- #[error("Confidential clients must have a secret, but it was not provided")]
- NoSecret,
- #[error("Only confidential clients may be trusted")]
- TrustedError,
- #[error("Redirect URIs must not include a fragment component")]
- UriFragment,
- #[error("Redirect URIs must use HTTPS")]
- NonHttpsUri,
-}
-
-impl ResponseError for CreateClientError {
- fn status_code(&self) -> StatusCode {
- StatusCode::BAD_REQUEST
- }
-}
-
-impl Client {
- pub fn new(
- id: Uuid,
- alias: &str,
- ty: ClientType,
- secret: Option<&str>,
- allowed_scopes: Box<[Box<str>]>,
- default_scopes: Option<Box<[Box<str>]>>,
- redirect_uris: &[Url],
- trusted: bool,
- ) -> Result<Self, Expect<CreateClientError>> {
- let secret = if let Some(secret) = secret {
- Some(PasswordHash::new(secret)?)
- } else {
- None
- };
-
- if ty == ClientType::Confidential && secret.is_none() {
- yeet!(CreateClientError::NoSecret.into());
- }
-
- if ty == ClientType::Public && trusted {
- yeet!(CreateClientError::TrustedError.into());
- }
-
- for redirect_uri in redirect_uris {
- if redirect_uri.scheme() != "https" {
- yeet!(CreateClientError::NonHttpsUri.into())
- }
-
- if redirect_uri.fragment().is_some() {
- yeet!(CreateClientError::UriFragment.into())
- }
- }
-
- Ok(Self {
- id,
- alias: Box::from(alias),
- ty,
- secret,
- allowed_scopes,
- default_scopes,
- redirect_uris: redirect_uris.into_iter().cloned().collect(),
- trusted,
- })
- }
-
- pub fn id(&self) -> Uuid {
- self.id
- }
-
- pub fn alias(&self) -> &str {
- &self.alias
- }
-
- pub fn client_type(&self) -> ClientType {
- self.ty
- }
-
- pub fn redirect_uris(&self) -> &[Url] {
- &self.redirect_uris
- }
-
- pub fn secret_hash(&self) -> Option<&[u8]> {
- self.secret.as_ref().map(|s| s.hash())
- }
-
- pub fn secret_salt(&self) -> Option<&[u8]> {
- self.secret.as_ref().map(|s| s.salt())
- }
-
- pub fn secret_version(&self) -> Option<u8> {
- self.secret.as_ref().map(|s| s.version())
- }
-
- pub fn allowed_scopes(&self) -> String {
- self.allowed_scopes.join(" ")
- }
-
- pub fn default_scopes(&self) -> Option<String> {
- self.default_scopes.clone().map(|s| s.join(" "))
- }
-
- pub fn is_trusted(&self) -> bool {
- self.trusted
- }
-
- pub fn check_secret(&self, secret: &str) -> Option<Result<bool, RawUnexpected>> {
- self.secret.as_ref().map(|s| s.check_password(secret))
- }
-}
+use std::{hash::Hash, marker::PhantomData};
+
+use actix_web::{http::StatusCode, ResponseError};
+use exun::{Expect, RawUnexpected};
+use raise::yeet;
+use serde::{Deserialize, Serialize};
+use thiserror::Error;
+use url::Url;
+use uuid::Uuid;
+
+use crate::services::crypto::PasswordHash;
+
+/// There are two types of clients, based on their ability to maintain the
+/// security of their client credentials.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, sqlx::Type)]
+#[sqlx(rename_all = "lowercase")]
+#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
+pub enum ClientType {
+ /// A client that is capable of maintaining the confidentiality of their
+ /// credentials, or capable of secure client authentication using other
+ /// means. An example would be a secure server with restricted access to
+ /// the client credentials.
+ Confidential,
+ /// A client that is incapable of maintaining the confidentiality of their
+ /// credentials and cannot authenticate securely by any other means, such
+ /// as an installed application, or a web-browser based application.
+ Public,
+}
+
+#[derive(Debug, Clone)]
+pub struct Client {
+ id: Uuid,
+ ty: ClientType,
+ alias: Box<str>,
+ secret: Option<PasswordHash>,
+ allowed_scopes: Box<[Box<str>]>,
+ default_scopes: Option<Box<[Box<str>]>>,
+ redirect_uris: Box<[Url]>,
+ trusted: bool,
+}
+
+impl PartialEq for Client {
+ fn eq(&self, other: &Self) -> bool {
+ self.id == other.id
+ }
+}
+
+impl Eq for Client {}
+
+impl Hash for Client {
+ fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
+ state.write_u128(self.id.as_u128())
+ }
+}
+
+#[derive(Debug, Clone, Copy, Error)]
+#[error("Confidential clients must have a secret, but it was not provided")]
+pub enum CreateClientError {
+ #[error("Confidential clients must have a secret, but it was not provided")]
+ NoSecret,
+ #[error("Only confidential clients may be trusted")]
+ TrustedError,
+ #[error("Redirect URIs must not include a fragment component")]
+ UriFragment,
+ #[error("Redirect URIs must use HTTPS")]
+ NonHttpsUri,
+}
+
+impl ResponseError for CreateClientError {
+ fn status_code(&self) -> StatusCode {
+ StatusCode::BAD_REQUEST
+ }
+}
+
+impl Client {
+ pub fn new(
+ id: Uuid,
+ alias: &str,
+ ty: ClientType,
+ secret: Option<&str>,
+ allowed_scopes: Box<[Box<str>]>,
+ default_scopes: Option<Box<[Box<str>]>>,
+ redirect_uris: &[Url],
+ trusted: bool,
+ ) -> Result<Self, Expect<CreateClientError>> {
+ let secret = if let Some(secret) = secret {
+ Some(PasswordHash::new(secret)?)
+ } else {
+ None
+ };
+
+ if ty == ClientType::Confidential && secret.is_none() {
+ yeet!(CreateClientError::NoSecret.into());
+ }
+
+ if ty == ClientType::Public && trusted {
+ yeet!(CreateClientError::TrustedError.into());
+ }
+
+ for redirect_uri in redirect_uris {
+ if redirect_uri.scheme() != "https" {
+ yeet!(CreateClientError::NonHttpsUri.into())
+ }
+
+ if redirect_uri.fragment().is_some() {
+ yeet!(CreateClientError::UriFragment.into())
+ }
+ }
+
+ Ok(Self {
+ id,
+ alias: Box::from(alias),
+ ty,
+ secret,
+ allowed_scopes,
+ default_scopes,
+ redirect_uris: redirect_uris.into_iter().cloned().collect(),
+ trusted,
+ })
+ }
+
+ pub fn id(&self) -> Uuid {
+ self.id
+ }
+
+ pub fn alias(&self) -> &str {
+ &self.alias
+ }
+
+ pub fn client_type(&self) -> ClientType {
+ self.ty
+ }
+
+ pub fn redirect_uris(&self) -> &[Url] {
+ &self.redirect_uris
+ }
+
+ pub fn secret_hash(&self) -> Option<&[u8]> {
+ self.secret.as_ref().map(|s| s.hash())
+ }
+
+ pub fn secret_salt(&self) -> Option<&[u8]> {
+ self.secret.as_ref().map(|s| s.salt())
+ }
+
+ pub fn secret_version(&self) -> Option<u8> {
+ self.secret.as_ref().map(|s| s.version())
+ }
+
+ pub fn allowed_scopes(&self) -> String {
+ self.allowed_scopes.join(" ")
+ }
+
+ pub fn default_scopes(&self) -> Option<String> {
+ self.default_scopes.clone().map(|s| s.join(" "))
+ }
+
+ pub fn is_trusted(&self) -> bool {
+ self.trusted
+ }
+
+ pub fn check_secret(&self, secret: &str) -> Option<Result<bool, RawUnexpected>> {
+ self.secret.as_ref().map(|s| s.check_password(secret))
+ }
+}
diff --git a/src/models/mod.rs b/src/models/mod.rs
index 633f846..1379893 100644
--- a/src/models/mod.rs
+++ b/src/models/mod.rs
@@ -1,2 +1,2 @@
-pub mod client;
-pub mod user;
+pub mod client;
+pub mod user;
diff --git a/src/models/user.rs b/src/models/user.rs
index 8555ee2..493a267 100644
--- a/src/models/user.rs
+++ b/src/models/user.rs
@@ -1,49 +1,49 @@
-use std::hash::Hash;
-
-use exun::RawUnexpected;
-use uuid::Uuid;
-
-use crate::services::crypto::PasswordHash;
-
-#[derive(Debug, Clone)]
-pub struct User {
- pub id: Uuid,
- pub username: Box<str>,
- pub password: PasswordHash,
-}
-
-impl PartialEq for User {
- fn eq(&self, other: &Self) -> bool {
- self.id == other.id
- }
-}
-
-impl Eq for User {}
-
-impl Hash for User {
- fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
- state.write_u128(self.id.as_u128())
- }
-}
-
-impl User {
- pub fn username(&self) -> &str {
- &self.username
- }
-
- pub fn password_hash(&self) -> &[u8] {
- self.password.hash()
- }
-
- pub fn password_salt(&self) -> &[u8] {
- self.password.salt()
- }
-
- pub fn password_version(&self) -> u8 {
- self.password.version()
- }
-
- pub fn check_password(&self, password: &str) -> Result<bool, RawUnexpected> {
- self.password.check_password(password)
- }
-}
+use std::hash::Hash;
+
+use exun::RawUnexpected;
+use uuid::Uuid;
+
+use crate::services::crypto::PasswordHash;
+
+#[derive(Debug, Clone)]
+pub struct User {
+ pub id: Uuid,
+ pub username: Box<str>,
+ pub password: PasswordHash,
+}
+
+impl PartialEq for User {
+ fn eq(&self, other: &Self) -> bool {
+ self.id == other.id
+ }
+}
+
+impl Eq for User {}
+
+impl Hash for User {
+ fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
+ state.write_u128(self.id.as_u128())
+ }
+}
+
+impl User {
+ pub fn username(&self) -> &str {
+ &self.username
+ }
+
+ pub fn password_hash(&self) -> &[u8] {
+ self.password.hash()
+ }
+
+ pub fn password_salt(&self) -> &[u8] {
+ self.password.salt()
+ }
+
+ pub fn password_version(&self) -> u8 {
+ self.password.version()
+ }
+
+ pub fn check_password(&self, password: &str) -> Result<bool, RawUnexpected> {
+ self.password.check_password(password)
+ }
+}