236 lines
7.8 KiB
Crystal
236 lines
7.8 KiB
Crystal
# 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 "uuid"
|
|
require "uuid/json"
|
|
|
|
module Backend
|
|
module Api
|
|
module Schema
|
|
@[GraphQL::Object]
|
|
class Mutation < GraphQL::BaseMutation
|
|
@[GraphQL::Field]
|
|
# Logs in as *username* with credential *password*
|
|
def login(username : String, password : String) : LoginPayload?
|
|
raise Errors::Authentication.new if username.empty? || password.empty?
|
|
|
|
user = Db::User.query.find { var(:username) == username.downcase }
|
|
raise Errors::Authentication.new unless user && user.password_hash.verify(password)
|
|
|
|
token = Db::Token.create!(
|
|
id: UUID.random(Random::Secure),
|
|
iat: Time.utc,
|
|
exp: Time.utc + Backend.config.api.jwt_expiration.minutes,
|
|
active: true,
|
|
user_id: user.id
|
|
)
|
|
|
|
LoginPayload.new(
|
|
user: User.new(user),
|
|
token: Auth::Token.new(
|
|
iat: token.iat.to_unix,
|
|
exp: token.exp.to_unix,
|
|
jti: token.id.not_nil! # user_id: user.id.not_nil!
|
|
).encode
|
|
)
|
|
end
|
|
|
|
@[GraphQL::Field]
|
|
# Logs out of account by revoking token
|
|
def logout(context : Context) : Scalars::UUID?
|
|
context.authenticated!
|
|
|
|
jti = context.jti.not_nil!
|
|
|
|
token = Db::Token.find!(jti)
|
|
token.active = false
|
|
token.save!
|
|
|
|
Scalars::UUID.new(jti)
|
|
end
|
|
|
|
@[GraphQL::Field]
|
|
def revoke_token(context : Context, token : Scalars::UUID) : Scalars::UUID
|
|
context.authenticated!
|
|
|
|
Db::Token.query.find!(token.value).delete
|
|
|
|
Scalars::UUID.new(token.value)
|
|
end
|
|
|
|
# @[GraphQL::Field]
|
|
# # Creates user
|
|
# def create_user(context : Context, input : UserCreateInput, check_ldap : Bool = true) : User?
|
|
# context.admin!
|
|
|
|
# raise Errors::LdapUserDoesNotExist.new if check_ldap && begin
|
|
# !Ldap::User.from_username(input.username)
|
|
# rescue LDAP::Client::AuthError
|
|
# true
|
|
# end
|
|
# user = Db::User.create!(username: input.username, role: input.role.to_db, admin: input.admin)
|
|
# if input.role.student?
|
|
# Db::Student.create!(user_id: user.id)
|
|
# end
|
|
# Worker::Jobs::CacheLdapUserJob.new(user.id.not_nil!.to_i).enqueue
|
|
|
|
# User.new(user)
|
|
# end
|
|
|
|
# @[GraphQL::Field]
|
|
# # Deletes user by ID
|
|
# def delete_user(context : Context, id : Int32) : Int32?
|
|
# context.admin!
|
|
|
|
# user = Db::User.find!(id)
|
|
# user.delete
|
|
|
|
# id
|
|
# end
|
|
|
|
@[GraphQL::Field]
|
|
# Starts assignment job of mentors to students
|
|
def start_assignment(context : Context) : Bool?
|
|
context.admin!
|
|
|
|
Worker::Jobs::AssignmentJob.new.enqueue
|
|
|
|
true
|
|
end
|
|
|
|
# @[GraphQL::Field]
|
|
# # Creates teacher
|
|
# def create_teacher(context : Context, input : TeacherCreateInput) : Teacher
|
|
# context.admin!
|
|
|
|
# teacher = Db::Teacher.create!(user_id: input.user_id, max_students: input.max_students)
|
|
# Teacher.new(teacher)
|
|
# end
|
|
|
|
# @[GraphQL::Field]
|
|
# def register_teacher(context : Context, input : TeacherInput) : Teacher?
|
|
# context.teacher!(false)
|
|
# raise Errors::InvalidPermissions.new if context.user.not_nil!.teacher
|
|
|
|
# teacher = Db::Teacher.create!(user_id: context.user.not_nil!.id, max_students: input.max_students)
|
|
# Teacher.new(teacher)
|
|
# end
|
|
|
|
# @[GraphQL::Field]
|
|
# # Deletes teacher by ID
|
|
# def delete_teacher(context : Context, id : Int32) : Int32
|
|
# context.admin!
|
|
|
|
# teacher = Db::Teacher.find!(id)
|
|
# teacher.delete
|
|
|
|
# id
|
|
# end
|
|
|
|
@[GraphQL::Field]
|
|
# Self register as teacher
|
|
def register_teacher(context : Context, input : TeacherInput) : Teacher
|
|
context.teacher! external_check: false
|
|
|
|
Teacher.new(
|
|
Db::Teacher.create!(user_id: context.user.not_nil!.id, max_students: input.max_students)
|
|
)
|
|
end
|
|
|
|
# @[GraphQL::Field]
|
|
# # Creates student
|
|
# def create_student(context : Context, input : StudentCreateInput) : Student
|
|
# context.admin!
|
|
|
|
# user = Db::User.find!(input.user_id)
|
|
# raise "User not a student" unless user.role.to_api.student?
|
|
|
|
# student = Db::Student.create!(user_id: user.id)
|
|
# Student.new(student)
|
|
# end
|
|
|
|
# @[GraphQL::Field]
|
|
# # Deletes student by ID
|
|
# def delete_student(context : Context, id : Int32) : Int32
|
|
# context.admin!
|
|
|
|
# student = Db::Student.find!(id)
|
|
# student.delete
|
|
|
|
# id
|
|
# end
|
|
|
|
# @[GraphQL::Field]
|
|
# # Self register as student
|
|
# def register_student(context : Context) : Student
|
|
# context.student! external_check: false
|
|
|
|
# Student.new(
|
|
# Db::Student.create!(user_id: context.user.not_nil!.id)
|
|
# )
|
|
# end
|
|
|
|
@[GraphQL::Field]
|
|
# Creates vote for authenticated user's student
|
|
def create_vote(context : Context, input : VoteCreateInput) : Vote?
|
|
context.student!
|
|
|
|
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?
|
|
|
|
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)
|
|
|
|
if teacher.nil?
|
|
raise Errors::TeachersNotFound.new
|
|
# elsif teacher.user.skif != context.user.not_nil!.skif
|
|
# if teacher.user.skif
|
|
# raise "Teacher is SKIF, student is not"
|
|
# else
|
|
# raise "Teacher is not SKIF, student is"
|
|
# end
|
|
end
|
|
end
|
|
|
|
student = context.external.not_nil!.as(Db::Student)
|
|
vote = Db::Vote.create!(student_id: student.id)
|
|
Db::TeacherVote.import(input.teacher_ids.map_with_index { |id, i| Db::TeacherVote.new({vote_id: vote.id, teacher_id: id, priority: i}) })
|
|
|
|
context.loaders.vote.prime(vote.id, vote)
|
|
|
|
Vote.new(vote)
|
|
end
|
|
|
|
@[GraphQL::Field]
|
|
# Sets if students are allowed to vote
|
|
def set_voting(context : Context, state : Bool) : Bool?
|
|
context.admin!
|
|
|
|
config = Db::Config.query.where { active }.first!
|
|
config.can_vote = state
|
|
config.save!
|
|
|
|
true
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|