From 783e3699e865f367dc736617085c909608de8a10 Mon Sep 17 00:00:00 2001 From: jaina heartles Date: Sat, 10 Dec 2022 01:42:07 -0800 Subject: [PATCH] Create signup page --- src/main/controllers/web.zig | 99 +++++++++++++++++++++++ src/main/controllers/web/signup.tmpl.html | 54 +++++++++++++ static/site.css | 4 + 3 files changed, 157 insertions(+) create mode 100644 src/main/controllers/web/signup.tmpl.html diff --git a/src/main/controllers/web.zig b/src/main/controllers/web.zig index 0a05d33..7910d71 100644 --- a/src/main/controllers/web.zig +++ b/src/main/controllers/web.zig @@ -1,5 +1,6 @@ const std = @import("std"); const util = @import("util"); +const http = @import("http"); const controllers = @import("../controllers.zig"); pub const routes = .{ @@ -10,6 +11,9 @@ pub const routes = .{ controllers.apiEndpoint(cluster.overview), controllers.apiEndpoint(media), controllers.apiEndpoint(static), + controllers.apiEndpoint(signup.page), + controllers.apiEndpoint(signup.with_invite), + controllers.apiEndpoint(signup.submit), }; const static = struct { @@ -94,6 +98,101 @@ const login = struct { } }; +const signup = struct { + const tmpl = @embedFile("./web/signup.tmpl.html"); + + fn servePage( + invite_code: ?[]const u8, + error_msg: ?[]const u8, + status: http.Status, + res: anytype, + srv: anytype, + ) !void { + const invite = if (invite_code) |code| srv.validateInvite(code) catch |err| switch (err) { + error.InvalidInvite => return servePage(null, "Invite is not valid", .bad_request, res, srv), + else => |e| return e, + } else null; + defer util.deepFree(srv.allocator, invite); + + try res.template(status, srv, tmpl, .{ + .error_msg = error_msg, + .invite = invite, + }); + } + + const page = struct { + pub const path = "/signup"; + pub const method = .GET; + + pub fn handler(_: anytype, res: anytype, srv: anytype) !void { + try servePage(null, null, .ok, res, srv); + } + }; + + const with_invite = struct { + pub const path = "/invite/:code"; + pub const method = .GET; + + pub const Args = struct { + code: []const u8, + }; + + pub fn handler(req: anytype, res: anytype, srv: anytype) !void { + std.log.debug("{s}", .{req.args.code}); + try servePage(req.args.code, null, .ok, res, srv); + } + }; + + const submit = struct { + pub const path = "/signup"; + pub const method = .POST; + + pub const Body = struct { + username: []const u8, + password: []const u8, + email: ?[]const u8 = null, + invite_code: ?[]const u8 = null, + }; + + pub fn handler(req: anytype, res: anytype, srv: anytype) !void { + const user = srv.register(req.body.username, req.body.password, .{ + .email = req.body.email, + .invite_code = req.body.invite_code, + }) catch |err| { + var status: http.Status = .bad_request; + const err_msg = switch (err) { + error.UsernameEmpty => "Username cannot be empty", + error.UsernameContainsInvalidChar => "Username must be composed of alphanumeric characters and underscore", + error.UsernameTooLong => "Username too long", + error.PasswordTooShort => "Password too short, must be at least 12 chars", + + error.UsernameTaken => blk: { + status = .unprocessable_entity; + break :blk "Username is already registered"; + }, + else => blk: { + status = .internal_server_error; + break :blk "an internal error occurred"; + }, + }; + + return servePage(req.body.invite_code, err_msg, status, res, srv); + }; + defer util.deepFree(srv.allocator, user); + + const token = try srv.login(req.body.username, req.body.password); + + try res.headers.put("Location", index.path); + var buf: [64]u8 = undefined; + const cookie_name = try std.fmt.bufPrint(&buf, "token.{s}", .{req.body.username}); + try res.headers.setCookie(cookie_name, token.token, .{}); + try res.headers.setCookie("active_account", req.body.username, .{ .HttpOnly = false }); + + try res.status(.see_other); + } + }; +}; + const global_timeline = struct { pub const path = "/timelines/global"; pub const method = .GET; diff --git a/src/main/controllers/web/signup.tmpl.html b/src/main/controllers/web/signup.tmpl.html new file mode 100644 index 0000000..f9a9254 --- /dev/null +++ b/src/main/controllers/web/signup.tmpl.html @@ -0,0 +1,54 @@ +
+

{ %community.name }

+
+
+

Sign Up

+ {#if .error_msg |$msg| =} +
Error: {$msg}
+ {= /if} + {#if .invite |$invite| =} +
+
You are about to accept an invite from:
+
+
+ {=#if $invite.creator.display_name |$name|=} + {$name} + {= #else =} + {$invite.creator.username} + {= /if =} +
+
@{$invite.creator.username}@{$invite.creator.host}
+
+ {#if @isTag($invite.kind, community_owner) =} +
This act will make your new account the owner of { %community.name }
+ {/if =} +
+ {=/if} + + + + {#if .invite |$invite| =} + + {/if =} + +
diff --git a/static/site.css b/static/site.css index fea8141..2eff495 100644 --- a/static/site.css +++ b/static/site.css @@ -92,6 +92,10 @@ form[action*=login] .textinput span.suffix { outline: none; } +.form-helpinfo { + font-size: small; +} + button, a.button { padding: 5px; border-radius: 10px;