From 65bd2c808a9309d65c6939f68071727c2e284f73 Mon Sep 17 00:00:00 2001 From: brizzinck <87083857+brizzinck@users.noreply.github.com> Date: Wed, 8 Jan 2025 15:29:38 +0200 Subject: [PATCH 1/3] refactor: devide into files --- .../up.sql | 39 ++--- .../2024-12-12-214746_set_up_database/up.sql | 156 ++++++++++++------ .../2024-12-25-221730_rebase_db/down.sql | 1 - migrations/2024-12-25-221730_rebase_db/up.sql | 25 --- .../2025-01-05-162627_add_team/down.sql | 1 - migrations/2025-01-05-162627_add_team/up.sql | 49 ------ .../down.sql | 1 - .../up.sql | 2 - .../down.sql | 1 - .../up.sql | 5 - .../down.sql | 1 - .../up.sql | 13 -- src/api/hackathon_2024/team/delete.rs | 36 +--- src/api/hackathon_2024/team/get.rs | 40 ++--- src/api/hackathon_2024/team/post.rs | 21 ++- src/api/hackathon_2024/team/put.rs | 41 +---- src/api/hackathon_2024/university/delete.rs | 36 +--- src/api/hackathon_2024/university/get.rs | 43 ++--- src/api/hackathon_2024/university/post.rs | 25 +-- src/api/hackathon_2024/university/put.rs | 55 ++---- src/api/hackathon_2024/user/delete.rs | 34 +--- src/api/hackathon_2024/user/get.rs | 59 ++----- src/api/hackathon_2024/user/local.rs | 42 +---- src/api/hackathon_2024/user/post.rs | 39 ++--- src/api/hackathon_2024/user/put.rs | 51 ++---- src/data/hackathon_2024/api.rs | 9 - src/data/user.rs | 18 -- .../{database_diesel.rs => configurator.rs} | 4 +- src/diesel/mod.rs | 3 +- src/diesel/models/hackathon_2024/team.rs | 12 +- .../models/hackathon_2024/university.rs | 4 +- src/diesel/models/hackathon_2024/user.rs | 14 +- src/diesel/prelude.rs | 10 ++ src/diesel/schema.rs | 12 +- src/diesel/utils/hackathon_2024/fetch.rs | 30 ---- src/diesel/utils/hackathon_2024/insert.rs | 35 ---- src/diesel/utils/hackathon_2024/mod.rs | 5 +- .../utils/hackathon_2024/team/delete.rs | 15 ++ src/diesel/utils/hackathon_2024/team/fetch.rs | 14 ++ .../utils/hackathon_2024/team/insert.rs | 14 ++ src/diesel/utils/hackathon_2024/team/mod.rs | 4 + .../utils/hackathon_2024/team/update.rs | 23 +++ .../utils/hackathon_2024/university/delete.rs | 14 ++ .../utils/hackathon_2024/university/fetch.rs | 20 +++ .../utils/hackathon_2024/university/insert.rs | 20 +++ .../utils/hackathon_2024/university/mod.rs | 4 + .../utils/hackathon_2024/university/update.rs | 21 +++ .../utils/hackathon_2024/user/delete.rs | 12 ++ src/diesel/utils/hackathon_2024/user/fetch.rs | 16 ++ .../utils/hackathon_2024/user/insert.rs | 13 ++ src/diesel/utils/hackathon_2024/user/mod.rs | 4 + .../utils/hackathon_2024/user/update.rs | 28 ++++ src/dto/mod.rs | 2 + .../request}/hackathon_2024/mod.rs | 2 +- .../request}/hackathon_2024/team.rs | 3 +- src/dto/request/hackathon_2024/university.rs | 4 + src/dto/request/hackathon_2024/user.rs | 17 ++ src/{data => dto/request}/mod.rs | 2 - src/dto/request/user.rs | 9 + src/dto/response/hackathon_2024/mod.rs | 2 + src/dto/response/hackathon_2024/university.rs | 9 + src/dto/response/hackathon_2024/user.rs | 7 + src/dto/response/mod.rs | 2 + src/dto/response/user.rs | 11 ++ src/error/api_error.rs | 71 +++++--- src/main.rs | 5 +- src/{data => middleware}/admin_match.rs | 12 +- src/{data => middleware}/claims.rs | 0 src/middleware/mod.rs | 2 + src/models/hackathon_2024/mod.rs | 1 + src/{data => models}/hackathon_2024/user.rs | 22 ++- src/models/mod.rs | 1 + src/server.rs | 4 +- src/tests/main.rs | 4 + src/tests/mod.rs | 3 +- src/tests/test.rs | 7 - .../constants/{database.rs => diesel.rs} | 0 src/utils/constants/mod.rs | 3 +- src/utils/constants/routes.rs | 1 - src/utils/mod.rs | 1 + src/utils/prelude_api.rs | 4 + src/utils/security.rs | 3 + src/utils/validation/data/fields.rs | 35 ++-- .../validation/data/hackathon_2024/team.rs | 15 +- .../validation/data/hackathon_2024/user.rs | 21 ++- src/utils/validation/validation_string.rs | 7 + 86 files changed, 739 insertions(+), 747 deletions(-) delete mode 100644 migrations/2024-12-25-221730_rebase_db/down.sql delete mode 100644 migrations/2024-12-25-221730_rebase_db/up.sql delete mode 100644 migrations/2025-01-05-162627_add_team/down.sql delete mode 100644 migrations/2025-01-05-162627_add_team/up.sql delete mode 100644 migrations/2025-01-05-164355_user_team_id_not_null/down.sql delete mode 100644 migrations/2025-01-05-164355_user_team_id_not_null/up.sql delete mode 100644 migrations/2025-01-05-165244_add_email_to_hackathon_team_2024/down.sql delete mode 100644 migrations/2025-01-05-165244_add_email_to_hackathon_team_2024/up.sql delete mode 100644 migrations/2025-01-05-202614_add_team_trigger_count_member/down.sql delete mode 100644 migrations/2025-01-05-202614_add_team_trigger_count_member/up.sql delete mode 100644 src/data/hackathon_2024/api.rs delete mode 100644 src/data/user.rs rename src/diesel/{database_diesel.rs => configurator.rs} (96%) create mode 100644 src/diesel/prelude.rs delete mode 100644 src/diesel/utils/hackathon_2024/fetch.rs delete mode 100644 src/diesel/utils/hackathon_2024/insert.rs create mode 100644 src/diesel/utils/hackathon_2024/team/delete.rs create mode 100644 src/diesel/utils/hackathon_2024/team/fetch.rs create mode 100644 src/diesel/utils/hackathon_2024/team/insert.rs create mode 100644 src/diesel/utils/hackathon_2024/team/mod.rs create mode 100644 src/diesel/utils/hackathon_2024/team/update.rs create mode 100644 src/diesel/utils/hackathon_2024/university/delete.rs create mode 100644 src/diesel/utils/hackathon_2024/university/fetch.rs create mode 100644 src/diesel/utils/hackathon_2024/university/insert.rs create mode 100644 src/diesel/utils/hackathon_2024/university/mod.rs create mode 100644 src/diesel/utils/hackathon_2024/university/update.rs create mode 100644 src/diesel/utils/hackathon_2024/user/delete.rs create mode 100644 src/diesel/utils/hackathon_2024/user/fetch.rs create mode 100644 src/diesel/utils/hackathon_2024/user/insert.rs create mode 100644 src/diesel/utils/hackathon_2024/user/mod.rs create mode 100644 src/diesel/utils/hackathon_2024/user/update.rs create mode 100644 src/dto/mod.rs rename src/{data => dto/request}/hackathon_2024/mod.rs (58%) rename src/{data => dto/request}/hackathon_2024/team.rs (92%) create mode 100644 src/dto/request/hackathon_2024/university.rs create mode 100644 src/dto/request/hackathon_2024/user.rs rename src/{data => dto/request}/mod.rs (50%) create mode 100644 src/dto/request/user.rs create mode 100644 src/dto/response/hackathon_2024/mod.rs create mode 100644 src/dto/response/hackathon_2024/university.rs create mode 100644 src/dto/response/hackathon_2024/user.rs create mode 100644 src/dto/response/mod.rs create mode 100644 src/dto/response/user.rs rename src/{data => middleware}/admin_match.rs (77%) rename src/{data => middleware}/claims.rs (100%) create mode 100644 src/middleware/mod.rs create mode 100644 src/models/hackathon_2024/mod.rs rename src/{data => models}/hackathon_2024/user.rs (55%) create mode 100644 src/models/mod.rs create mode 100644 src/tests/main.rs delete mode 100644 src/tests/test.rs rename src/utils/constants/{database.rs => diesel.rs} (100%) delete mode 100644 src/utils/constants/routes.rs create mode 100644 src/utils/prelude_api.rs diff --git a/migrations/00000000000000_diesel_initial_setup/up.sql b/migrations/00000000000000_diesel_initial_setup/up.sql index d68895b..17b5933 100644 --- a/migrations/00000000000000_diesel_initial_setup/up.sql +++ b/migrations/00000000000000_diesel_initial_setup/up.sql @@ -1,36 +1,23 @@ --- This file was automatically created by Diesel to setup helper functions --- and other internal bookkeeping. This file is safe to edit, any future --- changes will be added to existing projects as new migrations. - - - - --- Sets up a trigger for the given table to automatically set a column called --- `updated_at` whenever the row is modified (unless `updated_at` was included --- in the modified columns) --- --- # Example --- --- ```sql --- CREATE TABLE users (id SERIAL PRIMARY KEY, updated_at TIMESTAMP NOT NULL DEFAULT NOW()); --- --- SELECT diesel_manage_updated_at('users'); --- ``` -CREATE OR REPLACE FUNCTION diesel_manage_updated_at(_tbl regclass) RETURNS VOID AS $$ +CREATE +OR REPLACE FUNCTION diesel_manage_updated_at(_tbl regclass) RETURNS VOID AS $$ BEGIN - EXECUTE format('CREATE TRIGGER set_updated_at BEFORE UPDATE ON %s +EXECUTE format('CREATE TRIGGER set_updated_at BEFORE UPDATE ON %s FOR EACH ROW EXECUTE PROCEDURE diesel_set_updated_at()', _tbl); END; -$$ LANGUAGE plpgsql; +$$ +LANGUAGE plpgsql; -CREATE OR REPLACE FUNCTION diesel_set_updated_at() RETURNS trigger AS $$ +CREATE +OR REPLACE FUNCTION diesel_set_updated_at() RETURNS trigger AS $$ BEGIN - IF ( + IF +( NEW IS DISTINCT FROM OLD AND NEW.updated_at IS NOT DISTINCT FROM OLD.updated_at ) THEN NEW.updated_at := current_timestamp; - END IF; - RETURN NEW; +END IF; +RETURN NEW; END; -$$ LANGUAGE plpgsql; +$$ +LANGUAGE plpgsql; diff --git a/migrations/2024-12-12-214746_set_up_database/up.sql b/migrations/2024-12-12-214746_set_up_database/up.sql index af53b1d..5e99107 100644 --- a/migrations/2024-12-12-214746_set_up_database/up.sql +++ b/migrations/2024-12-12-214746_set_up_database/up.sql @@ -1,92 +1,144 @@ -- Enum Definitions CREATE TYPE user_role AS ENUM ('Admin', 'User'); -CREATE TYPE hackathon_category AS ENUM ('education', 'military', 'web3_0', 'cybersecurity'); +CREATE TYPE hackathon_category_2024 AS ENUM ('education', 'military', 'web3_0', 'cybersecurity'); CREATE TYPE type_media AS ENUM ('video', 'photo'); -- Function for Updated Timestamp -CREATE OR REPLACE FUNCTION update_timestamp() +CREATE +OR REPLACE FUNCTION update_timestamp() RETURNS TRIGGER AS $$ BEGIN - NEW.updated_at = CURRENT_TIMESTAMP; + NEW.updated_at += CURRENT_TIMESTAMP; RETURN NEW; END; -$$ LANGUAGE plpgsql; +$$ +LANGUAGE plpgsql; --- Users Table -CREATE TABLE users ( - id SERIAL PRIMARY KEY, - first_name VARCHAR(50) NOT NULL, - last_name VARCHAR(50) NOT NULL, - password_hash VARCHAR(255) NOT NULL, - phone VARCHAR(20) NOT NULL UNIQUE, - email VARCHAR(255) NOT NULL UNIQUE, - role user_role NOT NUll, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP +-- University Table +CREATE TABLE hackathon_university_2024 +( + id SERIAL PRIMARY KEY, + name VARCHAR(255) NOT NULL UNIQUE, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -CREATE TRIGGER update_users_updated_at - BEFORE UPDATE ON users +CREATE TRIGGER update_hackathon_university_updated_at + BEFORE UPDATE + ON hackathon_university_2024 FOR EACH ROW EXECUTE FUNCTION update_timestamp(); --- Hackathon Table -CREATE TABLE hackathon ( - id SERIAL PRIMARY KEY, - user_id INT NOT NULL REFERENCES users(id) ON DELETE CASCADE, - category hackathon_category NOT NULL, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP +-- Hackathon Team Table +CREATE TABLE hackathon_team_2024 +( + id SERIAL PRIMARY KEY, + name VARCHAR(255) NOT NULL, + category hackathon_category_2024 NOT NULL, + password_registration VARCHAR(255) NOT NULL, + count_members INT NOT NULL DEFAULT 0, + nickname_tg VARCHAR(255) NOT NULL UNIQUE, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); + +CREATE TRIGGER update_hackathon_team_updated_at + BEFORE UPDATE + ON hackathon_team_2024 + FOR EACH ROW + EXECUTE FUNCTION update_timestamp(); + +-- Users Table +CREATE TABLE hackathon_user_2024 +( + id SERIAL PRIMARY KEY, + first_name VARCHAR(50) NOT NULL, + last_name VARCHAR(50) NOT NULL, + phone VARCHAR(20) NOT NULL UNIQUE, + nickname_tg VARCHAR(255) NOT NULL UNIQUE, + university_id INT, + team_id INT, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + CONSTRAINT fk_university FOREIGN KEY (university_id) REFERENCES hackathon_university_2024 (id) ON DELETE SET NULL, + CONSTRAINT fk_team FOREIGN KEY (team_id) REFERENCES hackathon_team_2024 (id) ON DELETE SET NULL ); -CREATE TRIGGER update_hackathon_updated_at - BEFORE UPDATE ON hackathon +CREATE TRIGGER update_hackathon_user_updated_at + BEFORE UPDATE + ON hackathon_user_2024 FOR EACH ROW EXECUTE FUNCTION update_timestamp(); +-- Trigger to Increment Team Member Count +CREATE +OR REPLACE FUNCTION increment_team_member_count() +RETURNS TRIGGER AS $$ +BEGIN +UPDATE hackathon_team_2024 +SET count_members = count_members + 1 +WHERE id = NEW.team_id; +RETURN NEW; +END; +$$ +LANGUAGE plpgsql; + +CREATE TRIGGER increment_team_member_trigger + AFTER INSERT + ON hackathon_user_2024 + FOR EACH ROW + EXECUTE FUNCTION increment_team_member_count(); + -- News Table -CREATE TABLE news ( - id SERIAL PRIMARY KEY, - description TEXT NOT NULL, - preview_id INT, - header VARCHAR(255) NOT NULL, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP +CREATE TABLE news +( + id SERIAL PRIMARY KEY, + description TEXT NOT NULL, + preview_id INT, + header VARCHAR(255) NOT NULL, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); CREATE TRIGGER update_news_updated_at - BEFORE UPDATE ON news + BEFORE UPDATE + ON news FOR EACH ROW EXECUTE FUNCTION update_timestamp(); -- News Media Table -CREATE TABLE news_media ( - id SERIAL PRIMARY KEY, - src_url TEXT NOT NULL, - news_id INT REFERENCES news(id) ON DELETE CASCADE, - type_media type_media NOT NULL, - position INT NOT NULL, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP +CREATE TABLE news_media +( + id SERIAL PRIMARY KEY, + src_url TEXT NOT NULL, + news_id INT REFERENCES news (id) ON DELETE CASCADE, + type_media type_media NOT NULL, + position INT NOT NULL, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); CREATE TRIGGER update_news_media_updated_at - BEFORE UPDATE ON news_media + BEFORE UPDATE + ON news_media FOR EACH ROW EXECUTE FUNCTION update_timestamp(); -- Announcement Banner Table -CREATE TABLE announcement_banner ( - id SERIAL PRIMARY KEY, - src_url TEXT NOT NULL, - type_media type_media NOT NULL, - description VARCHAR(255) NOT NULL, - showing BOOLEAN NOT NULL DEFAULT FALSE, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP +CREATE TABLE announcement_banner +( + id SERIAL PRIMARY KEY, + src_url TEXT NOT NULL, + type_media type_media NOT NULL, + description VARCHAR(255) NOT NULL, + showing BOOLEAN NOT NULL DEFAULT FALSE, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); CREATE TRIGGER update_announcement_banner_updated_at - BEFORE UPDATE ON announcement_banner + BEFORE UPDATE + ON announcement_banner FOR EACH ROW EXECUTE FUNCTION update_timestamp(); diff --git a/migrations/2024-12-25-221730_rebase_db/down.sql b/migrations/2024-12-25-221730_rebase_db/down.sql deleted file mode 100644 index d9a93fe..0000000 --- a/migrations/2024-12-25-221730_rebase_db/down.sql +++ /dev/null @@ -1 +0,0 @@ --- This file should undo anything in `up.sql` diff --git a/migrations/2024-12-25-221730_rebase_db/up.sql b/migrations/2024-12-25-221730_rebase_db/up.sql deleted file mode 100644 index 7e57bf6..0000000 --- a/migrations/2024-12-25-221730_rebase_db/up.sql +++ /dev/null @@ -1,25 +0,0 @@ -ALTER TABLE users RENAME TO hackathon_user_2024; -ALTER TABLE hackathon_user_2024 ADD COLUMN category hackathon_category NOT NULL; -DROP TABLE hackathon; -ALTER TYPE hackathon_category RENAME TO hackathon_category_2024; -CREATE TABLE hackathon_university_2024 ( - id SERIAL PRIMARY KEY, - name VARCHAR(255) NOT NULL UNIQUE, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP -); -CREATE TRIGGER update_hackathon_university_2024_updated_at - BEFORE UPDATE ON hackathon_university_2024 - FOR EACH ROW - EXECUTE FUNCTION update_timestamp(); - -ALTER TABLE hackathon_user_2024 - ADD COLUMN university INT; - -ALTER TABLE hackathon_user_2024 - ADD CONSTRAINT fk_university - FOREIGN KEY (university) REFERENCES hackathon_university_2024(id) - ON DELETE SET NULL; - -ALTER TABLE hackathon_user_2024 DROP COLUMN password_hash; -ALTER TABLE hackathon_user_2024 DROP COLUMN role; diff --git a/migrations/2025-01-05-162627_add_team/down.sql b/migrations/2025-01-05-162627_add_team/down.sql deleted file mode 100644 index d9a93fe..0000000 --- a/migrations/2025-01-05-162627_add_team/down.sql +++ /dev/null @@ -1 +0,0 @@ --- This file should undo anything in `up.sql` diff --git a/migrations/2025-01-05-162627_add_team/up.sql b/migrations/2025-01-05-162627_add_team/up.sql deleted file mode 100644 index f8055dc..0000000 --- a/migrations/2025-01-05-162627_add_team/up.sql +++ /dev/null @@ -1,49 +0,0 @@ --- Create the new table for hackathon teams -CREATE TABLE hackathon_team_2024 -( - id SERIAL PRIMARY KEY, - name VARCHAR(255) NOT NULL, - category hackathon_category_2024 NOT NULL, - password_registration VARCHAR(255) NOT NULL, - count_members INT NOT NULL DEFAULT 0, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP -); - --- Drop the old category column from hackathon_user_2024 -ALTER TABLE hackathon_user_2024 DROP COLUMN category; - --- Add the new column in hackathon_user_2024 for team reference -ALTER TABLE hackathon_user_2024 - ADD COLUMN team_id INT; - --- Add foreign key constraint for the new team_id column -ALTER TABLE hackathon_user_2024 - ADD CONSTRAINT fk_team - FOREIGN KEY (team_id) REFERENCES hackathon_team_2024 (id) - ON DELETE SET NULL; - --- Trigger for updated timestamp in hackathon_team_2024 -CREATE TRIGGER update_hackathon_team_2024_updated_at - BEFORE UPDATE - ON hackathon_team_2024 - FOR EACH ROW - EXECUTE FUNCTION update_timestamp(); - --- Adjust related triggers and constraints if necessary --- For example, ensure the updated_at trigger works for both old and new structures -CREATE -OR REPLACE FUNCTION update_timestamp() -RETURNS TRIGGER AS $$ -BEGIN - NEW.updated_at -= CURRENT_TIMESTAMP; -RETURN NEW; -END; -$$ -LANGUAGE plpgsql; - --- Ensure all foreign key constraints and relationships are consistent -ALTER TABLE hackathon_user_2024 -DROP -CONSTRAINT IF EXISTS fk_category; diff --git a/migrations/2025-01-05-164355_user_team_id_not_null/down.sql b/migrations/2025-01-05-164355_user_team_id_not_null/down.sql deleted file mode 100644 index d9a93fe..0000000 --- a/migrations/2025-01-05-164355_user_team_id_not_null/down.sql +++ /dev/null @@ -1 +0,0 @@ --- This file should undo anything in `up.sql` diff --git a/migrations/2025-01-05-164355_user_team_id_not_null/up.sql b/migrations/2025-01-05-164355_user_team_id_not_null/up.sql deleted file mode 100644 index 54eda37..0000000 --- a/migrations/2025-01-05-164355_user_team_id_not_null/up.sql +++ /dev/null @@ -1,2 +0,0 @@ -ALTER TABLE hackathon_user_2024 - ALTER COLUMN team_id SET NOT NULL; \ No newline at end of file diff --git a/migrations/2025-01-05-165244_add_email_to_hackathon_team_2024/down.sql b/migrations/2025-01-05-165244_add_email_to_hackathon_team_2024/down.sql deleted file mode 100644 index d9a93fe..0000000 --- a/migrations/2025-01-05-165244_add_email_to_hackathon_team_2024/down.sql +++ /dev/null @@ -1 +0,0 @@ --- This file should undo anything in `up.sql` diff --git a/migrations/2025-01-05-165244_add_email_to_hackathon_team_2024/up.sql b/migrations/2025-01-05-165244_add_email_to_hackathon_team_2024/up.sql deleted file mode 100644 index b362830..0000000 --- a/migrations/2025-01-05-165244_add_email_to_hackathon_team_2024/up.sql +++ /dev/null @@ -1,5 +0,0 @@ -ALTER TABLE hackathon_team_2024 - ADD COLUMN email VARCHAR(255) NOT NULL; - -ALTER TABLE hackathon_team_2024 - ADD CONSTRAINT unique_email UNIQUE (email); diff --git a/migrations/2025-01-05-202614_add_team_trigger_count_member/down.sql b/migrations/2025-01-05-202614_add_team_trigger_count_member/down.sql deleted file mode 100644 index d9a93fe..0000000 --- a/migrations/2025-01-05-202614_add_team_trigger_count_member/down.sql +++ /dev/null @@ -1 +0,0 @@ --- This file should undo anything in `up.sql` diff --git a/migrations/2025-01-05-202614_add_team_trigger_count_member/up.sql b/migrations/2025-01-05-202614_add_team_trigger_count_member/up.sql deleted file mode 100644 index baab4bd..0000000 --- a/migrations/2025-01-05-202614_add_team_trigger_count_member/up.sql +++ /dev/null @@ -1,13 +0,0 @@ -CREATE OR REPLACE FUNCTION increment_team_member_count() RETURNS TRIGGER AS $$ -BEGIN -UPDATE hackathon_team_2024 -SET count_members = count_members + 1 -WHERE id = NEW.team_id; -RETURN NEW; -END; -$$ LANGUAGE plpgsql; - -CREATE TRIGGER increment_team_member_trigger - AFTER INSERT ON hackathon_user_2024 - FOR EACH ROW - EXECUTE FUNCTION increment_team_member_count(); diff --git a/src/api/hackathon_2024/team/delete.rs b/src/api/hackathon_2024/team/delete.rs index 84b8d6c..14bc33a 100644 --- a/src/api/hackathon_2024/team/delete.rs +++ b/src/api/hackathon_2024/team/delete.rs @@ -1,31 +1,11 @@ -use crate::data::admin_match::AdminMatch; -use crate::diesel::database_diesel::{get_connection, DbPool}; -use crate::diesel::schema::hackathon_team_2024::dsl::*; -use crate::diesel::schema::hackathon_team_2024::id; -use crate::error::api_error::ApiError; -use diesel::ExpressionMethods; -use diesel::RunQueryDsl; -use rocket::{delete, State}; +use crate::diesel::prelude::*; +use crate::middleware::admin_match::AdminMatch; +use rocket::delete; -#[delete("/hackathon_2024/team/by_id/")] -pub async fn by_id( - db_pool: &State, - team_id: i32, - admin_match: AdminMatch, -) -> Result { +#[delete("/hackathon_2024/team/by_id/")] +pub async fn by_id(db_pool: &DbState, id: i32, admin_match: AdminMatch) -> Result<(), ApiError> { admin_match.check_admin()?; - - let mut db_connection = get_connection(db_pool)?; - - diesel::delete(hackathon_team_2024) - .filter(id.eq(team_id)) - .execute(&mut db_connection) - .map_err(|err| { - log::error!("Error deleting hackathon_university_2024: {:?}", err); - ApiError::DatabaseErrorResult(err) - })?; - - Ok(format!( - "Successfully deleted team from hackathon_team_2024 with id {team_id}" - )) + let id = crate::diesel::utils::hackathon_2024::team::delete::by_id(db_pool, id)?; + info!("Successfully deleted team from hackathon_team_2024 with id {id}"); + Ok(()) } diff --git a/src/api/hackathon_2024/team/get.rs b/src/api/hackathon_2024/team/get.rs index 25c4015..e10e5aa 100644 --- a/src/api/hackathon_2024/team/get.rs +++ b/src/api/hackathon_2024/team/get.rs @@ -1,36 +1,20 @@ -use crate::diesel::database_diesel::{get_connection, DbPool}; use crate::diesel::models::hackathon_2024::team::HackathonTeam2024Queryable; -use crate::diesel::schema::hackathon_team_2024::dsl::hackathon_team_2024; -use crate::diesel::schema::hackathon_team_2024::id; -use crate::error::api_error::ApiError; -use diesel::prelude::*; -use rocket::serde::json::Json; -use rocket::{get, State}; +use crate::utils::prelude_api::*; +use rocket::get; #[get("/hackathon_2024/team/all")] -pub async fn all( - db_pool: &State, -) -> Result>, ApiError> { - let mut db_connection = get_connection(db_pool)?; - - let result = hackathon_team_2024 - .load::(&mut db_connection) - .map_err(ApiError::DatabaseErrorResult)?; - - Ok(Json(result)) +pub async fn all(db_pool: &DbState) -> Result>, ApiError> { + Ok(Json( + crate::diesel::utils::hackathon_2024::team::fetch::all(db_pool)?, + )) } -#[get("/hackathon_2024/team/by_id/")] +#[get("/hackathon_2024/team/by_id/")] pub async fn by_id( - db_pool: &State, - team_id: i32, + db_pool: &DbState, + id: i32, ) -> Result, ApiError> { - let mut db_connection = get_connection(db_pool)?; - - let result = hackathon_team_2024 - .filter(id.eq(team_id)) - .first::(&mut db_connection) - .map_err(ApiError::DatabaseErrorResult)?; - - Ok(Json(result)) + Ok(Json( + crate::diesel::utils::hackathon_2024::team::fetch::by_id(db_pool, id)?, + )) } diff --git a/src/api/hackathon_2024/team/post.rs b/src/api/hackathon_2024/team/post.rs index 30ce476..94b7b9e 100644 --- a/src/api/hackathon_2024/team/post.rs +++ b/src/api/hackathon_2024/team/post.rs @@ -1,22 +1,21 @@ -use crate::diesel::database_diesel::DbPool; use crate::diesel::models::hackathon_2024::team::HackathonTeam2024Insertable; -use crate::error::api_error::ApiError; +use crate::utils::prelude_api::*; use crate::utils::security::hashing_data; -use rocket::serde::json::Json; -use rocket::{post, State}; +use rocket::post; #[post("/hackathon_2024/team/create", data = "")] pub async fn create( - db_pool: &State, - data: Json>, -) -> Result { + db_pool: &DbState, + data: Json, +) -> Result<(), ApiError> { let mut team = data.into_inner(); crate::utils::validation::data::hackathon_2024::team::field(&team)?; + team.password_registration = hashing_data(team.password_registration)?; - let hashed_password = hashing_data(team.password_registration)?; - team.password_registration = hashed_password.as_str(); + let id = crate::diesel::utils::hackathon_2024::team::insert::new(db_pool, team)?; - let id = crate::diesel::utils::hackathon_2024::insert::team(db_pool, team)?; - Ok(format!("Succeed insert new hackathon 2024 team with id - {}", id).to_owned()) + info!("Succeed insert new hackathon 2024 team with id - {id}"); + + Ok(()) } diff --git a/src/api/hackathon_2024/team/put.rs b/src/api/hackathon_2024/team/put.rs index d245944..e1c5b52 100644 --- a/src/api/hackathon_2024/team/put.rs +++ b/src/api/hackathon_2024/team/put.rs @@ -1,40 +1,17 @@ -use crate::data::admin_match::AdminMatch; -use crate::data::hackathon_2024::team::TeamUpdateData; -use crate::diesel::database_diesel::{get_connection, DbPool}; -use crate::diesel::schema::hackathon_team_2024::dsl::hackathon_team_2024; -use crate::diesel::schema::hackathon_team_2024::{category, email, id, name, updated_at}; -use crate::error::api_error::ApiError; -use diesel::ExpressionMethods; -use diesel::RunQueryDsl; -use rocket::serde::json::Json; -use rocket::{put, State}; +use crate::dto::request::hackathon_2024::team::TeamUpdateData; +use crate::middleware::admin_match::AdminMatch; +use crate::utils::prelude_api::*; +use rocket::put; #[put("/hackathon_2024/team/by_id", data = "")] pub async fn by_id( - db_pool: &State, + db_pool: &DbState, data: Json, admin_match: AdminMatch, -) -> Result { +) -> Result<(), ApiError> { admin_match.check_admin()?; let data = data.into_inner(); - - let mut db_connection = get_connection(db_pool)?; - - diesel::update(hackathon_team_2024) - .filter(id.eq(data.id)) - .set(( - name.eq(data.name.clone()), - category.eq(data.category), - email.eq(data.email.clone()), - updated_at.eq(chrono::Utc::now().naive_utc()), - )) - .execute(&mut db_connection) - .map_err(|err| { - log::error!("Error updating hackathon_university_2024, bellow error"); - ApiError::DatabaseErrorResult(err) - })?; - - Ok(format!( - "Successfully updating team from hackathon_team_2024 with data: {data:?}" - )) + let _ = crate::diesel::utils::hackathon_2024::team::update::by_data(db_pool, &data)?; + info!("Successfully updating team from hackathon_team_2024 with data: {data:?}"); + Ok(()) } diff --git a/src/api/hackathon_2024/university/delete.rs b/src/api/hackathon_2024/university/delete.rs index 1ca6aac..cd0bde3 100644 --- a/src/api/hackathon_2024/university/delete.rs +++ b/src/api/hackathon_2024/university/delete.rs @@ -1,31 +1,11 @@ -use crate::data::admin_match::AdminMatch; -use crate::diesel::database_diesel::{get_connection, DbPool}; -use crate::diesel::schema::hackathon_university_2024::dsl::hackathon_university_2024; -use crate::diesel::schema::hackathon_university_2024::id; -use crate::error::api_error::ApiError; -use diesel::ExpressionMethods; -use diesel::QueryDsl; -use diesel::RunQueryDsl; -use rocket::{delete, State}; +use crate::middleware::admin_match::AdminMatch; +use crate::utils::prelude_api::*; +use rocket::delete; -#[delete("/hackathon_2024/university/by_id/")] -pub async fn by_id( - db_pool: &State, - university_id: i32, - admin_match: AdminMatch, -) -> Result { +#[delete("/hackathon_2024/university/by_id/")] +pub async fn by_id(db_pool: &DbState, id: i32, admin_match: AdminMatch) -> Result<(), ApiError> { admin_match.check_admin()?; - - let mut db_connection = get_connection(db_pool)?; - - diesel::delete(hackathon_university_2024.filter(id.eq(university_id))) - .execute(&mut db_connection) - .map_err(|err| { - log::error!("Error deleting hackathon_university_2024, bellow error"); - ApiError::DatabaseErrorResult(err) - })?; - - Ok(format!( - "Successfully deleted university from hackathon_university_2024 with id {university_id}" - )) + let id = crate::diesel::utils::hackathon_2024::university::delete::by_id(db_pool, id)?; + info!("Successfully deleted university from hackathon_university_2024 with id {id}"); + Ok(()) } diff --git a/src/api/hackathon_2024/university/get.rs b/src/api/hackathon_2024/university/get.rs index e9845ba..817785a 100644 --- a/src/api/hackathon_2024/university/get.rs +++ b/src/api/hackathon_2024/university/get.rs @@ -1,36 +1,17 @@ -use crate::diesel::database_diesel::{get_connection, DbPool}; -use crate::diesel::models::hackathon_2024::university::HackathonUniversity2024Queryable; -use crate::error::api_error::ApiError; -use diesel::prelude::*; -use rocket::serde::json::Json; -use rocket::{get, State}; - -use crate::diesel::schema::hackathon_university_2024::dsl::*; +use crate::dto::response::hackathon_2024::university::{University, VecUniversity}; +use crate::utils::prelude_api::*; +use rocket::get; #[get("/hackathon_2024/university/all")] -pub async fn all( - db_pool: &State, -) -> Result>, ApiError> { - let mut db_connection = get_connection(db_pool).map_err(|_| ApiError::InternalServerError)?; - - let result = hackathon_university_2024 - .load::(&mut db_connection) - .map_err(|_| ApiError::InternalServerError)?; - - Ok(Json(result)) +pub async fn all(db_pool: &DbState) -> Result, ApiError> { + Ok(Json(VecUniversity( + crate::diesel::utils::hackathon_2024::university::fetch::all(db_pool)?, + ))) } -#[get("/hackathon_2024/university/by_id/")] -pub async fn by_id( - db_pool: &State, - university_id: i32, -) -> Result, ApiError> { - let mut db_connection = get_connection(db_pool).map_err(|_| ApiError::InternalServerError)?; - - let result = hackathon_university_2024 - .filter(id.eq(university_id)) - .first::(&mut db_connection) - .map_err(|_| ApiError::NotFound)?; - - Ok(Json(result)) +#[get("/hackathon_2024/university/by_id/")] +pub async fn by_id(db_pool: &DbState, id: i32) -> Result, ApiError> { + Ok(Json(University( + crate::diesel::utils::hackathon_2024::university::fetch::by_id(db_pool, id)?, + ))) } diff --git a/src/api/hackathon_2024/university/post.rs b/src/api/hackathon_2024/university/post.rs index a089cd1..17c2514 100644 --- a/src/api/hackathon_2024/university/post.rs +++ b/src/api/hackathon_2024/university/post.rs @@ -1,18 +1,19 @@ -use crate::data::admin_match::AdminMatch; -use crate::diesel::database_diesel::DbPool; -use crate::diesel::models::hackathon_2024::university::HackathonUniversity2024Insertable as University; -use crate::error::api_error::ApiError; -use rocket::serde::json::Json; -use rocket::{post, State}; +use crate::dto::request::hackathon_2024::university::University; +use crate::middleware::admin_match::AdminMatch; +use crate::utils::prelude_api::*; +use rocket::post; #[post("/hackathon_2024/university/create", data = "")] pub async fn create( - db_pool: &State, - data: Json>, + db_pool: &DbState, + data: Json, admin_match: AdminMatch, -) -> Result { +) -> Result<(), ApiError> { admin_match.check_admin()?; - let data = data.into_inner(); - let id = crate::diesel::utils::hackathon_2024::insert::university(db_pool, data)?; - Ok(format!("Succeed insert new university with id - {}", id).to_owned()) + let id = crate::diesel::utils::hackathon_2024::university::insert::new( + db_pool, + data.into_inner().0, + )?; + info!("Succeed insert new university with id - {id}"); + Ok(()) } diff --git a/src/api/hackathon_2024/university/put.rs b/src/api/hackathon_2024/university/put.rs index 3289fe1..6a6e0fe 100644 --- a/src/api/hackathon_2024/university/put.rs +++ b/src/api/hackathon_2024/university/put.rs @@ -1,44 +1,21 @@ -use crate::data::admin_match::AdminMatch; -use crate::diesel::database_diesel::{get_connection, DbPool}; -use crate::diesel::models::hackathon_2024::university::HackathonUniversity2024Insertable; -use crate::diesel::schema::hackathon_university_2024::dsl::*; -use crate::error::api_error::ApiError; -use diesel::prelude::*; -use rocket::serde::json::Json; -use rocket::{put, State}; +use crate::dto::request::hackathon_2024::university::University; +use crate::middleware::admin_match::AdminMatch; +use crate::utils::prelude_api::*; +use rocket::put; -#[put( - "/hackathon_2024/university/by_id/", - data = "" -)] +#[put("/hackathon_2024/university/by_id/", data = "")] pub async fn by_id( - db_pool: &State, - university_id: i32, + db_pool: &DbState, + id: i32, admin_match: AdminMatch, - university_data: Json>, -) -> Result { + data: Json, +) -> Result<(), ApiError> { admin_match.check_admin()?; - let university = university_data.into_inner(); - let mut db_connection = get_connection(db_pool).map_err(|_| ApiError::InternalServerError)?; - - let rows_affected = diesel::update(hackathon_university_2024.filter(id.eq(university_id))) - .set(( - name.eq(university.name), - updated_at.eq(chrono::Utc::now().naive_utc()), - )) - .execute(&mut db_connection) - .map_err(|err| { - log::error!("Error updating hackathon_university_2024: {:?}", err); - ApiError::DatabaseErrorResult(err) - })?; - - if rows_affected == 0 { - return Err(ApiError::NotFound); - } - - Ok(format!( - "Successfully updated hackathon_university_2024 with id: {}", - university_id - ) - .to_owned()) + let id = crate::diesel::utils::hackathon_2024::university::update::by_id( + db_pool, + id, + data.into_inner().0, + )?; + info!("Successfully updated hackathon_university_2024 with id: {id}"); + Ok(()) } diff --git a/src/api/hackathon_2024/user/delete.rs b/src/api/hackathon_2024/user/delete.rs index ee074d9..de1c3c9 100644 --- a/src/api/hackathon_2024/user/delete.rs +++ b/src/api/hackathon_2024/user/delete.rs @@ -1,11 +1,7 @@ -use crate::data::admin_match::AdminMatch; -use crate::diesel::database_diesel::{get_connection, DbPool}; -use crate::diesel::schema::hackathon_user_2024::dsl::hackathon_user_2024; -use crate::diesel::schema::hackathon_user_2024::id; +use crate::diesel::configurator::DbPool; use crate::error::api_error::ApiError; -use diesel::ExpressionMethods; -use diesel::QueryDsl; -use diesel::RunQueryDsl; +use crate::middleware::admin_match::AdminMatch; +use log::info; use rocket::{delete, State}; #[delete("/hackathon_2024/user/by_id/")] @@ -13,25 +9,9 @@ pub async fn by_id( db_pool: &State, user_id: i32, admin_match: AdminMatch, -) -> Result { +) -> Result<(), ApiError> { admin_match.check_admin()?; - - let mut db_connection = get_connection(db_pool)?; - - let rows_deleted = diesel::delete(hackathon_user_2024.filter(id.eq(user_id))) - .execute(&mut db_connection) - .map_err(|err| { - log::error!("Error deleting hackathon_user_2024: {:?}", err); - ApiError::DatabaseErrorResult(err) - })?; - - if rows_deleted == 0 { - return Err(ApiError::NotFound); - } - - Ok(format!( - "Successfully deleted hackathon_user_2024 from hackathon 2024 with id {}", - user_id - ) - .to_owned()) + let user_id = crate::diesel::utils::hackathon_2024::user::delete::by_id(db_pool, user_id)?; + info!("Successfully deleted hackathon_user_2024 from hackathon 2024 with id {user_id}"); + Ok(()) } diff --git a/src/api/hackathon_2024/user/get.rs b/src/api/hackathon_2024/user/get.rs index 970926a..5387e68 100644 --- a/src/api/hackathon_2024/user/get.rs +++ b/src/api/hackathon_2024/user/get.rs @@ -1,54 +1,29 @@ -use crate::api::hackathon_2024::user::local::create_user; -use crate::data::admin_match::AdminMatch; -use crate::data::claims::Claims; -use crate::diesel::database_diesel::{get_connection, DbPool}; -use crate::diesel::models::hackathon_2024::user::HackathonUser2024Queryable; -use crate::diesel::schema::hackathon_user_2024::dsl::hackathon_user_2024; -use crate::diesel::schema::hackathon_user_2024::id; -use crate::error::api_error::ApiError; +use crate::api::hackathon_2024::user::local::create_user_by_jwt; +use crate::dto::response::hackathon_2024::user::User; +use crate::dto::response::hackathon_2024::user::VecUser; +use crate::middleware::admin_match::AdminMatch; +use crate::middleware::claims::Claims; +use crate::utils::prelude_api::*; use crate::utils::security::decoded_data; -use diesel::{ExpressionMethods, QueryDsl, RunQueryDsl}; -use rocket::serde::json::Json; -use rocket::{get, State}; +use rocket::get; #[get("/hackathon_2024/user/confirm_new_user?")] -pub async fn confirm_new_user( - db_pool: &State, - jwt_token: String, -) -> Result { - let decoded = decoded_data(&jwt_token)?; - create_user(db_pool, decoded.claims) +pub async fn confirm_new_user(db_pool: &DbState, jwt_token: String) -> Result<(), ApiError> { + create_user_by_jwt(db_pool, decoded_data(&jwt_token)?.claims) } #[allow(dead_code)] #[get("/hackathon_2024/user/authorization_user")] -pub async fn authorization_user( - db_pool: &State, - claims: Claims, -) -> Result, ApiError> { - let mut connection = get_connection(db_pool)?; - let user: Result = hackathon_user_2024 - .filter(id.eq(claims.sub)) - .first::(&mut connection); - match user { - Ok(user) => Ok(Json(user)), - Err(diesel::result::Error::NotFound) => { - Err(ApiError::Unauthorized("Token or mismatched".to_string())) - } - Err(e) => Err(ApiError::DatabaseErrorResult(e)), - } +pub async fn authorization_user(db_pool: &DbState, claims: Claims) -> Result, ApiError> { + Ok(Json(User( + crate::diesel::utils::hackathon_2024::user::fetch::by_id(db_pool, claims.sub)?, + ))) } #[get("/hackathon_2024/user/all")] -pub async fn all( - db_pool: &State, - admin_match: AdminMatch, -) -> Result>, ApiError> { +pub async fn all(db_pool: &DbState, admin_match: AdminMatch) -> Result, ApiError> { admin_match.check_admin()?; - let mut db_connection = get_connection(db_pool)?; - let results = hackathon_user_2024 - .load::(&mut db_connection) - .map_err(ApiError::DatabaseErrorResult)?; - - Ok(Json(results)) + Ok(Json(VecUser( + crate::diesel::utils::hackathon_2024::user::fetch::all(db_pool)?, + ))) } diff --git a/src/api/hackathon_2024/user/local.rs b/src/api/hackathon_2024/user/local.rs index 9fdd16d..abd6995 100644 --- a/src/api/hackathon_2024/user/local.rs +++ b/src/api/hackathon_2024/user/local.rs @@ -1,38 +1,14 @@ -use crate::data::hackathon_2024::user::UserJwt; -use crate::diesel::database_diesel::{get_connection, DbPool}; -use crate::diesel::models::hackathon_2024::user::HackathonUser2024Insertable; -use crate::error::api_error::ApiError; +use crate::models::hackathon_2024::user::UserJwt; +use crate::utils::prelude_api::*; use crate::utils::validation::data; -use diesel::RunQueryDsl; -use rocket::{info, State}; -pub fn create_user(db_pool: &State, new_user: UserJwt) -> Result { - let mut db_connection = get_connection(db_pool)?; - let new_user = HackathonUser2024Insertable { - first_name: new_user.first_name, - last_name: new_user.last_name, - email: new_user.email, - phone: new_user.phone, - team_id: new_user.team_id, - university: new_user.university, - }; - data::hackathon_2024::user::field(&new_user)?; +pub fn create_user_by_jwt(db_pool: &DbState, new_user: UserJwt) -> Result<(), ApiError> { + let data = new_user.into(); + data::hackathon_2024::user::field(&data)?; - let user_id = diesel::insert_into(crate::diesel::schema::hackathon_user_2024::table) - .values(new_user) - .returning(crate::diesel::schema::hackathon_user_2024::id) - .get_result::(&mut db_connection) - .map_err(|err| { - log::error!("Error inserting hackathon_user_2024: {:?}", err); - ApiError::DatabaseErrorResult(err) - })?; + let user_id = crate::diesel::utils::hackathon_2024::user::insert::new(db_pool, data)?; - info!( - "Successfully inserted a new hackathon_user_2024 with ID: {}", - user_id - ); - Ok(format!( - "Hackathon_user_2024 created successfully with ID: {}", - user_id - )) + info!("Successfully inserted a new hackathon_user_2024 with ID: {user_id}"); + + Ok(()) } diff --git a/src/api/hackathon_2024/user/post.rs b/src/api/hackathon_2024/user/post.rs index 2de3972..f4ed915 100644 --- a/src/api/hackathon_2024/user/post.rs +++ b/src/api/hackathon_2024/user/post.rs @@ -1,18 +1,16 @@ -use crate::data::hackathon_2024::api::RegistrationData; -use crate::data::hackathon_2024::user::UserJwt; -use crate::diesel::database_diesel::DbPool; -use crate::error::api_error::ApiError; +use crate::dto::request::hackathon_2024::user::RegistrationData; +use crate::models::hackathon_2024::user::UserJwt; use crate::utils::actions; +use crate::utils::prelude_api::*; use crate::utils::security::{encoded_data, verify_password}; use crate::utils::validation; -use rocket::serde::json::Json; -use rocket::{post, State}; +use rocket::post; #[post("/hackathon_2024/user/try_registration", data = "")] pub async fn try_registration( - db_pool: &State, + db_pool: &DbState, registration_data: Json, -) -> Result { +) -> Result<(), ApiError> { let registration_data = registration_data.into_inner(); let RegistrationData { @@ -24,33 +22,36 @@ pub async fn try_registration( validation::data::hackathon_2024::team::check_team_password(team_data.password.as_str())?; validation::data::hackathon_2024::user::field(&user_data)?; - let team = crate::diesel::utils::hackathon_2024::fetch::team(db_pool, team_data.id)?; + let team = crate::diesel::utils::hackathon_2024::team::fetch::by_id(db_pool, team_data.id)?; verify_password(team_data.password, team.password_registration.as_str())?; - let _ = crate::diesel::utils::hackathon_2024::fetch::university(db_pool, user_data.university)?; + let _ = crate::diesel::utils::hackathon_2024::university::fetch::by_id( + db_pool, + user_data.university_id, + )?; let jwt_user = UserJwt::from(&user_data, 5); let token = encoded_data(&jwt_user)?; actions::send_letter::send_letter( - "letter".to_owned(), + "HACKATHON".to_owned(), format!( " -

