diff options
| author | physcik <mynameisgennadiy@vk.com> | 2026-04-17 23:11:33 +0500 |
|---|---|---|
| committer | physcik <mynameisgennadiy@vk.com> | 2026-04-17 23:11:33 +0500 |
| commit | e293a40d6bb62e4fa8cc212fcc8bb4b3501da287 (patch) | |
| tree | f0da17a7292dbfd8aa5722f9cbd774f9ad2f9e23 /backend | |
| parent | c03658c1b5a8dad87f4b11d1b48f2c057ac3a439 (diff) | |
Sesstion token generation + storage
Diffstat (limited to 'backend')
| -rw-r--r-- | backend/src/API/AuthenticationAPI.zig | 6 | ||||
| -rw-r--r-- | backend/src/Authentication/Tokens.zig | 42 | ||||
| -rw-r--r-- | backend/src/Redis/Connection.zig | 15 | ||||
| -rw-r--r-- | backend/src/main.zig | 3 |
4 files changed, 61 insertions, 5 deletions
diff --git a/backend/src/API/AuthenticationAPI.zig b/backend/src/API/AuthenticationAPI.zig index af3a975..a792e33 100644 --- a/backend/src/API/AuthenticationAPI.zig +++ b/backend/src/API/AuthenticationAPI.zig @@ -4,6 +4,7 @@ const model = @import("../Models/User.zig"); const db = @import("../Database/Connection.zig"); 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 { router.post("/auth/register", register, .{}); @@ -39,7 +40,7 @@ fn login(_: *Handler.Handler, req: *httpz.Request, res: *httpz.Response) !void { const username = body.Username; const pwd = body.Password; - _ = db.Users.GetByCredentials(req.arena, username, pwd) catch |err| { + const user = db.Users.GetByCredentials(req.arena, username, pwd) catch |err| { if (err == db.ResultErrors.NotFound) { res.setStatus(.unauthorized); try res.json(errDesc.ErrorDescriptor { @@ -50,5 +51,8 @@ fn login(_: *Handler.Handler, req: *httpz.Request, res: *httpz.Response) !void { return err; }; + const token = try Tokens.GenerateNewSession(res.arena, user); + try res.json(.{ .Token = token } , .{}); + // TODO: add token here } diff --git a/backend/src/Authentication/Tokens.zig b/backend/src/Authentication/Tokens.zig new file mode 100644 index 0000000..6548ce7 --- /dev/null +++ b/backend/src/Authentication/Tokens.zig @@ -0,0 +1,42 @@ +const std = @import("std"); +const redis = @import("../Redis/Connection.zig"); +const userModel = @import("../Models/User.zig"); + +const topicName = "cp2020_auth"; +const token_ttl: u16 = 43_200; // 12 hours + +var prng: std.Random.DefaultPrng= undefined; +var rnd: std.Random = undefined; + +pub fn Init() !void { + // Random enough + var seed: u64 = undefined; + try std.posix.getrandom(std.mem.asBytes(&seed)); + prng = std.Random.DefaultPrng.init(seed); + rnd = prng.random(); +} + +/// Generates a new token in the heap. Expects [64]u8 as an input +fn generateSessionToken(buf: []u8) []u8 { + for (0..64) |i| { + buf[i] = std.Random.intRangeAtMost(rnd, u8, 'A', 'z'); + } + return buf; +} + +pub fn GenerateNewSession(allocator: std.mem.Allocator, user: userModel.User) ![]u8 { + const token: []u8 = try allocator.alloc(u8, 64); + const newToken = generateSessionToken(token); + + // Redis cache + var string: std.io.Writer.Allocating = .init(allocator); + defer string.deinit(); + try string.writer.print("{f}", .{std.json.fmt(user, .{})}); + try redis.WriteToTopic(topicName, redis.Message { + .Key = token, + .Value = string.written(), + .SecondsToLive = token_ttl, + }); + + return newToken; +} diff --git a/backend/src/Redis/Connection.zig b/backend/src/Redis/Connection.zig index 83adb2c..737d5cb 100644 --- a/backend/src/Redis/Connection.zig +++ b/backend/src/Redis/Connection.zig @@ -28,11 +28,15 @@ pub const Message = struct { }; pub fn WriteToTopic(topic: []const u8, message: Message) !void { - _ = redis.redisCommand(connection, "SET %s:%s %s EX %d", - topic.ptr, - message.Key.ptr, - message.Value.ptr, + const rep = redis.redisCommand(connection, "SET %b:%b %b EX %d", + topic.ptr, topic.len, + message.Key.ptr, message.Key.len, + message.Value.ptr, message.Value.len, message.SecondsToLive); + + if (rep != null) { + redis.freeReplyObject(rep); + } } pub fn ReadFromTopic(topic: []const u8, Key: []const u8) ?[]const u8 { @@ -42,6 +46,9 @@ pub fn ReadFromTopic(topic: []const u8, Key: []const u8) ?[]const u8 { if (raw == null) { return null; } + defer { + redis.freeReplyObject(raw); + } const resp: *redis.redisReply = @alignCast(@ptrCast(raw)); if (resp.type != redis.REDIS_REPLY_STRING) { return null; diff --git a/backend/src/main.zig b/backend/src/main.zig index 6f9b21b..6fa8f56 100644 --- a/backend/src/main.zig +++ b/backend/src/main.zig @@ -3,11 +3,14 @@ const backend = @import("backend"); const httpz = @import("httpz"); const db = @import("Database/Connection.zig"); const handler = @import("Handler.zig"); +const tokens = @import("Authentication/Tokens.zig"); const redis = @import("Redis/Connection.zig"); pub fn main() !void { var gpa = std.heap.GeneralPurposeAllocator(.{}){}; const allocator = gpa.allocator(); + + try tokens.Init(); // PSQL connection try db.Connect(allocator); |
