diff options
| author | physcik <mynameisgennadiy@vk.com> | 2026-04-20 15:45:45 +0500 |
|---|---|---|
| committer | physcik <mynameisgennadiy@vk.com> | 2026-04-20 15:45:45 +0500 |
| commit | 6898919979c914be4c4650158fe0451a21349bb5 (patch) | |
| tree | 41de46b5fad0bf620f9a6dff3baed4e94914e7aa | |
| parent | e293a40d6bb62e4fa8cc212fcc8bb4b3501da287 (diff) | |
login
| -rw-r--r-- | backend/src/API/AuthenticationAPI.zig | 8 | ||||
| -rw-r--r-- | backend/src/API/WeaponsAPI.zig | 12 | ||||
| -rw-r--r-- | backend/src/Authentication/Tokens.zig | 19 | ||||
| -rw-r--r-- | backend/src/Handler.zig | 40 | ||||
| -rw-r--r-- | backend/src/Redis/Connection.zig | 24 | ||||
| -rw-r--r-- | backend/src/main.zig | 9 |
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" { |