Здравствуйте!

-

Чтобы подтвердить участие в хакатоне, пожалуйста, перейдите по ссылке:

- Подтвердить участие +

Hello!

+ Accept ", token ) .to_string(), - user_data.email.to_owned(), + user_data.nickname_tg.to_owned(), )?; - Ok(format!( - "verify email sent to {}, jwt token - {}", - user_data.email, token - )) + info!( + "verify email sent to {}, jwt token - {token}", + user_data.nickname_tg + ); + Ok(()) } diff --git a/src/api/hackathon_2024/user/put.rs b/src/api/hackathon_2024/user/put.rs index 3be07a3..9a3ff78 100644 --- a/src/api/hackathon_2024/user/put.rs +++ b/src/api/hackathon_2024/user/put.rs @@ -1,48 +1,19 @@ -use crate::data::admin_match::AdminMatch; -use crate::diesel::database_diesel::{get_connection, DbPool}; -use crate::diesel::models::hackathon_2024::user::HackathonUser2024Insertable; -use crate::diesel::schema::hackathon_user_2024::dsl::*; -use crate::error::api_error::ApiError; -use diesel::prelude::*; -use rocket::serde::json::Json; -use rocket::{put, State}; - -#[put("/hackathon_2024/user/by_id/", data = "")] +use crate::dto::request::hackathon_2024::user::User; +use crate::middleware::admin_match::AdminMatch; +use crate::utils::prelude_api::*; +use rocket::put; +#[put("/hackathon_2024/user/by_id/", data = "")] pub async fn by_id( - db_pool: &State, - user_data: Json, + db_pool: &DbState, + data: Json, user_id: i32, admin_match: AdminMatch, ) -> Result { admin_match.check_admin()?; - - let new_user = user_data.into_inner(); - - let mut db_connection = get_connection(db_pool)?; - - let rows_affected = diesel::update(hackathon_user_2024.filter(id.eq(user_id))) - .set(( - first_name.eq(new_user.first_name), - last_name.eq(new_user.last_name), - email.eq(&new_user.email), - phone.eq(new_user.phone), - university.eq(new_user.university), - team_id.eq(new_user.team_id), - updated_at.eq(chrono::Utc::now().naive_utc()), - )) - .execute(&mut db_connection) - .map_err(|err| { - log::error!("Error updating hackathon_user_2024, bellow error"); - ApiError::DatabaseErrorResult(err) - })?; - - if rows_affected == 0 { - return Err(ApiError::NotFound); - } - + let data = data.into_inner(); + crate::diesel::utils::hackathon_2024::user::update::by_id(db_pool, user_id, &data.0)?; Ok(format!( "Successfully updated hackathon_user_2024 with email: {}", - new_user.email - ) - .to_owned()) + data.0.nickname_tg + )) } diff --git a/src/data/hackathon_2024/api.rs b/src/data/hackathon_2024/api.rs deleted file mode 100644 index d812827..0000000 --- a/src/data/hackathon_2024/api.rs +++ /dev/null @@ -1,9 +0,0 @@ -use crate::data::hackathon_2024::team::TeamRegistrationData; -use crate::diesel::models::hackathon_2024::user::HackathonUser2024Insertable; -use serde::Deserialize; - -#[derive(Deserialize)] -pub struct RegistrationData { - pub user_data: HackathonUser2024Insertable, - pub team_data: TeamRegistrationData, -} diff --git a/src/data/user.rs b/src/data/user.rs deleted file mode 100644 index d5ee992..0000000 --- a/src/data/user.rs +++ /dev/null @@ -1,18 +0,0 @@ -use rocket::serde::{Deserialize, Serialize}; - -#[derive(Debug, Deserialize)] -pub struct UserLoginRequest { - #[allow(dead_code)] - pub email: String, - #[allow(dead_code)] - pub password: String, -} -#[derive(Debug, Serialize)] -pub struct UserLoginResponse { - #[allow(dead_code)] - pub id: i32, - #[allow(dead_code)] - pub email: String, - #[allow(dead_code)] - pub token: String, -} diff --git a/src/diesel/database_diesel.rs b/src/diesel/configurator.rs similarity index 96% rename from src/diesel/database_diesel.rs rename to src/diesel/configurator.rs index 933e934..373411a 100644 --- a/src/diesel/database_diesel.rs +++ b/src/diesel/configurator.rs @@ -1,5 +1,5 @@ use crate::error::api_error::ApiError; -use crate::utils::constants::database::MIGRATIONS; +use crate::utils::constants::diesel::MIGRATIONS; use crate::utils::env_configuration::EnvConfiguration; use diesel::pg::PgConnection; use diesel::r2d2::{ConnectionManager, Pool, PooledConnection}; @@ -10,7 +10,7 @@ use rocket::State; pub type DbPool = Pool>; -pub fn init_database() -> DbPool { +pub fn configuration_database() -> DbPool { let database_url = format!( "postgres://{}:{}@{}:{}", EnvConfiguration::get().database_user, diff --git a/src/diesel/mod.rs b/src/diesel/mod.rs index 70a4ac6..00a12a9 100644 --- a/src/diesel/mod.rs +++ b/src/diesel/mod.rs @@ -1,4 +1,5 @@ -pub mod database_diesel; +pub mod configurator; pub mod models; +pub mod prelude; pub mod schema; pub mod utils; diff --git a/src/diesel/models/hackathon_2024/team.rs b/src/diesel/models/hackathon_2024/team.rs index 4ec9bdd..c9dedea 100644 --- a/src/diesel/models/hackathon_2024/team.rs +++ b/src/diesel/models/hackathon_2024/team.rs @@ -17,22 +17,22 @@ pub struct HackathonTeam2024Queryable { #[allow(dead_code)] pub count_members: i32, #[allow(dead_code)] + pub email: String, + #[allow(dead_code)] pub created_at: Option, #[allow(dead_code)] pub updated_at: Option, - #[allow(dead_code)] - pub email: String, } #[derive(Insertable, Debug, Deserialize, Serialize)] #[diesel(table_name = crate::diesel::schema::hackathon_team_2024)] -pub struct HackathonTeam2024Insertable<'a> { +pub struct HackathonTeam2024Insertable { #[allow(dead_code)] - pub name: &'a str, + pub name: String, #[allow(dead_code)] pub category: HackathonCategory2024Enum, #[allow(dead_code)] - pub password_registration: &'a str, + pub password_registration: String, #[allow(dead_code)] - pub email: &'a str, + pub nickname_tg: String, } diff --git a/src/diesel/models/hackathon_2024/university.rs b/src/diesel/models/hackathon_2024/university.rs index e54cba3..6ff5322 100644 --- a/src/diesel/models/hackathon_2024/university.rs +++ b/src/diesel/models/hackathon_2024/university.rs @@ -17,6 +17,6 @@ pub struct HackathonUniversity2024Queryable { #[derive(Insertable, Debug, Deserialize, Serialize)] #[diesel(table_name = crate::diesel::schema::hackathon_university_2024)] -pub struct HackathonUniversity2024Insertable<'a> { - pub name: &'a str, +pub struct HackathonUniversity2024Insertable { + pub name: String, } diff --git a/src/diesel/models/hackathon_2024/user.rs b/src/diesel/models/hackathon_2024/user.rs index a752dba..d895d78 100644 --- a/src/diesel/models/hackathon_2024/user.rs +++ b/src/diesel/models/hackathon_2024/user.rs @@ -12,17 +12,17 @@ pub struct HackathonUser2024Queryable { #[allow(dead_code)] pub last_name: String, #[allow(dead_code)] - pub email: String, + pub nickname_tg: String, #[allow(dead_code)] pub phone: String, #[allow(dead_code)] - pub created_at: Option, + pub university_id: Option, #[allow(dead_code)] - pub updated_at: Option, + pub team_id: Option, #[allow(dead_code)] - pub university: Option, + pub created_at: Option, #[allow(dead_code)] - pub team_id: i32, + pub updated_at: Option, } #[derive(Insertable, Debug, Deserialize, Serialize)] @@ -30,8 +30,8 @@ pub struct HackathonUser2024Queryable { pub struct HackathonUser2024Insertable { pub first_name: String, pub last_name: String, - pub email: String, + pub nickname_tg: String, pub phone: String, - pub university: i32, + pub university_id: i32, pub team_id: i32, } diff --git a/src/diesel/prelude.rs b/src/diesel/prelude.rs new file mode 100644 index 0000000..8009d47 --- /dev/null +++ b/src/diesel/prelude.rs @@ -0,0 +1,10 @@ +pub use crate::diesel::configurator::get_connection; +pub use crate::diesel::configurator::DbPool; +pub use crate::error::api_error::ApiError; +pub use diesel::ExpressionMethods; +pub use diesel::QueryDsl; +pub use diesel::RunQueryDsl; +pub use log::error; +pub use log::info; +pub use rocket::State; +pub type DbState = State; diff --git a/src/diesel/schema.rs b/src/diesel/schema.rs index 0521873..e01424e 100644 --- a/src/diesel/schema.rs +++ b/src/diesel/schema.rs @@ -38,10 +38,10 @@ diesel::table! { #[max_length = 255] password_registration -> Varchar, count_members -> Int4, + #[max_length = 255] + nickname_tg -> Varchar, created_at -> Nullable, updated_at -> Nullable, - #[max_length = 255] - email -> Varchar, } } @@ -65,11 +65,11 @@ diesel::table! { #[max_length = 20] phone -> Varchar, #[max_length = 255] - email -> Varchar, + nickname_tg -> Varchar, + university_id -> Nullable, + team_id -> Nullable, created_at -> Nullable, updated_at -> Nullable, - university -> Nullable, - team_id -> Int4, } } @@ -101,7 +101,7 @@ diesel::table! { } diesel::joinable!(hackathon_user_2024 -> hackathon_team_2024 (team_id)); -diesel::joinable!(hackathon_user_2024 -> hackathon_university_2024 (university)); +diesel::joinable!(hackathon_user_2024 -> hackathon_university_2024 (university_id)); diesel::joinable!(news_media -> news (news_id)); diesel::allow_tables_to_appear_in_same_query!( diff --git a/src/diesel/utils/hackathon_2024/fetch.rs b/src/diesel/utils/hackathon_2024/fetch.rs deleted file mode 100644 index ceb9850..0000000 --- a/src/diesel/utils/hackathon_2024/fetch.rs +++ /dev/null @@ -1,30 +0,0 @@ -use crate::diesel::database_diesel::{get_connection, DbPool}; -use crate::diesel::models::hackathon_2024::team::HackathonTeam2024Queryable; -use crate::diesel::models::hackathon_2024::university::HackathonUniversity2024Queryable; -use crate::diesel::schema::hackathon_team_2024::dsl::hackathon_team_2024; -use crate::diesel::schema::hackathon_team_2024::id as team_id; -use crate::diesel::schema::hackathon_university_2024::dsl::hackathon_university_2024; -use crate::diesel::schema::hackathon_university_2024::id as university_id; -use crate::error::api_error::ApiError; -use diesel::ExpressionMethods; -use diesel::{QueryDsl, RunQueryDsl}; -use rocket::State; -pub fn team(db_pool: &State, id: i32) -> Result { - let mut db_connection = get_connection(db_pool)?; - - hackathon_team_2024 - .filter(team_id.eq(id)) - .first::(&mut db_connection) - .map_err(ApiError::DatabaseErrorResult) -} -pub fn university( - db_pool: &State, - id: i32, -) -> Result { - let mut db_connection = get_connection(db_pool)?; - - hackathon_university_2024 - .filter(university_id.eq(id)) - .first::(&mut db_connection) - .map_err(ApiError::DatabaseErrorResult) -} diff --git a/src/diesel/utils/hackathon_2024/insert.rs b/src/diesel/utils/hackathon_2024/insert.rs deleted file mode 100644 index 6e32051..0000000 --- a/src/diesel/utils/hackathon_2024/insert.rs +++ /dev/null @@ -1,35 +0,0 @@ -use crate::diesel::database_diesel::{get_connection, DbPool}; -use crate::diesel::models::hackathon_2024::team::HackathonTeam2024Insertable; -use crate::diesel::models::hackathon_2024::university::HackathonUniversity2024Insertable; -use crate::error::api_error::ApiError; -use diesel::query_dsl::RunQueryDsl; -use rocket::State; - -pub fn university( - db_pool: &State, - data: HackathonUniversity2024Insertable, -) -> Result { - let mut db_connection = get_connection(db_pool)?; - diesel::insert_into(crate::diesel::schema::hackathon_university_2024::table) - .values(data) - .returning(crate::diesel::schema::hackathon_university_2024::id) - .get_result::(&mut db_connection) - .map_err(|err| { - log::error!( - "Error inserting hackathon 2024 university with id - {:?}", - err - ); - ApiError::DatabaseErrorResult(err) - }) -} -pub fn team(db_pool: &State, data: HackathonTeam2024Insertable) -> Result { - let mut db_connection = get_connection(db_pool)?; - diesel::insert_into(crate::diesel::schema::hackathon_team_2024::table) - .values(data) - .returning(crate::diesel::schema::hackathon_team_2024::id) - .get_result::(&mut db_connection) - .map_err(|err| { - log::error!("Error inserting hackathon 2024 team with id - {:?}", err); - ApiError::DatabaseErrorResult(err) - }) -} diff --git a/src/diesel/utils/hackathon_2024/mod.rs b/src/diesel/utils/hackathon_2024/mod.rs index 7bc0231..18a8dfe 100644 --- a/src/diesel/utils/hackathon_2024/mod.rs +++ b/src/diesel/utils/hackathon_2024/mod.rs @@ -1,2 +1,3 @@ -pub mod fetch; -pub mod insert; +pub mod team; +pub mod university; +pub mod user; diff --git a/src/diesel/utils/hackathon_2024/team/delete.rs b/src/diesel/utils/hackathon_2024/team/delete.rs new file mode 100644 index 0000000..740646d --- /dev/null +++ b/src/diesel/utils/hackathon_2024/team/delete.rs @@ -0,0 +1,15 @@ +use crate::diesel::configurator::{get_connection, DbPool}; +use crate::diesel::prelude::*; +use crate::diesel::schema::hackathon_team_2024::dsl::hackathon_team_2024; +use crate::error::api_error::ApiError; +use rocket::State; + +pub fn by_id(db_pool: &State, id: i32) -> Result { + diesel::delete(hackathon_team_2024) + .filter(crate::diesel::schema::hackathon_team_2024::id.eq(id)) + .execute(&mut get_connection(db_pool)?) + .map_err(|err| { + error!("Error deleting hackathon_university_2024 with id {id}"); + ApiError::DatabaseErrorResult(err) + }) +} diff --git a/src/diesel/utils/hackathon_2024/team/fetch.rs b/src/diesel/utils/hackathon_2024/team/fetch.rs new file mode 100644 index 0000000..28bd95a --- /dev/null +++ b/src/diesel/utils/hackathon_2024/team/fetch.rs @@ -0,0 +1,14 @@ +use crate::diesel::models::hackathon_2024::team::HackathonTeam2024Queryable; +use crate::diesel::prelude::*; +use crate::diesel::schema::hackathon_team_2024::dsl::hackathon_team_2024; +pub fn by_id(db_pool: &DbState, team_id: i32) -> Result { + hackathon_team_2024 + .filter(crate::diesel::schema::hackathon_team_2024::columns::id.eq(team_id)) + .first::(&mut get_connection(db_pool)?) + .map_err(ApiError::DatabaseErrorResult) +} +pub fn all(db_pool: &State) -> Result, ApiError> { + hackathon_team_2024 + .load::(&mut get_connection(db_pool)?) + .map_err(ApiError::DatabaseErrorResult) +} diff --git a/src/diesel/utils/hackathon_2024/team/insert.rs b/src/diesel/utils/hackathon_2024/team/insert.rs new file mode 100644 index 0000000..7911dbd --- /dev/null +++ b/src/diesel/utils/hackathon_2024/team/insert.rs @@ -0,0 +1,14 @@ +use crate::diesel::models::hackathon_2024::team::HackathonTeam2024Insertable; +use crate::diesel::prelude::*; + +pub fn new(db_pool: &DbState, data: HackathonTeam2024Insertable) -> Result { + let mut db_connection = get_connection(db_pool)?; + diesel::insert_into(crate::diesel::schema::hackathon_team_2024::table) + .values(data) + .returning(crate::diesel::schema::hackathon_team_2024::id) + .get_result::(&mut db_connection) + .map_err(|err| { + error!("Error inserting hackathon 2024 team with id - {:?}", err); + ApiError::DatabaseErrorResult(err) + }) +} diff --git a/src/diesel/utils/hackathon_2024/team/mod.rs b/src/diesel/utils/hackathon_2024/team/mod.rs new file mode 100644 index 0000000..e792214 --- /dev/null +++ b/src/diesel/utils/hackathon_2024/team/mod.rs @@ -0,0 +1,4 @@ +pub mod delete; +pub mod fetch; +pub mod insert; +pub mod update; diff --git a/src/diesel/utils/hackathon_2024/team/update.rs b/src/diesel/utils/hackathon_2024/team/update.rs new file mode 100644 index 0000000..a71f78e --- /dev/null +++ b/src/diesel/utils/hackathon_2024/team/update.rs @@ -0,0 +1,23 @@ +use crate::diesel::prelude::*; +use crate::diesel::schema::hackathon_team_2024::dsl::hackathon_team_2024; +use crate::diesel::schema::hackathon_team_2024::{category, name, nickname_tg, updated_at}; +use crate::dto::request::hackathon_2024::team::TeamUpdateData; + +pub fn by_data(db_pool: &DbState, data: &TeamUpdateData) -> Result { + diesel::update(hackathon_team_2024) + .filter(crate::diesel::schema::hackathon_team_2024::id.eq(data.id)) + .set(( + name.eq(&data.name), + category.eq(data.category), + nickname_tg.eq(&data.nickname_tg), + updated_at.eq(chrono::Utc::now().naive_utc()), + )) + .execute(&mut get_connection(db_pool)?) + .map_err(|err| { + error!( + "Error updating hackathon_university_2024 with data {:?}", + data + ); + ApiError::DatabaseErrorResult(err) + }) +} diff --git a/src/diesel/utils/hackathon_2024/university/delete.rs b/src/diesel/utils/hackathon_2024/university/delete.rs new file mode 100644 index 0000000..cb79b70 --- /dev/null +++ b/src/diesel/utils/hackathon_2024/university/delete.rs @@ -0,0 +1,14 @@ +use crate::diesel::prelude::*; +use crate::diesel::schema::hackathon_university_2024::dsl::hackathon_university_2024; + +pub fn by_id(db_pool: &DbState, id: i32) -> Result { + diesel::delete( + hackathon_university_2024 + .filter(crate::diesel::schema::hackathon_university_2024::id.eq(id)), + ) + .execute(&mut get_connection(db_pool)?) + .map_err(|err| { + log::error!("Error deleting university from hackathon_university_2024 with id {id}"); + ApiError::DatabaseErrorResult(err) + }) +} diff --git a/src/diesel/utils/hackathon_2024/university/fetch.rs b/src/diesel/utils/hackathon_2024/university/fetch.rs new file mode 100644 index 0000000..28155ed --- /dev/null +++ b/src/diesel/utils/hackathon_2024/university/fetch.rs @@ -0,0 +1,20 @@ +use crate::diesel::models::hackathon_2024::university::HackathonUniversity2024Queryable; +use crate::diesel::prelude::*; +use crate::diesel::schema::hackathon_university_2024::dsl::hackathon_university_2024; +pub fn by_id(db_pool: &DbState, id: i32) -> Result { + hackathon_university_2024 + .filter(crate::diesel::schema::hackathon_university_2024::columns::id.eq(id)) + .first::(&mut get_connection(db_pool)?) + .map_err(|err| { + error!("Error to get hackathon_university_2024 with id {id}"); + ApiError::DatabaseErrorResult(err) + }) +} +pub fn all(db_pool: &State) -> Result, ApiError> { + hackathon_university_2024 + .load::(&mut get_connection(db_pool)?) + .map_err(|err| { + error!("Error to get all hackathon_university_2024"); + ApiError::DatabaseErrorResult(err) + }) +} diff --git a/src/diesel/utils/hackathon_2024/university/insert.rs b/src/diesel/utils/hackathon_2024/university/insert.rs new file mode 100644 index 0000000..b7d10da --- /dev/null +++ b/src/diesel/utils/hackathon_2024/university/insert.rs @@ -0,0 +1,20 @@ +use crate::diesel::models::hackathon_2024::university::HackathonUniversity2024Insertable; +use crate::diesel::prelude::*; + +pub fn new( + db_pool: &State, + data: HackathonUniversity2024Insertable, +) -> Result { + let mut db_connection = get_connection(db_pool)?; + diesel::insert_into(crate::diesel::schema::hackathon_university_2024::table) + .values(data) + .returning(crate::diesel::schema::hackathon_university_2024::id) + .get_result::(&mut db_connection) + .map_err(|err| { + error!( + "Error inserting hackathon 2024 university with id - {:?}", + err + ); + ApiError::DatabaseErrorResult(err) + }) +} diff --git a/src/diesel/utils/hackathon_2024/university/mod.rs b/src/diesel/utils/hackathon_2024/university/mod.rs new file mode 100644 index 0000000..e792214 --- /dev/null +++ b/src/diesel/utils/hackathon_2024/university/mod.rs @@ -0,0 +1,4 @@ +pub mod delete; +pub mod fetch; +pub mod insert; +pub mod update; diff --git a/src/diesel/utils/hackathon_2024/university/update.rs b/src/diesel/utils/hackathon_2024/university/update.rs new file mode 100644 index 0000000..dfa9069 --- /dev/null +++ b/src/diesel/utils/hackathon_2024/university/update.rs @@ -0,0 +1,21 @@ +use crate::diesel::models::hackathon_2024::university::HackathonUniversity2024Insertable; +use crate::diesel::prelude::*; +use crate::diesel::schema::hackathon_university_2024::dsl::hackathon_university_2024; +use crate::diesel::schema::hackathon_university_2024::{id, name, updated_at}; + +pub fn by_id( + db_pool: &State, + university_id: i32, + data: HackathonUniversity2024Insertable, +) -> Result { + diesel::update(hackathon_university_2024.filter(id.eq(university_id))) + .set(( + name.eq(data.name), + updated_at.eq(chrono::Utc::now().naive_utc()), + )) + .execute(&mut get_connection(db_pool)?) + .map_err(|err| { + error!("Error updating hackathon_university_2024"); + ApiError::DatabaseErrorResult(err) + }) +} diff --git a/src/diesel/utils/hackathon_2024/user/delete.rs b/src/diesel/utils/hackathon_2024/user/delete.rs new file mode 100644 index 0000000..d5b4d76 --- /dev/null +++ b/src/diesel/utils/hackathon_2024/user/delete.rs @@ -0,0 +1,12 @@ +use crate::diesel::prelude::*; +use crate::diesel::schema::hackathon_user_2024::dsl::hackathon_user_2024; +use crate::diesel::schema::hackathon_user_2024::id; + +pub fn by_id(db_pool: &State, user_id: i32) -> Result { + diesel::delete(hackathon_user_2024.filter(id.eq(user_id))) + .execute(&mut get_connection(db_pool)?) + .map_err(|err| { + error!("Error deleting hackathon_user_2024"); + ApiError::DatabaseErrorResult(err) + }) +} diff --git a/src/diesel/utils/hackathon_2024/user/fetch.rs b/src/diesel/utils/hackathon_2024/user/fetch.rs new file mode 100644 index 0000000..89ef0cb --- /dev/null +++ b/src/diesel/utils/hackathon_2024/user/fetch.rs @@ -0,0 +1,16 @@ +use crate::diesel::models::hackathon_2024::user::HackathonUser2024Queryable; +use crate::diesel::prelude::*; +use crate::diesel::schema::hackathon_user_2024::dsl::hackathon_user_2024; +use crate::diesel::schema::hackathon_user_2024::id; + +pub fn all(db_pool: &DbState) -> Result, ApiError> { + hackathon_user_2024 + .load::(&mut get_connection(db_pool)?) + .map_err(ApiError::DatabaseErrorResult) +} +pub fn by_id(db_pool: &DbState, user_id: i32) -> Result { + hackathon_user_2024 + .filter(id.eq(user_id)) + .first::(&mut get_connection(db_pool)?) + .map_err(ApiError::DatabaseErrorResult) +} diff --git a/src/diesel/utils/hackathon_2024/user/insert.rs b/src/diesel/utils/hackathon_2024/user/insert.rs new file mode 100644 index 0000000..5be4902 --- /dev/null +++ b/src/diesel/utils/hackathon_2024/user/insert.rs @@ -0,0 +1,13 @@ +use crate::diesel::models::hackathon_2024::user::HackathonUser2024Insertable; +use crate::diesel::prelude::*; + +pub fn new(db_pool: &DbState, data: HackathonUser2024Insertable) -> Result { + diesel::insert_into(crate::diesel::schema::hackathon_user_2024::table) + .values(data) + .returning(crate::diesel::schema::hackathon_user_2024::id) + .get_result::(&mut get_connection(db_pool)?) + .map_err(|err| { + error!("Error inserting hackathon_user_2024"); + ApiError::DatabaseErrorResult(err) + }) +} diff --git a/src/diesel/utils/hackathon_2024/user/mod.rs b/src/diesel/utils/hackathon_2024/user/mod.rs new file mode 100644 index 0000000..e792214 --- /dev/null +++ b/src/diesel/utils/hackathon_2024/user/mod.rs @@ -0,0 +1,4 @@ +pub mod delete; +pub mod fetch; +pub mod insert; +pub mod update; diff --git a/src/diesel/utils/hackathon_2024/user/update.rs b/src/diesel/utils/hackathon_2024/user/update.rs new file mode 100644 index 0000000..4e898ba --- /dev/null +++ b/src/diesel/utils/hackathon_2024/user/update.rs @@ -0,0 +1,28 @@ +use crate::diesel::models::hackathon_2024::user::HackathonUser2024Insertable; +use crate::diesel::prelude::*; +use crate::diesel::schema::hackathon_user_2024::dsl::hackathon_user_2024; +use crate::diesel::schema::hackathon_user_2024::{ + first_name, id, last_name, nickname_tg, phone, university_id, updated_at, +}; + +pub fn by_id( + dp_pool: &State, + user_id: i32, + data: &HackathonUser2024Insertable, +) -> Result { + diesel::update(hackathon_user_2024.filter(id.eq(user_id))) + .set(( + first_name.eq(&data.first_name), + last_name.eq(&data.last_name), + nickname_tg.eq(&data.nickname_tg), + phone.eq(&data.phone), + university_id.eq(data.university_id), + id.eq(data.team_id), + updated_at.eq(chrono::Utc::now().naive_utc()), + )) + .execute(&mut get_connection(dp_pool)?) + .map_err(|err| { + error!("Error updating hackathon_user_2024, bellow error"); + ApiError::DatabaseErrorResult(err) + }) +} diff --git a/src/dto/mod.rs b/src/dto/mod.rs new file mode 100644 index 0000000..e006218 --- /dev/null +++ b/src/dto/mod.rs @@ -0,0 +1,2 @@ +pub mod request; +pub mod response; diff --git a/src/data/hackathon_2024/mod.rs b/src/dto/request/hackathon_2024/mod.rs similarity index 58% rename from src/data/hackathon_2024/mod.rs rename to src/dto/request/hackathon_2024/mod.rs index 686f3c5..18a8dfe 100644 --- a/src/data/hackathon_2024/mod.rs +++ b/src/dto/request/hackathon_2024/mod.rs @@ -1,3 +1,3 @@ -pub mod api; pub mod team; +pub mod university; pub mod user; diff --git a/src/data/hackathon_2024/team.rs b/src/dto/request/hackathon_2024/team.rs similarity index 92% rename from src/data/hackathon_2024/team.rs rename to src/dto/request/hackathon_2024/team.rs index a2c26aa..7ce8044 100644 --- a/src/data/hackathon_2024/team.rs +++ b/src/dto/request/hackathon_2024/team.rs @@ -6,10 +6,11 @@ pub struct TeamRegistrationData { pub id: i32, pub password: String, } + #[derive(Debug, Deserialize)] pub struct TeamUpdateData { pub id: i32, pub name: String, pub category: HackathonCategory2024Enum, - pub email: String, + pub nickname_tg: String, } diff --git a/src/dto/request/hackathon_2024/university.rs b/src/dto/request/hackathon_2024/university.rs new file mode 100644 index 0000000..ae82690 --- /dev/null +++ b/src/dto/request/hackathon_2024/university.rs @@ -0,0 +1,4 @@ +#[derive(serde::Deserialize)] +pub struct University( + pub crate::diesel::models::hackathon_2024::university::HackathonUniversity2024Insertable, +); diff --git a/src/dto/request/hackathon_2024/user.rs b/src/dto/request/hackathon_2024/user.rs new file mode 100644 index 0000000..3162a0a --- /dev/null +++ b/src/dto/request/hackathon_2024/user.rs @@ -0,0 +1,17 @@ +use crate::diesel::models::hackathon_2024::user::HackathonUser2024Insertable; +use crate::dto::request::hackathon_2024::team::TeamRegistrationData; +use serde::Deserialize; + +#[derive(Deserialize)] +pub struct RegistrationData { + pub user_data: HackathonUser2024Insertable, + pub team_data: TeamRegistrationData, +} + +#[allow(dead_code)] +#[derive(serde::Deserialize)] +pub struct User(pub HackathonUser2024Insertable); + +#[allow(dead_code)] +#[derive(serde::Deserialize)] +pub struct VecUser(pub Vec); diff --git a/src/data/mod.rs b/src/dto/request/mod.rs similarity index 50% rename from src/data/mod.rs rename to src/dto/request/mod.rs index 87c3eae..2086991 100644 --- a/src/data/mod.rs +++ b/src/dto/request/mod.rs @@ -1,4 +1,2 @@ -pub mod admin_match; -pub mod claims; pub mod hackathon_2024; pub mod user; diff --git a/src/dto/request/user.rs b/src/dto/request/user.rs new file mode 100644 index 0000000..51d6e03 --- /dev/null +++ b/src/dto/request/user.rs @@ -0,0 +1,9 @@ +use rocket::serde::Deserialize; + +#[derive(Debug, Deserialize)] +pub struct UserLoginRequest { + #[allow(dead_code)] + pub email: String, + #[allow(dead_code)] + pub password: String, +} diff --git a/src/dto/response/hackathon_2024/mod.rs b/src/dto/response/hackathon_2024/mod.rs new file mode 100644 index 0000000..2de672d --- /dev/null +++ b/src/dto/response/hackathon_2024/mod.rs @@ -0,0 +1,2 @@ +pub mod university; +pub mod user; diff --git a/src/dto/response/hackathon_2024/university.rs b/src/dto/response/hackathon_2024/university.rs new file mode 100644 index 0000000..294c006 --- /dev/null +++ b/src/dto/response/hackathon_2024/university.rs @@ -0,0 +1,9 @@ +#[derive(serde::Serialize)] +pub struct University( + pub crate::diesel::models::hackathon_2024::university::HackathonUniversity2024Queryable, +); + +#[derive(serde::Serialize)] +pub struct VecUniversity( + pub Vec, +); diff --git a/src/dto/response/hackathon_2024/user.rs b/src/dto/response/hackathon_2024/user.rs new file mode 100644 index 0000000..ece1d3f --- /dev/null +++ b/src/dto/response/hackathon_2024/user.rs @@ -0,0 +1,7 @@ +use crate::diesel::models::hackathon_2024::user::HackathonUser2024Queryable; + +#[derive(serde::Serialize)] +pub struct User(pub HackathonUser2024Queryable); + +#[derive(serde::Serialize)] +pub struct VecUser(pub Vec); diff --git a/src/dto/response/mod.rs b/src/dto/response/mod.rs new file mode 100644 index 0000000..2086991 --- /dev/null +++ b/src/dto/response/mod.rs @@ -0,0 +1,2 @@ +pub mod hackathon_2024; +pub mod user; diff --git a/src/dto/response/user.rs b/src/dto/response/user.rs new file mode 100644 index 0000000..c329b56 --- /dev/null +++ b/src/dto/response/user.rs @@ -0,0 +1,11 @@ +use rocket::serde::Serialize; + +#[derive(Debug, Serialize)] +pub struct UserLoginResponse { + #[allow(dead_code)] + pub id: i32, + #[allow(dead_code)] + pub email: String, + #[allow(dead_code)] + pub token: String, +} diff --git a/src/error/api_error.rs b/src/error/api_error.rs index c02b1fd..c56e570 100644 --- a/src/error/api_error.rs +++ b/src/error/api_error.rs @@ -10,42 +10,58 @@ pub enum ApiError { #[allow(dead_code)] #[error("Error not found")] NotFound, + #[allow(dead_code)] #[error("Database result error occurred")] DatabaseErrorResult(#[from] diesel::result::Error), + #[allow(dead_code)] #[error("Database connection error occurred")] DatabaseErrorConnection(String), + #[allow(dead_code)] #[error("Internal server error")] InternalServerError, + #[allow(dead_code)] #[error("Bad request error")] BadRequest, + #[allow(dead_code)] #[error("HTTP error")] HttpError, + #[allow(dead_code)] #[error("Hashing error")] HashingError(String), + #[allow(dead_code)] #[error("Validation error")] ValidationError(String), + #[allow(dead_code)] #[error("Token generation error")] TokenGenerationError(String), + #[allow(dead_code)] #[error("Token decoded error")] TokenDecodeError(String), + #[allow(dead_code)] #[error("Unauthorized error")] Unauthorized(String), + #[allow(dead_code)] #[error("Invalid claims error")] InvalidClaims, + #[allow(dead_code)] #[error("Email send error")] SendEmailError(String), + + #[allow(dead_code)] + #[error("Header mismatched error")] + HeaderMismatched(String), } impl<'r> Responder<'r, 'static> for ApiError { @@ -53,45 +69,46 @@ impl<'r> Responder<'r, 'static> for ApiError { log::error!("API error occurred: {:?}", self); let (status, message) = match self { - ApiError::NotFound => (Status::NotFound, "Error not found".to_owned()), - ApiError::DatabaseErrorResult(_) => ( + ApiError::NotFound => (Status::NotFound, "Resource not found".to_owned()), + + ApiError::DatabaseErrorResult(err) => ( Status::InternalServerError, - "Database error occurred".to_owned(), + format!("Database error result: {}", err), ), + ApiError::InternalServerError => ( Status::InternalServerError, "Internal server error".to_owned(), ), - ApiError::BadRequest => (Status::BadRequest, "Bad request error".to_owned()), - ApiError::HttpError => ( - Status::InternalServerError, - "HTTP error occurred".to_owned(), - ), - ApiError::HashingError(_) => (Status::NotFound, "Hashing error".to_owned()), - ApiError::ValidationError(_) => (Status::NotFound, "Validation error".to_owned()), - ApiError::TokenGenerationError(_) => { - (Status::NotFound, "Token generation error".to_owned()) - } - ApiError::TokenDecodeError(_) => (Status::NotFound, "Token decoded error".to_owned()), - ApiError::Unauthorized(err) => ( - Status::Unauthorized, - format!("Unauthorized error - {}", err).to_owned(), - ), - ApiError::InvalidClaims => (Status::Unauthorized, "Invalid claims error".to_owned()), - ApiError::DatabaseErrorConnection(_) => ( - Status::InternalServerError, - "Database connection error".to_owned(), - ), - ApiError::SendEmailError(_) => { - (Status::InternalServerError, "Email send error".to_owned()) - } + + ApiError::BadRequest => (Status::BadRequest, "Bad request".to_owned()), + + ApiError::HttpError => (Status::BadGateway, "HTTP error".to_owned()), + + ApiError::HashingError(err) => (Status::InternalServerError, err), + + ApiError::ValidationError(err) => (Status::UnprocessableEntity, err), + + ApiError::TokenGenerationError(err) => (Status::InternalServerError, err), + + ApiError::TokenDecodeError(err) => (Status::Unauthorized, err), + + ApiError::Unauthorized(err) => (Status::Unauthorized, err), + + ApiError::InvalidClaims => (Status::Unauthorized, "Invalid claims".to_owned()), + + ApiError::DatabaseErrorConnection(err) => (Status::ServiceUnavailable, err), + + ApiError::SendEmailError(err) => (Status::InternalServerError, err), + + ApiError::HeaderMismatched(err) => (Status::BadRequest, err), }; let body = serde_json::to_string(&ApiErrorBody { error: status.to_string(), message, }) - .expect("Failed to serialize error body"); + .unwrap_or("Can't deserialize api error body".to_owned()); Response::build() .status(status) diff --git a/src/main.rs b/src/main.rs index b62618a..621da26 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,9 +1,12 @@ use crate::server::Server; mod api; -mod data; mod diesel; +mod dto; mod error; +mod middleware; +mod models; mod server; +#[cfg(test)] mod tests; mod utils; diff --git a/src/data/admin_match.rs b/src/middleware/admin_match.rs similarity index 77% rename from src/data/admin_match.rs rename to src/middleware/admin_match.rs index e72c3fc..fd9c82e 100644 --- a/src/data/admin_match.rs +++ b/src/middleware/admin_match.rs @@ -28,7 +28,7 @@ impl AdminMatch { #[rocket::async_trait] impl<'r> FromRequest<'r> for AdminMatch { - type Error = (); + type Error = ApiError; #[allow(dead_code)] async fn from_request(req: &'r Request<'_>) -> request::Outcome { @@ -41,12 +41,18 @@ impl<'r> FromRequest<'r> for AdminMatch { request::Outcome::Success(AdminMatch { is_admin: true }) } else { warn!("Error admin password"); - request::Outcome::Error((Status::Unauthorized, ())) + request::Outcome::Error(( + Status::Unauthorized, + ApiError::HeaderMismatched("Admin header mismatched".to_owned()), + )) } } None => { warn!("Token not found in header \"Authorization\""); - request::Outcome::Error((Status::Unauthorized, ())) + request::Outcome::Error(( + Status::Unauthorized, + ApiError::HeaderMismatched("Admin header mismatched".to_owned()), + )) } } } diff --git a/src/data/claims.rs b/src/middleware/claims.rs similarity index 100% rename from src/data/claims.rs rename to src/middleware/claims.rs diff --git a/src/middleware/mod.rs b/src/middleware/mod.rs new file mode 100644 index 0000000..27abfb0 --- /dev/null +++ b/src/middleware/mod.rs @@ -0,0 +1,2 @@ +pub mod admin_match; +pub mod claims; diff --git a/src/models/hackathon_2024/mod.rs b/src/models/hackathon_2024/mod.rs new file mode 100644 index 0000000..22d12a3 --- /dev/null +++ b/src/models/hackathon_2024/mod.rs @@ -0,0 +1 @@ +pub mod user; diff --git a/src/data/hackathon_2024/user.rs b/src/models/hackathon_2024/user.rs similarity index 55% rename from src/data/hackathon_2024/user.rs rename to src/models/hackathon_2024/user.rs index c72fac1..dadf6ec 100644 --- a/src/data/hackathon_2024/user.rs +++ b/src/models/hackathon_2024/user.rs @@ -1,15 +1,17 @@ use crate::diesel::models::hackathon_2024::user::HackathonUser2024Insertable; +use serde::{Deserialize, Serialize}; -#[derive(Debug, serde::Serialize, serde::Deserialize)] +#[derive(Debug, Serialize, Deserialize)] pub struct UserJwt { pub first_name: String, pub last_name: String, - pub email: String, + pub nickname_tg: String, pub phone: String, pub team_id: i32, - pub university: i32, + pub university_id: i32, pub exp: usize, } + impl UserJwt { pub fn from(data: &HackathonUser2024Insertable, exp: i64) -> Self { let exp = chrono::Utc::now() @@ -19,11 +21,21 @@ impl UserJwt { Self { first_name: data.first_name.to_owned(), last_name: data.last_name.to_owned(), - email: data.email.to_owned(), + nickname_tg: data.nickname_tg.to_owned(), phone: data.phone.to_owned(), team_id: data.team_id, - university: data.university, + university_id: data.university_id, exp, } } + pub fn into(self) -> HackathonUser2024Insertable { + HackathonUser2024Insertable { + first_name: self.first_name, + last_name: self.last_name, + nickname_tg: self.nickname_tg, + phone: self.phone, + team_id: self.team_id, + university_id: self.university_id, + } + } } diff --git a/src/models/mod.rs b/src/models/mod.rs new file mode 100644 index 0000000..60226f9 --- /dev/null +++ b/src/models/mod.rs @@ -0,0 +1 @@ +pub mod hackathon_2024; diff --git a/src/server.rs b/src/server.rs index f15cced..5ae0252 100644 --- a/src/server.rs +++ b/src/server.rs @@ -1,5 +1,5 @@ use crate::api; -use crate::diesel::database_diesel::{init_database, DbPool}; +use crate::diesel::configurator::{configuration_database, DbPool}; use crate::utils::env_configuration::EnvConfiguration; use log::LevelFilter; use rocket::figment::Figment; @@ -15,7 +15,7 @@ impl Server { let config = Server::get_server_config().expect("Failed to configure Rocket server"); let cors = Server::configure_cors(); - let db_pool = init_database(); + let db_pool = configuration_database(); Server::build_rocket(db_pool, config, cors).await; } diff --git a/src/tests/main.rs b/src/tests/main.rs new file mode 100644 index 0000000..652e2a4 --- /dev/null +++ b/src/tests/main.rs @@ -0,0 +1,4 @@ +#[test] +fn bootstrap_test() { + assert_eq!(2 + 2, 4); +} diff --git a/src/tests/mod.rs b/src/tests/mod.rs index 7b788c2..158a20c 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -1 +1,2 @@ -pub mod test; +#[cfg(test)] +pub mod main; diff --git a/src/tests/test.rs b/src/tests/test.rs deleted file mode 100644 index a9e3994..0000000 --- a/src/tests/test.rs +++ /dev/null @@ -1,7 +0,0 @@ -#[cfg(test)] -mod main_test { - #[test] - fn bootstrap_test() { - assert_eq!(2 + 2, 4); - } -} diff --git a/src/utils/constants/database.rs b/src/utils/constants/diesel.rs similarity index 100% rename from src/utils/constants/database.rs rename to src/utils/constants/diesel.rs diff --git a/src/utils/constants/mod.rs b/src/utils/constants/mod.rs index 72ebf17..0912a1d 100644 --- a/src/utils/constants/mod.rs +++ b/src/utils/constants/mod.rs @@ -1,2 +1 @@ -pub mod database; -pub mod routes; +pub mod diesel; diff --git a/src/utils/constants/routes.rs b/src/utils/constants/routes.rs deleted file mode 100644 index 8b13789..0000000 --- a/src/utils/constants/routes.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 9d43876..e7ea2b1 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -1,5 +1,6 @@ pub mod actions; pub mod constants; pub mod env_configuration; +pub mod prelude_api; pub mod security; pub mod validation; diff --git a/src/utils/prelude_api.rs b/src/utils/prelude_api.rs new file mode 100644 index 0000000..1dfdd21 --- /dev/null +++ b/src/utils/prelude_api.rs @@ -0,0 +1,4 @@ +pub use crate::diesel::prelude::DbState; +pub use crate::error::api_error::ApiError; +pub use log::info; +pub use rocket::serde::json::Json; diff --git a/src/utils/security.rs b/src/utils/security.rs index fa085b3..fb3dbe4 100644 --- a/src/utils/security.rs +++ b/src/utils/security.rs @@ -14,6 +14,7 @@ pub fn hashing_data(value: impl AsRef) -> Result { ApiError::HashingError(err.to_string()) }) } + #[allow(dead_code)] pub fn verify_password(password: impl AsRef, hash: impl AsRef) -> Result { verify(password.as_ref(), hash.as_ref()).map_err(|err| { @@ -21,6 +22,7 @@ pub fn verify_password(password: impl AsRef, hash: impl AsRef) -> Resu ApiError::HashingError(err.to_string()) }) } + pub fn decoded_data( jwt_token: impl AsRef, ) -> Result, ApiError> { @@ -31,6 +33,7 @@ pub fn decoded_data( ) .map_err(|err| ApiError::TokenDecodeError(err.to_string())) } + pub fn encoded_data(value: &T) -> Result { encode( &Header::new(Algorithm::HS512), diff --git a/src/utils/validation/data/fields.rs b/src/utils/validation/data/fields.rs index 3cdd0e6..8712fb3 100644 --- a/src/utils/validation/data/fields.rs +++ b/src/utils/validation/data/fields.rs @@ -1,31 +1,42 @@ use crate::error::api_error::ApiError; use crate::utils::validation::validation_string::Validate; -pub fn check_email(email: &str, error_message: &str) -> Result<(), ApiError> { - if email.is_email() { +pub fn check_email(email: impl AsRef, error_message: impl AsRef) -> Result<(), ApiError> { + if email.as_ref().is_email() { Ok(()) } else { - Err(ApiError::ValidationError(error_message.to_owned())) + Err(ApiError::ValidationError(error_message.as_ref().to_owned())) } } -pub fn check_name(name: &str, lenght: usize, error_message: &str) -> Result<(), ApiError> { - if name.less_for(lenght) { + +pub fn check_name( + name: impl AsRef, + length: usize, + error_message: impl AsRef, +) -> Result<(), ApiError> { + if name.as_ref().less_for(length) { Ok(()) } else { - Err(ApiError::ValidationError(error_message.to_owned())) + Err(ApiError::ValidationError(error_message.as_ref().to_owned())) } } -pub fn check_phone(phone: &str, error_message: &str) -> Result<(), ApiError> { - if phone.is_phone() { + +pub fn check_phone(phone: impl AsRef, error_message: impl AsRef) -> Result<(), ApiError> { + if phone.as_ref().is_phone() { Ok(()) } else { - Err(ApiError::ValidationError(error_message.to_owned())) + Err(ApiError::ValidationError(error_message.as_ref().to_owned())) } } -pub fn check_password(password: &str, length: usize, error_message: &str) -> Result<(), ApiError> { - if password.is_password(length) { + +pub fn check_password( + password: impl AsRef, + length: usize, + error_message: impl AsRef, +) -> Result<(), ApiError> { + if password.as_ref().is_password(length) { Ok(()) } else { - Err(ApiError::ValidationError(error_message.to_owned())) + Err(ApiError::ValidationError(error_message.as_ref().to_owned())) } } diff --git a/src/utils/validation/data/hackathon_2024/team.rs b/src/utils/validation/data/hackathon_2024/team.rs index c808fa3..095343e 100644 --- a/src/utils/validation/data/hackathon_2024/team.rs +++ b/src/utils/validation/data/hackathon_2024/team.rs @@ -5,21 +5,24 @@ use crate::utils::validation::data::fields::{check_email, check_name, check_pass #[allow(dead_code)] pub fn field(new_team: &HackathonTeam2024Insertable) -> Result<(), ApiError> { check_email( - new_team.email, - format!("Email don't correct {}", new_team.email).as_str(), + &new_team.nickname_tg, + format!("Email don't correct {}", new_team.nickname_tg).as_str(), )?; + check_name( - new_team.name, + &new_team.name, 30, format!("Team name greater for {} symbol", 30).as_str(), )?; - check_team_password(new_team.password_registration)?; + + check_team_password(&new_team.password_registration)?; + Ok(()) } -pub fn check_team_password(password: &str) -> Result<(), ApiError> { +pub fn check_team_password(password: impl AsRef) -> Result<(), ApiError> { check_password( - password, + password.as_ref(), 20, format!( "Team password greater for {} symbol or don't correct regex", diff --git a/src/utils/validation/data/hackathon_2024/user.rs b/src/utils/validation/data/hackathon_2024/user.rs index 6d25e8f..2f82568 100644 --- a/src/utils/validation/data/hackathon_2024/user.rs +++ b/src/utils/validation/data/hackathon_2024/user.rs @@ -4,30 +4,29 @@ use crate::utils::validation::data::fields::{check_email, check_name, check_phon pub fn field(new_user: &HackathonUser2024Insertable) -> Result<(), ApiError> { check_email( - new_user.email.as_str(), - format!("Email don't correct {}", new_user.email.as_str()).as_str(), + new_user.nickname_tg.as_str(), + format!("Email don't correct {}", new_user.nickname_tg), )?; + check_phone( new_user.phone.as_str(), - format!("Phone don't correct {}", new_user.phone.as_str()).as_str(), + format!("Phone don't correct {}", new_user.phone), )?; + check_name( new_user.first_name.as_str(), 20, - format!( - "First name length greater {} symbol", - new_user.first_name.as_str() - ) - .as_str(), + format!("First name length greater {} symbol", new_user.first_name), )?; + check_name( new_user.last_name.as_str(), 20, format!( "Lastname name length greater {} symbol", - new_user.first_name.as_str() - ) - .as_str(), + new_user.first_name + ), )?; + Ok(()) } diff --git a/src/utils/validation/validation_string.rs b/src/utils/validation/validation_string.rs index f4c1ddc..61c47cb 100644 --- a/src/utils/validation/validation_string.rs +++ b/src/utils/validation/validation_string.rs @@ -3,12 +3,16 @@ use regex::Regex; pub trait Validate { #[allow(dead_code)] fn less_for(&self, len: usize) -> bool; + #[allow(dead_code)] fn greater_for(&self, len: usize) -> bool; + #[allow(dead_code)] fn is_email(&self) -> bool; + #[allow(dead_code)] fn is_phone(&self) -> bool; + #[allow(dead_code)] fn is_password(&self, max_len: usize) -> bool; } @@ -47,14 +51,17 @@ impl> Validate for T { Ok(regex) => regex, Err(_) => return false, }; + let has_symbol = match Regex::new(r"[!@#$%^&*()_+=\-{}\[\]|\\:;'<>,.?/~`]") { Ok(regex) => regex, Err(_) => return false, }; + let has_lowercase = match Regex::new(r"[a-z]") { Ok(regex) => regex, Err(_) => return false, }; + let has_uppercase = match Regex::new(r"[A-Z]") { Ok(regex) => regex, Err(_) => return false, From 3861bfc1e2975a9e81eed4c9cb56ecd4fdd0559a Mon Sep 17 00:00:00 2001 From: brizzinck <87083857+brizzinck@users.noreply.github.com> Date: Wed, 8 Jan 2025 15:45:12 +0200 Subject: [PATCH 2/3] feat: registration by tg --- src/api/hackathon_2024/user/post.rs | 46 +++++-------------- src/dto/request/hackathon_2024/user.rs | 1 + src/models/hackathon_2024/user.rs | 3 ++ src/server.rs | 2 +- src/utils/actions/send_letter.rs | 1 + src/utils/env_configuration.rs | 1 + src/utils/security.rs | 1 + src/utils/validation/data/fields.rs | 12 +++++ .../validation/data/hackathon_2024/team.rs | 5 +- .../validation/data/hackathon_2024/user.rs | 4 +- src/utils/validation/validation_string.rs | 10 ++++ 11 files changed, 46 insertions(+), 40 deletions(-) diff --git a/src/api/hackathon_2024/user/post.rs b/src/api/hackathon_2024/user/post.rs index f4ed915..5a79856 100644 --- a/src/api/hackathon_2024/user/post.rs +++ b/src/api/hackathon_2024/user/post.rs @@ -1,57 +1,33 @@ use crate::dto::request::hackathon_2024::user::RegistrationData; -use crate::models::hackathon_2024::user::UserJwt; -use crate::utils::actions; use crate::utils::prelude_api::*; -use crate::utils::security::{encoded_data, verify_password}; +use crate::utils::security::verify_password; use crate::utils::validation; use rocket::post; -#[post("/hackathon_2024/user/try_registration", data = "")] -pub async fn try_registration( +#[post("/hackathon_2024/user/registration_by_tg", data = "")] +pub async fn registration_by_tg( db_pool: &DbState, - registration_data: Json, + data: Json, ) -> Result<(), ApiError> { - let registration_data = registration_data.into_inner(); + let data = data.into_inner(); let RegistrationData { user_data, team_data, - .. - } = registration_data; + } = data; validation::data::hackathon_2024::team::check_team_password(team_data.password.as_str())?; validation::data::hackathon_2024::user::field(&user_data)?; let team = crate::diesel::utils::hackathon_2024::team::fetch::by_id(db_pool, team_data.id)?; - verify_password(team_data.password, team.password_registration.as_str())?; - - let _ = crate::diesel::utils::hackathon_2024::university::fetch::by_id( - db_pool, - user_data.university_id, + verify_password( + team_data.password.as_str(), + team.password_registration.as_str(), )?; - let jwt_user = UserJwt::from(&user_data, 5); - - let token = encoded_data(&jwt_user)?; + let id = crate::diesel::utils::hackathon_2024::user::insert::new(db_pool, user_data)?; - actions::send_letter::send_letter( - "HACKATHON".to_owned(), - format!( - " - -

