diff --git a/.example.env b/.example.env index 449f080..a766173 100644 --- a/.example.env +++ b/.example.env @@ -30,26 +30,11 @@ AUTH_UNTIS_PASSWORD= # Backend BACKEND_MINIMUM_TEACHER_SELECTION_COUNT=6 -BACKEND_ASSIGNMENT_POSSIBILITY_COUNT=65536 +BACKEND_ASSIGNMENT_POSSIBILITY_COUNT=16777216 BACKEND_URL=URL # Backend - API BACKEND_API_JWT_SECRET= BACKEND_API_JWT_EXPIRATION=360 # Backend - Worker -# Backend - SMTP -BACKEND_SMTP_HELO= -BACKEND_SMTP_HOST= -BACKEND_SMTP_PORT=587 -BACKEND_SMTP_NAME= -BACKEND_SMTP_USERNAME= -BACKEND_SMTP_PASSWORD= # Backend - Db BACKEND_DB_ALLOW_OLD_SCHEMA=false -# Backend - LDAP -BACKEND_LDAP_HOST="ldap.example.com" -BACKEND_LDAP_PORT=389 -BACKEND_LDAP_BASE_DN="dc=ldap,dc=example,dc=com" -BACKEND_LDAP_BASE_USER_DN="ou=users,dc=ldap,dc=example,dc=com" -BACKEND_LDAP_BIND_DN="cn=admin,dc=ldap,dc=example,dc=com" -BACKEND_LDAP_BIND_PASSWORD= -BACKEND_LDAP_CACHE_REFRESH_INTERVAL=720 diff --git a/backend/Dockerfile b/backend/Dockerfile index 908c6fe..96bc50e 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -61,18 +61,11 @@ COPY --from=templates-html /usr/src/templates/html ./templates/html COPY ./src ./src RUN if [ "${BUILD_ENV}" = "development" ]; then \ make dev; \ + ldd bin/backend | tr -s '[:blank:]' '\n' | grep '^/' | \ + xargs -I % sh -c 'mkdir -p $(dirname deps%); cp % deps%;'; \ else \ make; \ fi -RUN if [ "${BUILD_ENV}" = "development" ]; then \ - ldd bin/backend | tr -s '[:blank:]' '\n' | grep '^/' | \ - xargs -I % sh -c 'mkdir -p $(dirname deps%); cp % deps%;'; \ - fi - -# FROM alpine as config -# WORKDIR /usr/src/config -# RUN mkdir ./tmp -# RUN chmod -R 1777 ./tmp FROM busybox as runner LABEL maintainer="Dominic Grimm " \ @@ -80,7 +73,6 @@ LABEL maintainer="Dominic Grimm " \ org.opencontainers.image.licenses="GPL-3.0" \ org.opencontainers.image.source="https://git.dergrimm.net/mentorenwahl/mentorenwahl" \ org.opencontainers.image.url="https://git.dergrimm.net/mentorenwahl/mentorenwahl" -# COPY --from=config /usr/src/config/tmp /tmp WORKDIR /usr/src/mentorenwahl COPY --from=micrate-builder /usr/src/micrate/bin/micrate ./bin/micrate COPY --from=builder /usr/src/mentorenwahl/db ./db diff --git a/backend/shard.lock b/backend/shard.lock index 656a75f..7b39831 100644 --- a/backend/shard.lock +++ b/backend/shard.lock @@ -60,6 +60,10 @@ shards: git: https://git.dergrimm.net/dergrimm/compiled_license.git version: 2.0.0 + cute: + git: https://github.com/papierkorb/cute.git + version: 0.4.0 + db: git: https://github.com/crystal-lang/crystal-db.git version: 0.11.0 @@ -68,14 +72,18 @@ shards: git: https://github.com/repomaa/docker.cr.git version: 0.1.2 - email: - git: https://github.com/arcage/crystal-email.git - version: 0.6.4 - env_config: git: https://github.com/repomaa/env_config.cr.git version: 0.1.0+git.commit.a3ef5b955f27e2c65de2fe0ff41718e2eea7c06f + fancyline: + git: https://github.com/papierkorb/fancyline.git + version: 0.4.1 + + future: + git: https://github.com/crystal-community/future.cr.git + version: 1.0.0 + generate: git: https://github.com/anykeyh/generate.cr.git version: 0.1.0+git.commit.f5dafc934a70e0ee2f246dddf3df44686f844da2 @@ -100,18 +108,6 @@ shards: git: https://github.com/crystal-community/jwt.git version: 1.6.0 - kilt: - git: https://github.com/jeromegn/kilt.git - version: 0.6.1 - - ldap: - git: https://github.com/spider-gazelle/crystal-ldap.git - version: 0.9.1 - - ldap_escape: - git: https://git.dergrimm.net/dergrimm/ldap_escape.git - version: 0.1.0 - mosquito: git: https://github.com/mosquito-cr/mosquito.git version: 0.11.2 @@ -132,14 +128,6 @@ shards: git: https://github.com/maiha/pretty.cr.git version: 1.1.2 - promise: - git: https://github.com/spider-gazelle/promise.git - version: 3.0.0 - - quartz_mailer: - git: https://github.com/amberframework/quartz-mailer.git - version: 0.8.0 - redis: git: https://github.com/stefanwille/crystal-redis.git version: 2.8.3 diff --git a/backend/shard.yml b/backend/shard.yml index d22466a..4500ccc 100644 --- a/backend/shard.yml +++ b/backend/shard.yml @@ -41,16 +41,8 @@ dependencies: github: mrrooijen/commander mosquito: github: mosquito-cr/mosquito - quartz_mailer: - github: amberframework/quartz-mailer - kilt: - github: jeromegn/kilt env_config: github: repomaa/env_config.cr - ldap: - github: spider-gazelle/crystal-ldap - ldap_escape: - git: https://git.dergrimm.net/dergrimm/ldap_escape.git shard: github: maiha/shard.cr retriable: @@ -59,8 +51,6 @@ dependencies: git: https://git.dergrimm.net/dergrimm/service.git redis: github: stefanwille/crystal-redis - pool: - github: ysbaddaden/pool athena: github: athena-framework/framework baked_file_system: @@ -76,3 +66,5 @@ dependencies: graphql-dataloader: github: graphql-crystal/dataloader branch: main + fancyline: + github: Papierkorb/fancyline diff --git a/backend/src/backend/api/errors.cr b/backend/src/backend/api/errors.cr index f36eb95..8045754 100644 --- a/backend/src/backend/api/errors.cr +++ b/backend/src/backend/api/errors.cr @@ -36,11 +36,11 @@ module Backend::Api::Errors end end - class LdapUserDoesNotExist < PublicError - def api_message : String - "LDAP user does not exist" - end - end + # class LdapUserDoesNotExist < PublicError + # def api_message : String + # "LDAP user does not exist" + # end + # end class DuplicateTeachers < PublicError def api_message : String @@ -54,9 +54,15 @@ module Backend::Api::Errors end end - class TeachersNotRegistered < PublicError + # class TeachersNotRegistered < PublicError + # def api_message : String + # "Teachers not registered" + # end + # end + + class VotingNotAllowed < PublicError def api_message : String - "Teachers not registered" + "Voting not yet allowed" end end diff --git a/backend/src/backend/api/schema/mutation.cr b/backend/src/backend/api/schema/mutation.cr index ba9d7ac..caa62c4 100644 --- a/backend/src/backend/api/schema/mutation.cr +++ b/backend/src/backend/api/schema/mutation.cr @@ -14,7 +14,6 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -require "ldap" require "uuid" require "uuid/json" @@ -191,8 +190,11 @@ module Backend raise Errors::DuplicateTeachers.new if input.teacher_ids.uniq.size != input.teacher_ids.size raise Errors::NotEnoughTeachers.new if input.teacher_ids.size < Backend.config.minimum_teacher_selection_count - teacher_role_count = Db::User.query.where(role: Db::UserRole::Teacher).count - raise Errors::TeachersNotRegistered.new if teacher_role_count != Db::Teacher.query.count || teacher_role_count.zero? + # teacher_role_count = Db::User.query.where(role: Db::UserRole::Teacher).count + # raise Errors::TeachersNotRegistered.new if teacher_role_count != Db::Teacher.query.count || teacher_role_count.zero? + + pp! config = Db::Config.query.select(:can_vote).where { active }.first! + raise Errors::VotingNotAllowed.new unless Db::Config.query.select(:can_vote).where { active }.first!.can_vote input.teacher_ids.each do |id| teacher = Db::Teacher.find(id) @@ -226,7 +228,7 @@ module Backend config.can_vote = state config.save! - state + true end end end diff --git a/backend/src/backend/cli.cr b/backend/src/backend/cli.cr index b07fe27..035dcd4 100644 --- a/backend/src/backend/cli.cr +++ b/backend/src/backend/cli.cr @@ -1,124 +1,9 @@ require "commander" require "tallboy" require "wannabe_bool" -require "csv" +require "fancyline" module Backend - alias TeacherVote = {student: Int32, priority: Int32} - alias Assignment = {teacher: Int32, priority: Int32} - - def do_assignment(roll_count : UInt32) : Time::Span - teachers = Db::Teacher.query - .where do - raw("EXISTS (SELECT 1 FROM teacher_votes WHERE teacher_id = teachers.id)") & - (max_students > 0) - end - .with_teacher_votes - .to_a - teacher_ids = teachers.map(&.id) - teacher_max_students = Hash.zip(teacher_ids, teachers.map(&.max_students)) - teacher_votes : Hash(Int32, Array(TeacherVote)) = Hash.zip( - teacher_ids, - teachers.map do |t| - t.teacher_votes.map do |tv| - { - student: tv.vote.student.id, - priority: tv.priority, - } - end - end - ) - - students = Db::Student.query - .with_vote(&.with_teacher_votes(&.order_by(priority: :desc))) - .to_a - student_ids = students.map(&.id) - votes = Hash.zip( - student_ids, - students.map do |s| - s.vote.not_nil!.teacher_votes - .to_a - .select! { |tv| teacher_votes.has_key?(tv.teacher.id) } - .map do |tv| - { - teacher: tv.teacher.id, - priority: tv.priority, - } - end - end - ) - votes_a = votes.to_a - - t1 = Time.utc - best : {assignment: Hash(Int32, Assignment), priority_score: Int64, teacher_score: Int64}? = nil - empty_assignment_count = Hash.zip(teachers.map(&.id), [0] * teachers.size) - roll_count.times.each do |i| - p! i - assignment = {} of Int32 => Assignment - assignment_count = empty_assignment_count.clone - votes_a.shuffle(Random::Secure).each do |s, tvs| - tvs.each do |tv| - if assignment_count[tv[:teacher]] < teacher_max_students[tv[:teacher]] - if assignment[s]?.nil? - assignment_count[tv[:teacher]] += 1 - assignment[s] = {teacher: tv[:teacher], priority: tv[:priority]} - else - assignment_count[assignment[s][:teacher]] -= 1 - assignment_count[tv[:teacher]] += 1 - assignment[s] = {teacher: tv[:teacher], priority: tv[:priority]} - end - end - end - end - - priority_score = 0_i64 - assignment.each do |_, a| - priority_score += a[:priority] ** 2 - end - - teacher_score = 0_i64 - assignment_count.each do |t, c| - teacher_score += (teacher_max_students[t] ** c) * teacher_max_students[t] - end - - if best.nil? - best = { - assignment: assignment, - priority_score: priority_score, - teacher_score: teacher_score, - } - elsif priority_score < best.not_nil![:priority_score] && teacher_score < best.not_nil![:teacher_score] - best = { - assignment: assignment, - priority_score: priority_score, - teacher_score: teacher_score, - } - end - end - t2 = Time.utc - - pp! best - - # Db::Assignment.import(best.not_nil![:assignment].map { |s, a| Db::Assignment.new({student_id: s, teacher_id: a[:teacher]}) }) - Db::Assignment.query.where { active }.to_update.set(active: false).execute - assignment_id = Db::Assignment.create!({ - active: true, - priority_score: best.not_nil![:priority_score], - teacher_score: best.not_nil![:teacher_score], - }).id - Db::StudentAssignment.import( - best.not_nil![:assignment].map do |s, a| - Db::StudentAssignment.new({ - assignment_id: assignment_id, - student_id: s, - teacher_id: a[:teacher], - }) - end - ) - - t2 - t1 - end - CLI = Commander::Command.new do |cmd| cmd.use = "backend" cmd.short = "Mentorenwahl backend CLI" @@ -365,118 +250,5 @@ module Backend end end end - - # ameba:disable Lint/ShadowingOuterLocalVar - cmd.commands.add do |cmd| - cmd.use = "stats" - cmd.short = "Runs tests and outputs statistics for analysis" - cmd.long = cmd.short - - cmd.run do - result = CSV.build do |csv| - csv.row "roll_count", "students", "time", "priority_score", "teacher_score" - - (2..100).each do |i| - p! i - p! student_count = 0...i * 10 - p! teacher_count = 0...i * 5 - - Db::User.import( - student_count.map do |x| - Db::User.new({ - username: "student#{x}", - password_hash: "$2a$12$eEkFG9OAfaAgwPSHTIVfMedH9VIijpRIz1jddkxuJnbe5zwfVIQ6y", - initial_password: "12345", - password_changed: false, - first_name: "Student#{x}", - last_name: "Student#{x}", - role: Db::UserRole::Student, - admin: false, - }) - end.concat( - teacher_count.map do |x| - Db::User.new({ - username: "teacher#{x}", - password_hash: "$2a$12$eEkFG9OAfaAgwPSHTIVfMedH9VIijpRIz1jddkxuJnbe5zwfVIQ6y", - initial_password: "12345", - password_changed: false, - first_name: "Teacher#{x}", - last_name: "Teacher#{x}", - role: Db::UserRole::Teacher, - admin: false, - }) - end - ) - ) - - class_id = Db::Class.create!({name: "Default class"}).id - student_user_ids = Db::User.query.select(:id).where { role == Db::UserRole::Student }.map(&.id) - Db::Student.import( - student_user_ids.map do |id| - Db::Student.new({ - user_id: id, - class_id: class_id, - }) - end - ) - student_ids = Db::Student.query.select(:id).map(&.id) - - teacher_user_ids = Db::User.query.select(:id).where { role == Db::UserRole::Teacher }.map(&.id) - Db::Teacher.import( - teacher_user_ids.map do |id| - Db::Teacher.new({ - user_id: id, - max_students: id % 5, - }) - end - ) - teacher_ids = Db::Teacher.query.select(:id).map(&.id) - - Db::Vote.import( - student_ids.map do |id| - Db::Vote.new({student_id: id}) - end - ) - vote_ids = Db::Vote.query.select(:id).map(&.id) - Db::TeacherVote.import( - vote_ids.flat_map do |id| - size = 6 + id % 4 - tvs = [] of Int32 - while tvs.size < size - t_id = teacher_ids.sample - tvs << t_id unless t_id.in?(tvs) - end - - tvs.map_with_index do |t, j| - Db::TeacherVote.new({ - vote_id: id, - teacher_id: t, - priority: j, - }) - end - end - ) - - dt = do_assignment(Backend.config.assignment_possibility_count) - a = Db::Assignment.query.where { active }.first! - csv.row Backend.config.assignment_possibility_count, student_ids.size, dt.seconds, a.priority_score, a.teacher_score - - puts csv - - Db::StudentAssignment.query.to_delete.execute - Db::Assignment.query.to_delete.execute - Db::TeacherVote.query.to_delete.execute - Db::Vote.query.to_delete.execute - Db::Teacher.query.to_delete.execute - Db::Student.query.to_delete.execute - Db::Class.query.to_delete.execute - Db::User.query.to_delete.execute - end - end - - puts result - File.write("/static/stats.csv", result.to_s) - end - end end end diff --git a/backend/src/backend/config.cr b/backend/src/backend/config.cr index 96927a8..84ff3f1 100644 --- a/backend/src/backend/config.cr +++ b/backend/src/backend/config.cr @@ -68,10 +68,6 @@ module Backend # Configuration for `Api` getter api : ApiConfig - @[EnvConfig::Setting(key: "smtp")] - # Configuration for `Mailers` - getter smtp : SmtpConfig - @[EnvConfig::Setting(key: "db")] # Configuration for `Db` getter db : DbConfig @@ -79,10 +75,6 @@ module Backend @[EnvConfig::Setting(key: "redis")] getter redis : RedisConfig - @[EnvConfig::Setting(key: "ldap")] - # Configuration for `Ldap` - getter ldap : LdapConfig - @[EnvConfig::Setting(key: "auth")] # Configuration for authorization provider getter auth : AuthConfig @@ -103,31 +95,6 @@ module Backend end end - # Configuration for `Mailers` - class SmtpConfig - include EnvConfig - - # SMTP host HELO - # - # NOTE: HELOs are [FQDNs](https://en.wikipedia.org/wiki/Fully_qualified_domain_name), so this should be a domain name - getter helo : String - - # SMTP hostname - getter host : String - - # SMTP port - getter port : Int32 - - # Name to send from - getter name : String - - # SMTP username - getter username : String - - # SMTP password - getter password : String - end - # Configuration for `Db` class DbConfig include EnvConfig @@ -155,34 +122,6 @@ module Backend end end - # Configuration for `Ldap` - class LdapConfig - include EnvConfig - - # LDAP hostname - getter host : String - - # LDAP port - getter port : Int32 - - # LDAP base DN - getter base_dn : String - - # LDAP user base DN - getter base_user_dn : String - - # LDAP bind DN - # - # NOTE: This is the DN to search with - getter bind_dn : String - - # LDAP bind password - getter bind_password : String - - # Periodical cache refresh interval - getter cache_refresh_interval : Int32 - end - # Configuration for authoriuation API class AuthConfig include EnvConfig diff --git a/backend/src/backend/ldap.cr b/backend/src/backend/ldap.cr deleted file mode 100644 index 22e575d..0000000 --- a/backend/src/backend/ldap.cr +++ /dev/null @@ -1,43 +0,0 @@ -# Mentorenwahl: A fullstack application for assigning mentors to students based on their whishes. -# Copyright (C) 2022 Dominic Grimm -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -require "ldap" -require "socket" -require "ldap_escape" -require "pool/connection" - -require "./ldap/*" - -module Backend - # Provides LDAP utility functions - module Ldap - extend self - - CLIENT = ConnectionPool.new(capacity: 25) { create_client } - - # Creates a new LDAP connection - private def create_client : LDAP::Client - LDAP::Client.new(TCPSocket.new(Backend.config.ldap.host, Backend.config.ldap.port)) - end - - # Checks if credentials are valid - def authenticate?(dn : String, password : String) : Bool - !!create_client.authenticate(dn, password) - rescue LDAP::Client::AuthError - false - end - end -end diff --git a/backend/src/backend/ldap/dn.cr b/backend/src/backend/ldap/dn.cr deleted file mode 100644 index b6f25c6..0000000 --- a/backend/src/backend/ldap/dn.cr +++ /dev/null @@ -1,34 +0,0 @@ -# Mentorenwahl: A fullstack application for assigning mentors to students based on their whishes. -# Copyright (C) 2022 Dominic Grimm -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -module Backend - module Ldap - # DN construction utilities - module DN - extend self - - # Constructs a CN DN from a username - def cn(username : String) : String - "cn=#{LdapEscape.dn(username)},#{Backend.config.ldap.user_dn}" - end - - # Constructs a UID DN from a username - def uid(uid : String) : String - "uid=#{LdapEscape.dn(uid)},#{Backend.config.ldap.base_user_dn}" - end - end - end -end diff --git a/backend/src/backend/ldap/user.cr b/backend/src/backend/ldap/user.cr deleted file mode 100644 index cfd0fb3..0000000 --- a/backend/src/backend/ldap/user.cr +++ /dev/null @@ -1,86 +0,0 @@ -# Mentorenwahl: A fullstack application for assigning mentors to students based on their whishes. -# Copyright (C) 2022 Dominic Grimm -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -require "json" - -module Backend - module Ldap - # LDAP user properties - struct User - include JSON::Serializable - - alias Raw = Hash(String, Array(String)) - - # First name - getter first_name : String - - # Last name - getter last_name : String - - @[JSON::Field(key: "mail")] - # Email address - getter email : String - - def initialize(@first_name : String, @last_name : String, @email : String) - end - - # Name - def name(formal = true) : String - if formal - "#{@last_name}, #{@first_name}" - else - "#{@first_name} #{@last_name}" - end - end - - # Creates user data from LDAP entry - def self.from_raw(raw : Raw) : self - self.new( - first_name: raw["givenName"].first, - last_name: raw["sn"].first, - email: raw["mail"].first - ) - end - - # Creates user data from LDAP DN entry - def self.from_dn(dn : String) : self - from_raw( - CLIENT.connection do |client| - client - .authenticate(Backend.config.ldap.bind_dn, Backend.config.ldap.bind_password) - .search(base: dn, attributes: %w(givenName sn mail)) - .first - end - ) - end - - # Creates user data from LDAP username - def self.from_username(username : String) : self - from_dn(Ldap::DN.uid(username)) - end - - # Creates user data from DB entry - def self.from_db(user : Db::User) : self - from_username(user.username) - end - - # Creates user data from DB entry index - def self.from_id(id : Int32) : self - from_username(Db::User.query.first(id).select(:id)) - end - end - end -end diff --git a/backend/src/backend/mailers.cr b/backend/src/backend/mailers.cr deleted file mode 100644 index ec78f53..0000000 --- a/backend/src/backend/mailers.cr +++ /dev/null @@ -1,36 +0,0 @@ -# Mentorenwahl: A fullstack application for assigning mentors to students based on their whishes. -# Copyright (C) 2022 Dominic Grimm -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -require "quartz_mailer" -require "kilt" - -require "./mailers/*" - -module Backend - # Mailer definitions - module Mailers - Quartz.config do |config| - config.smtp_enabled = true - config.smtp_address = Backend.config.smtp.host - config.smtp_port = Backend.config.smtp.port - config.helo_domain = Backend.config.smtp.helo - config.use_tls = EMail::Client::TLSMode::STARTTLS - config.username = Backend.config.smtp.username - config.password = Backend.config.smtp.password - config.use_authentication = true - end - end -end diff --git a/backend/src/backend/mailers/templates/.keep b/backend/src/backend/mailers/templates/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/backend/src/backend/worker/jobs/cache_ldap_user_job.cr b/backend/src/backend/worker/jobs/cache_ldap_user_job.cr deleted file mode 100644 index 73afcce..0000000 --- a/backend/src/backend/worker/jobs/cache_ldap_user_job.cr +++ /dev/null @@ -1,40 +0,0 @@ -# Mentorenwahl: A fullstack application for assigning mentors to students based on their whishes. -# Copyright (C) 2022 Dominic Grimm -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -module Backend - module Worker - module Jobs - # Caches user data in redis cache - class CacheLdapUserJob < Mosquito::QueuedJob - params id : Int32 - - # :ditto: - def perform : Nil - key = "ldap:user:#{id}" - user = Db::User.find!(id) - if user - log "Caching user ##{id}..." - ldap_user = Ldap::User.from_username(user.username) - Redis::CLIENT.set(key, ldap_user.to_json, ex: (Time.utc + Backend.config.ldap.cache_refresh_interval.minutes).to_unix) - else - log "User ##{id} not found. Deleting cache..." - Redis::CLIENT.del(key) - end - end - end - end - end -end diff --git a/backend/templates/html/users.html.ecr b/backend/templates/html/users.html.ecr index 600a5fa..6d22e6b 100644 --- a/backend/templates/html/users.html.ecr +++ b/backend/templates/html/users.html.ecr @@ -154,6 +154,8 @@ + <%- else -%> + <%- end -%> <%- end -%> diff --git a/config/nginx/nginx.conf b/config/nginx/nginx.conf index 20d933e..0d81387 100644 --- a/config/nginx/nginx.conf +++ b/config/nginx/nginx.conf @@ -23,6 +23,8 @@ http { more_clear_headers Server; server { + listen 80; + location / { proxy_pass http://frontend/; } @@ -30,6 +32,10 @@ http { location /graphql { proxy_pass http://backend/; } + } + + server { + listen 8080; location /adminer { proxy_pass http://adminer:8080/; diff --git a/docker-compose.yml b/docker-compose.yml index 4f3be43..ae6d813 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -18,12 +18,13 @@ version: "3" services: nginx: - image: docker.io/byjg/nginx-extras + image: docker.io/openresty/openresty:1.21.4.1-0-alpine restart: always volumes: - - ./config/nginx/nginx.conf:/etc/nginx/nginx.conf:ro + - ./config/nginx/nginx.conf:/usr/local/openresty/nginx/conf/nginx.conf:ro ports: - 80:80 + - 8080:8080 depends_on: - adminer - backend @@ -82,23 +83,10 @@ services: BACKEND_ASSIGNMENT_POSSIBILITY_COUNT: ${BACKEND_ASSIGNMENT_POSSIBILITY_COUNT} BACKEND_API_JWT_SECRET: ${BACKEND_API_JWT_SECRET} BACKEND_API_JWT_EXPIRATION: ${BACKEND_API_JWT_EXPIRATION} - BACKEND_SMTP_HELO: ${BACKEND_SMTP_HELO} - BACKEND_SMTP_HOST: ${BACKEND_SMTP_HOST} - BACKEND_SMTP_PORT: ${BACKEND_SMTP_PORT} - BACKEND_SMTP_NAME: ${BACKEND_SMTP_NAME} - BACKEND_SMTP_USERNAME: ${BACKEND_SMTP_USERNAME} - BACKEND_SMTP_PASSWORD: ${BACKEND_SMTP_PASSWORD} BACKEND_DB_URL: postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_USER} BACKEND_DB_ALLOW_OLD_SCHEMA: ${BACKEND_DB_ALLOW_OLD_SCHEMA} BACKEND_REDIS_HOST: redis BACKEND_REDIS_PORT: 6379 - BACKEND_LDAP_HOST: ${BACKEND_LDAP_HOST} - BACKEND_LDAP_PORT: ${BACKEND_LDAP_PORT} - BACKEND_LDAP_BASE_DN: ${BACKEND_LDAP_BASE_DN} - BACKEND_LDAP_BASE_USER_DN: ${BACKEND_LDAP_BASE_USER_DN} - BACKEND_LDAP_BIND_DN: ${BACKEND_LDAP_BIND_DN} - BACKEND_LDAP_BIND_PASSWORD: ${BACKEND_LDAP_BIND_PASSWORD} - BACKEND_LDAP_CACHE_REFRESH_INTERVAL: ${BACKEND_LDAP_CACHE_REFRESH_INTERVAL} BACKEND_AUTH_URL: "http://auth/v1" volumes: - /etc/timezone:/etc/timezone:ro diff --git a/frontend/Dockerfile b/frontend/Dockerfile index 808a070..017cae9 100644 --- a/frontend/Dockerfile +++ b/frontend/Dockerfile @@ -47,11 +47,11 @@ WORKDIR /usr/src/public COPY --from=public /usr/src/public . RUN find . -name "*.wasm" -type f | xargs -I % wasm-opt % -o % -O --intrinsic-lowering -Oz -FROM byjg/nginx-extras as runner +FROM docker.io/openresty/openresty:1.21.4.1-0-alpine as runner LABEL maintainer="Dominic Grimm " \ org.opencontainers.image.description="Frontend of Mentorenwahl" \ org.opencontainers.image.licenses="GPL-3.0" \ org.opencontainers.image.source="https://git.dergrimm.net/mentorenwahl/mentorenwahl" \ org.opencontainers.image.url="https://git.dergrimm.net/mentorenwahl/mentorenwahl" -COPY ./nginx.conf /etc/nginx/nginx.conf +COPY ./nginx.conf /usr/local/openresty/nginx/conf/nginx.conf COPY --from=binaryen /usr/src/public /var/www/html diff --git a/frontend/nginx.conf b/frontend/nginx.conf index 80007c3..26bd086 100644 --- a/frontend/nginx.conf +++ b/frontend/nginx.conf @@ -3,7 +3,7 @@ events { } http { - include /etc/nginx/mime.types; + include mime.types; default_type application/octet-stream; sendfile on; diff --git a/frontend/src/routes/home/student_vote.rs b/frontend/src/routes/home/student_vote.rs index 2769e6b..7c679c4 100644 --- a/frontend/src/routes/home/student_vote.rs +++ b/frontend/src/routes/home/student_vote.rs @@ -168,7 +168,8 @@ impl Component for StudentVote { ) .await .unwrap(); - log::debug!("{:?}", response.data.unwrap().create_vote.unwrap()); + // log::debug!("{:?}", response.data.unwrap().create_vote.unwrap()); + log::debug!("{:?}", response); Msg::Vote(graphql::convert(response.errors)) });