From a45ccfe0e414acb24a1bc0af811ca47ab4975fe0 Mon Sep 17 00:00:00 2001 From: jaina heartles Date: Fri, 2 Dec 2022 23:44:27 -0800 Subject: [PATCH] Basic file upload --- .gitignore | 1 + src/api/lib.zig | 6 ++++++ src/api/services/files.zig | 14 ++++++++------ src/http/lib.zig | 3 +++ src/http/multipart.zig | 2 +- src/main/controllers/api.zig | 2 ++ src/main/controllers/api/drive.zig | 17 +++++++++++++++++ 7 files changed, 38 insertions(+), 7 deletions(-) create mode 100644 src/main/controllers/api/drive.zig diff --git a/.gitignore b/.gitignore index 7e4c4e7..db4419f 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ **/zig-cache **.db /config.json +/files diff --git a/src/api/lib.zig b/src/api/lib.zig index 1a46fa9..49c174e 100644 --- a/src/api/lib.zig +++ b/src/api/lib.zig @@ -9,6 +9,7 @@ const services = struct { const communities = @import("./services/communities.zig"); const actors = @import("./services/actors.zig"); const auth = @import("./services/auth.zig"); + const drive = @import("./services/files.zig").files; const invites = @import("./services/invites.zig"); const notes = @import("./services/notes.zig"); const follows = @import("./services/follows.zig"); @@ -509,5 +510,10 @@ fn ApiConn(comptime DbConn: type) type { self.allocator, ); } + + pub fn uploadFile(self: *Self, filename: []const u8, body: []const u8) !void { + const user_id = self.user_id orelse return error.NoToken; + try services.drive.create(self.db, .{ .user_id = user_id }, filename, body, self.allocator); + } }; } diff --git a/src/api/services/files.zig b/src/api/services/files.zig index 18c0e9d..fa3b0a1 100644 --- a/src/api/services/files.zig +++ b/src/api/services/files.zig @@ -26,8 +26,10 @@ pub const files = struct { db.insert("drive_file", .{ .id = id, .filename = filename, - .owner = owner, + .account_owner_id = if (owner == .user_id) owner.user_id else null, + .community_owner_id = if (owner == .community_id) owner.community_id else null, .created_at = now, + .size = data.len, }, alloc) catch return error.DatabaseFailure; // Assume the previous statement succeeded and is not stuck in a transaction errdefer { @@ -41,10 +43,10 @@ pub const files = struct { const data_root = "./files"; fn saveFile(id: Uuid, data: []const u8) !void { - var dir = try std.fs.cwd().openDir(data_root); + var dir = try std.fs.cwd().openDir(data_root, .{}); defer dir.close(); - var file = try dir.createFile(id.toCharArray(), .{ .exclusive = true }); + var file = try dir.createFile(&id.toCharArray(), .{ .exclusive = true }); defer file.close(); try file.writer().writeAll(data); @@ -52,14 +54,14 @@ pub const files = struct { } pub fn deref(alloc: std.mem.Allocator, id: Uuid) ![]const u8 { - var dir = try std.fs.cwd().openDir(data_root); + var dir = try std.fs.cwd().openDir(data_root, .{}); defer dir.close(); - return dir.readFileAlloc(alloc, id.toCharArray(), 1 << 32); + return dir.readFileAlloc(alloc, &id.toCharArray(), 1 << 32); } pub fn delete(db: anytype, alloc: std.mem.Allocator, id: Uuid) !void { - var dir = try std.fs.cwd().openDir(data_root); + var dir = try std.fs.cwd().openDir(data_root, .{}); defer dir.close(); try dir.deleteFile(id.toCharArray()); diff --git a/src/http/lib.zig b/src/http/lib.zig index 3cb0f56..f667c04 100644 --- a/src/http/lib.zig +++ b/src/http/lib.zig @@ -5,6 +5,7 @@ const server = @import("./server.zig"); pub const urlencode = @import("./urlencode.zig"); pub const socket = @import("./socket.zig"); const json = @import("./json.zig"); +const multipart = @import("./multipart.zig"); pub const fields = @import("./fields.zig"); pub const Method = std.http.Method; @@ -19,6 +20,8 @@ pub const middleware = @import("./middleware.zig"); pub const Fields = fields.Fields; +pub const FormFile = multipart.FormFile; + pub const Protocol = enum { http_1_0, http_1_1, diff --git a/src/http/multipart.zig b/src/http/multipart.zig index 62bff59..251d1ef 100644 --- a/src/http/multipart.zig +++ b/src/http/multipart.zig @@ -110,7 +110,7 @@ const MultipartFormField = struct { content_type: ?[]const u8 = null, }; -const FormFile = struct { +pub const FormFile = struct { data: []const u8, filename: []const u8, }; diff --git a/src/main/controllers/api.zig b/src/main/controllers/api.zig index 12f3a1f..08e4f1d 100644 --- a/src/main/controllers/api.zig +++ b/src/main/controllers/api.zig @@ -2,6 +2,7 @@ const controllers = @import("../controllers.zig"); const auth = @import("./api/auth.zig"); const communities = @import("./api/communities.zig"); +const drive = @import("./api/drive.zig"); const invites = @import("./api/invites.zig"); const users = @import("./api/users.zig"); const follows = @import("./api/users/follows.zig"); @@ -26,4 +27,5 @@ pub const routes = .{ controllers.apiEndpoint(follows.delete), controllers.apiEndpoint(follows.query_followers), controllers.apiEndpoint(follows.query_following), + controllers.apiEndpoint(drive.upload), }; diff --git a/src/main/controllers/api/drive.zig b/src/main/controllers/api/drive.zig new file mode 100644 index 0000000..1072aee --- /dev/null +++ b/src/main/controllers/api/drive.zig @@ -0,0 +1,17 @@ +pub const http = @import("http"); + +pub const upload = struct { + pub const method = .POST; + pub const path = "/drive/:path*"; + + pub const Body = struct { + file: http.FormFile, + }; + + pub fn handler(req: anytype, res: anytype, srv: anytype) !void { + const f = req.body.file; + try srv.uploadFile(f.filename, f.data); + + try res.json(.created, .{}); + } +};