Skip to content

Commit

Permalink
Merge pull request #19 from vapor/guard-middleware
Browse files Browse the repository at this point in the history
redirect middleware
  • Loading branch information
tanner0101 authored Jul 26, 2017
2 parents 8ce4d96 + af34d7a commit b04c9ce
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 0 deletions.
35 changes: 35 additions & 0 deletions Sources/AuthProvider/InverseRedirectMiddleware.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import HTTP
import Authentication

/// Redirects authenticated requests to a supplied path.
public final class InverseRedirectMiddleware<U: Authenticatable>: Middleware {
/// The path to redirect to
public let path: String

/// Which type of redirect to perform
public let redirectType: RedirectType

/// Create a new inverse redirect middleware.
public init(
_ userType: U.Type = U.self,
path: String,
redirectType: RedirectType = .normal
) {
self.path = path
self.redirectType = redirectType
}

public func respond(to req: Request, chainingTo next: Responder) throws -> Response {
guard !req.auth.isAuthenticated(U.self) else {
return Response(redirect: path, redirectType)
}

return try next.respond(to: req)
}

/// Use this middleware to redirect authenticated
/// away from login pages back to a secure home page.
public static func home(_ userType: U.Type = U.self, path: String = "/") -> InverseRedirectMiddleware {
return InverseRedirectMiddleware(U.self, path: path)
}
}
34 changes: 34 additions & 0 deletions Sources/AuthProvider/RedirectMiddleware.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import HTTP
import Authentication

/// Redirects unauthenticated requests to a supplied path.
public final class RedirectMiddleware: Middleware {
/// The path to redirect to
public let path: String

/// Which type of redirect to perform
public let redirectType: RedirectType

/// Create a new redirect middleware.
public init(
path: String,
redirectType: RedirectType = .normal
) {
self.path = path
self.redirectType = redirectType
}

public func respond(to req: Request, chainingTo next: Responder) throws -> Response {
do {
return try next.respond(to: req)
} catch is AuthenticationError {
return Response(redirect: path, redirectType)
}
}

/// Use this middleware to redirect users away from
/// protected content to a login page
public static func login(path: String = "/login") -> RedirectMiddleware {
return RedirectMiddleware(path: path)
}
}
56 changes: 56 additions & 0 deletions Tests/AuthProviderTests/MiddlewareTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import XCTest
import Vapor
import HTTP
import AuthProvider
import Authentication
import Testing

class MiddlewareTests: XCTestCase {
override func setUp() {
Testing.onFail = XCTFail
}

/// Test that an unauthenticated request to a secure
/// page gets redirected to the login page.
func testRedirectMiddleware() throws {
let drop = try Droplet()

let redirect = RedirectMiddleware.login()
let auth = TokenAuthenticationMiddleware(TestUser.self)

let protected = drop.grouped([redirect, auth])
protected.get { req in
let user = try req.auth.assertAuthenticated(TestUser.self)
return "Welcome to the dashboard, \(user.name)"
}

try drop.testResponse(to: .get, at: "/")
.assertStatus(is: .seeOther)
.assertHeader("Location", contains: "/login")
}

/// Test that an authenticated request to login
/// gets redirected to the home page.
func testInverseRedirectMiddleware() throws {
let drop = try Droplet()

let redirect = InverseRedirectMiddleware.home(TestUser.self)
let group = drop.grouped([redirect])
group.get("login") { req in
return "Please login"
}

let req = Request.makeTest(method: .get, path: "/login")
let user = TestUser(name: "Foo")
req.auth.authenticate(user)

try drop.testResponse(to: req)
.assertStatus(is: .seeOther)
.assertHeader("Location", contains: "/")
}

static var allTests = [
("testRedirectMiddleware", testRedirectMiddleware),
("testInverseRedirectMiddleware", testInverseRedirectMiddleware)
]
}

0 comments on commit b04c9ce

Please sign in to comment.