From a97850964ef891f3d0541d9598cf8f37753c5892 Mon Sep 17 00:00:00 2001 From: jaina heartles Date: Sat, 3 Dec 2022 01:00:04 -0800 Subject: [PATCH] Stub out filesystem apis --- src/http/lib.zig | 24 +++++- src/main/controllers/api/drive.zig | 128 ++++++++++++++++++++++++++++- 2 files changed, 147 insertions(+), 5 deletions(-) diff --git a/src/http/lib.zig b/src/http/lib.zig index f667c04..c114bea 100644 --- a/src/http/lib.zig +++ b/src/http/lib.zig @@ -8,7 +8,29 @@ const json = @import("./json.zig"); const multipart = @import("./multipart.zig"); pub const fields = @import("./fields.zig"); -pub const Method = std.http.Method; +pub const Method = enum { + GET, + HEAD, + POST, + PUT, + DELETE, + CONNECT, + OPTIONS, + TRACE, + PATCH, + + // WebDAV methods (we use some of them for the drive system) + MKCOL, + MOVE, + + pub fn requestHasBody(self: Method) bool { + return switch (self) { + .POST, .PUT, .PATCH, .MKCOL, .MOVE => true, + else => false, + }; + } +}; + pub const Status = std.http.Status; pub const Request = request.Request(server.Stream.Reader); diff --git a/src/main/controllers/api/drive.zig b/src/main/controllers/api/drive.zig index 1072aee..c89f357 100644 --- a/src/main/controllers/api/drive.zig +++ b/src/main/controllers/api/drive.zig @@ -1,17 +1,137 @@ -pub const http = @import("http"); +const api = @import("api"); +const http = @import("http"); +const util = @import("util"); +const controller_utils = @import("../../controllers.zig").helpers; + +const Uuid = util.Uuid; +const DateTime = util.DateTime; + +pub const drive_path = "/drive/:path*"; +pub const DriveArgs = struct { + path: []const u8, +}; + +pub const query = struct { + pub const method = .GET; + pub const path = drive_path; + pub const Args = DriveArgs; + + pub const Query = struct { + const OrderBy = enum { + created_at, + filename, + }; + + max_items: usize = 20, + + like: ?[]const u8 = null, + + order_by: OrderBy = .created_at, + direction: api.Direction = .descending, + + prev: ?struct { + id: Uuid, + order_val: union(OrderBy) { + created_at: DateTime, + filename: []const u8, + }, + } = null, + + page_direction: api.PageDirection = .forward, + }; + + pub fn handler(req: anytype, res: anytype, srv: anytype) !void { + const result = srv.driveQuery(req.args.path, req.query) catch |err| switch (err) { + error.NotADirectory => { + const meta = try srv.getFile(path); + try res.json(.ok, meta); + return; + }, + else => |e| return e, + }; + + try controller_utils.paginate(result, res, req.allocator); + } +}; pub const upload = struct { pub const method = .POST; - pub const path = "/drive/:path*"; + pub const path = drive_path; + pub const Args = DriveArgs; pub const Body = struct { file: http.FormFile, + description: ?[]const u8 = null, + sensitive: bool = false, }; pub fn handler(req: anytype, res: anytype, srv: anytype) !void { const f = req.body.file; - try srv.uploadFile(f.filename, f.data); + const meta = try srv.createFile(f.filename, f.content_type, f.data); - try res.json(.created, .{}); + try res.json(.created, meta); + } +}; + +pub const delete = struct { + pub const method = .DELETE; + pub const path = drive_path; + pub const Args = DriveArgs; + + pub fn handler(req: anytype, res: anytype, srv: anytype) !void { + const info = try srv.driveLookup(req.args.path); + if (info == .dir) + try srv.driveRmdir(req.args.path) + else if (info == .file) + try srv.deleteFile(req.args.path); + + return res.json(.ok, .{}); + } +}; + +pub const mkdir = struct { + pub const method = .MKCOL; + pub const path = drive_path; + pub const Args = DriveArgs; + + pub fn handler(req: anytype, res: anytype, srv: anytype) !void { + try srv.driveMkdir(req.args.path); + + return res.json(.created, .{}); + } +}; + +pub const update = struct { + pub const method = .PUT; + pub const path = drive_path; + pub const Args = DriveArgs; + + pub const Body = struct { + description: ?[]const u8 = null, + content_type: ?[]const u8 = null, + sensitive: ?bool = null, + }; + + pub fn handler(req: anytype, res: anytype, srv: anytype) !void { + const info = try srv.driveLookup(req.args.path); + if (info != .file) return error.NotFile; + + const new_info = try srv.updateFile(path, req.body); + try res.json(.ok, new_info); + } +}; + +pub const move = struct { + pub const method = .MOVE; + pub const path = drive_path; + pub const Args = DriveArgs; + + pub fn handler(req: anytype, res: anytype, srv: anytype) !void { + const destination = req.fields.get("Destination") orelse return error.NoDestination; + + try srv.driveMove(req.args.path, destination); + + try res.fields.put("Location", destination); + try srv.json(.created, .{}); } };