Skip to content

Commit

Permalink
feat: room handlers for admin and client API (#23)
Browse files Browse the repository at this point in the history
Hopefully the commit messages are self-explanatory

<!--
Developer's Certificate of Origin 1.1

By making a contribution to this project, I certify that:

(a) The contribution was created in whole or in part by me and I
    have the right to submit it under the open source license
    indicated in the file; or

(b) The contribution is based upon previous work that, to the best
    of my knowledge, is covered under an appropriate open source
    license and I have the right under that license to submit that
    work with modifications, whether created in whole or in part
    by me, under the same open source license (unless I am
    permitted to submit under a different license), as indicated
    in the file; or

(c) The contribution was provided directly to me by some other
    person who certified (a), (b) or (c) and I have not modified
    it.

(d) I understand and agree that this project and the contribution
    are public and that a record of the contribution (including all
    personal information I submit with it, including my sign-off) is
    maintained indefinitely and may be redistributed consistent with
    this project or the open source license(s) involved.
-->

---------

Co-authored-by: Esteban Borai <[email protected]>
  • Loading branch information
avdb13 and LeoBorai authored Feb 13, 2024
1 parent 9beaa22 commit b2d6546
Show file tree
Hide file tree
Showing 43 changed files with 1,807 additions and 240 deletions.
1 change: 1 addition & 0 deletions crates/core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ serde_json = { workspace = true }
tracing = { workspace = true }
uuid = { workspace = true, features= ["serde"] }
url = { workspace = true, features = ["serde"] }
tokio = { workspace = true, features = ["full"] }

# Local Dependencies
matrix = { path = "../matrix" }
46 changes: 25 additions & 21 deletions crates/core/src/account/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,26 @@ use url::Url;
use uuid::Uuid;
use validator::{Validate, ValidationError};

use matrix::admin::resources::user::{
ListUsersParams, LoginAsUserDto, ThreePid, User as MatrixUser, UserCreateDto,
use matrix::{
admin::resources::{
user::{ListUsersParams, LoginAsUserDto, ThreePid, User as MatrixUser, UserCreateDto},
user_id::UserId,
},
Client as MatrixAdminClient,
};
use matrix::admin::resources::user_id::UserId;
use matrix::Client as MatrixAdminClient;

use crate::auth::service::AuthService;
use crate::mail::service::{EmailTemplate, MailService};
use crate::util::secret::Secret;
use crate::util::time::timestamp;
use crate::{Error, Result};
use crate::{
auth::service::AuthService,
mail::service::{EmailTemplate, MailService},
util::{secret::Secret, time::timestamp},
Error, Result,
};

use super::error::AccountErrorCode;
use super::model::Account;
use super::{error::AccountErrorCode, model::Account};

const DEFAULT_AVATAR_URL: &str = "https://via.placeholder.com/150";
const MIN_USERNAME_LENGTH: usize = 3;
const MAX_USERNAME_LENGTH: usize = 12;
const MIN_USERNAME_LENGTH: usize = 1;
const MAX_USERNAME_LENGTH: usize = 255;
const MIN_PASSWORD_LENGTH: usize = 8;

#[derive(Debug, Validate)]
Expand Down Expand Up @@ -191,8 +193,8 @@ impl AccountService {
Ok(account)
}

/// Registers a new user account in Matrix Server without verifying the email ownership.
/// This shuld be used for testing purposes only.
/// Registers a new user account in Matrix Server without verifying the
/// email ownership. This shuld be used for testing purposes only.
#[instrument(skip(self, dto))]
pub async fn register_unverified(&self, dto: CreateUnverifiedAccountDto) -> Result<Account> {
dto.validate().map_err(|err| {
Expand Down Expand Up @@ -318,29 +320,29 @@ mod test {
#[test]
fn ensure_username_is_not_too_short() {
let dto = CreateAccountDto {
username: "ab".to_string(),
username: "".to_string(),
password: Secret::new("password"),
email: "[email protected]".to_string(),
code: Secret::new("1234"),
session: Uuid::new_v4(),
};
let err = dto.validate().err().unwrap();

assert_eq!(err.to_string(), "username is too short");
assert!(err.to_string().contains("username is too short"));
}

#[test]
fn ensure_username_is_not_too_long() {
let dto = CreateAccountDto {
username: "abbeyroadismyfavoritealbum".to_string(),
username: (0..300).map(|_| "a").collect(),
password: Secret::new("password"),
email: "[email protected]".to_string(),
code: Secret::new("1234"),
session: Uuid::new_v4(),
};
let err = dto.validate().err().unwrap();

assert_eq!(err.to_string(), "username is too long");
assert!(err.to_string().contains("username is too long"));
}

#[test]
Expand All @@ -354,7 +356,7 @@ mod test {
};
let err = dto.validate().err().unwrap();

assert_eq!(err.to_string(), "username cannot contain spaces");
assert!(err.to_string().contains("username cannot contain spaces"));
}

#[test]
Expand All @@ -368,6 +370,8 @@ mod test {
};
let err = dto.validate().err().unwrap();

assert_eq!(err.to_string(), "username cannot contain uppercase letters");
assert!(err
.to_string()
.contains("username cannot contain uppercase letters"));
}
}
6 changes: 4 additions & 2 deletions crates/core/src/auth/model.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use rand::distributions::{Alphanumeric, DistString};
use rand::SeedableRng;
use rand::{
distributions::{Alphanumeric, DistString},
SeedableRng,
};
use serde::{Deserialize, Serialize};
use uuid::Uuid;

Expand Down
21 changes: 16 additions & 5 deletions crates/core/src/auth/service.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
use std::sync::Arc;

use matrix::client::resources::login::Login;
use matrix::Client as MatrixAdminClient;
use matrix::{
client::resources::login::{Login, LoginFlows as LoginFlowsResponse},
Client as MatrixAdminClient,
};
use redis::AsyncCommands;
use uuid::Uuid;

use crate::auth::error::AuthErrorCode;
use crate::util::secret::Secret;
use crate::Result;
use crate::{auth::error::AuthErrorCode, util::secret::Secret, Error, Result};

use super::model::VerificationCode;

Expand Down Expand Up @@ -43,13 +43,24 @@ impl AuthService {
credentials.password.inner(),
)
.await
// ???
.unwrap();

Ok(LoginCredentialsResponse {
access_token: Secret::new(login_response.access_token),
})
}

pub async fn get_login_flows(&self) -> Result<LoginFlowsResponse> {
match Login::get_login_flows(&self.admin).await {
Ok(flows) => Ok(flows),
Err(err) => {
tracing::error!("Failed to get login flows: {}", err);
Err(Error::Unknown)
}
}
}

pub async fn send_verification_code(
&self,
email: &str,
Expand Down
8 changes: 4 additions & 4 deletions crates/core/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use http::StatusCode;
use thiserror::Error;

use crate::account::error::AccountErrorCode;
use crate::auth::error::AuthErrorCode;
use crate::mail::error::MailErrorCode;
use crate::room::error::RoomErrorCode;
use crate::{
account::error::AccountErrorCode, auth::error::AuthErrorCode, mail::error::MailErrorCode,
room::error::RoomErrorCode,
};

pub type Result<T> = std::result::Result<T, Error>;

Expand Down
7 changes: 2 additions & 5 deletions crates/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,11 @@ use mail::service::MailService;
use room::service::RoomService;
use url::Url;

use std::fmt::Debug;
use std::str::FromStr;
use std::sync::Arc;
use std::{fmt::Debug, str::FromStr, sync::Arc};

use matrix::Client as MatrixAdminClient;

use self::account::service::AccountService;
use self::auth::service::AuthService;
use self::{account::service::AccountService, auth::service::AuthService};

pub mod env {
pub const COMMUNE_SYNAPSE_HOST: &str = "COMMUNE_SYNAPSE_HOST";
Expand Down
3 changes: 1 addition & 2 deletions crates/core/src/mail/error.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use http::StatusCode;
use lettre::error::Error as LettreError;
use lettre::transport::smtp::Error as LettreSmtpError;
use lettre::{error::Error as LettreError, transport::smtp::Error as LettreSmtpError};
use thiserror::Error;

use crate::error::HttpStatusCode;
Expand Down
7 changes: 2 additions & 5 deletions crates/core/src/mail/service.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
use handlebars::Handlebars;
use lettre::message::header::ContentType;
use lettre::{Message, SmtpTransport, Transport};
use lettre::{message::header::ContentType, Message, SmtpTransport, Transport};
use url::Url;

use crate::mail::error::MailErrorCode;
use crate::util::secret::Secret;
use crate::{CommuneConfig, Result};
use crate::{mail::error::MailErrorCode, util::secret::Secret, CommuneConfig, Result};

pub struct MailDevConfig {
pub smtp_host: Url,
Expand Down
9 changes: 7 additions & 2 deletions crates/core/src/room/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,24 @@ use crate::error::HttpStatusCode;

#[derive(Debug, Error)]
pub enum RoomErrorCode {
#[error("Vaildation error. {0}")]
#[error("Failed to parse RoomId")]
MalformedRoomId,
#[error("Validation error. {0}")]
ValidationError(#[from] ValidationErrors),
}

impl HttpStatusCode for RoomErrorCode {
fn status_code(&self) -> StatusCode {
match self {
RoomErrorCode::ValidationError(_) => StatusCode::BAD_REQUEST,
RoomErrorCode::MalformedRoomId | RoomErrorCode::ValidationError(_) => {
StatusCode::BAD_REQUEST
}
}
}

fn error_code(&self) -> &'static str {
match self {
RoomErrorCode::MalformedRoomId => "BAD_REQUEST",
RoomErrorCode::ValidationError(_) => "CREATION_DETAIL_INVALID",
}
}
Expand Down
25 changes: 9 additions & 16 deletions crates/core/src/room/service.rs
Original file line number Diff line number Diff line change
@@ -1,29 +1,25 @@
use std::sync::Arc;

use tracing::instrument;
use validator::Validate;

use matrix::client::resources::room::{
Room as MatrixRoom, RoomPreset, RoomCreationContent, CreateRoomBody,
use matrix::{
client::resources::room::{
CreateRoomBody, Room as MatrixRoom, RoomCreationContent, RoomPreset,
},
Client as MatrixAdminClient,
};
use matrix::Client as MatrixAdminClient;
use validator::Validate;

use crate::util::secret::Secret;
use crate::{Error, Result};
use crate::{util::secret::Secret, Error, Result};

use super::error::RoomErrorCode;
use super::model::Room;

#[derive(Debug, Clone, Validate)]
#[derive(Debug, Default, Validate)]
pub struct CreateRoomDto {
#[validate(length(min = 3, max = 255))]
pub name: String,
#[validate(length(min = 3, max = 255))]
pub topic: String,
#[validate(length(min = 3, max = 255))]
pub alias: String,
}

pub struct RoomService {
admin: Arc<MatrixAdminClient>,
}
Expand All @@ -40,9 +36,6 @@ impl RoomService {
access_token: &Secret,
dto: CreateRoomDto,
) -> Result<Room> {
dto.validate()
.map_err(|err| Error::Room(RoomErrorCode::from(err)))?;

match MatrixRoom::create(
&self.admin,
access_token.to_string(),
Expand All @@ -61,7 +54,7 @@ impl RoomService {
room_id: room.room_id,
}),
Err(err) => {
tracing::error!("Failed to create room: {}", err);
tracing::error!("Failed to create public room: {}", err);
Err(Error::Unknown)
}
}
Expand Down
13 changes: 8 additions & 5 deletions crates/core/src/util/secret.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
use std::borrow::Cow;
use std::convert::Infallible;
use std::fmt::{Debug, Display};
use std::str::FromStr;
use std::{
borrow::Cow,
convert::Infallible,
fmt::{Debug, Display},
str::FromStr,
};

use serde::{Deserialize, Serialize};

/// A `String` wrapper that does not display the value when debugged or displayed.
/// A `String` wrapper that does not display the value when debugged or
/// displayed.
#[derive(Clone, Deserialize, PartialEq, Eq, Hash, Serialize)]
pub struct Secret(Cow<'static, str>);

Expand Down
1 change: 1 addition & 0 deletions crates/matrix/src/admin/resources/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod room;
pub mod token;
pub mod user;
pub mod user_id;
Loading

0 comments on commit b2d6546

Please sign in to comment.