diff options
Diffstat (limited to 'src/storage/user.zig')
| -rw-r--r-- | src/storage/user.zig | 234 |
1 files changed, 0 insertions, 234 deletions
diff --git a/src/storage/user.zig b/src/storage/user.zig deleted file mode 100644 index c2cc82a..0000000 --- a/src/storage/user.zig +++ /dev/null @@ -1,234 +0,0 @@ -const std = @import("std"); -const Storage = @import("root.zig"); - -const log = std.log.scoped(.user); - -const Self = @This(); - -pub const Info = struct { - name: []const u8, - full_name: []const u8, - birthday: []const u8, - hash: []const u8, - is_admin: bool, - - pub fn clone(self: *const @This(), allocator: std.mem.Allocator) !@This() { - var clone_self: @This() = undefined; - var i: usize = 0; - - inline for (std.meta.fields(@This())) |field_info| { - if (field_info.type == []const u8) { - @field(clone_self, field_info.name) = try allocator.dupe( - u8, - @field(self, field_info.name), - ); - errdefer allocator.free(@field(clone_self, field_info.name)); - } else { - @field(clone_self, field_info.name) = @field(self, field_info.name); - } - i += 1; - } - - return clone_self; - } - - pub fn deinit(self: *const @This(), allocator: std.mem.Allocator) void { - inline for (std.meta.fields(@This())) |field_info| { - if (field_info.type == []const u8) { - allocator.free(@field(self, field_info.name)); - } - } - } -}; - -dir: std.fs.Dir, -info: Info, -arena: std.heap.ArenaAllocator, - -pub fn open( - storage: *Storage, - name: []const u8, -) !Self { - var arena: std.heap.ArenaAllocator = .init(storage.allocator); - errdefer arena.deinit(); - const allocator = arena.allocator(); - - var user_dir = try storage.dir.openDir("user", .{}); - defer user_dir.close(); - - var dir = try user_dir.openDir(name, .{}); - errdefer dir.close(); - - const file = try dir.openFile("info.json", .{ .lock = .shared }); - defer file.close(); - const content = try file.readToEndAlloc(allocator, std.math.maxInt(usize)); - - const info = try std.json.parseFromSliceLeaky(Info, allocator, content, .{}); - - return .{ - .dir = dir, - .arena = arena, - .info = info, - }; -} - -pub fn new( - storage: *Storage, - name: []const u8, - full_name: []const u8, - birthday: []const u8, - password: []const u8, - is_admin: bool, - inner_allocator: std.mem.Allocator -) !Self { - var arena: std.heap.ArenaAllocator = .init(inner_allocator); - const allocator = arena.allocator(); - errdefer arena.deinit(); - - var user_dir = try storage.dir.openDir("user", .{}); - defer user_dir.close(); - - try user_dir.makeDir(name); - var dir = try user_dir.openDir(name, .{}); - errdefer dir.close(); - - var file = try dir.createFile("info.json", .{ .lock = .exclusive }); - file.close(); - - const hash_buf = try allocator.alloc(u8, 256); - const hash = try std.crypto.pwhash.bcrypt.strHash( - password, - .{ - .params = .{ - .rounds_log = 3, - .silently_truncate_password = false, - }, - .encoding = .phc, - }, - hash_buf - ); - - const info: Info = .{ - .name = name, - .full_name = full_name, - .birthday = birthday, - .hash = hash, - .is_admin = is_admin, - }; - - - return .{ - .dir = dir, - .arena = arena, - .info = info, - }; -} - -pub fn set_password(self: *Self, password: []const u8) !void { - const allocator = self.arena.allocator(); - const hash_buf = try allocator.alloc(u8, 256); - const hash = try std.crypto.pwhash.bcrypt.strHash( - password, - .{ - .params = .{ - .rounds_log = 3, - .silently_truncate_password = false, - }, - .encoding = .phc, - }, - hash_buf - ); - - self.info.hash = hash; -} - -pub fn sync(self: *Self) !void { - const file = try self.dir.createFile("info.json", .{ - .lock = .exclusive, - }); - defer file.close(); - - var buffer: [1024]u8 = undefined; - var writer = file.writer(&buffer); - - var stringify = std.json.Stringify { - .writer = &writer.interface, - .options = .{ .whitespace = .indent_2 } - }; - - try stringify.write(self.info); - try writer.interface.flush(); -} - -pub fn check_password(self: *Self, password: []const u8) bool { - std.crypto.pwhash.bcrypt.strVerify(self.info.hash, password, .{ - .silently_truncate_password = false, - }) catch return false; - return true; -} - -pub fn deinit(self: *Self) void { - self.dir.close(); - self.arena.deinit(); - self.* = undefined; -} - -pub fn exists(storage: *Storage, name: []const u8) bool { - var user = storage.dir.openDir("user", .{}) catch return false; - defer user.close(); - - user.access(name, .{}) catch return false; - return true; -} - -pub fn image(storage: *Storage, name: []const u8) ?std.fs.File { - var user = storage.dir.openDir("user", .{}) catch return null; - defer user.close(); - - var profile = user.openDir(name, .{}) catch return null; - defer profile.close(); - return profile.openFile("image.jpg", .{ .lock = .shared }) catch null; -} - -pub fn set_image( - storage: *Storage, - name: []const u8, - reader: *std.Io.Reader, - size: usize, -) !void { - var user = try storage.dir.openDir("user", .{}); - defer user.close(); - - var profile = try user.openDir(name, .{}); - defer profile.close(); - - var image_file = try profile.createFile("image.jpg", .{ .lock = .exclusive }); - defer image_file.close(); - - var buffer: [1024]u8 = undefined; - var file_writer = image_file.writer(&buffer); - - log.info("uploaded to profile {s} [{} bytes]", .{ name, size }); - - try reader.streamExact(&file_writer.interface, size); - - try file_writer.interface.flush(); -} - -pub fn list( - storage: *Storage, - allocator: std.mem.Allocator, -) ![][]const u8 { - var user = try storage.dir.openDir("user", .{ .iterate = true }); - defer user.close(); - - var ids: std.ArrayList([]const u8) = .empty; - - var iterator = user.iterate(); - - while (try iterator.next()) |entry| { - try ids.append(allocator, try allocator.dupe(u8, entry.name)); - } - - return ids.toOwnedSlice(allocator); -} |