diff --git a/.gitea/workflows/test-pr.yml b/.gitea/workflows/test-pr.yml
new file mode 100644
index 0000000..18dca5b
--- /dev/null
+++ b/.gitea/workflows/test-pr.yml
@@ -0,0 +1,19 @@
+name: check-and-test
+on: [push, pull_request]
+jobs:
+ check-and-test:
+ runs-on: ubuntu-latest
+ steps:
+ - name: git checkout repository
+ uses: actions/checkout@v4
+ - name: setup rust
+ uses: https://github.com/actions-rs/toolchain@v1
+ - name: cargo check
+ uses: https://github.com/actions-rs/cargo@v1
+ with:
+ command: check
+ - name: test
+ uses: https://github.com/actions-rs/cargo@v1
+ with:
+ command: test
+ args: --workspace -- --skip projections::irc
diff --git a/Cargo.lock b/Cargo.lock
index 8e90fa1..2469e90 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -44,6 +44,54 @@ version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5"
+[[package]]
+name = "anstream"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b1f58811cfac344940f1a400b6e6231ce35171f614f26439e80f8c1465c5cc0c"
+dependencies = [
+ "anstyle",
+ "anstyle-parse",
+ "anstyle-query",
+ "anstyle-wincon",
+ "colorchoice",
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b84bf0a05bbb2a83e5eb6fa36bb6e87baa08193c35ff52bbf6b38d8af2890e46"
+
+[[package]]
+name = "anstyle-parse"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333"
+dependencies = [
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle-query"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b"
+dependencies = [
+ "windows-sys",
+]
+
+[[package]]
+name = "anstyle-wincon"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "58f54d10c6dfa51283a066ceab3ec1ab78d13fae00aa49243a45e4571fb79dfd"
+dependencies = [
+ "anstyle",
+ "windows-sys",
+]
+
[[package]]
name = "anyhow"
version = "1.0.75"
@@ -161,6 +209,52 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+[[package]]
+name = "clap"
+version = "4.4.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b1d7b8d5ec32af0fadc644bf1fd509a688c2103b185644bb1e29d164e0703136"
+dependencies = [
+ "clap_builder",
+ "clap_derive",
+]
+
+[[package]]
+name = "clap_builder"
+version = "4.4.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5179bb514e4d7c2051749d8fcefa2ed6d06a9f4e6d69faf3805f5d80b8cf8d56"
+dependencies = [
+ "anstream",
+ "anstyle",
+ "clap_lex",
+ "strsim",
+]
+
+[[package]]
+name = "clap_derive"
+version = "4.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0862016ff20d69b84ef8247369fabf5c008a7417002411897d40ee1f4532b873"
+dependencies = [
+ "heck",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.29",
+]
+
+[[package]]
+name = "clap_lex"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961"
+
+[[package]]
+name = "colorchoice"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
+
[[package]]
name = "const-oid"
version = "0.9.5"
@@ -754,11 +848,13 @@ version = "0.0.1-dev"
dependencies = [
"anyhow",
"assert_matches",
+ "clap",
"derive_more",
"figment",
"futures-util",
"http-body-util",
"hyper 1.0.0-rc.3",
+ "mgmt-api",
"nonempty",
"prometheus",
"proto-irc",
@@ -846,6 +942,13 @@ version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
+[[package]]
+name = "mgmt-api"
+version = "0.0.1-dev"
+dependencies = [
+ "serde",
+]
+
[[package]]
name = "mime"
version = "0.3.17"
@@ -1794,6 +1897,12 @@ dependencies = [
"unicode-normalization",
]
+[[package]]
+name = "strsim"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
+
[[package]]
name = "subtle"
version = "2.5.0"
@@ -2104,6 +2213,12 @@ dependencies = [
"percent-encoding",
]
+[[package]]
+name = "utf8parse"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
+
[[package]]
name = "uuid"
version = "1.4.1"
diff --git a/Cargo.toml b/Cargo.toml
index b1a599b..4c90804 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -3,6 +3,7 @@ members = [
".",
"crates/proto-irc",
"crates/proto-xmpp",
+ "crates/mgmt-api",
]
[workspace.package]
@@ -19,6 +20,8 @@ quick-xml = { version = "0.30.0", features = ["async-tokio"] }
lazy_static = "1.4.0"
regex = "1.7.1"
derive_more = "0.99.17"
+clap = { version = "4.4.4", features = ["derive"] }
+serde = { version = "1.0.152", features = ["rc", "serde_derive"] }
[package]
name = "lavina"
@@ -31,7 +34,7 @@ anyhow.workspace = true
figment = { version = "0.10.8", features = ["env", "toml"] } # configuration files
hyper = { version = "1.0.0-rc.3,<1.0.0-rc.4", features = ["server", "http1"] } # http server
http-body-util = "0.1.0-rc.3"
-serde = { version = "1.0.152", features = ["rc", "serde_derive"] }
+serde.workspace = true
serde_json = "1.0.93"
tokio.workspace = true
tracing = "0.1.37" # logging & tracing api
@@ -47,6 +50,8 @@ uuid = { version = "1.3.0", features = ["v4"] }
sqlx = { version = "0.7.0-alpha.2", features = ["sqlite", "migrate"] }
proto-irc = { path = "crates/proto-irc" }
proto-xmpp = { path = "crates/proto-xmpp" }
+mgmt-api = { path = "crates/mgmt-api" }
+clap.workspace = true
[dev-dependencies]
assert_matches.workspace = true
diff --git a/crates/mgmt-api/Cargo.toml b/crates/mgmt-api/Cargo.toml
new file mode 100644
index 0000000..030f3cf
--- /dev/null
+++ b/crates/mgmt-api/Cargo.toml
@@ -0,0 +1,8 @@
+[package]
+name = "mgmt-api"
+edition = "2021"
+version.workspace = true
+publish = false
+
+[dependencies]
+serde.workspace = true
diff --git a/crates/mgmt-api/src/lib.rs b/crates/mgmt-api/src/lib.rs
new file mode 100644
index 0000000..cfe5b69
--- /dev/null
+++ b/crates/mgmt-api/src/lib.rs
@@ -0,0 +1,29 @@
+use serde::{Deserialize, Serialize};
+
+#[derive(Serialize, Deserialize)]
+pub struct ErrorResponse<'a> {
+ pub code: &'a str,
+ pub message: &'a str,
+}
+
+#[derive(Serialize, Deserialize)]
+pub struct CreatePlayerRequest<'a> {
+ pub name: &'a str,
+}
+
+#[derive(Serialize, Deserialize)]
+pub struct ChangePasswordRequest<'a> {
+ pub player_name: &'a str,
+ pub password: &'a str,
+}
+
+pub mod paths {
+ pub const CREATE_PLAYER: &'static str = "/mgmt/create_player";
+ pub const SET_PASSWORD: &'static str = "/mgmt/set_password";
+}
+
+pub mod errors {
+ pub const INVALID_PATH: &'static str = "invalid_path";
+ pub const MALFORMED_REQUEST: &'static str = "malformed_request";
+ pub const PLAYER_NOT_FOUND: &'static str = "player_not_found";
+}
diff --git a/crates/proto-irc/Cargo.toml b/crates/proto-irc/Cargo.toml
index e2225a7..4a5286e 100644
--- a/crates/proto-irc/Cargo.toml
+++ b/crates/proto-irc/Cargo.toml
@@ -2,6 +2,7 @@
name = "proto-irc"
edition = "2021"
version.workspace = true
+publish = false
[dependencies]
nom.workspace = true
diff --git a/dist/alpine3.18.Dockerfile b/dist/alpine3.18.Dockerfile
index 3a4a5d4..facdfb0 100644
--- a/dist/alpine3.18.Dockerfile
+++ b/dist/alpine3.18.Dockerfile
@@ -8,4 +8,4 @@ FROM alpine:3.18@sha256:7144f7bab3d4c2648d7e59409f15ec52a18006a128c733fcff20d3a4
COPY --from=bld target/release/lavina /usr/bin/lavina
VOLUME ["/etc/lavina/", "/var/lib/lavina/"]
-ENTRYPOINT ["lavina"]
+ENTRYPOINT ["lavina", "--config", "/etc/lavina/config.toml"]
diff --git a/rustfmt.toml b/rustfmt.toml
new file mode 100644
index 0000000..866c756
--- /dev/null
+++ b/rustfmt.toml
@@ -0,0 +1 @@
+max_width = 120
\ No newline at end of file
diff --git a/src/core/repo/mod.rs b/src/core/repo/mod.rs
index 10b601a..57371ed 100644
--- a/src/core/repo/mod.rs
+++ b/src/core/repo/mod.rs
@@ -5,7 +5,7 @@ use std::sync::Arc;
use serde::Deserialize;
use sqlx::sqlite::SqliteConnectOptions;
-use sqlx::{ConnectOptions, Connection, FromRow, SqliteConnection};
+use sqlx::{ConnectOptions, Connection, FromRow, Sqlite, SqliteConnection, Transaction};
use tokio::sync::Mutex;
use crate::prelude::*;
@@ -102,6 +102,50 @@ impl Storage {
res.close().await?;
Ok(())
}
+
+ pub async fn create_user(&mut self, name: &str) -> Result<()> {
+ let query = sqlx::query(
+ "insert into users(name)
+ values (?);",
+ )
+ .bind(name);
+ let mut executor = self.conn.lock().await;
+ query.execute(&mut *executor).await?;
+
+ Ok(())
+ }
+
+ pub async fn set_password<'a>(&'a mut self, name: &'a str, pwd: &'a str) -> Result