Skip to content

Commit

Permalink
Merge pull request #115 from ssciwr/add-backend-connection-to-user-login
Browse files Browse the repository at this point in the history
Add backend connection to user login
  • Loading branch information
lkeegan authored Oct 17, 2024
2 parents 3b8b826 + 39cc4b2 commit 5e2c9bc
Show file tree
Hide file tree
Showing 11 changed files with 401 additions and 377 deletions.
29 changes: 29 additions & 0 deletions default.cert
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
-----BEGIN CERTIFICATE-----
MIIFCTCCAvGgAwIBAgIUbvD0dvnZOCfstZkE6ByRwYah4VMwDQYJKoZIhvcNAQEL
BQAwFDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTI0MTAxNjA4NDM0OFoXDTI1MTAx
NjA4NDM0OFowFDESMBAGA1UEAwwJbG9jYWxob3N0MIICIjANBgkqhkiG9w0BAQEF
AAOCAg8AMIICCgKCAgEApiFVMNAFtrai9s/xP+kYxsa7NzmPBlJg07MsFlW7JPek
FMAy/4HSSZd8gG3fWz73U3cy4J+Oecdy3O0T708ImVBcYskN/Hi/JCBuTRSJZqH4
SlFFqoqR5E8H1bVDL9l4QQgWqoBzNiAEwBMlPSTAeoL91a02qYIPTNjVx93d+1Ua
eGq3/4HhYxogD6vjJOol32T2Twe7xMJ2j4IIsaQLvprA05HhYpJOxRkeuJQO7TEv
o5VcwxURtKm15z8GN6Fj0/MQ/edvj6l59g4ywtNeqIKyQHq/B9QVsfYQIK3HA9j/
Z5cVEfvMjhMl2x6Bh29npg2DRWiucRJioEwRYsxP5G8DO6f0maP+siY8lZrrioxV
LVbyz4z6skFSoGR0lY59oe4+V4UR8Djww/WxuzmI8UJFT0/2cV1ux8mY/UAePjUo
HOzkUn7E669eabRldcBzWpb0ocmeufPdi+LWGHvZxE4v3iUVsxv+GgH7QAYy2LV3
XW5PwHGEMbOkrb772oe13IEYiXCXKgPheI26u3dw6LUKk9V2w+aGvjfjY7IQMDZy
kZ6r5XdLeyUMYfu2UEs+8e8WTW+DYade35k9Hd2AWYYjoGeUjEoht1KKVA9cTyMg
Mf34u40bR5xb9TRLSZc9ZR3OBIIT3gea0gdNQ59XBwRHzcdW1bgOARFcYGcjWOkC
AwEAAaNTMFEwHQYDVR0OBBYEFJS1zAOTGWa0+TgIne/tFIk2h3dsMB8GA1UdIwQY
MBaAFJS1zAOTGWa0+TgIne/tFIk2h3dsMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZI
hvcNAQELBQADggIBACAc9yR77JcUdFYPqVwwkm/hLPTKzcJCEgUZ/8MuYk8CEDxf
ZPeckksEaKHOCi4R6pUqGRudQ7+jW7z9+1zU4iS3s6TxoydTuIFIWlVWfvlCRtWi
CldfpHJH/fw8c7g0pV5neEMKmA1E2tNz8escjSqIDy8Ow8TUbZQvupId+izIg705
gd5Bjb88WlGsEIEY7myIgU7MvSFwv2hogqUGomjJIv9dArOS3hDcLoFcL5Nb3W7/
CqLgwOUPsLy+/bS8DvYe3Q6knPUmiPYA+jI0XNYmDqadrv00/5sYKEU27dKsu2RZ
GSD+M0cgxrDfO+hthlYVefak0edz0T3WYxVc+PFGmm6CjDd0Y2iCabaAID8RJzEf
GUwZRbrF0sQWWwvwxtMUvxvCY1I8N1gTFYaH6mDPPYPd72Cbu5UBtsOg1SHJ3WuE
rSUWgkjieQIS87kDMgFKcgrUUogkkivJhXy0dBWDQAZtHbG5qUuqypRlmGgST1zI
aRQD+tIR8aY6lsG8GAGXrSXA8YOyDHNwkR+7LpC6eNi96GDbOJdy6aF7qmJ3beRw
vP5MDwsITZp9BM3IofFQVS7MVEuPQ71plM/aqM5Jf0tqZFpzPN3S+udycyzHfPrK
5OBU6MSaClmyrsTjsh0TjCdOVZrX1nNvfg+2WlfzMn9XfQlpd+iXbjuShFuP
-----END CERTIFICATE-----
51 changes: 29 additions & 22 deletions frontend/src/lib/components/UserLandingPage.svelte
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
<script lang="ts">
import { activeTabChildren, activeTabPersonal, componentTable } from '$lib/stores/componentStore';
import { currentUser } from '$lib/stores/userStore';
import { TabItem, Tabs } from 'flowbite-svelte';
import { GridPlusSolid, ProfileCardSolid } from 'flowbite-svelte-icons';
import { get } from 'svelte/store';
import UserVerify from './UserVerify.svelte';
import { activeTabChildren, activeTabPersonal, componentTable } from '$lib/stores/componentStore';
import { onDestroy } from 'svelte';
export let userData: any[];
console.log('user: ', get(currentUser));
const isVerifed = get(currentUser)?.is_verified;
let currentPersonal = 'userDataInput';
let currentChildren = 'childrenGallery';
export let userData: any[];
const unsubscribePersonal = activeTabPersonal.subscribe((value) => {
console.log('personal tab: ', value);
currentPersonal = value;
});
const unsubscribeChildren = activeTabChildren.subscribe((value) => {
console.log('children tab: ', value);
currentChildren = value;
});
Expand All @@ -25,21 +28,25 @@
});
</script>

