summaryrefslogtreecommitdiff
path: root/backend/src
diff options
context:
space:
mode:
authorphyscik <mynameisgennadiy@vk.com>2026-04-15 22:16:17 +0500
committerphyscik <mynameisgennadiy@vk.com>2026-04-15 22:16:17 +0500
commit9848b5589773a2d3e172fe72285b9203c36fd260 (patch)
treea079f11e46c1e1eed76ff84d94dc90303dd05c9c /backend/src
parentdf1052bad682d957a60ded13cd6243bd44ca83e2 (diff)
Register endpoint
Diffstat (limited to 'backend/src')
-rw-r--r--backend/src/API/AuthenticationAPI.zig30
-rw-r--r--backend/src/API/ErrorDescription.zig4
-rw-r--r--backend/src/API/WeaponsAPI.zig4
-rw-r--r--backend/src/Database/Connection.zig1
-rw-r--r--backend/src/Database/UserAccessLayer.zig48
-rw-r--r--backend/src/Handler.zig2
-rw-r--r--backend/src/main.zig1
7 files changed, 87 insertions, 3 deletions
diff --git a/backend/src/API/AuthenticationAPI.zig b/backend/src/API/AuthenticationAPI.zig
new file mode 100644
index 0000000..23a979f
--- /dev/null
+++ b/backend/src/API/AuthenticationAPI.zig
@@ -0,0 +1,30 @@
+const std = @import("std");
+const httpz = @import("httpz");
+const model = @import("../Models/User.zig");
+const db = @import("../Database/Connection.zig");
+const errDesc = @import("ErrorDescription.zig");
+const Handler = @import("../Handler.zig");
+
+pub fn RegisterEndpoints(router: *httpz.Router(*Handler.Handler,*const fn (*Handler.Handler, *httpz.request.Request, *httpz.response.Response) anyerror!void)) void {
+ router.post("/auth/register", register, .{});
+}
+
+fn register(_: *Handler.Handler, req: *httpz.Request, res: *httpz.Response) !void {
+ var body = try req.json(model.RequestBody) orelse {
+ res.setStatus(.bad_request);
+ return;
+ };
+
+ var body_model = try body.ToModel(req.arena);
+
+ db.Users.Create(&body_model) catch |err| {
+ if (err == db.ResultErrors.AlreadyExists) {
+ res.setStatus(.bad_request);
+ try res.json(errDesc.AlreadyExistsDescriptor, .{});
+ return;
+ }
+ res.setStatus(.internal_server_error);
+ return;
+ };
+ res.setStatus(.created);
+}
diff --git a/backend/src/API/ErrorDescription.zig b/backend/src/API/ErrorDescription.zig
index 76f420a..2c3f338 100644
--- a/backend/src/API/ErrorDescription.zig
+++ b/backend/src/API/ErrorDescription.zig
@@ -5,3 +5,7 @@ pub const ErrorDescriptor = struct {
pub const NotFoundDescriptor = ErrorDescriptor {
.Message = "The requested object was not found"
};
+
+pub const AlreadyExistsDescriptor = ErrorDescriptor {
+ .Message = "The object already exists in the database"
+};
diff --git a/backend/src/API/WeaponsAPI.zig b/backend/src/API/WeaponsAPI.zig
index 75cd6e8..901bbb0 100644
--- a/backend/src/API/WeaponsAPI.zig
+++ b/backend/src/API/WeaponsAPI.zig
@@ -62,12 +62,12 @@ fn newRangedWeapon(_: *Handler.Handler, req: *httpz.Request, res: *httpz.Respons
fn updateRangedWeapon(_: *Handler.Handler, req: *httpz.Request, res: *httpz.Response) !void {
const id = req.param("id") orelse {
- res.setStatus(.no_content);
+ res.setStatus(.bad_request);
return;
};
var body = try req.json(model.RequestBody) orelse {
- res.setStatus(.no_content);
+ res.setStatus(.bad_request);
return;
};
diff --git a/backend/src/Database/Connection.zig b/backend/src/Database/Connection.zig
index e08760c..0114cba 100644
--- a/backend/src/Database/Connection.zig
+++ b/backend/src/Database/Connection.zig
@@ -32,4 +32,5 @@ pub fn Disconnect() void {
pool.deinit();
}
+pub const Users = @import("UserAccessLayer.zig");
pub const RangedWeapons = @import("RangedWeaponsAccessLayer.zig");
diff --git a/backend/src/Database/UserAccessLayer.zig b/backend/src/Database/UserAccessLayer.zig
new file mode 100644
index 0000000..46692ad
--- /dev/null
+++ b/backend/src/Database/UserAccessLayer.zig
@@ -0,0 +1,48 @@
+// You are not supposed to include this file. To access this you should use
+// Connection.Users.
+
+const conn = @import("Connection.zig");
+const std = @import("std");
+const pg = @import("pg");
+const model = @import("../Models/User.zig");
+
+
+pub fn Create(NewUser: *model.User) !void {
+ if (try ExistsByUsername(NewUser.Username))
+ return conn.ResultErrors.AlreadyExists;
+ const query =
+ \\ INSERT INTO Users
+ \\ (Username, PasswordHash, Role)
+ \\ VALUES
+ \\ ($1, $2, $3)
+ ;
+
+ _ = try conn.pool.exec(query, .{
+ NewUser.Username,
+ NewUser.PasswordHash,
+ model.Role.ToString(NewUser.Role),
+ });
+}
+
+pub fn GetByCredentials(allocator: std.mem.Allocator, username: []const u8, passwordHash: []const u8) !model.User {
+ const query =
+ \\ SELECT * FROM Users WHERE
+ \\ Username = $1 AND PasswordHash = $2
+ ;
+ var row = try conn.pool.row(query, .{ username, passwordHash }) orelse {
+ return conn.ResultErrors.NotFound;
+ };
+
+ const outp = try model.User.MapWithAllocator(allocator, row.row);
+ try row.deinit();
+ return outp;
+}
+
+pub fn ExistsByUsername(username: []const u8) !bool {
+ const query = "SELECT Id FROM Users WHERE Username = $1";
+ var row = try conn.pool.row(query, .{username}) orelse {
+ return false;
+ };
+ try row.deinit();
+ return true;
+}
diff --git a/backend/src/Handler.zig b/backend/src/Handler.zig
index 0cee922..010dd0e 100644
--- a/backend/src/Handler.zig
+++ b/backend/src/Handler.zig
@@ -4,6 +4,6 @@ const httpz = @import("httpz");
pub const Handler = struct {
pub fn dispatch(self: *Handler, action: httpz.Action(*Handler), req: *httpz.Request, res: *httpz.Response) !void {
try action(self, req, res);
- std.debug.print("{any} {s}\n", .{req.method, req.url.raw});
+ std.debug.print("{any} {s}: {d}\n", .{req.method, req.url.raw, res.status});
}
};
diff --git a/backend/src/main.zig b/backend/src/main.zig
index 6ed630f..db48a38 100644
--- a/backend/src/main.zig
+++ b/backend/src/main.zig
@@ -24,6 +24,7 @@ pub fn main() !void {
router.get("/", index, .{});
@import("API/WeaponsAPI.zig").RegisterEndpoints(router);
+ @import("API/AuthenticationAPI.zig").RegisterEndpoints(router);
// PSQL connection
try db.Connect(allocator);