Create API Context
This commit is contained in:
parent
62d47d9d2f
commit
6f30696d30
4 changed files with 64 additions and 55 deletions
103
src/api/lib.zig
103
src/api/lib.zig
|
@ -287,8 +287,9 @@ pub const ApiSource = struct {
|
||||||
|
|
||||||
return Conn{
|
return Conn{
|
||||||
.db = db,
|
.db = db,
|
||||||
.user_id = null,
|
.context = .{
|
||||||
.community = community,
|
.community = community,
|
||||||
|
},
|
||||||
.allocator = alloc,
|
.allocator = alloc,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -307,40 +308,48 @@ pub const ApiSource = struct {
|
||||||
|
|
||||||
return Conn{
|
return Conn{
|
||||||
.db = db,
|
.db = db,
|
||||||
.token_info = token_info,
|
.context = .{
|
||||||
.user_id = token_info.user_id,
|
.community = community,
|
||||||
.community = community,
|
.token_info = token_info,
|
||||||
|
},
|
||||||
.allocator = alloc,
|
.allocator = alloc,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const ApiContext = struct {
|
||||||
|
token_info: ?Token.Info = null,
|
||||||
|
community: Community,
|
||||||
|
|
||||||
|
pub fn userId(self: ApiContext) ?Uuid {
|
||||||
|
if (self.token_info) |t| return t.user_id else return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
fn ApiConn(comptime DbConn: type, comptime models: anytype) type {
|
fn ApiConn(comptime DbConn: type, comptime models: anytype) type {
|
||||||
return struct {
|
return struct {
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
|
|
||||||
db: DbConn,
|
db: DbConn,
|
||||||
token_info: ?Token.Info = null,
|
context: ApiContext,
|
||||||
user_id: ?Uuid = null,
|
|
||||||
community: Community,
|
|
||||||
allocator: std.mem.Allocator,
|
allocator: std.mem.Allocator,
|
||||||
|
|
||||||
pub fn close(self: *Self) void {
|
pub fn close(self: *Self) void {
|
||||||
util.deepFree(self.allocator, self.community);
|
util.deepFree(self.allocator, self.context.community);
|
||||||
if (self.token_info) |info| util.deepFree(self.allocator, info);
|
if (self.context.token_info) |info| util.deepFree(self.allocator, info);
|
||||||
self.db.releaseConnection();
|
self.db.releaseConnection();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn isAdmin(self: *Self) bool {
|
fn isAdmin(self: *Self) bool {
|
||||||
// TODO
|
// TODO
|
||||||
return self.user_id != null and self.community.kind == .admin;
|
return self.context.userId() != null and self.context.community.kind == .admin;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn login(self: *Self, username: []const u8, password: []const u8) !Token {
|
pub fn login(self: *Self, username: []const u8, password: []const u8) !Token {
|
||||||
return models.auth.login(
|
return models.auth.login(
|
||||||
self.db,
|
self.db,
|
||||||
username,
|
username,
|
||||||
self.community.id,
|
self.context.community.id,
|
||||||
password,
|
password,
|
||||||
self.allocator,
|
self.allocator,
|
||||||
);
|
);
|
||||||
|
@ -355,7 +364,7 @@ fn ApiConn(comptime DbConn: type, comptime models: anytype) type {
|
||||||
issued_at: DateTime,
|
issued_at: DateTime,
|
||||||
};
|
};
|
||||||
pub fn verifyAuthorization(self: *Self) !AuthorizationInfo {
|
pub fn verifyAuthorization(self: *Self) !AuthorizationInfo {
|
||||||
if (self.token_info) |info| {
|
if (self.context.token_info) |info| {
|
||||||
const user = try models.actors.get(self.db, info.user_id, self.allocator);
|
const user = try models.actors.get(self.db, info.user_id, self.allocator);
|
||||||
defer util.deepFree(self.allocator, user);
|
defer util.deepFree(self.allocator, user);
|
||||||
|
|
||||||
|
@ -365,8 +374,8 @@ fn ApiConn(comptime DbConn: type, comptime models: anytype) type {
|
||||||
return AuthorizationInfo{
|
return AuthorizationInfo{
|
||||||
.id = user.id,
|
.id = user.id,
|
||||||
.username = username,
|
.username = username,
|
||||||
.community_id = self.community.id,
|
.community_id = self.context.community.id,
|
||||||
.host = try util.deepClone(self.allocator, self.community.host),
|
.host = try util.deepClone(self.allocator, self.context.community.host),
|
||||||
|
|
||||||
.issued_at = info.issued_at,
|
.issued_at = info.issued_at,
|
||||||
};
|
};
|
||||||
|
@ -405,14 +414,14 @@ fn ApiConn(comptime DbConn: type, comptime models: anytype) type {
|
||||||
|
|
||||||
pub fn createInvite(self: *Self, options: InviteOptions) !InviteResponse {
|
pub fn createInvite(self: *Self, options: InviteOptions) !InviteResponse {
|
||||||
// Only logged in users can make invites
|
// Only logged in users can make invites
|
||||||
const user_id = self.user_id orelse return error.TokenRequired;
|
const user_id = self.context.userId() orelse return error.TokenRequired;
|
||||||
|
|
||||||
const community_id = if (options.to_community) |id| blk: {
|
const community_id = if (options.to_community) |id| blk: {
|
||||||
// Only admins can send invites for other communities
|
// Only admins can send invites for other communities
|
||||||
if (!self.isAdmin()) return error.PermissionDenied;
|
if (!self.isAdmin()) return error.PermissionDenied;
|
||||||
|
|
||||||
break :blk id;
|
break :blk id;
|
||||||
} else self.community.id;
|
} else self.context.community.id;
|
||||||
|
|
||||||
// Users can only make user invites
|
// Users can only make user invites
|
||||||
if (options.kind != .user and !self.isAdmin()) return error.PermissionDenied;
|
if (options.kind != .user and !self.isAdmin()) return error.PermissionDenied;
|
||||||
|
@ -438,7 +447,7 @@ fn ApiConn(comptime DbConn: type, comptime models: anytype) type {
|
||||||
} else try std.fmt.allocPrint(
|
} else try std.fmt.allocPrint(
|
||||||
self.allocator,
|
self.allocator,
|
||||||
"{s}://{s}/invite/{s}",
|
"{s}://{s}/invite/{s}",
|
||||||
.{ @tagName(self.community.scheme), self.community.host, invite.code },
|
.{ @tagName(self.context.community.scheme), self.context.community.host, invite.code },
|
||||||
);
|
);
|
||||||
errdefer util.deepFree(self.allocator, url);
|
errdefer util.deepFree(self.allocator, url);
|
||||||
|
|
||||||
|
@ -468,25 +477,25 @@ fn ApiConn(comptime DbConn: type, comptime models: anytype) type {
|
||||||
// pub fn register(self: *Self, username: []const u8, password: []const u8, opt: RegistrationOptions) !UserResponse {
|
// pub fn register(self: *Self, username: []const u8, password: []const u8, opt: RegistrationOptions) !UserResponse {
|
||||||
// const tx = try self.db.beginOrSavepoint();
|
// const tx = try self.db.beginOrSavepoint();
|
||||||
// const maybe_invite = if (opt.invite_code) |code|
|
// const maybe_invite = if (opt.invite_code) |code|
|
||||||
// try models.invites.getByCode(tx, code, self.community.id, self.allocator)
|
// try models.invites.getByCode(tx, code, self.context.community.id, self.allocator)
|
||||||
// else
|
// else
|
||||||
// null;
|
// null;
|
||||||
// defer if (maybe_invite) |inv| util.deepFree(self.allocator, inv);
|
// defer if (maybe_invite) |inv| util.deepFree(self.allocator, inv);
|
||||||
|
|
||||||
// if (maybe_invite) |invite| {
|
// if (maybe_invite) |invite| {
|
||||||
// if (!Uuid.eql(invite.community_id, self.community.id)) return error.WrongCommunity;
|
// if (!Uuid.eql(invite.community_id, self.context.community.id)) return error.WrongCommunity;
|
||||||
// if (!isInviteValid(invite)) return error.InvalidInvite;
|
// if (!isInviteValid(invite)) return error.InvalidInvite;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// const invite_kind = if (maybe_invite) |inv| inv.kind else .user;
|
// const invite_kind = if (maybe_invite) |inv| inv.kind else .user;
|
||||||
|
|
||||||
// if (self.community.kind == .admin) @panic("Unimplmented");
|
// if (self.context.community.kind == .admin) @panic("Unimplmented");
|
||||||
|
|
||||||
// const user_id = try models.auth.register(
|
// const user_id = try models.auth.register(
|
||||||
// tx,
|
// tx,
|
||||||
// username,
|
// username,
|
||||||
// password,
|
// password,
|
||||||
// self.community.id,
|
// self.context.community.id,
|
||||||
// .{
|
// .{
|
||||||
// .invite_id = if (maybe_invite) |inv| @as(?Uuid, inv.id) else null,
|
// .invite_id = if (maybe_invite) |inv| @as(?Uuid, inv.id) else null,
|
||||||
// .email = opt.email,
|
// .email = opt.email,
|
||||||
|
@ -498,7 +507,7 @@ fn ApiConn(comptime DbConn: type, comptime models: anytype) type {
|
||||||
// .user => {},
|
// .user => {},
|
||||||
// .system => @panic("System user invites unimplemented"),
|
// .system => @panic("System user invites unimplemented"),
|
||||||
// .community_owner => {
|
// .community_owner => {
|
||||||
// try models.communities.transferOwnership(tx, self.community.id, user_id);
|
// try models.communities.transferOwnership(tx, self.context.community.id, user_id);
|
||||||
// },
|
// },
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
@ -519,20 +528,20 @@ fn ApiConn(comptime DbConn: type, comptime models: anytype) type {
|
||||||
try std.fmt.allocPrint(
|
try std.fmt.allocPrint(
|
||||||
self.allocator,
|
self.allocator,
|
||||||
"{s}://{s}/media/{}",
|
"{s}://{s}/media/{}",
|
||||||
.{ @tagName(self.community.scheme), self.community.host, fid },
|
.{ @tagName(self.context.community.scheme), self.context.community.host, fid },
|
||||||
)
|
)
|
||||||
else
|
else
|
||||||
try std.fmt.allocPrint(
|
try std.fmt.allocPrint(
|
||||||
self.allocator,
|
self.allocator,
|
||||||
"{s}://{s}/{s}",
|
"{s}://{s}/{s}",
|
||||||
.{ @tagName(self.community.scheme), self.community.host, default_avatar },
|
.{ @tagName(self.context.community.scheme), self.context.community.host, default_avatar },
|
||||||
);
|
);
|
||||||
errdefer self.allocator.free(avatar_url);
|
errdefer self.allocator.free(avatar_url);
|
||||||
const header_url = if (user.header_file_id) |fid|
|
const header_url = if (user.header_file_id) |fid|
|
||||||
try std.fmt.allocPrint(
|
try std.fmt.allocPrint(
|
||||||
self.allocator,
|
self.allocator,
|
||||||
"{s}://{s}/media/{}",
|
"{s}://{s}/media/{}",
|
||||||
.{ @tagName(self.community.scheme), self.community.host, fid },
|
.{ @tagName(self.context.community.scheme), self.context.community.host, fid },
|
||||||
)
|
)
|
||||||
else
|
else
|
||||||
null;
|
null;
|
||||||
|
@ -565,8 +574,8 @@ fn ApiConn(comptime DbConn: type, comptime models: anytype) type {
|
||||||
const user = try self.getUserUnchecked(self.db, user_id);
|
const user = try self.getUserUnchecked(self.db, user_id);
|
||||||
errdefer util.deepFree(self.allocator, user);
|
errdefer util.deepFree(self.allocator, user);
|
||||||
|
|
||||||
if (self.user_id == null) {
|
if (self.context.userId() == null) {
|
||||||
if (!Uuid.eql(self.community.id, user.community_id)) return error.NotFound;
|
if (!Uuid.eql(self.context.community.id, user.community_id)) return error.NotFound;
|
||||||
}
|
}
|
||||||
|
|
||||||
return user;
|
return user;
|
||||||
|
@ -574,10 +583,10 @@ fn ApiConn(comptime DbConn: type, comptime models: anytype) type {
|
||||||
|
|
||||||
pub fn createNote(self: *Self, content: []const u8) !Note {
|
pub fn createNote(self: *Self, content: []const u8) !Note {
|
||||||
// You cannot post on admin accounts
|
// You cannot post on admin accounts
|
||||||
if (self.community.kind == .admin) return error.WrongCommunity;
|
if (self.context.community.kind == .admin) return error.WrongCommunity;
|
||||||
|
|
||||||
// Only authenticated users can post
|
// Only authenticated users can post
|
||||||
const user_id = self.user_id orelse return error.TokenRequired;
|
const user_id = self.context.userId() orelse return error.TokenRequired;
|
||||||
const note_id = try models.notes.create(self.db, user_id, content, self.allocator);
|
const note_id = try models.notes.create(self.db, user_id, content, self.allocator);
|
||||||
|
|
||||||
return self.getNote(note_id) catch |err| switch (err) {
|
return self.getNote(note_id) catch |err| switch (err) {
|
||||||
|
@ -591,8 +600,8 @@ fn ApiConn(comptime DbConn: type, comptime models: anytype) type {
|
||||||
errdefer util.deepFree(self.allocator, note);
|
errdefer util.deepFree(self.allocator, note);
|
||||||
|
|
||||||
// Only serve community-specific notes on unauthenticated requests
|
// Only serve community-specific notes on unauthenticated requests
|
||||||
if (self.user_id == null) {
|
if (self.context.userId() == null) {
|
||||||
if (!Uuid.eql(self.community.id, note.author.community_id)) return error.NotFound;
|
if (!Uuid.eql(self.context.community.id, note.author.community_id)) return error.NotFound;
|
||||||
}
|
}
|
||||||
|
|
||||||
return note;
|
return note;
|
||||||
|
@ -615,7 +624,7 @@ fn ApiConn(comptime DbConn: type, comptime models: anytype) type {
|
||||||
|
|
||||||
pub fn localTimeline(self: *Self, args: TimelineArgs) !TimelineResult {
|
pub fn localTimeline(self: *Self, args: TimelineArgs) !TimelineResult {
|
||||||
var all_args = std.mem.zeroInit(Note.QueryArgs, args);
|
var all_args = std.mem.zeroInit(Note.QueryArgs, args);
|
||||||
all_args.community_id = self.community.id;
|
all_args.community_id = self.context.community.id;
|
||||||
const result = try models.notes.query(self.db, all_args, self.allocator);
|
const result = try models.notes.query(self.db, all_args, self.allocator);
|
||||||
return TimelineResult{
|
return TimelineResult{
|
||||||
.items = result.items,
|
.items = result.items,
|
||||||
|
@ -625,10 +634,10 @@ fn ApiConn(comptime DbConn: type, comptime models: anytype) type {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn homeTimeline(self: *Self, args: TimelineArgs) !TimelineResult {
|
pub fn homeTimeline(self: *Self, args: TimelineArgs) !TimelineResult {
|
||||||
if (self.user_id == null) return error.NoToken;
|
if (self.context.userId() == null) return error.NoToken;
|
||||||
|
|
||||||
var all_args = std.mem.zeroInit(Note.QueryArgs, args);
|
var all_args = std.mem.zeroInit(Note.QueryArgs, args);
|
||||||
all_args.followed_by = self.user_id;
|
all_args.followed_by = self.context.userId();
|
||||||
const result = try models.notes.query(self.db, all_args, self.allocator);
|
const result = try models.notes.query(self.db, all_args, self.allocator);
|
||||||
return TimelineResult{
|
return TimelineResult{
|
||||||
.items = result.items,
|
.items = result.items,
|
||||||
|
@ -660,12 +669,12 @@ fn ApiConn(comptime DbConn: type, comptime models: anytype) type {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn follow(self: *Self, followee: Uuid) !void {
|
pub fn follow(self: *Self, followee: Uuid) !void {
|
||||||
const result = try models.follows.create(self.db, self.user_id orelse return error.NoToken, followee, self.allocator);
|
const result = try models.follows.create(self.db, self.context.userId() orelse return error.NoToken, followee, self.allocator);
|
||||||
defer util.deepFree(self.allocator, result);
|
defer util.deepFree(self.allocator, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn unfollow(self: *Self, followee: Uuid) !void {
|
pub fn unfollow(self: *Self, followee: Uuid) !void {
|
||||||
const result = try models.follows.delete(self.db, self.user_id orelse return error.NoToken, followee, self.allocator);
|
const result = try models.follows.delete(self.db, self.context.userId() orelse return error.NoToken, followee, self.allocator);
|
||||||
defer util.deepFree(self.allocator, result);
|
defer util.deepFree(self.allocator, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -736,7 +745,7 @@ fn ApiConn(comptime DbConn: type, comptime models: anytype) type {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn driveUpload(self: *Self, meta: UploadFileArgs, body: []const u8) !DriveEntry {
|
pub fn driveUpload(self: *Self, meta: UploadFileArgs, body: []const u8) !DriveEntry {
|
||||||
const user_id = self.user_id orelse return error.NoToken;
|
const user_id = self.context.userId() orelse return error.NoToken;
|
||||||
const file_id = try models.files.create(self.db, user_id, .{
|
const file_id = try models.files.create(self.db, user_id, .{
|
||||||
.filename = meta.filename,
|
.filename = meta.filename,
|
||||||
.description = meta.description,
|
.description = meta.description,
|
||||||
|
@ -782,14 +791,14 @@ fn ApiConn(comptime DbConn: type, comptime models: anytype) type {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn driveMkdir(self: *Self, parent_path: []const u8, name: []const u8) !DriveEntry {
|
pub fn driveMkdir(self: *Self, parent_path: []const u8, name: []const u8) !DriveEntry {
|
||||||
const user_id = self.user_id orelse return error.NoToken;
|
const user_id = self.context.userId() orelse return error.NoToken;
|
||||||
const entry = try models.drive.create(self.db, user_id, parent_path, name, null, self.allocator);
|
const entry = try models.drive.create(self.db, user_id, parent_path, name, null, self.allocator);
|
||||||
errdefer util.deepFree(self.allocator, entry);
|
errdefer util.deepFree(self.allocator, entry);
|
||||||
return try self.backendDriveEntryToFrontend(entry, true);
|
return try self.backendDriveEntryToFrontend(entry, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn driveDelete(self: *Self, path: []const u8) !void {
|
pub fn driveDelete(self: *Self, path: []const u8) !void {
|
||||||
const user_id = self.user_id orelse return error.NoToken;
|
const user_id = self.context.userId() orelse return error.NoToken;
|
||||||
const entry = try models.drive.stat(self.db, user_id, path, self.allocator);
|
const entry = try models.drive.stat(self.db, user_id, path, self.allocator);
|
||||||
defer util.deepFree(self.allocator, entry);
|
defer util.deepFree(self.allocator, entry);
|
||||||
try models.drive.delete(self.db, entry.id, self.allocator);
|
try models.drive.delete(self.db, entry.id, self.allocator);
|
||||||
|
@ -797,14 +806,14 @@ fn ApiConn(comptime DbConn: type, comptime models: anytype) type {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn driveMove(self: *Self, src: []const u8, dest: []const u8) !DriveEntry {
|
pub fn driveMove(self: *Self, src: []const u8, dest: []const u8) !DriveEntry {
|
||||||
const user_id = self.user_id orelse return error.NoToken;
|
const user_id = self.context.userId() orelse return error.NoToken;
|
||||||
try models.drive.move(self.db, user_id, src, dest, self.allocator);
|
try models.drive.move(self.db, user_id, src, dest, self.allocator);
|
||||||
|
|
||||||
return try self.driveGet(dest);
|
return try self.driveGet(dest);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn driveGet(self: *Self, path: []const u8) !DriveEntry {
|
pub fn driveGet(self: *Self, path: []const u8) !DriveEntry {
|
||||||
const user_id = self.user_id orelse return error.NoToken;
|
const user_id = self.context.userId() orelse return error.NoToken;
|
||||||
const entry = try models.drive.stat(self.db, user_id, path, self.allocator);
|
const entry = try models.drive.stat(self.db, user_id, path, self.allocator);
|
||||||
errdefer util.deepFree(self.allocator, entry);
|
errdefer util.deepFree(self.allocator, entry);
|
||||||
|
|
||||||
|
@ -812,7 +821,7 @@ fn ApiConn(comptime DbConn: type, comptime models: anytype) type {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn driveUpdate(self: *Self, path: []const u8, meta: FileUpload.UpdateArgs) !DriveEntry {
|
pub fn driveUpdate(self: *Self, path: []const u8, meta: FileUpload.UpdateArgs) !DriveEntry {
|
||||||
const user_id = self.user_id orelse return error.NoToken;
|
const user_id = self.context.userId() orelse return error.NoToken;
|
||||||
std.log.debug("{s}", .{path});
|
std.log.debug("{s}", .{path});
|
||||||
const entry = try models.drive.stat(self.db, user_id, path, self.allocator);
|
const entry = try models.drive.stat(self.db, user_id, path, self.allocator);
|
||||||
defer util.deepFree(self.allocator, entry);
|
defer util.deepFree(self.allocator, entry);
|
||||||
|
@ -834,7 +843,7 @@ fn ApiConn(comptime DbConn: type, comptime models: anytype) type {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn updateUserProfile(self: *Self, id: Uuid, data: Actor.ProfileUpdateArgs) !void {
|
pub fn updateUserProfile(self: *Self, id: Uuid, data: Actor.ProfileUpdateArgs) !void {
|
||||||
if (!Uuid.eql(id, self.user_id orelse return error.NoToken)) return error.AccessDenied;
|
if (!Uuid.eql(id, self.context.userId() orelse return error.NoToken)) return error.AccessDenied;
|
||||||
try models.actors.updateProfile(self.db, id, data, self.allocator);
|
try models.actors.updateProfile(self.db, id, data, self.allocator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -842,7 +851,7 @@ fn ApiConn(comptime DbConn: type, comptime models: anytype) type {
|
||||||
const invite = models.invites.getByCode(
|
const invite = models.invites.getByCode(
|
||||||
self.db,
|
self.db,
|
||||||
code,
|
code,
|
||||||
self.community.id,
|
self.context.community.id,
|
||||||
self.allocator,
|
self.allocator,
|
||||||
) catch |err| switch (err) {
|
) catch |err| switch (err) {
|
||||||
error.NotFound => return error.InvalidInvite,
|
error.NotFound => return error.InvalidInvite,
|
||||||
|
@ -850,13 +859,13 @@ fn ApiConn(comptime DbConn: type, comptime models: anytype) type {
|
||||||
};
|
};
|
||||||
errdefer util.deepFree(self.allocator, invite);
|
errdefer util.deepFree(self.allocator, invite);
|
||||||
|
|
||||||
if (!Uuid.eql(invite.community_id, self.community.id)) return error.InvalidInvite;
|
if (!Uuid.eql(invite.community_id, self.context.community.id)) return error.InvalidInvite;
|
||||||
if (!isInviteValid(invite)) return error.InvalidInvite;
|
if (!isInviteValid(invite)) return error.InvalidInvite;
|
||||||
|
|
||||||
const url = try std.fmt.allocPrint(
|
const url = try std.fmt.allocPrint(
|
||||||
self.allocator,
|
self.allocator,
|
||||||
"{s}://{s}/invite/{s}",
|
"{s}://{s}/invite/{s}",
|
||||||
.{ @tagName(self.community.scheme), self.community.host, invite.code },
|
.{ @tagName(self.context.community.scheme), self.context.community.host, invite.code },
|
||||||
);
|
);
|
||||||
errdefer util.deepFree(self.allocator, url);
|
errdefer util.deepFree(self.allocator, url);
|
||||||
|
|
||||||
|
|
|
@ -18,25 +18,25 @@ pub fn methods(comptime models: type) type {
|
||||||
pub fn register(self: anytype, username: []const u8, password: []const u8, opt: RegistrationOptions) !types.Actor {
|
pub fn register(self: anytype, username: []const u8, password: []const u8, opt: RegistrationOptions) !types.Actor {
|
||||||
const tx = try self.db.beginOrSavepoint();
|
const tx = try self.db.beginOrSavepoint();
|
||||||
const maybe_invite = if (opt.invite_code) |code|
|
const maybe_invite = if (opt.invite_code) |code|
|
||||||
try models.invites.getByCode(tx, code, self.community.id, self.allocator)
|
try models.invites.getByCode(tx, code, self.context.community.id, self.allocator)
|
||||||
else
|
else
|
||||||
null;
|
null;
|
||||||
defer if (maybe_invite) |inv| util.deepFree(self.allocator, inv);
|
defer if (maybe_invite) |inv| util.deepFree(self.allocator, inv);
|
||||||
|
|
||||||
if (maybe_invite) |invite| {
|
if (maybe_invite) |invite| {
|
||||||
if (!Uuid.eql(invite.community_id, self.community.id)) return error.WrongCommunity;
|
if (!Uuid.eql(invite.community_id, self.context.community.id)) return error.WrongCommunity;
|
||||||
if (!isInviteValid(invite)) return error.InvalidInvite;
|
if (!isInviteValid(invite)) return error.InvalidInvite;
|
||||||
}
|
}
|
||||||
|
|
||||||
const invite_kind = if (maybe_invite) |inv| inv.kind else .user;
|
const invite_kind = if (maybe_invite) |inv| inv.kind else .user;
|
||||||
|
|
||||||
if (self.community.kind == .admin) @panic("Unimplmented");
|
if (self.context.community.kind == .admin) @panic("Unimplmented");
|
||||||
|
|
||||||
const user_id = try models.auth.register(
|
const user_id = try models.auth.register(
|
||||||
tx,
|
tx,
|
||||||
username,
|
username,
|
||||||
password,
|
password,
|
||||||
self.community.id,
|
self.context.community.id,
|
||||||
.{
|
.{
|
||||||
.invite_id = if (maybe_invite) |inv| @as(?Uuid, inv.id) else null,
|
.invite_id = if (maybe_invite) |inv| @as(?Uuid, inv.id) else null,
|
||||||
.email = opt.email,
|
.email = opt.email,
|
||||||
|
@ -48,7 +48,7 @@ pub fn methods(comptime models: type) type {
|
||||||
.user => {},
|
.user => {},
|
||||||
.system => @panic("System user invites unimplemented"),
|
.system => @panic("System user invites unimplemented"),
|
||||||
.community_owner => {
|
.community_owner => {
|
||||||
try models.communities.transferOwnership(tx, self.community.id, user_id);
|
try models.communities.transferOwnership(tx, self.context.community.id, user_id);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -282,7 +282,7 @@ pub const Response = struct {
|
||||||
pub fn template(self: *Self, status_code: http.Status, srv: anytype, comptime templ: []const u8, data: anytype) !void {
|
pub fn template(self: *Self, status_code: http.Status, srv: anytype, comptime templ: []const u8, data: anytype) !void {
|
||||||
try self.headers.put("Content-Type", "text/html");
|
try self.headers.put("Content-Type", "text/html");
|
||||||
|
|
||||||
const user = if (srv.user_id) |uid| try srv.getUser(uid) else null;
|
const user = if (srv.context.userId()) |uid| try srv.getUser(uid) else null;
|
||||||
defer util.deepFree(srv.allocator, user);
|
defer util.deepFree(srv.allocator, user);
|
||||||
|
|
||||||
var stream = try self.open(status_code);
|
var stream = try self.open(status_code);
|
||||||
|
@ -300,7 +300,7 @@ pub const Response = struct {
|
||||||
.{
|
.{
|
||||||
.community = srv.community,
|
.community = srv.community,
|
||||||
.user = user,
|
.user = user,
|
||||||
.user_id = srv.user_id,
|
.user_id = srv.context.userId(),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -61,7 +61,7 @@ const index = struct {
|
||||||
pub const method = .GET;
|
pub const method = .GET;
|
||||||
|
|
||||||
pub fn handler(_: anytype, res: anytype, srv: anytype) !void {
|
pub fn handler(_: anytype, res: anytype, srv: anytype) !void {
|
||||||
if (srv.user_id == null) {
|
if (srv.context.userId() == null) {
|
||||||
try res.headers.put("Location", about.path);
|
try res.headers.put("Location", about.path);
|
||||||
return res.status(.see_other);
|
return res.status(.see_other);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue