spit into crates and fix app
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Patrick Michl 2022-07-07 15:10:31 +02:00
parent 26e39c7c06
commit 35bde07b39
No known key found for this signature in database
GPG Key ID: BFE0ACEE21CD5EB0
27 changed files with 751 additions and 384 deletions

445
Cargo.lock generated
View File

@ -19,6 +19,15 @@ dependencies = [
"version_check",
]
[[package]]
name = "aho-corasick"
version = "0.7.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
dependencies = [
"memchr",
]
[[package]]
name = "aliasable"
version = "0.1.3"
@ -63,6 +72,113 @@ version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f093eed78becd229346bf859eec0aa4dd7ddde0757287b2b4107a1f09c80002"
[[package]]
name = "async-attributes"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3203e79f4dd9bdda415ed03cf14dae5a2bf775c683a00f94e9cd1faf0f596e5"
dependencies = [
"quote",
"syn",
]
[[package]]
name = "async-channel"
version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2114d64672151c0c5eaa5e131ec84a74f06e1e559830dabba01ca30605d66319"
dependencies = [
"concurrent-queue",
"event-listener",
"futures-core",
]
[[package]]
name = "async-executor"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "871f9bb5e0a22eeb7e8cf16641feb87c9dc67032ccf8ff49e772eb9941d3a965"
dependencies = [
"async-task",
"concurrent-queue",
"fastrand",
"futures-lite",
"once_cell",
"slab",
]
[[package]]
name = "async-global-executor"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5262ed948da60dd8956c6c5aca4d4163593dddb7b32d73267c93dab7b2e98940"
dependencies = [
"async-channel",
"async-executor",
"async-io",
"async-lock",
"blocking",
"futures-lite",
"num_cpus",
"once_cell",
"tokio",
]
[[package]]
name = "async-io"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5e18f61464ae81cde0a23e713ae8fd299580c54d697a35820cfd0625b8b0e07"
dependencies = [
"concurrent-queue",
"futures-lite",
"libc",
"log",
"once_cell",
"parking",
"polling",
"slab",
"socket2",
"waker-fn",
"winapi",
]
[[package]]
name = "async-lock"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e97a171d191782fba31bb902b14ad94e24a68145032b7eedf871ab0bc0d077b6"
dependencies = [
"event-listener",
]
[[package]]
name = "async-std"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62565bb4402e926b29953c785397c6dc0391b7b446e45008b0049eb43cec6f5d"
dependencies = [
"async-attributes",
"async-channel",
"async-global-executor",
"async-io",
"async-lock",
"crossbeam-utils",
"futures-channel",
"futures-core",
"futures-io",
"futures-lite",
"gloo-timers",
"kv-log-macro",
"log",
"memchr",
"once_cell",
"pin-project-lite",
"pin-utils",
"slab",
"wasm-bindgen-futures",
]
[[package]]
name = "async-stream"
version = "0.3.3"
@ -84,6 +200,12 @@ dependencies = [
"syn",
]
[[package]]
name = "async-task"
version = "4.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30696a84d817107fc028e049980e09d5e140e8da8f1caeb17e8e950658a3cea9"
[[package]]
name = "async-trait"
version = "0.1.56"
@ -104,6 +226,23 @@ dependencies = [
"num-traits",
]
[[package]]
name = "atomic-waker"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "065374052e7df7ee4047b1160cca5e1467a12351a40b3da123c870ba0b8eda2a"
[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
"hermit-abi",
"libc",
"winapi",
]
[[package]]
name = "autocfg"
version = "1.1.0"
@ -231,6 +370,20 @@ dependencies = [
"generic-array",
]
[[package]]
name = "blocking"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c6ccb65d468978a086b69884437ded69a90faab3bbe6e67f242173ea728acccc"
dependencies = [
"async-channel",
"async-task",
"atomic-waker",
"fastrand",
"futures-lite",
"once_cell",
]
[[package]]
name = "bumpalo"
version = "3.10.0"
@ -249,6 +402,12 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8"
[[package]]
name = "cache-padded"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1db59621ec70f09c5e9b597b220c7a2b43611f4710dc03ceb8748637775692c"
[[package]]
name = "cc"
version = "1.0.73"
@ -275,6 +434,30 @@ dependencies = [
"winapi",
]
[[package]]
name = "clap"
version = "2.34.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c"
dependencies = [
"ansi_term",
"atty",
"bitflags",
"strsim",
"textwrap",
"unicode-width",
"vec_map",
]
[[package]]
name = "concurrent-queue"
version = "1.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30ed07550be01594c6026cff2a1d7fe9c8f683caa798e12b68694ac9e88286a3"
dependencies = [
"cache-padded",
]
[[package]]
name = "const-oid"
version = "0.6.2"
@ -357,6 +540,16 @@ dependencies = [
"typenum",
]
[[package]]
name = "ctor"
version = "0.1.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f877be4f7c9f246b183111634f75baa039715e3f46ce860677d3b19a69fb229c"
dependencies = [
"quote",
"syn",
]
[[package]]
name = "curve25519-dalek"
version = "3.2.1"
@ -557,6 +750,21 @@ version = "0.3.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b"
[[package]]
name = "futures-lite"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7694489acd39452c77daa48516b894c153f192c3578d5a839b62c58099fcbf48"
dependencies = [
"fastrand",
"futures-core",
"futures-io",
"memchr",
"parking",
"pin-project-lite",
"waker-fn",
]
[[package]]
name = "futures-macro"
version = "0.3.21"
@ -630,6 +838,18 @@ dependencies = [
"wasi 0.11.0+wasi-snapshot-preview1",
]
[[package]]
name = "gloo-timers"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5fb7d06c1c8cc2a29bee7ec961009a0b2caa0793ee4900c2ffb348734ba1c8f9"
dependencies = [
"futures-channel",
"futures-core",
"js-sys",
"wasm-bindgen",
]
[[package]]
name = "hashbrown"
version = "0.11.2"
@ -796,6 +1016,15 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d"
[[package]]
name = "js-sys"
version = "0.3.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3fac17f7123a73ca62df411b1bf727ccc805daa070338fda671c86dac1bdc27"
dependencies = [
"wasm-bindgen",
]
[[package]]
name = "js_int"
version = "0.2.2"
@ -814,6 +1043,15 @@ dependencies = [
"serde",
]
[[package]]
name = "kv-log-macro"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f"
dependencies = [
"log",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
@ -854,6 +1092,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
dependencies = [
"cfg-if",
"value-bag",
]
[[package]]
@ -883,29 +1122,6 @@ version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73cbba799671b762df5a175adf59ce145165747bb891505c43d09aefbbf38beb"
[[package]]
name = "matrix"
version = "0.1.0"
dependencies = [
"anyhow",
"argon2",
"axum",
"axum-macros",
"http",
"neo-entity",
"rand 0.8.5",
"ruma",
"sea-orm",
"serde",
"serde_json",
"thiserror",
"tokio",
"tower-http 0.2.5",
"tracing",
"tracing-subscriber",
"uuid 1.1.2",
]
[[package]]
name = "memchr"
version = "2.5.0"
@ -954,6 +1170,30 @@ dependencies = [
"tempfile",
]
[[package]]
name = "neo"
version = "0.1.0"
dependencies = [
"anyhow",
"argon2",
"axum",
"axum-macros",
"http",
"neo-entity",
"neo-migration",
"rand 0.8.5",
"ruma",
"sea-orm",
"serde",
"serde_json",
"thiserror",
"tokio",
"tower-http 0.2.5",
"tracing",
"tracing-subscriber",
"uuid 1.1.2",
]
[[package]]
name = "neo-entity"
version = "0.1.0"
@ -965,6 +1205,14 @@ dependencies = [
"uuid 1.1.2",
]
[[package]]
name = "neo-migration"
version = "0.1.0"
dependencies = [
"neo-entity",
"sea-orm-migration",
]
[[package]]
name = "nom"
version = "7.1.1"
@ -1096,6 +1344,12 @@ dependencies = [
"syn",
]
[[package]]
name = "parking"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72"
[[package]]
name = "parking_lot"
version = "0.11.2"
@ -1216,6 +1470,19 @@ version = "0.3.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae"
[[package]]
name = "polling"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "685404d509889fade3e86fe3a5803bca2ec09b0c0778d5ada6ec8bf7a8de5259"
dependencies = [
"cfg-if",
"libc",
"log",
"wepoll-ffi",
"winapi",
]
[[package]]
name = "ppv-lite86"
version = "0.2.16"
@ -1366,6 +1633,8 @@ version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
@ -1577,6 +1846,23 @@ dependencies = [
"uuid 0.8.2",
]
[[package]]
name = "sea-orm-cli"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fca862fdba12c753bffba9c9adf95d3d3f5dcc82fd589b12faeee7068bb173d5"
dependencies = [
"async-std",
"chrono",
"clap",
"dotenv",
"regex",
"sea-schema",
"tracing",
"tracing-subscriber",
"url",
]
[[package]]
name = "sea-orm-macros"
version = "0.8.0"
@ -1590,6 +1876,22 @@ dependencies = [
"syn",
]
[[package]]
name = "sea-orm-migration"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "15589f057677f57bea393572bd8eb9e8feb843a5f09b4fa518be6cef3a6ffedc"
dependencies = [
"async-trait",
"clap",
"dotenv",
"sea-orm",
"sea-orm-cli",
"sea-schema",
"tracing",
"tracing-subscriber",
]
[[package]]
name = "sea-query"
version = "0.24.6"
@ -1629,6 +1931,29 @@ dependencies = [
"syn",
]
[[package]]
name = "sea-schema"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a01a736b624984160b22a10a6d8efcb95958af68d3dd0a06a529092056ddc902"
dependencies = [
"futures",
"sea-query",
"sea-schema-derive",
]
[[package]]
name = "sea-schema-derive"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56821b7076f5096b8f726e2791ad255a99c82498e08ec477a65a96c461ff1927"
dependencies = [
"heck 0.3.3",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "sea-strum"
version = "0.23.0"
@ -2011,6 +2336,12 @@ dependencies = [
"unicode-normalization",
]
[[package]]
name = "strsim"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
[[package]]
name = "subtle"
version = "2.4.1"
@ -2060,6 +2391,15 @@ dependencies = [
"winapi",
]
[[package]]
name = "textwrap"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
dependencies = [
"unicode-width",
]
[[package]]
name = "thiserror"
version = "1.0.31"
@ -2382,6 +2722,12 @@ version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99"
[[package]]
name = "unicode-width"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
[[package]]
name = "unicode-xid"
version = "0.2.3"
@ -2432,18 +2778,40 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
[[package]]
name = "value-bag"
version = "1.0.0-alpha.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2209b78d1249f7e6f3293657c9779fe31ced465df091bbd433a1cf88e916ec55"
dependencies = [
"ctor",
"version_check",
]
[[package]]
name = "vcpkg"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
[[package]]
name = "vec_map"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "waker-fn"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca"
[[package]]
name = "want"
version = "0.3.0"
@ -2497,6 +2865,18 @@ dependencies = [
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-futures"
version = "0.4.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de9a9cec1733468a8c657e57fa2413d2ae2c0129b95e87c5b72b8ace4d13f31f"
dependencies = [
"cfg-if",
"js-sys",
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.81"
@ -2526,6 +2906,25 @@ version = "0.2.81"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a89911bd99e5f3659ec4acf9c4d93b0a90fe4a2a11f15328472058edc5261be"
[[package]]
name = "web-sys"
version = "0.3.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fed94beee57daf8dd7d51f2b15dc2bcde92d7a72304cdf662a4371008b71b90"
dependencies = [
"js-sys",
"wasm-bindgen",
]
[[package]]
name = "wepoll-ffi"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d743fdedc5c64377b5fc2bc036b01c7fd642205a0d96356034ae3404d49eb7fb"
dependencies = [
"cc",
]
[[package]]
name = "wildmatch"
version = "2.1.1"

View File

@ -2,5 +2,6 @@
members = [
"neo",
"neo-entity"
"neo-entity",
"neo-migration"
]

View File

@ -1,4 +1,5 @@
use sea_orm::entity::prelude::*;
use sea_orm::Set;
#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
#[sea_orm(table_name = "devices")]
@ -36,4 +37,12 @@ impl Related<super::sessions::Entity> for Entity {
}
}
impl ActiveModelBehavior for ActiveModel {}
impl ActiveModelBehavior for ActiveModel {
fn new() -> Self {
Self {
uuid: Set(Uuid::new_v4()),
device_id: Set(Uuid::new_v4().to_string()),
..ActiveModelTrait::default()
}
}
}

View File

@ -1,3 +1,4 @@
pub mod users;
pub mod devices;
pub mod sessions;
pub mod sessions;
pub mod prelude;

View File

@ -0,0 +1,6 @@
#[allow(unused_imports)]
pub use crate::{
devices::{self, Entity as Device},
sessions::{self, Entity as Session},
users::{self, Entity as User},
};

View File

@ -1,4 +1,5 @@
use sea_orm::entity::prelude::*;
use sea_orm::Set;
#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
#[sea_orm(table_name = "users")]
@ -13,7 +14,7 @@ pub struct Model {
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {
#[sea_orm(has_many = "super::devices::Entity")]
Devices
Devices,
}
impl Related<super::devices::Entity> for Entity {
@ -22,4 +23,11 @@ impl Related<super::devices::Entity> for Entity {
}
}
impl ActiveModelBehavior for ActiveModel {}
impl ActiveModelBehavior for ActiveModel {
fn new() -> Self {
Self {
uuid: Set(Uuid::new_v4()),
..ActiveModelTrait::default()
}
}
}

9
neo-migration/Cargo.toml Normal file
View File

@ -0,0 +1,9 @@
[package]
name = "neo-migration"
version = "0.1.0"
edition = "2021"
publish = false
[dependencies]
sea-orm-migration = "^0.8"
neo-entity = { path = "../neo-entity" }

37
neo-migration/README.md Normal file
View File

@ -0,0 +1,37 @@
# Running Migrator CLI
- Apply all pending migrations
```sh
cargo run
```
```sh
cargo run -- up
```
- Apply first 10 pending migrations
```sh
cargo run -- up -n 10
```
- Rollback last applied migrations
```sh
cargo run -- down
```
- Rollback last 10 applied migrations
```sh
cargo run -- down -n 10
```
- Drop all tables from the database, then reapply all migrations
```sh
cargo run -- fresh
```
- Rollback all applied migrations, then reapply all migrations
```sh
cargo run -- refresh
```
- Rollback all applied migrations
```sh
cargo run -- reset
```
- Check the status of all migrations
```sh
cargo run -- status
```

18
neo-migration/src/lib.rs Normal file
View File

@ -0,0 +1,18 @@
pub use sea_orm_migration::prelude::*;
mod m20220707_092851_create_users;
mod m20220707_112339_create_devices;
mod m20220707_143304_create_sessions;
pub struct Migrator;
#[async_trait::async_trait]
impl MigratorTrait for Migrator {
fn migrations() -> Vec<Box<dyn MigrationTrait>> {
vec![
Box::new(m20220707_092851_create_users::Migration),
Box::new(m20220707_112339_create_devices::Migration),
Box::new(m20220707_143304_create_sessions::Migration),
]
}
}

View File

@ -0,0 +1,49 @@
use neo_entity::users::{self, Entity as User};
use sea_orm_migration::prelude::*;
pub struct Migration;
impl MigrationName for Migration {
fn name(&self) -> &str {
"m20220707_092851_create_users"
}
}
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.create_table(
Table::create()
.table(User)
.if_not_exists()
.col(
ColumnDef::new(users::Column::Uuid)
.uuid()
.primary_key()
.not_null(),
)
.col(ColumnDef::new(users::Column::UserId).string().not_null())
.col(
ColumnDef::new(users::Column::DisplayName)
.string()
.not_null(),
)
.col(
ColumnDef::new(users::Column::PasswordHash)
.string()
.not_null(),
)
.to_owned(),
)
.await?;
manager
.create_index(
Index::create()
.table(User)
.col(users::Column::UserId)
.to_owned(),
)
.await
}
}

View File

@ -0,0 +1,57 @@
use neo_entity::devices::{self, Entity as Device};
use sea_orm_migration::prelude::*;
pub struct Migration;
impl MigrationName for Migration {
fn name(&self) -> &str {
"m20220707_112339_create_devices.rs"
}
}
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.create_table(
Table::create()
.table(Device)
.if_not_exists()
.col(
ColumnDef::new(devices::Column::Uuid)
.uuid()
.primary_key()
.not_null(),
)
.col(ColumnDef::new(devices::Column::UserUuid).uuid().not_null())
.col(
ColumnDef::new(devices::Column::DeviceId)
.string()
.not_null(),
)
.col(
ColumnDef::new(devices::Column::DisplayName)
.string()
.not_null(),
)
.to_owned(),
)
.await?;
manager
.create_index(
Index::create()
.table(Device)
.col(devices::Column::DeviceId)
.to_owned(),
)
.await?;
manager
.create_index(
Index::create()
.table(Device)
.col(devices::Column::UserUuid)
.to_owned(),
)
.await
}
}

