Move api to package
This commit is contained in:
parent
1aec8031e6
commit
581159963f
14 changed files with 43 additions and 74 deletions
|
@ -17,10 +17,16 @@ const sql_pkg = std.build.Pkg{
|
||||||
.dependencies = &.{util_pkg},
|
.dependencies = &.{util_pkg},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const api_pkg = std.build.Pkg{
|
||||||
|
.name = "api",
|
||||||
|
.source = std.build.FileSource.relative("src/api/lib.zig"),
|
||||||
|
.dependencies = &.{ util_pkg, sql_pkg },
|
||||||
|
};
|
||||||
|
|
||||||
const main_pkg = std.build.Pkg{
|
const main_pkg = std.build.Pkg{
|
||||||
.name = "main",
|
.name = "main",
|
||||||
.source = std.build.FileSource.relative("src/main/main.zig"),
|
.source = std.build.FileSource.relative("src/main/main.zig"),
|
||||||
.dependencies = &.{ util_pkg, http_pkg, sql_pkg },
|
.dependencies = &.{ util_pkg, http_pkg, sql_pkg, api_pkg },
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn build(b: *std.build.Builder) void {
|
pub fn build(b: *std.build.Builder) void {
|
||||||
|
@ -41,6 +47,7 @@ pub fn build(b: *std.build.Builder) void {
|
||||||
exe.addPackage(sql_pkg);
|
exe.addPackage(sql_pkg);
|
||||||
exe.addPackage(util_pkg);
|
exe.addPackage(util_pkg);
|
||||||
exe.addPackage(http_pkg);
|
exe.addPackage(http_pkg);
|
||||||
|
exe.addPackage(api_pkg);
|
||||||
|
|
||||||
exe.linkSystemLibrary("sqlite3");
|
exe.linkSystemLibrary("sqlite3");
|
||||||
exe.linkSystemLibrary("pq");
|
exe.linkSystemLibrary("pq");
|
||||||
|
|
|
@ -1,18 +1,16 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const util = @import("util");
|
const util = @import("util");
|
||||||
const builtin = @import("builtin");
|
|
||||||
const sql = @import("sql");
|
const sql = @import("sql");
|
||||||
|
|
||||||
const DateTime = util.DateTime;
|
const DateTime = util.DateTime;
|
||||||
const Uuid = util.Uuid;
|
const Uuid = util.Uuid;
|
||||||
const Config = @import("./main.zig").Config;
|
|
||||||
|
|
||||||
const services = struct {
|
const services = struct {
|
||||||
const communities = @import("./api/communities.zig");
|
const communities = @import("./services/communities.zig");
|
||||||
const users = @import("./api/users.zig");
|
const users = @import("./services/users.zig");
|
||||||
const auth = @import("./api/auth.zig");
|
const auth = @import("./services/auth.zig");
|
||||||
const invites = @import("./api/invites.zig");
|
const invites = @import("./services/invites.zig");
|
||||||
const notes = @import("./api/notes.zig");
|
const notes = @import("./services/notes.zig");
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const RegistrationRequest = struct {
|
pub const RegistrationRequest = struct {
|
||||||
|
@ -59,38 +57,6 @@ pub const NoteResponse = struct {
|
||||||
|
|
||||||
pub const CommunityQueryArgs = services.communities.QueryArgs;
|
pub const CommunityQueryArgs = services.communities.QueryArgs;
|
||||||
|
|
||||||
// Frees an api struct and its fields allocated from alloc
|
|
||||||
pub fn free(alloc: std.mem.Allocator, val: anytype) void {
|
|
||||||
switch (@typeInfo(@TypeOf(val))) {
|
|
||||||
.Pointer => |ptr_info| switch (ptr_info.size) {
|
|
||||||
.One => {
|
|
||||||
free(alloc, val.*);
|
|
||||||
alloc.destroy(val);
|
|
||||||
},
|
|
||||||
.Slice => {
|
|
||||||
for (val) |elem| free(alloc, elem);
|
|
||||||
alloc.free(val);
|
|
||||||
},
|
|
||||||
else => unreachable,
|
|
||||||
},
|
|
||||||
.Struct => inline for (std.meta.fields(@TypeOf(val))) |f| free(alloc, @field(val, f.name)),
|
|
||||||
.Array => for (val) |elem| free(alloc, elem),
|
|
||||||
.Optional => if (val) |opt| free(alloc, opt),
|
|
||||||
.Bool, .Int, .Float, .Enum => {},
|
|
||||||
else => unreachable,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
threadlocal var prng: std.rand.DefaultPrng = undefined;
|
|
||||||
|
|
||||||
pub fn initThreadPrng(seed: u64) void {
|
|
||||||
prng = std.rand.DefaultPrng.init(seed +% std.Thread.getCurrentId());
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn getRandom() std.rand.Random {
|
|
||||||
return prng.random();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn isAdminSetup(db: sql.Db) !bool {
|
pub fn isAdminSetup(db: sql.Db) !bool {
|
||||||
_ = services.communities.adminCommunityId(db) catch |err| switch (err) {
|
_ = services.communities.adminCommunityId(db) catch |err| switch (err) {
|
||||||
error.NotFound => return false,
|
error.NotFound => return false,
|
||||||
|
@ -129,16 +95,14 @@ pub fn setupAdmin(db: sql.Db, origin: []const u8, username: []const u8, password
|
||||||
|
|
||||||
pub const ApiSource = struct {
|
pub const ApiSource = struct {
|
||||||
db_conn: *sql.Conn,
|
db_conn: *sql.Conn,
|
||||||
config: Config,
|
|
||||||
|
|
||||||
pub const Conn = ApiConn(sql.Db);
|
pub const Conn = ApiConn(sql.Db);
|
||||||
|
|
||||||
const root_username = "root";
|
const root_username = "root";
|
||||||
|
|
||||||
pub fn init(cfg: Config, db_conn: *sql.Conn) !ApiSource {
|
pub fn init(db_conn: *sql.Conn) !ApiSource {
|
||||||
return ApiSource{
|
return ApiSource{
|
||||||
.db_conn = db_conn,
|
.db_conn = db_conn,
|
||||||
.config = cfg,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,6 @@ const builtin = @import("builtin");
|
||||||
const util = @import("util");
|
const util = @import("util");
|
||||||
const sql = @import("sql");
|
const sql = @import("sql");
|
||||||
|
|
||||||
const getRandom = @import("../api.zig").getRandom;
|
|
||||||
|
|
||||||
const Uuid = util.Uuid;
|
const Uuid = util.Uuid;
|
||||||
const DateTime = util.DateTime;
|
const DateTime = util.DateTime;
|
||||||
|
|
||||||
|
@ -70,7 +68,7 @@ pub fn create(db: anytype, origin: []const u8, options: CreateOptions, alloc: st
|
||||||
// Require TLS on production builds
|
// Require TLS on production builds
|
||||||
if (scheme != .https and builtin.mode != .Debug) return error.UnsupportedScheme;
|
if (scheme != .https and builtin.mode != .Debug) return error.UnsupportedScheme;
|
||||||
|
|
||||||
const id = Uuid.randV4(getRandom());
|
const id = Uuid.randV4(util.getThreadPrng());
|
||||||
|
|
||||||
// TODO: wrap this in TX
|
// TODO: wrap this in TX
|
||||||
if (db.queryRow(
|
if (db.queryRow(
|
|
@ -1,7 +1,6 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const builtin = @import("builtin");
|
const builtin = @import("builtin");
|
||||||
const util = @import("util");
|
const util = @import("util");
|
||||||
const getRandom = @import("../api.zig").getRandom;
|
|
||||||
|
|
||||||
const Uuid = util.Uuid;
|
const Uuid = util.Uuid;
|
||||||
const DateTime = util.DateTime;
|
const DateTime = util.DateTime;
|
||||||
|
@ -47,10 +46,10 @@ pub const InviteOptions = struct {
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn create(db: anytype, created_by: Uuid, community_id: ?Uuid, options: InviteOptions, alloc: std.mem.Allocator) !Uuid {
|
pub fn create(db: anytype, created_by: Uuid, community_id: ?Uuid, options: InviteOptions, alloc: std.mem.Allocator) !Uuid {
|
||||||
const id = Uuid.randV4(getRandom());
|
const id = Uuid.randV4(util.getThreadPrng());
|
||||||
|
|
||||||
var code_bytes: [rand_len]u8 = undefined;
|
var code_bytes: [rand_len]u8 = undefined;
|
||||||
getRandom().bytes(&code_bytes);
|
util.getThreadPrng().bytes(&code_bytes);
|
||||||
|
|
||||||
const code = try alloc.alloc(u8, code_len);
|
const code = try alloc.alloc(u8, code_len);
|
||||||
defer alloc.free(code);
|
defer alloc.free(code);
|
|
@ -4,7 +4,6 @@ const sql = @import("sql");
|
||||||
|
|
||||||
const Uuid = util.Uuid;
|
const Uuid = util.Uuid;
|
||||||
const DateTime = util.DateTime;
|
const DateTime = util.DateTime;
|
||||||
const getRandom = @import("../api.zig").getRandom;
|
|
||||||
|
|
||||||
pub const Note = struct {
|
pub const Note = struct {
|
||||||
id: Uuid,
|
id: Uuid,
|
||||||
|
@ -23,7 +22,7 @@ pub fn create(
|
||||||
content: []const u8,
|
content: []const u8,
|
||||||
alloc: std.mem.Allocator,
|
alloc: std.mem.Allocator,
|
||||||
) CreateError!Uuid {
|
) CreateError!Uuid {
|
||||||
const id = Uuid.randV4(getRandom());
|
const id = Uuid.randV4(util.getThreadPrng());
|
||||||
|
|
||||||
db.insert("note", .{
|
db.insert("note", .{
|
||||||
.id = id,
|
.id = id,
|
|
@ -4,7 +4,6 @@ const auth = @import("./auth.zig");
|
||||||
|
|
||||||
const Uuid = util.Uuid;
|
const Uuid = util.Uuid;
|
||||||
const DateTime = util.DateTime;
|
const DateTime = util.DateTime;
|
||||||
const getRandom = @import("../api.zig").getRandom;
|
|
||||||
|
|
||||||
pub const CreateError = error{
|
pub const CreateError = error{
|
||||||
UsernameTaken,
|
UsernameTaken,
|
||||||
|
@ -81,7 +80,7 @@ pub fn create(
|
||||||
kind: Kind,
|
kind: Kind,
|
||||||
alloc: std.mem.Allocator,
|
alloc: std.mem.Allocator,
|
||||||
) CreateError!Uuid {
|
) CreateError!Uuid {
|
||||||
const id = Uuid.randV4(getRandom());
|
const id = Uuid.randV4(util.getThreadPrng());
|
||||||
|
|
||||||
try validateUsername(username);
|
try validateUsername(username);
|
||||||
|
|
|
@ -2,9 +2,8 @@ const std = @import("std");
|
||||||
const root = @import("root");
|
const root = @import("root");
|
||||||
const builtin = @import("builtin");
|
const builtin = @import("builtin");
|
||||||
const http = @import("http");
|
const http = @import("http");
|
||||||
const api = @import("./api.zig");
|
const api = @import("api");
|
||||||
const util = @import("util");
|
const util = @import("util");
|
||||||
const Uuid = util.Uuid;
|
|
||||||
|
|
||||||
pub const auth = @import("./controllers/auth.zig");
|
pub const auth = @import("./controllers/auth.zig");
|
||||||
pub const communities = @import("./controllers/communities.zig");
|
pub const communities = @import("./controllers/communities.zig");
|
||||||
|
|
|
@ -4,7 +4,6 @@ const builtin = @import("builtin");
|
||||||
const http = @import("http");
|
const http = @import("http");
|
||||||
const Uuid = @import("util").Uuid;
|
const Uuid = @import("util").Uuid;
|
||||||
|
|
||||||
const RegistrationInfo = @import("../api.zig").RegistrationInfo;
|
|
||||||
const utils = @import("../controllers.zig").utils;
|
const utils = @import("../controllers.zig").utils;
|
||||||
|
|
||||||
const RequestServer = root.RequestServer;
|
const RequestServer = root.RequestServer;
|
||||||
|
@ -20,7 +19,6 @@ pub const login = struct {
|
||||||
var api = try utils.getApiConn(srv, ctx);
|
var api = try utils.getApiConn(srv, ctx);
|
||||||
defer api.close();
|
defer api.close();
|
||||||
|
|
||||||
std.log.debug("connected to api", .{});
|
|
||||||
const token = try api.login(credentials.username, credentials.password);
|
const token = try api.login(credentials.username, credentials.password);
|
||||||
|
|
||||||
try utils.respondJson(ctx, .ok, token);
|
try utils.respondJson(ctx, .ok, token);
|
||||||
|
|
|
@ -15,7 +15,7 @@ pub const create = struct {
|
||||||
// TODO: get rid of this temporary struct, find json library that lets me extend
|
// TODO: get rid of this temporary struct, find json library that lets me extend
|
||||||
// it to parse UUIDs/etc in place
|
// it to parse UUIDs/etc in place
|
||||||
const InviteRequest = struct {
|
const InviteRequest = struct {
|
||||||
const Kind = @import("../api.zig").InviteRequest.Kind;
|
const Kind = @import("api").InviteRequest.Kind;
|
||||||
|
|
||||||
name: ?[]const u8 = null,
|
name: ?[]const u8 = null,
|
||||||
|
|
||||||
|
|
|
@ -3,13 +3,11 @@ const http = @import("http");
|
||||||
const Uuid = @import("util").Uuid;
|
const Uuid = @import("util").Uuid;
|
||||||
|
|
||||||
const utils = @import("../controllers.zig").utils;
|
const utils = @import("../controllers.zig").utils;
|
||||||
const NoteCreateInfo = @import("../api.zig").NoteCreateInfo;
|
const NoteCreateInfo = @import("api").NoteCreateInfo;
|
||||||
|
|
||||||
const RequestServer = root.RequestServer;
|
const RequestServer = root.RequestServer;
|
||||||
const RouteArgs = http.RouteArgs;
|
const RouteArgs = http.RouteArgs;
|
||||||
|
|
||||||
//pub const reacts = @import("./notes/reacts.zig");
|
|
||||||
|
|
||||||
pub const create = struct {
|
pub const create = struct {
|
||||||
pub const method = .POST;
|
pub const method = .POST;
|
||||||
pub const path = "/notes";
|
pub const path = "/notes";
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const root = @import("root");
|
const root = @import("root");
|
||||||
const builtin = @import("builtin");
|
|
||||||
const http = @import("http");
|
const http = @import("http");
|
||||||
const Uuid = @import("util").Uuid;
|
const Uuid = @import("util").Uuid;
|
||||||
|
|
||||||
const RegistrationRequest = @import("../api.zig").RegistrationRequest;
|
const RegistrationRequest = @import("api").RegistrationRequest;
|
||||||
const utils = @import("../controllers.zig").utils;
|
const utils = @import("../controllers.zig").utils;
|
||||||
|
|
||||||
const RequestServer = root.RequestServer;
|
const RequestServer = root.RequestServer;
|
||||||
|
|
|
@ -4,8 +4,8 @@ const sql = @import("sql");
|
||||||
const http = @import("http");
|
const http = @import("http");
|
||||||
const util = @import("util");
|
const util = @import("util");
|
||||||
|
|
||||||
pub const api = @import("./api.zig");
|
const api = @import("api");
|
||||||
pub const migrations = @import("./migrations.zig");
|
const migrations = @import("./migrations.zig");
|
||||||
const Uuid = util.Uuid;
|
const Uuid = util.Uuid;
|
||||||
const c = @import("./controllers.zig");
|
const c = @import("./controllers.zig");
|
||||||
|
|
||||||
|
@ -112,7 +112,6 @@ fn runAdminSetup(db: sql.Db, alloc: std.mem.Allocator) !void {
|
||||||
|
|
||||||
fn prepareDb(db: sql.Db, alloc: std.mem.Allocator) !void {
|
fn prepareDb(db: sql.Db, alloc: std.mem.Allocator) !void {
|
||||||
try migrations.up(db);
|
try migrations.up(db);
|
||||||
api.initThreadPrng(@bitCast(u64, std.time.milliTimestamp()));
|
|
||||||
|
|
||||||
if (!try api.isAdminSetup(db)) {
|
if (!try api.isAdminSetup(db)) {
|
||||||
std.log.info("Performing first-time admin creation...", .{});
|
std.log.info("Performing first-time admin creation...", .{});
|
||||||
|
@ -136,14 +135,14 @@ fn prepareDb(db: sql.Db, alloc: std.mem.Allocator) !void {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn main() !void {
|
pub fn main() !void {
|
||||||
|
try util.seedThreadPrng();
|
||||||
|
|
||||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||||
var cfg = try loadConfig(gpa.allocator());
|
var cfg = try loadConfig(gpa.allocator());
|
||||||
var db_conn = try sql.Conn.open(cfg.db);
|
var db_conn = try sql.Conn.open(cfg.db);
|
||||||
try prepareDb(try db_conn.acquire(), gpa.allocator());
|
try prepareDb(try db_conn.acquire(), gpa.allocator());
|
||||||
//try migrations.up(&db_conn);
|
|
||||||
//try api.setupAdmin(&db_conn, "http://localhost:8080", "root", "password", gpa.allocator());
|
|
||||||
|
|
||||||
var api_src = try api.ApiSource.init(cfg, &db_conn);
|
var api_src = try api.ApiSource.init(&db_conn);
|
||||||
var srv = try RequestServer.init(gpa.allocator(), &api_src, cfg);
|
var srv = try RequestServer.init(gpa.allocator(), &api_src, cfg);
|
||||||
return srv.listenAndRun(std.net.Address.parseIp("0.0.0.0", 8080) catch unreachable);
|
return srv.listenAndRun(std.net.Address.parseIp("0.0.0.0", 8080) catch unreachable);
|
||||||
}
|
}
|
||||||
|
|
|
@ -169,9 +169,19 @@ pub fn deepClone(alloc: std.mem.Allocator, val: anytype) !@TypeOf(val) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
test {
|
threadlocal var prng: ?std.rand.DefaultPrng = null;
|
||||||
_ = ciutf8;
|
|
||||||
_ = Uuid;
|
pub fn getThreadPrng() std.rand.Random {
|
||||||
_ = PathIter;
|
if (prng) |*p| return p.random();
|
||||||
_ = DateTime;
|
|
||||||
|
@panic("Thread PRNG not seeded");
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn seedThreadPrng() !void {
|
||||||
|
@setCold(true);
|
||||||
|
|
||||||
|
var buf: [8]u8 = undefined;
|
||||||
|
try std.os.getrandom(&buf);
|
||||||
|
|
||||||
|
prng = std.rand.DefaultPrng.init(@bitCast(u64, buf));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue