diff --git a/src/app/middleware/AuthMiddleware.zig b/src/app/middleware/AuthMiddleware.zig deleted file mode 100644 index e69de29..0000000 diff --git a/src/app/middleware/DemoMiddleware.zig b/src/app/middleware/DemoMiddleware.zig deleted file mode 100644 index adc6f9d..0000000 --- a/src/app/middleware/DemoMiddleware.zig +++ /dev/null @@ -1,82 +0,0 @@ -/// Demo middleware. Assign middleware by declaring `pub const middleware` in the -/// `jetzig_options` defined in your application's `src/main.zig`. -/// -/// Middleware is called before and after the request, providing full access to the active -/// request, allowing you to execute any custom code for logging, tracking, inserting response -/// headers, etc. -/// -/// This middleware is configured in the demo app's `src/main.zig`: -/// -/// ``` -/// pub const jetzig_options = struct { -/// pub const middleware: []const type = &.{@import("app/middleware/DemoMiddleware.zig")}; -/// }; -/// ``` -const std = @import("std"); -const jetzig = @import("jetzig"); - -const Zmd = @import("zmd").Zmd; -const fragments = @import("zmd").html.DefaultFragments; - -/// Define any custom data fields you want to store here. Assigning to these fields in the `init` -/// function allows you to access them in various middleware callbacks defined below, where they -/// can also be modified. -my_custom_value: []const u8, - -const DemoMiddleware = @This(); - -/// Initialize middleware. -pub fn init(request: *jetzig.http.Request) !*DemoMiddleware { - var middleware = try request.allocator.create(DemoMiddleware); - middleware.my_custom_value = "initial value"; - return middleware; -} - -/// Invoked immediately after the request is received but before it has started processing. -/// Any calls to `request.render` or `request.redirect` will prevent further processing of the -/// request, including any other middleware in the chain. -pub fn afterRequest(self: *DemoMiddleware, request: *jetzig.http.Request) !void { - // Middleware can invoke `request.redirect` or `request.render`. All request processing stops - // and the response is immediately returned if either of these two functions are called - // during middleware processing. - // _ = request.redirect("/foobar", .moved_permanently); - // _ = request.render(.unauthorized); - - try request.server.logger.DEBUG( - "[DemoMiddleware:afterRequest] my_custom_value: {s}", - .{self.my_custom_value}, - ); - self.my_custom_value = @tagName(request.method); -} - -/// Invoked immediately before the response renders to the client. -/// The response can be modified here if needed. -pub fn beforeResponse( - self: *DemoMiddleware, - request: *jetzig.http.Request, - response: *jetzig.http.Response, -) !void { - try request.server.logger.DEBUG( - "[DemoMiddleware:beforeResponse] my_custom_value: {s}, response status: {s}", - .{ self.my_custom_value, @tagName(response.status_code) }, - ); -} - -/// Invoked immediately after the response has been finalized and sent to the client. -/// Response data can be accessed for logging, but any modifications will have no impact. -pub fn afterResponse( - self: *DemoMiddleware, - request: *jetzig.http.Request, - response: *jetzig.http.Response, -) !void { - _ = self; - _ = response; - try request.server.logger.DEBUG("[DemoMiddleware:afterResponse] response completed", .{}); -} - -/// Invoked after `afterResponse` is called. Use this function to do any clean-up. -/// Note that `request.allocator` is an arena allocator, so any allocations are automatically -/// freed before the next request starts processing. -pub fn deinit(self: *DemoMiddleware, request: *jetzig.http.Request) void { - request.allocator.destroy(self); -} diff --git a/src/app/views/blogs.zig b/src/app/views/blogs.zig index ca6ba35..254e83d 100644 --- a/src/app/views/blogs.zig +++ b/src/app/views/blogs.zig @@ -76,6 +76,18 @@ pub fn index(request: *jetzig.Request) !jetzig.View { var root = try request.data(.object); try root.put("blogs", blogs); + const cookies = try request.cookies(); + const allowed = blk: { + const session = cookies.get("session") orelse break :blk false; + + const session_query = jetzig.database.Query(.Session) + .findBy(.{ .session_id = session.value }); + _ = request.repo.execute(session_query) catch break :blk false; + break :blk true; + }; + + try root.put("allowed", allowed); + return request.render(.ok); } @@ -120,19 +132,34 @@ pub fn new(request: *jetzig.Request) !jetzig.View { } pub fn post(request: *jetzig.Request) !jetzig.View { - const params = try request.params(); - - const title = params.getT(.string, "title") orelse { - return request.fail(.unprocessable_entity); + // check "session" cookie for authentication + const cookies = try request.cookies(); + const session = cookies.get("session") orelse { + return request.fail(.not_found); }; - const content = params.getT(.string, "content") orelse { - return request.fail(.unprocessable_entity); - }; + // check if session is valid + const query = jetzig.database.Query(.Session) + .findBy(.{ .session_id = session.value }); - try request.repo.insert(.Blog, .{ .title = title, .content = content }); + if (try request.repo.execute(query)) |_| { + const params = try request.params(); + + const title = params.getT(.string, "title") orelse { + return request.fail(.unprocessable_entity); + }; + + const content = params.getT(.string, "content") orelse { + return request.fail(.unprocessable_entity); + }; + + try request.repo.insert(.Blog, .{ .title = title, .content = content }); + + return request.redirect("/blogs", .moved_permanently); + } else { + return request.fail(.not_found); + } - return request.redirect("/blogs", .moved_permanently); } diff --git a/src/app/views/blogs/index.zmpl b/src/app/views/blogs/index.zmpl index 470a07c..ba43ea8 100644 --- a/src/app/views/blogs/index.zmpl +++ b/src/app/views/blogs/index.zmpl @@ -1,3 +1,4 @@ +@args allowed: bool
@for (.blogs) |blog| { {{blog.title}} @@ -5,5 +6,8 @@
}
- New Blog + + @if ($.allowed) + New Blog + @end
diff --git a/src/app/views/root.zig b/src/app/views/root.zig index 469b301..200ac33 100644 --- a/src/app/views/root.zig +++ b/src/app/views/root.zig @@ -31,6 +31,7 @@ pub fn index(request: *jetzig.Request, data: *jetzig.Data) !jetzig.View { // param. JSON data is also accepted when the `content-type: application/json` header is // present. const params = try request.params(); + const cookies = try request.cookies(); var obj = try data.object(); try obj.put("title",data.string("The simplest article ever")); @@ -49,6 +50,17 @@ pub fn index(request: *jetzig.Request, data: *jetzig.Data) !jetzig.View { try root.put("articles", blogs); + const allowed = blk: { + const session = cookies.get("session") orelse break :blk false; + + const session_query = jetzig.database.Query(.Session) + .findBy(.{ .session_id = session.value }); + _ = request.repo.execute(session_query) catch break :blk false; + break :blk true; + }; + + try root.put("allowed", allowed); + try root.put("message_param", params.get("message")); // Set arbitrary response headers as required. `content-type` is automatically assigned for diff --git a/src/app/views/root/_article_blob.zmpl b/src/app/views/root/_article_blob.zmpl index dab85aa..1bfc872 100644 --- a/src/app/views/root/_article_blob.zmpl +++ b/src/app/views/root/_article_blob.zmpl @@ -1,5 +1,4 @@ -@args title: []const u8, blob: []const u8 +@args title: []const u8

{{title}}

-

{{blob}}

diff --git a/src/app/views/root/index.zmpl b/src/app/views/root/index.zmpl index ce5b7b9..9a8dcbb 100644 --- a/src/app/views/root/index.zmpl +++ b/src/app/views/root/index.zmpl @@ -1,4 +1,4 @@ -@args articles: Zmpl.Array +@args articles: Zmpl.Array, allowed: bool @@ -17,13 +17,18 @@
Blog - TTRPG - Design - Writing + @if ($.allowed) + Logout + @else + Login + @end + Gitea instance + IRC + Tor url + RSS feed + E-mail
- @partial root/article_blob(title: "hi test", blob: "owo") - @for (.articles) |article| { @partial root/article_blob(title: article.title, blob: article.content) } diff --git a/src/main.zig b/src/main.zig index 0b9402e..f16a91e 100644 --- a/src/main.zig +++ b/src/main.zig @@ -12,11 +12,8 @@ pub const jetzig_options = struct { /// Middleware chain. Add any custom middleware here, or use middleware provided in /// `jetzig.middleware` (e.g. `jetzig.middleware.HtmxMiddleware`). pub const middleware: []const type = &.{ - // jetzig.middleware.AuthMiddleware, - // jetzig.middleware.AntiCsrfMiddleware, - // jetzig.middleware.HtmxMiddleware, - // jetzig.middleware.CompressionMiddleware, - // @import("app/middleware/DemoMiddleware.zig"), + jetzig.middleware.AntiCsrfMiddleware, + //@import("app/middleware/AuthMiddleware.zig"), }; // Maximum bytes to allow in request body.