From e95cf5c7b6a08eb560763d5167fbddc1c2117bcc Mon Sep 17 00:00:00 2001 From: Nathan Reiner Date: Mon, 17 Nov 2025 09:57:09 +0100 Subject: add file uploading and multi-threading --- src/routes/api/image/list.zig | 30 ++++++++++++++++++++++++++++++ src/routes/api/image/load.zig | 14 ++++++++++++++ src/routes/api/image/root.zig | 2 ++ src/routes/api/image/upload.zig | 4 ++-- src/routes/api/session/is-valid.zig | 5 +++++ src/routes/handler-info.zig | 34 +++++++++++++++++++--------------- 6 files changed, 72 insertions(+), 17 deletions(-) create mode 100644 src/routes/api/image/list.zig create mode 100644 src/routes/api/image/load.zig (limited to 'src/routes') diff --git a/src/routes/api/image/list.zig b/src/routes/api/image/list.zig new file mode 100644 index 0000000..ee7a648 --- /dev/null +++ b/src/routes/api/image/list.zig @@ -0,0 +1,30 @@ +const std = @import("std"); +const Context = @import("../../context.zig"); +const Storage = @import("../../../storage/root.zig"); + +pub const access = .users; + +const ImageInfo = struct { + id: []const u8, +}; + +const Result = struct { + images: []ImageInfo, +}; + +pub fn get(ctx: *Context) !Result { + var images: std.ArrayList(ImageInfo) = .empty; + + const images_list = ctx.storage.images.list(); + defer images_list.deinit(); + + for (images_list.images) |*image| { + try images.append(ctx.allocator, .{ + .id = image.id + }); + } + + return .{ + .images = try images.toOwnedSlice(ctx.allocator), + }; +} diff --git a/src/routes/api/image/load.zig b/src/routes/api/image/load.zig new file mode 100644 index 0000000..1bafb11 --- /dev/null +++ b/src/routes/api/image/load.zig @@ -0,0 +1,14 @@ +const std = @import("std"); +const Context = @import("../../context.zig"); +const Storage = @import("../../../storage/root.zig"); + +pub const access = .users; + +pub fn get(ctx: *Context) ![]const u8 { + const id = ctx.request.head.target["/api/image/load/".len..]; + var image = Storage.Image { .id = id }; + var file = try image.file(ctx.storage); + defer file.close(); + + return try file.readToEndAlloc(ctx.allocator, std.math.maxInt(usize)); +} diff --git a/src/routes/api/image/root.zig b/src/routes/api/image/root.zig index 0ad1960..dafa090 100644 --- a/src/routes/api/image/root.zig +++ b/src/routes/api/image/root.zig @@ -1,3 +1,5 @@ const HandlerInfo = @import("../../handler-info.zig"); pub const upload: HandlerInfo = .from_type(@import("upload.zig")); +pub const list: HandlerInfo = .from_type(@import("list.zig")); +pub const load: HandlerInfo = .from_type(@import("load.zig")); diff --git a/src/routes/api/image/upload.zig b/src/routes/api/image/upload.zig index 7cd5cf1..3aa2ea6 100644 --- a/src/routes/api/image/upload.zig +++ b/src/routes/api/image/upload.zig @@ -4,12 +4,12 @@ const Storage = @import("../../../storage/root.zig"); const log = std.log.scoped(.image_upload); -pub const access = .everyone; +pub const access = .users; pub fn post(ctx: *Context) !void { if (ctx.request.head.content_length) |length| { var buffer: [1024]u8 = undefined; const reader = try ctx.request.readerExpectContinue(&buffer); - try Storage.Image.new(ctx.storage, reader, length); + try ctx.storage.images.add(ctx.storage, reader, length); } } diff --git a/src/routes/api/session/is-valid.zig b/src/routes/api/session/is-valid.zig index 0c26040..4ea4f1a 100644 --- a/src/routes/api/session/is-valid.zig +++ b/src/routes/api/session/is-valid.zig @@ -1,4 +1,5 @@ const std = @import("std"); +const config = @import("config"); const Context = @import("../../context.zig"); pub const access = .everyone; @@ -8,6 +9,10 @@ const Result = struct { }; pub fn get(ctx: *Context) !Result { + if (comptime config.disable_auth) { + return .{ .is_valid = true }; + } + return .{ .is_valid = ctx.storage.sessions.get(ctx.storage, ctx.fingerprint) != null }; diff --git a/src/routes/handler-info.zig b/src/routes/handler-info.zig index 7b744d2..94d0491 100644 --- a/src/routes/handler-info.zig +++ b/src/routes/handler-info.zig @@ -2,6 +2,8 @@ const std = @import("std"); const Context = @import("context.zig"); const Storage = @import("../storage/root.zig"); +const config = @import("config"); + const Access = @import("access.zig").Access; const log = std.log.scoped(.handler_info); @@ -71,22 +73,24 @@ pub fn handle( .fingerprint = get_fingerprint(cookie), }; - const allowed = switch (self.access) { - .everyone => true, - .users => storage.sessions.get(storage, context.fingerprint) != null, - .admins => admin: { - if (storage.sessions.get(storage, context.fingerprint)) |session| { - break :admin session.info.is_admin; - } - break :admin false; - }, - }; + if (!comptime config.disable_auth) { + const allowed = switch (self.access) { + .everyone => true, + .users => storage.sessions.get(storage, context.fingerprint) != null, + .admins => admin: { + if (storage.sessions.get(storage, context.fingerprint)) |session| { + break :admin session.info.is_admin; + } + break :admin false; + }, + }; - if (!allowed) { - return request.respond( - "{ \"error\": \"Forbidden\" }", - .{ .status = .forbidden } - ); + if (!allowed) { + return request.respond( + "{ \"error\": \"Forbidden\" }", + .{ .status = .forbidden } + ); + } } const response = handler(&context) catch |err| { -- cgit v1.2.3-70-g09d2