Initial
This commit is contained in:
		
						commit
						f7fefe300d
					
				
							
								
								
									
										2
									
								
								.cargo/config.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								.cargo/config.toml
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,2 @@
 | 
				
			||||||
 | 
					[env]
 | 
				
			||||||
 | 
					RUST_LOG="debug,sqlx=info"
 | 
				
			||||||
							
								
								
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,4 @@
 | 
				
			||||||
 | 
					/target
 | 
				
			||||||
 | 
					/**/target
 | 
				
			||||||
 | 
					/db.sqite
 | 
				
			||||||
 | 
					/src/db/models
 | 
				
			||||||
							
								
								
									
										3010
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										3010
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										22
									
								
								Cargo.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								Cargo.toml
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,22 @@
 | 
				
			||||||
 | 
					[package]
 | 
				
			||||||
 | 
					name = "rtmc-be"
 | 
				
			||||||
 | 
					version = "0.1.0"
 | 
				
			||||||
 | 
					edition = "2021"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[dependencies]
 | 
				
			||||||
 | 
					anyhow = "1.0.92"
 | 
				
			||||||
 | 
					argon2 = { version = "0.5.3", features = ["simple"] }
 | 
				
			||||||
 | 
					axum = { version = "0.7.7", features = ["ws"] }
 | 
				
			||||||
 | 
					axum-extra = { version = "0.9.4", features = ["typed-header"] }
 | 
				
			||||||
 | 
					chrono = "0.4.38"
 | 
				
			||||||
 | 
					clap = "4.5.20"
 | 
				
			||||||
 | 
					env_logger = "0.11.5"
 | 
				
			||||||
 | 
					futures-util = "0.3.31"
 | 
				
			||||||
 | 
					headers = "0.4.0"
 | 
				
			||||||
 | 
					lazy_static = "1.5.0"
 | 
				
			||||||
 | 
					log = "0.4.22"
 | 
				
			||||||
 | 
					sea-orm = { version = "1.1.0", features = ["macros", "runtime-tokio-rustls", "sqlx-sqlite", "with-json", "with-uuid"] }
 | 
				
			||||||
 | 
					serde = { version = "1.0.214", features = ["derive"] }
 | 
				
			||||||
 | 
					serde_json = "1.0.132"
 | 
				
			||||||
 | 
					tokio = { version = "1.41.0", features = ["full"] }
 | 
				
			||||||
 | 
					uuid = { version = "1.11.0", features = ["serde", "v4"] }
 | 
				
			||||||
							
								
								
									
										64
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,64 @@
 | 
				
			||||||
 | 
					# setup
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```sh
 | 
				
			||||||
 | 
					cargo install sea-orm-cli
 | 
				
			||||||
 | 
					sea-orm-cli generate entity -o src/db/models # do this every time you edit the migrations, or first time on clone
 | 
				
			||||||
 | 
					cargo build
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# api docs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					u-token = user token
 | 
				
			||||||
 | 
					p-token = pc token
 | 
				
			||||||
 | 
					a-token = u-token or p-token
 | 
				
			||||||
 | 
					pid     = cc:t pc id
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GET  - /ws                   (nothing required on first req, see ws docs for more info)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					POST - /api/user/login       (no token (duh),  json body with email, pwd, returns json with token)
 | 
				
			||||||
 | 
					POST - /api/user/add         (u-token in header, json body with full user info)
 | 
				
			||||||
 | 
					POST - /api/user/:id/edit    (u-token in header, json body with data to replace with)
 | 
				
			||||||
 | 
					POST - /api/user/:id/remove  (u-token in header, no body required)
 | 
				
			||||||
 | 
					GET  - /api/user/:id/info    (u-token in header, get back json)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GET  - /api/cct/                  (a-token in header, gets a list of all groups)
 | 
				
			||||||
 | 
					GET  - /api/cct/:group/           (a-token in header, gets a list of all pid's)
 | 
				
			||||||
 | 
					GET  - /api/cct/:group/:pid/      (a-token in header, gets a list of all values for that pc)
 | 
				
			||||||
 | 
					GET  - /api/cct/:group/:pid/:val  (a-token in header, gets a value from a pc in a group)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					POST  - /api/cct/group/add                  (a-token in header, adds a group)
 | 
				
			||||||
 | 
					POST  - /api/cct/:group/edit                (a-token in header, edits a group)
 | 
				
			||||||
 | 
					POST  - /api/cct/:group/pc/add              (a-token in header, adds a pc to a group)
 | 
				
			||||||
 | 
					POST  - /api/cct/:group/:pid/edit           (a-token in header, edits a pc in a group)
 | 
				
			||||||
 | 
					POST  - /api/cct/:group/:pid/val/add        (a-token in header, adds a value to a pc in a group)
 | 
				
			||||||
 | 
					POST  - /api/cct/:group/:pid/:val/edit      (a-token in header, edits value info in a pc in a group)
 | 
				
			||||||
 | 
					POST  - /api/cct/:group/:pid/:val/set      (a-token in header, sets a value in a pc in a group)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					==========
 | 
				
			||||||
 | 
					ws
 | 
				
			||||||
 | 
					==========
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					`ws_msg_t`:
 | 
				
			||||||
 | 
					0: heartbeat ping
 | 
				
			||||||
 | 
					1: server to client
 | 
				
			||||||
 | 
					2: client to server
 | 
				
			||||||
 | 
					`msg_t`:
 | 
				
			||||||
 | 
					TODO!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```json
 | 
				
			||||||
 | 
					{ // low level message
 | 
				
			||||||
 | 
					    "ws_msg_t": 0, // `ws_msg_t`
 | 
				
			||||||
 | 
					    "ws_msg": { // high level message
 | 
				
			||||||
 | 
					        "auth": "Token", // Auth token
 | 
				
			||||||
 | 
					        "msg": { // Data field
 | 
				
			||||||
 | 
					            "keypad": {
 | 
				
			||||||
 | 
					                "DoorOpenEv": { // "DataType": "Value, can be a struct or anything"
 | 
				
			||||||
 | 
					                    "user": "uid",
 | 
				
			||||||
 | 
					                    "timestamp": 123456,
 | 
				
			||||||
 | 
					                    "door_id": "1234-abcd-1234-abcd"
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        },  
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
							
								
								
									
										2201
									
								
								migration/Cargo.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										2201
									
								
								migration/Cargo.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										22
									
								
								migration/Cargo.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								migration/Cargo.toml
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,22 @@
 | 
				
			||||||
 | 
					[package]
 | 
				
			||||||
 | 
					name = "migration"
 | 
				
			||||||
 | 
					version = "0.1.0"
 | 
				
			||||||
 | 
					edition = "2021"
 | 
				
			||||||
 | 
					publish = false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[lib]
 | 
				
			||||||
 | 
					name = "migration"
 | 
				
			||||||
 | 
					path = "src/lib.rs"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[dependencies]
 | 
				
			||||||
 | 
					async-std = { version = "1", features = ["attributes", "tokio1"] }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[dependencies.sea-orm-migration]
 | 
				
			||||||
 | 
					version = "1.1.0"
 | 
				
			||||||
 | 
					features = [
 | 
				
			||||||
 | 
					  # Enable at least one `ASYNC_RUNTIME` and `DATABASE_DRIVER` feature if you want to run migration via CLI.
 | 
				
			||||||
 | 
					  # View the list of supported features at https://www.sea-ql.org/SeaORM/docs/install-and-config/database-and-async-runtime.
 | 
				
			||||||
 | 
					  # e.g.
 | 
				
			||||||
 | 
					  "runtime-tokio-rustls",  # `ASYNC_RUNTIME` feature
 | 
				
			||||||
 | 
					  "sqlx-sqlite",         # `DATABASE_DRIVER` feature
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
							
								
								
									
										41
									
								
								migration/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								migration/README.md
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,41 @@
 | 
				
			||||||
 | 
					# Running Migrator CLI
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Generate a new migration file
 | 
				
			||||||
 | 
					    ```sh
 | 
				
			||||||
 | 
					    cargo run -- generate MIGRATION_NAME
 | 
				
			||||||
 | 
					    ```
 | 
				
			||||||
 | 
					- 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
 | 
				
			||||||
 | 
					    ```
 | 
				
			||||||
							
								
								
									
										19
									
								
								migration/src/lib.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								migration/src/lib.rs
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,19 @@
 | 
				
			||||||
 | 
					pub use sea_orm_migration::prelude::*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					mod m20241102_133640_users;
 | 
				
			||||||
 | 
					mod m20241102_133644_computers;
 | 
				
			||||||
 | 
					mod m20241102_150432_pc_groups;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub struct Migrator;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[async_trait::async_trait]
 | 
				
			||||||
 | 
					impl MigratorTrait for Migrator {
 | 
				
			||||||
 | 
					    fn migrations() -> Vec<Box<dyn MigrationTrait>> {
 | 
				
			||||||
 | 
					        vec![
 | 
				
			||||||
 | 
					            Box::new(m20241102_133640_users::Migration),
 | 
				
			||||||
 | 
					            Box::new(m20241102_133644_computers::Migration),
 | 
				
			||||||
 | 
					            Box::new(m20241102_150432_pc_groups::Migration),
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										68
									
								
								migration/src/m20241102_133640_users.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								migration/src/m20241102_133640_users.rs
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,68 @@
 | 
				
			||||||
 | 
					use sea_orm_migration::prelude::*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(DeriveMigrationName)]
 | 
				
			||||||
 | 
					pub struct Migration;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[async_trait::async_trait]
 | 
				
			||||||
 | 
					impl MigrationTrait for Migration {
 | 
				
			||||||
 | 
					    async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
 | 
				
			||||||
 | 
					        manager
 | 
				
			||||||
 | 
					            .create_table(
 | 
				
			||||||
 | 
					                Table::create()
 | 
				
			||||||
 | 
					                    .table(User::Table)
 | 
				
			||||||
 | 
					                    .if_not_exists()
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(User::Id)
 | 
				
			||||||
 | 
					                        .uuid()
 | 
				
			||||||
 | 
					                        .unique_key()
 | 
				
			||||||
 | 
					                        .not_null()
 | 
				
			||||||
 | 
					                        .primary_key()
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(User::Username)
 | 
				
			||||||
 | 
					                        .string()
 | 
				
			||||||
 | 
					                        .unique_key()
 | 
				
			||||||
 | 
					                        .not_null()
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(User::Email)
 | 
				
			||||||
 | 
					                        .string()
 | 
				
			||||||
 | 
					                        .unique_key()
 | 
				
			||||||
 | 
					                        .not_null()
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(User::PwdHash)
 | 
				
			||||||
 | 
					                        .string()
 | 
				
			||||||
 | 
					                        .not_null()
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(User::PwdSalt)
 | 
				
			||||||
 | 
					                        .string()
 | 
				
			||||||
 | 
					                        .not_null()
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(User::IsAdministrator)
 | 
				
			||||||
 | 
					                        .boolean()
 | 
				
			||||||
 | 
					                        .not_null()
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(User::CreatedAt)
 | 
				
			||||||
 | 
					                        .date_time()
 | 
				
			||||||
 | 
					                        .not_null()
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					                    .to_owned(),
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            .await
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
 | 
				
			||||||
 | 
					        manager
 | 
				
			||||||
 | 
					            .drop_table(Table::drop().table(User::Table).to_owned())
 | 
				
			||||||
 | 
					            .await
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(DeriveIden)]
 | 
				
			||||||
 | 
					enum User {
 | 
				
			||||||
 | 
					    Table,
 | 
				
			||||||
 | 
					    Id,
 | 
				
			||||||
 | 
					    Username,
 | 
				
			||||||
 | 
					    Email,
 | 
				
			||||||
 | 
					    PwdHash,
 | 
				
			||||||
 | 
					    PwdSalt,
 | 
				
			||||||
 | 
					    IsAdministrator,
 | 
				
			||||||
 | 
					    CreatedAt
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										63
									
								
								migration/src/m20241102_133644_computers.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								migration/src/m20241102_133644_computers.rs
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,63 @@
 | 
				
			||||||
 | 
					use sea_orm_migration::prelude::*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(DeriveMigrationName)]
 | 
				
			||||||
 | 
					pub struct Migration;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[async_trait::async_trait]
 | 
				
			||||||
 | 
					impl MigrationTrait for Migration {
 | 
				
			||||||
 | 
					    async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
 | 
				
			||||||
 | 
					        // Replace the sample below with your own migration scripts
 | 
				
			||||||
 | 
					        manager
 | 
				
			||||||
 | 
					            .create_table(
 | 
				
			||||||
 | 
					                Table::create()
 | 
				
			||||||
 | 
					                    .table(Computer::Table)
 | 
				
			||||||
 | 
					                    .if_not_exists()
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(Computer::Id)
 | 
				
			||||||
 | 
					                        .uuid()
 | 
				
			||||||
 | 
					                        .not_null()
 | 
				
			||||||
 | 
					                        .primary_key()
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(Computer::Name)
 | 
				
			||||||
 | 
					                        .string()
 | 
				
			||||||
 | 
					                        .unique_key()
 | 
				
			||||||
 | 
					                        .not_null()
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(Computer::Group)
 | 
				
			||||||
 | 
					                        .string()
 | 
				
			||||||
 | 
					                        .not_null()
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(Computer::Type)
 | 
				
			||||||
 | 
					                        .string()
 | 
				
			||||||
 | 
					                        .not_null()
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(Computer::AccessToken)
 | 
				
			||||||
 | 
					                        .string()
 | 
				
			||||||
 | 
					                        .unique_key()
 | 
				
			||||||
 | 
					                        .not_null()
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(Computer::CreatedAt)
 | 
				
			||||||
 | 
					                        .date_time()
 | 
				
			||||||
 | 
					                        .not_null()
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					                    .to_owned(),
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            .await
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
 | 
				
			||||||
 | 
					        manager
 | 
				
			||||||
 | 
					            .drop_table(Table::drop().table(Computer::Table).to_owned())
 | 
				
			||||||
 | 
					            .await
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(DeriveIden)]
 | 
				
			||||||
 | 
					enum Computer {
 | 
				
			||||||
 | 
					    Table,
 | 
				
			||||||
 | 
					    Id,
 | 
				
			||||||
 | 
					    Name,
 | 
				
			||||||
 | 
					    Group,
 | 
				
			||||||
 | 
					    Type,
 | 
				
			||||||
 | 
					    AccessToken,
 | 
				
			||||||
 | 
					    CreatedAt
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										46
									
								
								migration/src/m20241102_150432_pc_groups.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								migration/src/m20241102_150432_pc_groups.rs
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,46 @@
 | 
				
			||||||
 | 
					use sea_orm_migration::{prelude::*, schema::*};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(DeriveMigrationName)]
 | 
				
			||||||
 | 
					pub struct Migration;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[async_trait::async_trait]
 | 
				
			||||||
 | 
					impl MigrationTrait for Migration {
 | 
				
			||||||
 | 
					    async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
 | 
				
			||||||
 | 
					        manager
 | 
				
			||||||
 | 
					            .create_table(
 | 
				
			||||||
 | 
					                Table::create()
 | 
				
			||||||
 | 
					                    .table(PcGroup::Table)
 | 
				
			||||||
 | 
					                    .if_not_exists()
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(PcGroup::Id)
 | 
				
			||||||
 | 
					                        .uuid()
 | 
				
			||||||
 | 
					                        .unique_key()
 | 
				
			||||||
 | 
					                        .primary_key()
 | 
				
			||||||
 | 
					                        .not_null()
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(PcGroup::Name)
 | 
				
			||||||
 | 
					                        .string()
 | 
				
			||||||
 | 
					                        .not_null()
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(PcGroup::AvailableActions)
 | 
				
			||||||
 | 
					                        .json()
 | 
				
			||||||
 | 
					                        .not_null()
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					                    .to_owned(),
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            .await
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
 | 
				
			||||||
 | 
					        manager
 | 
				
			||||||
 | 
					            .drop_table(Table::drop().table(PcGroup::Table).to_owned())
 | 
				
			||||||
 | 
					            .await
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(DeriveIden)]
 | 
				
			||||||
 | 
					enum PcGroup {
 | 
				
			||||||
 | 
					    Table,
 | 
				
			||||||
 | 
					    Id,
 | 
				
			||||||
 | 
					    Name,
 | 
				
			||||||
 | 
					    AvailableActions,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										6
									
								
								migration/src/main.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								migration/src/main.rs
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,6 @@
 | 
				
			||||||
 | 
					use sea_orm_migration::prelude::*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[async_std::main]
 | 
				
			||||||
 | 
					async fn main() {
 | 
				
			||||||
 | 
					    cli::run_cli(migration::Migrator).await;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										31
									
								
								src/api/mod.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								src/api/mod.rs
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,31 @@
 | 
				
			||||||
 | 
					use crate::context::AppContext;
 | 
				
			||||||
 | 
					use axum::{
 | 
				
			||||||
 | 
					    routing::{get, post},
 | 
				
			||||||
 | 
					    http::StatusCode,
 | 
				
			||||||
 | 
					    Json, Router,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub mod routes;
 | 
				
			||||||
 | 
					pub mod ws;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async fn get_api_info() -> String {
 | 
				
			||||||
 | 
					    format!("API v{}", env!("CARGO_PKG_VERSION"))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub async fn start_api(ctx: AppContext) {
 | 
				
			||||||
 | 
					    // build our application with a route
 | 
				
			||||||
 | 
					    let app = Router::new()
 | 
				
			||||||
 | 
					        // `GET /` goes to `root`
 | 
				
			||||||
 | 
					        .route("/api/", get(get_api_info))
 | 
				
			||||||
 | 
					        .route("/ws/", get(ws::WsHandler::ws_handler))
 | 
				
			||||||
 | 
					        .with_state(ctx);
 | 
				
			||||||
 | 
					        // `POST /users` goes to `create_user`
 | 
				
			||||||
 | 
					        // .route("/users", post(create_user));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // run our app with hyper, listening globally on port 3000
 | 
				
			||||||
 | 
					    log::info!("Listening on http://0.0.0.0:3000");
 | 
				
			||||||
 | 
					    let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
 | 
				
			||||||
 | 
					    axum::serve(listener, app).await.unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										0
									
								
								src/api/routes/cct/event/mod.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								src/api/routes/cct/event/mod.rs
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										0
									
								
								src/api/routes/cct/event/typ.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								src/api/routes/cct/event/typ.rs
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										0
									
								
								src/api/routes/cct/login.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								src/api/routes/cct/login.rs
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										3
									
								
								src/api/routes/cct/mod.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								src/api/routes/cct/mod.rs
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,3 @@
 | 
				
			||||||
 | 
					mod login;
 | 
				
			||||||
 | 
					mod register;
 | 
				
			||||||
 | 
					mod event;
 | 
				
			||||||
							
								
								
									
										0
									
								
								src/api/routes/cct/register.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								src/api/routes/cct/register.rs
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										0
									
								
								src/api/routes/data/mod.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								src/api/routes/data/mod.rs
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										2
									
								
								src/api/routes/mod.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								src/api/routes/mod.rs
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,2 @@
 | 
				
			||||||
 | 
					pub mod cct;
 | 
				
			||||||
 | 
					pub mod user;
 | 
				
			||||||
							
								
								
									
										0
									
								
								src/api/routes/user/add.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								src/api/routes/user/add.rs
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										0
									
								
								src/api/routes/user/edit.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								src/api/routes/user/edit.rs
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										0
									
								
								src/api/routes/user/login.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								src/api/routes/user/login.rs
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										14
									
								
								src/api/routes/user/mod.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/api/routes/user/mod.rs
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,14 @@
 | 
				
			||||||
 | 
					use axum::extract::State;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use crate::context::AppContext;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub mod add;
 | 
				
			||||||
 | 
					pub mod edit;
 | 
				
			||||||
 | 
					pub mod login;
 | 
				
			||||||
 | 
					pub mod remove;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async fn handler(State(ctx): State<AppContext>) -> String {
 | 
				
			||||||
 | 
					    format!(":333")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										0
									
								
								src/api/routes/user/remove.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								src/api/routes/user/remove.rs
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										116
									
								
								src/api/ws/mod.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								src/api/ws/mod.rs
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,116 @@
 | 
				
			||||||
 | 
					use std::{collections::HashMap, sync::mpsc::{self, Receiver, Sender}};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use axum::{body::HttpBody, extract::{ws::WebSocket, State, WebSocketUpgrade}, http::StatusCode, response::Response};
 | 
				
			||||||
 | 
					use axum_extra::TypedHeader;
 | 
				
			||||||
 | 
					use chrono::{DateTime, Utc};
 | 
				
			||||||
 | 
					use futures_util::{stream::{SplitSink, SplitStream}, StreamExt};
 | 
				
			||||||
 | 
					use headers::{authorization::Bearer, Authorization};
 | 
				
			||||||
 | 
					use sea_orm::prelude::Uuid;
 | 
				
			||||||
 | 
					use serde::{Deserialize, Serialize};
 | 
				
			||||||
 | 
					use tokio::sync::Mutex;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use crate::context::AppContext;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					lazy_static::lazy_static!(
 | 
				
			||||||
 | 
					    pub static ref WS_CLIENTS: Mutex<HashMap<Uuid, WsClient>> = Mutex::new(HashMap::new());
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug)]
 | 
				
			||||||
 | 
					pub struct WsClient {
 | 
				
			||||||
 | 
					    rx: Receiver<WsMessage>,
 | 
				
			||||||
 | 
					    tx: Sender<WsMessage>,
 | 
				
			||||||
 | 
					    alive: bool,
 | 
				
			||||||
 | 
					    last_heartbeat: DateTime<Utc>
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl WsClient {
 | 
				
			||||||
 | 
					    pub fn new(rx: Receiver<WsMessage>, tx: Sender<WsMessage>) -> Self {
 | 
				
			||||||
 | 
					        Self {
 | 
				
			||||||
 | 
					            rx, tx, 
 | 
				
			||||||
 | 
					            alive: false,
 | 
				
			||||||
 | 
					            last_heartbeat: chrono::Utc::now()
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug, Clone)]
 | 
				
			||||||
 | 
					pub struct WsHandler {
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl WsHandler {
 | 
				
			||||||
 | 
					    pub fn new() -> Self {
 | 
				
			||||||
 | 
					        Self {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    pub async fn ws_handler(ws: WebSocketUpgrade, State(ctx): State<AppContext>, TypedHeader(token): TypedHeader<Authorization<Bearer>>) -> Response {
 | 
				
			||||||
 | 
					        let token = token.0.token().to_string();
 | 
				
			||||||
 | 
					        let Ok(token) = Uuid::parse_str(&token) else {
 | 
				
			||||||
 | 
					            todo!()
 | 
				
			||||||
 | 
					            // return Response::status(Body)
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        ws.on_upgrade(move |socket| Self::handle_socket(socket, token))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    async fn handle_socket(socket: WebSocket, token: Uuid) {
 | 
				
			||||||
 | 
					        let (sender, receiver) = socket.split();
 | 
				
			||||||
 | 
					        let (r_tx, from_socket) = mpsc::channel();
 | 
				
			||||||
 | 
					        let (to_socket, s_rx) = mpsc::channel();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        async fn send(sender: SplitSink<WebSocket, axum::extract::ws::Message>, s_rx: mpsc::Receiver<WsMessage>) {
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        async fn recv(mut receiver: SplitStream<WebSocket>, tx: mpsc::Sender<WsMessage>) {
 | 
				
			||||||
 | 
					            while let Some(msg) = receiver.next().await {
 | 
				
			||||||
 | 
					                let Ok(msg) = msg else {
 | 
				
			||||||
 | 
					                    return;
 | 
				
			||||||
 | 
					                };
 | 
				
			||||||
 | 
					                let Ok(msg) = msg.to_text() else {
 | 
				
			||||||
 | 
					                    return;
 | 
				
			||||||
 | 
					                };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        tokio::spawn(recv(receiver, r_tx));
 | 
				
			||||||
 | 
					        tokio::spawn(send(sender, s_rx));
 | 
				
			||||||
 | 
					        Self::add_client(token, from_socket, to_socket).await;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    async fn add_client(token: Uuid, rx: Receiver<WsMessage>, tx: Sender<WsMessage>) {
 | 
				
			||||||
 | 
					        WS_CLIENTS.lock().await.insert(token, WsClient::new(rx, tx));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug, Clone, Serialize, Deserialize)]
 | 
				
			||||||
 | 
					pub struct WsMessage {
 | 
				
			||||||
 | 
					    pub ws_msg_t: usize,
 | 
				
			||||||
 | 
					    pub ws_msg: Message,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug, Clone, Serialize, Deserialize)]
 | 
				
			||||||
 | 
					pub struct Message {
 | 
				
			||||||
 | 
					    pub auth: Uuid,
 | 
				
			||||||
 | 
					    pub msg: MessageType
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug, Clone, Serialize, Deserialize)]
 | 
				
			||||||
 | 
					pub enum MessageType {
 | 
				
			||||||
 | 
					    Keypad(KeypadMessageType)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug, Clone, Serialize, Deserialize)]
 | 
				
			||||||
 | 
					pub enum KeypadMessageType {
 | 
				
			||||||
 | 
					    DoorOpenEv {
 | 
				
			||||||
 | 
					        user: Uuid,
 | 
				
			||||||
 | 
					        timestamp: usize,
 | 
				
			||||||
 | 
					        door_id: Uuid
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										26
									
								
								src/context/mod.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								src/context/mod.rs
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,26 @@
 | 
				
			||||||
 | 
					use std::sync::{Arc, Mutex, MutexGuard, PoisonError};
 | 
				
			||||||
 | 
					use crate::{api::ws::WsHandler, db::Database};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug, Clone)]
 | 
				
			||||||
 | 
					pub struct AppContext {
 | 
				
			||||||
 | 
					    db: Database,
 | 
				
			||||||
 | 
					    ws: WsHandler
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl AppContext {
 | 
				
			||||||
 | 
					    pub fn new(db: Database) -> Self {
 | 
				
			||||||
 | 
					        Self {
 | 
				
			||||||
 | 
					            db,
 | 
				
			||||||
 | 
					            ws: WsHandler::new()
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn db(&mut self) -> &mut Database {
 | 
				
			||||||
 | 
					        &mut self.db
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    pub fn ws(&mut self) -> &mut WsHandler {
 | 
				
			||||||
 | 
					        &mut self.ws
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										36
									
								
								src/db/mod.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								src/db/mod.rs
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,36 @@
 | 
				
			||||||
 | 
					use std::time::Duration;
 | 
				
			||||||
 | 
					use sea_orm::{ConnectOptions, Database as SODatabase, DatabaseConnection};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					mod models;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// to update the models run `sea-orm-cli generate entity -o src/db/models`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug, Clone)]
 | 
				
			||||||
 | 
					pub struct Database {
 | 
				
			||||||
 | 
					    db: DatabaseConnection
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Database {
 | 
				
			||||||
 | 
					    pub fn new() -> Self {
 | 
				
			||||||
 | 
					        Self {
 | 
				
			||||||
 | 
					            db: DatabaseConnection::Disconnected
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    pub async fn connect(&mut self) -> anyhow::Result<()> {
 | 
				
			||||||
 | 
					        log::info!("Connecting to SQlite database at ./db.sqlite");
 | 
				
			||||||
 | 
					        let mut opt = ConnectOptions::new("sqlite://db.sqlite?mode=rwc");
 | 
				
			||||||
 | 
					        opt.max_connections(100)
 | 
				
			||||||
 | 
					            .min_connections(5)
 | 
				
			||||||
 | 
					            .connect_timeout(Duration::from_secs(8))
 | 
				
			||||||
 | 
					            .acquire_timeout(Duration::from_secs(8))
 | 
				
			||||||
 | 
					            .idle_timeout(Duration::from_secs(8))
 | 
				
			||||||
 | 
					            .max_lifetime(Duration::from_secs(8))
 | 
				
			||||||
 | 
					            .sqlx_logging(true)
 | 
				
			||||||
 | 
					            .sqlx_logging_level(log::LevelFilter::Debug);
 | 
				
			||||||
 | 
					        self.db = SODatabase::connect(opt).await?;
 | 
				
			||||||
 | 
					        log::info!("Connection successful");
 | 
				
			||||||
 | 
					        Ok(())
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										38
									
								
								src/main.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								src/main.rs
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,38 @@
 | 
				
			||||||
 | 
					use api::ws::{KeypadMessageType, Message, WsMessage};
 | 
				
			||||||
 | 
					use sea_orm::prelude::Uuid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					mod api;
 | 
				
			||||||
 | 
					mod db;
 | 
				
			||||||
 | 
					mod context;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[tokio::main]
 | 
				
			||||||
 | 
					async fn main() -> anyhow::Result<()> {
 | 
				
			||||||
 | 
					    env_logger::init();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let msg = WsMessage {
 | 
				
			||||||
 | 
					        ws_msg_t: 0,
 | 
				
			||||||
 | 
					        ws_msg: Message {
 | 
				
			||||||
 | 
					            auth: Uuid::new_v4(),
 | 
				
			||||||
 | 
					            msg: api::ws::MessageType::Keypad(
 | 
				
			||||||
 | 
					                KeypadMessageType::DoorOpenEv { 
 | 
				
			||||||
 | 
					                    user: Uuid::new_v4(), 
 | 
				
			||||||
 | 
					                    timestamp: 0,
 | 
				
			||||||
 | 
					                    door_id: Uuid::new_v4() 
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    dbg!(&msg);
 | 
				
			||||||
 | 
					    let txt = serde_json::to_string_pretty(&msg)?;
 | 
				
			||||||
 | 
					    println!("{txt}");
 | 
				
			||||||
 | 
					    return Ok(());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // TODO: Start db
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    let mut db = db::Database::new();
 | 
				
			||||||
 | 
					    db.connect().await?;
 | 
				
			||||||
 | 
					    let ctx = context::AppContext::new(db);
 | 
				
			||||||
 | 
					    api::start_api(ctx).await;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Ok(())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user