-
Notifications
You must be signed in to change notification settings - Fork 28
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #120 from jetzig-framework/anti-csrf
Closes #108: Anti-CSRF middleware
- Loading branch information
Showing
28 changed files
with
696 additions
and
138 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
const std = @import("std"); | ||
const jetzig = @import("jetzig"); | ||
|
||
pub const layout = "application"; | ||
|
||
pub const actions = .{ | ||
.before = .{jetzig.middleware.AntiCsrfMiddleware}, | ||
}; | ||
|
||
pub fn post(request: *jetzig.Request) !jetzig.View { | ||
var root = try request.data(.object); | ||
|
||
const Params = struct { spam: []const u8 }; | ||
const params = try request.expectParams(Params) orelse { | ||
return request.fail(.unprocessable_entity); | ||
}; | ||
|
||
try root.put("spam", params.spam); | ||
|
||
return request.render(.created); | ||
} | ||
|
||
pub fn index(request: *jetzig.Request) !jetzig.View { | ||
return request.render(.ok); | ||
} | ||
|
||
test "post with missing token" { | ||
var app = try jetzig.testing.app(std.testing.allocator, @import("routes")); | ||
defer app.deinit(); | ||
|
||
const response = try app.request(.POST, "/anti_csrf", .{}); | ||
try response.expectStatus(.forbidden); | ||
} | ||
|
||
test "post with invalid token" { | ||
var app = try jetzig.testing.app(std.testing.allocator, @import("routes")); | ||
defer app.deinit(); | ||
|
||
const response = try app.request(.POST, "/anti_csrf", .{}); | ||
try response.expectStatus(.forbidden); | ||
} | ||
|
||
test "post with valid token but missing expected params" { | ||
var app = try jetzig.testing.app(std.testing.allocator, @import("routes")); | ||
defer app.deinit(); | ||
|
||
_ = try app.request(.GET, "/anti_csrf", .{}); | ||
const token = app.session.getT(.string, jetzig.authenticity_token_name).?; | ||
const response = try app.request( | ||
.POST, | ||
"/anti_csrf", | ||
.{ .params = .{ ._jetzig_authenticity_token = token } }, | ||
); | ||
try response.expectStatus(.unprocessable_entity); | ||
} | ||
|
||
test "post with valid token and expected params" { | ||
var app = try jetzig.testing.app(std.testing.allocator, @import("routes")); | ||
defer app.deinit(); | ||
|
||
_ = try app.request(.GET, "/anti_csrf", .{}); | ||
const token = app.session.getT(.string, jetzig.authenticity_token_name).?; | ||
const response = try app.request( | ||
.POST, | ||
"/anti_csrf", | ||
.{ .params = .{ ._jetzig_authenticity_token = token, .spam = "Spam" } }, | ||
); | ||
try response.expectStatus(.created); | ||
} | ||
|
||
test "index" { | ||
var app = try jetzig.testing.app(std.testing.allocator, @import("routes")); | ||
defer app.deinit(); | ||
|
||
const response = try app.request(.GET, "/anti_csrf", .{}); | ||
try response.expectStatus(.ok); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
<form action="/anti_csrf" method="POST"> | ||
{{context.authenticityFormElement()}} | ||
|
||
<label>Enter spam here:</label> | ||
<input type="text" name="spam" /> | ||
|
||
<input type="submit" value="Submit Spam" /> | ||
</form> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
<h1>Spam Submitted Successfully</h1> | ||
|
||
<h2>Spam:</h2> | ||
|
||
<div>{{$.spam}}</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
const std = @import("std"); | ||
|
||
pub const http = @import("http.zig"); | ||
pub const config = @import("config.zig"); | ||
|
||
/// Context available in every Zmpl template as `context`. | ||
pub const TemplateContext = @This(); | ||
|
||
request: ?*http.Request = null, | ||
|
||
pub fn authenticityToken(self: TemplateContext) !?[]const u8 { | ||
return if (self.request) |request| | ||
try request.authenticityToken() | ||
else | ||
null; | ||
} | ||
|
||
pub fn authenticityFormElement(self: TemplateContext) !?[]const u8 { | ||
return if (self.request) |request| blk: { | ||
const token = try request.authenticityToken(); | ||
break :blk try std.fmt.allocPrint(request.allocator, | ||
\\<input type="hidden" name="{s}" value="{s}" /> | ||
, .{ config.get([]const u8, "authenticity_token_name"), token }); | ||
} else null; | ||
} |
Oops, something went wrong.