This commit is contained in:
Dominic Grimm 2023-02-25 14:38:14 +01:00
parent ece7e8e87b
commit a9fcab7add
No known key found for this signature in database
GPG Key ID: 6F294212DEAAC530
20 changed files with 53 additions and 619 deletions

View File

@ -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

View File

@ -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 <dominic@dergrimm.net>" \
@ -80,7 +73,6 @@ LABEL maintainer="Dominic Grimm <dominic@dergrimm.net>" \
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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -14,7 +14,6 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
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

View File

@ -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

View File

@ -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

View File

@ -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 <https://www.gnu.org/licenses/>.
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

View File

@ -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 <https://www.gnu.org/licenses/>.
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

View File

@ -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 <https://www.gnu.org/licenses/>.
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

View File

@ -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 <https://www.gnu.org/licenses/>.
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

View File

@ -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 <https://www.gnu.org/licenses/>.
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

View File

@ -154,6 +154,8 @@
</tr>
</table>
</td>
<%- else -%>
<td class="border-padded" />
<%- end -%>
<%- end -%>
</tr>

View File

@ -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/;

View File

@ -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

View File

@ -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 <dominic@dergrimm.net>" \
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

View File

@ -3,7 +3,7 @@ events {
}
http {
include /etc/nginx/mime.types;
include mime.types;
default_type application/octet-stream;
sendfile on;

View File

@ -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))
});