User registration completed

This commit is contained in:
2024-09-10 20:28:24 +02:00
parent f6e4bfdf2f
commit fd06b8a9a4
14 changed files with 203 additions and 56 deletions

3
.gitignore vendored
View File

@@ -31,4 +31,5 @@ coverage
# Build and package files/folders # Build and package files/folders
build build
*.sqlite *.sqlite
out/

View File

@@ -4,7 +4,10 @@
"id": 0, "id": 0,
"username": "hagemeister93", "username": "hagemeister93",
"password": "Xjt3qb5t", "password": "Xjt3qb5t",
"address": "Laportestraße 22, 30449 Hannover", "street": "Laportestraße",
"houseNumber": 22,
"postalCode": 30449,
"city": "Hannover",
"firstName": "Laurin", "firstName": "Laurin",
"lastName": "Hagemeister" "lastName": "Hagemeister"
}, },
@@ -12,7 +15,10 @@
"id": 1, "id": 1,
"username": "katjaStoiber", "username": "katjaStoiber",
"password": "target123", "password": "target123",
"address": "Gustav-Adolf-Straße 30, 30167 Hannover", "street": "Gustav-Adolf-Straße",
"houseNumber": 30,
"postalCode": 30167,
"city": "Hannover",
"firstName": "Katja", "firstName": "Katja",
"lastName": "Stoiber" "lastName": "Stoiber"
}, },
@@ -20,7 +26,10 @@
"id": 2, "id": 2,
"username": "oetkerohnek", "username": "oetkerohnek",
"password": "iloveyou", "password": "iloveyou",
"address": "Eckermannstraße 1, 30625 Hannover", "street": "Eckermannstraße",
"houseNumber": 1,
"postalCode": 30625,
"city": "Hannover",
"firstName": "Luna", "firstName": "Luna",
"lastName": "Oeter" "lastName": "Oeter"
}, },
@@ -28,7 +37,10 @@
"id": 3, "id": 3,
"username": "duranduran", "username": "duranduran",
"password": "H4nn0ver", "password": "H4nn0ver",
"address": "Schlägerstraße 36, 30171 Hannover", "street": "Schlägerstraße",
"houseNumber": 36,
"postalCode": 30171,
"city": "Hannover",
"firstName": "Jürgen", "firstName": "Jürgen",
"lastName": "Durand" "lastName": "Durand"
}, },
@@ -36,7 +48,10 @@
"id": 4, "id": 4,
"username": "guitarhero", "username": "guitarhero",
"password": "gwerty123", "password": "gwerty123",
"address": "Steinmetzstraße 12, 30163 Hannover", "street": "Steinmetzstraße",
"houseNumber": 12,
"postalCode": 30163,
"city": "Hannover",
"firstName": "Frederik", "firstName": "Frederik",
"lastName": "Furtwängler" "lastName": "Furtwängler"
}, },
@@ -44,7 +59,10 @@
"id": 5, "id": 5,
"username": "herbstMareike", "username": "herbstMareike",
"password": "qhsrbpgrs", "password": "qhsrbpgrs",
"address": "Allerweg 33, 30851 Langenhagen", "street": "Allerweg",
"houseNumber": 33,
"postalCode": 30851,
"city": "Langenhagen",
"firstName": "Mareike", "firstName": "Mareike",
"lastName": "Herbst" "lastName": "Herbst"
}, },
@@ -52,7 +70,10 @@
"id": 6, "id": 6,
"username": "seibertmitb", "username": "seibertmitb",
"password": "{jkz+WvQe", "password": "{jkz+WvQe",
"address": "Marktstraße 26, 30880 Laatzen", "street": "Marktstraße",
"houseNumber": 26,
"postalCode": 30880,
"city": "Laatzen",
"firstName": "Janna", "firstName": "Janna",
"lastName": "Seibert" "lastName": "Seibert"
} }

View File

