fuck
This commit is contained in:
parent
9774f214f3
commit
39565bccf0
14 changed files with 785 additions and 557 deletions
156
src/api/lib.zig
156
src/api/lib.zig
|
@ -1,35 +1,19 @@
|
|||
const std = @import("std");
|
||||
const util = @import("util");
|
||||
const sql = @import("sql");
|
||||
const services = @import("./services.zig");
|
||||
const types = @import("./types.zig");
|
||||
|
||||
const DateTime = util.DateTime;
|
||||
const Uuid = util.Uuid;
|
||||
|
||||
const default_avatar = "static/default_avi.png";
|
||||
|
||||
const services = struct {
|
||||
pub const communities = @import("./services/communities.zig");
|
||||
pub const actors = @import("./services/actors.zig");
|
||||
pub const drive = @import("./services/drive.zig");
|
||||
pub const files = @import("./services/files.zig");
|
||||
pub const invites = @import("./services/invites.zig");
|
||||
pub const notes = @import("./services/notes.zig");
|
||||
pub const follows = @import("./services/follows.zig");
|
||||
|
||||
pub const accounts = @import("./services/accounts.zig");
|
||||
pub const tokens = @import("./services/tokens.zig");
|
||||
};
|
||||
|
||||
test {
|
||||
_ = @import("./methods/auth.zig");
|
||||
}
|
||||
|
||||
const types = @import("./types.zig");
|
||||
|
||||
pub const QueryResult = types.QueryResult;
|
||||
const QueryResult = types.QueryResult;
|
||||
|
||||
pub usingnamespace types;
|
||||
pub const Account = types.Account;
|
||||
pub const Actor = types.Actor;
|
||||
pub const Actor = types.actors.Actor;
|
||||
pub const Community = types.Community;
|
||||
pub const Invite = types.Invite;
|
||||
pub const Note = types.Note;
|
||||
|
@ -93,37 +77,6 @@ pub const NoteResponse = struct {
|
|||
created_at: DateTime,
|
||||
};
|
||||
|
||||
pub const TimelineArgs = struct {
|
||||
pub const PageDirection = Note.QueryArgs.PageDirection;
|
||||
pub const Prev = Note.QueryArgs.Prev;
|
||||
|
||||
max_items: usize = 20,
|
||||
|
||||
created_before: ?DateTime = null,
|
||||
created_after: ?DateTime = null,
|
||||
|
||||
prev: ?Prev = null,
|
||||
|
||||
page_direction: PageDirection = .forward,
|
||||
|
||||
fn from(args: Note.QueryArgs) TimelineArgs {
|
||||
return .{
|
||||
.max_items = args.max_items,
|
||||
.created_before = args.created_before,
|
||||
.created_after = args.created_after,
|
||||
.prev = args.prev,
|
||||
.page_direction = args.page_direction,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
pub const TimelineResult = struct {
|
||||
items: []Note,
|
||||
|
||||
prev_page: TimelineArgs,
|
||||
next_page: TimelineArgs,
|
||||
};
|
||||
|
||||
const FollowQueryArgs = struct {
|
||||
pub const OrderBy = services.follows.QueryArgs.OrderBy;
|
||||
pub const Direction = services.follows.QueryArgs.Direction;
|
||||
|
@ -322,9 +275,15 @@ pub const ApiContext = struct {
|
|||
}
|
||||
};
|
||||
|
||||
const methods = struct {
|
||||
const auth = @import("./methods/auth.zig");
|
||||
const timelines = @import("./methods/timelines.zig");
|
||||
};
|
||||
|
||||
fn ApiConn(comptime DbConn: type, comptime models: anytype) type {
|
||||
return struct {
|
||||
const Self = @This();
|
||||
const Services = @import("./services.zig").Services(DbConn);
|
||||
|
||||
db: DbConn,
|
||||
context: ApiContext,
|
||||
|
@ -341,6 +300,10 @@ fn ApiConn(comptime DbConn: type, comptime models: anytype) type {
|
|||
return self.context.userId() != null and self.context.community.kind == .admin;
|
||||
}
|
||||
|
||||
fn getServices(self: *Self) Services {
|
||||
return Services{ .db = self.db };
|
||||
}
|
||||
|
||||
pub const AuthorizationInfo = struct {
|
||||
id: Uuid,
|
||||
username: []const u8,
|
||||
|
@ -459,17 +422,10 @@ fn ApiConn(comptime DbConn: type, comptime models: anytype) type {
|
|||
return true;
|
||||
}
|
||||
|
||||
const Services = @import("./services.zig").Services(DbConn);
|
||||
fn getServices(self: *Self) Services {
|
||||
return Services{ .db = self.db };
|
||||
}
|
||||
pub fn login(self: *Self, username: []const u8, password: []const u8) !Token {
|
||||
return methods.auth.login(self.allocator, self.context, self.getServices(), username, password);
|
||||
}
|
||||
|
||||
const methods = struct {
|
||||
const auth = @import("./methods/auth.zig");
|
||||
};
|
||||
pub fn register(
|
||||
self: *Self,
|
||||
username: []const u8,
|
||||
|
@ -479,54 +435,6 @@ fn ApiConn(comptime DbConn: type, comptime models: anytype) type {
|
|||
return methods.auth.register(self.allocator, self.context, self.getServices(), username, password, opt);
|
||||
}
|
||||
|
||||
//pub usingnamespace @import("./methods/auth.zig").methods(models);
|
||||
// pub fn register(self: *Self, username: []const u8, password: []const u8, opt: RegistrationOptions) !UserResponse {
|
||||
// const tx = try self.db.beginOrSavepoint();
|
||||
// const maybe_invite = if (opt.invite_code) |code|
|
||||
// try models.invites.getByCode(tx, code, self.context.community.id, self.allocator)
|
||||
// else
|
||||
// null;
|
||||
// defer if (maybe_invite) |inv| util.deepFree(self.allocator, inv);
|
||||
|
||||
// if (maybe_invite) |invite| {
|
||||
// if (!Uuid.eql(invite.community_id, self.context.community.id)) return error.WrongCommunity;
|
||||
// if (!isInviteValid(invite)) return error.InvalidInvite;
|
||||
// }
|
||||
|
||||
// const invite_kind = if (maybe_invite) |inv| inv.kind else .user;
|
||||
|
||||
// if (self.context.community.kind == .admin) @panic("Unimplmented");
|
||||
|
||||
// const user_id = try models.auth.register(
|
||||
// tx,
|
||||
// username,
|
||||
// password,
|
||||
// self.context.community.id,
|
||||
// .{
|
||||
// .invite_id = if (maybe_invite) |inv| @as(?Uuid, inv.id) else null,
|
||||
// .email = opt.email,
|
||||
// },
|
||||
// self.allocator,
|
||||
// );
|
||||
|
||||
// switch (invite_kind) {
|
||||
// .user => {},
|
||||
// .system => @panic("System user invites unimplemented"),
|
||||
// .community_owner => {
|
||||
// try models.communities.transferOwnership(tx, self.context.community.id, user_id);
|
||||
// },
|
||||
// }
|
||||
|
||||
// const user = self.getUserUnchecked(tx, user_id) catch |err| switch (err) {
|
||||
// error.NotFound => return error.Unexpected,
|
||||
// else => |e| return e,
|
||||
// };
|
||||
// errdefer util.deepFree(self.allocator, user);
|
||||
|
||||
// try tx.commit();
|
||||
// return user;
|
||||
// }
|
||||
|
||||
fn getUserUnchecked(self: *Self, db: anytype, user_id: Uuid) !UserResponse {
|
||||
const user = try models.actors.get(db, user_id, self.allocator);
|
||||
|
||||
|
@ -618,38 +526,16 @@ fn ApiConn(comptime DbConn: type, comptime models: anytype) type {
|
|||
return try models.communities.query(self.db, args, self.allocator);
|
||||
}
|
||||
|
||||
pub fn globalTimeline(self: *Self, args: TimelineArgs) !TimelineResult {
|
||||
const all_args = std.mem.zeroInit(Note.QueryArgs, args);
|
||||
const result = try models.notes.query(self.db, all_args, self.allocator);
|
||||
return TimelineResult{
|
||||
.items = result.items,
|
||||
.prev_page = TimelineArgs.from(result.prev_page),
|
||||
.next_page = TimelineArgs.from(result.next_page),
|
||||
};
|
||||
pub fn globalTimeline(self: *Self, args: services.timelines.TimelineArgs) !methods.timelines.TimelineResult {
|
||||
return methods.timelines.globalTimeline(self.allocator, self.context, self.getServices(), args);
|
||||
}
|
||||
|
||||
pub fn localTimeline(self: *Self, args: TimelineArgs) !TimelineResult {
|
||||
var all_args = std.mem.zeroInit(Note.QueryArgs, args);
|
||||
all_args.community_id = self.context.community.id;
|
||||
const result = try models.notes.query(self.db, all_args, self.allocator);
|
||||
return TimelineResult{
|
||||
.items = result.items,
|
||||
.prev_page = TimelineArgs.from(result.prev_page),
|
||||
.next_page = TimelineArgs.from(result.next_page),
|
||||
};
|
||||
pub fn localTimeline(self: *Self, args: services.timelines.TimelineArgs) !methods.timelines.TimelineResult {
|
||||
return methods.timelines.localTimeline(self.allocator, self.context, self.getServices(), args);
|
||||
}
|
||||
|
||||
pub fn homeTimeline(self: *Self, args: TimelineArgs) !TimelineResult {
|
||||
if (self.context.userId() == null) return error.NoToken;
|
||||
|
||||
var all_args = std.mem.zeroInit(Note.QueryArgs, args);
|
||||
all_args.followed_by = self.context.userId();
|
||||
const result = try models.notes.query(self.db, all_args, self.allocator);
|
||||
return TimelineResult{
|
||||
.items = result.items,
|
||||
.prev_page = TimelineArgs.from(result.prev_page),
|
||||
.next_page = TimelineArgs.from(result.next_page),
|
||||
};
|
||||
pub fn homeTimeline(self: *Self, args: services.timelines.TimelineArgs) !methods.timelines.TimelineResult {
|
||||
return methods.timelines.homeTimeline(self.allocator, self.context, self.getServices(), args);
|
||||
}
|
||||
|
||||
pub fn queryFollowers(self: *Self, user_id: Uuid, args: FollowerQueryArgs) !FollowerQueryResult {
|
||||
|
|
|
@ -1,18 +1,21 @@
|
|||
const std = @import("std");
|
||||
const util = @import("util");
|
||||
const types = @import("../types.zig");
|
||||
const pkg = @import("../lib.zig");
|
||||
const services = @import("../services.zig");
|
||||
|
||||
const Uuid = util.Uuid;
|
||||
const DateTime = util.DateTime;
|
||||
const Invite = @import("../lib.zig").Invite;
|
||||
pub const Token = types.Token;
|
||||
const ApiContext = pkg.ApiContext;
|
||||
const Invite = types.Invite;
|
||||
const Token = types.Token;
|
||||
|
||||
pub const RegistrationOptions = struct {
|
||||
const RegistrationOptions = struct {
|
||||
invite_code: ?[]const u8 = null,
|
||||
email: ?[]const u8 = null,
|
||||
};
|
||||
|
||||
pub const AccountCreateOptions = @import("../services/accounts.zig").CreateOptions;
|
||||
const AccountCreateOptions = services.accounts.CreateOptions;
|
||||
|
||||
fn isInviteValid(invite: Invite) bool {
|
||||
if (invite.max_uses != null and invite.times_used >= invite.max_uses.?) return false;
|
||||
|
@ -108,7 +111,6 @@ pub fn verifyToken(alloc: std.mem.Allocator, ctx: ApiContext, svcs: anytype, tok
|
|||
return .{ .user_id = info.account_id, .issued_at = info.issued_at };
|
||||
}
|
||||
|
||||
const ApiContext = @import("../lib.zig").ApiContext;
|
||||
pub fn login(
|
||||
alloc: std.mem.Allocator,
|
||||
ctx: ApiContext,
|
||||
|
|
45
src/api/methods/communities.zig
Normal file
45
src/api/methods/communities.zig
Normal file
|
@ -0,0 +1,45 @@
|
|||
const std = @import("std");
|
||||
const util = @import("util");
|
||||
const types = @import("../types.zig");
|
||||
|
||||
const Uuid = util.Uuid;
|
||||
const DateTime = util.DateTime;
|
||||
const QueryResult = types.QueryResult;
|
||||
const Community = types.Community;
|
||||
|
||||
pub fn methods(comptime models: type) type {
|
||||
return struct {
|
||||
pub fn createCommunity(self: anytype, origin: []const u8, name: ?[]const u8) !Community {
|
||||
if (!self.isAdmin()) {
|
||||
return error.PermissionDenied;
|
||||
}
|
||||
|
||||
const tx = try self.db.begin();
|
||||
errdefer tx.rollback();
|
||||
const community_id = try models.communities.create(
|
||||
tx,
|
||||
origin,
|
||||
.{ .name = name },
|
||||
self.allocator,
|
||||
);
|
||||
|
||||
const community = models.communities.get(
|
||||
tx,
|
||||
community_id,
|
||||
self.allocator,
|
||||
) catch |err| return switch (err) {
|
||||
error.NotFound => error.DatabaseError,
|
||||
else => |err2| err2,
|
||||
};
|
||||
|
||||
try tx.commit();
|
||||
|
||||
return community;
|
||||
}
|
||||
|
||||
pub fn queryCommunities(self: anytype, args: Community.QueryArgs) !QueryResult(Community) {
|
||||
if (!self.context.isAdmin()) return error.PermissionDenied;
|
||||
return try models.communities.query(self.db, args, self.allocator);
|
||||
}
|
||||
};
|
||||
}
|
91
src/api/methods/timelines.zig
Normal file
91
src/api/methods/timelines.zig
Normal file
|
@ -0,0 +1,91 @@
|
|||
const std = @import("std");
|
||||
const util = @import("util");
|
||||
const pkg = @import("../lib.zig");
|
||||
|
||||
const ApiContext = pkg.ApiContext;
|
||||
const Uuid = util.Uuid;
|
||||
const DateTime = util.DateTime;
|
||||
|
||||
const services = @import("../services.zig");
|
||||
const Note = services.Note;
|
||||
const QueryArgs = services.notes.QueryArgs;
|
||||
|
||||
pub const TimelineArgs = struct {
|
||||
pub const PageDirection = QueryArgs.PageDirection;
|
||||
pub const Prev = QueryArgs.Prev;
|
||||
|
||||
max_items: usize = 20,
|
||||
|
||||
created_before: ?DateTime = null,
|
||||
created_after: ?DateTime = null,
|
||||
|
||||
prev: ?Prev = null,
|
||||
|
||||
page_direction: PageDirection = .forward,
|
||||
|
||||
fn from(args: QueryArgs) TimelineArgs {
|
||||
return .{
|
||||
.max_items = args.max_items,
|
||||
.created_before = args.created_before,
|
||||
.created_after = args.created_after,
|
||||
.prev = args.prev,
|
||||
.page_direction = args.page_direction,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
pub const TimelineResult = struct {
|
||||
items: []Note,
|
||||
|
||||
prev_page: TimelineArgs,
|
||||
next_page: TimelineArgs,
|
||||
};
|
||||
|
||||
pub fn globalTimeline(
|
||||
alloc: std.mem.Allocator,
|
||||
_: ApiContext,
|
||||
svcs: anytype,
|
||||
args: TimelineArgs,
|
||||
) !TimelineResult {
|
||||
const all_args = std.mem.zeroInit(QueryArgs, args);
|
||||
const result = try svcs.queryNotes(alloc, all_args);
|
||||
return TimelineResult{
|
||||
.items = result.items,
|
||||
.prev_page = TimelineArgs.from(result.prev_page),
|
||||
.next_page = TimelineArgs.from(result.next_page),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn localTimeline(
|
||||
alloc: std.mem.Allocator,
|
||||
ctx: ApiContext,
|
||||
svcs: anytype,
|
||||
args: TimelineArgs,
|
||||
) !TimelineResult {
|
||||
var all_args = std.mem.zeroInit(QueryArgs, args);
|
||||
all_args.community_id = ctx.community.id;
|
||||
const result = try svcs.queryNotes(alloc, all_args);
|
||||
return TimelineResult{
|
||||
.items = result.items,
|
||||
.prev_page = TimelineArgs.from(result.prev_page),
|
||||
.next_page = TimelineArgs.from(result.next_page),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn homeTimeline(
|
||||
alloc: std.mem.Allocator,
|
||||
ctx: ApiContext,
|
||||
svcs: anytype,
|
||||
args: TimelineArgs,
|
||||
) !TimelineResult {
|
||||
if (ctx.userId() == null) return error.NoToken;
|
||||
|
||||
var all_args = std.mem.zeroInit(QueryArgs, args);
|
||||
all_args.followed_by = ctx.userId();
|
||||
const result = try svcs.queryNotes(alloc, all_args);
|
||||
return TimelineResult{
|
||||
.items = result.items,
|
||||
.prev_page = TimelineArgs.from(result.prev_page),
|
||||
.next_page = TimelineArgs.from(result.next_page),
|
||||
};
|
||||
}
|
|
@ -4,21 +4,30 @@ const util = @import("util");
|
|||
const Uuid = util.Uuid;
|
||||
const DateTime = util.DateTime;
|
||||
|
||||
const communities = @import("./services/communities.zig");
|
||||
const actors = @import("./services/actors.zig");
|
||||
const drive = @import("./services/drive.zig");
|
||||
const files = @import("./services/files.zig");
|
||||
const invites = @import("./services/invites.zig");
|
||||
const notes = @import("./services/notes.zig");
|
||||
const follows = @import("./services/follows.zig");
|
||||
const accounts = @import("./services/accounts.zig");
|
||||
const tokens = @import("./services/tokens.zig");
|
||||
const impl = struct {
|
||||
const communities = @import("./services/communities.zig");
|
||||
const actors = @import("./services/actors.zig");
|
||||
const drive = @import("./services/drive.zig");
|
||||
const files = @import("./services/files.zig");
|
||||
const invites = @import("./services/invites.zig");
|
||||
const notes = @import("./services/notes.zig");
|
||||
const follows = @import("./services/follows.zig");
|
||||
const accounts = @import("./services/accounts.zig");
|
||||
const tokens = @import("./services/tokens.zig");
|
||||
};
|
||||
|
||||
pub const Account = accounts.Account;
|
||||
pub const Credentials = accounts.Credentials;
|
||||
pub const Actor = actors.Actor;
|
||||
pub const Invite = invites.Invite;
|
||||
pub const Token = tokens.Token;
|
||||
const types = @import("./services/types.zig");
|
||||
pub usingnamespace types;
|
||||
|
||||
pub const Account = types.accounts.Account;
|
||||
pub const Credentials = types.accounts.Credentials;
|
||||
pub const Actor = types.actors.Actor;
|
||||
pub const Community = types.communities.Community;
|
||||
pub const DriveEntry = types.drive.DriveEntry;
|
||||
pub const FileUpload = types.files.FileUpload;
|
||||
pub const Invite = types.invites.Invite;
|
||||
pub const Note = types.notes.Note;
|
||||
pub const Token = types.tokens.Token;
|
||||
|
||||
pub fn Services(comptime Db: type) type {
|
||||
return struct {
|
||||
|
@ -45,9 +54,9 @@ pub fn Services(comptime Db: type) type {
|
|||
alloc: std.mem.Allocator,
|
||||
actor: Uuid,
|
||||
password_hash: []const u8,
|
||||
options: accounts.CreateOptions,
|
||||
options: types.accounts.CreateOptions,
|
||||
) !void {
|
||||
return try accounts.create(self.db, actor, password_hash, options, alloc);
|
||||
return try impl.accounts.create(self.db, actor, password_hash, options, alloc);
|
||||
}
|
||||
|
||||
pub fn getCredentialsByUsername(
|
||||
|
@ -56,7 +65,7 @@ pub fn Services(comptime Db: type) type {
|
|||
username: []const u8,
|
||||
community_id: Uuid,
|
||||
) !Credentials {
|
||||
return try accounts.getCredentialsByUsername(self.db, username, community_id, alloc);
|
||||
return try impl.accounts.getCredentialsByUsername(self.db, username, community_id, alloc);
|
||||
}
|
||||
|
||||
pub fn createActor(
|
||||
|
@ -66,7 +75,7 @@ pub fn Services(comptime Db: type) type {
|
|||
community_id: Uuid,
|
||||
lax_username: bool, // TODO: remove this
|
||||
) !Uuid {
|
||||
return try actors.create(self.db, username, community_id, lax_username, alloc);
|
||||
return try impl.actors.create(self.db, username, community_id, lax_username, alloc);
|
||||
}
|
||||
|
||||
pub fn getActor(
|
||||
|
@ -74,16 +83,50 @@ pub fn Services(comptime Db: type) type {
|
|||
alloc: std.mem.Allocator,
|
||||
user_id: Uuid,
|
||||
) !Actor {
|
||||
return try actors.get(self.db, user_id, alloc);
|
||||
return try impl.actors.get(self.db, user_id, alloc);
|
||||
}
|
||||
|
||||
pub fn lookupActorByUsername(
|
||||
self: Self,
|
||||
alloc: std.mem.Allocator,
|
||||
username: []const u8,
|
||||
community_id: Uuid,
|
||||
) !Actor {
|
||||
return try impl.actors.lookupByUsername(self.db, username, community_id, alloc);
|
||||
}
|
||||
|
||||
pub fn updateActorProfile(
|
||||
self: Self,
|
||||
alloc: std.mem.Allocator,
|
||||
actor_id: Uuid,
|
||||
new: types.actors.ProfileUpdateArgs,
|
||||
) !Actor {
|
||||
return try impl.actors.updateProfile(self.db, actor_id, new, alloc);
|
||||
}
|
||||
|
||||
pub fn createCommunity(
|
||||
self: Self,
|
||||
alloc: std.mem.Allocator,
|
||||
origin: []const u8,
|
||||
options: communities.CreateOptions,
|
||||
options: types.communities.CreateOptions,
|
||||
) !Uuid {
|
||||
return try communities.create(self.db, origin, options, alloc);
|
||||
return try impl.communities.create(self.db, origin, options, alloc);
|
||||
}
|
||||
|
||||
pub fn getCommunity(
|
||||
self: Self,
|
||||
alloc: std.mem.Allocator,
|
||||
id: Uuid,
|
||||
) !Community {
|
||||
return try impl.communities.get(self.db, id, alloc);
|
||||
}
|
||||
|
||||
pub fn getCommunityByHost(
|
||||
self: Self,
|
||||
alloc: std.mem.Allocator,
|
||||
host: []const u8,
|
||||
) !Community {
|
||||
return try impl.communities.getByHost(self.db, host, alloc);
|
||||
}
|
||||
|
||||
pub fn transferCommunityOwnership(
|
||||
|
@ -91,7 +134,168 @@ pub fn Services(comptime Db: type) type {
|
|||
community_id: Uuid,
|
||||
owner_id: Uuid,
|
||||
) !void {
|
||||
return try communities.transferOwnership(self.db, community_id, owner_id);
|
||||
return try impl.communities.transferOwnership(self.db, community_id, owner_id);
|
||||
}
|
||||
|
||||
pub fn statDriveEntry(
|
||||
self: Self,
|
||||
alloc: std.mem.Allocator,
|
||||
owner_id: Uuid,
|
||||
path: []const u8,
|
||||
) !DriveEntry {
|
||||
return try impl.drive.stat(self.db, owner_id, path, alloc);
|
||||
}
|
||||
|
||||
pub fn createDriveEntry(
|
||||
self: Self,
|
||||
alloc: std.mem.Allocator,
|
||||
owner_id: Uuid,
|
||||
containing_path: []const u8,
|
||||
name: []const u8,
|
||||
file_id: ?Uuid,
|
||||
) !Uuid {
|
||||
return try impl.drive.create(self.db, owner_id, containing_path, name, file_id, alloc);
|
||||
}
|
||||
|
||||
pub fn deleteDriveEntry(
|
||||
self: Self,
|
||||
alloc: std.mem.Allocator,
|
||||
entry_id: Uuid,
|
||||
) !void {
|
||||
return try impl.drive.delete(self.db, entry_id, alloc);
|
||||
}
|
||||
|
||||
pub fn moveDriveEntry(
|
||||
self: Self,
|
||||
alloc: std.mem.Allocator,
|
||||
owner_id: Uuid,
|
||||
src: []const u8,
|
||||
dest: []const u8,
|
||||
) !void {
|
||||
return try impl.drive.move(self.db, owner_id, src, dest, alloc);
|
||||
}
|
||||
|
||||
// TODO: paginate
|
||||
pub fn listDriveEntry(
|
||||
self: Self,
|
||||
alloc: std.mem.Allocator,
|
||||
owner_id: Uuid,
|
||||
path: []const u8,
|
||||
) ![]DriveEntry {
|
||||
return try impl.drive.list(self.db, owner_id, path, alloc);
|
||||
}
|
||||
|
||||
pub fn createFile(
|
||||
self: Self,
|
||||
alloc: std.mem.Allocator,
|
||||
owner_id: Uuid,
|
||||
meta: types.files.CreateOptions,
|
||||
data: []const u8,
|
||||
) !Uuid {
|
||||
return try impl.files.create(self.db, owner_id, meta, data, alloc);
|
||||
}
|
||||
|
||||
pub fn deleteFile(
|
||||
self: Self,
|
||||
alloc: std.mem.Allocator,
|
||||
id: Uuid,
|
||||
) !void {
|
||||
return try impl.files.delete(self.db, id, alloc);
|
||||
}
|
||||
|
||||
pub fn statFile(
|
||||
self: Self,
|
||||
alloc: std.mem.Allocator,
|
||||
id: Uuid,
|
||||
) !FileUpload {
|
||||
return try impl.files.get(self.db, id, alloc);
|
||||
}
|
||||
|
||||
pub fn derefFile(
|
||||
_: Self,
|
||||
alloc: std.mem.Allocator,
|
||||
id: Uuid,
|
||||
) ![]const u8 {
|
||||
return try impl.files.deref(alloc, id);
|
||||
}
|
||||
|
||||
pub fn updateFileMetadata(
|
||||
self: Self,
|
||||
alloc: std.mem.Allocator,
|
||||
id: Uuid,
|
||||
meta: types.files.UpdateArgs,
|
||||
) !FileUpload {
|
||||
return try impl.files.update(self.db, id, meta, alloc);
|
||||
}
|
||||
|
||||
pub fn createFollow(
|
||||
self: Self,
|
||||
alloc: std.mem.Allocator,
|
||||
followed_by: Uuid,
|
||||
followee: Uuid,
|
||||
) !void {
|
||||
return try impl.follows.create(self.db, followed_by, followee, alloc);
|
||||
}
|
||||
|
||||
pub fn deleteFollow(
|
||||
self: Self,
|
||||
alloc: std.mem.Allocator,
|
||||
followed_by: Uuid,
|
||||
followee: Uuid,
|
||||
) !void {
|
||||
return try impl.follows.delete(self.db, followed_by, followee, alloc);
|
||||
}
|
||||
|
||||
pub fn queryFollows(
|
||||
self: Self,
|
||||
alloc: std.mem.Allocator,
|
||||
args: types.follows.QueryArgs,
|
||||
) !types.follows.QueryResult {
|
||||
return try impl.follows.query(self.db, args, alloc);
|
||||
}
|
||||
|
||||
pub fn createInvite(
|
||||
self: Self,
|
||||
alloc: std.mem.Allocator,
|
||||
created_by: Uuid,
|
||||
community_id: Uuid,
|
||||
name: []const u8,
|
||||
options: types.invites.CreateOptions,
|
||||
) !Invite {
|
||||
return try impl.invites.create(self.db, created_by, community_id, name, options, alloc);
|
||||
}
|
||||
|
||||
pub fn getInvite(
|
||||
self: Self,
|
||||
alloc: std.mem.Allocator,
|
||||
invite_id: Uuid,
|
||||
) !Invite {
|
||||
return try impl.invites.get(self.db, invite_id, alloc);
|
||||
}
|
||||
|
||||
pub fn createNote(
|
||||
self: Self,
|
||||
alloc: std.mem.Allocator,
|
||||
author_id: Uuid,
|
||||
content: []const u8,
|
||||
) !Uuid {
|
||||
return try impl.notes.create(self.db, author_id, content, alloc);
|
||||
}
|
||||
|
||||
pub fn getNote(
|
||||
self: Self,
|
||||
alloc: std.mem.Allocator,
|
||||
id: Uuid,
|
||||
) !Note {
|
||||
return try impl.notes.get(self.db, id, alloc);
|
||||
}
|
||||
|
||||
pub fn queryNotes(
|
||||
self: Self,
|
||||
alloc: std.mem.Allocator,
|
||||
args: types.notes.QueryArgs,
|
||||
) !types.notes.QueryResult {
|
||||
return try impl.notes.query(self.db, args, alloc);
|
||||
}
|
||||
|
||||
pub fn getInviteByCode(
|
||||
|
@ -100,7 +304,7 @@ pub fn Services(comptime Db: type) type {
|
|||
code: []const u8,
|
||||
community_id: Uuid,
|
||||
) !Invite {
|
||||
return try invites.getByCode(self.db, code, community_id, alloc);
|
||||
return try impl.invites.getByCode(self.db, code, community_id, alloc);
|
||||
}
|
||||
|
||||
pub fn createToken(
|
||||
|
@ -109,7 +313,7 @@ pub fn Services(comptime Db: type) type {
|
|||
account_id: Uuid,
|
||||
hash: []const u8,
|
||||
) !void {
|
||||
return try tokens.create(self.db, account_id, hash, alloc);
|
||||
return try impl.tokens.create(self.db, account_id, hash, alloc);
|
||||
}
|
||||
|
||||
pub fn getTokenByHash(
|
||||
|
@ -118,7 +322,7 @@ pub fn Services(comptime Db: type) type {
|
|||
hash: []const u8,
|
||||
community_id: Uuid,
|
||||
) !Token {
|
||||
return try tokens.getByHash(self.db, hash, community_id, alloc);
|
||||
return try impl.tokens.getByHash(self.db, hash, community_id, alloc);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,18 +1,12 @@
|
|||
const std = @import("std");
|
||||
const util = @import("util");
|
||||
const types = @import("./types.zig");
|
||||
|
||||
const Uuid = util.Uuid;
|
||||
const DateTime = util.DateTime;
|
||||
|
||||
pub const Role = enum {
|
||||
user,
|
||||
admin,
|
||||
};
|
||||
pub const CreateOptions = struct {
|
||||
invite_id: ?Uuid = null,
|
||||
email: ?[]const u8 = null,
|
||||
role: Role = .user,
|
||||
};
|
||||
const CreateOptions = types.accounts.CreateOptions;
|
||||
const Credentials = types.accounts.Credentials;
|
||||
|
||||
/// Creates a local account with the given information
|
||||
pub fn create(
|
||||
|
@ -40,11 +34,6 @@ pub fn create(
|
|||
tx.commitOrRelease() catch return error.DatabaseFailure;
|
||||
}
|
||||
|
||||
pub const Credentials = struct {
|
||||
account_id: Uuid,
|
||||
password_hash: []const u8,
|
||||
};
|
||||
|
||||
pub fn getCredentialsByUsername(db: anytype, username: []const u8, community_id: Uuid, alloc: std.mem.Allocator) !Credentials {
|
||||
return db.queryRow(
|
||||
Credentials,
|
||||
|
|
|
@ -3,7 +3,7 @@ const util = @import("util");
|
|||
const sql = @import("sql");
|
||||
const common = @import("./common.zig");
|
||||
const files = @import("./files.zig");
|
||||
const types = @import("../types.zig");
|
||||
const types = @import("./types.zig");
|
||||
|
||||
const Uuid = util.Uuid;
|
||||
const DateTime = util.DateTime;
|
||||
|
|
|
@ -3,14 +3,15 @@ const builtin = @import("builtin");
|
|||
const util = @import("util");
|
||||
const sql = @import("sql");
|
||||
const actors = @import("./actors.zig");
|
||||
const types = @import("../types.zig");
|
||||
const types = @import("./types.zig");
|
||||
|
||||
const Uuid = util.Uuid;
|
||||
const DateTime = util.DateTime;
|
||||
const Community = types.Community;
|
||||
pub const CreateOptions = Community.CreateOptions;
|
||||
const QueryArgs = Community.QueryArgs;
|
||||
const QueryResult = types.QueryResult(Community);
|
||||
const Community = types.communities.Community;
|
||||
const Scheme = types.communities.Scheme;
|
||||
const CreateOptions = types.communities.CreateOptions;
|
||||
const QueryArgs = types.communities.QueryArgs;
|
||||
const QueryResult = types.communities.QueryResult;
|
||||
|
||||
pub const CreateError = error{
|
||||
UnsupportedScheme,
|
||||
|
@ -21,7 +22,7 @@ pub const CreateError = error{
|
|||
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;
|
||||
const scheme_str = origin[0..scheme_len];
|
||||
const scheme = std.meta.stringToEnum(Community.Scheme, scheme_str) orelse return error.UnsupportedScheme;
|
||||
const scheme = std.meta.stringToEnum(Scheme, scheme_str) orelse return error.UnsupportedScheme;
|
||||
|
||||
// host must be in the format "{scheme}://{host}"
|
||||
if (origin.len <= scheme_len + ("://").len or
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
const std = @import("std");
|
||||
const sql = @import("sql");
|
||||
const util = @import("util");
|
||||
const types = @import("../types.zig");
|
||||
const types = @import("./types.zig");
|
||||
|
||||
const Uuid = util.Uuid;
|
||||
const DateTime = util.DateTime;
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const util = @import("util");
|
||||
const types = @import("../types.zig");
|
||||
const types = @import("./types.zig");
|
||||
|
||||
const Uuid = util.Uuid;
|
||||
const DateTime = util.DateTime;
|
||||
pub const Invite = types.Invite;
|
||||
const Invite = types.Invite;
|
||||
|
||||
// 9 random bytes = 12 random b64
|
||||
const rand_len = 8;
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
const std = @import("std");
|
||||
const util = @import("util");
|
||||
const sql = @import("sql");
|
||||
const common = @import("./common.zig");
|
||||
const types = @import("../types.zig");
|
||||
const types = @import("./types.zig");
|
||||
|
||||
const Uuid = util.Uuid;
|
||||
const DateTime = util.DateTime;
|
||||
|
|
|
@ -4,12 +4,7 @@ const util = @import("util");
|
|||
const Uuid = util.Uuid;
|
||||
const DateTime = util.DateTime;
|
||||
|
||||
pub const Token = struct {
|
||||
account_id: Uuid,
|
||||
issued_at: DateTime,
|
||||
|
||||
hash: []const u8,
|
||||
};
|
||||
const Token = @import("./types.zig").tokens.Token;
|
||||
|
||||
pub fn create(db: anytype, account_id: Uuid, hash: []const u8, alloc: std.mem.Allocator) !void {
|
||||
const now = DateTime.now();
|
||||
|
|
373
src/api/services/types.zig
Normal file
373
src/api/services/types.zig
Normal file
|
@ -0,0 +1,373 @@
|
|||
const util = @import("util");
|
||||
|
||||
const Uuid = util.Uuid;
|
||||
const DateTime = util.DateTime;
|
||||
|
||||
const common = struct {
|
||||
const Direction = enum {
|
||||
ascending,
|
||||
descending,
|
||||
|
||||
pub const jsonStringify = util.jsonSerializeEnumAsString;
|
||||
};
|
||||
|
||||
const PageDirection = enum {
|
||||
forward,
|
||||
backward,
|
||||
|
||||
pub const jsonStringify = util.jsonSerializeEnumAsString;
|
||||
};
|
||||
|
||||
fn QueryResult(comptime R: type, comptime A: type) type {
|
||||
return struct {
|
||||
items: []R,
|
||||
|
||||
next_page: A,
|
||||
prev_page: A,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
pub const accounts = struct {
|
||||
pub const Role = enum {
|
||||
user,
|
||||
admin,
|
||||
};
|
||||
|
||||
pub const CreateOptions = struct {
|
||||
invite_id: ?Uuid = null,
|
||||
email: ?[]const u8 = null,
|
||||
role: Role = .user,
|
||||
};
|
||||
|
||||
pub const Credentials = struct {
|
||||
account_id: Uuid,
|
||||
password_hash: []const u8,
|
||||
};
|
||||
};
|
||||
|
||||
pub const actors = struct {
|
||||
pub const Actor = struct {
|
||||
id: Uuid,
|
||||
|
||||
username: []const u8,
|
||||
host: []const u8,
|
||||
community_id: Uuid,
|
||||
|
||||
display_name: ?[]const u8,
|
||||
bio: []const u8,
|
||||
|
||||
avatar_file_id: ?Uuid,
|
||||
header_file_id: ?Uuid,
|
||||
|
||||
profile_fields: []const ProfileField,
|
||||
|
||||
created_at: DateTime,
|
||||
updated_at: DateTime,
|
||||
|
||||
pub const sql_serialize = struct {
|
||||
pub const profile_fields = .json;
|
||||
};
|
||||
};
|
||||
|
||||
pub const ProfileField = struct {
|
||||
key: []const u8,
|
||||
value: []const u8,
|
||||
};
|
||||
|
||||
// TODO: get rid of this
|
||||
pub const Profile = struct {
|
||||
display_name: ?[]const u8,
|
||||
bio: []const u8,
|
||||
avatar_file_id: ?Uuid,
|
||||
header_file_id: ?Uuid,
|
||||
profile_fields: []const ProfileField,
|
||||
|
||||
pub const sql_serialize = struct {
|
||||
pub const profile_fields = .json;
|
||||
};
|
||||
};
|
||||
|
||||
pub const ProfileUpdateArgs = struct {
|
||||
display_name: ??[]const u8,
|
||||
bio: ?[]const u8,
|
||||
avatar_file_id: ??Uuid,
|
||||
header_file_id: ??Uuid,
|
||||
profile_fields: ?[]const ProfileField,
|
||||
|
||||
pub const sql_serialize = struct {
|
||||
pub const profile_fields = .json;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
pub const communities = struct {
|
||||
pub const Community = struct {
|
||||
id: Uuid,
|
||||
|
||||
owner_id: ?Uuid,
|
||||
host: []const u8,
|
||||
name: []const u8,
|
||||
|
||||
scheme: Scheme,
|
||||
kind: Kind,
|
||||
created_at: DateTime,
|
||||
};
|
||||
|
||||
pub const Kind = enum {
|
||||
admin,
|
||||
local,
|
||||
|
||||
pub const jsonStringify = util.jsonSerializeEnumAsString;
|
||||
};
|
||||
|
||||
pub const Scheme = enum {
|
||||
https,
|
||||
http,
|
||||
|
||||
pub const jsonStringify = util.jsonSerializeEnumAsString;
|
||||
};
|
||||
|
||||
pub const CreateOptions = struct {
|
||||
name: ?[]const u8 = null,
|
||||
kind: Kind = .local,
|
||||
};
|
||||
|
||||
pub const QueryArgs = struct {
|
||||
pub const OrderBy = enum {
|
||||
name,
|
||||
host,
|
||||
created_at,
|
||||
|
||||
pub const jsonStringify = util.jsonSerializeEnumAsString;
|
||||
};
|
||||
|
||||
pub const Direction = common.Direction;
|
||||
pub const PageDirection = common.PageDirection;
|
||||
pub const Prev = struct {
|
||||
id: Uuid,
|
||||
order_val: OrderVal,
|
||||
};
|
||||
pub const OrderVal = union(OrderBy) {
|
||||
name: []const u8,
|
||||
host: []const u8,
|
||||
created_at: DateTime,
|
||||
};
|
||||
|
||||
// Max items to fetch
|
||||
max_items: usize = 20,
|
||||
|
||||
// Selection filters
|
||||
owner_id: ?Uuid = null, // searches for communities owned by this user
|
||||
like: ?[]const u8 = null, // searches for communities with host or name LIKE '%?%'
|
||||
created_before: ?DateTime = null,
|
||||
created_after: ?DateTime = null,
|
||||
|
||||
// Ordering parameter
|
||||
order_by: OrderBy = .created_at,
|
||||
direction: Direction = .ascending,
|
||||
|
||||
// Page start parameter(s)
|
||||
// This struct is a reference to the last value scanned
|
||||
// If prev is present, then prev.order_val must have the same tag as order_by
|
||||
// "prev" here refers to it being the previous value returned. It may be that
|
||||
// prev refers to the item directly after the results you are about to recieve,
|
||||
// if you are querying the previous page.
|
||||
prev: ?Prev = null,
|
||||
|
||||
// What direction to scan the page window
|
||||
// If "forward", then "prev" is interpreted as the item directly before the items
|
||||
// to query, in the direction of "direction" above. If "backward", then the opposite
|
||||
page_direction: PageDirection = .forward,
|
||||
};
|
||||
|
||||
pub const QueryResult = common.QueryResult(Community, QueryArgs);
|
||||
};
|
||||
|
||||
pub const drive = struct {
|
||||
pub const DriveEntry = struct {
|
||||
pub const Kind = enum {
|
||||
dir,
|
||||
file,
|
||||
|
||||
pub const jsonStringify = util.jsonSerializeEnumAsString;
|
||||
};
|
||||
|
||||
id: Uuid,
|
||||
owner_id: Uuid,
|
||||
|
||||
name: ?[]const u8,
|
||||
|
||||
path: []const u8,
|
||||
parent_directory_id: ?Uuid,
|
||||
|
||||
file_id: ?Uuid,
|
||||
kind: Kind,
|
||||
};
|
||||
};
|
||||
|
||||
pub const files = struct {
|
||||
pub const FileUpload = struct {
|
||||
id: Uuid,
|
||||
|
||||
owner_id: Uuid,
|
||||
size: usize,
|
||||
|
||||
filename: []const u8,
|
||||
description: ?[]const u8,
|
||||
content_type: ?[]const u8,
|
||||
sensitive: bool,
|
||||
|
||||
status: Status,
|
||||
|
||||
created_at: DateTime,
|
||||
updated_at: DateTime,
|
||||
};
|
||||
|
||||
pub const Status = enum {
|
||||
uploading,
|
||||
uploaded,
|
||||
external,
|
||||
deleted,
|
||||
|
||||
pub const jsonStringify = util.jsonSerializeEnumAsString;
|
||||
};
|
||||
|
||||
pub const CreateOptions = struct {
|
||||
filename: []const u8,
|
||||
description: ?[]const u8,
|
||||
content_type: ?[]const u8,
|
||||
sensitive: bool,
|
||||
};
|
||||
|
||||
pub const UpdateArgs = struct {
|
||||
filename: ?[]const u8,
|
||||
description: ?[]const u8,
|
||||
content_type: ?[]const u8,
|
||||
sensitive: ?bool,
|
||||
};
|
||||
};
|
||||
|
||||
pub const invites = struct {
|
||||
const UseCount = usize;
|
||||
pub const Invite = struct {
|
||||
id: Uuid,
|
||||
|
||||
created_by: Uuid, // User ID
|
||||
community_id: Uuid,
|
||||
name: []const u8,
|
||||
code: []const u8,
|
||||
|
||||
created_at: DateTime,
|
||||
times_used: UseCount,
|
||||
|
||||
expires_at: ?DateTime,
|
||||
max_uses: ?UseCount,
|
||||
|
||||
kind: Kind,
|
||||
};
|
||||
pub const Kind = enum {
|
||||
system,
|
||||
community_owner,
|
||||
user,
|
||||
|
||||
pub const jsonStringify = util.jsonSerializeEnumAsString;
|
||||
};
|
||||
pub const CreateOptions = struct {
|
||||
name: ?[]const u8 = null,
|
||||
max_uses: ?UseCount = null,
|
||||
lifespan: ?DateTime.Duration = null,
|
||||
kind: Kind = .user,
|
||||
to_community: ?Uuid = null,
|
||||
};
|
||||
|
||||
pub const InternalCreateOptions = struct {
|
||||
name: ?[]const u8 = null,
|
||||
max_uses: ?UseCount = null,
|
||||
lifespan: ?DateTime.Duration = null,
|
||||
kind: Kind = .user,
|
||||
};
|
||||
};
|
||||
|
||||
pub const follows = struct {
|
||||
pub const Follow = struct {
|
||||
id: Uuid,
|
||||
|
||||
followed_by_id: Uuid,
|
||||
followee_id: Uuid,
|
||||
|
||||
created_at: DateTime,
|
||||
};
|
||||
pub const QueryArgs = struct {
|
||||
pub const OrderBy = enum {
|
||||
created_at,
|
||||
};
|
||||
|
||||
pub const Direction = common.Direction;
|
||||
pub const PageDirection = common.PageDirection;
|
||||
pub const Prev = struct {
|
||||
id: Uuid,
|
||||
order_val: union(OrderBy) {
|
||||
created_at: DateTime,
|
||||
},
|
||||
};
|
||||
|
||||
max_items: usize = 20,
|
||||
|
||||
followed_by_id: ?Uuid = null,
|
||||
followee_id: ?Uuid = null,
|
||||
|
||||
order_by: OrderBy = .created_at,
|
||||
|
||||
direction: Direction = .descending,
|
||||
|
||||
prev: ?Prev = null,
|
||||
|
||||
page_direction: PageDirection = .forward,
|
||||
};
|
||||
|
||||
pub const QueryResult = common.QueryResult(Follow, QueryArgs);
|
||||
};
|
||||
|
||||
pub const notes = struct {
|
||||
pub const Note = struct {
|
||||
id: Uuid,
|
||||
|
||||
author_id: actors.Actor, // TODO
|
||||
content: []const u8,
|
||||
created_at: DateTime,
|
||||
|
||||
// TODO: This sucks
|
||||
pub const sql_serialize = struct {
|
||||
pub const @"author.profile_fields" = .json;
|
||||
};
|
||||
};
|
||||
pub const QueryArgs = struct {
|
||||
pub const PageDirection = common.PageDirection;
|
||||
pub const Prev = struct {
|
||||
id: Uuid,
|
||||
created_at: DateTime,
|
||||
};
|
||||
|
||||
max_items: usize = 20,
|
||||
|
||||
created_before: ?DateTime = null,
|
||||
created_after: ?DateTime = null,
|
||||
community_id: ?Uuid = null,
|
||||
followed_by: ?Uuid = null,
|
||||
|
||||
prev: ?Prev = null,
|
||||
|
||||
page_direction: PageDirection = .forward,
|
||||
};
|
||||
pub const QueryResult = common.QueryResult(Note, QueryArgs);
|
||||
};
|
||||
|
||||
pub const tokens = struct {
|
||||
pub const Token = struct {
|
||||
account_id: Uuid,
|
||||
issued_at: DateTime,
|
||||
|
||||
hash: []const u8,
|
||||
};
|
||||
};
|
|
@ -1,362 +1,5 @@
|
|||
const util = @import("util");
|
||||
const services = @import("../services.zig");
|
||||
|
||||
const Uuid = util.Uuid;
|
||||
const DateTime = util.DateTime;
|
||||
|
||||
const common = struct {
|
||||
const Direction = enum {
|
||||
ascending,
|
||||
descending,
|
||||
|
||||
pub const jsonStringify = util.jsonSerializeEnumAsString;
|
||||
};
|
||||
|
||||
const PageDirection = enum {
|
||||
forward,
|
||||
backward,
|
||||
|
||||
pub const jsonStringify = util.jsonSerializeEnumAsString;
|
||||
};
|
||||
};
|
||||
|
||||
pub fn QueryResult(comptime T: type) type {
|
||||
return QueryResultArguments(T, T.QueryArgs);
|
||||
}
|
||||
|
||||
pub fn QueryResultArguments(comptime T: type, comptime A: type) type {
|
||||
return struct {
|
||||
items: []T,
|
||||
|
||||
next_page: A,
|
||||
prev_page: A,
|
||||
};
|
||||
}
|
||||
|
||||
pub const Account = struct {
|
||||
pub const Auth = struct {
|
||||
password_hash: []const u8,
|
||||
updated_at: DateTime,
|
||||
};
|
||||
pub const Kind = enum {
|
||||
user,
|
||||
admin,
|
||||
};
|
||||
|
||||
id: Uuid,
|
||||
invite_id: ?Uuid,
|
||||
email: ?[]const u8,
|
||||
kind: Kind,
|
||||
};
|
||||
|
||||
pub const Actor = struct {
|
||||
pub const ProfileField = struct {
|
||||
key: []const u8,
|
||||
value: []const u8,
|
||||
};
|
||||
|
||||
id: Uuid,
|
||||
|
||||
username: []const u8,
|
||||
host: []const u8,
|
||||
community_id: Uuid,
|
||||
|
||||
display_name: ?[]const u8,
|
||||
bio: []const u8,
|
||||
|
||||
avatar_file_id: ?Uuid,
|
||||
header_file_id: ?Uuid,
|
||||
|
||||
profile_fields: []const ProfileField,
|
||||
|
||||
created_at: DateTime,
|
||||
updated_at: DateTime,
|
||||
|
||||
// TODO: get rid of this
|
||||
pub const Profile = struct {
|
||||
display_name: ?[]const u8,
|
||||
bio: []const u8,
|
||||
avatar_file_id: ?Uuid,
|
||||
header_file_id: ?Uuid,
|
||||
profile_fields: []const ProfileField,
|
||||
|
||||
pub const sql_serialize = struct {
|
||||
pub const profile_fields = .json;
|
||||
};
|
||||
};
|
||||
|
||||
pub const ProfileUpdateArgs = struct {
|
||||
display_name: ??[]const u8,
|
||||
bio: ?[]const u8,
|
||||
avatar_file_id: ??Uuid,
|
||||
header_file_id: ??Uuid,
|
||||
profile_fields: ?[]const ProfileField,
|
||||
|
||||
pub const sql_serialize = struct {
|
||||
pub const profile_fields = .json;
|
||||
};
|
||||
};
|
||||
|
||||
pub const sql_serialize = struct {
|
||||
pub const profile_fields = .json;
|
||||
};
|
||||
};
|
||||
|
||||
pub const Community = struct {
|
||||
pub const Kind = enum {
|
||||
admin,
|
||||
local,
|
||||
|
||||
pub const jsonStringify = util.jsonSerializeEnumAsString;
|
||||
};
|
||||
|
||||
pub const Scheme = enum {
|
||||
https,
|
||||
http,
|
||||
|
||||
pub const jsonStringify = util.jsonSerializeEnumAsString;
|
||||
};
|
||||
|
||||
id: Uuid,
|
||||
|
||||
owner_id: ?Uuid,
|
||||
host: []const u8,
|
||||
name: []const u8,
|
||||
|
||||
scheme: Scheme,
|
||||
kind: Kind,
|
||||
created_at: DateTime,
|
||||
|
||||
pub const CreateOptions = struct {
|
||||
name: ?[]const u8 = null,
|
||||
kind: Kind = .local,
|
||||
};
|
||||
|
||||
pub const QueryArgs = struct {
|
||||
pub const OrderBy = enum {
|
||||
name,
|
||||
host,
|
||||
created_at,
|
||||
|
||||
pub const jsonStringify = util.jsonSerializeEnumAsString;
|
||||
};
|
||||
|
||||
pub const Direction = common.Direction;
|
||||
pub const PageDirection = common.PageDirection;
|
||||
pub const Prev = struct {
|
||||
id: Uuid,
|
||||
order_val: OrderVal,
|
||||
};
|
||||
pub const OrderVal = union(OrderBy) {
|
||||
name: []const u8,
|
||||
host: []const u8,
|
||||
created_at: DateTime,
|
||||
};
|
||||
|
||||
// Max items to fetch
|
||||
max_items: usize = 20,
|
||||
|
||||
// Selection filters
|
||||
owner_id: ?Uuid = null, // searches for communities owned by this user
|
||||
like: ?[]const u8 = null, // searches for communities with host or name LIKE '%?%'
|
||||
created_before: ?DateTime = null,
|
||||
created_after: ?DateTime = null,
|
||||
|
||||
// Ordering parameter
|
||||
order_by: OrderBy = .created_at,
|
||||
direction: Direction = .ascending,
|
||||
|
||||
// Page start parameter(s)
|
||||
// This struct is a reference to the last value scanned
|
||||
// If prev is present, then prev.order_val must have the same tag as order_by
|
||||
// "prev" here refers to it being the previous value returned. It may be that
|
||||
// prev refers to the item directly after the results you are about to recieve,
|
||||
// if you are querying the previous page.
|
||||
prev: ?Prev = null,
|
||||
|
||||
// What direction to scan the page window
|
||||
// If "forward", then "prev" is interpreted as the item directly before the items
|
||||
// to query, in the direction of "direction" above. If "backward", then the opposite
|
||||
page_direction: PageDirection = .forward,
|
||||
};
|
||||
};
|
||||
|
||||
pub const DriveEntry = struct {
|
||||
pub const Kind = enum {
|
||||
dir,
|
||||
file,
|
||||
|
||||
pub const jsonStringify = util.jsonSerializeEnumAsString;
|
||||
};
|
||||
|
||||
id: Uuid,
|
||||
owner_id: Uuid,
|
||||
|
||||
name: ?[]const u8,
|
||||
|
||||
path: []const u8,
|
||||
parent_directory_id: ?Uuid,
|
||||
|
||||
file_id: ?Uuid,
|
||||
kind: Kind,
|
||||
};
|
||||
|
||||
pub const FileUpload = struct {
|
||||
pub const Status = enum {
|
||||
uploading,
|
||||
uploaded,
|
||||
external,
|
||||
deleted,
|
||||
|
||||
pub const jsonStringify = util.jsonSerializeEnumAsString;
|
||||
};
|
||||
|
||||
id: Uuid,
|
||||
|
||||
owner_id: Uuid,
|
||||
size: usize,
|
||||
|
||||
filename: []const u8,
|
||||
description: ?[]const u8,
|
||||
content_type: ?[]const u8,
|
||||
sensitive: bool,
|
||||
|
||||
status: Status,
|
||||
|
||||
created_at: DateTime,
|
||||
updated_at: DateTime,
|
||||
|
||||
pub const CreateOptions = struct {
|
||||
filename: []const u8,
|
||||
description: ?[]const u8,
|
||||
content_type: ?[]const u8,
|
||||
sensitive: bool,
|
||||
};
|
||||
|
||||
pub const UpdateArgs = struct {
|
||||
filename: ?[]const u8,
|
||||
description: ?[]const u8,
|
||||
content_type: ?[]const u8,
|
||||
sensitive: ?bool,
|
||||
};
|
||||
};
|
||||
|
||||
pub const Invite = struct {
|
||||
const UseCount = usize;
|
||||
|
||||
pub const Kind = enum {
|
||||
system,
|
||||
community_owner,
|
||||
user,
|
||||
|
||||
pub const jsonStringify = util.jsonSerializeEnumAsString;
|
||||
};
|
||||
|
||||
id: Uuid,
|
||||
|
||||
created_by: Uuid, // User ID
|
||||
community_id: Uuid,
|
||||
name: []const u8,
|
||||
code: []const u8,
|
||||
|
||||
created_at: DateTime,
|
||||
times_used: UseCount,
|
||||
|
||||
expires_at: ?DateTime,
|
||||
max_uses: ?UseCount,
|
||||
|
||||
kind: Kind,
|
||||
|
||||
pub const CreateOptions = struct {
|
||||
name: ?[]const u8 = null,
|
||||
max_uses: ?UseCount = null,
|
||||
lifespan: ?DateTime.Duration = null,
|
||||
kind: Kind = .user,
|
||||
to_community: ?Uuid = null,
|
||||
};
|
||||
|
||||
pub const InternalCreateOptions = struct {
|
||||
name: ?[]const u8 = null,
|
||||
max_uses: ?UseCount = null,
|
||||
lifespan: ?DateTime.Duration = null,
|
||||
kind: Kind = .user,
|
||||
};
|
||||
};
|
||||
|
||||
pub const Follow = struct {
|
||||
id: Uuid,
|
||||
|
||||
followed_by_id: Uuid,
|
||||
followee_id: Uuid,
|
||||
|
||||
created_at: DateTime,
|
||||
|
||||
pub const QueryArgs = struct {
|
||||
pub const OrderBy = enum {
|
||||
created_at,
|
||||
};
|
||||
|
||||
pub const Direction = common.Direction;
|
||||
pub const PageDirection = common.PageDirection;
|
||||
pub const Prev = struct {
|
||||
id: Uuid,
|
||||
order_val: union(OrderBy) {
|
||||
created_at: DateTime,
|
||||
},
|
||||
};
|
||||
|
||||
max_items: usize = 20,
|
||||
|
||||
followed_by_id: ?Uuid = null,
|
||||
followee_id: ?Uuid = null,
|
||||
|
||||
order_by: OrderBy = .created_at,
|
||||
|
||||
direction: Direction = .descending,
|
||||
|
||||
prev: ?Prev = null,
|
||||
|
||||
page_direction: PageDirection = .forward,
|
||||
};
|
||||
};
|
||||
|
||||
pub const Note = struct {
|
||||
id: Uuid,
|
||||
|
||||
author: Actor,
|
||||
content: []const u8,
|
||||
created_at: DateTime,
|
||||
|
||||
pub const QueryArgs = struct {
|
||||
pub const PageDirection = common.PageDirection;
|
||||
pub const Prev = struct {
|
||||
id: Uuid,
|
||||
created_at: DateTime,
|
||||
};
|
||||
|
||||
max_items: usize = 20,
|
||||
|
||||
created_before: ?DateTime = null,
|
||||
created_after: ?DateTime = null,
|
||||
community_id: ?Uuid = null,
|
||||
followed_by: ?Uuid = null,
|
||||
|
||||
prev: ?Prev = null,
|
||||
|
||||
page_direction: PageDirection = .forward,
|
||||
};
|
||||
|
||||
// TODO: This sucks
|
||||
pub const sql_serialize = struct {
|
||||
pub const @"author.profile_fields" = .json;
|
||||
};
|
||||
};
|
||||
|
||||
pub const Token = struct {
|
||||
pub const Info = struct {
|
||||
user_id: Uuid,
|
||||
issued_at: DateTime,
|
||||
};
|
||||
|
||||
value: []const u8,
|
||||
info: Info,
|
||||
pub const actors = struct {
|
||||
pub const Actor = services.actors.Actor;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue