Update
continuous-integration/drone/push Build is failing
Details
continuous-integration/drone/push Build is failing
Details
This commit is contained in:
parent
1c164d6ed2
commit
94acd6205d
|
@ -84,6 +84,10 @@ shards:
|
|||
git: https://github.com/graphql-crystal/graphql.git
|
||||
version: 0.4.0+git.commit.e3281bb0ef0ca301ccea176e6839422ac766465b
|
||||
|
||||
graphql-dataloader:
|
||||
git: https://github.com/graphql-crystal/dataloader.git
|
||||
version: 0.1.0+git.commit.6d1dcbcb88922ae29c3c919db4fa44de28bd489d
|
||||
|
||||
habitat:
|
||||
git: https://github.com/luckyframework/habitat.git
|
||||
version: 0.4.7
|
||||
|
|
|
@ -73,3 +73,6 @@ dependencies:
|
|||
github: epoch/tallboy
|
||||
wannabe_bool:
|
||||
github: llamicron/wannabe_bool
|
||||
graphql-dataloader:
|
||||
github: graphql-crystal/dataloader
|
||||
branch: main
|
||||
|
|
|
@ -34,13 +34,14 @@ module Backend
|
|||
getter iat : Int64
|
||||
getter exp : Int64
|
||||
getter jti : UUID
|
||||
getter user_id : Int32
|
||||
|
||||
# getter user_id : Int32
|
||||
|
||||
def initialize(
|
||||
@iat : Int64,
|
||||
@exp : Int64,
|
||||
@jti : UUID,
|
||||
@user_id : Int32
|
||||
@jti : UUID
|
||||
# @user_id : Int32
|
||||
)
|
||||
end
|
||||
|
||||
|
@ -52,8 +53,7 @@ module Backend
|
|||
self.new(
|
||||
iat: token["iat"].as_i64,
|
||||
exp: token["exp"].as_i64,
|
||||
jti: UUID.new(token["jti"].as_s),
|
||||
user_id: token["user_id"].as_i
|
||||
jti: UUID.new(token["jti"].as_s) # user_id: token["user_id"].as_i
|
||||
)
|
||||
end
|
||||
|
||||
|
|
|
@ -42,6 +42,9 @@ module Backend
|
|||
# JTI of request token
|
||||
getter jti
|
||||
|
||||
# Dataloaders
|
||||
getter loaders = Loaders::DataLoaders.new
|
||||
|
||||
def initialize(
|
||||
@status : Status,
|
||||
@user : Db::User?,
|
||||
|
@ -63,13 +66,17 @@ module Backend
|
|||
rescue
|
||||
@status = Status::JWTError
|
||||
else
|
||||
if @user = Db::User.find(payload.user_id)
|
||||
@jti = payload.jti
|
||||
if Db::Token.query.where { (id == payload.jti) & active }.first.nil?
|
||||
@status = Status::SessionExpired
|
||||
else
|
||||
@admin = user.not_nil!.admin
|
||||
@role = user.not_nil!.role.to_api
|
||||
token = Db::Token.query.where { (id == payload.jti) & active }
|
||||
.with_user(&.with_teacher.with_student)
|
||||
.first
|
||||
if token.nil?
|
||||
@status = Status::SessionExpired
|
||||
else
|
||||
@user = token.user
|
||||
if @user
|
||||
@jti = token.id
|
||||
@admin = @user.not_nil!.admin
|
||||
@role = @user.not_nil!.role.to_api
|
||||
@external =
|
||||
case @role.not_nil!
|
||||
when .teacher?
|
||||
|
@ -77,6 +84,8 @@ module Backend
|
|||
when .student?
|
||||
@user.not_nil!.student
|
||||
end
|
||||
else
|
||||
@status = Status::SessionExpired
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
require "graphql-dataloader"
|
||||
|
||||
require "../db.cr"
|
||||
|
||||
require "./loaders/*"
|
||||
|
||||
module Backend::Api::Loaders
|
||||
class DataLoaders
|
||||
getter user = User.new
|
||||
getter user_student = UserStudent.new
|
||||
getter user_teacher = UserTeacher.new
|
||||
|
||||
getter student = Student.new
|
||||
|
||||
getter teacher = Teacher.new
|
||||
|
||||
getter vote = Vote.new
|
||||
|
||||
getter teacher_vote = TeacherVote.new
|
||||
end
|
||||
end
|
|
@ -0,0 +1,8 @@
|
|||
module Backend::Api::Loaders
|
||||
class Student < GraphQL::DataLoader::Loader(Int32, Int32, Backend::Db::Student?)
|
||||
def fetch(batch ids : Array(Int32)) : Array(Db::Student?)
|
||||
students = Db::Student.query.where { id.in?(ids) }.to_a
|
||||
ids.map { |id| students.find { |u| u.id == id } }
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,8 @@
|
|||
module Backend::Api::Loaders
|
||||
class Teacher < GraphQL::DataLoader::Loader(Int32, Int32, Backend::Db::Teacher?)
|
||||
def fetch(batch ids : Array(Int32)) : Array(Db::Teacher?)
|
||||
teachers = Db::Teacher.query.where { id.in?(ids) }.to_a
|
||||
ids.map { |id| teachers.find { |t| t.id == id } }
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,8 @@
|
|||
module Backend::Api::Loaders
|
||||
class TeacherVote < GraphQL::DataLoader::Loader(Int32, Int32, Backend::Db::TeacherVote?)
|
||||
def fetch(batch ids : Array(Int32)) : Array(Db::TeacherVote?)
|
||||
teacher_votes = Db::TeacherVote.query.where { id.in?(ids) }.to_a
|
||||
ids.map { |id| teacher_votes.find { |tv| tv.id == id } }
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,32 @@
|
|||
module Backend::Api::Loaders
|
||||
class User < GraphQL::DataLoader::Loader(Int32, Int32, Backend::Db::User?)
|
||||
def fetch(batch ids : Array(Int32)) : Array(Db::User?)
|
||||
users = Db::User.query.where { id.in?(ids) }.to_a
|
||||
ids.map { |id| users.find { |u| u.id == id } }
|
||||
end
|
||||
end
|
||||
|
||||
class UserStudent < GraphQL::DataLoader::Loader(Backend::Db::User, Int32, Backend::Db::Student?)
|
||||
def key_for(user : Db::User) : Int32
|
||||
user.id
|
||||
end
|
||||
|
||||
def fetch(batch users : Array(Db::User)) : Array(Db::Student?)
|
||||
user_ids = users.map(&.id)
|
||||
students = Db::Student.query.where { user_id.in?(user_ids) }.to_a
|
||||
users.map { |u| students.find { |s| s.user_id == u.id } }
|
||||
end
|
||||
end
|
||||
|
||||
class UserTeacher < GraphQL::DataLoader::Loader(Backend::Db::User, Int32, Backend::Db::Teacher?)
|
||||
def key_for(user : Db::User) : Int32
|
||||
user.id
|
||||
end
|
||||
|
||||
def fetch(batch users : Array(Db::User)) : Array(Db::Teacher?)
|
||||
user_ids = users.map(&.id)
|
||||
teachers = Db::Teacher.query.where { user_id.in?(user_ids) }.to_a
|
||||
users.map { |u| teachers.find { |t| t.user_id == u.id } }
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,8 @@
|
|||
module Backend::Api::Loaders
|
||||
class Vote < GraphQL::DataLoader::Loader(Int32, Int32, Backend::Db::Vote?)
|
||||
def fetch(batch ids : Array(Int32)) : Array(Db::Vote?)
|
||||
votes = Db::Vote.query.where { id.in?(ids) }.to_a
|
||||
ids.map { |id| votes.find { |v| v.id == id } }
|
||||
end
|
||||
end
|
||||
end
|
|
@ -44,8 +44,7 @@ module Backend
|
|||
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!
|
||||
jti: token.id.not_nil! # user_id: user.id.not_nil!
|
||||
).encode
|
||||
)
|
||||
end
|
||||
|
|
|
@ -54,7 +54,7 @@ module Backend
|
|||
def user(context : Context, id : Int32) : User?
|
||||
context.admin!
|
||||
|
||||
User.from_id(id)
|
||||
(user = context.loaders.user.load(id)) && User.new(user)
|
||||
end
|
||||
|
||||
@[GraphQL::Field]
|
||||
|
@ -62,14 +62,14 @@ module Backend
|
|||
def users(context : Context) : Array(User)?
|
||||
context.admin!
|
||||
|
||||
Db::User.query.map { |user| User.new(user) }
|
||||
context.loaders.user.load(Db::User.query.select(:id).map(&.id)).map { |u| User.new(u.not_nil!) }
|
||||
end
|
||||
|
||||
@[GraphQL::Field]
|
||||
def user_by_username(context : Context, username : String) : User?
|
||||
context.admin!
|
||||
|
||||
User.new(Db::User.query.find { var(:username) == username }.not_nil!)
|
||||
(user = context.loaders.user.load(Db::User.query.select(:id).find { var(:username) == username }.not_nil!.id)) && User.new(user)
|
||||
end
|
||||
|
||||
@[GraphQL::Field]
|
||||
|
@ -77,19 +77,22 @@ module Backend
|
|||
def admins(context : Context) : Array(User)?
|
||||
context.admin!
|
||||
|
||||
Db::User.query.where(admin: true).map { |user| User.new(user) }
|
||||
# Db::User.query.where(admin: true).map { |user| User.new(user) }
|
||||
context.loaders.user.load(Db::User.query.select(:id).where(admin: true).map(&.id)).map { |u| User.new(u.not_nil!) }
|
||||
end
|
||||
|
||||
@[GraphQL::Field]
|
||||
# Teacher by ID
|
||||
def teacher(id : Int32) : Teacher
|
||||
Teacher.new(Db::Teacher.find!(id))
|
||||
def teacher(context : Context, id : Int32) : Teacher?
|
||||
# Teacher.new(Db::Teacher.find!(id))
|
||||
(teacher = context.loaders.teacher.load(id)) && Teacher.new(teacher)
|
||||
end
|
||||
|
||||
@[GraphQL::Field]
|
||||
# All teachers
|
||||
def teachers : Array(Teacher)
|
||||
Db::Teacher.query.map { |teacher| Teacher.new(teacher) }
|
||||
def teachers(context : Context) : Array(Teacher)
|
||||
# Db::Teacher.query.map { |teacher| Teacher.new(teacher) }
|
||||
context.loaders.teacher.load(Db::Teacher.query.select(:id).map(&.id)).map { |t| Teacher.new(t.not_nil!) }
|
||||
end
|
||||
|
||||
@[GraphQL::Field]
|
||||
|
@ -97,7 +100,7 @@ module Backend
|
|||
def student(context : Context, id : Int32) : Student?
|
||||
context.admin!
|
||||
|
||||
Student.new(Db::Student.find!(id))
|
||||
(student = context.loaders.student.load(id)) && Student.new(student)
|
||||
end
|
||||
|
||||
@[GraphQL::Field]
|
||||
|
@ -105,7 +108,7 @@ module Backend
|
|||
def students(context : Context) : Array(Student)?
|
||||
context.admin!
|
||||
|
||||
Db::Student.query.map { |student| Student.new(student) }
|
||||
context.loaders.student.load(Db::Student.query.select(:id).map(&.id)).map { |s| Student.new(s.not_nil!) }
|
||||
end
|
||||
|
||||
@[GraphQL::Field]
|
||||
|
@ -113,7 +116,8 @@ module Backend
|
|||
def vote(context : Context, id : Int32) : Vote?
|
||||
context.admin!
|
||||
|
||||
Vote.new(Db::Vote.find!(id))
|
||||
# Vote.new(Db::Vote.find!(id))
|
||||
(vote = context.loaders.vote.load(id)) && Vote.new(vote)
|
||||
end
|
||||
|
||||
@[GraphQL::Field]
|
||||
|
@ -121,7 +125,8 @@ module Backend
|
|||
def votes(context : Context) : Array(Vote)?
|
||||
context.admin!
|
||||
|
||||
Db::Vote.query.map { |vote| Vote.new(vote) }
|
||||
# Db::Vote.query.map { |vote| Vote.new(vote) }
|
||||
context.loaders.vote.load(Db::Vote.query.select(:id).map(&.id)).map { |v| Vote.new(v.not_nil!) }
|
||||
end
|
||||
|
||||
@[GraphQL::Field]
|
||||
|
@ -148,7 +153,8 @@ module Backend
|
|||
def teacher_vote(context : Context, id : Int32) : TeacherVote?
|
||||
context.admin!
|
||||
|
||||
TeacherVote.new(Db::TeacherVote.find!(id))
|
||||
# TeacherVote.new(Db::TeacherVote.find!(id))
|
||||
(tv = context.loaders.teacher_vote.load(id)) && TeacherVote.new(tv)
|
||||
end
|
||||
|
||||
@[GraphQL::Field]
|
||||
|
@ -156,7 +162,8 @@ module Backend
|
|||
def teacher_votes(context : Context) : Array(TeacherVote)?
|
||||
context.admin!
|
||||
|
||||
Db::TeacherVote.query.map { |vote| TeacherVote.new(vote) }
|
||||
# Db::TeacherVote.query.map { |vote| TeacherVote.new(vote) }
|
||||
context.loaders.teacher_vote.load(Db::TeacherVote.query.select(:id).map(&.id)).map { |tv| TeacherVote.new(tv.not_nil!) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -75,7 +75,6 @@ module Backend
|
|||
@[GraphQL::Field]
|
||||
# User's full name
|
||||
def name(formal : Bool = true) : String
|
||||
# ldap.name(formal)
|
||||
if formal
|
||||
"#{@model.last_name}, #{@model.first_name}"
|
||||
else
|
||||
|
@ -113,15 +112,15 @@ module Backend
|
|||
end
|
||||
|
||||
@[GraphQL::Field]
|
||||
# User's external teacher object
|
||||
def teacher : Teacher?
|
||||
@model.teacher.try { |t| Teacher.new(t) }
|
||||
# User's external student object
|
||||
def student(context : Context) : Student?
|
||||
(student = context.loaders.user_student.load(@model)) && Student.new(student)
|
||||
end
|
||||
|
||||
@[GraphQL::Field]
|
||||
# User's external student object
|
||||
def student : Student?
|
||||
@model.student.try { |s| Student.new(s) }
|
||||
# User's external teacher object
|
||||
def teacher(context : Context) : Teacher?
|
||||
(teacher = context.loaders.user_teacher.load(@model)) && Teacher.new(teacher)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -6,14 +6,13 @@
|
|||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Benutzeraccounts | Mentorenwahl</title>
|
||||
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Fira+Code&display=swap" rel="stylesheet">
|
||||
<link rel="preconnect" href="https://fonts.bunny.net">
|
||||
<link href="https://fonts.bunny.net/css?family=jetbrains-mono:400" rel="stylesheet" />
|
||||
|
||||
<style>
|
||||
html,
|
||||
body {
|
||||
font-family: "Fira Code", monospace;
|
||||
font-family: "JetBrains Mono", monospace;
|
||||
}
|
||||
|
||||
.column {
|
||||
|
@ -38,7 +37,7 @@
|
|||
}
|
||||
|
||||
code {
|
||||
font-family: "Fira Code", monospace;
|
||||
font-family: "JetBrains Mono", monospace;
|
||||
background: #f4f4f4;
|
||||
word-wrap: break-word;
|
||||
box-decoration-break: clone;
|
||||
|
|
|
@ -23,7 +23,7 @@ type Query {
|
|||
student(id: Int!): Student
|
||||
students: [Student!]
|
||||
studentsCanVote: Boolean!
|
||||
teacher(id: Int!): Teacher!
|
||||
teacher(id: Int!): Teacher
|
||||
teacherVote(id: Int!): TeacherVote
|
||||
teacherVotes: [TeacherVote!]
|
||||
teachers: [Teacher!]!
|
||||
|
|
|
@ -3,7 +3,6 @@ use yew::prelude::*;
|
|||
use crate::components;
|
||||
|
||||
pub mod assignments;
|
||||
pub mod new_user_modal;
|
||||
pub mod tokens;
|
||||
pub mod users;
|
||||
|
||||
|
|
|
@ -1,74 +0,0 @@
|
|||
use yew::prelude::*;
|
||||
|
||||
pub enum Msg {
|
||||
CloseModal,
|
||||
Save,
|
||||
}
|
||||
|
||||
#[derive(Properties, PartialEq)]
|
||||
pub struct NewUserModalProps {
|
||||
pub close: Callback<()>,
|
||||
pub active: bool,
|
||||
}
|
||||
|
||||
pub struct NewUserModal {
|
||||
username: NodeRef,
|
||||
admin: NodeRef,
|
||||
}
|
||||
|
||||
impl Component for NewUserModal {
|
||||
type Message = Msg;
|
||||
type Properties = NewUserModalProps;
|
||||
|
||||
fn create(_ctx: &Context<Self>) -> Self {
|
||||
Self {
|
||||
username: NodeRef::default(),
|
||||
admin: NodeRef::default(),
|
||||
}
|
||||
}
|
||||
|
||||
fn update(&mut self, ctx: &Context<Self>, msg: Self::Message) -> bool {
|
||||
match msg {
|
||||
Msg::CloseModal => {
|
||||
ctx.props().close.emit(());
|
||||
false
|
||||
}
|
||||
Msg::Save => {
|
||||
log::debug!("self.username = {:?}", self.username);
|
||||
log::debug!("self.admin = {:?}", self.admin);
|
||||
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn view(&self, ctx: &Context<Self>) -> Html {
|
||||
let close = ctx.link().callback(|_| Msg::CloseModal);
|
||||
|
||||
html! {
|
||||
<div class={classes!("modal", if ctx.props().active { Some("is-active") } else { None })}>
|
||||
<div onclick={close.clone()}
|
||||
class={classes!("modal-background")}
|
||||
/>
|
||||
<div class={classes!("modal-card")}>
|
||||
<header class={classes!("modal-card-head")}>
|
||||
<p class={classes!("modal-card-title")}>{ "Neuer Benutzer" }</p>
|
||||
<button onclick={close.clone()} class={classes!("delete")} aria-label="close" />
|
||||
</header>
|
||||
|
||||
<section class={classes!("modal-card-body")}>
|
||||
<form onsubmit={ctx.link().callback(|e: SubmitEvent| { e.prevent_default(); Msg::Save })}>
|
||||
<div class={classes!("field")}>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
<footer class={classes!("modal-card-foot")}>
|
||||
<button onclick={close} class={classes!("button")}>{ "Abbrechen" }</button>
|
||||
<button class={classes!("button", "is-success")}>{ "Speichern" }</button>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,7 +3,6 @@ use yew::prelude::*;
|
|||
|
||||
use crate::components;
|
||||
use crate::graphql;
|
||||
use crate::routes::settings::new_user_modal;
|
||||
|
||||
pub enum Msg {
|
||||
DoneFetching {
|
||||
|
@ -12,8 +11,6 @@ pub enum Msg {
|
|||
teachers: Option<Vec<graphql::queries::users_by_role::teachers::TeachersTeachers>>,
|
||||
},
|
||||
SwitchTab(UsersTab),
|
||||
OpenModal,
|
||||
CloseModal,
|
||||
}
|
||||
|
||||
#[derive(Properties, PartialEq, Eq)]
|
||||
|
@ -34,7 +31,6 @@ pub struct Users {
|
|||
errors: graphql::Errors,
|
||||
students: Option<Vec<graphql::queries::users_by_role::students::StudentsStudents>>,
|
||||
teachers: Option<Vec<graphql::queries::users_by_role::teachers::TeachersTeachers>>,
|
||||
modal_active: bool,
|
||||
}
|
||||
|
||||
impl Component for Users {
|
||||
|
@ -86,7 +82,6 @@ impl Component for Users {
|
|||
errors: None,
|
||||
students: None,
|
||||
teachers: None,
|
||||
modal_active: false,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -112,14 +107,6 @@ impl Component for Users {
|
|||
true
|
||||
}
|
||||
}
|
||||
Msg::OpenModal => {
|
||||
self.modal_active = true;
|
||||
true
|
||||
}
|
||||
Msg::CloseModal => {
|
||||
self.modal_active = false;
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -285,19 +272,6 @@ impl Component for Users {
|
|||
},
|
||||
}
|
||||
}
|
||||
|
||||
<button onclick={ctx.link().callback(|_| Msg::OpenModal)}
|
||||
class={classes!("button", "is-success", "is-fullwidth")}
|
||||
>
|
||||
<span class={classes!("icon")}>
|
||||
<i class={classes!("fas", "fa-user-plus")} />
|
||||
</span>
|
||||
<span>{ "Neuer Benutzer" }</span>
|
||||
</button>
|
||||
|
||||
<new_user_modal::NewUserModal close={ctx.link().callback(|_| Msg::CloseModal)}
|
||||
active={self.modal_active}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<components::graphql_errors::GraphQLErrors errors={self.errors.to_owned()} />
|
||||
|
|
Loading…
Reference in New Issue