This commit is contained in:
Dominic Grimm 2023-02-22 18:02:10 +01:00
parent 027aad58f9
commit 7f3cf3b2b5
No known key found for this signature in database
GPG key ID: 6F294212DEAAC530
11 changed files with 55 additions and 710 deletions

326
backend/Cargo.lock generated
View file

@ -2,53 +2,6 @@
# It is not intended for manual editing.
version = 3
[[package]]
name = "actix"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3720d0064a0ce5c0de7bd93bdb0a6caebab2a9b5668746145d7b3b0c5da02914"
dependencies = [
"actix-rt",
"actix_derive",
"bitflags",
"bytes",
"crossbeam-channel",
"futures-core",
"futures-sink",
"futures-task",
"futures-util",
"log",
"once_cell",
"parking_lot 0.11.2",
"pin-project-lite",
"smallvec",
"tokio",
"tokio-util 0.6.10",
]
[[package]]
name = "actix"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f728064aca1c318585bf4bb04ffcfac9e75e508ab4e8b1bd9ba5dfe04e2cbed5"
dependencies = [
"actix-rt",
"bitflags",
"bytes",
"crossbeam-channel",
"futures-core",
"futures-sink",
"futures-task",
"futures-util",
"log",
"once_cell",
"parking_lot 0.12.1",
"pin-project-lite",
"smallvec",
"tokio",
"tokio-util 0.7.4",
]
[[package]]
name = "actix-codec"
version = "0.5.0"
@ -63,7 +16,7 @@ dependencies = [
"memchr",
"pin-project-lite",
"tokio",
"tokio-util 0.7.4",
"tokio-util",
]
[[package]]
@ -115,7 +68,7 @@ dependencies = [
"sha1 0.10.5",
"smallvec",
"tokio",
"tokio-util 0.7.4",
"tokio-util",
"tracing",
"zstd",
]
@ -233,24 +186,6 @@ dependencies = [
"url",
]
[[package]]
name = "actix-web-actors"
version = "4.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf6e9ccc371cfddbed7aa842256a4abc7a6dcac9f3fce392fe1d0f68cfd136b2"
dependencies = [
"actix 0.13.0",
"actix-codec",
"actix-http",
"actix-web",
"bytes",
"bytestring",
"futures-core",
"pin-project-lite",
"tokio",
"tokio-util 0.7.4",
]
[[package]]
name = "actix-web-codegen"
version = "4.1.0"
@ -263,17 +198,6 @@ dependencies = [
"syn",
]
[[package]]
name = "actix_derive"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d44b8fee1ced9671ba043476deddef739dd0959bf77030b26b738cc591737a7"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "addr2line"
version = "0.19.0"
@ -396,12 +320,6 @@ version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6"
[[package]]
name = "ascii"
version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eab1c04a571841102f5345a8fc0f6bb3d31c315dec879b5c6e42e40ce7ffa34e"
[[package]]
name = "async-channel"
version = "1.8.0"
@ -547,8 +465,6 @@ dependencies = [
"diesel",
"env_logger",
"envconfig",
"juniper",
"juniper_actix",
"lazy_static",
"log",
"r2d2_redis",
@ -649,23 +565,6 @@ dependencies = [
"alloc-stdlib",
]
[[package]]
name = "bson"
version = "1.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de0aa578035b938855a710ba58d43cfb4d435f3619f99236fb35922a574d6cb1"
dependencies = [
"base64 0.13.1",
"chrono",
"hex",
"lazy_static",
"linked-hash-map",
"rand 0.7.3",
"serde",
"serde_json",
"uuid",
]
[[package]]
name = "bstr"
version = "1.1.0"
@ -812,19 +711,6 @@ dependencies = [
"winapi",
]
[[package]]
name = "combine"
version = "3.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da3da6baa321ec19e1cc41d31bf599f00c783d0517095cdaf0332e3fe8d20680"
dependencies = [
"ascii",
"byteorder",
"either",
"memchr",
"unreachable",
]
[[package]]
name = "combine"
version = "4.6.6"
@ -836,7 +722,7 @@ dependencies = [
"memchr",
"pin-project-lite",
"tokio",
"tokio-util 0.7.4",
"tokio-util",
]
[[package]]
@ -905,16 +791,6 @@ dependencies = [
"cfg-if",
]
[[package]]
name = "crossbeam-channel"
version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521"
dependencies = [
"cfg-if",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.14"
@ -1018,17 +894,6 @@ dependencies = [
"syn",
]
[[package]]
name = "derive_utils"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "532b4c15dccee12c7044f1fcad956e98410860b22231e44a3b827464797ca7bf"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "des"
version = "0.8.1"
@ -1103,12 +968,6 @@ version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a68a4904193147e0a8dec3314640e6db742afd5f6e634f428a6af230d9b3591"
[[package]]
name = "either"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
[[package]]
name = "encoding_rs"
version = "0.8.31"
@ -1274,17 +1133,6 @@ version = "0.3.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac"
[[package]]
name = "futures-enum"
version = "0.1.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3422d14de7903a52e9dbc10ae05a7e14445ec61890100e098754e120b2bd7b1e"
dependencies = [
"derive_utils",
"quote",
"syn",
]
[[package]]
name = "futures-executor"
version = "0.3.25"
@ -1427,16 +1275,6 @@ dependencies = [
"regex",
]
[[package]]
name = "graphql-parser"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d1abd4ce5247dfc04a03ccde70f87a048458c9356c7e41d21ad8c407b3dde6f2"
dependencies = [
"combine 3.8.1",
"thiserror",
]
[[package]]
name = "h2"
version = "0.3.15"
@ -1452,7 +1290,7 @@ dependencies = [
"indexmap",
"slab",
"tokio",
"tokio-util 0.7.4",
"tokio-util",
"tracing",
]
@ -1480,12 +1318,6 @@ dependencies = [
"libc",
]
[[package]]
name = "hex"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
[[package]]
name = "hmac"
version = "0.12.1"
@ -1639,7 +1471,6 @@ checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399"
dependencies = [
"autocfg",
"hashbrown",
"serde",
]
[[package]]
@ -1697,59 +1528,6 @@ dependencies = [
"wasm-bindgen",
]
[[package]]
name = "juniper"
version = "0.15.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4f478f229a8ab52ff242f3250c8b3b8fe0a59b5b934f9706b7bdbc980991a7b6"
dependencies = [
"async-trait",
"bson",
"chrono",
"fnv",
"futures",
"futures-enum",
"graphql-parser",
"indexmap",
"juniper_codegen",
"serde",
"smartstring",
"static_assertions",
"url",
"uuid",
]
[[package]]
name = "juniper_actix"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc44af18ae1f551076171e24eb453c52132a19c219d1f1a1c3068ab363b946b5"
dependencies = [
"actix 0.12.0",
"actix-http",
"actix-web",
"actix-web-actors",
"anyhow",
"futures",
"http",
"juniper",
"serde",
"serde_json",
"thiserror",
]
[[package]]
name = "juniper_codegen"
version = "0.15.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aee97671061ad50301ba077d054d295e01d31a1868fbd07902db651f987e71db"
dependencies = [
"proc-macro-error",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "language-tags"
version = "0.3.2"
@ -1770,7 +1548,7 @@ dependencies = [
"flume",
"futures-core",
"futures-io",
"parking_lot 0.12.1",
"parking_lot",
"pinky-swear",
"reactor-trait",
"serde",
@ -1799,12 +1577,6 @@ dependencies = [
"cc",
]
[[package]]
name = "linked-hash-map"
version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
[[package]]
name = "local-channel"
version = "0.1.3"
@ -2065,17 +1837,6 @@ version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72"
[[package]]
name = "parking_lot"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99"
dependencies = [
"instant",
"lock_api",
"parking_lot_core 0.8.6",
]
[[package]]
name = "parking_lot"
version = "0.12.1"
@ -2083,21 +1844,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
dependencies = [
"lock_api",
"parking_lot_core 0.9.6",
]
[[package]]
name = "parking_lot_core"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc"
dependencies = [
"cfg-if",
"instant",
"libc",
"redox_syscall",
"smallvec",
"winapi",
"parking_lot_core",
]
[[package]]
@ -2257,7 +2004,7 @@ checksum = "d894b67aa7a4bf295db5e85349078c604edaa6fa5c8721e8eca3c7729a27f2ac"
dependencies = [
"doc-comment",
"flume",
"parking_lot 0.12.1",
"parking_lot",
"tracing",
]
@ -2357,7 +2104,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51de85fb3fb6524929c8a2eb85e6b6d363de4e8c48f9e2c2eac4944abc181c93"
dependencies = [
"log",
"parking_lot 0.12.1",
"parking_lot",
"scheduled-thread-pool",
]
@ -2479,7 +2226,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4f0ceb2ec0dd769483ecd283f6615aa83dcd0be556d5294c6e659caefe7cc54"
dependencies = [
"async-trait",
"combine 4.6.6",
"combine",
"dtoa",
"itoa 0.4.8",
"percent-encoding",
@ -2496,7 +2243,7 @@ dependencies = [
"arc-swap",
"async-trait",
"bytes",
"combine 4.6.6",
"combine",
"futures",
"futures-util",
"itoa 1.0.5",
@ -2505,7 +2252,7 @@ dependencies = [
"ryu",
"sha1 0.6.1",
"tokio",
"tokio-util 0.7.4",
"tokio-util",
"url",
]
@ -2677,7 +2424,7 @@ version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "977a7519bff143a44f842fd07e80ad1329295bd71686457f18e496736f4bf9bf"
dependencies = [
"parking_lot 0.12.1",
"parking_lot",
]
[[package]]
@ -2793,7 +2540,6 @@ version = "1.0.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883"
dependencies = [
"indexmap",
"itoa 1.0.5",
"ryu",
"serde",
@ -2877,15 +2623,6 @@ version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
[[package]]
name = "smartstring"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e714dff2b33f2321fdcd475b71cec79781a692d846f37f415fb395a1d2bcd48e"
dependencies = [
"static_assertions",
]
[[package]]
name = "socket2"
version = "0.4.7"
@ -2917,12 +2654,6 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
[[package]]
name = "static_assertions"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]]
name = "stdext"
version = "0.3.1"
@ -2937,7 +2668,7 @@ checksum = "213494b7a2b503146286049378ce02b482200519accc31872ee8be91fa820a08"
dependencies = [
"new_debug_unreachable",
"once_cell",
"parking_lot 0.12.1",
"parking_lot",
"phf_shared 0.10.0",
"precomputed-hash",
"serde",
@ -3130,7 +2861,7 @@ dependencies = [
"memchr",
"mio",
"num_cpus",
"parking_lot 0.12.1",
"parking_lot",
"pin-project-lite",
"signal-hook-registry",
"socket2",
@ -3195,20 +2926,6 @@ dependencies = [
"tokio",
]
[[package]]
name = "tokio-util"
version = "0.6.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "36943ee01a6d67977dd3f84a5a1d2efeb4ada3a1ae771cadfaa535d9d9fc6507"
dependencies = [
"bytes",
"futures-core",
"futures-sink",
"log",
"pin-project-lite",
"tokio",
]
[[package]]
name = "tokio-util"
version = "0.7.4"
@ -3289,15 +3006,6 @@ version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
[[package]]
name = "unreachable"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56"
dependencies = [
"void",
]
[[package]]
name = "untis"
version = "0.1.0"
@ -3356,12 +3064,6 @@ version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "void"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
[[package]]
name = "waker-fn"
version = "1.1.0"

View file

@ -24,8 +24,6 @@ chrono = "0.4.23"
diesel = { version = "2.0.2", features = ["i-implement-a-third-party-backend-and-opt-into-breaking-changes", "postgres", "chrono", "r2d2"] }
env_logger = "0.9.3"
envconfig = "0.10.0"
juniper = { version = "0.15.10", features = ["scalar-naivetime"] }
juniper_actix = "0.4.0"
lazy_static = "1.4.0"
log = "0.4.17"
r2d2_redis = "0.14.0"

View file

@ -2,30 +2,32 @@ CREATE TABLE schoolyears (
id SERIAL PRIMARY KEY,
untis_id INTEGER NOT NULL UNIQUE,
name VARCHAR NOT NULL,
start_date DATE NOT NULL,
end_date DATE NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP
);
CREATE UNIQUE INDEX schoolyears_unique ON schoolyears(active)
WHERE
active;
CREATE TABLE tenants (
id SERIAL PRIMARY KEY,
untis_id INTEGER NOT NULL UNIQUE,
schoolyear_id INTEGER NOT NULL REFERENCES schoolyears (id),
schoolyear_id INTEGER NOT NULL REFERENCES schoolyears(id),
name VARCHAR NOT NULL,
active BOOLEAN NOT NULL DEFAULT FALSE,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP
);
CREATE UNIQUE INDEX tenants_active ON tenants (active)
CREATE UNIQUE INDEX tenants_active ON tenants(active)
WHERE
active;
CREATE TABLE teachers (
id SERIAL PRIMARY KEY,
untis_id INTEGER NOT NULL UNIQUE,
schoolyear_id INTEGER NOT NULL REFERENCES schoolyears (id),
schoolyear_id INTEGER NOT NULL REFERENCES schoolyears(id),
name VARCHAR NOT NULL,
forename VARCHAR,
display_name VARCHAR NOT NULL,
@ -36,7 +38,7 @@ CREATE TABLE teachers (
CREATE TABLE classes (
id SERIAL PRIMARY KEY,
untis_id INTEGER NOT NULL UNIQUE,
schoolyear_id INTEGER NOT NULL REFERENCES schoolyears (id),
schoolyear_id INTEGER NOT NULL REFERENCES schoolyears(id),
name VARCHAR NOT NULL,
long_name VARCHAR NOT NULL,
active BOOLEAN NOT NULL,
@ -47,7 +49,7 @@ CREATE TABLE classes (
CREATE TABLE subjects (
id SERIAL PRIMARY KEY,
untis_id INTEGER NOT NULL UNIQUE,
schoolyear_id INTEGER NOT NULL REFERENCES schoolyears (id),
schoolyear_id INTEGER NOT NULL REFERENCES schoolyears(id),
name VARCHAR NOT NULL,
long_name VARCHAR NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
@ -57,7 +59,7 @@ CREATE TABLE subjects (
CREATE TABLE rooms (
id SERIAL PRIMARY KEY,
untis_id INTEGER NOT NULL UNIQUE,
schoolyear_id INTEGER NOT NULL REFERENCES schoolyears (id),
schoolyear_id INTEGER NOT NULL REFERENCES schoolyears(id),
name VARCHAR NOT NULL,
long_name VARCHAR NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
@ -67,7 +69,7 @@ CREATE TABLE rooms (
CREATE TABLE departments (
id SERIAL PRIMARY KEY,
untis_id INTEGER NOT NULL UNIQUE,
schoolyear_id INTEGER NOT NULL REFERENCES schoolyears (id),
schoolyear_id INTEGER NOT NULL REFERENCES schoolyears(id),
name VARCHAR NOT NULL,
long_name VARCHAR NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
@ -77,7 +79,7 @@ CREATE TABLE departments (
CREATE TABLE holidays (
id SERIAL PRIMARY KEY,
untis_id INTEGER NOT NULL UNIQUE,
schoolyear_id INTEGER NOT NULL REFERENCES schoolyears (id),
schoolyear_id INTEGER NOT NULL REFERENCES schoolyears(id),
name VARCHAR NOT NULL,
long_name VARCHAR NOT NULL,
start_date DATE NOT NULL,
@ -88,14 +90,14 @@ CREATE TABLE holidays (
CREATE TABLE timegrids (
id SERIAL PRIMARY KEY,
schoolyear_id INTEGER NOT NULL REFERENCES schoolyears (id),
schoolyear_id INTEGER NOT NULL REFERENCES schoolyears(id),
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP
);
CREATE TABLE timegrid_days (
id SERIAL PRIMARY KEY,
timegrid_id INTEGER NOT NULL REFERENCES timegrids (id),
timegrid_id INTEGER NOT NULL REFERENCES timegrids(id),
day_index SMALLINT NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP
@ -103,7 +105,7 @@ CREATE TABLE timegrid_days (
CREATE TABLE timegrid_time_unit (
id SERIAL PRIMARY KEY,
timegrid_day_id INTEGER NOT NULL REFERENCES timegrid_days (id),
timegrid_day_id INTEGER NOT NULL REFERENCES timegrid_days(id),
start_time TIME NOT NULL,
end_time TIME NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
@ -114,7 +116,7 @@ CREATE TYPE week_type AS ENUM ('a', 'b');
CREATE TABLE substitution_queries (
id SERIAL PRIMARY KEY,
schoolyear_id INTEGER NOT NULL REFERENCES schoolyears (id),
schoolyear_id INTEGER NOT NULL REFERENCES schoolyears(id),
date DATE NOT NULL,
week_type week_type NOT NULL,
queried_at TIMESTAMP NOT NULL,
@ -142,7 +144,7 @@ CREATE TYPE substitution_type AS ENUM (
CREATE TABLE substitutions(
id SERIAL PRIMARY KEY,
substitution_query_id INTEGER NOT NULL REFERENCES substitution_queries (id),
substitution_query_id INTEGER NOT NULL REFERENCES substitution_queries(id),
subst_type substitution_type NOT NULL,
lesson_id INTEGER NOT NULL,
start_time TIME NOT NULL,
@ -154,37 +156,37 @@ CREATE TABLE substitutions(
CREATE TABLE substitution_classes (
id SERIAL PRIMARY KEY,
substitution_id INTEGER NOT NULL REFERENCES substitutions (id),
substitution_id INTEGER NOT NULL REFERENCES substitutions(id),
position SMALLINT NOT NULL,
class_id INTEGER NOT NULL REFERENCES classes (id),
class_id INTEGER NOT NULL REFERENCES classes(id),
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP
);
CREATE TABLE substitution_teachers (
id SERIAL PRIMARY KEY,
substitution_id INTEGER NOT NULL REFERENCES substitutions (id),
substitution_id INTEGER NOT NULL REFERENCES substitutions(id),
position SMALLINT NOT NULL,
teacher_id INTEGER REFERENCES teachers (id),
teacher_id INTEGER REFERENCES teachers(id),
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP
);
CREATE TABLE substitution_subjects (
id SERIAL PRIMARY KEY,
substitution_id INTEGER NOT NULL REFERENCES substitutions (id),
substitution_id INTEGER NOT NULL REFERENCES substitutions(id),
position SMALLINT NOT NULL,
subject_id INTEGER NOT NULL REFERENCES subjects (id),
subject_id INTEGER NOT NULL REFERENCES subjects(id),
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP
);
CREATE TABLE substitution_rooms (
id SERIAL PRIMARY KEY,
substitution_id INTEGER NOT NULL REFERENCES substitutions (id),
substitution_id INTEGER NOT NULL REFERENCES substitutions(id),
position SMALLINT NOT NULL,
room_id INTEGER REFERENCES rooms (id),
original_room_id INTEGER REFERENCES rooms (id),
room_id INTEGER REFERENCES rooms(id),
original_room_id INTEGER REFERENCES rooms(id),
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP
);

View file

@ -6,21 +6,7 @@ use tikv_jemallocator::Jemalloc;
static GLOBAL: Jemalloc = Jemalloc;
use actix_cors::Cors;
use actix_web::{
http::header,
middleware,
web::{self, Data},
App, Error, HttpResponse, HttpServer,
};
use juniper_actix::graphql_handler;
async fn graphql_route(
req: actix_web::HttpRequest,
payload: actix_web::web::Payload,
schema: web::Data<backend::graphql::Schema>,
) -> Result<HttpResponse, Error> {
graphql_handler(&schema, &backend::graphql::Context, req, payload).await
}
use actix_web::{http::header, middleware, App, HttpServer};
#[actix_web::main]
async fn main() -> std::io::Result<()> {
@ -29,23 +15,17 @@ async fn main() -> std::io::Result<()> {
let server = HttpServer::new(move || {
App::new()
.app_data(Data::new(backend::graphql::schema()))
.wrap(
Cors::default()
.allow_any_origin()
.allowed_methods(vec!["POST", "GET"])
.allowed_headers(vec![header::AUTHORIZATION, header::ACCEPT])
.allowed_header(header::ACCEPT)
.allowed_header(header::CONTENT_TYPE)
.supports_credentials()
.max_age(3600),
)
.wrap(middleware::Compress::default())
.wrap(middleware::Logger::default())
.service(
web::resource("/graphql")
.route(web::post().to(graphql_route))
.route(web::get().to(graphql_route)),
)
});
server.bind("0.0.0.0:80").unwrap().run().await
}

View file

@ -22,5 +22,5 @@ lazy_static! {
}
pub mod keys {
pub const LAST_SUBSTITUTION_QUERY_ID: &str = "last_subst_query_id";
// pub const LAST_SUBSTITUTION_QUERY_ID: &str = "last_subst_query_id";
}

View file

@ -1,6 +1,5 @@
use chrono::prelude::*;
use diesel::prelude::*;
use juniper::GraphQLEnum;
use std::io::Write;
use crate::db::schema;
@ -11,8 +10,6 @@ pub struct Schoolyear {
pub id: i32,
pub untis_id: i32,
pub name: String,
pub start_date: NaiveDate,
pub end_date: NaiveDate,
pub created_at: NaiveDateTime,
pub updated_at: Option<NaiveDateTime>,
}
@ -22,8 +19,6 @@ pub struct Schoolyear {
pub struct NewSchoolyear<'a> {
pub untis_id: i32,
pub name: &'a str,
pub start_date: NaiveDate,
pub end_date: NaiveDate,
}
#[derive(Identifiable, Queryable, Associations, Debug)]
@ -188,7 +183,7 @@ pub struct NewHoliday<'a> {
pub end_date: NaiveDate,
}
#[derive(GraphQLEnum, diesel::FromSqlRow, diesel::AsExpression, PartialEq, Eq, Clone, Debug)]
#[derive(diesel::FromSqlRow, diesel::AsExpression, PartialEq, Eq, Clone, Debug)]
#[diesel(sql_type = schema::sql_types::WeekType)]
pub enum WeekType {
A,
@ -243,7 +238,7 @@ pub struct NewSubstitutionQuery {
pub queried_at: NaiveDateTime,
}
#[derive(GraphQLEnum, diesel::FromSqlRow, diesel::AsExpression, PartialEq, Eq, Clone, Debug)]
#[derive(diesel::FromSqlRow, diesel::AsExpression, PartialEq, Eq, Clone, Debug)]
#[diesel(sql_type = schema::sql_types::SubstitutionType)]
pub enum SubstitutionType {
Cancel,

View file

@ -13,8 +13,6 @@ diesel::table! {
id -> Integer,
untis_id -> Integer,
name -> VarChar,
start_date -> Date,
end_date -> Date,
created_at -> Timestamp,
updated_at -> Nullable<Timestamp>,
}

View file

@ -1,324 +0,0 @@
use diesel::prelude::*;
use juniper::{graphql_object, EmptyMutation, EmptySubscription, FieldResult, RootNode};
use r2d2_redis::redis;
use std::ops::DerefMut;
use crate::{cache, db};
#[derive(Clone)]
pub struct Context;
impl juniper::Context for Context {}
pub struct Schoolyear {
pub model: db::models::Schoolyear,
}
#[graphql_object]
impl Schoolyear {
fn id(&self) -> i32 {
self.model.id
}
fn untis_id(&self) -> i32 {
self.model.untis_id
}
fn name(&self) -> &str {
self.model.name.as_str()
}
fn start_date(&self) -> chrono::NaiveDate {
self.model.start_date
}
fn end_date(&self) -> chrono::NaiveDate {
self.model.end_date
}
}
pub struct Teacher {
pub model: db::models::Teacher,
}
#[graphql_object]
impl Teacher {
fn id(&self) -> i32 {
self.model.id
}
fn untis_id(&self) -> i32 {
self.model.untis_id
}
fn schoolyear(&self) -> FieldResult<Schoolyear> {
let db_conn = &mut db::POOL.get()?;
Ok(Schoolyear {
model: db::schema::schoolyears::table
.filter(db::schema::schoolyears::id.eq(self.model.schoolyear_id))
.first::<db::models::Schoolyear>(db_conn)?,
})
}
fn name(&self) -> &str {
&self.model.name
}
fn forename(&self) -> Option<&str> {
self.model.forename.as_deref()
}
fn display_name(&self) -> &str {
&self.model.display_name
}
}
pub struct Class {
pub model: db::models::Class,
}
#[graphql_object]
impl Class {
fn id(&self) -> i32 {
self.model.id
}
fn untis_id(&self) -> i32 {
self.model.untis_id
}
fn schoolyear(&self) -> FieldResult<Schoolyear> {
let db_conn = &mut db::POOL.get()?;
Ok(Schoolyear {
model: db::schema::schoolyears::table
.filter(db::schema::schoolyears::id.eq(self.model.schoolyear_id))
.first::<db::models::Schoolyear>(db_conn)?,
})
}
fn name(&self) -> &str {
&self.model.name
}
fn long_name(&self) -> &str {
&self.model.long_name
}
fn active(&self) -> bool {
self.model.active
}
}
pub struct SubstitutionClass {
pub model: db::models::SubstitutionClass,
}
#[graphql_object]
impl SubstitutionClass {
fn id(&self) -> i32 {
self.model.id
}
fn substitution(&self) -> FieldResult<Substitution> {
let db_conn = &mut db::POOL.get()?;
Ok(Substitution {
model: db::schema::substitutions::table
.filter(db::schema::substitutions::id.eq(self.model.substitution_id))
.first::<db::models::Substitution>(db_conn)?,
})
}
fn position(&self) -> i32 {
self.model.position as i32
}
fn class(&self) -> FieldResult<Class> {
let db_conn = &mut db::POOL.get()?;
Ok(Class {
model: db::schema::classes::table
.filter(db::schema::classes::id.eq(self.model.class_id))
.first::<db::models::Class>(db_conn)?,
})
}
}
pub struct SubstitutionTeacher {
pub model: db::models::SubstitutionTeacher,
}
#[graphql_object]
impl SubstitutionTeacher {
fn id(&self) -> i32 {
self.model.id
}
fn substitution(&self) -> FieldResult<Substitution> {
let db_conn = &mut db::POOL.get()?;
Ok(Substitution {
model: db::schema::substitutions::table
.filter(db::schema::substitutions::id.eq(self.model.substitution_id))
.first::<db::models::Substitution>(db_conn)?,
})
}
fn position(&self) -> i32 {
self.model.position as i32
}
fn teacher(&self) -> FieldResult<Option<Teacher>> {
if let Some(teacher_id) = self.model.teacher_id {
let db_conn = &mut db::POOL.get()?;
Ok(Some(Teacher {
model: db::schema::teachers::table
.filter(db::schema::teachers::id.eq(teacher_id))
.first::<db::models::Teacher>(db_conn)?,
}))
} else {
Ok(None)
}
}
}
pub struct Substitution {
pub model: db::models::Substitution,
}
#[graphql_object]
impl Substitution {
fn id(&self) -> i32 {
self.model.id
}
fn substitution_query(&self) -> FieldResult<SubstitutionQuery> {
let db_conn = &mut db::POOL.get()?;
Ok(SubstitutionQuery {
model: db::schema::substitution_queries::table
.filter(db::schema::substitution_queries::id.eq(self.model.substitution_query_id))
.first::<db::models::SubstitutionQuery>(db_conn)?,
})
}
fn subst_type(&self) -> db::models::SubstitutionType {
self.model.subst_type.to_owned()
}
fn lesson_id(&self) -> i32 {
self.model.lesson_id
}
fn start_time(&self) -> chrono::NaiveTime {
self.model.start_time
}
fn end_time(&self) -> chrono::NaiveTime {
self.model.end_time
}
fn text(&self) -> Option<&str> {
self.model.text.as_deref()
}
fn classes(&self) -> FieldResult<Vec<SubstitutionClass>> {
let db_conn = &mut db::POOL.get()?;
Ok(db::schema::substitution_classes::table
.filter(db::schema::substitution_classes::substitution_id.eq(self.model.id))
.load::<db::models::SubstitutionClass>(db_conn)?
.into_iter()
.map(|x| SubstitutionClass { model: x })
.collect())
}
}
pub struct SubstitutionQuery {
pub model: db::models::SubstitutionQuery,
}
#[graphql_object]
impl SubstitutionQuery {
fn id(&self) -> i32 {
self.model.id
}
fn schoolyear(&self) -> FieldResult<Schoolyear> {
let db_conn = &mut db::POOL.get()?;
Ok(Schoolyear {
model: db::schema::schoolyears::table
.filter(db::schema::schoolyears::id.eq(self.model.schoolyear_id))
.first::<db::models::Schoolyear>(db_conn)?,
})
}
fn date(&self) -> chrono::NaiveDate {
self.model.date
}
fn week_type(&self) -> db::models::WeekType {
self.model.week_type.to_owned()
}
fn queried_at(&self) -> chrono::NaiveDateTime {
self.model.queried_at
}
fn substitutions(&self) -> FieldResult<Vec<Substitution>> {
let db_conn = &mut db::POOL.get()?;
Ok(db::schema::substitutions::table
.filter(db::schema::substitutions::substitution_query_id.eq(self.model.id))
.load::<db::models::Substitution>(db_conn)?
.into_iter()
.map(|x| Substitution { model: x })
.collect())
}
}
pub struct Query;
#[graphql_object(context = Context)]
impl Query {
fn ping() -> &'static str {
"pong"
}
fn last_substitution_query() -> FieldResult<SubstitutionQuery> {
let db_conn = &mut db::POOL.get()?;
let redis_conn = &mut cache::POOL.get()?;
let id = redis::cmd("GET")
.arg(cache::keys::LAST_SUBSTITUTION_QUERY_ID)
.query::<Option<i32>>(redis_conn.deref_mut())?
.map_or_else(
|| {
db::schema::substitution_queries::table
.select(db::schema::substitution_queries::id)
.order(db::schema::substitution_queries::queried_at.desc())
.first::<i32>(db_conn)
},
|x| Ok(x),
)?;
let last_query = db::schema::substitution_queries::table
.filter(db::schema::substitution_queries::id.eq(id))
.first::<db::models::SubstitutionQuery>(db_conn)?;
Ok(SubstitutionQuery { model: last_query })
}
}
pub type Schema = RootNode<'static, Query, EmptyMutation<Context>, EmptySubscription<Context>>;
pub fn schema() -> Schema {
Schema::new(
Query,
EmptyMutation::<Context>::new(),
EmptySubscription::<Context>::new(),
)
}

View file

@ -1,5 +1,4 @@
pub mod cache;
pub mod config;
pub mod db;
pub mod graphql;
pub mod worker;

View file

@ -4,13 +4,11 @@ use celery::task::TaskResult;
use chrono::prelude::*;
use diesel::prelude::*;
use lazy_static::lazy_static;
use r2d2_redis::redis;
use regex::Regex;
use std::ops::DerefMut;
use std::thread;
use std::time::Duration;
use crate::{cache, config, db};
use crate::{config, db};
async fn fetch_schoolyears(client: &untis::Client, db_conn: &mut PgConnection) -> Result<i32> {
let existing_schoolyears = db::schema::schoolyears::table
@ -26,8 +24,6 @@ async fn fetch_schoolyears(client: &untis::Client, db_conn: &mut PgConnection) -
.map(|y| db::models::NewSchoolyear {
untis_id: y.id,
name: &y.name,
start_date: y.start_date,
end_date: y.end_date,
})
.collect::<Vec<db::models::NewSchoolyear>>(),
)
@ -273,7 +269,6 @@ async fn fetch_holidays(
async fn fetch_substitutions(
client: &untis::Client,
db_conn: &mut PgConnection,
redis_conn: &mut cache::ConnectionPool,
schoolyear_id: i32,
) -> Result<()> {
lazy_static! {
@ -347,10 +342,6 @@ async fn fetch_substitutions(
})
.returning(db::schema::substitution_queries::id)
.get_result::<i32>(db_conn)?;
redis::cmd("SET")
.arg(cache::keys::LAST_SUBSTITUTION_QUERY_ID)
.arg(substitution_query_id)
.query(redis_conn.deref_mut())?;
for substitution in client.substitutions(&date, &date, None).await? {
let substitution_id = diesel::insert_into(db::schema::substitutions::table)
@ -489,10 +480,10 @@ pub async fn update_info() -> TaskResult<()> {
Ok(x) => x,
Err(e) => return Err(TaskError::UnexpectedError(e.to_string())),
};
let redis_conn = &mut match cache::POOL.get() {
Ok(x) => x,
Err(e) => return Err(TaskError::UnexpectedError(e.to_string())),
};
// let redis_conn = &mut match cache::POOL.get() {
// Ok(x) => x,
// Err(e) => return Err(TaskError::UnexpectedError(e.to_string())),
// };
let schoolyear_id = match fetch_schoolyears(&client, db_conn).await {
Ok(x) => x,
@ -527,7 +518,7 @@ pub async fn update_info() -> TaskResult<()> {
return Err(TaskError::UnexpectedError(e.to_string()));
}
thread::sleep(dur);
if let Err(e) = fetch_substitutions(&client, db_conn, redis_conn, schoolyear_id).await {
if let Err(e) = fetch_substitutions(&client, db_conn, schoolyear_id).await {
return Err(TaskError::UnexpectedError(e.to_string()));
}
thread::sleep(dur);

View file

@ -23,6 +23,10 @@ http {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
server {
listen 8080;
location /adminer {
proxy_pass http://adminer:8080/;