2022-04-02 20:23:18 +00:00
const std = @import ( " std " ) ;
2022-07-10 22:19:21 +00:00
const builtin = @import ( " builtin " ) ;
2022-09-15 01:12:07 +00:00
const sql = @import ( " sql " ) ;
2022-07-09 22:07:51 +00:00
const http = @import ( " http " ) ;
2022-07-13 04:16:33 +00:00
const util = @import ( " util " ) ;
2022-09-09 04:15:52 +00:00
pub const api = @import ( " ./api.zig " ) ;
2022-09-05 09:15:16 +00:00
const models = @import ( " ./db/models.zig " ) ;
2022-07-13 04:16:33 +00:00
const Uuid = util . Uuid ;
2022-07-13 07:57:21 +00:00
const c = @import ( " ./controllers.zig " ) ;
2022-07-10 05:05:01 +00:00
// this thing is overcomplicated and weird. stop this
const Router = http . Router ( * RequestServer ) ;
const Route = Router . Route ;
const RouteArgs = http . RouteArgs ;
const router = Router {
. routes = & [ _ ] Route {
2022-09-05 10:33:54 +00:00
Route . new ( . GET , " /healthcheck " , & c . healthcheck ) ,
2022-07-16 18:41:09 +00:00
2022-09-08 02:19:46 +00:00
prepare ( c . auth . login ) ,
prepare ( c . auth . verify_login ) ,
2022-07-17 23:21:03 +00:00
2022-09-08 02:19:46 +00:00
prepare ( c . communities . create ) ,
2022-09-07 23:14:52 +00:00
2022-09-08 05:10:58 +00:00
prepare ( c . invites . create ) ,
2022-09-07 23:14:52 +00:00
2022-09-08 06:56:29 +00:00
prepare ( c . users . create ) ,
2022-09-08 07:52:23 +00:00
prepare ( c . notes . create ) ,
prepare ( c . notes . get ) ,
2022-07-21 05:26:13 +00:00
2022-09-05 07:10:03 +00:00
//Route.new(.GET, "/notes/:id/reacts", &c.notes.reacts.list),
//Route.new(.POST, "/notes/:id/reacts", &c.notes.reacts.create),
2022-07-22 06:53:05 +00:00
2022-09-05 07:10:03 +00:00
//Route.new(.GET, "/actors/:id", &c.actors.get),
2022-07-27 05:02:09 +00:00
2022-09-05 07:10:03 +00:00
//Route.new(.GET, "/admin/invites/:id", &c.admin.invites.get),
2022-08-02 04:33:23 +00:00
2022-09-05 07:10:03 +00:00
//Route.new(.GET, "/admin/communities/:host", &c.admin.communities.get),
2022-07-10 05:05:01 +00:00
} ,
} ;
2022-09-08 02:19:46 +00:00
fn prepare ( comptime route_desc : type ) Route {
return Route . new ( route_desc . method , route_desc . path , & route_desc . handler ) ;
}
2022-07-13 07:57:21 +00:00
pub const RequestServer = struct {
2022-07-10 05:05:01 +00:00
alloc : std . mem . Allocator ,
2022-09-09 04:15:52 +00:00
api : * api . ApiSource ,
2022-07-30 06:14:42 +00:00
config : Config ,
2022-07-10 05:05:01 +00:00
2022-09-09 04:15:52 +00:00
fn init ( alloc : std . mem . Allocator , src : * api . ApiSource , config : Config ) ! RequestServer {
2022-07-10 05:05:01 +00:00
return RequestServer {
. alloc = alloc ,
2022-09-09 04:15:52 +00:00
. api = src ,
2022-07-30 06:14:42 +00:00
. config = config ,
2022-07-10 05:05:01 +00:00
} ;
}
2022-07-18 07:37:10 +00:00
fn listenAndRun ( self : * RequestServer , addr : std . net . Address ) ! void {
2022-07-10 01:01:03 +00:00
var srv = http . Server . listen ( addr ) catch unreachable ;
defer srv . shutdown ( ) ;
2022-04-04 03:36:32 +00:00
2022-07-10 01:01:03 +00:00
while ( true ) {
2022-07-21 05:26:13 +00:00
const buf = try self . alloc . alloc ( u8 , 1 < < 28 ) ; // 4mb
defer self . alloc . free ( buf ) ;
var fba = std . heap . FixedBufferAllocator . init ( buf ) ;
2022-07-10 01:01:03 +00:00
const alloc = fba . allocator ( ) ;
2022-04-02 20:23:18 +00:00
2022-07-18 07:37:10 +00:00
var ctx = try srv . accept ( alloc ) ;
2022-07-10 01:01:03 +00:00
defer ctx . close ( ) ;
2022-04-21 09:34:04 +00:00
2022-07-11 00:48:54 +00:00
router . dispatch ( self , & ctx , ctx . request . method , ctx . request . path ) catch | err | switch ( err ) {
2022-07-13 07:57:21 +00:00
error . NotFound , error . RouteNotApplicable = > c . notFound ( self , & ctx ) ,
2022-08-02 06:24:16 +00:00
else = > {
2022-09-07 23:14:52 +00:00
std . log . err ( " Unhandled error in controller ({s}): {} \n Stack Trace \n {?} " , . { ctx . request . path , err , @errorReturnTrace ( ) } ) ;
2022-08-02 06:24:16 +00:00
c . internalServerError ( self , & ctx ) ;
} ,
2022-07-11 00:48:54 +00:00
} ;
2022-07-10 01:01:03 +00:00
}
}
} ;
2022-07-30 06:14:42 +00:00
pub const Config = struct {
2022-09-05 08:52:49 +00:00
cluster_host : [ ] const u8 ,
2022-09-15 01:12:07 +00:00
db : sql . Config ,
2022-09-09 04:15:52 +00:00
root_password : ? [ ] const u8 = null ,
2022-07-30 06:14:42 +00:00
} ;
fn loadConfig ( alloc : std . mem . Allocator ) ! Config {
var file = try std . fs . cwd ( ) . openFile ( " config.json " , . { } ) ;
defer file . close ( ) ;
const bytes = try file . reader ( ) . readAllAlloc ( alloc , 1 < < 63 ) ;
defer alloc . free ( bytes ) ;
var ts = std . json . TokenStream . init ( bytes ) ;
return std . json . parse ( Config , & ts , . { . allocator = alloc } ) ;
}
2022-09-09 04:15:52 +00:00
const root_password_envvar = " CLUSTER_ROOT_PASSWORD " ;
2022-07-10 01:01:03 +00:00
pub fn main ( ) anyerror ! void {
2022-07-10 05:05:01 +00:00
var gpa = std . heap . GeneralPurposeAllocator ( . { } ) { } ;
2022-09-09 04:15:52 +00:00
var cfg = try loadConfig ( gpa . allocator ( ) ) ;
2022-09-15 01:12:07 +00:00
var db_conn = try sql . Db . open ( cfg . db ) ;
2022-09-25 08:10:30 +00:00
var api_src = api . ApiSource . init ( gpa . allocator ( ) , cfg , std . os . getenv ( root_password_envvar ) , & db_conn ) catch | err | switch ( err ) {
2022-09-09 04:15:52 +00:00
error . NeedRootPassword = > {
std . log . err (
" No root user created and no password specified. Please provide the password for the root user by the ${s} environment variable for initial startup. This only needs to be done once " ,
. { root_password_envvar } ,
) ;
return err ;
} ,
else = > return err ,
} ;
var srv = try RequestServer . init ( gpa . allocator ( ) , & api_src , cfg ) ;
2022-07-25 00:18:25 +00:00
api . initThreadPrng ( @bitCast ( u64 , std . time . milliTimestamp ( ) ) ) ;
2022-07-18 07:37:10 +00:00
return srv . listenAndRun ( std . net . Address . parseIp ( " 0.0.0.0 " , 8080 ) catch unreachable ) ;
2022-05-20 04:46:39 +00:00
}