View File

@ -0,0 +1,44 @@
use neo_entity::sessions::{self, Entity as Session};
use sea_orm_migration::prelude::*;
pub struct Migration;
impl MigrationName for Migration {
fn name(&self) -> &str {
"m20220707_143304_create_sessions.rs"
}
}
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.create_table(
Table::create()
.table(Session)
.if_not_exists()
.col(
ColumnDef::new(sessions::Column::Uuid)
.uuid()
.primary_key()
.not_null(),
)
.col(
ColumnDef::new(sessions::Column::DeviceUuid)
.uuid()
.not_null(),
)
.col(ColumnDef::new(sessions::Column::Key).string().not_null())
.to_owned(),
)
.await?;
manager
.create_index(
Index::create()
.table(Session)
.col(sessions::Column::DeviceUuid)
.to_owned(),
)
.await
}
}

View File

@ -1,10 +1,8 @@
[package]
name = "matrix"
name = "neo"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
tokio = { version = "1.17", features = ["full"] }
axum = "0.5"
@ -13,7 +11,6 @@ tracing-subscriber = { version = "0.3", features = ["env-filter"] }
serde = {version = "1.0", features = ["derive"] }
serde_json = "1.0"
tower-http = { version = "0.2", features = ["cors", "trace"]}
#sqlx = { version = "0.5", features = ["sqlite", "macros", "runtime-tokio-rustls", "offline"] }
anyhow = "1.0"
thiserror = "1.0"
argon2 = { version = "0.4", features = ["std"] }
@ -23,4 +20,5 @@ ruma = { version = "0.6.4", features = ["client-api", "compat"] }
axum-macros = "0.2.2"
http = "0.2.8"
sea-orm = { version = "^0.8", features = ["sqlx-sqlite", "runtime-tokio-native-tls", "macros"], default-features = false }
neo-entity = { version = "*", path = "../neo-entity" }
neo-entity = { version = "*", path = "../neo-entity" }
neo-migration = { version = "*", path = "../neo-migration" }

