Skip to content

Commit 64ba32b

Browse files
authored
Merge pull request #14 from QuantGeekDev/feature/add-pms
Feature/add pms
2 parents 9791414 + c577fc0 commit 64ba32b

File tree

13 files changed

+276
-32
lines changed

13 files changed

+276
-32
lines changed

Makefile

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,11 @@ clean:
2121
cargo clean
2222

2323
db:
24-
docker-compose up -d
24+
docker compose up -d
25+
@sleep 3
2526

2627
db-stop:
27-
docker-compose down
28+
docker compose down
2829

2930
db-setup:
3031
diesel setup
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
ALTER TABLE users DROP CONSTRAINT valid_role;
2+
ALTER TABLE users ADD CONSTRAINT valid_role
3+
CHECK (role IN ('user', 'admin'));
4+
5+
UPDATE users SET role = 'user' WHERE role = 'developer';
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
ALTER TABLE users DROP CONSTRAINT valid_role;
2+
ALTER TABLE users ADD CONSTRAINT valid_role
3+
CHECK (role IN ('admin', 'project_manager', 'developer'));
4+
5+
UPDATE users SET role = 'developer' WHERE role = 'user';
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
DROP TABLE dev_pm_relationships;
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
CREATE TABLE dev_pm_relationships (
2+
id SERIAL PRIMARY KEY,
3+
developer_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
4+
project_manager_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
5+
status VARCHAR NOT NULL CHECK (status IN ('pending', 'accepted', 'rejected')),
6+
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
7+
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
8+
);
9+
10+
CREATE INDEX idx_dev_pm_developer ON dev_pm_relationships(developer_id);
11+
CREATE INDEX idx_dev_pm_manager ON dev_pm_relationships(project_manager_id);
12+
CREATE INDEX idx_dev_pm_status ON dev_pm_relationships(status);
13+
14+
CREATE UNIQUE INDEX idx_unique_dev_pm_relationship
15+
ON dev_pm_relationships(developer_id, project_manager_id)
16+
WHERE status != 'rejected';
17+
18+
SELECT diesel_manage_updated_at('dev_pm_relationships');

src/main.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ mod db;
99
mod schema;
1010

1111
use crate::routes::auth::{login, register};
12-
use crate::routes::snack::{create_snack, delete_snack, list_snacks, update_snack};
12+
use crate::routes::relationship::{invite_project_manager, list_developers, list_snacks, respond_to_invite};
13+
use crate::routes::snack::{create_snack, delete_snack, update_snack};
1314
use dotenv::dotenv;
1415
use rocket::*;
1516

