Merge pull request 'Self registration' (#60) from self-registration into main
Reviewed-on: mentorenwahl/mentorenwahl#60
This commit is contained in:
commit
12c4fd4e49
5 changed files with 173 additions and 12 deletions
|
@ -21,9 +21,6 @@ module Backend
|
|||
module Api
|
||||
# GraphQL request context class
|
||||
class Context < GraphQL::Context
|
||||
# Request object
|
||||
getter request
|
||||
|
||||
# Development mode
|
||||
getter development : Bool
|
||||
|
||||
|
@ -39,10 +36,10 @@ module Backend
|
|||
# User's external object
|
||||
getter external : (Db::Teacher | Db::Student)?
|
||||
|
||||
def initialize(@request : HTTP::Request, @development : Bool, *rest)
|
||||
def initialize(request : HTTP::Request, @development : Bool, *rest)
|
||||
super(*rest)
|
||||
|
||||
token = @request.headers["Authorization"]?
|
||||
token = request.headers["Authorization"]?
|
||||
if token && token[..Auth::BEARER.size - 1] == Auth::BEARER
|
||||
payload = Auth.decode_jwt?(token[Auth::BEARER.size..])
|
||||
return unless payload
|
||||
|
|
|
@ -127,6 +127,16 @@ module Backend
|
|||
id
|
||||
end
|
||||
|
||||
@[GraphQL::Field]
|
||||
# Self register as student
|
||||
def register_student(context : Context, input : StudentInput) : Student
|
||||
context.student! external_check: false
|
||||
|
||||
Student.new(
|
||||
Db::Student.create!(user_id: context.user.not_nil!.id, skif: input.skif)
|
||||
)
|
||||
end
|
||||
|
||||
@[GraphQL::Field]
|
||||
# Creates vote for authenticated user's student
|
||||
def create_vote(context : Context, input : VoteCreateInput) : Vote
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
<script lang="ts">
|
||||
import { initClient } from "@urql/svelte";
|
||||
import { removeCookie } from "typescript-cookie";
|
||||
|
||||
import { session } from "$app/stores";
|
||||
import { goto } from "$app/navigation";
|
||||
import * as cookieNames from "$lib/cookieNames";
|
||||
|
||||
initClient({
|
||||
url: "/graphql",
|
||||
|
@ -17,8 +20,28 @@
|
|||
return {};
|
||||
},
|
||||
});
|
||||
|
||||
function logout(): void {
|
||||
$session.user.token = undefined;
|
||||
removeCookie(cookieNames.TOKEN);
|
||||
goto("/login");
|
||||
}
|
||||
</script>
|
||||
|
||||
<nav>
|
||||
<ul>
|
||||
<li>
|
||||
{#if $session.user.token}
|
||||
<button on:click={logout}>Logout</button>
|
||||
{:else}
|
||||
<button><a href="/login">Login</a></button>
|
||||
{/if}
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<hr />
|
||||
|
||||
<main>
|
||||
<slot />
|
||||
</main>
|
||||
|
|
|
@ -16,9 +16,11 @@
|
|||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import { operationStore, query, gql } from "@urql/svelte";
|
||||
import { operationStore, query, gql, mutation } from "@urql/svelte";
|
||||
import * as svelteForms from "svelte-forms";
|
||||
import * as validators from "svelte-forms/validators";
|
||||
|
||||
import type { User } from "$lib/graphql";
|
||||
import type { User, Teacher, Student } from "$lib/graphql";
|
||||
import { UserRole } from "$lib/graphql";
|
||||
|
||||
interface Data {
|
||||
|
@ -44,6 +46,82 @@
|
|||
}
|
||||
`);
|
||||
query(meStore);
|
||||
|
||||
const teacherRegisterFormMaxStudents = svelteForms.field("maxStudents", 0, [
|
||||
validators.required(),
|
||||
validators.min(0),
|
||||
]);
|
||||
const teacherRegisterFormSkif = svelteForms.field("skif", false);
|
||||
const teacheRegisterForm = svelteForms.form(
|
||||
teacherRegisterFormMaxStudents,
|
||||
teacherRegisterFormSkif
|
||||
);
|
||||
|
||||
interface RegisterTeacherData {
|
||||
registerTeacher: Teacher;
|
||||
}
|
||||
|
||||
interface RegisterTeacherVars {
|
||||
maxStudents: number;
|
||||
skif: boolean;
|
||||
}
|
||||
|
||||
const registerTeacherStore = operationStore<
|
||||
RegisterTeacherData,
|
||||
RegisterTeacherVars
|
||||
>(gql`
|
||||
mutation RegisterTeacher($maxStudents: Int!, $skif: Boolean!) {
|
||||
registerTeacher(input: { maxStudents: $maxStudents, skif: $skif }) {
|
||||
id
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
||||
const registerTeacherMutation = mutation(registerTeacherStore);
|
||||
|
||||
async function registerTeacher(): Promise<void> {
|
||||
await registerTeacherMutation({
|
||||
maxStudents: $teacherRegisterFormMaxStudents.value,
|
||||
skif: $teacherRegisterFormSkif.value,
|
||||
});
|
||||
|
||||
if (!$registerTeacherStore.error && $registerTeacherStore.data) {
|
||||
location.reload();
|
||||
}
|
||||
}
|
||||
|
||||
const registerStudentSkif = svelteForms.field("skif", false);
|
||||
const registerStudentForm = svelteForms.form(registerStudentSkif);
|
||||
|
||||
interface RegisterStudentData {
|
||||
registerStudent: Student;
|
||||
}
|
||||
|
||||
interface RegisterStudentVars {
|
||||
skif: boolean;
|
||||
}
|
||||
|
||||
const registerStudentStore = operationStore<
|
||||
RegisterStudentData,
|
||||
RegisterStudentVars
|
||||
>(gql`
|
||||
mutation RegisterStudent($skif: Boolean!) {
|
||||
registerStudent(input: { skif: $skif }) {
|
||||
id
|
||||
}
|
||||
}
|
||||
`);
|
||||
const registerStudentMutation = mutation(registerStudentStore);
|
||||
|
||||
async function registerStudent(): Promise<void> {
|
||||
await registerStudentMutation({
|
||||
skif: $registerStudentSkif.value,
|
||||
});
|
||||
|
||||
if (!$registerStudentStore.error && $registerStudentStore.data) {
|
||||
location.reload();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if $meStore.error}
|
||||
|
@ -56,11 +134,64 @@
|
|||
|
||||
{#if $meStore.data.me.role === UserRole.TEACHER}
|
||||
{#if !$meStore.data.me.teacher}
|
||||
<p>Registriere dich jetzt als Lehrer!</p>
|
||||
<p>Registriere dich jetzt als Lehrer:</p>
|
||||
<form on:submit|preventDefault={registerTeacher}>
|
||||
<label for="maxStudents">Maximale Schüler:</label>
|
||||
<br />
|
||||
<input
|
||||
type="number"
|
||||
name="maxStudents"
|
||||
min="0"
|
||||
bind:value={$teacherRegisterFormMaxStudents.value}
|
||||
/>
|
||||
<br />
|
||||
<label for="skif">SKIF:</label>
|
||||
<br />
|
||||
<input
|
||||
type="checkbox"
|
||||
name="skif"
|
||||
bind:checked={$teacherRegisterFormSkif.value}
|
||||
/>
|
||||
|
||||
<br /><br />
|
||||
|
||||
<button type="submit" disabled={!$teacheRegisterForm.valid}
|
||||
>Registrieren</button
|
||||
>
|
||||
</form>
|
||||
{#if $registerTeacherStore.error}
|
||||
<p style="color: red;">{$registerTeacherStore.error.message}</p>
|
||||
{:else if $registerTeacherStore.fetching}
|
||||
<p>Laden...</p>
|
||||
{:else if $registerTeacherStore.data}
|
||||
<p>Registrierung erfolgreich!</p>
|
||||
{/if}
|
||||
{/if}
|
||||
{:else if $meStore.data.me.role === UserRole.STUDENT}
|
||||
{#if !$meStore.data.me.student}
|
||||
<p>Registriere dich jetzt als Schüler!</p>
|
||||
<p>Registriere dich jetzt als Schüler:</p>
|
||||
<form on:submit|preventDefault={registerStudent}>
|
||||
<label for="skif">SKIF:</label>
|
||||
<br />
|
||||
<input
|
||||
type="checkbox"
|
||||
name="skif"
|
||||
bind:checked={$registerStudentSkif.value}
|
||||
/>
|
||||
|
||||
<br /><br />
|
||||
|
||||
<button type="submit" disabled={!$registerStudentForm.valid}
|
||||
>Registrieren</button
|
||||
>
|
||||
</form>
|
||||
{#if $registerStudentStore.error}
|
||||
<p style="color: red;">{$registerStudentStore.error.message}</p>
|
||||
{:else if $registerStudentStore.fetching}
|
||||
<p>Laden...</p>
|
||||
{:else if $registerStudentStore.data}
|
||||
<p>Registrierung erfolgreich!</p>
|
||||
{/if}
|
||||
{/if}
|
||||
{/if}
|
||||
{/if}
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
`);
|
||||
const login = mutation(loginStore);
|
||||
|
||||
async function submit(event: Event): Promise<void> {
|
||||
async function submit(): Promise<void> {
|
||||
await login({
|
||||
username: $username.value as string,
|
||||
password: $password.value as string,
|
||||
|
@ -58,7 +58,7 @@
|
|||
<br />
|
||||
<input type="text" id="username" bind:value={$username.value} />
|
||||
<br />
|
||||
<label for="password">Password</label>
|
||||
<label for="password">Kennwort:</label>
|
||||
<br />
|
||||
<input type="password" id="password" bind:value={$password.value} />
|
||||
|
||||
|
|
Loading…
Reference in a new issue