Hello!

- Accept - - ", - token - ) - .to_string(), - user_data.nickname_tg.to_owned(), - )?; + info!("Succeed create user with id {id}"); - info!( - "verify email sent to {}, jwt token - {token}", - user_data.nickname_tg - ); Ok(()) } diff --git a/src/dto/request/hackathon_2024/user.rs b/src/dto/request/hackathon_2024/user.rs index 3162a0a..fec945f 100644 --- a/src/dto/request/hackathon_2024/user.rs +++ b/src/dto/request/hackathon_2024/user.rs @@ -2,6 +2,7 @@ use crate::diesel::models::hackathon_2024::user::HackathonUser2024Insertable; use crate::dto::request::hackathon_2024::team::TeamRegistrationData; use serde::Deserialize; +#[non_exhaustive] #[derive(Deserialize)] pub struct RegistrationData { pub user_data: HackathonUser2024Insertable, diff --git a/src/models/hackathon_2024/user.rs b/src/models/hackathon_2024/user.rs index dadf6ec..dad3491 100644 --- a/src/models/hackathon_2024/user.rs +++ b/src/models/hackathon_2024/user.rs @@ -1,6 +1,7 @@ use crate::diesel::models::hackathon_2024::user::HackathonUser2024Insertable; use serde::{Deserialize, Serialize}; +#[allow(dead_code)] #[derive(Debug, Serialize, Deserialize)] pub struct UserJwt { pub first_name: String, @@ -13,6 +14,7 @@ pub struct UserJwt { } impl UserJwt { + #[allow(dead_code)] pub fn from(data: &HackathonUser2024Insertable, exp: i64) -> Self { let exp = chrono::Utc::now() .checked_add_signed(chrono::Duration::minutes(exp)) @@ -28,6 +30,7 @@ impl UserJwt { exp, } } + #[allow(dead_code)] pub fn into(self) -> HackathonUser2024Insertable { HackathonUser2024Insertable { first_name: self.first_name, diff --git a/src/server.rs b/src/server.rs index 5ae0252..b3e27dd 100644 --- a/src/server.rs +++ b/src/server.rs @@ -67,7 +67,7 @@ impl Server { // /test/* api::test::get::ping, // /hackathon_2024/user/* - api::hackathon_2024::user::post::try_registration, + api::hackathon_2024::user::post::registration_by_tg, api::hackathon_2024::user::get::confirm_new_user, api::hackathon_2024::user::get::all, api::hackathon_2024::user::put::by_id, diff --git a/src/utils/actions/send_letter.rs b/src/utils/actions/send_letter.rs index 9ed784e..53ad130 100644 --- a/src/utils/actions/send_letter.rs +++ b/src/utils/actions/send_letter.rs @@ -3,6 +3,7 @@ use crate::utils::env_configuration::EnvConfiguration; use lettre::transport::smtp::authentication::Credentials; use lettre::{Message, SmtpTransport, Transport}; +#[allow(dead_code)] pub fn send_letter( title_letter: String, body_letter: String, diff --git a/src/utils/env_configuration.rs b/src/utils/env_configuration.rs index 43af6f2..9383380 100644 --- a/src/utils/env_configuration.rs +++ b/src/utils/env_configuration.rs @@ -13,6 +13,7 @@ pub struct EnvConfiguration { pub main_url: String, #[allow(dead_code)] pub smtp_email: String, + #[allow(dead_code)] pub smtp_password: String, pub server_port: u16, /* WILL UNCOMMENT WHEN IN SCHEMA.RS EXISTS USER_ROLE!!! diff --git a/src/utils/security.rs b/src/utils/security.rs index fb3dbe4..a2921e4 100644 --- a/src/utils/security.rs +++ b/src/utils/security.rs @@ -34,6 +34,7 @@ pub fn decoded_data( .map_err(|err| ApiError::TokenDecodeError(err.to_string())) } +#[allow(dead_code)] pub fn encoded_data(value: &T) -> Result { encode( &Header::new(Algorithm::HS512), diff --git a/src/utils/validation/data/fields.rs b/src/utils/validation/data/fields.rs index 8712fb3..fba398c 100644 --- a/src/utils/validation/data/fields.rs +++ b/src/utils/validation/data/fields.rs @@ -1,6 +1,7 @@ use crate::error::api_error::ApiError; use crate::utils::validation::validation_string::Validate; +#[allow(dead_code)] pub fn check_email(email: impl AsRef, error_message: impl AsRef) -> Result<(), ApiError> { if email.as_ref().is_email() { Ok(()) @@ -9,6 +10,17 @@ pub fn check_email(email: impl AsRef, error_message: impl AsRef) -> Re } } +pub fn check_nickname_tg( + nickname_tg: impl AsRef, + error_message: impl AsRef, +) -> Result<(), ApiError> { + if nickname_tg.as_ref().is_nickname_tg() { + Ok(()) + } else { + Err(ApiError::ValidationError(error_message.as_ref().to_owned())) + } +} + pub fn check_name( name: impl AsRef, length: usize, diff --git a/src/utils/validation/data/hackathon_2024/team.rs b/src/utils/validation/data/hackathon_2024/team.rs index 095343e..3eca7df 100644 --- a/src/utils/validation/data/hackathon_2024/team.rs +++ b/src/utils/validation/data/hackathon_2024/team.rs @@ -1,10 +1,10 @@ use crate::diesel::models::hackathon_2024::team::HackathonTeam2024Insertable; use crate::error::api_error::ApiError; -use crate::utils::validation::data::fields::{check_email, check_name, check_password}; +use crate::utils::validation::data::fields::{check_name, check_nickname_tg, check_password}; #[allow(dead_code)] pub fn field(new_team: &HackathonTeam2024Insertable) -> Result<(), ApiError> { - check_email( + check_nickname_tg( &new_team.nickname_tg, format!("Email don't correct {}", new_team.nickname_tg).as_str(), )?; @@ -30,5 +30,6 @@ pub fn check_team_password(password: impl AsRef) -> Result<(), ApiError> { ) .as_str(), )?; + Ok(()) } diff --git a/src/utils/validation/data/hackathon_2024/user.rs b/src/utils/validation/data/hackathon_2024/user.rs index 2f82568..b3c9e6f 100644 --- a/src/utils/validation/data/hackathon_2024/user.rs +++ b/src/utils/validation/data/hackathon_2024/user.rs @@ -1,9 +1,9 @@ use crate::diesel::models::hackathon_2024::user::HackathonUser2024Insertable; use crate::error::api_error::ApiError; -use crate::utils::validation::data::fields::{check_email, check_name, check_phone}; +use crate::utils::validation::data::fields::{check_name, check_nickname_tg, check_phone}; pub fn field(new_user: &HackathonUser2024Insertable) -> Result<(), ApiError> { - check_email( + check_nickname_tg( new_user.nickname_tg.as_str(), format!("Email don't correct {}", new_user.nickname_tg), )?; diff --git a/src/utils/validation/validation_string.rs b/src/utils/validation/validation_string.rs index 61c47cb..a3e6c81 100644 --- a/src/utils/validation/validation_string.rs +++ b/src/utils/validation/validation_string.rs @@ -10,6 +10,9 @@ pub trait Validate { #[allow(dead_code)] fn is_email(&self) -> bool; + #[allow(dead_code)] + fn is_nickname_tg(&self) -> bool; + #[allow(dead_code)] fn is_phone(&self) -> bool; @@ -33,6 +36,13 @@ impl> Validate for T { } } + fn is_nickname_tg(&self) -> bool { + match Regex::new(r"(?i)^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$") { + Ok(nickname_regex) => nickname_regex.is_match(self.as_ref()), + Err(_) => false, + } + } + fn is_phone(&self) -> bool { match Regex::new(r"^(\+380|0)\d{9}$") { Ok(phone_regex) => phone_regex.is_match(self.as_ref()), From 83a3179c32c0f6a2f791ed112654b4092a0dade0 Mon Sep 17 00:00:00 2001 From: brizzinck <87083857+brizzinck@users.noreply.github.com> Date: Thu, 9 Jan 2025 22:46:32 +0200 Subject: [PATCH 3/3] feat: dto team --- src/api/admin/get.rs | 1 + src/api/admin/mod.rs | 2 ++ src/api/admin/post.rs | 1 + src/api/hackathon_2024/team/post.rs | 9 +++------ src/api/hackathon_2024/user/get.rs | 1 + src/api/mod.rs | 1 + src/dto/request/hackathon_2024/team.rs | 3 +++ src/dto/response/hackathon_2024/mod.rs | 1 + src/dto/response/hackathon_2024/team.rs | 7 +++++++ src/server.rs | 3 +-- src/utils/env_configuration.rs | 2 +- src/utils/prelude_api.rs | 2 ++ src/utils/validation/validation_string.rs | 2 +- 13 files changed, 25 insertions(+), 10 deletions(-) create mode 100644 src/api/admin/get.rs create mode 100644 src/api/admin/mod.rs create mode 100644 src/api/admin/post.rs create mode 100644 src/dto/response/hackathon_2024/team.rs diff --git a/src/api/admin/get.rs b/src/api/admin/get.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/api/admin/get.rs @@ -0,0 +1 @@ + diff --git a/src/api/admin/mod.rs b/src/api/admin/mod.rs new file mode 100644 index 0000000..69e599d --- /dev/null +++ b/src/api/admin/mod.rs @@ -0,0 +1,2 @@ +pub mod get; +pub mod post; diff --git a/src/api/admin/post.rs b/src/api/admin/post.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/api/admin/post.rs @@ -0,0 +1 @@ + diff --git a/src/api/hackathon_2024/team/post.rs b/src/api/hackathon_2024/team/post.rs index 94b7b9e..5db883d 100644 --- a/src/api/hackathon_2024/team/post.rs +++ b/src/api/hackathon_2024/team/post.rs @@ -1,14 +1,11 @@ -use crate::diesel::models::hackathon_2024::team::HackathonTeam2024Insertable; +use crate::dto::request::hackathon_2024::team::TeamCreateData; use crate::utils::prelude_api::*; use crate::utils::security::hashing_data; use rocket::post; #[post("/hackathon_2024/team/create", data = "")] -pub async fn create( - db_pool: &DbState, - data: Json, -) -> Result<(), ApiError> { - let mut team = data.into_inner(); +pub async fn create(db_pool: &DbState, data: Json) -> Result<(), ApiError> { + let mut team = data.into_inner().0; crate::utils::validation::data::hackathon_2024::team::field(&team)?; team.password_registration = hashing_data(team.password_registration)?; diff --git a/src/api/hackathon_2024/user/get.rs b/src/api/hackathon_2024/user/get.rs index 5387e68..17de422 100644 --- a/src/api/hackathon_2024/user/get.rs +++ b/src/api/hackathon_2024/user/get.rs @@ -7,6 +7,7 @@ use crate::utils::prelude_api::*; use crate::utils::security::decoded_data; use rocket::get; +#[allow(dead_code)] #[get("/hackathon_2024/user/confirm_new_user?")] pub async fn confirm_new_user(db_pool: &DbState, jwt_token: String) -> Result<(), ApiError> { create_user_by_jwt(db_pool, decoded_data(&jwt_token)?.claims) diff --git a/src/api/mod.rs b/src/api/mod.rs index 1296b13..56a5b3d 100644 --- a/src/api/mod.rs +++ b/src/api/mod.rs @@ -1,3 +1,4 @@ +pub mod admin; pub mod banner; pub mod hackathon_2024; pub mod news; diff --git a/src/dto/request/hackathon_2024/team.rs b/src/dto/request/hackathon_2024/team.rs index 7ce8044..b55ab6c 100644 --- a/src/dto/request/hackathon_2024/team.rs +++ b/src/dto/request/hackathon_2024/team.rs @@ -1,4 +1,5 @@ use crate::diesel::models::hackathon_2024::category::HackathonCategory2024Enum; +use crate::diesel::models::hackathon_2024::team::HackathonTeam2024Insertable; use serde::Deserialize; #[derive(Deserialize)] @@ -14,3 +15,5 @@ pub struct TeamUpdateData { pub category: HackathonCategory2024Enum, pub nickname_tg: String, } +#[derive(Debug, Deserialize)] +pub struct TeamCreateData(pub HackathonTeam2024Insertable); diff --git a/src/dto/response/hackathon_2024/mod.rs b/src/dto/response/hackathon_2024/mod.rs index 2de672d..18a8dfe 100644 --- a/src/dto/response/hackathon_2024/mod.rs +++ b/src/dto/response/hackathon_2024/mod.rs @@ -1,2 +1,3 @@ +pub mod team; pub mod university; pub mod user; diff --git a/src/dto/response/hackathon_2024/team.rs b/src/dto/response/hackathon_2024/team.rs new file mode 100644 index 0000000..cb4cd6c --- /dev/null +++ b/src/dto/response/hackathon_2024/team.rs @@ -0,0 +1,7 @@ +#[derive(serde::Serialize)] +pub struct Team(pub crate::diesel::models::hackathon_2024::team::HackathonTeam2024Queryable); + +#[derive(serde::Serialize)] +pub struct VecTeam( + pub Vec, +); diff --git a/src/server.rs b/src/server.rs index b3e27dd..4683702 100644 --- a/src/server.rs +++ b/src/server.rs @@ -42,7 +42,7 @@ impl Server { } fn configure_cors() -> Cors { - let exact = &[&format!("https://{}", "your_main_url.com")]; + let exact = &[&format!("https://{}", EnvConfiguration::get().main_url)]; CorsOptions { allowed_origins: AllowedOrigins::some_exact(exact), allowed_methods: vec!["GET", "POST", "PUT", "DELETE"] @@ -68,7 +68,6 @@ impl Server { api::test::get::ping, // /hackathon_2024/user/* api::hackathon_2024::user::post::registration_by_tg, - api::hackathon_2024::user::get::confirm_new_user, api::hackathon_2024::user::get::all, api::hackathon_2024::user::put::by_id, api::hackathon_2024::user::delete::by_id, diff --git a/src/utils/env_configuration.rs b/src/utils/env_configuration.rs index 9383380..35e04dc 100644 --- a/src/utils/env_configuration.rs +++ b/src/utils/env_configuration.rs @@ -43,7 +43,7 @@ impl EnvConfiguration { .parse() .expect("Invalid DATABASE_PORT"), main_url: EnvConfiguration::unwrap_env( - "DATABASE_PASSWORD", + "MAIN_URL", Some("http://localhost:3000".to_owned()), ), server_port: EnvConfiguration::unwrap_env("SERVER_PORT", Some(8080.to_string())) diff --git a/src/utils/prelude_api.rs b/src/utils/prelude_api.rs index 1dfdd21..fe8a534 100644 --- a/src/utils/prelude_api.rs +++ b/src/utils/prelude_api.rs @@ -1,4 +1,6 @@ pub use crate::diesel::prelude::DbState; pub use crate::error::api_error::ApiError; +#[allow(unused_imports)] +pub use crate::utils::env_configuration::EnvConfiguration; pub use log::info; pub use rocket::serde::json::Json; diff --git a/src/utils/validation/validation_string.rs b/src/utils/validation/validation_string.rs index a3e6c81..22166a4 100644 --- a/src/utils/validation/validation_string.rs +++ b/src/utils/validation/validation_string.rs @@ -37,7 +37,7 @@ impl> Validate for T { } fn is_nickname_tg(&self) -> bool { - match Regex::new(r"(?i)^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$") { + match Regex::new(r"^[a-zA-Z0-9](?:[a-zA-Z0-9_]{3,30}[a-zA-Z0-9])?$") { Ok(nickname_regex) => nickname_regex.is_match(self.as_ref()), Err(_) => false, }