Add first routes for accounts management
This commit is contained in:
parent
03f57a0ad7
commit
72e67d9e91
@ -1,6 +1,6 @@
|
|||||||
DROP TABLE IF EXISTS inbox;
|
DROP TABLE IF EXISTS inbox;
|
||||||
DROP TABLE IF EXISTS movement;
|
DROP TABLE IF EXISTS movements;
|
||||||
DROP TABLE IF EXISTS account;
|
DROP TABLE IF EXISTS accounts;
|
||||||
DROP TABLE IF EXISTS attachment;
|
DROP TABLE IF EXISTS attachments;
|
||||||
DROP TABLE IF EXISTS token;
|
DROP TABLE IF EXISTS tokens;
|
||||||
DROP TABLE IF EXISTS users;
|
DROP TABLE IF EXISTS users;
|
@ -7,7 +7,7 @@ CREATE TABLE users
|
|||||||
time_update BIGINT NOT NULL
|
time_update BIGINT NOT NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE token
|
CREATE TABLE tokens
|
||||||
(
|
(
|
||||||
id SERIAL PRIMARY KEY,
|
id SERIAL PRIMARY KEY,
|
||||||
name VARCHAR(150) NOT NULL,
|
name VARCHAR(150) NOT NULL,
|
||||||
@ -25,7 +25,7 @@ CREATE TABLE token
|
|||||||
right_auth BOOLEAN NOT NULL DEFAULT false
|
right_auth BOOLEAN NOT NULL DEFAULT false
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE attachment
|
CREATE TABLE attachments
|
||||||
(
|
(
|
||||||
id SERIAL PRIMARY KEY,
|
id SERIAL PRIMARY KEY,
|
||||||
time_create BIGINT NOT NULL,
|
time_create BIGINT NOT NULL,
|
||||||
@ -35,7 +35,7 @@ CREATE TABLE attachment
|
|||||||
user_id INTEGER NOT NULL REFERENCES users ON DELETE SET NULL
|
user_id INTEGER NOT NULL REFERENCES users ON DELETE SET NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE account
|
CREATE TABLE accounts
|
||||||
(
|
(
|
||||||
id SERIAL PRIMARY KEY,
|
id SERIAL PRIMARY KEY,
|
||||||
name VARCHAR(50) NOT NULL,
|
name VARCHAR(50) NOT NULL,
|
||||||
@ -45,13 +45,13 @@ CREATE TABLE account
|
|||||||
default_account BOOLEAN NOT NULL DEFAULT false
|
default_account BOOLEAN NOT NULL DEFAULT false
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE movement
|
CREATE TABLE movements
|
||||||
(
|
(
|
||||||
id SERIAL PRIMARY KEY,
|
id SERIAL PRIMARY KEY,
|
||||||
account_id INTEGER NOT NULL REFERENCES account ON DELETE CASCADE,
|
account_id INTEGER NOT NULL REFERENCES accounts ON DELETE CASCADE,
|
||||||
time BIGINT NOT NULL,
|
time BIGINT NOT NULL,
|
||||||
label VARCHAR(200) NOT NULL,
|
label VARCHAR(200) NOT NULL,
|
||||||
attachment_id INT REFERENCES attachment ON DELETE SET NULL,
|
attachment_id INT REFERENCES attachments ON DELETE SET NULL,
|
||||||
amount REAL NOT NULL,
|
amount REAL NOT NULL,
|
||||||
checked BOOLEAN NOT NULL DEFAULT false,
|
checked BOOLEAN NOT NULL DEFAULT false,
|
||||||
time_create BIGINT NOT NULL,
|
time_create BIGINT NOT NULL,
|
||||||
@ -61,9 +61,9 @@ CREATE TABLE movement
|
|||||||
CREATE TABLE inbox
|
CREATE TABLE inbox
|
||||||
(
|
(
|
||||||
id SERIAL PRIMARY KEY,
|
id SERIAL PRIMARY KEY,
|
||||||
attachment_id INTEGER NOT NULL REFERENCES attachment ON DELETE CASCADE,
|
attachment_id INTEGER NOT NULL REFERENCES attachments ON DELETE CASCADE,
|
||||||
user_id INTEGER NOT NULL REFERENCES users ON DELETE CASCADE,
|
user_id INTEGER NOT NULL REFERENCES users ON DELETE CASCADE,
|
||||||
account_id INTEGER REFERENCES account ON DELETE CASCADE,
|
account_id INTEGER REFERENCES accounts ON DELETE CASCADE,
|
||||||
time_create BIGINT NOT NULL,
|
time_create BIGINT NOT NULL,
|
||||||
time_update BIGINT NOT NULL
|
time_update BIGINT NOT NULL
|
||||||
);
|
);
|
35
moneymgr_backend/src/controllers/accounts_controller.rs
Normal file
35
moneymgr_backend/src/controllers/accounts_controller.rs
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
use crate::controllers::HttpResult;
|
||||||
|
use crate::controllers::server_controller::ServerConstraints;
|
||||||
|
use crate::extractors::auth_extractor::AuthExtractor;
|
||||||
|
use crate::services::accounts_service;
|
||||||
|
use crate::services::accounts_service::UpdateAccountQuery;
|
||||||
|
use actix_web::{HttpResponse, web};
|
||||||
|
|
||||||
|
#[derive(serde::Deserialize)]
|
||||||
|
pub struct CreateAccountRequest {
|
||||||
|
name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a new account
|
||||||
|
pub async fn create(auth: AuthExtractor, req: web::Json<CreateAccountRequest>) -> HttpResult {
|
||||||
|
let constraints = ServerConstraints::default();
|
||||||
|
|
||||||
|
if !constraints.account_name.check_str(&req.name) {
|
||||||
|
return Ok(HttpResponse::BadRequest().json("Invalid account name length!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
accounts_service::create(
|
||||||
|
auth.user_id(),
|
||||||
|
&UpdateAccountQuery {
|
||||||
|
name: req.name.clone(),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(HttpResponse::Created().finish())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the list of accounts of the user
|
||||||
|
pub async fn get_list(auth: AuthExtractor) -> HttpResult {
|
||||||
|
Ok(HttpResponse::Ok().json(accounts_service::get_list_user(auth.user_id()).await?))
|
||||||
|
}
|
@ -2,6 +2,7 @@ use actix_web::http::StatusCode;
|
|||||||
use actix_web::{HttpResponse, ResponseError};
|
use actix_web::{HttpResponse, ResponseError};
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
|
||||||
|
pub mod accounts_controller;
|
||||||
pub mod auth_controller;
|
pub mod auth_controller;
|
||||||
pub mod server_controller;
|
pub mod server_controller;
|
||||||
pub mod static_controller;
|
pub mod static_controller;
|
||||||
|
@ -39,6 +39,7 @@ pub struct ServerConstraints {
|
|||||||
pub token_name: LenConstraints,
|
pub token_name: LenConstraints,
|
||||||
pub token_ip_net: LenConstraints,
|
pub token_ip_net: LenConstraints,
|
||||||
pub token_max_inactivity: LenConstraints,
|
pub token_max_inactivity: LenConstraints,
|
||||||
|
pub account_name: LenConstraints,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for ServerConstraints {
|
impl Default for ServerConstraints {
|
||||||
@ -47,6 +48,7 @@ impl Default for ServerConstraints {
|
|||||||
token_name: LenConstraints::new(5, 255),
|
token_name: LenConstraints::new(5, 255),
|
||||||
token_ip_net: LenConstraints::max_only(44),
|
token_ip_net: LenConstraints::max_only(44),
|
||||||
token_max_inactivity: LenConstraints::new(3600, 3600 * 24 * 365),
|
token_max_inactivity: LenConstraints::new(3600, 3600 * 24 * 365),
|
||||||
|
account_name: LenConstraints::not_empty(50),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -141,10 +141,10 @@ impl FromRequest for AuthExtractor {
|
|||||||
|
|
||||||
// Check for authorization
|
// Check for authorization
|
||||||
let uri = req.uri().to_string();
|
let uri = req.uri().to_string();
|
||||||
let authorized = (uri.starts_with("/api/account/") && token.right_account)
|
let authorized = (uri.starts_with("/api/accounts/") && token.right_account)
|
||||||
|| (uri.starts_with("/api/movement/") && token.right_movement)
|
|| (uri.starts_with("/api/movements/") && token.right_movement)
|
||||||
|| (uri.starts_with("/api/inbox/") && token.right_inbox)
|
|| (uri.starts_with("/api/inbox/") && token.right_inbox)
|
||||||
|| (uri.starts_with("/api/attachment/") && token.right_attachment)
|
|| (uri.starts_with("/api/attachments/") && token.right_attachment)
|
||||||
|| (uri.starts_with("/api/auth/") && token.right_auth);
|
|| (uri.starts_with("/api/auth/") && token.right_auth);
|
||||||
|
|
||||||
if !authorized {
|
if !authorized {
|
||||||
|
@ -100,6 +100,19 @@ async fn main() -> std::io::Result<()> {
|
|||||||
"/api/tokens/{id}",
|
"/api/tokens/{id}",
|
||||||
web::delete().to(tokens_controller::delete),
|
web::delete().to(tokens_controller::delete),
|
||||||
)
|
)
|
||||||
|
// Accounts controller
|
||||||
|
.route("/api/accounts", web::post().to(accounts_controller::create))
|
||||||
|
.route(
|
||||||
|
"/api/accounts/list",
|
||||||
|
web::get().to(accounts_controller::get_list),
|
||||||
|
)
|
||||||
|
// TODO : update account
|
||||||
|
//TODO
|
||||||
|
/*.route(
|
||||||
|
"/api/accounts/{id}",
|
||||||
|
web::delete().to(accounts_controller::delete),
|
||||||
|
)*/
|
||||||
|
// TODO : set as default
|
||||||
// Static assets
|
// Static assets
|
||||||
.route("/", web::get().to(static_controller::root_index))
|
.route("/", web::get().to(static_controller::root_index))
|
||||||
.route(
|
.route(
|
||||||
|
35
moneymgr_backend/src/models/accounts.rs
Normal file
35
moneymgr_backend/src/models/accounts.rs
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
use crate::models::users::UserID;
|
||||||
|
use crate::schema::*;
|
||||||
|
use diesel::prelude::*;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, serde::Serialize, serde::Deserialize, PartialEq, Eq)]
|
||||||
|
pub struct AccountID(pub i32);
|
||||||
|
|
||||||
|
#[derive(Queryable, Debug, Clone, serde::Serialize)]
|
||||||
|
pub struct Account {
|
||||||
|
id: i32,
|
||||||
|
pub name: String,
|
||||||
|
user_id: i32,
|
||||||
|
pub time_create: i64,
|
||||||
|
pub time_update: i64,
|
||||||
|
pub default_account: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Account {
|
||||||
|
pub fn id(&self) -> AccountID {
|
||||||
|
AccountID(self.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn user_id(&self) -> UserID {
|
||||||
|
UserID(self.user_id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Insertable)]
|
||||||
|
#[diesel(table_name = accounts)]
|
||||||
|
pub struct NewAccount<'a> {
|
||||||
|
pub name: &'a str,
|
||||||
|
pub user_id: i32,
|
||||||
|
pub time_create: i64,
|
||||||
|
pub time_update: i64,
|
||||||
|
}
|
@ -1,2 +1,3 @@
|
|||||||
|
pub mod accounts;
|
||||||
pub mod tokens;
|
pub mod tokens;
|
||||||
pub mod users;
|
pub mod users;
|
||||||
|
@ -63,7 +63,7 @@ impl Token {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Insertable)]
|
#[derive(Insertable)]
|
||||||
#[diesel(table_name = token)]
|
#[diesel(table_name = tokens)]
|
||||||
pub struct NewToken<'a> {
|
pub struct NewToken<'a> {
|
||||||
pub name: &'a str,
|
pub name: &'a str,
|
||||||
pub user_id: i32,
|
pub user_id: i32,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// @generated automatically by Diesel CLI.
|
// @generated automatically by Diesel CLI.
|
||||||
|
|
||||||
diesel::table! {
|
diesel::table! {
|
||||||
account (id) {
|
accounts (id) {
|
||||||
id -> Int4,
|
id -> Int4,
|
||||||
#[max_length = 50]
|
#[max_length = 50]
|
||||||
name -> Varchar,
|
name -> Varchar,
|
||||||
@ -13,7 +13,7 @@ diesel::table! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
diesel::table! {
|
diesel::table! {
|
||||||
attachment (id) {
|
attachments (id) {
|
||||||
id -> Int4,
|
id -> Int4,
|
||||||
time_create -> Int8,
|
time_create -> Int8,
|
||||||
#[max_length = 150]
|
#[max_length = 150]
|
||||||
@ -37,7 +37,7 @@ diesel::table! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
diesel::table! {
|
diesel::table! {
|
||||||
movement (id) {
|
movements (id) {
|
||||||
id -> Int4,
|
id -> Int4,
|
||||||
account_id -> Int4,
|
account_id -> Int4,
|
||||||
time -> Int8,
|
time -> Int8,
|
||||||
@ -52,7 +52,7 @@ diesel::table! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
diesel::table! {
|
diesel::table! {
|
||||||
token (id) {
|
tokens (id) {
|
||||||
id -> Int4,
|
id -> Int4,
|
||||||
#[max_length = 150]
|
#[max_length = 150]
|
||||||
name -> Varchar,
|
name -> Varchar,
|
||||||
@ -85,13 +85,20 @@ diesel::table! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
diesel::joinable!(account -> users (user_id));
|
diesel::joinable!(accounts -> users (user_id));
|
||||||
diesel::joinable!(attachment -> users (user_id));
|
diesel::joinable!(attachments -> users (user_id));
|
||||||
diesel::joinable!(inbox -> account (account_id));
|
diesel::joinable!(inbox -> accounts (account_id));
|
||||||
diesel::joinable!(inbox -> attachment (attachment_id));
|
diesel::joinable!(inbox -> attachments (attachment_id));
|
||||||
diesel::joinable!(inbox -> users (user_id));
|
diesel::joinable!(inbox -> users (user_id));
|
||||||
diesel::joinable!(movement -> account (account_id));
|
diesel::joinable!(movements -> accounts (account_id));
|
||||||
diesel::joinable!(movement -> attachment (attachment_id));
|
diesel::joinable!(movements -> attachments (attachment_id));
|
||||||
diesel::joinable!(token -> users (user_id));
|
diesel::joinable!(tokens -> users (user_id));
|
||||||
|
|
||||||
diesel::allow_tables_to_appear_in_same_query!(account, attachment, inbox, movement, token, users,);
|
diesel::allow_tables_to_appear_in_same_query!(
|
||||||
|
accounts,
|
||||||
|
attachments,
|
||||||
|
inbox,
|
||||||
|
movements,
|
||||||
|
tokens,
|
||||||
|
users,
|
||||||
|
);
|
||||||
|
64
moneymgr_backend/src/services/accounts_service.rs
Normal file
64
moneymgr_backend/src/services/accounts_service.rs
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
use crate::connections::db_connection::db;
|
||||||
|
use crate::models::accounts::{Account, AccountID, NewAccount};
|
||||||
|
use crate::models::users::UserID;
|
||||||
|
use crate::schema::accounts;
|
||||||
|
use crate::utils::time_utils::time;
|
||||||
|
use diesel::RunQueryDsl;
|
||||||
|
use diesel::prelude::*;
|
||||||
|
|
||||||
|
#[derive(serde::Deserialize)]
|
||||||
|
pub struct UpdateAccountQuery {
|
||||||
|
pub name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a new account
|
||||||
|
pub async fn create(user_id: UserID, query: &UpdateAccountQuery) -> anyhow::Result<Account> {
|
||||||
|
let new_account = NewAccount {
|
||||||
|
name: query.name.as_str(),
|
||||||
|
user_id: user_id.0,
|
||||||
|
time_create: time() as i64,
|
||||||
|
time_update: time() as i64,
|
||||||
|
};
|
||||||
|
|
||||||
|
let res: Account = diesel::insert_into(accounts::table)
|
||||||
|
.values(&new_account)
|
||||||
|
.get_result(&mut db()?)?;
|
||||||
|
|
||||||
|
update(res.id(), query).await?;
|
||||||
|
|
||||||
|
Ok(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Update an account
|
||||||
|
pub async fn update(id: AccountID, q: &UpdateAccountQuery) -> anyhow::Result<()> {
|
||||||
|
diesel::update(accounts::dsl::accounts.filter(accounts::dsl::id.eq(id.0)))
|
||||||
|
.set((
|
||||||
|
accounts::dsl::time_update.eq(time() as i64),
|
||||||
|
accounts::dsl::name.eq(&q.name),
|
||||||
|
))
|
||||||
|
.execute(&mut db()?)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a single account by its id
|
||||||
|
pub async fn get_by_id(account_id: AccountID) -> anyhow::Result<Account> {
|
||||||
|
Ok(accounts::table
|
||||||
|
.filter(accounts::dsl::id.eq(account_id.0))
|
||||||
|
.get_result(&mut db()?)?)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the accounts of a user
|
||||||
|
pub async fn get_list_user(id: UserID) -> anyhow::Result<Vec<Account>> {
|
||||||
|
Ok(accounts::table
|
||||||
|
.filter(accounts::dsl::user_id.eq(id.0))
|
||||||
|
.get_results(&mut db()?)?)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Delete an account
|
||||||
|
pub async fn delete(id: AccountID) -> anyhow::Result<()> {
|
||||||
|
diesel::delete(accounts::dsl::accounts.filter(accounts::dsl::id.eq(id.0)))
|
||||||
|
.execute(&mut db()?)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
@ -1,2 +1,3 @@
|
|||||||
|
pub mod accounts_service;
|
||||||
pub mod tokens_service;
|
pub mod tokens_service;
|
||||||
pub mod users_service;
|
pub mod users_service;
|
||||||
|
@ -4,7 +4,7 @@ use crate::connections::db_connection::db;
|
|||||||
use crate::constants;
|
use crate::constants;
|
||||||
use crate::models::tokens::{NewToken, Token, TokenID};
|
use crate::models::tokens::{NewToken, Token, TokenID};
|
||||||
use crate::models::users::UserID;
|
use crate::models::users::UserID;
|
||||||
use crate::schema::token;
|
use crate::schema::tokens;
|
||||||
use crate::utils::rand_utils::rand_string;
|
use crate::utils::rand_utils::rand_string;
|
||||||
use crate::utils::time_utils::time;
|
use crate::utils::time_utils::time;
|
||||||
|
|
||||||
@ -41,7 +41,7 @@ pub async fn create(new_token: NewTokenInfo) -> anyhow::Result<Token> {
|
|||||||
right_attachment: new_token.right_attachment,
|
right_attachment: new_token.right_attachment,
|
||||||
};
|
};
|
||||||
|
|
||||||
let res = diesel::insert_into(token::table)
|
let res = diesel::insert_into(tokens::table)
|
||||||
.values(&t)
|
.values(&t)
|
||||||
.get_result(&mut db()?)?;
|
.get_result(&mut db()?)?;
|
||||||
|
|
||||||
@ -50,36 +50,36 @@ pub async fn create(new_token: NewTokenInfo) -> anyhow::Result<Token> {
|
|||||||
|
|
||||||
/// Get a single token by its id
|
/// Get a single token by its id
|
||||||
pub async fn get_by_id(token_id: TokenID) -> anyhow::Result<Token> {
|
pub async fn get_by_id(token_id: TokenID) -> anyhow::Result<Token> {
|
||||||
Ok(token::table
|
Ok(tokens::table
|
||||||
.filter(token::dsl::id.eq(token_id.0))
|
.filter(tokens::dsl::id.eq(token_id.0))
|
||||||
.get_result(&mut db()?)?)
|
.get_result(&mut db()?)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a single token by its name
|
/// Get a single token by its name
|
||||||
pub fn get_by_name(name: &str) -> anyhow::Result<Token> {
|
pub fn get_by_name(name: &str) -> anyhow::Result<Token> {
|
||||||
Ok(token::table
|
Ok(tokens::table
|
||||||
.filter(token::dsl::name.eq(name))
|
.filter(tokens::dsl::name.eq(name))
|
||||||
.get_result(&mut db()?)?)
|
.get_result(&mut db()?)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a single token by its value
|
/// Get a single token by its value
|
||||||
pub async fn get_by_value(value: &str) -> anyhow::Result<Token> {
|
pub async fn get_by_value(value: &str) -> anyhow::Result<Token> {
|
||||||
Ok(token::table
|
Ok(tokens::table
|
||||||
.filter(token::dsl::token_value.eq(value))
|
.filter(tokens::dsl::token_value.eq(value))
|
||||||
.get_result(&mut db()?)?)
|
.get_result(&mut db()?)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the token of a user
|
/// Get the token of a user
|
||||||
pub async fn get_list_user(id: UserID) -> anyhow::Result<Vec<Token>> {
|
pub async fn get_list_user(id: UserID) -> anyhow::Result<Vec<Token>> {
|
||||||
Ok(token::table
|
Ok(tokens::table
|
||||||
.filter(token::dsl::user_id.eq(id.0))
|
.filter(tokens::dsl::user_id.eq(id.0))
|
||||||
.get_results(&mut db()?)?)
|
.get_results(&mut db()?)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Update last used value of a token
|
/// Update last used value of a token
|
||||||
pub async fn update_time_used(token: &Token) -> anyhow::Result<()> {
|
pub async fn update_time_used(token: &Token) -> anyhow::Result<()> {
|
||||||
diesel::update(token::dsl::token.filter(token::dsl::id.eq(token.id().0)))
|
diesel::update(tokens::dsl::tokens.filter(tokens::dsl::id.eq(token.id().0)))
|
||||||
.set(token::dsl::time_used.eq(time() as i64))
|
.set(tokens::dsl::time_used.eq(time() as i64))
|
||||||
.execute(&mut db()?)?;
|
.execute(&mut db()?)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -87,10 +87,10 @@ pub async fn update_time_used(token: &Token) -> anyhow::Result<()> {
|
|||||||
/// Delete the token of a user
|
/// Delete the token of a user
|
||||||
pub async fn delete(user_id: UserID, token_id: TokenID) -> anyhow::Result<()> {
|
pub async fn delete(user_id: UserID, token_id: TokenID) -> anyhow::Result<()> {
|
||||||
diesel::delete(
|
diesel::delete(
|
||||||
token::dsl::token.filter(
|
tokens::dsl::tokens.filter(
|
||||||
token::dsl::id
|
tokens::dsl::id
|
||||||
.eq(token_id.0)
|
.eq(token_id.0)
|
||||||
.and(token::dsl::user_id.eq(user_id.0)),
|
.and(tokens::dsl::user_id.eq(user_id.0)),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.execute(&mut db()?)?;
|
.execute(&mut db()?)?;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user