1 module app; 2 3 import vibe.core.core; 4 import vibe.core.log; 5 import vibe.http.auth.basic_auth; 6 import vibe.http.client; 7 import vibe.http.router; 8 import vibe.http.server; 9 import vibe.web.auth; 10 import vibe.web.web; 11 12 import std.algorithm : among; 13 import std.datetime; 14 import std.format : format; 15 16 17 shared static this() 18 { 19 auto settings = new HTTPServerSettings; 20 settings.port = 0; 21 settings.bindAddresses = ["127.0.0.1"]; 22 auto router = new URLRouter; 23 router.registerWebInterface(new Service); 24 immutable serverAddr = listenHTTP(settings, router).bindAddresses[0]; 25 26 runTask({ 27 scope (exit) exitEventLoop(); 28 29 void test(string url, string user, HTTPStatus expected) 30 nothrow { 31 try { 32 requestHTTP("http://" ~ serverAddr.toString ~ url, (scope req) { 33 if (user !is null) req.addBasicAuth(user, "secret"); 34 }, (scope res) { 35 res.dropBody(); 36 assert(res.statusCode == expected, format("Unexpected status code for GET %s (%s): %s", url, user, res.statusCode)); 37 }); 38 } catch (Exception e) { 39 assert(false, e.msg); 40 } 41 } 42 43 test("/public", null, HTTPStatus.ok); 44 test("/any", null, HTTPStatus.unauthorized); 45 test("/any", "stacy", HTTPStatus.ok); 46 test("/any_a", null, HTTPStatus.unauthorized); 47 test("/any_a", "stacy", HTTPStatus.ok); 48 test("/admin", null, HTTPStatus.unauthorized); 49 test("/admin", "admin", HTTPStatus.ok); 50 test("/admin", "peter", HTTPStatus.forbidden); 51 test("/admin", "stacy", HTTPStatus.forbidden); 52 test("/admin_a", null, HTTPStatus.unauthorized); 53 test("/admin_a", "admin", HTTPStatus.ok); 54 test("/admin_a", "peter", HTTPStatus.forbidden); 55 test("/admin_a", "stacy", HTTPStatus.forbidden); 56 test("/member", "admin", HTTPStatus.forbidden); 57 test("/member", "peter", HTTPStatus.ok); 58 test("/member", "stacy", HTTPStatus.forbidden); 59 test("/admin_member", "peter", HTTPStatus.ok); 60 test("/admin_member", "admin", HTTPStatus.ok); 61 test("/admin_member", "stacy", HTTPStatus.forbidden); 62 logInfo("All auth tests successful."); 63 }); 64 } 65 66 struct Auth { 67 string username; 68 69 bool isAdmin() { return username == "admin"; } 70 bool isMember() { return username == "peter"; } 71 } 72 73 @requiresAuth 74 class Service { 75 @noAuth void getPublic(HTTPServerResponse res) { res.writeBody("success"); } 76 @anyAuth void getAny(HTTPServerResponse res) { res.writeBody("success"); } 77 @anyAuth void getAnyA(HTTPServerResponse res, Auth auth) { assert(auth.username.among("admin", "peter", "stacy")); res.writeBody("success"); } 78 @auth(Role.admin) void getAdmin(HTTPServerResponse res) { res.writeBody("success"); } 79 @auth(Role.admin) void getAdminA(HTTPServerResponse res, Auth auth) { assert(auth.username == "admin"); res.writeBody("success"); } 80 @auth(Role.member) void getMember(HTTPServerResponse res) { res.writeBody("success"); } 81 @auth(Role.admin | Role.member) void getAdminMember(HTTPServerResponse res) { res.writeBody("success"); } 82 83 @noRoute Auth authenticate(HTTPServerRequest req, HTTPServerResponse res) 84 { 85 Auth ret; 86 ret.username = performBasicAuth(req, res, "test", (user, pw) { return pw == "secret"; }); 87 return ret; 88 } 89 }