Can create a family
This commit is contained in:
parent
e6c896efa2
commit
f54dfde7f7
@ -14,18 +14,18 @@ CREATE TABLE users (
|
||||
admin BOOLEAN NOT NULL DEFAULT FALSE
|
||||
);
|
||||
|
||||
CREATE TABLE families(
|
||||
CREATE TABLE families (
|
||||
id SERIAL PRIMARY KEY,
|
||||
time_create BIGINT NOT NULL,
|
||||
name VARCHAR(30) NOT NULL,
|
||||
invitation_code VARCHAR(7) NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE memberships(
|
||||
CREATE TABLE memberships (
|
||||
user_id integer NOT NULL REFERENCES users,
|
||||
family_id integer NOT NULL REFERENCES families,
|
||||
time_create BIGINT NOT NULL,
|
||||
is_admin BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
is_admin BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
|
||||
PRIMARY KEY(user_id, family_id)
|
||||
);
|
@ -22,6 +22,7 @@ pub struct StaticConstraints {
|
||||
pub mail_len: SizeConstraint,
|
||||
pub user_name_len: SizeConstraint,
|
||||
pub password_len: SizeConstraint,
|
||||
pub family_name_len: SizeConstraint,
|
||||
}
|
||||
|
||||
impl Default for StaticConstraints {
|
||||
@ -30,6 +31,7 @@ impl Default for StaticConstraints {
|
||||
mail_len: SizeConstraint::new(5, 255),
|
||||
user_name_len: SizeConstraint::new(3, 30),
|
||||
password_len: SizeConstraint::new(8, 255),
|
||||
family_name_len: SizeConstraint::new(3, 30),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -42,3 +44,6 @@ pub const ACCOUNT_DELETE_TOKEN_DURATION: Duration = Duration::from_secs(3600 * 1
|
||||
|
||||
/// OpenID state duration
|
||||
pub const OPEN_ID_STATE_DURATION: Duration = Duration::from_secs(3600);
|
||||
|
||||
/// Length of family invitation code
|
||||
pub const FAMILY_INVITATION_CODE_LEN: usize = 7;
|
||||
|
24
geneit_backend/src/controllers/families_controller.rs
Normal file
24
geneit_backend/src/controllers/families_controller.rs
Normal file
@ -0,0 +1,24 @@
|
||||
use crate::constants::StaticConstraints;
|
||||
use crate::controllers::HttpResult;
|
||||
use crate::services::families_service;
|
||||
use crate::services::login_token_service::LoginToken;
|
||||
use actix_web::{web, HttpResponse};
|
||||
|
||||
#[derive(Debug, serde::Deserialize)]
|
||||
pub struct CreateFamilyReq {
|
||||
name: String,
|
||||
}
|
||||
|
||||
/// Create a new family
|
||||
pub async fn create(req: web::Json<CreateFamilyReq>, token: LoginToken) -> HttpResult {
|
||||
if !StaticConstraints::default()
|
||||
.family_name_len
|
||||
.validate(&req.name)
|
||||
{
|
||||
return Ok(HttpResponse::BadRequest().body("Invalid family name!"));
|
||||
}
|
||||
|
||||
let family = families_service::create(&req.name, token.user_id).await?;
|
||||
|
||||
Ok(HttpResponse::Created().json(family))
|
||||
}
|
@ -5,8 +5,9 @@ use actix_web::HttpResponse;
|
||||
use std::fmt::{Debug, Display, Formatter};
|
||||
|
||||
pub mod auth_controller;
|
||||
pub mod families_controller;
|
||||
pub mod server_controller;
|
||||
pub mod user_controller;
|
||||
pub mod users_controller;
|
||||
|
||||
/// Custom error to ease controller writing
|
||||
#[derive(Debug)]
|
||||
|
@ -3,7 +3,9 @@ use actix_remote_ip::RemoteIPConfig;
|
||||
use actix_web::middleware::Logger;
|
||||
use actix_web::{web, App, HttpServer};
|
||||
use geneit_backend::app_config::AppConfig;
|
||||
use geneit_backend::controllers::{auth_controller, server_controller, user_controller};
|
||||
use geneit_backend::controllers::{
|
||||
auth_controller, families_controller, server_controller, users_controller,
|
||||
};
|
||||
|
||||
#[actix_web::main]
|
||||
async fn main() -> std::io::Result<()> {
|
||||
@ -63,26 +65,31 @@ async fn main() -> std::io::Result<()> {
|
||||
)
|
||||
.route("/auth/logout", web::get().to(auth_controller::logout))
|
||||
// User controller
|
||||
.route("/user/info", web::get().to(user_controller::auth_info))
|
||||
.route("/user/info", web::get().to(users_controller::auth_info))
|
||||
.route(
|
||||
"/user/update_profile",
|
||||
web::post().to(user_controller::update_profile),
|
||||
web::post().to(users_controller::update_profile),
|
||||
)
|
||||
.route(
|
||||
"/user/replace_password",
|
||||
web::post().to(user_controller::replace_password),
|
||||
web::post().to(users_controller::replace_password),
|
||||
)
|
||||
.route(
|
||||
"/user/request_delete",
|
||||
web::get().to(user_controller::request_delete_account),
|
||||
web::get().to(users_controller::request_delete_account),
|
||||
)
|
||||
.route(
|
||||
"/user/check_delete_token",
|
||||
web::post().to(user_controller::check_delete_token),
|
||||
web::post().to(users_controller::check_delete_token),
|
||||
)
|
||||
.route(
|
||||
"/user/delete_account",
|
||||
web::post().to(user_controller::delete_account),
|
||||
web::post().to(users_controller::delete_account),
|
||||
)
|
||||
// Families controller
|
||||
.route(
|
||||
"/family/create",
|
||||
web::post().to(families_controller::create),
|
||||
)
|
||||
})
|
||||
.bind(AppConfig::get().listen_address.as_str())?
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::schema::users;
|
||||
use crate::schema::{families, memberships, users};
|
||||
use diesel::prelude::*;
|
||||
|
||||
/// User ID holder
|
||||
@ -51,3 +51,46 @@ pub struct NewUser<'a> {
|
||||
pub email: &'a str,
|
||||
pub time_create: i64,
|
||||
}
|
||||
|
||||
/// Family ID holder
|
||||
#[derive(Debug, Clone, Copy, serde::Serialize, serde::Deserialize)]
|
||||
pub struct FamilyID(pub i32);
|
||||
|
||||
#[derive(Queryable, Debug, serde::Serialize)]
|
||||
pub struct Family {
|
||||
pub id: i32,
|
||||
pub time_create: i64,
|
||||
pub name: String,
|
||||
pub invitation_code: String,
|
||||
}
|
||||
|
||||
impl Family {
|
||||
pub fn id(&self) -> FamilyID {
|
||||
FamilyID(self.id)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Insertable)]
|
||||
#[diesel(table_name = families)]
|
||||
pub struct NewFamily<'a> {
|
||||
pub name: &'a str,
|
||||
pub invitation_code: String,
|
||||
pub time_create: i64,
|
||||
}
|
||||
|
||||
#[derive(Queryable, Debug, serde::Serialize)]
|
||||
pub struct Membership {
|
||||
user_id: i32,
|
||||
family_id: i32,
|
||||
time_create: i64,
|
||||
is_admin: bool,
|
||||
}
|
||||
|
||||
#[derive(Insertable)]
|
||||
#[diesel(table_name = memberships)]
|
||||
pub struct NewMembership {
|
||||
pub user_id: i32,
|
||||
pub family_id: i32,
|
||||
pub time_create: i64,
|
||||
pub is_admin: bool,
|
||||
}
|
||||
|
@ -38,8 +38,4 @@ diesel::table! {
|
||||
diesel::joinable!(memberships -> families (family_id));
|
||||
diesel::joinable!(memberships -> users (user_id));
|
||||
|
||||
diesel::allow_tables_to_appear_in_same_query!(
|
||||
families,
|
||||
memberships,
|
||||
users,
|
||||
);
|
||||
diesel::allow_tables_to_appear_in_same_query!(families, memberships, users,);
|
||||
|
46
geneit_backend/src/services/families_service.rs
Normal file
46
geneit_backend/src/services/families_service.rs
Normal file
@ -0,0 +1,46 @@
|
||||
use crate::connections::db_connection;
|
||||
use crate::constants::FAMILY_INVITATION_CODE_LEN;
|
||||
use crate::models::{Family, FamilyID, Membership, NewFamily, NewMembership, UserID};
|
||||
use crate::schema::{families, memberships};
|
||||
use crate::utils::string_utils::rand_str;
|
||||
use crate::utils::time_utils::time;
|
||||
use diesel::RunQueryDsl;
|
||||
|
||||
/// Create a new family, with an initial administrator
|
||||
pub async fn create(name: &str, user_id: UserID) -> anyhow::Result<Family> {
|
||||
let family = db_connection::execute(|conn| {
|
||||
let res: Family = diesel::insert_into(families::table)
|
||||
.values(&NewFamily {
|
||||
name: name.trim(),
|
||||
invitation_code: rand_str(FAMILY_INVITATION_CODE_LEN),
|
||||
time_create: time() as i64,
|
||||
})
|
||||
.get_result(conn)?;
|
||||
|
||||
Ok(res)
|
||||
})?;
|
||||
|
||||
add_member(family.id(), user_id, true).await?;
|
||||
|
||||
Ok(family)
|
||||
}
|
||||
|
||||
/// Add a member to a family
|
||||
pub async fn add_member(
|
||||
family_id: FamilyID,
|
||||
user_id: UserID,
|
||||
admin: bool,
|
||||
) -> anyhow::Result<Membership> {
|
||||
db_connection::execute(|conn| {
|
||||
let res = diesel::insert_into(memberships::table)
|
||||
.values(&NewMembership {
|
||||
user_id: user_id.0,
|
||||
family_id: family_id.0,
|
||||
time_create: time() as i64,
|
||||
is_admin: admin,
|
||||
})
|
||||
.get_result(conn)?;
|
||||
|
||||
Ok(res)
|
||||
})
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
//! # Backend services
|
||||
|
||||
pub mod families_service;
|
||||
pub mod login_token_service;
|
||||
pub mod mail_service;
|
||||
pub mod openid_service;
|
||||
|
Loading…
Reference in New Issue
Block a user