Update frontend dockerfile
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
This commit is contained in:
parent
2b568d37f6
commit
7e1eda596c
|
@ -20,44 +20,52 @@
|
|||
CREATE TYPE user_roles AS ENUM ('student', 'teacher');
|
||||
|
||||
CREATE TABLE users(
|
||||
id SERIAL PRIMARY KEY,
|
||||
username TEXT UNIQUE NOT NULL,
|
||||
id serial PRIMARY KEY,
|
||||
username text UNIQUE NOT NULL,
|
||||
role user_roles NOT NULL,
|
||||
admin BOOLEAN NOT NULL,
|
||||
jti uuid UNIQUE
|
||||
admin boolean NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE tokens(
|
||||
id uuid PRIMARY KEY,
|
||||
iat timestamp NOT NULL,
|
||||
exp timestamp NOT NULL,
|
||||
user_id int NOT NULL REFERENCES users(id)
|
||||
);
|
||||
|
||||
CREATE TABLE teachers(
|
||||
id SERIAL PRIMARY KEY,
|
||||
user_id INT NOT NULL UNIQUE REFERENCES users(id),
|
||||
max_students INT NOT NULL
|
||||
id serial PRIMARY KEY,
|
||||
user_id int NOT NULL UNIQUE REFERENCES users(id),
|
||||
max_students int NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE students(
|
||||
id SERIAL PRIMARY KEY,
|
||||
user_id INT NOT NULL UNIQUE REFERENCES users(id)
|
||||
id serial PRIMARY KEY,
|
||||
user_id int NOT NULL UNIQUE REFERENCES users(id)
|
||||
);
|
||||
|
||||
CREATE TABLE votes(
|
||||
id SERIAL PRIMARY KEY,
|
||||
student_id INT NOT NULL UNIQUE REFERENCES students(id)
|
||||
id serial PRIMARY KEY,
|
||||
student_id int NOT NULL UNIQUE REFERENCES students(id)
|
||||
);
|
||||
|
||||
CREATE TABLE teacher_votes(
|
||||
id SERIAL PRIMARY KEY,
|
||||
vote_id INT NOT NULL REFERENCES votes(id),
|
||||
teacher_id INT NOT NULL REFERENCES teachers(id),
|
||||
priority INT NOT NULL
|
||||
id serial PRIMARY KEY,
|
||||
vote_id int NOT NULL REFERENCES votes(id),
|
||||
teacher_id int NOT NULL REFERENCES teachers(id),
|
||||
priority int NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE assignments(
|
||||
id SERIAL PRIMARY KEY,
|
||||
student_id INT NOT NULL REFERENCES students(id),
|
||||
teacher_id INT NOT NULL REFERENCES teachers(id)
|
||||
id serial PRIMARY KEY,
|
||||
student_id int NOT NULL REFERENCES students(id),
|
||||
teacher_id int NOT NULL REFERENCES teachers(id)
|
||||
);
|
||||
|
||||
-- +micrate Down
|
||||
-- SQL section ' Down ' is executed when this migration is rolled back
|
||||
DROP TABLE assignments;
|
||||
|
||||
DROP TABLE teacher_votes;
|
||||
|
||||
DROP TABLE votes;
|
||||
|
@ -68,6 +76,8 @@ DROP TABLE teachers;
|
|||
|
||||
DROP TABLE students;
|
||||
|
||||
DROP TABLE tokens;
|
||||
|
||||
DROP TABLE users;
|
||||
|
||||
DROP TYPE user_roles;
|
|
@ -31,16 +31,12 @@ module Backend
|
|||
struct Token
|
||||
include JSON::Serializable
|
||||
|
||||
getter iss : String
|
||||
getter vrs : String
|
||||
getter iat : Int64
|
||||
getter exp : Int64
|
||||
getter jti : UUID
|
||||
getter context : Context
|
||||
|
||||
def initialize(
|
||||
@iss : String,
|
||||
@vrs : String,
|
||||
@iat : Int64,
|
||||
@exp : Int64,
|
||||
@jti : UUID,
|
||||
|
@ -54,8 +50,6 @@ module Backend
|
|||
|
||||
def self.from_hash(token : Hash(String, JSON::Any)) : self
|
||||
self.new(
|
||||
iss: token["iss"].as_s,
|
||||
vrs: token["vrs"].as_s,
|
||||
iat: token["iat"].as_i64,
|
||||
exp: token["exp"].as_i64,
|
||||
jti: UUID.new(token["jti"].as_s),
|
||||
|
|
|
@ -62,10 +62,7 @@ module Backend
|
|||
rescue
|
||||
@status = Status::JWTError
|
||||
else
|
||||
pp! payload
|
||||
if payload.iss != "Mentorenwahl" || payload.vrs != Backend::VERSION
|
||||
@status = Status::JWTError
|
||||
elsif @user = Db::User.find(payload.context.user)
|
||||
if @user = Db::User.find(payload.context.user)
|
||||
@admin = user.not_nil!.admin
|
||||
@role = user.not_nil!.role.to_api
|
||||
@external =
|
||||
|
|
|
@ -32,15 +32,20 @@ module Backend
|
|||
user = Db::User.query.find { var(:username) == username }
|
||||
raise Errors::Authentication.new unless user && Ldap.authenticate?(Ldap::DN.uid(username), password)
|
||||
|
||||
jti = UUID.random(Random::Secure)
|
||||
token = Db::Token.create!(
|
||||
id: UUID.random(Random::Secure),
|
||||
iat: Time.utc,
|
||||
exp: Time.utc + Backend.config.api.jwt_expiration.minutes,
|
||||
user_id: user.id
|
||||
)
|
||||
pp! token, typeof(token.id)
|
||||
|
||||
LoginPayload.new(
|
||||
user: User.new(user),
|
||||
token: Auth::Token.new(
|
||||
iss: "Mentorenwahl",
|
||||
vrs: Backend::VERSION,
|
||||
iat: Time.utc.to_unix,
|
||||
exp: (Time.utc + Backend.config.api.jwt_expiration.minutes).to_unix,
|
||||
jti: jti,
|
||||
iat: token.iat.to_unix,
|
||||
exp: token.exp.to_unix,
|
||||
jti: token.id.not_nil!,
|
||||
context: Auth::Context.new(user.id.not_nil!)
|
||||
).encode
|
||||
)
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
module Backend::Db
|
||||
class Token
|
||||
include Clear::Model
|
||||
self.table = :tokens
|
||||
|
||||
primary_key type: :uuid
|
||||
|
||||
column iat : Time
|
||||
column exp : Time
|
||||
|
||||
belongs_to user : User
|
||||
end
|
||||
end
|
|
@ -30,10 +30,11 @@ module Backend
|
|||
column username : String
|
||||
column role : UserRole
|
||||
column admin : Bool = false
|
||||
column jti : UUID?
|
||||
|
||||
has_one student : Student?, foreign_key: :user_id
|
||||
has_one teacher : Teacher?, foreign_key: :user_id
|
||||
|
||||
has_many tokens : Token, foreign_key: :user_id
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -26,8 +26,9 @@ WORKDIR /usr/src/public
|
|||
COPY --from=builder /usr/src/frontend/dist .
|
||||
RUN minify . -r -o .
|
||||
|
||||
FROM alpine as binaryen
|
||||
RUN apk add --no-cache binaryen
|
||||
# FROM alpine as binaryen
|
||||
# RUN apk add --no-cache binaryen
|
||||
FROM niklasei/wasm-opt-action:v2.1.0 as binaryen
|
||||
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
|
||||
|
|
|
@ -24,6 +24,9 @@ pub enum Msg {
|
|||
},
|
||||
Submit,
|
||||
Vote(Option<Vec<String>>),
|
||||
AddSlot,
|
||||
RemoveSlot,
|
||||
Reset,
|
||||
}
|
||||
|
||||
#[derive(Properties, PartialEq)]
|
||||
|
@ -37,7 +40,8 @@ pub struct StudentVote {
|
|||
can_vote: bool,
|
||||
errors: Option<Vec<String>>,
|
||||
min: usize,
|
||||
teachers: Option<Vec<graphql::queries::teachers::teachers::TeachersTeachers>>,
|
||||
slots: usize,
|
||||
teachers: Vec<graphql::queries::teachers::teachers::TeachersTeachers>,
|
||||
votes: HashMap<usize, Option<i64>>,
|
||||
}
|
||||
|
||||
|
@ -68,7 +72,8 @@ impl Component for StudentVote {
|
|||
can_vote: false,
|
||||
errors: None,
|
||||
min: 0,
|
||||
teachers: None,
|
||||
slots: 0,
|
||||
teachers: vec![],
|
||||
votes: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
@ -109,6 +114,7 @@ impl Component for StudentVote {
|
|||
Msg::DoneFetchingConfig { errors, min } => {
|
||||
self.errors = errors;
|
||||
self.min = min;
|
||||
self.slots = self.min;
|
||||
|
||||
let client = graphql::client(Some(&ctx.props().token)).unwrap();
|
||||
ctx.link().send_future(async move {
|
||||
|
@ -131,7 +137,7 @@ impl Component for StudentVote {
|
|||
Msg::DoneFetchingTeachers { errors, teachers } => {
|
||||
self.fetching = false;
|
||||
self.errors = errors;
|
||||
self.teachers = Some(teachers);
|
||||
self.teachers = teachers;
|
||||
true
|
||||
}
|
||||
Msg::RadioSelect { priority, teacher } => {
|
||||
|
@ -178,6 +184,27 @@ impl Component for StudentVote {
|
|||
true
|
||||
}
|
||||
}
|
||||
Msg::AddSlot => {
|
||||
if self.slots < self.teachers.len() {
|
||||
self.slots += 1;
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
Msg::RemoveSlot => {
|
||||
if self.slots > self.min {
|
||||
self.votes.remove(&(self.slots - 1));
|
||||
self.slots -= 1;
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
Msg::Reset => {
|
||||
self.slots = self.min;
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -202,7 +229,7 @@ impl Component for StudentVote {
|
|||
<>
|
||||
<h3>{ "Wähle deine Wunschmentoren aus:" }</h3>
|
||||
<form {onsubmit}>
|
||||
{ for (0..self.min).map(|i| {
|
||||
{ for (0..self.slots).map(|i| {
|
||||
let curr_t = self.votes.get(&i);
|
||||
if let Some(te) = curr_t {
|
||||
if let Some(t) = te {
|
||||
|
@ -216,7 +243,7 @@ impl Component for StudentVote {
|
|||
<fieldset>
|
||||
<legend>{ format!("{}. Wahl", i + 1) }</legend>
|
||||
|
||||
{ for self.teachers.as_ref().unwrap().iter().enumerate().filter_map(|(j, t)| {
|
||||
{ for self.teachers.iter().enumerate().filter_map(|(j, t)| {
|
||||
let checked = curr_t == Some(&Some(t.id));
|
||||
|
||||
if teachers.contains(&t.id) && !checked {
|
||||
|
@ -243,16 +270,35 @@ impl Component for StudentVote {
|
|||
}
|
||||
}) }
|
||||
</fieldset>
|
||||
if i < self.min - 1 {
|
||||
if i < self.slots - 1 {
|
||||
<br />
|
||||
}
|
||||
</>
|
||||
}
|
||||
}) }
|
||||
|
||||
<div>
|
||||
<button
|
||||
onclick={ctx.link().callback(|e: MouseEvent| {
|
||||
e.prevent_default();
|
||||
Msg::AddSlot
|
||||
})}
|
||||
>
|
||||
{ "+" }
|
||||
</button>
|
||||
<button
|
||||
onclick={ctx.link().callback(|e: MouseEvent| {
|
||||
e.prevent_default();
|
||||
Msg::RemoveSlot
|
||||
})}
|
||||
>
|
||||
{ "-" }
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<input type="submit" value="Submit" />
|
||||
<input type="reset" value="Reset" />
|
||||
<input type="reset" value="Reset" onclick={ctx.link().callback(|_| Msg::Reset)} />
|
||||
</div>
|
||||
|
||||
<components::graphql_errors::GraphQLErrors errors={self.errors.clone()} />
|
||||
|
|
Loading…
Reference in New Issue