diff --git a/src/api/services/communities.zig b/src/api/services/communities.zig index 780b7d5..824957e 100644 --- a/src/api/services/communities.zig +++ b/src/api/services/communities.zig @@ -3,6 +3,7 @@ const builtin = @import("builtin"); const util = @import("util"); const sql = @import("sql"); const common = @import("./common.zig"); +const actors = @import("./actors.zig"); const Uuid = util.Uuid; const DateTime = util.DateTime; @@ -38,11 +39,10 @@ pub const CreateOptions = struct { }; pub const CreateError = error{ - DatabaseFailure, UnsupportedScheme, InvalidOrigin, CommunityExists, -}; +} || sql.DatabaseError; pub fn create(db: anytype, origin: []const u8, options: CreateOptions, alloc: std.mem.Allocator) CreateError!Uuid { const scheme_len = std.mem.indexOfScalar(u8, origin, ':') orelse return error.InvalidOrigin; @@ -71,7 +71,9 @@ pub fn create(db: anytype, origin: []const u8, options: CreateOptions, alloc: st const id = Uuid.randV4(util.getThreadPrng()); // TODO: wrap this in TX - if (db.queryRow( + var tx = try db.beginOrSavepoint(); + errdefer tx.rollback(); + if (tx.queryRow( std.meta.Tuple(&.{Uuid}), "SELECT id FROM community WHERE host = $1", .{host}, @@ -80,11 +82,11 @@ pub fn create(db: anytype, origin: []const u8, options: CreateOptions, alloc: st return error.CommunityExists; } else |err| switch (err) { error.NoRows => {}, - else => return error.DatabaseFailure, + else => |e| return e, } const name = options.name orelse host; - db.insert("community", .{ + try tx.insert("community", .{ .id = id, .owner_id = null, .host = host, @@ -92,8 +94,26 @@ pub fn create(db: anytype, origin: []const u8, options: CreateOptions, alloc: st .scheme = scheme, .kind = options.kind, .created_at = DateTime.now(), - }, alloc) catch return error.DatabaseFailure; + }, alloc); + if (options.kind == .local) { + const actor_id = actors.create(tx, "community.actor", id, alloc) catch |err| switch (err) { + error.UsernameContainsInvalidChar, + error.UsernameTooLong, + error.UsernameEmpty, + error.UsernameTaken, + => unreachable, + else => @panic("TODO"), + }; + try tx.exec( + \\UPDATE community + \\SET community_actor_id = $1 + \\WHERE id = $2 + \\LIMIT 1 + , .{ actor_id, id }, alloc); + } + + try tx.commitOrRelease(); return id; }