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
|
module Api
|
||||||
# GraphQL request context class
|
# GraphQL request context class
|
||||||
class Context < GraphQL::Context
|
class Context < GraphQL::Context
|
||||||
# Request object
|
|
||||||
getter request
|
|
||||||
|
|
||||||
# Development mode
|
# Development mode
|
||||||
getter development : Bool
|
getter development : Bool
|
||||||
|
|
||||||
|
@ -39,10 +36,10 @@ module Backend
|
||||||
# User's external object
|
# User's external object
|
||||||
getter external : (Db::Teacher | Db::Student)?
|
getter external : (Db::Teacher | Db::Student)?
|
||||||
|
|
||||||
def initialize(@request : HTTP::Request, @development : Bool, *rest)
|
def initialize(request : HTTP::Request, @development : Bool, *rest)
|
||||||
super(*rest)
|
super(*rest)
|
||||||
|
|
||||||
token = @request.headers["Authorization"]?
|
token = request.headers["Authorization"]?
|
||||||
if token && token[..Auth::BEARER.size - 1] == Auth::BEARER
|
if token && token[..Auth::BEARER.size - 1] == Auth::BEARER
|
||||||
payload = Auth.decode_jwt?(token[Auth::BEARER.size..])
|
payload = Auth.decode_jwt?(token[Auth::BEARER.size..])
|
||||||
return unless payload
|
return unless payload
|
||||||
|
|
|
@ -127,6 +127,16 @@ module Backend
|
||||||
id
|
id
|
||||||
end
|
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]
|
@[GraphQL::Field]
|
||||||
# Creates vote for authenticated user's student
|
# Creates vote for authenticated user's student
|
||||||
def create_vote(context : Context, input : VoteCreateInput) : Vote
|
def create_vote(context : Context, input : VoteCreateInput) : Vote
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { initClient } from "@urql/svelte";
|
import { initClient } from "@urql/svelte";
|
||||||
|
import { removeCookie } from "typescript-cookie";
|
||||||
|
|
||||||
import { session } from "$app/stores";
|
import { session } from "$app/stores";
|
||||||
|
import { goto } from "$app/navigation";
|
||||||
|
import * as cookieNames from "$lib/cookieNames";
|
||||||
|
|
||||||
initClient({
|
initClient({
|
||||||
url: "/graphql",
|
url: "/graphql",
|
||||||
|
@ -17,8 +20,28 @@
|
||||||
return {};
|
return {};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function logout(): void {
|
||||||
|
$session.user.token = undefined;
|
||||||
|
removeCookie(cookieNames.TOKEN);
|
||||||
|
goto("/login");
|
||||||
|
}
|
||||||
</script>
|
</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>
|
<main>
|
||||||
<slot />
|
<slot />
|
||||||
</main>
|
</main>
|
||||||
|
|
|
@ -16,9 +16,11 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script lang="ts">
|
<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";
|
import { UserRole } from "$lib/graphql";
|
||||||
|
|
||||||
interface Data {
|
interface Data {
|
||||||
|
@ -44,6 +46,82 @@
|
||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
query(meStore);
|
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>
|
</script>
|
||||||
|
|
||||||
{#if $meStore.error}
|
{#if $meStore.error}
|
||||||
|
@ -56,11 +134,64 @@
|
||||||
|
|
||||||
{#if $meStore.data.me.role === UserRole.TEACHER}
|
{#if $meStore.data.me.role === UserRole.TEACHER}
|
||||||
{#if !$meStore.data.me.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}
|
{/if}
|
||||||
{:else if $meStore.data.me.role === UserRole.STUDENT}
|
{:else if $meStore.data.me.role === UserRole.STUDENT}
|
||||||
{#if !$meStore.data.me.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}
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
`);
|
`);
|
||||||
const login = mutation(loginStore);
|
const login = mutation(loginStore);
|
||||||
|
|
||||||
async function submit(event: Event): Promise<void> {
|
async function submit(): Promise<void> {
|
||||||
await login({
|
await login({
|
||||||
username: $username.value as string,
|
username: $username.value as string,
|
||||||
password: $password.value as string,
|
password: $password.value as string,
|
||||||
|
@ -58,7 +58,7 @@
|
||||||
<br />
|
<br />
|
||||||
<input type="text" id="username" bind:value={$username.value} />
|
<input type="text" id="username" bind:value={$username.value} />
|
||||||
<br />
|
<br />
|
||||||
<label for="password">Password</label>
|
<label for="password">Kennwort:</label>
|
||||||
<br />
|
<br />
|
||||||
<input type="password" id="password" bind:value={$password.value} />
|
<input type="password" id="password" bind:value={$password.value} />
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue