diff --git a/.gitignore b/.gitignore
index 3978cb6..b6bf0fa 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,6 @@
/target
.~*.xls
schedule.json
-teachers.json
\ No newline at end of file
+teachers.json
+
+.env*
\ No newline at end of file
diff --git a/.idea/dataSources.xml b/.idea/dataSources.xml
new file mode 100644
index 0000000..165053c
--- /dev/null
+++ b/.idea/dataSources.xml
@@ -0,0 +1,12 @@
+
+
+
+
+ postgresql
+ true
+ org.postgresql.Driver
+ jdbc:postgresql://localhost:5432/sp
+ $ProjectFileDir$
+
+
+
\ No newline at end of file
diff --git a/.idea/sqldialects.xml b/.idea/sqldialects.xml
new file mode 100644
index 0000000..da3341b
--- /dev/null
+++ b/.idea/sqldialects.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Cargo.lock b/Cargo.lock
index d1cb14a..d5c15c9 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2,6 +2,189 @@
# It is not intended for manual editing.
version = 4
+[[package]]
+name = "actix-codec"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5f7b0a21988c1bf877cf4759ef5ddaac04c1c9fe808c9142ecb78ba97d97a28a"
+dependencies = [
+ "bitflags",
+ "bytes",
+ "futures-core",
+ "futures-sink",
+ "memchr",
+ "pin-project-lite",
+ "tokio",
+ "tokio-util",
+ "tracing",
+]
+
+[[package]]
+name = "actix-http"
+version = "3.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fa882656b67966045e4152c634051e70346939fced7117d5f0b52146a7c74c9"
+dependencies = [
+ "actix-codec",
+ "actix-rt",
+ "actix-service",
+ "actix-utils",
+ "base64",
+ "bitflags",
+ "brotli",
+ "bytes",
+ "bytestring",
+ "derive_more",
+ "encoding_rs",
+ "flate2",
+ "foldhash",
+ "futures-core",
+ "h2 0.3.26",
+ "http 0.2.12",
+ "httparse",
+ "httpdate",
+ "itoa",
+ "language-tags",
+ "local-channel",
+ "mime",
+ "percent-encoding",
+ "pin-project-lite",
+ "rand",
+ "sha1",
+ "smallvec",
+ "tokio",
+ "tokio-util",
+ "tracing",
+ "zstd",
+]
+
+[[package]]
+name = "actix-macros"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb"
+dependencies = [
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "actix-router"
+version = "0.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "13d324164c51f63867b57e73ba5936ea151b8a41a1d23d1031eeb9f70d0236f8"
+dependencies = [
+ "bytestring",
+ "cfg-if",
+ "http 0.2.12",
+ "regex",
+ "regex-lite",
+ "serde",
+ "tracing",
+]
+
+[[package]]
+name = "actix-rt"
+version = "2.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "24eda4e2a6e042aa4e55ac438a2ae052d3b5da0ecf83d7411e1a368946925208"
+dependencies = [
+ "futures-core",
+ "tokio",
+]
+
+[[package]]
+name = "actix-server"
+version = "2.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6398974fd4284f4768af07965701efbbb5fdc0616bff20cade1bb14b77675e24"
+dependencies = [
+ "actix-rt",
+ "actix-service",
+ "actix-utils",
+ "futures-core",
+ "futures-util",
+ "mio",
+ "socket2",
+ "tokio",
+ "tracing",
+]
+
+[[package]]
+name = "actix-service"
+version = "2.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9e46f36bf0e5af44bdc4bdb36fbbd421aa98c79a9bce724e1edeb3894e10dc7f"
+dependencies = [
+ "futures-core",
+ "pin-project-lite",
+]
+
+[[package]]
+name = "actix-utils"
+version = "3.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "88a1dcdff1466e3c2488e1cb5c36a71822750ad43839937f85d2f4d9f8b705d8"
+dependencies = [
+ "local-waker",
+ "pin-project-lite",
+]
+
+[[package]]
+name = "actix-web"
+version = "4.10.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f2e3b15b3dc6c6ed996e4032389e9849d4ab002b1e92fbfe85b5f307d1479b4d"
+dependencies = [
+ "actix-codec",
+ "actix-http",
+ "actix-macros",
+ "actix-router",
+ "actix-rt",
+ "actix-server",
+ "actix-service",
+ "actix-utils",
+ "actix-web-codegen",
+ "bytes",
+ "bytestring",
+ "cfg-if",
+ "cookie",
+ "derive_more",
+ "encoding_rs",
+ "foldhash",
+ "futures-core",
+ "futures-util",
+ "impl-more",
+ "itoa",
+ "language-tags",
+ "log",
+ "mime",
+ "once_cell",
+ "pin-project-lite",
+ "regex",
+ "regex-lite",
+ "serde",
+ "serde_json",
+ "serde_urlencoded",
+ "smallvec",
+ "socket2",
+ "time",
+ "tracing",
+ "url",
+]
+
+[[package]]
+name = "actix-web-codegen"
+version = "4.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f591380e2e68490b5dfaf1dd1aa0ebe78d84ba7067078512b4ea6e4492d622b8"
+dependencies = [
+ "actix-router",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
[[package]]
name = "addr2line"
version = "0.24.2"
@@ -26,6 +209,21 @@ dependencies = [
"memchr",
]
+[[package]]
+name = "alloc-no-stdlib"
+version = "2.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3"
+
+[[package]]
+name = "alloc-stdlib"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece"
+dependencies = [
+ "alloc-no-stdlib",
+]
+
[[package]]
name = "android-tzdata"
version = "0.1.1"
@@ -101,6 +299,36 @@ version = "2.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd"
+[[package]]
+name = "block-buffer"
+version = "0.10.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
+dependencies = [
+ "generic-array",
+]
+
+[[package]]
+name = "brotli"
+version = "7.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cc97b8f16f944bba54f0433f07e30be199b6dc2bd25937444bbad560bcea29bd"
+dependencies = [
+ "alloc-no-stdlib",
+ "alloc-stdlib",
+ "brotli-decompressor",
+]
+
+[[package]]
+name = "brotli-decompressor"
+version = "4.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "74fa05ad7d803d413eb8380983b092cbbaf9a85f151b871360e7b00cd7060b37"
+dependencies = [
+ "alloc-no-stdlib",
+ "alloc-stdlib",
+]
+
[[package]]
name = "bumpalo"
version = "3.17.0"
@@ -119,6 +347,15 @@ version = "1.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a"
+[[package]]
+name = "bytestring"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e465647ae23b2823b0753f50decb2d5a86d2bb2cac04788fafd1f80e45378e5f"
+dependencies = [
+ "bytes",
+]
+
[[package]]
name = "calamine"
version = "0.26.1"
@@ -146,6 +383,8 @@ version = "1.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be714c154be609ec7f5dad223a33bf1482fff90472de28f7362806e6d4832b8c"
dependencies = [
+ "jobserver",
+ "libc",
"shlex",
]
@@ -231,6 +470,17 @@ dependencies = [
"encoding_rs",
]
+[[package]]
+name = "cookie"
+version = "0.16.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e859cd57d0710d9e06c381b550c06e76992472a8c6d527aecd2fc673dcc231fb"
+dependencies = [
+ "percent-encoding",
+ "time",
+ "version_check",
+]
+
[[package]]
name = "core-foundation"
version = "0.9.4"
@@ -247,6 +497,15 @@ version = "0.8.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
+[[package]]
+name = "cpufeatures"
+version = "0.2.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
+dependencies = [
+ "libc",
+]
+
[[package]]
name = "crc32fast"
version = "1.4.2"
@@ -323,6 +582,60 @@ version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929"
+[[package]]
+name = "crypto-common"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
+dependencies = [
+ "generic-array",
+ "typenum",
+]
+
+[[package]]
+name = "darling"
+version = "0.20.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989"
+dependencies = [
+ "darling_core",
+ "darling_macro",
+]
+
+[[package]]
+name = "darling_core"
+version = "0.20.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5"
+dependencies = [
+ "fnv",
+ "ident_case",
+ "proc-macro2",
+ "quote",
+ "strsim",
+ "syn",
+]
+
+[[package]]
+name = "darling_macro"
+version = "0.20.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806"
+dependencies = [
+ "darling_core",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "deranged"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e"
+dependencies = [
+ "powerfmt",
+]
+
[[package]]
name = "derive_arbitrary"
version = "1.4.1"
@@ -334,6 +647,83 @@ dependencies = [
"syn",
]
+[[package]]
+name = "derive_more"
+version = "2.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678"
+dependencies = [
+ "derive_more-impl",
+]
+
+[[package]]
+name = "derive_more-impl"
+version = "2.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "unicode-xid",
+]
+
+[[package]]
+name = "diesel"
+version = "2.2.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "470eb10efc8646313634c99bb1593f402a6434cbd86e266770c6e39219adb86a"
+dependencies = [
+ "bitflags",
+ "byteorder",
+ "diesel_derives",
+ "itoa",
+ "pq-sys",
+]
+
+[[package]]
+name = "diesel-derive-enum"
+version = "2.2.0"
+source = "git+https://github.com/Havunen/diesel-derive-enum.git#e0e57dad5508863da9a43dd35953fa92819261d7"
+dependencies = [
+ "heck",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "diesel_derives"
+version = "2.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a93958254b70bea63b4187ff73d10180599d9d8d177071b7f91e6da4e0c0ad55"
+dependencies = [
+ "diesel_table_macro_syntax",
+ "dsl_auto_type",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "diesel_table_macro_syntax"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "209c735641a413bc68c4923a9d6ad4bcb3ca306b794edaa7eb0b3228a99ffb25"
+dependencies = [
+ "syn",
+]
+
+[[package]]
+name = "digest"
+version = "0.10.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
+dependencies = [
+ "block-buffer",
+ "crypto-common",
+]
+
[[package]]
name = "displaydoc"
version = "0.2.5"
@@ -345,6 +735,26 @@ dependencies = [
"syn",
]
+[[package]]
+name = "dotenvy"
+version = "0.15.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b"
+
+[[package]]
+name = "dsl_auto_type"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "139ae9aca7527f85f26dd76483eb38533fd84bd571065da1739656ef71c5ff5b"
+dependencies = [
+ "darling",
+ "either",
+ "heck",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
[[package]]
name = "either"
version = "1.15.0"
@@ -398,6 +808,12 @@ version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
+[[package]]
+name = "foldhash"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
+
[[package]]
name = "foreign-types"
version = "0.3.2"
@@ -470,6 +886,16 @@ dependencies = [
"thread_local",
]
+[[package]]
+name = "generic-array"
+version = "0.14.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
+dependencies = [
+ "typenum",
+ "version_check",
+]
+
[[package]]
name = "getrandom"
version = "0.2.15"
@@ -499,6 +925,25 @@ version = "0.31.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
+[[package]]
+name = "h2"
+version = "0.3.26"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8"
+dependencies = [
+ "bytes",
+ "fnv",
+ "futures-core",
+ "futures-sink",
+ "futures-util",
+ "http 0.2.12",
+ "indexmap",
+ "slab",
+ "tokio",
+ "tokio-util",
+ "tracing",
+]
+
[[package]]
name = "h2"
version = "0.4.8"
@@ -510,7 +955,7 @@ dependencies = [
"fnv",
"futures-core",
"futures-sink",
- "http",
+ "http 1.3.1",
"indexmap",
"slab",
"tokio",
@@ -534,12 +979,29 @@ version = "0.15.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
+[[package]]
+name = "heck"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
+
[[package]]
name = "hermit-abi"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fbd780fe5cc30f81464441920d82ac8740e2e46b29a6fad543ddd075229ce37e"
+[[package]]
+name = "http"
+version = "0.2.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1"
+dependencies = [
+ "bytes",
+ "fnv",
+ "itoa",
+]
+
[[package]]
name = "http"
version = "1.3.1"
@@ -558,7 +1020,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184"
dependencies = [
"bytes",
- "http",
+ "http 1.3.1",
]
[[package]]
@@ -569,7 +1031,7 @@ checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a"
dependencies = [
"bytes",
"futures-core",
- "http",
+ "http 1.3.1",
"http-body",
"pin-project-lite",
]
@@ -580,6 +1042,12 @@ version = "1.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87"
+[[package]]
+name = "httpdate"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
+
[[package]]
name = "hyper"
version = "1.6.0"
@@ -589,8 +1057,8 @@ dependencies = [
"bytes",
"futures-channel",
"futures-util",
- "h2",
- "http",
+ "h2 0.4.8",
+ "http 1.3.1",
"http-body",
"httparse",
"itoa",
@@ -607,7 +1075,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d191583f3da1305256f22463b9bb0471acad48a4e534a5218b9963e9c1f59b2"
dependencies = [
"futures-util",
- "http",
+ "http 1.3.1",
"hyper",
"hyper-util",
"rustls",
@@ -642,7 +1110,7 @@ dependencies = [
"bytes",
"futures-channel",
"futures-util",
- "http",
+ "http 1.3.1",
"http-body",
"hyper",
"pin-project-lite",
@@ -793,6 +1261,12 @@ dependencies = [
"syn",
]
+[[package]]
+name = "ident_case"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
+
[[package]]
name = "idna"
version = "1.0.3"
@@ -814,6 +1288,12 @@ dependencies = [
"icu_properties",
]
+[[package]]
+name = "impl-more"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e8a5a9a0ff0086c7a148acb942baaabeadf9504d10400b5a05645853729b9cd2"
+
[[package]]
name = "indexmap"
version = "2.8.0"
@@ -856,6 +1336,15 @@ version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
+[[package]]
+name = "jobserver"
+version = "0.1.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0"
+dependencies = [
+ "libc",
+]
+
[[package]]
name = "js-sys"
version = "0.3.77"
@@ -866,6 +1355,12 @@ dependencies = [
"wasm-bindgen",
]
+[[package]]
+name = "language-tags"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d4345964bb142484797b161f473a503a434de77149dd8c7427788c6e13379388"
+
[[package]]
name = "libc"
version = "0.2.171"
@@ -884,6 +1379,33 @@ version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856"
+[[package]]
+name = "local-channel"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6cbc85e69b8df4b8bb8b89ec634e7189099cea8927a276b7384ce5488e53ec8"
+dependencies = [
+ "futures-core",
+ "futures-sink",
+ "local-waker",
+]
+
+[[package]]
+name = "local-waker"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4d873d7c67ce09b42110d801813efbc9364414e356be9935700d368351657487"
+
+[[package]]
+name = "lock_api"
+version = "0.4.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
+dependencies = [
+ "autocfg",
+ "scopeguard",
+]
+
[[package]]
name = "lockfree-object-pool"
version = "0.1.6"
@@ -924,6 +1446,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd"
dependencies = [
"libc",
+ "log",
"wasi 0.11.0+wasi-snapshot-preview1",
"windows-sys 0.52.0",
]
@@ -945,6 +1468,12 @@ dependencies = [
"tempfile",
]
+[[package]]
+name = "num-conv"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
+
[[package]]
name = "num-traits"
version = "0.2.19"
@@ -1019,6 +1548,29 @@ dependencies = [
"vcpkg",
]
+[[package]]
+name = "parking_lot"
+version = "0.12.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27"
+dependencies = [
+ "lock_api",
+ "parking_lot_core",
+]
+
+[[package]]
+name = "parking_lot_core"
+version = "0.9.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "redox_syscall",
+ "smallvec",
+ "windows-targets 0.52.6",
+]
+
[[package]]
name = "percent-encoding"
version = "2.3.1"
@@ -1071,6 +1623,31 @@ dependencies = [
"plotters-backend",
]
+[[package]]
+name = "powerfmt"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
+
+[[package]]
+name = "ppv-lite86"
+version = "0.2.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
+dependencies = [
+ "zerocopy",
+]
+
+[[package]]
+name = "pq-sys"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "30b51d65ebe1cb1f40641b15abae017fed35ccdda46e3dab1ff8768f625a3222"
+dependencies = [
+ "libc",
+ "vcpkg",
+]
+
[[package]]
name = "proc-macro2"
version = "1.0.94"
@@ -1105,6 +1682,36 @@ version = "5.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5"
+[[package]]
+name = "rand"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94"
+dependencies = [
+ "rand_chacha",
+ "rand_core",
+ "zerocopy",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
+dependencies = [
+ "ppv-lite86",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38"
+dependencies = [
+ "getrandom 0.3.2",
+]
+
[[package]]
name = "rayon"
version = "1.10.0"
@@ -1125,6 +1732,15 @@ dependencies = [
"crossbeam-utils",
]
+[[package]]
+name = "redox_syscall"
+version = "0.5.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b8c0c260b63a8219631167be35e6a988e9554dbd323f8bd08439c8ed1302bd1"
+dependencies = [
+ "bitflags",
+]
+
[[package]]
name = "regex"
version = "1.11.1"
@@ -1148,6 +1764,12 @@ dependencies = [
"regex-syntax",
]
+[[package]]
+name = "regex-lite"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "53a49587ad06b26609c52e423de037e7f57f20d53535d66e08c695f347df952a"
+
[[package]]
name = "regex-syntax"
version = "0.8.5"
@@ -1165,8 +1787,8 @@ dependencies = [
"encoding_rs",
"futures-core",
"futures-util",
- "h2",
- "http",
+ "h2 0.4.8",
+ "http 1.3.1",
"http-body",
"http-body-util",
"hyper",
@@ -1304,11 +1926,14 @@ dependencies = [
name = "schedule-parser-rusted"
version = "0.3.0"
dependencies = [
+ "actix-web",
"chrono",
+ "diesel",
+ "diesel-derive-enum",
+ "dotenvy",
"reqwest",
"schedule_parser",
"serde",
- "serde_json",
"tokio",
]
@@ -1325,6 +1950,12 @@ dependencies = [
"serde_repr",
]
+[[package]]
+name = "scopeguard"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
+
[[package]]
name = "security-framework"
version = "2.11.1"
@@ -1403,12 +2034,32 @@ dependencies = [
"serde",
]
+[[package]]
+name = "sha1"
+version = "0.10.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba"
+dependencies = [
+ "cfg-if",
+ "cpufeatures",
+ "digest",
+]
+
[[package]]
name = "shlex"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
+[[package]]
+name = "signal-hook-registry"
+version = "1.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1"
+dependencies = [
+ "libc",
+]
+
[[package]]
name = "simd-adler32"
version = "0.3.7"
@@ -1446,6 +2097,12 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
+[[package]]
+name = "strsim"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
+
[[package]]
name = "subtle"
version = "2.6.1"
@@ -1547,6 +2204,37 @@ dependencies = [
"once_cell",
]
+[[package]]
+name = "time"
+version = "0.3.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9d9c75b47bdff86fa3334a3db91356b8d7d86a9b839dab7d0bdc5c3d3a077618"
+dependencies = [
+ "deranged",
+ "itoa",
+ "num-conv",
+ "powerfmt",
+ "serde",
+ "time-core",
+ "time-macros",
+]
+
+[[package]]
+name = "time-core"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c"
+
+[[package]]
+name = "time-macros"
+version = "0.2.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "29aa485584182073ed57fd5004aa09c371f021325014694e432313345865fd04"
+dependencies = [
+ "num-conv",
+ "time-core",
+]
+
[[package]]
name = "tinystr"
version = "0.7.6"
@@ -1577,7 +2265,9 @@ dependencies = [
"bytes",
"libc",
"mio",
+ "parking_lot",
"pin-project-lite",
+ "signal-hook-registry",
"socket2",
"tokio-macros",
"windows-sys 0.52.0",
@@ -1660,10 +2350,23 @@ version = "0.1.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0"
dependencies = [
+ "log",
"pin-project-lite",
+ "tracing-attributes",
"tracing-core",
]
+[[package]]
+name = "tracing-attributes"
+version = "0.1.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
[[package]]
name = "tracing-core"
version = "0.1.33"
@@ -1679,12 +2382,24 @@ version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
+[[package]]
+name = "typenum"
+version = "1.18.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f"
+
[[package]]
name = "unicode-ident"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
+[[package]]
+name = "unicode-xid"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
+
[[package]]
name = "untrusted"
version = "0.9.0"
@@ -1720,6 +2435,12 @@ version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
+[[package]]
+name = "version_check"
+version = "0.9.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
+
[[package]]
name = "walkdir"
version = "2.5.0"
@@ -2079,6 +2800,26 @@ dependencies = [
"synstructure",
]
+[[package]]
+name = "zerocopy"
+version = "0.8.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2586fea28e186957ef732a5f8b3be2da217d65c5969d4b1e17f973ebbe876879"
+dependencies = [
+ "zerocopy-derive",
+]
+
+[[package]]
+name = "zerocopy-derive"
+version = "0.8.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a996a8f63c5c4448cd959ac1bab0aaa3306ccfd060472f85943ee0750f0169be"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
[[package]]
name = "zerofrom"
version = "0.1.6"
@@ -2158,3 +2899,31 @@ dependencies = [
"once_cell",
"simd-adler32",
]
+
+[[package]]
+name = "zstd"
+version = "0.13.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a"
+dependencies = [
+ "zstd-safe",
+]
+
+[[package]]
+name = "zstd-safe"
+version = "7.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d"
+dependencies = [
+ "zstd-sys",
+]
+
+[[package]]
+name = "zstd-sys"
+version = "2.0.15+zstd.1.5.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eb81183ddd97d0c74cedf1d50d85c8d08c1b8b68ee863bdee9e706eedba1a237"
+dependencies = [
+ "cc",
+ "pkg-config",
+]
diff --git a/Cargo.toml b/Cargo.toml
index 65275d1..2094a0c 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -8,9 +8,12 @@ edition = "2024"
publish = false
[dependencies]
+diesel = { version = "2.2.8", features = ["postgres"] }
+diesel-derive-enum = { git = "https://github.com/Havunen/diesel-derive-enum.git", features = ["postgres"] }
+dotenvy = "0.15.7"
serde = { version = "1.0.219", features = ["derive"] }
-serde_json = "1.0.140"
schedule_parser = { path = "./lib/schedule_parser" }
chrono = "0.4.40"
reqwest = "0.12.15"
tokio = { version = "1.44.1", features = ["macros", "rt-multi-thread"] }
+actix-web = "4.10.2"
diff --git a/diesel.toml b/diesel.toml
new file mode 100644
index 0000000..803c125
--- /dev/null
+++ b/diesel.toml
@@ -0,0 +1,9 @@
+# For documentation on how to configure this file,
+# see https://diesel.rs/guides/configuring-diesel-cli
+
+[print_schema]
+file = "src/database/schema.rs"
+custom_type_derives = ["diesel::query_builder::QueryId", "Clone"]
+
+[migrations_directory]
+dir = "./migrations"
diff --git a/lib/schedule_parser/src/lib/lib.rs b/lib/schedule_parser/src/lib/lib.rs
index 88fb2e7..c30bb7b 100644
--- a/lib/schedule_parser/src/lib/lib.rs
+++ b/lib/schedule_parser/src/lib/lib.rs
@@ -10,7 +10,7 @@ use std::collections::HashMap;
use std::io::Cursor;
use std::sync::LazyLock;
-mod schema;
+pub mod schema;
struct InternalId {
/**
diff --git a/migrations/.keep b/migrations/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/migrations/00000000000000_diesel_initial_setup/down.sql b/migrations/00000000000000_diesel_initial_setup/down.sql
new file mode 100644
index 0000000..a9f5260
--- /dev/null
+++ b/migrations/00000000000000_diesel_initial_setup/down.sql
@@ -0,0 +1,6 @@
+-- This file was automatically created by Diesel to setup helper functions
+-- and other internal bookkeeping. This file is safe to edit, any future
+-- changes will be added to existing projects as new migrations.
+
+DROP FUNCTION IF EXISTS diesel_manage_updated_at(_tbl regclass);
+DROP FUNCTION IF EXISTS diesel_set_updated_at();
diff --git a/migrations/00000000000000_diesel_initial_setup/up.sql b/migrations/00000000000000_diesel_initial_setup/up.sql
new file mode 100644
index 0000000..d68895b
--- /dev/null
+++ b/migrations/00000000000000_diesel_initial_setup/up.sql
@@ -0,0 +1,36 @@
+-- This file was automatically created by Diesel to setup helper functions
+-- and other internal bookkeeping. This file is safe to edit, any future
+-- changes will be added to existing projects as new migrations.
+
+
+
+
+-- Sets up a trigger for the given table to automatically set a column called
+-- `updated_at` whenever the row is modified (unless `updated_at` was included
+-- in the modified columns)
+--
+-- # Example
+--
+-- ```sql
+-- CREATE TABLE users (id SERIAL PRIMARY KEY, updated_at TIMESTAMP NOT NULL DEFAULT NOW());
+--
+-- SELECT diesel_manage_updated_at('users');
+-- ```
+CREATE OR REPLACE FUNCTION diesel_manage_updated_at(_tbl regclass) RETURNS VOID AS $$
+BEGIN
+ EXECUTE format('CREATE TRIGGER set_updated_at BEFORE UPDATE ON %s
+ FOR EACH ROW EXECUTE PROCEDURE diesel_set_updated_at()', _tbl);
+END;
+$$ LANGUAGE plpgsql;
+
+CREATE OR REPLACE FUNCTION diesel_set_updated_at() RETURNS trigger AS $$
+BEGIN
+ IF (
+ NEW IS DISTINCT FROM OLD AND
+ NEW.updated_at IS NOT DISTINCT FROM OLD.updated_at
+ ) THEN
+ NEW.updated_at := current_timestamp;
+ END IF;
+ RETURN NEW;
+END;
+$$ LANGUAGE plpgsql;
diff --git a/migrations/2025-03-21-211822_create_user_role/down.sql b/migrations/2025-03-21-211822_create_user_role/down.sql
new file mode 100644
index 0000000..8df4f0f
--- /dev/null
+++ b/migrations/2025-03-21-211822_create_user_role/down.sql
@@ -0,0 +1 @@
+DROP TYPE user_role;
\ No newline at end of file
diff --git a/migrations/2025-03-21-211822_create_user_role/up.sql b/migrations/2025-03-21-211822_create_user_role/up.sql
new file mode 100644
index 0000000..889ca7a
--- /dev/null
+++ b/migrations/2025-03-21-211822_create_user_role/up.sql
@@ -0,0 +1,4 @@
+CREATE TYPE user_role AS ENUM (
+ 'STUDENT',
+ 'TEACHER',
+ 'ADMIN');
\ No newline at end of file
diff --git a/migrations/2025-03-21-212111_create_users/down.sql b/migrations/2025-03-21-212111_create_users/down.sql
new file mode 100644
index 0000000..441087a
--- /dev/null
+++ b/migrations/2025-03-21-212111_create_users/down.sql
@@ -0,0 +1 @@
+DROP TABLE users;
\ No newline at end of file
diff --git a/migrations/2025-03-21-212111_create_users/up.sql b/migrations/2025-03-21-212111_create_users/up.sql
new file mode 100644
index 0000000..ca1ac7e
--- /dev/null
+++ b/migrations/2025-03-21-212111_create_users/up.sql
@@ -0,0 +1,11 @@
+CREATE TABLE users
+(
+ id text PRIMARY KEY NOT NULL,
+ username text UNIQUE NOT NULL,
+ "password" text NOT NULL,
+ vk_id int4 NULL,
+ access_token text UNIQUE NOT NULL,
+ "group" text NOT NULL,
+ role user_role NOT NULL,
+ version text NOT NULL
+);
\ No newline at end of file
diff --git a/migrations/2025-03-21-212723_create_fcm/down.sql b/migrations/2025-03-21-212723_create_fcm/down.sql
new file mode 100644
index 0000000..82e5923
--- /dev/null
+++ b/migrations/2025-03-21-212723_create_fcm/down.sql
@@ -0,0 +1 @@
+DROP TABLE fcm;
\ No newline at end of file
diff --git a/migrations/2025-03-21-212723_create_fcm/up.sql b/migrations/2025-03-21-212723_create_fcm/up.sql
new file mode 100644
index 0000000..77dd7da
--- /dev/null
+++ b/migrations/2025-03-21-212723_create_fcm/up.sql
@@ -0,0 +1,11 @@
+CREATE TABLE fcm
+(
+ user_id text PRIMARY KEY NOT NULL,
+ token text NOT NULL,
+ topics text[] NULL
+);
+
+CREATE UNIQUE INDEX fcm_user_id_key ON fcm USING btree (user_id);
+
+ALTER TABLE fcm
+ ADD CONSTRAINT fcm_user_id_fkey FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE RESTRICT ON UPDATE CASCADE;
\ No newline at end of file
diff --git a/src/database/mod.rs b/src/database/mod.rs
new file mode 100644
index 0000000..2e2cb1f
--- /dev/null
+++ b/src/database/mod.rs
@@ -0,0 +1,2 @@
+pub mod schema;
+pub mod models;
diff --git a/src/database/models.rs b/src/database/models.rs
new file mode 100644
index 0000000..18ab713
--- /dev/null
+++ b/src/database/models.rs
@@ -0,0 +1,26 @@
+use diesel::prelude::*;
+use serde::Serialize;
+
+#[derive(diesel_derive_enum::DbEnum, Serialize, Debug)]
+#[ExistingTypePath = "crate::database::schema::sql_types::UserRole"]
+#[DbValueStyle = "UPPERCASE"]
+#[serde(rename_all = "UPPERCASE")]
+pub enum UserRole {
+ Student,
+ Teacher,
+ Admin,
+}
+
+#[derive(Queryable, Selectable, Serialize)]
+#[diesel(table_name = crate::database::schema::users)]
+#[diesel(check_for_backend(diesel::pg::Pg))]
+pub struct User {
+ pub id: String,
+ pub username: String,
+ pub password: String,
+ pub vk_id: Option,
+ pub access_token: String,
+ pub group: String,
+ pub role: UserRole,
+ pub version: String,
+}
diff --git a/src/database/schema.rs b/src/database/schema.rs
new file mode 100644
index 0000000..ae691df
--- /dev/null
+++ b/src/database/schema.rs
@@ -0,0 +1,38 @@
+// @generated automatically by Diesel CLI.
+
+pub mod sql_types {
+ #[derive(diesel::query_builder::QueryId, Clone, diesel::sql_types::SqlType)]
+ #[diesel(postgres_type(name = "user_role"))]
+ pub struct UserRole;
+}
+
+diesel::table! {
+ fcm (user_id) {
+ user_id -> Text,
+ token -> Text,
+ topics -> Nullable>>,
+ }
+}
+
+diesel::table! {
+ use diesel::sql_types::*;
+ use super::sql_types::UserRole;
+
+ users (id) {
+ id -> Text,
+ username -> Text,
+ password -> Text,
+ vk_id -> Nullable,
+ access_token -> Text,
+ group -> Text,
+ role -> UserRole,
+ version -> Text,
+ }
+}
+
+diesel::joinable!(fcm -> users (user_id));
+
+diesel::allow_tables_to_appear_in_same_query!(
+ fcm,
+ users,
+);
diff --git a/src/main.rs b/src/main.rs
index 9803a4e..c453f95 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,39 +1,57 @@
+use crate::routes::auth::sign_in::sign_in;
use crate::xls_downloader::basic_impl::BasicXlsDownloader;
-use crate::xls_downloader::interface::XLSDownloader;
-use schedule_parser::parse_xls;
-use std::{env, fs};
+use actix_web::{web, App, HttpServer};
+use chrono::{DateTime, Utc};
+use diesel::{Connection, PgConnection};
+use dotenvy::dotenv;
+use schedule_parser::schema::ScheduleEntity;
+use std::collections::HashMap;
+use std::sync::Mutex;
+use std::env;
+mod database;
+mod routes;
mod xls_downloader;
-#[tokio::main]
-async fn main() {
- let args: Vec = env::args().collect();
- assert_ne!(args.len(), 1);
-
- let mut downloader = BasicXlsDownloader::new();
-
- downloader
- .set_url(args[1].to_string())
- .await
- .expect("Failed to set url");
-
- let fetch_res = downloader.fetch(false).await.expect("Failed to fetch xls");
-
- let (teachers, groups) = parse_xls(fetch_res.data.as_ref().unwrap());
-
- fs::write(
- "./schedule.json",
- serde_json::to_string_pretty(&groups)
- .expect("Failed to serialize schedule")
- .as_bytes(),
- )
- .expect("Failed to write schedule");
-
- fs::write(
- "./teachers.json",
- serde_json::to_string_pretty(&teachers)
- .expect("Failed to serialize teachers schedule")
- .as_bytes(),
- )
- .expect("Failed to write teachers schedule");
+pub struct AppState {
+ downloader: Mutex,
+ schedule: Mutex<
+ Option<(
+ String,
+ DateTime,
+ (
+ HashMap,
+ HashMap,
+ ),
+ )>,
+ >,
+ database: Mutex,
+}
+
+#[actix_web::main]
+async fn main() {
+ dotenv().ok();
+
+ let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
+
+ let data = web::Data::new(AppState {
+ downloader: Mutex::new(BasicXlsDownloader::new()),
+ schedule: Mutex::new(None),
+ database: Mutex::new(
+ PgConnection::establish(&database_url)
+ .unwrap_or_else(|_| panic!("Error connecting to {}", database_url)),
+ ),
+ });
+
+ HttpServer::new(move || {
+ let schedule_scope = web::scope("/auth").service(sign_in);
+ let api_scope = web::scope("/api/v1").service(schedule_scope);
+
+ App::new().app_data(data.clone()).service(api_scope)
+ })
+ .bind(("127.0.0.1", 8080))
+ .unwrap()
+ .run()
+ .await
+ .unwrap();
}
diff --git a/src/routes/auth/mod.rs b/src/routes/auth/mod.rs
new file mode 100644
index 0000000..523aba4
--- /dev/null
+++ b/src/routes/auth/mod.rs
@@ -0,0 +1,2 @@
+pub mod sign_in;
+mod schema;
\ No newline at end of file
diff --git a/src/routes/auth/schema.rs b/src/routes/auth/schema.rs
new file mode 100644
index 0000000..d881008
--- /dev/null
+++ b/src/routes/auth/schema.rs
@@ -0,0 +1,56 @@
+use crate::database::models::User;
+use serde::{Deserialize, Serialize, Serializer};
+
+#[derive(Deserialize)]
+pub struct SignInDto {
+ pub username: String,
+ pub password: String,
+}
+
+pub struct SignInResult(Result);
+
+#[derive(Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct SignInOk {
+ id: String,
+ access_token: String,
+ group: String,
+}
+
+#[derive(Serialize)]
+pub struct SignInErr {
+ code: SignInErrCode,
+}
+
+#[derive(Serialize)]
+#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
+pub enum SignInErrCode {
+ IncorrectCredentials,
+ InvalidVkAccessToken,
+}
+
+impl SignInResult {
+ pub fn ok(user: &User) -> Self {
+ Self(Ok(SignInOk {
+ id: user.id.clone(),
+ access_token: user.access_token.clone(),
+ group: user.group.clone(),
+ }))
+ }
+
+ pub fn err(code: SignInErrCode) -> SignInResult {
+ Self(Err(SignInErr { code }))
+ }
+}
+
+impl Serialize for SignInResult {
+ fn serialize(&self, serializer: S) -> Result
+ where
+ S: Serializer,
+ {
+ match &self.0 {
+ Ok(ok) => serializer.serialize_some(&ok),
+ Err(err) => serializer.serialize_some(&err),
+ }
+ }
+}
diff --git a/src/routes/auth/sign_in.rs b/src/routes/auth/sign_in.rs
new file mode 100644
index 0000000..83d953d
--- /dev/null
+++ b/src/routes/auth/sign_in.rs
@@ -0,0 +1,26 @@
+use crate::database::models::User;
+use crate::routes::auth::schema::SignInErrCode::IncorrectCredentials;
+use crate::routes::auth::schema::{SignInDto, SignInResult};
+use crate::AppState;
+use actix_web::{post, web};
+use diesel::{ExpressionMethods, QueryDsl, RunQueryDsl, SelectableHelper};
+use std::ops::DerefMut;
+use web::Json;
+
+#[post("/sign-in")]
+pub async fn sign_in(data: Json, app_state: web::Data) -> Json {
+ use crate::database::schema::users::dsl::*;
+
+ match {
+ let mut lock = app_state.database.lock().unwrap();
+ let connection = lock.deref_mut();
+
+ users
+ .filter(username.eq(data.username.clone()))
+ .select(User::as_select())
+ .first(connection)
+ } {
+ Ok(user) => Json(SignInResult::ok(&user)),
+ Err(_) => Json(SignInResult::err(IncorrectCredentials)),
+ }
+}
diff --git a/src/routes/mod.rs b/src/routes/mod.rs
new file mode 100644
index 0000000..5696e21
--- /dev/null
+++ b/src/routes/mod.rs
@@ -0,0 +1 @@
+pub mod auth;
\ No newline at end of file