@@ -29,7 +30,7 @@ fn index() -> &'static str {
2930
fn rocket() -> _ {
3031
dotenv().ok();
3132

32-
rocket::build().mount("/", routes![index, create_snack, list_snacks, update_snack, delete_snack, register, login]).register("/", catchers![catchers::unauthorized, catchers::not_found,
33+
rocket::build().mount("/", routes![index, invite_project_manager,list_developers, respond_to_invite, create_snack, list_snacks, update_snack, delete_snack, register, login]).register("/", catchers![catchers::unauthorized, catchers::not_found,
3334
catchers::internal_server_error])
3435
}
3536

src/models/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
pub mod snack;
2-
pub(crate) mod user;
2+
pub(crate) mod user;
3+
pub(crate) mod relationship;

src/models/relationship.rs

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// src/models/relationship.rs
2+
use crate::models::user::User;
3+
use chrono::NaiveDateTime;
4+
use diesel::prelude::*;
5+
use serde::{Deserialize, Serialize};
6+
use diesel::pg::Pg;
7+
use crate::schema::dev_pm_relationships;
8+
use crate::schema::dev_pm_relationships::dsl;
9+
10+
#[derive(Queryable, Selectable, Serialize, Identifiable, Associations, Debug)]
11+
#[diesel(belongs_to(User, foreign_key = developer_id))]
12+
#[diesel(table_name = crate::schema::dev_pm_relationships)]
13+
pub struct DevPmRelationship {
14+
pub id: i32,
15+
pub developer_id: i32,
16+
pub project_manager_id: i32,
17+
pub status: String,
18+
pub created_at: NaiveDateTime,
19+
pub updated_at: NaiveDateTime,
20+
}
21+
22+
#[derive(Insertable)]
23+
#[diesel(table_name = crate::schema::dev_pm_relationships)]
24+
pub struct NewDevPmRelationship {
25+
pub developer_id: i32,
26+
pub project_manager_id: i32,
27+
pub status: String,
28+
}
29+
30+
#[derive(Deserialize)]
31+
pub struct InvitePmRequest {
32+
pub project_manager_id: i32,
33+
}
34+
35+
#[derive(Deserialize)]
36+
pub struct RespondToInviteRequest {
37+
pub status: String,
38+
}
39+
40+
// Query builders helper methods
41+
impl DevPmRelationship {
42+
pub fn for_developer(user_id: i32) -> dev_pm_relationships::BoxedQuery<'static, Pg> {
43+
use crate::schema::dev_pm_relationships::dsl::*;
44+
45+
dev_pm_relationships
46+
.filter(developer_id.eq(user_id))
47+
.into_boxed()
48+
}
49+
50+
pub fn for_project_manager(user_id: i32) -> dev_pm_relationships::BoxedQuery<'static, Pg> {
51+
use crate::schema::dev_pm_relationships::dsl::*;
52+
53+
dev_pm_relationships
54+
.filter(project_manager_id.eq(user_id))
55+
.into_boxed()
56+
}
57+
58+
pub fn pending() -> dev_pm_relationships::BoxedQuery<'static, Pg> {
59+
use crate::schema::dev_pm_relationships::dsl::*;
60+
61+
dev_pm_relationships
62+
.filter(status.eq("pending"))
63+
.into_boxed()
64+
}
65+
66+
pub fn accepted() -> dev_pm_relationships::BoxedQuery<'static, Pg> {
67+
use crate::schema::dev_pm_relationships::dsl::*;
68+
69+
dev_pm_relationships
70+
.filter(status.eq("accepted"))
71+
.into_boxed()
72+
}
73+
}

src/routes/auth.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,20 @@ use jsonwebtoken::{encode, EncodingKey, Header};
88
use rocket::http::Status;
99
use rocket::serde::json::Json;
1010
use serde::{Deserialize, Serialize};
11+
1112
#[derive(Deserialize)]
1213
pub struct RegisterInfo {
1314
username: String,
1415
password: String,
16+
role: Option<String>,
1517
}
1618

1719
#[derive(Deserialize)]
1820
pub struct LoginInfo {
1921
username: String,
2022
password: String,
2123
}
24+
2225
#[derive(Serialize)]
2326
pub struct TokenResponse {
2427
token: String,
@@ -30,10 +33,16 @@ pub fn register(info: Json<RegisterInfo>) -> Result<Json<User>, Status> {
3033
let hashed_password = hash(&info.password, DEFAULT_COST)
3134
.map_err(|_| Status::InternalServerError)?;
3235

36+
let user_role = match info.role.as_deref() {
37+
Some("developer") => "developer",
38+
Some("project_manager") => "project_manager",
39+
_ => "developer"
40+
}.to_string();
41+
3342
let new_user = NewUser {
3443
username: info.username.clone(),
3544
password_hash: hashed_password,
36-
role: "user".to_string(),
45+
role: user_role,
3746
};
3847

3948
diesel::insert_into(users)
@@ -66,4 +75,4 @@ pub fn login(info: Json<LoginInfo>) -> Result<Json<TokenResponse>, Status> {
6675
} else {
6776
Err(Status::Unauthorized)
6877
}
69-
}
78+
}

src/routes/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
pub mod snack;
2-
pub mod auth;
2+
pub mod auth;
3+
pub mod relationship;

0 commit comments

Comments
 (0)