<div class="m-2 p-2">
<Tabs tabStyle="pill">
<TabItem open={true}>
<div slot="title" class="flex items-center gap-2 text-lg">
<ProfileCardSolid size="lg" />
Persönliche Daten
</div>
<svelte:component this={componentTable[currentPersonal]} data={userData} />
</TabItem>
<TabItem>
<div slot="title" class="flex items-center gap-2 text-lg">
<GridPlusSolid size="lg" />
Kinder
</div>
<svelte:component this={componentTable[currentChildren]} />
</TabItem>
</Tabs>
</div>
{#if isVerifed === true}
<div class="m-2 p-2">
<Tabs tabStyle="pill">
<TabItem open={true}>
<div slot="title" class="flex items-center gap-2 text-lg">
<ProfileCardSolid size="lg" />
Persönliche Daten
</div>
<svelte:component this={componentTable[currentPersonal]} data={userData} />
</TabItem>
<TabItem>
<div slot="title" class="flex items-center gap-2 text-lg">
<GridPlusSolid size="lg" />
Kinder
</div>
<svelte:component this={componentTable[currentChildren]} />
</TabItem>
</Tabs>
</div>
{:else}
<UserVerify />
{/if}
219 changes: 101 additions & 118 deletions frontend/src/lib/components/UserLogin.svelte
Original file line number Diff line number Diff line change
@@ -1,102 +1,95 @@
<script lang="ts">
import { goto } from '$app/navigation';
import { base } from '$app/paths';
import UserLoginUtil from '$lib/components//UserLoginUtil.svelte';
import AlertMessage from '$lib/components/AlertMessage.svelte';
import DataInput from '$lib/components/DataInput/DataInput.svelte';
import NavigationButtons from '$lib/components/Navigation/NavigationButtons.svelte';
import { hash, users, type UserData } from '$lib/stores/userStore';
import { Card, Heading } from 'flowbite-svelte';
import { onDestroy, onMount } from 'svelte';
import { goto } from '$app/navigation';
import { authCookieLogin, usersCurrentUser } from '$lib/client/services.gen';
import { type AuthCookieLoginData, type UserRead } from '$lib/client/types.gen';
import { currentUser } from '$lib/stores/userStore';
import { preventDefault } from '$lib/util';
import { Button, Card, Heading, Input } from 'flowbite-svelte';
import { _ } from 'svelte-i18n';
async function refresh(): Promise<string> {
const returned = await usersCurrentUser();
if (returned.error) {
console.log('Error getting current user: ', returned.error.detail);
currentUser.set(null);
return returned.error.detail;
} else {
console.log('Successfully retrieved active user');
currentUser.set(returned.data as UserRead);
return 'success';
}
}
// functionality
async function submitData(): Promise<void> {
const loginData: AuthCookieLoginData = {
body: {
username: formData[0].value,
password: formData[1].value
}
};
/**
* This currently immitates the behavior of a login system by fetching data from
* the userstore that has been precreated. What fetchWithCredentials does currently will later go into the backend
*/
async function validateCredentials() {
// README: this should not be set here but in the child component. However, indication of something missing should
// not happen immediatelly in the first round of entry, so this code here defers it until the first hit of the login button.
const user = await users.fetchWithCredentials(
data[0].value,
await hash(data[1].value),
data[2].value
);
const authReturn = await authCookieLogin(loginData);
console.log(user);
// forget user data again to not have a plain text password lying around in memory somewhere
// any longer than needed
if (user) {
userID = user.id;
if (authReturn.error) {
showAlert = true;
} else {
const status: string = await refresh();
if (remember) {
localStorage.setItem('currentUser', JSON.stringify(userID));
if (status !== 'success') {
console.log('error during retrieving active users: ', status);
showAlert = true;
alertMessage = $_('login.unauthorized') + ': ' + status;
} else {
localStorage.removeItem('currentUser');
console.log('login and user retrieval successful');
goto('/userLand/userLandingpage');
}
await users.setLoggedIn(userID);
await users.save();
goto(`${base}/userLand/userLandingpage/`);
} else {
showAlert = true;
data = data.map((element) => {
element.value = null;
return element;
});
}
}
// data and variables
export let data: any[];
const buttons = [
// form data and variables
let formData = [
{
component: Input,
value: '',
props: {
label: $_('login.usernameLabel'),
type: 'email',
placeholder: $_('login.usernameLabel'),
required: true,
id: 'username'
}
},
{
label: 'Login',
href: null,
onclick: validateCredentials
component: Input,
value: '',
props: {
label: $_('login.passwordLabel'),
type: 'password',
placeholder: $_('login.passwordLabel'),
required: true,
id: 'password'
}
}
];
let alertMessage = 'Eingaben sind falsch';
let userID: string;
let remember: boolean = false;
let showAlert: boolean = false;
const heading = 'Einloggen';
// check if credentials are stored
onMount(async () => {
// make dummyUser if not already there
users.load();
// check if credentials are saved
const savedUID = JSON.parse(localStorage.getItem('currentUser'));
if (savedUID) {
userID = savedUID;
const user: UserData = (await users.fetch(userID)) as UserData;
data[0].value = user.name;
data[1].value = user.password;
data[2].value = user.role;
remember = true;
}
});
onDestroy(async () => {
await users.save();
});
let alertMessage: string = $_('login.badCredentials');
</script>

{#if showAlert}
<AlertMessage
title={'Fehler'}
title={$_('login.alertMessageTitle')}
message={alertMessage}
lastpage={`${base}/userLand/userLogin`}
onclick={() => {
Expand All @@ -105,53 +98,43 @@
/>
{/if}

{#if users.get()['loggedIn'] && users.get()['loggedIn'] !== null}
<AlertMessage
title={'Fehler'}
message={`Sie sind bereits angemeldet. Melden sie sich zuerst ab um den Account zu wechseln.`}
lastpage={`${base}`}
onclick={() => {
showAlert = false;
}}
/>
{:else}
<div class="container m-1 mx-auto w-full max-w-xl">
<Card class="container m-1 mx-auto mb-6 w-full max-w-xl pb-6">
{#if heading}
<Heading
tag="h3"
class="m-1 mb-3 p-1 text-center font-bold tracking-tight text-gray-700 dark:text-gray-400"
>{heading}</Heading
>
{/if}

<form class="m-1 m-3 mx-auto w-full flex-col space-y-6">
{#each data as element}
<DataInput
component={element.component}
label={element.props.label}
bind:value={element.value}
properties={element.props}
eventHandlers={{
'on:change': element.onchange,
'on:blur': element.onblur,
'on:click': element.onclick
}}
/>
{/each}
</form>
<div class="container m-2 mx-auto w-full max-w-xl">
<Card class="container m-2 mx-auto mb-6 w-full max-w-xl pb-6">
<Heading
tag="h3"
class="m-2 mb-3 p-2 text-center font-bold tracking-tight text-gray-700 dark:text-gray-400"
>{$_('login.heading')}</Heading
>

<UserLoginUtil cls="p-6 mb-3" bind:checked={remember} />
<form onsubmit={preventDefault(submitData)} class="m-2 mx-auto w-full flex-col space-y-6">
{#each formData as element}
<DataInput
component={element.component}
label={element.props.label}
bind:value={element.value}
properties={element.props}
eventHandlers={{
'on:change': element.onchange,
'on:blur': element.onblur,
'on:click': element.onclick
}}
/>
{/each}

<NavigationButtons {buttons} />
</Card>
<UserLoginUtil cls="p-6 mb-3" bind:checked={remember} />

<span class="container mx-auto w-full text-gray-700 dark:text-gray-400">Not registered?</span>
<a
href={`${base}/userLand/userRegistration`}
class="text-primary-700 hover:underline dark:text-primary-500"
>
Create account
</a>
</div>
{/if}
<Button
class="dark:bg-primay-700 w-full bg-primary-700 text-center text-sm text-white hover:bg-primary-800 hover:text-white dark:hover:bg-primary-800"
type="submit">{$_('login.submitButtonLabel')}</Button
>
</form>
</Card>

<span class="container mx-auto w-full text-gray-700 dark:text-gray-400">Not registered?</span>
<a
href={`${base}/userLand/userRegistration`}
class="text-primary-700 hover:underline dark:text-primary-500"
>
Create account
</a>
</div>
Loading

0 comments on commit 5e2c9bc

Please sign in to comment.