summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--backend/src/API/AuthenticationAPI.zig54
-rw-r--r--front/src/App.tsx12
-rw-r--r--front/src/Authentication/LoginPage.tsx4
-rw-r--r--front/src/Authentication/LogoutPage.tsx11
-rw-r--r--front/src/Authentication/RegisterPage.tsx59
-rw-r--r--front/src/Emelents/Sidebar.tsx16
-rw-r--r--front/src/Locales/ru_RU.ts2
7 files changed, 156 insertions, 2 deletions
diff --git a/backend/src/API/AuthenticationAPI.zig b/backend/src/API/AuthenticationAPI.zig
index 0c2a1e9..82cdb1c 100644
--- a/backend/src/API/AuthenticationAPI.zig
+++ b/backend/src/API/AuthenticationAPI.zig
@@ -23,6 +23,14 @@ fn getUser(data: *Handler.RequestData, _: *httpz.Request, res: *httpz.Response)
}, .{});
}
+const authResult = struct {
+ Token: []const u8,
+ User: struct {
+ Username: []const u8,
+ Role: []const u8
+ },
+};
+
fn register(_: *Handler.RequestData, req: *httpz.Request, res: *httpz.Response) !void {
var body = try req.json(model.RequestBody) orelse {
res.setStatus(.bad_request);
@@ -40,6 +48,19 @@ fn register(_: *Handler.RequestData, req: *httpz.Request, res: *httpz.Response)
res.setStatus(.internal_server_error);
return;
};
+
+ const loginResult = loginAction(req.arena, body) catch |err| {
+ if (err == db.ResultErrors.NotFound) {
+ res.setStatus(.unauthorized);
+ try res.json(errDesc.ErrorDescriptor {
+ .Message = "Login or password is incorrect"
+ }, .{});
+ return;
+ }
+ return err;
+ };
+
+ try res.json(loginResult, .{});
res.setStatus(.created);
}
@@ -72,3 +93,36 @@ fn login(_: *Handler.RequestData, req: *httpz.Request, res: *httpz.Response) !vo
},
} , .{});
}
+
+/// Logs in with the given credentials
+fn loginAction(allocator: std.mem.Allocator, requetsed: model.RequestBody) !authResult {
+ const username = requetsed.Username;
+ const pwd = requetsed.Password;
+ const user = try db.Users.GetByCredentials(allocator, username, pwd); // catch |err| {
+ // if (err == db.ResultErrors.NotFound) {
+ // res.setStatus(.unauthorized);
+ // try res.json(errDesc.ErrorDescriptor {
+ // .Message = "Login or password is incorrect"
+ // }, .{});
+ // return;
+ // }
+ // return err;
+ // };
+
+ const token = try Tokens.GenerateNewSession(allocator, user);
+
+ return authResult {
+ .Token = token,
+ .User = .{
+ .Username = user.Username,
+ .Role = user.Role.ToString(),
+ }
+ };
+ // try res.json(.{
+ // .Token = token,
+ // .User = .{
+ // .Username = user.Username,
+ // .Role = user.Role.ToString(),
+ // },
+ // } , .{});
+}
diff --git a/front/src/App.tsx b/front/src/App.tsx
index c106139..7b68f3e 100644
--- a/front/src/App.tsx
+++ b/front/src/App.tsx
@@ -14,7 +14,9 @@ import RangedWeaponPage from './Pages/RangedWeapon';
import { AuthContext, Authentication, GetUserInfo } from './Authentication/ContextProvider';
import { useCookies } from 'react-cookie';
import LoginPage from './Authentication/LoginPage';
+import LogoutPage from './Authentication/LogoutPage';
import { User } from './Authentication/Models';
+import RegisterPage from './Authentication/RegisterPage';
const router = createBrowserRouter([
{
@@ -33,10 +35,20 @@ const router = createBrowserRouter([
path: "/weapons/:id",
element: (<RangedWeaponPage />),
},
+
+ // auth
{
path: "/login",
element: (<LoginPage />),
},
+ {
+ path: "/register",
+ element: (<RegisterPage />),
+ },
+ {
+ path: "/logout",
+ element: (<LogoutPage />),
+ },
]);
function App() {
diff --git a/front/src/Authentication/LoginPage.tsx b/front/src/Authentication/LoginPage.tsx
index e98c506..e673418 100644
--- a/front/src/Authentication/LoginPage.tsx
+++ b/front/src/Authentication/LoginPage.tsx
@@ -3,7 +3,6 @@ import { useContext, useState } from "react";
import { useNavigate } from "react-router";
import { BackendURL } from "../Config";
import { Authentication, SaveState } from "./ContextProvider";
-import { useCookies } from 'react-cookie';
import { GetLocalizedString } from "../Locales/Locales";
import { LanguageContext } from "../Locales/Context";
@@ -40,6 +39,9 @@ function LoginPage() {
window.location.reload();
});
}}> { GetLocalizedString("Log in", lang) } </button>
+
+
+ <p> Don't have an account? <a href="/register"> Click here. </a> </p>
</div>
);
}
diff --git a/front/src/Authentication/LogoutPage.tsx b/front/src/Authentication/LogoutPage.tsx
new file mode 100644
index 0000000..a234985
--- /dev/null
+++ b/front/src/Authentication/LogoutPage.tsx
@@ -0,0 +1,11 @@
+import { useNavigate } from "react-router";
+
+function LogoutPage() {
+ const navigate = useNavigate();
+
+ document.cookie = "X-AUTH-TOKEN=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
+ navigate("/");
+ return (<p> Click <a href="/"> here </a> if you were not redirected already </p>);
+}
+
+export default LogoutPage;
diff --git a/front/src/Authentication/RegisterPage.tsx b/front/src/Authentication/RegisterPage.tsx
new file mode 100644
index 0000000..b30b182
--- /dev/null
+++ b/front/src/Authentication/RegisterPage.tsx
@@ -0,0 +1,59 @@
+import axios from "axios";
+import { useContext, useState } from "react";
+import { useNavigate } from "react-router";
+import { BackendURL } from "../Config";
+import { Authentication, SaveState } from "./ContextProvider";
+import { GetLocalizedString } from "../Locales/Locales";
+import { LanguageContext } from "../Locales/Context";
+
+const RegisterURL = `${BackendURL}/auth/register`;
+
+function RegisterPage() {
+ const lang = useContext(LanguageContext);
+
+ const [username, setUsername] = useState<string>("");
+ const [passw, setPassw] = useState<string>("");
+ const navigate = useNavigate();
+
+ function SetAuthState(newAuthState: Authentication | null) {
+ if (newAuthState) {
+ console.log(`Logging in as ${newAuthState.User}...`);
+ } else {
+ console.log(`Logging out...`);
+ }
+ SaveState(newAuthState, (cookie: string) => {
+ document.cookie = `X-AUTH-TOKEN=${cookie}; path=/;`;
+ })
+ }
+
+ return (
+ <div>
+ <h2> { GetLocalizedString("Username", lang) } </h2>
+ <input onChange={ev => setUsername(ev.target.value)} />
+ <h2> { GetLocalizedString("Password", lang) } </h2>
+ <input onChange={ev => setPassw(ev.target.value)} />
+ <button onClick={() => {
+ Register(username, passw, (data) => {
+ SetAuthState(data);
+ navigate("/");
+ window.location.reload();
+ });
+ }}> { GetLocalizedString("Register", lang) } </button>
+ </div>
+ );
+}
+
+async function Register(username: string, passw: string, onSuccess: (data: Authentication) => void) {
+ await axios.post<Authentication>(
+ RegisterURL, {
+ Username: username,
+ Password: passw
+ }
+ ).then(resp => {
+ onSuccess(resp.data);
+ }).catch(err => {
+ console.log(`Failed to send a login responce: ${err}`);
+ });
+}
+
+export default RegisterPage;
diff --git a/front/src/Emelents/Sidebar.tsx b/front/src/Emelents/Sidebar.tsx
index ad565fa..34766c3 100644
--- a/front/src/Emelents/Sidebar.tsx
+++ b/front/src/Emelents/Sidebar.tsx
@@ -1,4 +1,6 @@
import { useContext } from 'react';
+import { AuthContext } from '../Authentication/ContextProvider';
+import { User } from '../Authentication/Models';
import { AllowedLanguages, LanguageContext } from '../Locales/Context';
import { GetLocalizedString } from '../Locales/Locales';
import './Elements.css';
@@ -9,6 +11,7 @@ type SidebarProps = {
};
function Sidebar({setLang}: SidebarProps) {
+ var user = useContext(AuthContext);
var lang = useContext(LanguageContext);
return (
@@ -19,7 +22,7 @@ function Sidebar({setLang}: SidebarProps) {
<SidebarListElement Href='/' Text='Home' />
<SidebarListElement Href='/classes' Text='Classes' />
<SidebarListElement Href='/weapons' Text='Weapons' />
- <SidebarListElement Href='/login' Text='Login' />
+ { AuthElement(user) }
</ul>
<button onClick={() => {
setLang("ru");
@@ -34,4 +37,15 @@ function Sidebar({setLang}: SidebarProps) {
);
}
+function AuthElement(user: User | null) {
+ if (user != null) {
+ return (
+ <SidebarListElement Href='/logout' Text='Logout' />
+ );
+ }
+ return (
+ <SidebarListElement Href='/login' Text='Login' />
+ );
+}
+
export default Sidebar;
diff --git a/front/src/Locales/ru_RU.ts b/front/src/Locales/ru_RU.ts
index f10ac32..008d852 100644
--- a/front/src/Locales/ru_RU.ts
+++ b/front/src/Locales/ru_RU.ts
@@ -15,6 +15,8 @@ lang.LocalizedStrings = new Map<string, string>([
["username", "Имя пользователя"],
["password", "Пароль"],
["log in", "Войти"],
+ ["logout", "Выйти"],
+ ["register", "Зарегистрироваться"],
["welcome", "Добро пожаловать"],
["heavy pistols", "Тяжёлые пистолеты"],