(feat) Switched to sqlx.
Signed-off-by: Louis Hollingworth <louis@hollingworth.nl>
This commit is contained in:
parent
f267d6b285
commit
ba4216c21e
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -5,3 +5,4 @@
|
||||||
/target
|
/target
|
||||||
.DS_Store
|
.DS_Store
|
||||||
.env
|
.env
|
||||||
|
/.sqlx
|
||||||
|
|
1040
Cargo.lock
generated
1040
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -19,11 +19,15 @@ argon2 = { version = "0.5.2", features = ["password-hash", "std"] }
|
||||||
axum = {version = "0.6.20", features = ["macros"]}
|
axum = {version = "0.6.20", features = ["macros"]}
|
||||||
chrono = {version = "0.4.31", features = ["serde"]}
|
chrono = {version = "0.4.31", features = ["serde"]}
|
||||||
crypto = { version = "0.5.1", features = ["password-hash"] }
|
crypto = { version = "0.5.1", features = ["password-hash"] }
|
||||||
diesel = { version = "2.1.3", features = ["postgres", "extras", "uuid", "r2d2"] }
|
|
||||||
diesel_migrations = { version = "2.1.0", features = ["postgres"] }
|
|
||||||
dotenvy = "0.15.7"
|
dotenvy = "0.15.7"
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
serde = { version = "1.0.189", features = ["derive"] }
|
serde = { version = "1.0.189", features = ["derive"] }
|
||||||
serde_json = "1.0.107"
|
serde_json = "1.0.107"
|
||||||
tokio = { version = "1.33.0", features = ["full"] }
|
tokio = { version = "1.33.0", features = ["full"] }
|
||||||
uuid = { version = "1.0.0", features = ["serde", "v4", "v7"] }
|
uuid = { version = "1.0.0", features = ["serde", "v4", "v7"] }
|
||||||
|
sqlx = { version = "0.7", features = ["runtime-tokio", "postgres", "macros", "migrate", "uuid", "chrono", "json"] }
|
||||||
|
anyhow = "1.0.75"
|
||||||
|
thiserror = "1.0.50"
|
||||||
|
|
||||||
|
[profile.dev.package.sqlx-macros]
|
||||||
|
opt-level = 3
|
||||||
|
|
13
diesel.toml
13
diesel.toml
|
@ -1,13 +0,0 @@
|
||||||
# SPDX-FileCopyrightText: 2023 Louis Hollingworth <louis@hollingworth.nl>
|
|
||||||
#
|
|
||||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
||||||
|
|
||||||
# For documentation on how to configure this file,
|
|
||||||
# see https://diesel.rs/guides/configuring-diesel-cli
|
|
||||||
|
|
||||||
[print_schema]
|
|
||||||
file = "src/schema.rs"
|
|
||||||
custom_type_derives = ["diesel::query_builder::QueryId"]
|
|
||||||
|
|
||||||
[migrations_directory]
|
|
||||||
dir = "migrations"
|
|
|
@ -1,42 +0,0 @@
|
||||||
-- SPDX-FileCopyrightText: 2023 Louis Hollingworth <louis@hollingworth.nl>
|
|
||||||
--
|
|
||||||
-- SPDX-License-Identifier: AGPL-3.0-or-later
|
|
||||||
|
|
||||||
-- 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 $$
|
|
||||||
BEGIN
|
|
||||||
EXECUTE format('CREATE TRIGGER set_updated_at BEFORE UPDATE ON %s
|
|
||||||
FOR EACH ROW EXECUTE PROCEDURE diesel_set_updated_at()', _tbl);
|
|
||||||
END;
|
|
||||||
$$ LANGUAGE plpgsql;
|
|
||||||
|
|
||||||
CREATE OR REPLACE FUNCTION diesel_set_updated_at() RETURNS trigger AS $$
|
|
||||||
BEGIN
|
|
||||||
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;
|
|
||||||
$$ LANGUAGE plpgsql;
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
-- SPDX-FileCopyrightText: 2023 Louis Hollingworth <louis@hollingworth.nl>
|
|
||||||
--
|
|
||||||
-- SPDX-License-Identifier: AGPL-3.0-or-later
|
|
||||||
|
|
||||||
-- This file should undo anything in `up.sql`
|
|
||||||
DROP TABLE posts;
|
|
|
@ -1,17 +0,0 @@
|
||||||
-- SPDX-FileCopyrightText: 2023 Louis Hollingworth <louis@hollingworth.nl>
|
|
||||||
--
|
|
||||||
-- SPDX-License-Identifier: AGPL-3.0-or-later
|
|
||||||
|
|
||||||
-- Your SQL goes here
|
|
||||||
|
|
||||||
CREATE TABLE posts (
|
|
||||||
id SERIAL PRIMARY KEY,
|
|
||||||
slug VARCHAR NOT NULL,
|
|
||||||
title VARCHAR NOT NULL,
|
|
||||||
body TEXT NOT NULL,
|
|
||||||
published BOOLEAN NOT NULL DEFAULT FALSE,
|
|
||||||
user_id UUID NOT NULL REFERENCES users(id),
|
|
||||||
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
|
||||||
updated_at TIMESTAMP NOT NULL DEFAULT NOW()
|
|
||||||
);
|
|
||||||
SELECT diesel_manage_updated_at('posts');
|
|
|
@ -1,6 +0,0 @@
|
||||||
-- SPDX-FileCopyrightText: 2023 Louis Hollingworth <louis@hollingworth.nl>
|
|
||||||
--
|
|
||||||
-- SPDX-License-Identifier: AGPL-3.0-or-later
|
|
||||||
|
|
||||||
-- This file should undo anything in `up.sql`
|
|
||||||
DROP TABLE blogs;
|
|
|
@ -1,18 +0,0 @@
|
||||||
-- SPDX-FileCopyrightText: 2023 Louis Hollingworth <louis@hollingworth.nl>
|
|
||||||
--
|
|
||||||
-- SPDX-License-Identifier: AGPL-3.0-or-later
|
|
||||||
|
|
||||||
-- Your SQL goes here
|
|
||||||
CREATE TABLE blogs (
|
|
||||||
id SERIAL PRIMARY KEY,
|
|
||||||
slug VARCHAR NOT NULL,
|
|
||||||
name VARCHAR NOT NULL,
|
|
||||||
description TEXT NOT NULL,
|
|
||||||
url TEXT NOT NULL,
|
|
||||||
user_id UUID NOT NULL REFERENCES users(id),
|
|
||||||
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
|
||||||
updated_at TIMESTAMP NOT NULL DEFAULT NOW()
|
|
||||||
);
|
|
||||||
|
|
||||||
SELECT diesel_manage_updated_at('blogs');
|
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
-- SPDX-FileCopyrightText: 2023 Louis Hollingworth <louis@hollingworth.nl>
|
|
||||||
--
|
|
||||||
-- SPDX-License-Identifier: AGPL-3.0-or-later
|
|
||||||
|
|
||||||
-- This file should undo anything in `up.sql`
|
|
||||||
|
|
||||||
ALTER TABLE posts
|
|
||||||
DROP COLUMN blog_id;
|
|
|
@ -1,8 +0,0 @@
|
||||||
-- SPDX-FileCopyrightText: 2023 Louis Hollingworth <louis@hollingworth.nl>
|
|
||||||
--
|
|
||||||
-- SPDX-License-Identifier: AGPL-3.0-or-later
|
|
||||||
|
|
||||||
-- Your SQL goes here
|
|
||||||
|
|
||||||
ALTER TABLE posts
|
|
||||||
ADD COLUMN blog_id INTEGER NOT NULL REFERENCES blogs(id);
|
|
|
@ -2,9 +2,6 @@
|
||||||
--
|
--
|
||||||
-- SPDX-License-Identifier: AGPL-3.0-or-later
|
-- SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
-- This file was automatically created by Diesel to setup helper functions
|
-- Add down migration script here
|
||||||
-- and other internal bookkeeping. This file is safe to edit, any future
|
|
||||||
-- changes will be added to existing projects as new migrations.
|
|
||||||
|
|
||||||
DROP FUNCTION IF EXISTS diesel_manage_updated_at(_tbl regclass);
|
DROP FUNCTION IF EXISTS diesel_manage_updated_at(_tbl regclass);
|
||||||
DROP FUNCTION IF EXISTS diesel_set_updated_at();
|
DROP FUNCTION IF EXISTS diesel_set_updated_at();
|
24
migrations/20231026121809_init.up.sql
Normal file
24
migrations/20231026121809_init.up.sql
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
-- SPDX-FileCopyrightText: 2023 Louis Hollingworth <louis@hollingworth.nl>
|
||||||
|
--
|
||||||
|
-- SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
|
-- Add up migration script here
|
||||||
|
|
||||||
|
CREATE OR REPLACE FUNCTION manage_updated_at(_tbl regclass) RETURNS VOID AS $$
|
||||||
|
BEGIN
|
||||||
|
EXECUTE format('CREATE TRIGGER set_updated_at BEFORE UPDATE ON %s
|
||||||
|
FOR EACH ROW EXECUTE PROCEDURE set_updated_at()', _tbl);
|
||||||
|
END;
|
||||||
|
$$ LANGUAGE plpgsql;
|
||||||
|
|
||||||
|
CREATE OR REPLACE FUNCTION set_updated_at() RETURNS trigger AS $$
|
||||||
|
BEGIN
|
||||||
|
IF (
|
||||||
|
NEW IS DISTINCT FROM OLD AND
|
||||||
|
NEW.updated_at IS NOT DISTINCT FROM OLD.updated_at
|
||||||
|
) THEN
|
||||||
|
NEW.updated_at := NOW();
|
||||||
|
END IF;
|
||||||
|
RETURN NEW;
|
||||||
|
END;
|
||||||
|
$$ LANGUAGE plpgsql
|
|
@ -2,5 +2,5 @@
|
||||||
--
|
--
|
||||||
-- SPDX-License-Identifier: AGPL-3.0-or-later
|
-- SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
-- This file should undo anything in `up.sql`
|
-- Add down migration script here
|
||||||
DROP TABLE users;
|
DROP TABLE users;
|
|
@ -2,17 +2,16 @@
|
||||||
--
|
--
|
||||||
-- SPDX-License-Identifier: AGPL-3.0-or-later
|
-- SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
-- Your SQL goes here
|
-- Add up migration script here
|
||||||
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
|
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
|
||||||
|
|
||||||
CREATE TABLE users (
|
CREATE TABLE users (
|
||||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
username VARCHAR NOT NULL,
|
username VARCHAR UNIQUE NOT NULL,
|
||||||
epost VARCHAR NOT NULL,
|
epost VARCHAR UNIQUE NOT NULL,
|
||||||
pass VARCHAR NOT NULL,
|
pass VARCHAR NOT NULL,
|
||||||
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
||||||
updated_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
updated_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
||||||
main_fedi TEXT,
|
main_fedi TEXT
|
||||||
UNIQUE(username, epost)
|
|
||||||
);
|
);
|
||||||
SELECT diesel_manage_updated_at('users');
|
SELECT manage_updated_at('users');
|
55
src/lib.rs
55
src/lib.rs
|
@ -2,27 +2,52 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
pub mod models;
|
pub mod models;
|
||||||
pub mod schema;
|
use thiserror::Error;
|
||||||
use diesel::prelude::*;
|
|
||||||
|
|
||||||
pub type DbPool = diesel::r2d2::Pool<diesel::r2d2::ConnectionManager<diesel::PgConnection>>;
|
#[derive(Error, Debug)]
|
||||||
|
pub enum FbError {
|
||||||
|
#[error("Database Error: {0}")]
|
||||||
|
DbError(sqlx::Error),
|
||||||
|
|
||||||
pub fn establish_connection() -> diesel::pg::PgConnection {
|
#[error("Internal Error: {0}")]
|
||||||
|
IError(String)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn connection_pool() -> Result<sqlx::Pool<sqlx::Postgres>, sqlx::Error> {
|
||||||
dotenvy::dotenv().ok();
|
dotenvy::dotenv().ok();
|
||||||
|
|
||||||
let database_url = std::env::var("DATABASE_URL").expect("DATABASE_URL must be set");
|
let database_url = std::env::var("DATABASE_URL").expect("DATABASE_URL must be set");
|
||||||
diesel::pg::PgConnection::establish(&database_url)
|
|
||||||
.unwrap_or_else(|_| panic!("Error connecting to {}", database_url))
|
Ok(sqlx::postgres::PgPoolOptions::new()
|
||||||
|
.max_connections(5)
|
||||||
|
.connect(&database_url).await?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn connection_pool() -> DbPool {
|
pub async fn get_user_by_name_for_auth(username: String, pool: sqlx::Pool<sqlx::Postgres>) -> Result<models::user::AuthUser, sqlx::Error> {
|
||||||
dotenvy::dotenv().ok();
|
let user = sqlx::query_as!(models::user::AuthUser, "SELECT id, username, pass FROM users WHERE username = $1", username).fetch_one(&pool).await.unwrap();
|
||||||
|
|
||||||
let database_url = std::env::var("DATABASE_URL").expect("DATABASE_URL must be set");
|
Ok(user)
|
||||||
let manager = diesel::r2d2::ConnectionManager::<diesel::PgConnection>::new(database_url);
|
}
|
||||||
|
|
||||||
diesel::r2d2::Pool::builder()
|
|
||||||
.test_on_check_out(true)
|
pub async fn get_all_users(pool: sqlx::Pool<sqlx::Postgres>) -> Result<Vec<models::user::User>, sqlx::Error> {
|
||||||
.build(manager)
|
let users = sqlx::query_as!(models::user::User, "SELECT * FROM users").fetch_all(&pool).await.unwrap();
|
||||||
.expect("Could not build connection pool")
|
|
||||||
|
Ok(users)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates user in database. No need to salt and hash the password, the function does it for you.
|
||||||
|
pub async fn create_user(user: models::user::NewUser, pool: sqlx::Pool<sqlx::Postgres>) -> Result<(), FbError> {
|
||||||
|
use argon2::password_hash::{PasswordHasher, SaltString};
|
||||||
|
|
||||||
|
let argon = argon2::Argon2::default();
|
||||||
|
let salt = SaltString::generate(&mut rand::thread_rng());
|
||||||
|
let hashed: String = match argon.hash_password(&user.pass.into_bytes(), &salt) {
|
||||||
|
Err(_) => return Err(FbError::IError("Error while hashing password".to_string())),
|
||||||
|
Ok(pswd) => pswd.to_string()
|
||||||
|
};
|
||||||
|
let _ = sqlx::query_as!(models::user::NewUser, "
|
||||||
|
INSERT INTO users (username, epost, pass)
|
||||||
|
VALUES ($1, $2, $3)", user.username, user.epost, hashed).execute(&pool).await.unwrap();
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
114
src/main.rs
114
src/main.rs
|
@ -3,18 +3,16 @@
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
use argon2::password_hash::{PasswordHasher, SaltString};
|
|
||||||
use axum::{routing::{get, post}, Router, response::Json, extract::State};
|
use axum::{routing::{get, post}, Router, response::Json, extract::State};
|
||||||
use diesel::prelude::*;
|
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
let pool: fediblog::DbPool = fediblog::connection_pool();
|
let pool = fediblog::connection_pool().await.unwrap();
|
||||||
|
|
||||||
let app = Router::new()
|
let app = Router::new()
|
||||||
.route("/health", get(health_check))
|
.route("/health", get(health_check))
|
||||||
.route("/api/v0/user", post(create_user))
|
.route("/api/v0/user", post(create_user))
|
||||||
.route("/api/v0/user", get(get_user))
|
// .route("/api/v0/user", get(get_user))
|
||||||
.with_state(pool);
|
.with_state(pool);
|
||||||
|
|
||||||
axum::Server::bind(&"0.0.0.0:7654".parse().unwrap())
|
axum::Server::bind(&"0.0.0.0:7654".parse().unwrap())
|
||||||
|
@ -23,115 +21,17 @@ async fn main() {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[axum::debug_handler]
|
|
||||||
async fn create_user(
|
async fn create_user(
|
||||||
State(pool): State<fediblog::DbPool>,
|
State(pool): State<sqlx::Pool<sqlx::Postgres>>,
|
||||||
Json(new_user): Json<NewUser>,
|
Json(u): Json<fediblog::models::user::NewUser>
|
||||||
) -> Result<Json<UserResponse>, (axum::http::StatusCode, String)> {
|
) -> &'static str {
|
||||||
use fediblog::schema::users::dsl::*;
|
let _ = fediblog::create_user(u, pool).await;
|
||||||
let argon = argon2::Argon2::default();
|
|
||||||
let salt = SaltString::generate(&mut rand::thread_rng());
|
|
||||||
let hashed_pass: String = match argon.hash_password(&new_user.pass.into_bytes(), &salt) {
|
|
||||||
Err(_) => {
|
|
||||||
return Err((
|
|
||||||
axum::http::StatusCode::INTERNAL_SERVER_ERROR,
|
|
||||||
"Error hashing password".to_string(),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
Ok(pswd) => pswd.to_string(),
|
|
||||||
};
|
|
||||||
diesel::insert_into(users)
|
|
||||||
.values((
|
|
||||||
username.eq(new_user.username.clone()),
|
|
||||||
epost.eq(new_user.epost.clone()),
|
|
||||||
pass.eq(hashed_pass),
|
|
||||||
))
|
|
||||||
.execute(&mut pool.get().unwrap())
|
|
||||||
.expect("Error saving new user");
|
|
||||||
|
|
||||||
let uid = get_userid_from_name(new_user.username.clone(), &mut pool.get().unwrap());
|
"All done :)"
|
||||||
|
|
||||||
match uid {
|
|
||||||
None => return Err((axum::http::StatusCode::INTERNAL_SERVER_ERROR, "There was an error creating this account".to_string())),
|
|
||||||
Some(user_id) => return Ok(Json(
|
|
||||||
UserResponse {
|
|
||||||
id: user_id,
|
|
||||||
username: new_user.username,
|
|
||||||
epost: Some(new_user.epost.to_string()),
|
|
||||||
main_fedi: None
|
|
||||||
}
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_userid_from_name(username: String, pool: &mut diesel::r2d2::PooledConnection<diesel::r2d2::ConnectionManager<diesel::PgConnection>>) -> Option<uuid::Uuid> {
|
|
||||||
let uv: Result<Vec<fediblog::models::BaseUser>, diesel::result::Error> = pool.build_transaction().read_only().run(|conn| {
|
|
||||||
let userv = fediblog::schema::users::dsl::users
|
|
||||||
.select((fediblog::schema::users::dsl::id, fediblog::schema::users::dsl::username))
|
|
||||||
.load::<fediblog::models::BaseUser>(conn);
|
|
||||||
Ok(userv.unwrap())
|
|
||||||
});
|
|
||||||
|
|
||||||
find_userid_from_base_user(uv.unwrap(), username)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn find_userid_from_base_user(usrs: Vec<fediblog::models::BaseUser>, usrn: String) -> Option<uuid::Uuid> {
|
|
||||||
for u in usrs {
|
|
||||||
if u.username == usrn {
|
|
||||||
return Some(u.id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
async fn get_user(
|
|
||||||
State(pool): State<fediblog::DbPool>,
|
|
||||||
Json(auth_user): Json<AuthUser>
|
|
||||||
) ->Result<Json<UserResponse>, (axum::http::StatusCode, String)> {
|
|
||||||
let conn = &mut pool.get().unwrap();
|
|
||||||
|
|
||||||
let uid = get_userid_from_name(auth_user.username, conn).unwrap();
|
|
||||||
|
|
||||||
|
|
||||||
let userv = diesel::sql_query(format!("SELECT * FROM users WHERE id = {}", uid.to_string())).load::<fediblog::models::User>(conn);
|
|
||||||
|
|
||||||
match userv {
|
|
||||||
Ok(usrs) => return Ok(Json(UserResponse{
|
|
||||||
id: usrs[0].id,
|
|
||||||
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(Json(UserResponse{
|
|
||||||
id: user.id,
|
|
||||||
username: user.username.clone(),
|
|
||||||
epost: None,
|
|
||||||
main_fedi: None
|
|
||||||
}))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn health_check() -> &'static str {
|
async fn health_check() -> &'static str {
|
||||||
"Saluton, amiko! Looks like we are running!"
|
"Saluton, amiko! Looks like we are running!"
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, serde::Deserialize, serde::Serialize)]
|
|
||||||
struct NewUser {
|
|
||||||
username: String,
|
|
||||||
epost: String,
|
|
||||||
pass: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, serde::Deserialize, serde::Serialize)]
|
|
||||||
struct AuthUser {
|
|
||||||
username: String,
|
|
||||||
pass: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(serde::Deserialize, serde::Serialize)]
|
|
||||||
struct UserResponse {
|
|
||||||
id: uuid::Uuid,
|
|
||||||
username: String,
|
|
||||||
epost: Option<String>,
|
|
||||||
main_fedi: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,71 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: 2023 Louis Hollingworth <louis@hollingworth.nl>
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
||||||
|
|
||||||
use diesel::prelude::*;
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use uuid::Uuid;
|
|
||||||
|
|
||||||
#[derive(
|
|
||||||
Selectable, Debug, Queryable, QueryableByName
|
|
||||||
)]
|
|
||||||
#[diesel(table_name = crate::schema::users)]
|
|
||||||
#[diesel(check_for_backend(diesel::pg::Pg))]
|
|
||||||
pub struct User {
|
|
||||||
pub id: Uuid,
|
|
||||||
pub username: String,
|
|
||||||
pub epost: String,
|
|
||||||
pub pass: String,
|
|
||||||
pub created_at: chrono::NaiveDateTime,
|
|
||||||
pub updated_at: chrono::NaiveDateTime,
|
|
||||||
pub main_fedi: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Queryable, PartialEq, Debug)]
|
|
||||||
#[diesel(table_name = crate::schema::users)]
|
|
||||||
pub struct BaseUser {
|
|
||||||
pub id: Uuid,
|
|
||||||
pub username: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Insertable, Debug, Selectable)]
|
|
||||||
#[diesel(table_name = crate::schema::users)]
|
|
||||||
pub struct NewUser {
|
|
||||||
pub username: String,
|
|
||||||
pub epost: String,
|
|
||||||
pub pass: String
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(
|
|
||||||
Queryable, Selectable, Identifiable, Associations, Debug, PartialEq, Serialize, Deserialize,
|
|
||||||
)]
|
|
||||||
#[diesel(belongs_to(User))]
|
|
||||||
#[diesel(table_name = crate::schema::blogs)]
|
|
||||||
pub struct Blog {
|
|
||||||
pub id: isize,
|
|
||||||
pub slug: String,
|
|
||||||
pub name: String,
|
|
||||||
pub description: String,
|
|
||||||
pub url: String,
|
|
||||||
pub user_id: Uuid,
|
|
||||||
pub created_at: chrono::NaiveDateTime,
|
|
||||||
pub updated_at: chrono::NaiveDateTime,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(
|
|
||||||
Queryable, Selectable, Identifiable, Associations, Debug, PartialEq, Serialize, Deserialize,
|
|
||||||
)]
|
|
||||||
#[diesel(belongs_to(User))]
|
|
||||||
#[diesel(belongs_to(Blog))]
|
|
||||||
#[diesel(table_name = crate::schema::posts)]
|
|
||||||
pub struct Post {
|
|
||||||
pub id: isize,
|
|
||||||
pub slug: String,
|
|
||||||
pub title: String,
|
|
||||||
pub body: String,
|
|
||||||
pub published: bool,
|
|
||||||
pub user_id: Uuid,
|
|
||||||
pub blog_id: isize,
|
|
||||||
pub created_at: chrono::NaiveDateTime,
|
|
||||||
pub updated_at: chrono::NaiveDateTime,
|
|
||||||
}
|
|
5
src/models/mod.rs
Normal file
5
src/models/mod.rs
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
// SPDX-FileCopyrightText: 2023 Louis Hollingworth <louis@hollingworth.nl>
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
|
pub mod user;
|
28
src/models/user.rs
Normal file
28
src/models/user.rs
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
// SPDX-FileCopyrightText: 2023 Louis Hollingworth <louis@hollingworth.nl>
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
|
#[derive(serde::Serialize, serde::Deserialize, sqlx::FromRow)]
|
||||||
|
pub struct AuthUser {
|
||||||
|
pub id: uuid::Uuid,
|
||||||
|
pub username: String,
|
||||||
|
pub pass: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(serde::Serialize, serde::Deserialize, sqlx::FromRow)]
|
||||||
|
pub struct NewUser {
|
||||||
|
pub username: String,
|
||||||
|
pub pass: String,
|
||||||
|
pub epost: String
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(serde::Deserialize, serde::Serialize, sqlx::FromRow)]
|
||||||
|
pub struct User {
|
||||||
|
pub id: uuid::Uuid,
|
||||||
|
pub username: String,
|
||||||
|
pub epost: String,
|
||||||
|
pub pass: String,
|
||||||
|
pub created_at: chrono::NaiveDateTime,
|
||||||
|
pub updated_at: chrono::NaiveDateTime,
|
||||||
|
pub main_fedi: Option<String>
|
||||||
|
}
|
|
@ -1,54 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: 2023 Louis Hollingworth <louis@hollingworth.nl>
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
||||||
|
|
||||||
// @generated automatically by Diesel CLI.
|
|
||||||
|
|
||||||
diesel::table! {
|
|
||||||
blogs (id) {
|
|
||||||
id -> Int4,
|
|
||||||
slug -> Varchar,
|
|
||||||
name -> Varchar,
|
|
||||||
description -> Text,
|
|
||||||
url -> Text,
|
|
||||||
user_id -> Uuid,
|
|
||||||
created_at -> Timestamp,
|
|
||||||
updated_at -> Timestamp,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
diesel::table! {
|
|
||||||
posts (id) {
|
|
||||||
id -> Int4,
|
|
||||||
slug -> Varchar,
|
|
||||||
title -> Varchar,
|
|
||||||
body -> Text,
|
|
||||||
published -> Bool,
|
|
||||||
user_id -> Uuid,
|
|
||||||
created_at -> Timestamp,
|
|
||||||
updated_at -> Timestamp,
|
|
||||||
blog_id -> Int4,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
diesel::table! {
|
|
||||||
users (id) {
|
|
||||||
id -> Uuid,
|
|
||||||
username -> Varchar,
|
|
||||||
epost -> Varchar,
|
|
||||||
pass -> Varchar,
|
|
||||||
created_at -> Timestamp,
|
|
||||||
updated_at -> Timestamp,
|
|
||||||
main_fedi -> Nullable<Text>,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
diesel::joinable!(blogs -> users (user_id));
|
|
||||||
diesel::joinable!(posts -> blogs (blog_id));
|
|
||||||
diesel::joinable!(posts -> users (user_id));
|
|
||||||
|
|
||||||
diesel::allow_tables_to_appear_in_same_query!(
|
|
||||||
blogs,
|
|
||||||
posts,
|
|
||||||
users,
|
|
||||||
);
|
|
Loading…
Reference in a new issue