mentorenwahl/docker/backend/src/backend/api/context.cr

136 lines
3.6 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 "http/request"
require "graphql"
require "granite"
module Backend
module Api
# GraphQL request context class
class Context < GraphQL::Context
# Authenticated user
getter user : Db::User?
# User is admin
getter admin : Bool?
# User's role
getter role : Schema::UserRole?
# User's external object
getter external : (Db::Teacher | Db::Student)?
def initialize(request : HTTP::Request, max_complexity : Int32? = nil)
super(max_complexity)
token = request.headers["Authorization"]?
if token && token[..Auth::BEARER.size - 1] == Auth::BEARER
payload = Auth.decode_jwt?(token[Auth::BEARER.size..])
return unless payload
data = payload["data"].as_h
@user = Db::User.find(data["user_id"].as_i)
return unless @user
if @user
@admin = @user.not_nil!.admin
@role = Schema::UserRole.parse(@user.not_nil!.role).not_nil!
@external =
case @role.not_nil!
when .teacher?
@user.not_nil!.teacher
when .student?
@user.not_nil!.student
end
end
end
end
# User is authenticated
def authenticated? : Bool
!!@user
end
# :ditto:
def authenticated! : Bool
raise "Not authenticated" unless authenticated?
true
end
# User is admin
def admin? : Bool
authenticated? && !!@admin
end
# :ditto:
def admin! : Bool
raise "Invalid permissions" unless admin?
true
end
# User's is one of *roles*
def role?(external = true, *roles : Schema::UserRole) : Bool
return false unless authenticated?
roles.each do |role|
return true if @role == role && if external
role == case @external.not_nil!
when Db::Teacher
Schema::UserRole::Teacher
when Db::Student
Schema::UserRole::Student
end
else
true
end
end
false
end
# :ditto:
def role!(external = true, *roles : Schema::UserRole) : Bool
raise "Invalid permissions" unless role? external, *roles
true
end
# User is teacher
def teacher?(external = false) : Bool
role? external, Schema::UserRole::Teacher
end
# :ditto:
def teacher! : Bool
role! external, Schema::UserRole::Teacher
end
# User is student
def student?(external = false) : Bool
role? external, Schema::UserRole::Student
end
# :ditto:
def student! : Bool
role! external, Schema::UserRole::Student
end
end
end
end