Merge branch 'main' into wip/email
This commit is contained in:
commit
695ecd96f1
6 changed files with 98 additions and 29 deletions
|
@ -9,10 +9,12 @@ use uuid::Uuid;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
Data,
|
Data,
|
||||||
api::v1::auth::{EMAIL_REGEX, PASSWORD_REGEX, USERNAME_REGEX},
|
|
||||||
error::Error,
|
error::Error,
|
||||||
schema::*,
|
schema::*,
|
||||||
utils::{generate_access_token, generate_refresh_token, refresh_token_cookie},
|
utils::{
|
||||||
|
EMAIL_REGEX, PASSWORD_REGEX, USERNAME_REGEX, generate_access_token, generate_refresh_token,
|
||||||
|
refresh_token_cookie,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::Response;
|
use super::Response;
|
||||||
|
|
|
@ -23,15 +23,6 @@ struct Response {
|
||||||
access_token: String,
|
access_token: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
static EMAIL_REGEX: LazyLock<Regex> = LazyLock::new(|| {
|
|
||||||
Regex::new(r"[-A-Za-z0-9!#$%&'*+/=?^_`{|}~]+(?:\.[-A-Za-z0-9!#$%&'*+/=?^_`{|}~]+)*@(?:[A-Za-z0-9](?:[-A-Za-z0-9]*[A-Za-z0-9])?\.)+[A-Za-z0-9](?:[-A-Za-z0-9]*[A-Za-z0-9])?").unwrap()
|
|
||||||
});
|
|
||||||
|
|
||||||
static USERNAME_REGEX: LazyLock<Regex> = LazyLock::new(|| Regex::new(r"^[a-z0-9_.-]+$").unwrap());
|
|
||||||
|
|
||||||
// Password is expected to be hashed using SHA3-384
|
|
||||||
static PASSWORD_REGEX: LazyLock<Regex> = LazyLock::new(|| Regex::new(r"[0-9a-f]{96}").unwrap());
|
|
||||||
|
|
||||||
pub fn web() -> Scope {
|
pub fn web() -> Scope {
|
||||||
web::scope("/auth")
|
web::scope("/auth")
|
||||||
.service(register::res)
|
.service(register::res)
|
||||||
|
|
|
@ -13,14 +13,16 @@ use uuid::Uuid;
|
||||||
use super::Response;
|
use super::Response;
|
||||||
use crate::{
|
use crate::{
|
||||||
Data,
|
Data,
|
||||||
api::v1::auth::{EMAIL_REGEX, PASSWORD_REGEX, USERNAME_REGEX},
|
|
||||||
error::Error,
|
error::Error,
|
||||||
schema::{
|
schema::{
|
||||||
access_tokens::{self, dsl as adsl},
|
access_tokens::{self, dsl as adsl},
|
||||||
refresh_tokens::{self, dsl as rdsl},
|
refresh_tokens::{self, dsl as rdsl},
|
||||||
users::{self, dsl as udsl},
|
users::{self, dsl as udsl},
|
||||||
},
|
},
|
||||||
utils::{generate_access_token, generate_refresh_token, refresh_token_cookie},
|
utils::{
|
||||||
|
EMAIL_REGEX, PASSWORD_REGEX, USERNAME_REGEX, generate_access_token, generate_refresh_token,
|
||||||
|
refresh_token_cookie,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
|
@ -68,9 +70,11 @@ pub async fn res(
|
||||||
data: web::Data<Data>,
|
data: web::Data<Data>,
|
||||||
) -> Result<HttpResponse, Error> {
|
) -> Result<HttpResponse, Error> {
|
||||||
if !data.config.instance.registration {
|
if !data.config.instance.registration {
|
||||||
return Err(Error::Forbidden("registration is disabled on this instance".to_string()))
|
return Err(Error::Forbidden(
|
||||||
|
"registration is disabled on this instance".to_string(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let uuid = Uuid::now_v7();
|
let uuid = Uuid::now_v7();
|
||||||
|
|
||||||
if !EMAIL_REGEX.is_match(&account_information.email) {
|
if !EMAIL_REGEX.is_match(&account_information.email) {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use actix_multipart::form::{MultipartForm, json::Json as MpJson, tempfile::TempFile};
|
use actix_multipart::form::{MultipartForm, json::Json as MpJson, tempfile::TempFile};
|
||||||
use actix_web::{get, patch, web, HttpRequest, HttpResponse, Scope};
|
use actix_web::{HttpRequest, HttpResponse, Scope, get, patch, web};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -9,9 +9,7 @@ use crate::{
|
||||||
mod servers;
|
mod servers;
|
||||||
|
|
||||||
pub fn web() -> Scope {
|
pub fn web() -> Scope {
|
||||||
web::scope("/me")
|
web::scope("/me").service(get).service(update)
|
||||||
.service(get)
|
|
||||||
.service(update)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("")]
|
#[get("")]
|
||||||
|
@ -76,15 +74,15 @@ pub async fn update(
|
||||||
|
|
||||||
if let Some(new_info) = form.json {
|
if let Some(new_info) = form.json {
|
||||||
if let Some(username) = &new_info.username {
|
if let Some(username) = &new_info.username {
|
||||||
todo!();
|
me.set_username(&mut conn, username.clone()).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(display_name) = &new_info.display_name {
|
if let Some(display_name) = &new_info.display_name {
|
||||||
todo!();
|
me.set_display_name(&mut conn, display_name.clone()).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(email) = &new_info.email {
|
if let Some(email) = &new_info.email {
|
||||||
todo!();
|
me.set_email(&mut conn, email.to_string()).await?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,10 @@ use url::Url;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
error::Error, schema::*, utils::{generate_refresh_token, image_check, order_by_is_above}, Conn, Data
|
Conn, Data,
|
||||||
|
error::Error,
|
||||||
|
schema::*,
|
||||||
|
utils::{EMAIL_REGEX, USERNAME_REGEX, generate_refresh_token, image_check, order_by_is_above},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub trait HasUuid {
|
pub trait HasUuid {
|
||||||
|
@ -423,11 +426,7 @@ impl Guild {
|
||||||
futures::future::try_join_all(guild_futures).await
|
futures::future::try_join_all(guild_futures).await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn new(
|
pub async fn new(conn: &mut Conn, name: String, owner_uuid: Uuid) -> Result<Self, Error> {
|
||||||
conn: &mut Conn,
|
|
||||||
name: String,
|
|
||||||
owner_uuid: Uuid,
|
|
||||||
) -> Result<Self, Error> {
|
|
||||||
let guild_uuid = Uuid::now_v7();
|
let guild_uuid = Uuid::now_v7();
|
||||||
|
|
||||||
let guild_builder = GuildBuilder {
|
let guild_builder = GuildBuilder {
|
||||||
|
@ -856,6 +855,64 @@ impl Me {
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn set_username(
|
||||||
|
&mut self,
|
||||||
|
conn: &mut Conn,
|
||||||
|
new_username: String,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
if !USERNAME_REGEX.is_match(&new_username) {
|
||||||
|
return Err(Error::BadRequest("Invalid username".to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
|
use users::dsl;
|
||||||
|
update(users::table)
|
||||||
|
.filter(dsl::uuid.eq(self.uuid))
|
||||||
|
.set(dsl::username.eq(new_username.as_str()))
|
||||||
|
.execute(conn)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
self.username = new_username;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn set_display_name(
|
||||||
|
&mut self,
|
||||||
|
conn: &mut Conn,
|
||||||
|
new_display_name: String,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
use users::dsl;
|
||||||
|
update(users::table)
|
||||||
|
.filter(dsl::uuid.eq(self.uuid))
|
||||||
|
.set(dsl::display_name.eq(new_display_name.as_str()))
|
||||||
|
.execute(conn)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
self.display_name = Some(new_display_name);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn set_email(&mut self, conn: &mut Conn, new_email: String) -> Result<(), Error> {
|
||||||
|
if !EMAIL_REGEX.is_match(&new_email) {
|
||||||
|
return Err(Error::BadRequest("Invalid username".to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
|
use users::dsl;
|
||||||
|
update(users::table)
|
||||||
|
.filter(dsl::uuid.eq(self.uuid))
|
||||||
|
.set((
|
||||||
|
dsl::email.eq(new_email.as_str()),
|
||||||
|
dsl::email_verified.eq(false),
|
||||||
|
))
|
||||||
|
.execute(conn)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
self.email = new_email;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
|
|
19
src/utils.rs
19
src/utils.rs
|
@ -1,3 +1,5 @@
|
||||||
|
use std::sync::LazyLock;
|
||||||
|
|
||||||
use actix_web::{
|
use actix_web::{
|
||||||
cookie::{Cookie, SameSite, time::Duration},
|
cookie::{Cookie, SameSite, time::Duration},
|
||||||
http::header::HeaderMap,
|
http::header::HeaderMap,
|
||||||
|
@ -7,9 +9,24 @@ use bindet::FileType;
|
||||||
use getrandom::fill;
|
use getrandom::fill;
|
||||||
use hex::encode;
|
use hex::encode;
|
||||||
use redis::RedisError;
|
use redis::RedisError;
|
||||||
|
use regex::Regex;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
use crate::{error::Error, structs::{HasIsAbove, HasUuid}, Data};
|
use crate::{
|
||||||
|
Data,
|
||||||
|
error::Error,
|
||||||
|
structs::{HasIsAbove, HasUuid},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub static EMAIL_REGEX: LazyLock<Regex> = LazyLock::new(|| {
|
||||||
|
Regex::new(r"[-A-Za-z0-9!#$%&'*+/=?^_`{|}~]+(?:\.[-A-Za-z0-9!#$%&'*+/=?^_`{|}~]+)*@(?:[A-Za-z0-9](?:[-A-Za-z0-9]*[A-Za-z0-9])?\.)+[A-Za-z0-9](?:[-A-Za-z0-9]*[A-Za-z0-9])?").unwrap()
|
||||||
|
});
|
||||||
|
|
||||||
|
pub static USERNAME_REGEX: LazyLock<Regex> =
|
||||||
|
LazyLock::new(|| Regex::new(r"^[a-z0-9_.-]+$").unwrap());
|
||||||
|
|
||||||
|
// Password is expected to be hashed using SHA3-384
|
||||||
|
pub static PASSWORD_REGEX: LazyLock<Regex> = LazyLock::new(|| Regex::new(r"[0-9a-f]{96}").unwrap());
|
||||||
|
|
||||||
pub fn get_auth_header(headers: &HeaderMap) -> Result<&str, Error> {
|
pub fn get_auth_header(headers: &HeaderMap) -> Result<&str, Error> {
|
||||||
let auth_token = headers.get(actix_web::http::header::AUTHORIZATION);
|
let auth_token = headers.get(actix_web::http::header::AUTHORIZATION);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue