second commit...

This commit is contained in:
yuzu 2025-05-03 22:46:59 -05:00
parent 929f0b23a4
commit 76c670b287
8 changed files with 67 additions and 105 deletions

View File

@ -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);
}

View File

@ -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);
}

View File

@ -1,3 +1,4 @@
@args allowed: bool
<div>
@for (.blogs) |blog| {
<a href="/blogs/{{blog.id}}">{{blog.title}}</a>
@ -5,5 +6,8 @@
<br/>
}
<hr/>
<a href="/blogs/new">New Blog</a>
@if ($.allowed)
<a href="/blogs/new">New Blog</a>
@end
</div>

View File

@ -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

View File

@ -1,5 +1,4 @@
@args title: []const u8, blob: []const u8
@args title: []const u8
<div class="mb-4">
<h2 class="text-2xl font-semibold mb-2">{{title}}</h2>
<p class="text-lg">{{blob}}</p>
</div>

View File

@ -1,4 +1,4 @@
@args articles: Zmpl.Array
@args articles: Zmpl.Array, allowed: bool
<html>
<head>
@ -17,13 +17,18 @@
<div class="mb-8">
<a href="/blogs" class="text-blue-500 hover:underline">Blog</a>
<a href="#" class="text-blue-500 hover:underline ml-4">TTRPG</a>
<a href="#" class="text-blue-500 hover:underline ml-4">Design</a>
<a href="#" class="text-blue-500 hover:underline ml-4">Writing</a>
@if ($.allowed)
<a href="/logout" class="text-blue-500 hover:underline ml-4">Logout</a>
@else
<a href="/login" class="text-blue-500 hover:underline ml-4">Login</a>
@end
<a href="#" class="text-blue-500 hover:underline ml-4">Gitea instance</a>
<a href="#" class="text-blue-500 hover:underline ml-4">IRC</a>
<a href="#" class="text-blue-500 hover:underline ml-4">Tor url</a>
<a href="#" class="text-blue-500 hover:underline ml-4">RSS feed</a>
<a href="mailto:me@yuzucchii.xyz" class="text-blue-500 hover:underline ml-4">E-mail</a>
</div>
@partial root/article_blob(title: "hi test", blob: "owo")
@for (.articles) |article| {
@partial root/article_blob(title: article.title, blob: article.content)
}

View File

@ -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.