Skip to content

Commit

Permalink
Merge pull request #4 from B-urb/development
Browse files Browse the repository at this point in the history
Development
  • Loading branch information
B-urb authored Sep 27, 2023
2 parents 99a40db + 1c58cee commit 9005eee
Show file tree
Hide file tree
Showing 10 changed files with 70 additions and 23 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ This tool is designed to work as a point tracker for the card game doppelkopf.
## Tech Stack

- Kotlin/Ktor
- Svelte
- React
- SurrealDB
- Kubernetes
- Pulumi
Expand Down
6 changes: 5 additions & 1 deletion frontend/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import './App.css'
import {Header} from "semantic-ui-react";
import {Button, Header} from "semantic-ui-react";
import {Outlet, Route, Routes} from "react-router-dom";
import Groups from "./Groups";
import GroupDetail from "./GroupDetail";
Expand All @@ -8,12 +8,15 @@ import GameCreate from "./GameCreate";
import Login from "./Login";
import Register from "./Register";
import EntryPage from "./EntryPage";
import NotFound from "./NotFound.tsx";
import instance from "./constants.ts";

function App() {

return (
<>
<Header as={"h1"}>Cardmaster</Header>
<Button onClick={() => instance.get("/logout")}>Logout</Button>
<Routes>
<Route path={"/"} element={<EntryPage/>}/>
<Route path="login" element={<Login/>}/>
Expand All @@ -22,6 +25,7 @@ function App() {
<Route path="group/:groupId" element={<GroupDetail/>}/>
<Route path="group/:groupId/session/:sessionId" element={<SessionDetail/>}/>
<Route path="group/:groupId/session/:sessionId/game/:gameId" element={<GameCreate/>}/>
<Route path="*" element={<NotFound/>}/>

</Routes>
<Outlet/>
Expand Down
11 changes: 7 additions & 4 deletions frontend/src/Login.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import {Button, Form, Segment} from "semantic-ui-react";
import {Button, Form, Message, Segment} from "semantic-ui-react";
import {useNavigate} from "react-router-dom";
import React, {useEffect, useState} from "react";
import {checkLogin, login} from "./api/api";
import {HttpStatusCode} from "axios";
import {AxiosError, HttpStatusCode} from "axios";


const Login = () => {
Expand All @@ -12,6 +12,7 @@ const Login = () => {
checkLogin().then(code => code === HttpStatusCode.Ok ? navigate("/group") : void (0))
}, []);

const [error, setError] = useState("")

const [formData, setFormData] = useState({
username: '',
Expand All @@ -35,8 +36,9 @@ const Login = () => {
password: formData.password,
})
navigate("/group")
} catch (error) {
console.error('There was an error:', error);
} catch (error: any) {
const e = error as AxiosError
e.response === undefined ? setError(e.message) : setError(e.response.data as string);
}
};
return <Segment>
Expand All @@ -53,6 +55,7 @@ const Login = () => {
required/>
<Button>Login</Button>
</Form>
{error.length !== 0 ? <Message size='massive'>{error}</Message> : null}
</Segment>

}
Expand Down
8 changes: 8 additions & 0 deletions frontend/src/NotFound.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import {Message} from "semantic-ui-react";


const NotFound = () => {
return <Message size='massive'>Not Found!</Message>
}

export default NotFound;
11 changes: 8 additions & 3 deletions frontend/src/Register.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import {Button, Form, Segment} from "semantic-ui-react";
import {Button, Form, Message, Segment} from "semantic-ui-react";
import React, {useState} from "react";
import {useNavigate,} from "react-router-dom";
import {register} from "./api/api";
import {AxiosError} from "axios";


const Register = () => {
const navigate = useNavigate()


const [error, setError] = useState("")
const [formData, setFormData] = useState({
username: '',
email: '',
Expand Down Expand Up @@ -39,8 +42,9 @@ const Register = () => {
confirmPassword: formData.confirmPassword
})
navigate("/login")
} catch (error) {
console.error('There was an error:', error);
} catch (error: any) {
const e = error as AxiosError
e.response === undefined ? setError(e.message) : setError(e.response.data as string);
}
};
return <Segment>
Expand All @@ -67,6 +71,7 @@ const Register = () => {
required/>
<Button>Register</Button>
</Form>
{error.length !== 0 ? <Message size='massive'>{error}</Message> : null}
</Segment>
}

Expand Down
1 change: 0 additions & 1 deletion frontend/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ export const instance = axios.create({
headers: {
"Access-Control-Allow-Origin": "*",
"Content-Type": "application/json",
"cardmaster-user": "user:lhxwr5fi4p17z4ggtpy0",
},
withCredentials: true
});
Expand Down
9 changes: 8 additions & 1 deletion src/main/kotlin/com/cardmaster/plugins/CORS.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.cardmaster.plugins

import com.cardmaster.util.UserAlreadyExistsException
import com.cardmaster.util.UserNotFoundException
import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.plugins.cors.routing.*
Expand All @@ -9,6 +11,12 @@ import io.ktor.server.response.*

fun Application.configureCORS() {
install(StatusPages) {
exception<UserNotFoundException> { call, cause ->
call.respond(HttpStatusCode.Unauthorized, cause.message ?: "User not found")
}
exception<UserAlreadyExistsException> { call, cause ->
call.respond(HttpStatusCode.Conflict, cause.message ?: "User already exists")
}
exception<Throwable> { call, cause ->
call.respondText(text = "500: $cause", status = HttpStatusCode.InternalServerError)
}
Expand All @@ -19,7 +27,6 @@ fun Application.configureCORS() {
allowMethod(HttpMethod.Get)
allowHeader(HttpHeaders.AccessControlAllowOrigin)
allowHeader(HttpHeaders.ContentType)
allowHeadersPrefixed("cardmaster-") //FIXME: Remove and replace with token
allowCredentials = true
anyHost()
}
Expand Down
11 changes: 9 additions & 2 deletions src/main/kotlin/com/cardmaster/routes/UserRoutes.kt
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,15 @@ fun Routing.userRoutes() {
call.respond("Successfully logged in")
}
get("loginc") {
println("test")
if (call.sessions.get<UserSession>() != null) call.respond(HttpStatusCode.OK) else call.respond(HttpStatusCode.Unauthorized)
if (call.sessions.get<UserSession>() != null) {
call.respond(HttpStatusCode.OK)
} else {
call.respond(HttpStatusCode.Unauthorized)
}
}
get("logout") {
call.sessions.clear<UserSession>()
call.respond("Logged out")
}

route("user") {
Expand Down
29 changes: 19 additions & 10 deletions src/main/kotlin/com/cardmaster/service/CardMasterService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import com.cardmaster.model.PlayerGroup
import com.cardmaster.model.User
import com.cardmaster.model.UserSparse
import com.cardmaster.plugins.SurrealDatabase
import com.cardmaster.util.UserAlreadyExistsException
import com.cardmaster.util.UserNotFoundException
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject
import java.time.LocalDateTime
Expand Down Expand Up @@ -60,12 +62,18 @@ class CardMasterService : KoinComponent {
}

fun createUser(user: User): User? {
val hash = dbClient.driver.query(
"SELECT * FROM crypto::scrypt::generate('${user.password}')",
emptyMap(), String::class.java
).first().result.first()
val persistUser = user.copy(password = hash)
return dbClient.driver.create("user:rand()", persistUser)
if (dbClient.driver.query("SELECT * from user where mail = '${user.mail}'", emptyMap(), User::class.java)
.isEmpty()
) {
throw UserAlreadyExistsException(user.mail)
} else {
val hash = dbClient.driver.query(
"SELECT * FROM crypto::scrypt::generate('${user.password}')",
emptyMap(), String::class.java
).first().result.first()
val persistUser = user.copy(password = hash)
return dbClient.driver.create("user:rand()", persistUser)
}
}

fun login(user: User): String {
Expand All @@ -74,13 +82,14 @@ class CardMasterService : KoinComponent {
"SELECT * from user where username = '${user.username}'",
emptyMap(),
User::class.java
).first().result.first()
?: throw NoSuchElementException("User not found")
)
if (savedUser.first().result.isEmpty()) throw UserNotFoundException(user.username)
val queryUser = savedUser.first().result.first()
val passwordCorrect = dbClient.driver.query(
"SELECT * FROM crypto::scrypt::compare('${savedUser.password}','${user.password}')",
"SELECT * FROM crypto::scrypt::compare('${queryUser.password}','${user.password}')",
emptyMap(), String::class.java
).first().result.first()
if (passwordCorrect.toBoolean()) return savedUser.id!! else throw IllegalStateException("Password check failed")
if (passwordCorrect.toBoolean()) return queryUser.id!! else throw IllegalStateException("Password check failed")
}

fun createGroup(group: PlayerGroup): PlayerGroup {
Expand Down
5 changes: 5 additions & 0 deletions src/main/kotlin/com/cardmaster/util/Exceptions.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.cardmaster.util

class UserNotFoundException(val userId: String) : RuntimeException("User with ID $userId not found")

class UserAlreadyExistsException(val email: String) : RuntimeException("User with Mail $email found")

0 comments on commit 9005eee

Please sign in to comment.