diff --git a/jirs-server/migrations/2020-04-16-123403_add_bind_token/down.sql b/jirs-server/migrations/2020-04-16-123403_add_bind_token/down.sql new file mode 100644 index 00000000..764b8a62 --- /dev/null +++ b/jirs-server/migrations/2020-04-16-123403_add_bind_token/down.sql @@ -0,0 +1 @@ +ALTER TABLE tokens DROP COLUMN bind_token; diff --git a/jirs-server/migrations/2020-04-16-123403_add_bind_token/up.sql b/jirs-server/migrations/2020-04-16-123403_add_bind_token/up.sql new file mode 100644 index 00000000..ea20d0cf --- /dev/null +++ b/jirs-server/migrations/2020-04-16-123403_add_bind_token/up.sql @@ -0,0 +1 @@ +ALTER TABLE tokens ADD COLUMN bind_token UUID; diff --git a/jirs-server/src/db/mod.rs b/jirs-server/src/db/mod.rs index 9ec61e35..da75f843 100644 --- a/jirs-server/src/db/mod.rs +++ b/jirs-server/src/db/mod.rs @@ -11,6 +11,7 @@ pub mod comments; pub mod issue_assignees; pub mod issues; pub mod projects; +pub mod tokens; pub mod users; #[cfg(debug_assertions)] diff --git a/jirs-server/src/db/tokens.rs b/jirs-server/src/db/tokens.rs new file mode 100644 index 00000000..8d082282 --- /dev/null +++ b/jirs-server/src/db/tokens.rs @@ -0,0 +1,58 @@ +use actix::{Handler, Message}; +use diesel::prelude::*; +use serde::{Deserialize, Serialize}; +use uuid::Uuid; + +use jirs_data::UserId; + +use crate::db::DbExecutor; +use crate::errors::ServiceErrors; + +#[derive(Serialize, Deserialize, Debug)] +pub struct FindBindToken { + pub token: Uuid, +} + +impl Message for FindBindToken { + type Result = Result; +} + +impl Handler for DbExecutor { + type Result = Result; + + fn handle(&mut self, msg: FindBindToken, _: &mut Self::Context) -> Self::Result { + use crate::schema::tokens::dsl::{bind_token, tokens}; + let conn = &self + .0 + .get() + .map_err(|_| ServiceErrors::DatabaseConnectionLost)?; + + let token: crate::models::Token = tokens + .filter(bind_token.eq(msg.token)) + .first(conn) + .map_err(|_e| { + ServiceErrors::RecordNotFound(format!("token for {}", msg.access_token)) + })?; + } +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct CreateBindToken { + pub user_id: UserId, +} + +impl Message for CreateBindToken { + type Result = Result; +} + +impl Handler for DbExecutor { + type Result = Result; + + fn handle(&mut self, msg: CreateBindToken, _: &mut Self::Context) -> Self::Result { + use crate::schema::tokens::dsl::{access_token, tokens}; + let conn = &self + .0 + .get() + .map_err(|_| ServiceErrors::DatabaseConnectionLost)?; + } +} diff --git a/jirs-server/src/models.rs b/jirs-server/src/models.rs index ed9a1084..c30f0c1e 100644 --- a/jirs-server/src/models.rs +++ b/jirs-server/src/models.rs @@ -1,238 +1,239 @@ -use chrono::NaiveDateTime; -use serde::{Deserialize, Serialize}; -use uuid::Uuid; - -use jirs_data::{IssuePriority, IssueStatus, IssueType, ProjectCategory}; - -use crate::schema::*; - -#[derive(Debug, Serialize, Deserialize, Queryable)] -#[serde(rename_all = "camelCase")] -pub struct Comment { - pub id: i32, - pub body: String, - pub user_id: i32, - pub issue_id: i32, - pub created_at: NaiveDateTime, - pub updated_at: NaiveDateTime, -} - -impl Into for Comment { - fn into(self) -> jirs_data::Comment { - jirs_data::Comment { - id: self.id, - body: self.body, - user_id: self.user_id, - issue_id: self.issue_id, - created_at: self.created_at, - updated_at: self.updated_at, - } - } -} - -#[derive(Debug, Serialize, Deserialize, Insertable)] -#[serde(rename_all = "camelCase")] -#[table_name = "comments"] -pub struct CommentForm { - pub body: String, - pub user_id: i32, - pub issue_id: i32, -} - -#[derive(Debug, Serialize, Deserialize, Queryable)] -#[serde(rename_all = "camelCase")] -pub struct Issue { - pub id: i32, - pub title: String, - #[serde(rename = "type")] - pub issue_type: IssueType, - pub status: IssueStatus, - pub priority: IssuePriority, - pub list_position: i32, - pub description: Option, - pub description_text: Option, - pub estimate: Option, - pub time_spent: Option, - pub time_remaining: Option, - pub reporter_id: i32, - pub project_id: i32, - pub created_at: NaiveDateTime, - pub updated_at: NaiveDateTime, -} - -impl Into for Issue { - fn into(self) -> jirs_data::Issue { - jirs_data::Issue { - id: self.id, - title: self.title, - issue_type: self.issue_type, - status: self.status, - priority: self.priority, - list_position: self.list_position, - description: self.description, - description_text: self.description_text, - estimate: self.estimate, - time_spent: self.time_spent, - time_remaining: self.time_remaining, - reporter_id: self.reporter_id, - project_id: self.project_id, - created_at: self.created_at, - updated_at: self.updated_at, - - user_ids: vec![], - } - } -} - -#[derive(Debug, Serialize, Deserialize, Insertable)] -#[serde(rename_all = "camelCase")] -#[table_name = "issues"] -pub struct CreateIssueForm { - pub title: String, - #[serde(rename = "type")] - pub issue_type: IssueType, - pub status: IssueStatus, - pub priority: IssuePriority, - pub list_position: i32, - pub description: Option, - pub description_text: Option, - pub estimate: Option, - pub time_spent: Option, - pub time_remaining: Option, - pub reporter_id: i32, - pub project_id: i32, -} - -#[derive(Debug, Serialize, Deserialize, Queryable)] -pub struct IssueAssignee { - pub id: i32, - pub issue_id: i32, - pub user_id: i32, - pub created_at: NaiveDateTime, - pub updated_at: NaiveDateTime, -} - -#[derive(Debug, Serialize, Deserialize, Insertable)] -#[serde(rename_all = "camelCase")] -#[table_name = "issue_assignees"] -pub struct CreateIssueAssigneeForm { - pub issue_id: i32, - pub user_id: i32, -} - -#[derive(Debug, Serialize, Deserialize, Queryable)] -#[serde(rename_all = "camelCase")] -pub struct Project { - pub id: i32, - pub name: String, - pub url: String, - pub description: String, - pub category: ProjectCategory, - pub created_at: NaiveDateTime, - pub updated_at: NaiveDateTime, -} - -impl Into for Project { - fn into(self) -> jirs_data::Project { - jirs_data::Project { - id: self.id, - name: self.name, - url: self.url, - description: self.description, - category: self.category, - created_at: self.created_at, - updated_at: self.updated_at, - } - } -} - -#[derive(Debug, Serialize, Deserialize, Insertable)] -#[table_name = "projects"] -pub struct UpdateProjectForm { - pub name: Option, - pub url: Option, - pub description: Option, - pub category: Option, -} - -#[derive(Debug, Serialize, Deserialize, Queryable)] -pub struct User { - pub id: i32, - pub name: String, - pub email: String, - pub avatar_url: Option, - pub project_id: i32, - pub created_at: NaiveDateTime, - pub updated_at: NaiveDateTime, -} - -impl Into for User { - fn into(self) -> jirs_data::User { - jirs_data::User { - id: self.id, - name: self.name, - email: self.email, - avatar_url: self.avatar_url, - project_id: self.project_id, - created_at: self.created_at, - updated_at: self.updated_at, - } - } -} - -impl Into for &User { - fn into(self) -> jirs_data::User { - jirs_data::User { - id: self.id, - name: self.name.clone(), - email: self.email.clone(), - avatar_url: self.avatar_url.clone(), - project_id: self.project_id, - created_at: self.created_at, - updated_at: self.updated_at, - } - } -} - -#[derive(Debug, Serialize, Deserialize, Insertable)] -#[serde(rename_all = "camelCase")] -#[table_name = "users"] -pub struct UserForm { - pub name: String, - pub email: String, - pub avatar_url: Option, - pub project_id: Option, -} - -#[derive(Debug, Serialize, Deserialize, Queryable)] -#[serde(rename_all = "camelCase")] -pub struct Token { - pub id: i32, - pub user_id: i32, - pub access_token: Uuid, - pub refresh_token: Uuid, - pub created_at: NaiveDateTime, - pub updated_at: NaiveDateTime, -} - -impl Into for Token { - fn into(self) -> jirs_data::Token { - jirs_data::Token { - id: self.id, - user_id: self.user_id, - access_token: self.access_token, - refresh_token: self.refresh_token, - created_at: self.created_at, - updated_at: self.updated_at, - } - } -} - -#[derive(Debug, Serialize, Deserialize, Insertable)] -#[serde(rename_all = "camelCase")] -#[table_name = "tokens"] -pub struct TokenForm { - pub user_id: i32, - pub access_token: Uuid, - pub refresh_token: Uuid, -} +use chrono::NaiveDateTime; +use serde::{Deserialize, Serialize}; +use uuid::Uuid; + +use jirs_data::{IssuePriority, IssueStatus, IssueType, ProjectCategory}; + +use crate::schema::*; + +#[derive(Debug, Serialize, Deserialize, Queryable)] +#[serde(rename_all = "camelCase")] +pub struct Comment { + pub id: i32, + pub body: String, + pub user_id: i32, + pub issue_id: i32, + pub created_at: NaiveDateTime, + pub updated_at: NaiveDateTime, +} + +impl Into for Comment { + fn into(self) -> jirs_data::Comment { + jirs_data::Comment { + id: self.id, + body: self.body, + user_id: self.user_id, + issue_id: self.issue_id, + created_at: self.created_at, + updated_at: self.updated_at, + } + } +} + +#[derive(Debug, Serialize, Deserialize, Insertable)] +#[serde(rename_all = "camelCase")] +#[table_name = "comments"] +pub struct CommentForm { + pub body: String, + pub user_id: i32, + pub issue_id: i32, +} + +#[derive(Debug, Serialize, Deserialize, Queryable)] +#[serde(rename_all = "camelCase")] +pub struct Issue { + pub id: i32, + pub title: String, + #[serde(rename = "type")] + pub issue_type: IssueType, + pub status: IssueStatus, + pub priority: IssuePriority, + pub list_position: i32, + pub description: Option, + pub description_text: Option, + pub estimate: Option, + pub time_spent: Option, + pub time_remaining: Option, + pub reporter_id: i32, + pub project_id: i32, + pub created_at: NaiveDateTime, + pub updated_at: NaiveDateTime, +} + +impl Into for Issue { + fn into(self) -> jirs_data::Issue { + jirs_data::Issue { + id: self.id, + title: self.title, + issue_type: self.issue_type, + status: self.status, + priority: self.priority, + list_position: self.list_position, + description: self.description, + description_text: self.description_text, + estimate: self.estimate, + time_spent: self.time_spent, + time_remaining: self.time_remaining, + reporter_id: self.reporter_id, + project_id: self.project_id, + created_at: self.created_at, + updated_at: self.updated_at, + + user_ids: vec![], + } + } +} + +#[derive(Debug, Serialize, Deserialize, Insertable)] +#[serde(rename_all = "camelCase")] +#[table_name = "issues"] +pub struct CreateIssueForm { + pub title: String, + #[serde(rename = "type")] + pub issue_type: IssueType, + pub status: IssueStatus, + pub priority: IssuePriority, + pub list_position: i32, + pub description: Option, + pub description_text: Option, + pub estimate: Option, + pub time_spent: Option, + pub time_remaining: Option, + pub reporter_id: i32, + pub project_id: i32, +} + +#[derive(Debug, Serialize, Deserialize, Queryable)] +pub struct IssueAssignee { + pub id: i32, + pub issue_id: i32, + pub user_id: i32, + pub created_at: NaiveDateTime, + pub updated_at: NaiveDateTime, +} + +#[derive(Debug, Serialize, Deserialize, Insertable)] +#[serde(rename_all = "camelCase")] +#[table_name = "issue_assignees"] +pub struct CreateIssueAssigneeForm { + pub issue_id: i32, + pub user_id: i32, +} + +#[derive(Debug, Serialize, Deserialize, Queryable)] +#[serde(rename_all = "camelCase")] +pub struct Project { + pub id: i32, + pub name: String, + pub url: String, + pub description: String, + pub category: ProjectCategory, + pub created_at: NaiveDateTime, + pub updated_at: NaiveDateTime, +} + +impl Into for Project { + fn into(self) -> jirs_data::Project { + jirs_data::Project { + id: self.id, + name: self.name, + url: self.url, + description: self.description, + category: self.category, + created_at: self.created_at, + updated_at: self.updated_at, + } + } +} + +#[derive(Debug, Serialize, Deserialize, Insertable)] +#[table_name = "projects"] +pub struct UpdateProjectForm { + pub name: Option, + pub url: Option, + pub description: Option, + pub category: Option, +} + +#[derive(Debug, Serialize, Deserialize, Queryable)] +pub struct User { + pub id: i32, + pub name: String, + pub email: String, + pub avatar_url: Option, + pub project_id: i32, + pub created_at: NaiveDateTime, + pub updated_at: NaiveDateTime, +} + +impl Into for User { + fn into(self) -> jirs_data::User { + jirs_data::User { + id: self.id, + name: self.name, + email: self.email, + avatar_url: self.avatar_url, + project_id: self.project_id, + created_at: self.created_at, + updated_at: self.updated_at, + } + } +} + +impl Into for &User { + fn into(self) -> jirs_data::User { + jirs_data::User { + id: self.id, + name: self.name.clone(), + email: self.email.clone(), + avatar_url: self.avatar_url.clone(), + project_id: self.project_id, + created_at: self.created_at, + updated_at: self.updated_at, + } + } +} + +#[derive(Debug, Serialize, Deserialize, Insertable)] +#[serde(rename_all = "camelCase")] +#[table_name = "users"] +pub struct UserForm { + pub name: String, + pub email: String, + pub avatar_url: Option, + pub project_id: Option, +} + +#[derive(Debug, Serialize, Deserialize, Queryable)] +#[serde(rename_all = "camelCase")] +pub struct Token { + pub id: i32, + pub user_id: i32, + pub access_token: Uuid, + pub refresh_token: Uuid, + pub created_at: NaiveDateTime, + pub updated_at: NaiveDateTime, + pub bind_token: Option, +} + +impl Into for Token { + fn into(self) -> jirs_data::Token { + jirs_data::Token { + id: self.id, + user_id: self.user_id, + access_token: self.access_token, + refresh_token: self.refresh_token, + created_at: self.created_at, + updated_at: self.updated_at, + } + } +} + +#[derive(Debug, Serialize, Deserialize, Insertable)] +#[serde(rename_all = "camelCase")] +#[table_name = "tokens"] +pub struct TokenForm { + pub user_id: i32, + pub access_token: Uuid, + pub refresh_token: Uuid, +} diff --git a/jirs-server/src/schema.rs b/jirs-server/src/schema.rs index 3b9c1dca..e4d02828 100644 --- a/jirs-server/src/schema.rs +++ b/jirs-server/src/schema.rs @@ -286,6 +286,12 @@ table! { /// /// (Automatically generated by Diesel.) updated_at -> Timestamp, + /// The `bind_token` column of the `tokens` table. + /// + /// Its SQL type is `Nullable`. + /// + /// (Automatically generated by Diesel.) + bind_token -> Nullable, } }