summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorphyscik <mynameisgennadiy@vk.com>2026-04-20 15:45:45 +0500
committerphyscik <mynameisgennadiy@vk.com>2026-04-20 15:45:45 +0500
commit6898919979c914be4c4650158fe0451a21349bb5 (patch)
tree41de46b5fad0bf620f9a6dff3baed4e94914e7aa
parente293a40d6bb62e4fa8cc212fcc8bb4b3501da287 (diff)
login
-rw-r--r--backend/src/API/AuthenticationAPI.zig8
-rw-r--r--backend/src/API/WeaponsAPI.zig12
-rw-r--r--backend/src/Authentication/Tokens.zig19
-rw-r--r--backend/src/Handler.zig40
-rw-r--r--backend/src/Redis/Connection.zig24
-rw-r--r--backend/src/main.zig9
6 files changed, 89 insertions, 23 deletions
diff --git a/backend/src/API/AuthenticationAPI.zig b/backend/src/API/AuthenticationAPI.zig
index a792e33..9b45ff4 100644
--- a/backend/src/API/AuthenticationAPI.zig
+++ b/backend/src/API/AuthenticationAPI.zig
@@ -6,12 +6,12 @@ const errDesc = @import("ErrorDescription.zig");
const Handler = @import("../Handler.zig");
const Tokens = @import("../Authentication/Tokens.zig");
-pub fn RegisterEndpoints(router: *httpz.Router(*Handler.Handler,*const fn (*Handler.Handler, *httpz.request.Request, *httpz.response.Response) anyerror!void)) void {
+pub fn RegisterEndpoints(router: *httpz.Router(*Handler.Handler,*const fn (*Handler.RequestData, *httpz.request.Request, *httpz.response.Response) anyerror!void)) void {
router.post("/auth/register", register, .{});
router.post("/auth/login", login, .{});
}
-fn register(_: *Handler.Handler, req: *httpz.Request, res: *httpz.Response) !void {
+fn register(_: *Handler.RequestData, req: *httpz.Request, res: *httpz.Response) !void {
var body = try req.json(model.RequestBody) orelse {
res.setStatus(.bad_request);
return;
@@ -31,7 +31,7 @@ fn register(_: *Handler.Handler, req: *httpz.Request, res: *httpz.Response) !voi
res.setStatus(.created);
}
-fn login(_: *Handler.Handler, req: *httpz.Request, res: *httpz.Response) !void {
+fn login(_: *Handler.RequestData, req: *httpz.Request, res: *httpz.Response) !void {
const body = try req.json(model.RequestBody) orelse {
res.setStatus(.bad_request);
return;
@@ -53,6 +53,4 @@ fn login(_: *Handler.Handler, req: *httpz.Request, res: *httpz.Response) !void {
const token = try Tokens.GenerateNewSession(res.arena, user);
try res.json(.{ .Token = token } , .{});
-
- // TODO: add token here
}
diff --git a/backend/src/API/WeaponsAPI.zig b/backend/src/API/WeaponsAPI.zig
index 901bbb0..66871df 100644
--- a/backend/src/API/WeaponsAPI.zig
+++ b/backend/src/API/WeaponsAPI.zig
@@ -5,7 +5,7 @@ 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 {
+pub fn RegisterEndpoints(router: *httpz.Router(*Handler.Handler,*const fn (*Handler.RequestData, *httpz.request.Request, *httpz.response.Response) anyerror!void)) void {
router.get("/weapons/ranged", getAllRangedWeapons, .{});
router.post("/weapons/ranged", newRangedWeapon, .{});
router.get("/weapons/ranged/:id", getRangedWeaponById, .{});
@@ -13,14 +13,14 @@ pub fn RegisterEndpoints(router: *httpz.Router(*Handler.Handler,*const fn (*Hand
router.delete("/weapons/ranged/:id", deleteRangedWeapon, .{});
}
-fn getAllRangedWeapons(_: *Handler.Handler, req: *httpz.Request, res: *httpz.Response) !void {
+fn getAllRangedWeapons(_: *Handler.RequestData, req: *httpz.Request, res: *httpz.Response) !void {
var found = try db.RangedWeapons.GetAll(req.arena);
defer found.deinit(req.arena);
try res.json(found.items, .{});
}
-fn getRangedWeaponById(_: *Handler.Handler, req: *httpz.Request, res: *httpz.Response) !void {
+fn getRangedWeaponById(_: *Handler.RequestData, req: *httpz.Request, res: *httpz.Response) !void {
const id = req.param("id") orelse {
res.setStatus(.bad_request);
return;
@@ -39,7 +39,7 @@ fn getRangedWeaponById(_: *Handler.Handler, req: *httpz.Request, res: *httpz.Res
try res.json(found, .{});
}
-fn newRangedWeapon(_: *Handler.Handler, req: *httpz.Request, res: *httpz.Response) !void {
+fn newRangedWeapon(_: *Handler.RequestData, req: *httpz.Request, res: *httpz.Response) !void {
var body = try req.json(model.RequestBody) orelse {
res.setStatus(.bad_request);
return;
@@ -60,7 +60,7 @@ fn newRangedWeapon(_: *Handler.Handler, req: *httpz.Request, res: *httpz.Respons
res.setStatus(.created);
}
-fn updateRangedWeapon(_: *Handler.Handler, req: *httpz.Request, res: *httpz.Response) !void {
+fn updateRangedWeapon(_: *Handler.RequestData, req: *httpz.Request, res: *httpz.Response) !void {
const id = req.param("id") orelse {
res.setStatus(.bad_request);
return;
@@ -82,7 +82,7 @@ fn updateRangedWeapon(_: *Handler.Handler, req: *httpz.Request, res: *httpz.Resp
};
}
-fn deleteRangedWeapon(_: *Handler.Handler, req: *httpz.Request, res: *httpz.Response) !void {
+fn deleteRangedWeapon(_: *Handler.RequestData, req: *httpz.Request, res: *httpz.Response) !void {
const id = req.param("id") orelse {
res.setStatus(.bad_request);
return;
diff --git a/backend/src/Authentication/Tokens.zig b/backend/src/Authentication/Tokens.zig
index 6548ce7..37bfd5a 100644
--- a/backend/src/Authentication/Tokens.zig
+++ b/backend/src/Authentication/Tokens.zig
@@ -20,6 +20,9 @@ pub fn Init() !void {
fn generateSessionToken(buf: []u8) []u8 {
for (0..64) |i| {
buf[i] = std.Random.intRangeAtMost(rnd, u8, 'A', 'z');
+ if (buf[i] == '\\') {
+ buf[i] = '@';
+ }
}
return buf;
}
@@ -40,3 +43,19 @@ pub fn GenerateNewSession(allocator: std.mem.Allocator, user: userModel.User) ![
return newToken;
}
+
+pub fn GetUserFromToken(allocator: std.mem.Allocator, token: []const u8) !?std.json.Parsed(userModel.User) {
+ const saved = try redis.ReadFromTopic(allocator, topicName, token) orelse {
+ std.debug.print("The token was not found \n", .{});
+ return null;
+ };
+ std.debug.print("FromRedis: {s}\n", .{ saved });
+ const parsed = try std.json.parseFromSlice(
+ userModel.User,
+ allocator,
+ saved,
+ .{
+ .ignore_unknown_fields = true,
+ });
+ return parsed;
+}
diff --git a/backend/src/Handler.zig b/backend/src/Handler.zig
index 010dd0e..4623d36 100644
--- a/backend/src/Handler.zig
+++ b/backend/src/Handler.zig
@@ -1,9 +1,45 @@
const std = @import("std");
const httpz = @import("httpz");
+const userModel = @import("Models/User.zig");
+const tokens = @import("Authentication/Tokens.zig");
+
+pub const RequestData = struct {
+ User: ?userModel.User,
+
+ pub fn Init(req: *httpz.Request) !RequestData {
+ return .{
+ .User = try getUser(req),
+ };
+ }
+
+ fn getUser(req: *httpz.Request) !?userModel.User {
+ const header = req.header("authorization") orelse return null;
+ const stripped = stripBearerPrefix(header);
+ const parsed = tokens.GetUserFromToken(req.arena, stripped) catch |err| {
+ std.debug.print("Failed to parse a user: {any}\n", .{ err });
+ return err;
+ } orelse {
+ return null;
+ };
+
+ return parsed.value;
+ }
+};
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);
+ pub fn dispatch(_: *Handler, action: httpz.Action(*RequestData), req: *httpz.Request, res: *httpz.Response) !void {
+ var data = try RequestData.Init(req);
+ std.debug.print("Data: {any}\n", .{ data });
+ try action(&data, req, res);
std.debug.print("{any} {s}: {d}\n", .{req.method, req.url.raw, res.status});
}
};
+
+const headerPrefix = "Bearer ";
+
+fn stripBearerPrefix(header: []const u8) []const u8 {
+ if (std.mem.startsWith(u8, header, headerPrefix)) {
+ return header[headerPrefix.len..];
+ }
+ return header;
+}
diff --git a/backend/src/Redis/Connection.zig b/backend/src/Redis/Connection.zig
index 737d5cb..a69b9ec 100644
--- a/backend/src/Redis/Connection.zig
+++ b/backend/src/Redis/Connection.zig
@@ -39,10 +39,10 @@ pub fn WriteToTopic(topic: []const u8, message: Message) !void {
}
}
-pub fn ReadFromTopic(topic: []const u8, Key: []const u8) ?[]const u8 {
- const raw = redis.redisCommand(connection, "GET %s:%s",
- topic.ptr,
- Key.ptr);
+pub fn ReadFromTopic(allocator: std.mem.Allocator, topic: []const u8, Key: []const u8) !?[]const u8 {
+ const raw = redis.redisCommand(connection, "GET %b:%b",
+ topic.ptr, topic.len,
+ Key.ptr, Key.len);
if (raw == null) {
return null;
}
@@ -53,7 +53,7 @@ pub fn ReadFromTopic(topic: []const u8, Key: []const u8) ?[]const u8 {
if (resp.type != redis.REDIS_REPLY_STRING) {
return null;
}
- return std.mem.span(resp.str);
+ return try allocator.dupe(u8, resp.str[0..resp.len]);
}
test "Redis connection" {
@@ -66,8 +66,18 @@ test "Redis connection" {
.SecondsToLive = 1,
});
- try std.testing.expectEqualStrings("value", ReadFromTopic("test", "key") orelse "not found");
+ const alloc = std.testing.allocator;
+
+ var resp = try ReadFromTopic(alloc, "test", "key");
+ try std.testing.expectEqualStrings("value", resp orelse "not found");
std.Thread.sleep(1_500_000_000);
// KVP TTL check
- try std.testing.expectEqualStrings("not found", ReadFromTopic("test", "key") orelse "not found");
+ if (resp) |r| {
+ alloc.free(r);
+ }
+ resp = try ReadFromTopic(alloc, "test", "key");
+ try std.testing.expectEqualStrings("not found", resp orelse "not found");
+ if (resp) |r| {
+ defer alloc.free(r);
+ }
}
diff --git a/backend/src/main.zig b/backend/src/main.zig
index 6fa8f56..ff90540 100644
--- a/backend/src/main.zig
+++ b/backend/src/main.zig
@@ -40,9 +40,12 @@ pub fn main() !void {
try server.listen();
}
-fn index(_: *handler.Handler, _: *httpz.Request, res: *httpz.Response) !void {
- res.status = 200;
- try res.json(.{.status = "OK"}, .{});
+fn index(data: *handler.RequestData, _: *httpz.Request, res: *httpz.Response) !void {
+ if (data.User == null) {
+ try res.json(.{.status = "Unauthnticated"}, .{});
+ return;
+ }
+ try res.json(data.User, .{});
}
test "TestRunner" {