2022-11-21 11:58:54 +00:00
|
|
|
const std = @import("std");
|
|
|
|
const util = @import("util");
|
|
|
|
|
|
|
|
const Uuid = util.Uuid;
|
|
|
|
const DateTime = util.DateTime;
|
|
|
|
|
|
|
|
pub const FileOwner = union(enum) {
|
|
|
|
user_id: Uuid,
|
|
|
|
community_id: Uuid,
|
|
|
|
};
|
|
|
|
|
|
|
|
pub const DriveFile = struct {
|
|
|
|
id: Uuid,
|
|
|
|
filename: []const u8,
|
|
|
|
owner: FileOwner,
|
|
|
|
size: usize,
|
|
|
|
created_at: DateTime,
|
|
|
|
};
|
|
|
|
|
|
|
|
pub const files = struct {
|
|
|
|
pub fn create(db: anytype, owner: FileOwner, filename: []const u8, data: []const u8, alloc: std.mem.Allocator) !void {
|
|
|
|
const id = Uuid.randV4(util.getThreadPrng());
|
|
|
|
const now = DateTime.now();
|
|
|
|
|
|
|
|
// TODO: assert we're not in a transaction
|
|
|
|
db.insert("drive_file", .{
|
|
|
|
.id = id,
|
|
|
|
.filename = filename,
|
2022-12-03 07:44:27 +00:00
|
|
|
.account_owner_id = if (owner == .user_id) owner.user_id else null,
|
|
|
|
.community_owner_id = if (owner == .community_id) owner.community_id else null,
|
2022-11-21 11:58:54 +00:00
|
|
|
.created_at = now,
|
2022-12-03 07:44:27 +00:00
|
|
|
.size = data.len,
|
2022-11-21 11:58:54 +00:00
|
|
|
}, alloc) catch return error.DatabaseFailure;
|
|
|
|
// Assume the previous statement succeeded and is not stuck in a transaction
|
|
|
|
errdefer {
|
|
|
|
db.exec("DELETE FROM drive_file WHERE ID = $1", .{id}, alloc) catch |err| {
|
|
|
|
std.log.err("Unable to remove file record in DB: {}", .{err});
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
try saveFile(id, data);
|
|
|
|
}
|
|
|
|
|
|
|
|
const data_root = "./files";
|
|
|
|
fn saveFile(id: Uuid, data: []const u8) !void {
|
2022-12-03 07:44:27 +00:00
|
|
|
var dir = try std.fs.cwd().openDir(data_root, .{});
|
2022-11-21 11:58:54 +00:00
|
|
|
defer dir.close();
|
|
|
|
|
2022-12-03 07:44:27 +00:00
|
|
|
var file = try dir.createFile(&id.toCharArray(), .{ .exclusive = true });
|
2022-11-21 11:58:54 +00:00
|
|
|
defer file.close();
|
|
|
|
|
|
|
|
try file.writer().writeAll(data);
|
|
|
|
try file.sync();
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn deref(alloc: std.mem.Allocator, id: Uuid) ![]const u8 {
|
2022-12-03 07:44:27 +00:00
|
|
|
var dir = try std.fs.cwd().openDir(data_root, .{});
|
2022-11-21 11:58:54 +00:00
|
|
|
defer dir.close();
|
|
|
|
|
2022-12-03 07:44:27 +00:00
|
|
|
return dir.readFileAlloc(alloc, &id.toCharArray(), 1 << 32);
|
2022-11-21 11:58:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn delete(db: anytype, alloc: std.mem.Allocator, id: Uuid) !void {
|
2022-12-03 07:44:27 +00:00
|
|
|
var dir = try std.fs.cwd().openDir(data_root, .{});
|
2022-11-21 11:58:54 +00:00
|
|
|
defer dir.close();
|
|
|
|
|
|
|
|
try dir.deleteFile(id.toCharArray());
|
|
|
|
|
|
|
|
db.exec("DELETE FROM drive_file WHERE ID = $1", .{id}, alloc) catch return error.DatabaseFailure;
|
|
|
|
}
|
|
|
|
};
|