diff --git a/src/api/lib.zig b/src/api/lib.zig index 7e72810..29f18d2 100644 --- a/src/api/lib.zig +++ b/src/api/lib.zig @@ -143,6 +143,10 @@ fn ApiConn(comptime DbConn: type, comptime methods: anytype) type { return Services{ .db = self.db }; } + pub fn getCommunity(self: *Self, id: Uuid) !types.communities.Community { + return try methods.communities.get(self.allocator, self.context, self.getServices(), id); + } + pub fn createCommunity(self: *Self, origin: []const u8, name: ?[]const u8) !Uuid { return try methods.communities.create( self.allocator, @@ -157,6 +161,10 @@ fn ApiConn(comptime DbConn: type, comptime methods: anytype) type { return methods.invites.create(self.allocator, self.context, self.getServices(), options); } + pub fn getInvite(self: *Self, id: Uuid) !Invite { + return try methods.invites.get(self.allocator, self.context, self.getServices(), id); + } + pub fn login(self: *Self, username: []const u8, password: []const u8) !Token { return methods.auth.login(self.allocator, self.context, self.getServices(), username, password); } @@ -251,6 +259,10 @@ fn ApiConn(comptime DbConn: type, comptime methods: anytype) type { return try methods.drive.get(self.allocator, self.context, self.getServices(), path); } + pub fn driveGetEntryById(self: *Self, id: Uuid) !types.drive.DriveEntry { + return try methods.drive.getById(self.allocator, self.context, self.getServices(), id); + } + pub fn driveUpdate(self: *Self, path: []const u8, meta: types.files.UpdateArgs) !void { return try methods.drive.update(self.allocator, self.context, self.getServices(), path, meta); } diff --git a/src/api/methods/drive.zig b/src/api/methods/drive.zig index 29b2df6..2607a16 100644 --- a/src/api/methods/drive.zig +++ b/src/api/methods/drive.zig @@ -105,6 +105,20 @@ pub fn get( return try convert(alloc, svcs, entry, true); } +pub fn getById( + alloc: std.mem.Allocator, + ctx: ApiContext, + svcs: anytype, + id: Uuid, +) !pkg.drive.DriveEntry { + const user_id = ctx.userId() orelse return error.NoToken; + const entry = try svcs.getDriveEntry(alloc, id); + defer util.deepFree(alloc, entry); + if (!Uuid.eql(entry.owner_id, user_id)) return error.NotFound; + + return try convert(alloc, svcs, entry, true); +} + // TODO: These next two functions are more about files than drive entries, consider refactor? pub fn update( diff --git a/src/api/services.zig b/src/api/services.zig index 026bcb9..dbaf690 100644 --- a/src/api/services.zig +++ b/src/api/services.zig @@ -154,6 +154,14 @@ pub fn Services(comptime Db: type) type { return try impl.drive.stat(self.db, owner_id, path, alloc); } + pub fn getDriveEntry( + self: Self, + alloc: std.mem.Allocator, + id: Uuid, + ) !DriveEntry { + return try impl.drive.get(self.db, id, alloc); + } + pub fn createDriveEntry( self: Self, alloc: std.mem.Allocator, diff --git a/src/api/services/drive.zig b/src/api/services/drive.zig index 6457d54..d4f21f1 100644 --- a/src/api/services/drive.zig +++ b/src/api/services/drive.zig @@ -7,19 +7,36 @@ const Uuid = util.Uuid; const DateTime = util.DateTime; const Entry = types.drive.DriveEntry; -pub fn stat(db: anytype, owner: Uuid, path: []const u8, alloc: std.mem.Allocator) !Entry { - return (db.queryRow(Entry, +fn doGetQuery(db: anytype, comptime clause: []const u8, args: anytype, alloc: std.mem.Allocator) !Entry { + const q = std.fmt.comptimePrint( \\SELECT id, path, owner_id, name, file_id, kind, parent_directory_id \\FROM drive_entry_path - \\WHERE owner_id = $1 AND path = ('/' || $2) + \\WHERE {s} \\LIMIT 1 - , .{ - owner, - std.mem.trim(u8, path, "/"), - }, alloc) catch |err| switch (err) { + , + .{clause}, + ); + + return db.queryRow(Entry, q, args, alloc) catch |err| switch (err) { error.NoRows => return error.NotFound, else => |e| return e, - }); + }; +} + +pub fn stat(db: anytype, owner: Uuid, path: []const u8, alloc: std.mem.Allocator) !Entry { + return try doGetQuery( + db, + "owner_id = $1 AND path = ('/' || $2)", + .{ + owner, + std.mem.trim(u8, path, "/"), + }, + alloc, + ); +} + +pub fn get(db: anytype, id: Uuid, alloc: std.mem.Allocator) !Entry { + return try doGetQuery(db, "id = $1", .{id}, alloc); } /// Creates a file or directory diff --git a/src/main/controllers/api/drive.zig b/src/main/controllers/api/drive.zig index 17e8a27..8b7aad3 100644 --- a/src/main/controllers/api/drive.zig +++ b/src/main/controllers/api/drive.zig @@ -98,12 +98,14 @@ pub const update = struct { }; pub fn handler(req: anytype, res: anytype, srv: anytype) !void { - const result = try srv.driveUpdate(req.args.path, .{ + try srv.driveUpdate(req.args.path, .{ .filename = req.body.meta.filename, .description = req.body.meta.description, .content_type = req.body.meta.content_type, .sensitive = req.body.meta.sensitive, }); + + const result = try srv.driveGet(req.args.path); defer util.deepFree(srv.allocator, result); try res.json(.ok, result); } @@ -117,7 +119,9 @@ pub const move = struct { pub fn handler(req: anytype, res: anytype, srv: anytype) !void { const destination = req.headers.get("Destination") orelse return error.NoDestination; - const result = try srv.driveMove(req.args.path, destination); + try srv.driveMove(req.args.path, destination); + + const result = try srv.driveGet(req.args.path); defer util.deepFree(srv.allocator, result); try res.headers.put("Location", destination); diff --git a/src/main/controllers/web.zig b/src/main/controllers/web.zig index b23af48..4c83aaa 100644 --- a/src/main/controllers/web.zig +++ b/src/main/controllers/web.zig @@ -341,7 +341,7 @@ const drive = struct { return res.status(.see_other); }, .upload => |body| { - const entry = try srv.driveUpload( + const entry_id = try srv.driveUpload( .{ .filename = body.file.filename, .dir = trimmed_path, @@ -351,6 +351,7 @@ const drive = struct { }, body.file.data, ); + const entry = try srv.driveGetEntryById(entry_id); defer util.deepFree(srv.allocator, entry); const url = try std.fmt.allocPrint(srv.allocator, "{s}/drive/{s}", .{ @@ -402,16 +403,17 @@ const cluster = struct { }; pub fn handler(req: anytype, res: anytype, srv: anytype) !void { - const cid = try srv.createCommunity(req.body.origin, req.body.name); - const community = try srv.getCommunity(cid); + const comm_id = try srv.createCommunity(req.body.origin, req.body.name); + const community = try srv.getCommunity(comm_id); defer util.deepFree(srv.allocator, community); - const invite = try srv.createInvite(.{ + const invite_id = try srv.createInvite(.{ .max_uses = 1, .kind = .community_owner, .to_community = community.id, }); + const invite = try srv.getInvite(invite_id); defer util.deepFree(srv.allocator, invite); try res.template(.ok, srv, success_tmpl, .{ .community = community, .invite = invite });