View File

@ -27,7 +27,7 @@ pub enum ApiError {
AuthenticationError(#[from] AuthenticationError),
#[error("Database Error")]
DBError(#[from] sqlx::Error),
DBError(#[from] sea_orm::DbErr),
#[error("Generic Error")]
Generic(anyhow::Error),
@ -36,7 +36,7 @@ pub enum ApiError {
impl From<anyhow::Error> for ApiError {
fn from(err: anyhow::Error) -> Self {
map_err!(err,
sqlx::Error => ApiError::DBError,
sea_orm::DbErr => ApiError::DBError,
RegistrationError => ApiError::RegistrationError,
AuthenticationError => ApiError::AuthenticationError
);

View File

@ -5,11 +5,13 @@ use axum::{
routing::{get, post},
Extension,
};
use neo_entity::{
devices::{self, Entity as Device},
sessions::{self, Entity as Session},
users::{self, Entity as User},
};
// use neo_entity::{
// devices::{self, Entity as Device},
// sessions::{self, Entity as Session},
// users::{self, Entity as User},
// };
use neo_entity::prelude::*;
use sea_orm::{ActiveModelTrait, ColumnTrait, DatabaseConnection, EntityTrait, QueryFilter, Set};
use crate::{
@ -66,7 +68,7 @@ async fn login(
.one(&db)
.await?
.ok_or(AuthenticationError::InvalidUserId)?;
//todo check password
// TODO: check password
//db_user
// .password_correct(&password)
// .map_err(|_| AuthenticationError::Forbidden)?;
@ -95,7 +97,7 @@ async fn login(
};
device.insert(&db).await?
};
let session = sessions::ActiveModel {
device_uuid: Set(device.uuid),
..Default::default()
@ -123,7 +125,8 @@ async fn get_username_available(
let username = params
.get("username")
.ok_or(RegistrationError::MissingUserId)?.to_owned();
.ok_or(RegistrationError::MissingUserId)?
.to_owned();
let user_id = ruma::UserId::parse_with_server_name(username, &config.server_name)
.map_err(|_| RegistrationError::InvalidUserId)?;
@ -161,30 +164,44 @@ async fn post_register(
return Err(AuthenticationError::InvalidUserId.into());
};
if User::exists(&db, &user_id).await? {
return Err(ApiError::from(RegistrationError::UserIdTaken));
}
User::find()
.filter(users::Column::UserId.eq(user_id.as_str()))
.one(&db)
.await?
.ok_or(RegistrationError::UserIdTaken)?;
let display_name = req
.initial_device_display_name
.unwrap_or_else(|| "Random Display Name".into());
let user = User::new(&user_id, &user_id.to_string(), &password)?
.create(&db)
.await?;
let device = Device::new(
&user,
uuid::Uuid::new_v4().to_string().as_ref(),
&display_name,
)?
.create(&db)
// TODO: Hash password
let user = users::ActiveModel {
user_id: Set(user_id.to_string()),
display_name: Set(user_id.to_string()),
password_hash: Set(password),
..Default::default()
}
.insert(&db)
.await?;
let device = devices::ActiveModel {
display_name: Set(display_name),
user_uuid: Set(user.uuid),
..Default::default()
}
.insert(&db)
.await?;
let mut response = Response::new(
ruma::UserId::parse(&user.user_id).map_err(|e| anyhow::anyhow!(e))?,
);
if !req.inhibit_login {
let session = Session::new(&device)?.create(&db).await?;
let session = sessions::ActiveModel {
device_uuid: Set(device.uuid),
..Default::default()
}
.insert(&db)
.await?;
response.access_token = Some(session.key);
}
if !req.inhibit_login {
@ -202,36 +219,48 @@ async fn post_register(
.ok_or("password missing")
.map_err(|_| RegistrationError::AdditionalAuthenticationInformation)?;
let user_id = if let Some(username) = req.username {
let user_id = UserId::new(&username, config.server_name())?;
ruma::UserId::parse(user_id.to_string()).map_err(|e| anyhow::anyhow!(e))?
ruma::UserId::parse_with_server_name(username, &config.server_name)
.map_err(|e| anyhow::anyhow!(e))?
} else {
return Err(AuthenticationError::InvalidUserId.into());
};
if User::exists(&db, &user_id).await? {
return Err(RegistrationError::UserIdTaken.into());
}
User::find()
.filter(users::Column::UserId.eq(user_id.as_str()))
.one(&db)
.await?
.ok_or(RegistrationError::UserIdTaken)?;
let display_name = req
.initial_device_display_name
.unwrap_or_else(|| "Random Display Name".into());
let user = User::new(&user_id, &user_id.to_string(), &password)?
.create(&db)
.await?;
let device = Device::new(
&user,
uuid::Uuid::new_v4().to_string().as_ref(),
&display_name,
)?
.create(&db)
let user = users::ActiveModel {
user_id: Set(user_id.to_string()),
display_name: Set(user_id.to_string()),
password_hash: Set(password),
..Default::default()
}
.insert(&db)
.await?;
let device = devices::ActiveModel {
display_name: Set(display_name),
user_uuid: Set(user.uuid),
..Default::default()
}
.insert(&db)
.await?;
let mut response =
Response::new(ruma::UserId::parse(&user.user_id).map_err(|e| anyhow::anyhow!(e))?);
if !req.inhibit_login {
let session = Session::new(&device)?.create(&db).await?;
let session = sessions::ActiveModel {
device_uuid: Set(device.uuid),
..Default::default()
}
.insert(&db)
.await?;
response.access_token = Some(session.key);
}
if !req.inhibit_login {

View File

@ -4,7 +4,7 @@ use axum::routing::post;
use axum::Extension;
use crate::api::client_server::errors::api_error::ApiError;
use crate::models::users::User;
use neo_entity::prelude::*;
use crate::ruma_wrapper::{RumaRequest, RumaResponse};
use ruma::api::client::filter;

View File

@ -4,7 +4,7 @@ use axum::routing::post;
use axum::Extension;
use crate::api::client_server::errors::api_error::ApiError;
use crate::models::users::User;
use neo_entity::prelude::*;
use crate::ruma_wrapper::{RumaRequest, RumaResponse};
use ruma::api::client::keys;

View File

@ -4,7 +4,7 @@ use axum::routing::{get, put};
use axum::Extension;
use crate::api::client_server::errors::api_error::ApiError;
use crate::models::users::User;
use neo_entity::prelude::*;
use crate::ruma_wrapper::{RumaRequest, RumaResponse};
use ruma::api::client::presence;

View File

@ -4,7 +4,7 @@ use axum::routing::get;
use axum::Extension;
use crate::api::client_server::errors::api_error::ApiError;
use crate::models::users::User;
use neo_entity::prelude::*;
use crate::ruma_wrapper::{RumaRequest, RumaResponse};
use ruma::api::client::push;
@ -18,6 +18,7 @@ pub fn routes() -> axum::Router {
async fn get_pushrules(
Extension(_user): Extension<Arc<User>>,
RumaRequest(_req): RumaRequest<push::get_pushrules_all::v3::IncomingRequest>
) -> Result<RumaResponse<push::get_pushrules_all::v3::Response>, ApiError> {
use push::get_pushrules_all::v3::*;

View File

@ -4,8 +4,8 @@ use axum::routing::get;
use axum::Extension;
use crate::api::client_server::errors::api_error::ApiError;
use crate::models::users::User;
use crate::ruma_wrapper::{RumaRequest, RumaResponse};
use neo_entity::prelude::*;
use ruma::api::client::sync;

View File

@ -2,8 +2,10 @@ use std::{collections::BTreeMap, sync::Arc};
use axum::{routing::get, Extension};
use neo_entity::prelude::*;
use crate::{
api::client_server::errors::api_error::ApiError, models::users::User,
api::client_server::errors::api_error::ApiError,
ruma_wrapper::RumaResponse,
};

View File

@ -13,10 +13,10 @@ use tower_http::{
trace::{DefaultMakeSpan, DefaultOnRequest, DefaultOnResponse, TraceLayer},
};
use tracing::Level;
use neo_migration::{Migrator, MigratorTrait};
mod api;
mod config;
mod models;
mod responses;
mod ruma_wrapper;
mod types;
@ -31,7 +31,8 @@ async fn main() -> anyhow::Result<()> {
let config = Arc::new(Config::default());
let pool = Database::connect(config.db_path).await?;
let pool = Database::connect(config.db_path.clone()).await?;
Migrator::up(&pool, None).await?;
// TODO: set correct CORS headers
let cors = CorsLayer::new()

View File

@ -1,70 +0,0 @@
use sqlx::SqlitePool;
use crate::types::uuid::Uuid;
use super::users::User;
pub struct Device {
pub uuid: Uuid,
pub user_uuid: Uuid,
pub device_id: String,
pub display_name: String,
}
impl Device {
pub fn new(user: &User, device_id: &str, display_name: &str) -> anyhow::Result<Self> {
Ok(Self {
uuid: uuid::Uuid::new_v4().into(),
user_uuid: user.uuid.clone(),
device_id: device_id.to_owned(),
display_name: display_name.to_owned(),
})
}
pub async fn create(&self, conn: &SqlitePool) -> anyhow::Result<Self> {
Ok(sqlx::query_as!(
Self,
"insert into devices(uuid, user_uuid, device_id, display_name)
values(?, ?, ?, ?)
returning uuid as 'uuid: Uuid', user_uuid as 'user_uuid: Uuid', device_id, display_name",
self.uuid,
self.user_uuid,
self.device_id,
self.display_name)
.fetch_one(conn).await?
)
}
pub async fn find_for_user(
conn: &SqlitePool,
user: &User,
device_id: &str,
) -> anyhow::Result<Self> {
let user_uuid = user.uuid.clone();
Ok(sqlx::query_as!(
Self,
"select uuid as 'uuid: Uuid', user_uuid as 'user_uuid: Uuid', device_id, display_name from devices where user_uuid = ? and device_id = ?",
user_uuid, device_id)
.fetch_one(conn).await?
)
}
pub async fn find_by_uuid(conn: &SqlitePool, uuid: &Uuid) -> anyhow::Result<Self> {
Ok(sqlx::query_as!(
Self,
"select uuid as 'uuid: Uuid', user_uuid as 'user_uuid: Uuid', device_id, display_name from devices where uuid = ?",
uuid)
.fetch_one(conn).await?
)
}
pub async fn user(&self, conn: &SqlitePool) -> anyhow::Result<User> {
User::find_by_uuid(conn, &self.user_uuid).await
}
/// Get the device's id.
#[must_use]
pub fn uuid(&self) -> &Uuid {
&self.uuid
}
}

View File

@ -1,73 +0,0 @@
/* use sqlx::SqlitePool;
use crate::types::{uuid::Uuid, event_type::EventType};
use super::{users::User};
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct Event {
uuid: Uuid,
room_uuid: Uuid,
r#type: EventType,
state_key: Option<String>,
sender_uuid: Uuid,
origin_server_ts: i64,
content: String,
}
impl Event {
fn new(
room: &Room,
r#type: EventType,
state_key: Option<String>,
sender: &User,
origin_server_ts: i64,
content: &str,
) -> anyhow::Result<Self> {
Ok(Self {
uuid: uuid::Uuid::new_v4().into(),
room_uuid: room.uuid().to_owned(),
state_key,
r#type,
sender_uuid: sender.uuid().to_owned(),
origin_server_ts,
content: content.to_owned(),
})
}
pub async fn create(&self, conn: &SqlitePool) -> anyhow::Result<Self> {
Ok(sqlx::query_as!(
Self,
"insert into events(uuid, room_uuid, type, state_key, sender_uuid, origin_server_ts, content)
values(?, ?, ?, ?, ?, ?, ?)
returning uuid as 'uuid: Uuid', room_uuid as 'room_uuid: Uuid', type as 'type: EventType', state_key, sender_uuid as 'sender_uuid: Uuid', origin_server_ts, content",
self.uuid,
self.room_uuid,
self.r#type,
self.state_key,
self.sender_uuid,
self.origin_server_ts,
self.content
)
.fetch_one(conn)
.await?)
}
pub async fn all_for_room(conn: &SqlitePool, room: &Room) -> anyhow::Result<Vec<Event>> {
let room_uuid = room.uuid();
Ok(sqlx::query_as!(
Self,
"select uuid as 'uuid: Uuid', room_uuid as 'room_uuid: Uuid', type as 'type: EventType', state_key, sender_uuid as 'sender_uuid: Uuid', origin_server_ts, content
from events
where room_uuid = ?",
room_uuid
)
.fetch_all(conn)
.await?)
}
pub fn content(&self) -> serde_json::Value {
serde_json::from_str(&self.content).expect("has to be valid json")
}
}
*/

View File

@ -1,4 +0,0 @@
pub mod devices;
pub mod events;
pub mod sessions;
pub mod users;

View File

@ -1,54 +0,0 @@
use rand::{distributions::Alphanumeric, thread_rng, Rng};
use sqlx::SqlitePool;
use crate::types::uuid::Uuid;
use super::devices::Device;
pub struct Session {
pub uuid: Uuid,
pub device_uuid: Uuid,
pub key: String,
}
impl Session {
pub fn new(device: &Device) -> anyhow::Result<Self> {
let mut rng = thread_rng();
let key: String = (0..256).map(|_| rng.sample(Alphanumeric) as char).collect();
Ok(Self {
uuid: uuid::Uuid::new_v4().into(),
device_uuid: device.uuid().clone(),
key,
})
}
pub async fn create(&self, conn: &SqlitePool) -> anyhow::Result<Self> {
Ok(sqlx::query_as!(
Self,
"insert into sessions(uuid, device_uuid, key)
values(?, ?, ?)
returning uuid as 'uuid: Uuid', device_uuid as 'device_uuid: Uuid', key",
self.uuid,
self.device_uuid,
self.key
)
.fetch_one(conn)
.await?)
}
pub async fn find_by_key(conn: &SqlitePool, key: &str) -> anyhow::Result<Option<Self>> {
Ok(sqlx::query_as!(
Self,
"select uuid as 'uuid: Uuid', device_uuid as 'device_uuid: Uuid', key
from sessions where key = ?",
key
)
.fetch_optional(conn)
.await?)
}
pub async fn device(&self, conn: &SqlitePool) -> anyhow::Result<Device> {
Device::find_by_uuid(conn, &self.device_uuid).await
}
}

View File

@ -1,101 +0,0 @@
use crate::types::uuid::Uuid;
use argon2::{password_hash::SaltString, Argon2, PasswordHash, PasswordHasher, PasswordVerifier};
use rand::rngs::OsRng;
use ruma::OwnedUserId;
use sqlx::SqlitePool;
#[derive(Debug)]
pub struct User {
pub uuid: Uuid,
pub user_id: String,
pub display_name: String,
pub password_hash: String,
}
impl User {
pub fn new(user_id: &OwnedUserId, display_name: &str, password: &str) -> anyhow::Result<Self> {
let argon2 = Argon2::default();
let salt = SaltString::generate(OsRng);
let password_hash = argon2
.hash_password(password.as_bytes(), &salt)?
.to_string();
Ok(Self {
uuid: uuid::Uuid::new_v4().into(),
user_id: user_id.to_string(),
display_name: display_name.to_owned(),
password_hash,
})
}
pub async fn exists(conn: &SqlitePool, user_id: &OwnedUserId) -> anyhow::Result<bool> {
let user_id = user_id.to_string();
Ok(
sqlx::query!("select user_id from users where user_id = ?", user_id)
.fetch_optional(conn)
.await?
.is_some(),
)
}
pub async fn create(&self, conn: &SqlitePool) -> anyhow::Result<Self> {
Ok(sqlx::query_as!(
Self,
"insert into users(uuid, user_id, display_name, password_hash)
values (?, ?, ?, ?)
returning uuid as 'uuid: Uuid', user_id, display_name, password_hash",
self.uuid,
self.user_id,
self.display_name,
self.password_hash
)
.fetch_one(conn)
.await?)
}
pub async fn update(&self, conn: &SqlitePool) -> anyhow::Result<Self> {
Ok(sqlx::query_as!(
Self,
"update users set uuid = ?, user_id = ?, display_name = ?, password_hash = ?
where uuid = ?
returning uuid as 'uuid: Uuid', user_id, display_name, password_hash",
self.uuid,
self.user_id,
self.display_name,
self.password_hash,
self.uuid
)
.fetch_one(conn)
.await?)
}
pub async fn find_by_uuid(conn: &SqlitePool, uuid: &Uuid) -> anyhow::Result<Self> {
Ok(sqlx::query_as!(
Self,
"select uuid as 'uuid: Uuid', user_id, display_name, password_hash
from users where uuid = ?",
uuid
)
.fetch_one(conn)
.await?)
}
pub async fn find_by_user_id(conn: &SqlitePool, user_id: &str) -> anyhow::Result<Self> {
Ok(sqlx::query_as!(
Self,
"select uuid as 'uuid: Uuid', user_id, display_name, password_hash
from users where user_id = ?",
user_id
)
.fetch_one(conn)
.await?)
}
pub fn password_correct(&self, password: &str) -> anyhow::Result<bool> {
let password_hash = PasswordHash::new(&self.password_hash)?;
Ok(Argon2::default()
.verify_password(password.as_bytes(), &password_hash)
.is_ok())
}
}