@@ -23,7 +23,7 @@ export const sequelize = new Sequelize({
export function startDatabase() { export function startDatabase() {
// Create database and tables // Create database and tables
sequelize.sync({ force: false }) sequelize.sync({ force: true })
.then(() => { .then(() => {
console.log(`Database & tables created!`) console.log(`Database & tables created!`)
}) })

View File

@@ -1,23 +1,33 @@
import { Table, Column, Model, HasMany } from 'sequelize-typescript'; import { Table, Column, Model, HasMany, Unique } from 'sequelize-typescript';
import { Order } from './order.model'; import { Order } from './order.model';
@Table @Table
export class Account extends Model { export class Account extends Model {
@Unique
@Column @Column
username: string username: string
@Column @Column
password: string password: string
@Column
address: string
@Column @Column
firstName: string firstName: string
@Column @Column
lastName: string lastName: string
@Column
street: string
@Column
houseNumber: number
@Column
postalCode: number
@Column
city: string
// Relations // Relations
@HasMany(() => Order) @HasMany(() => Order)
orders: Order[] orders: Order[]

View File

@@ -1,12 +1,36 @@
import { Router, Request, Response, NextFunction } from "express"; import { Router, Request, Response, NextFunction } from "express";
import { Account } from "../models/account.model"; import { Account } from "../models/account.model";
import { validateString } from "../scripts/validateHelper";
export const account = Router() export const account = Router()
account.get("/", (req: Request, res: Response, next: NextFunction)=> { // Request all user from the database
account.get("/", (req: Request, res: Response, next: NextFunction) => {
Account.findAll() Account.findAll()
.then(accounts => { .then(accounts => {
res.json(accounts) res.json(accounts)
}) })
.catch(next) .catch(next)
})
// Creating a new user
account.post("/", (req: Request, res: Response, next: NextFunction) => {
if (!validateString(req.body.username, 4))
{
res.status(400).send({ error: "Username too short!" })
}
else if (!validateString(req.body.password, 8))
{
res.status(400).send({ error: "Password too short!" })
}
else
{
Account.create(req.body)
.then(account => {
res.json(account)
res.status(200).send()
}).catch(reason => {
res.status(400).send({ error: reason })
})
}
}) })

View File

@@ -13,7 +13,6 @@ category.get("/", (req: Request, res: Response, next: NextFunction) => {
category.post("/", (req: Request, res: Response, next: NextFunction) => { category.post("/", (req: Request, res: Response, next: NextFunction) => {
try { try {
console.log(req.body)
const category = Category.create(req.body) const category = Category.create(req.body)
res.status(201).json(category) res.status(201).json(category)
} catch (e) { } catch (e) {

View File

@@ -1,5 +0,0 @@
{
"id": 1,
"title": "Hello World",
"completed": false
}

View File

@@ -0,0 +1,16 @@
/**
* Validates a string for undefined and length
*
* @param string String to prove
* @param length Minimal length of string
*
* @returns True if valid
*/
export function validateString(string: string, length: number = 0) : boolean {
if (string != undefined) {
if (string.length >= length)
return true
}
return false
}

View File

@@ -0,0 +1,13 @@
export class AccountModel {
id: number
username: string = ""
password: string = ""
street: string = ""
houseNumber: number = 0
postalCode: number = 0
city: string = ""
firstName: string = ""
lastName: string = ""
createdAt: string = ""
updatedAt: string = ""
}

View File

@@ -36,7 +36,7 @@
"username": "Username", "username": "Username",
"password": "Password", "password": "Password",
"login": "Login", "login": "Login",
"noAccountRegister": "No Account? Register now!", "noAccountRegister": "Create new Account!",
"register": "Create Account", "register": "Create Account",
"userInfo": { "userInfo": {
"firstName": "First Name", "firstName": "First Name",
@@ -45,5 +45,6 @@
"houseNumber": "House Number", "houseNumber": "House Number",
"postalCode": "Postal Code", "postalCode": "Postal Code",
"city": "City" "city": "City"
} },
"backToLogin": "Back to Login"
} }

View File

@@ -36,7 +36,7 @@
"username": "Username", "username": "Username",
"password": "Passwort", "password": "Passwort",
"login": "Login", "login": "Login",
"noAccountRegister": "Noch keinen Account? Jetzt anmelden!", "noAccountRegister": "Neuen Account erstellen!",
"register": "Account erstellen", "register": "Account erstellen",
"userInfo": { "userInfo": {
"firstName": "Vorname", "firstName": "Vorname",
@@ -45,5 +45,6 @@
"houseNumber": "Hausnummer", "houseNumber": "Hausnummer",
"postalCode": "Postleitzahl", "postalCode": "Postleitzahl",
"city": "Stadt" "city": "Stadt"
} },
"backToLogin": "Zurück zum Login"
} }

View File

@@ -2,18 +2,35 @@
import { ref } from 'vue'; import { ref } from 'vue';
import loginForm from './loginForm.vue'; import loginForm from './loginForm.vue';
import registerForm from './registerForm.vue'; import registerForm from './registerForm.vue';
import BannerModel from '@/data/models/bannerModel';
import alertBanner from '@/components/alertBanner.vue';
const showRegisterDialog = ref(false) const showRegisterCard = ref(false)
const banner = ref(new BannerModel())
</script> </script>
<template> <template>
<v-container max-width="600"> <v-container max-width="800">
<v-row> <v-row>
<v-col> <v-col>
<login-form v-model:show-register-dialog="showRegisterDialog" /> <alert-banner v-model:alert-banner="banner" />
</v-col> </v-col>
</v-row> </v-row>
</v-container>
<register-form v-model:show-register-dialog="showRegisterDialog" /> <v-expand-transition>
<v-row v-if="!showRegisterCard">
<v-col>
<login-form v-model:show-register-card="showRegisterCard" />
</v-col>
</v-row>
</v-expand-transition>
<v-expand-transition>
<v-row v-if="showRegisterCard">
<v-col>
<register-form v-model:banner="banner" v-model:show-register-card="showRegisterCard" />
</v-col>
</v-row>
</v-expand-transition>
</v-container>
</template> </template>

View File

@@ -1,5 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
const showRegisterDialog = defineModel("showRegisterDialog", { type: Boolean, default: false }) const showRegisterCard = defineModel("showRegisterCard", { type: Boolean, default: false })
</script> </script>
<template> <template>
@@ -16,19 +16,15 @@ const showRegisterDialog = defineModel("showRegisterDialog", { type: Boolean, de
<v-text-field :label="$t('password')" prepend-icon="mdi-key" type="password" clearable /> <v-text-field :label="$t('password')" prepend-icon="mdi-key" type="password" clearable />
</v-col> </v-col>
</v-row> </v-row>
<v-row>
<v-col>
<!-- todo -->
<v-btn prepend-icon="mdi-send" color="primary" block>{{ $t('login') }}</v-btn>
</v-col>
</v-row>
</v-container> </v-container>
<v-card-text class="text-center"> <v-card-actions>
<v-btn flat append-icon="mdi-chevron-right" @click="showRegisterDialog = true"> <v-btn variant="outlined" @click="showRegisterCard = true" color="primary" prepend-icon="mdi-plus">
{{ $t('noAccountRegister') }} {{ $t('noAccountRegister') }}
</v-btn> </v-btn>
</v-card-text> <v-spacer />
<v-btn variant="outlined" append-icon="mdi-arrow-right" color="primary">{{ $t('login') }}</v-btn>
</v-card-actions>
</v-card> </v-card>
</template> </template>

View File

@@ -1,54 +1,107 @@
<script setup lang="ts"> <script setup lang="ts">
import actionDialog from '@/components/actionDialog.vue'; import { AccountModel } from '@/data/models/accountModel';
import BannerModel from '@/data/models/bannerModel';
import axios from 'axios';
import { ref } from 'vue';
const showRegisterDialog = defineModel("showRegisterDialog", { type: Boolean, required: true }) const newUser = ref(new AccountModel())
const banner = defineModel("banner", { required: true, type: BannerModel })
const showRegisterCard = defineModel("showRegisterCard", { type: Boolean, default: false })
function registerUser() {
axios.post('http://127.0.0.1:3000/accounts/', newUser.value)
.then(res => {
console.log(res.status)
if (res.status == 200) {
banner.value.message = "Created!"
banner.value.color = "green"
banner.value.icon = "mdi-check"
banner.value.show = true
}
})
.catch((error) => {
if (error.status == 400) {
banner.value.color = "red"
banner.value.icon = "mdi-alert-circle"
banner.value.message = error.response.data.error
banner.value.show = true
}
})
}
</script> </script>
<template> <template>
<action-dialog v-model="showRegisterDialog" :title="$t('register')"> <v-card :title="$t('register')">
<template #content> <v-container>
<v-row> <v-row>
<v-col> <v-col>
<v-text-field :label="$t('username')" prepend-icon="mdi-account" clearable /> <v-text-field
:label="$t('username')"
prepend-icon="mdi-account"
v-model="newUser.username"
clearable
/>
</v-col> </v-col>
<v-col> <v-col>
<v-text-field :label="$t('password')" prepend-icon="mdi-key" type="password" clearable /> <v-text-field
:label="$t('password')"
prepend-icon="mdi-key"
type="password"
v-model="newUser.password"
clearable
/>
</v-col> </v-col>
</v-row> </v-row>
<v-row> <v-row>
<v-col> <v-col>
<v-text-field :label="$t('userInfo.firstName')" prepend-icon="mdi-card-account-details" clearable /> <v-text-field
:label="$t('userInfo.firstName')"
prepend-icon="mdi-card-account-details"
v-model="newUser.firstName"
clearable
/>
</v-col> </v-col>
<v-col> <v-col>
<v-text-field :label="$t('userInfo.lastName')" clearable /> <v-text-field :label="$t('userInfo.lastName')" v-model="newUser.lastName" clearable />
</v-col> </v-col>
</v-row> </v-row>
<v-row> <v-row>
<v-col> <v-col>
<v-text-field :label="$t('userInfo.street')" prepend-icon="mdi-numeric" clearable /> <v-text-field
:label="$t('userInfo.street')"
prepend-icon="mdi-numeric"
v-model="newUser.street"
clearable
/>
</v-col> </v-col>
<v-col cols="4"> <v-col cols="4">
<v-text-field :label="$t('userInfo.houseNumber')" clearable /> <v-text-field :label="$t('userInfo.houseNumber')" v-model="newUser.houseNumber" clearable />
</v-col> </v-col>
</v-row> </v-row>
<v-row> <v-row>
<v-col cols="4"> <v-col cols="4">
<v-text-field :label="$t('userInfo.postalCode')" prepend-icon="mdi-city" clearable /> <v-text-field
:label="$t('userInfo.postalCode')"
prepend-icon="mdi-city"
v-model="newUser.postalCode"
clearable
/>
</v-col> </v-col>
<v-col> <v-col>
<v-text-field :label="$t('userInfo.city')" clearable /> <v-text-field :label="$t('userInfo.city')" v-model="newUser.city" clearable />
</v-col> </v-col>
</v-row> </v-row>
</v-container>
</template>
<template #actions> <template #actions>
<v-btn prepend-icon="mdi-account-plus" color="primary" variant="outlined">{{ $t('register') }}</v-btn> <v-btn prepend-icon="mdi-arrow-left" color="primary" variant="outlined" @click="showRegisterCard = false">{{ $t('backToLogin') }}</v-btn>
<v-spacer />
<v-btn prepend-icon="mdi-account-plus" color="primary" variant="outlined" @click="registerUser">{{ $t('register') }}</v-btn>
</template> </template>
</action-dialog> </v-card>
</template> </template>