├── webroot ├── views │ ├── footer.mustache │ ├── dashboard.mustache │ ├── register.mustache │ ├── login.mustache │ ├── index.mustache │ └── header.mustache └── styles │ └── jumbotron-narrow.css ├── README.md ├── Package.swift ├── .gitignore └── Sources └── main.swift /webroot/views/footer.mustache: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | THIS PACKAGE IS OBSOLETE AND SHOULD NOT BE USED FOR NEW PROJECTS. 2 | -------------------------------------------------------------------------------- /webroot/views/dashboard.mustache: -------------------------------------------------------------------------------- 1 | {{>header}} 2 | 3 |

Welcome! Here is your dashboard.

4 | 5 |

New Note

6 | 7 | 8 | {{#note}} 9 | 10 | {{/note}} 11 |
{{note}}
-------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // Generated automatically by Perfect Assistant Application 2 | // Date: 2017-10-11 20:12:26 +0000 3 | import PackageDescription 4 | let package = Package( 5 | name: "PerfectTurnstilePostgreSQLDemo", 6 | targets: [], 7 | dependencies: [ 8 | .Package(url: "https://github.com/PerfectlySoft/Perfect-Turnstile-PostgreSQL.git", majorVersion: 3), 9 | .Package(url: "https://github.com/PerfectlySoft/Perfect-RequestLogger.git", majorVersion: 3), 10 | ] 11 | ) 12 | -------------------------------------------------------------------------------- /webroot/views/register.mustache: -------------------------------------------------------------------------------- 1 | {{>header}} 2 | 3 |

Register

4 | 5 |
6 |
7 | 8 | 9 |
10 |
11 | 12 | 13 |
14 | 15 | 16 |
17 | 18 | {{>footer}} 19 | -------------------------------------------------------------------------------- /webroot/views/login.mustache: -------------------------------------------------------------------------------- 1 | {{>header}} 2 | 3 |

Login

4 | 5 |
6 |
7 | 8 | 9 |
10 |
11 | 12 | 13 |
14 | 15 | 16 |
17 | 18 |

Not a user of PerfectAuth? Register Today!

19 | 20 | {{>footer}} 21 | -------------------------------------------------------------------------------- /webroot/views/index.mustache: -------------------------------------------------------------------------------- 1 | {{>header}} 2 | 3 | {{^authenticated}} 4 |

Hi! Sign up today!

5 | {{/authenticated}} 6 | {{#authenticated}} 7 |

Hi!

8 |

Your unique account ID is: {{accountID}}

9 | {{/authenticated}} 10 | 11 |

Check out the following resources about Turnstile:

12 | 13 | 19 | 20 | {{>footer}} 21 | -------------------------------------------------------------------------------- /webroot/views/header.mustache: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {{title}} 6 | 7 | 8 |
9 |
10 | 20 |

Perfect Turnstile Authentication

21 |
22 | {{#flash}} 23 | 28 | {{/flash}} 29 | -------------------------------------------------------------------------------- /webroot/styles/jumbotron-narrow.css: -------------------------------------------------------------------------------- 1 | /* Space out content a bit */ 2 | body { 3 | padding-top: 20px; 4 | padding-bottom: 20px; 5 | } 6 | 7 | /* Everything but the jumbotron gets side spacing for mobile first views */ 8 | .header, 9 | .marketing, 10 | .footer { 11 | padding-right: 15px; 12 | padding-left: 15px; 13 | } 14 | 15 | /* Custom page header */ 16 | .header { 17 | padding-bottom: 20px; 18 | border-bottom: 1px solid #e5e5e5; 19 | } 20 | /* Make the masthead heading the same height as the navigation */ 21 | .header h3 { 22 | margin-top: 0; 23 | margin-bottom: 0; 24 | line-height: 40px; 25 | } 26 | 27 | /* Custom page footer */ 28 | .footer { 29 | padding-top: 19px; 30 | color: #777; 31 | border-top: 1px solid #e5e5e5; 32 | } 33 | 34 | /* Customize container */ 35 | @media (min-width: 768px) { 36 | .container { 37 | max-width: 730px; 38 | } 39 | } 40 | .container-narrow > hr { 41 | margin: 30px 0; 42 | } 43 | 44 | /* Main marketing message and sign up button */ 45 | .jumbotron { 46 | text-align: center; 47 | border-bottom: 1px solid #e5e5e5; 48 | } 49 | .jumbotron .btn { 50 | padding: 14px 24px; 51 | font-size: 21px; 52 | } 53 | 54 | /* Supporting marketing content */ 55 | .marketing { 56 | margin: 40px 0; 57 | } 58 | .marketing p + h4 { 59 | margin-top: 28px; 60 | } 61 | 62 | /* Responsive: Portrait tablets and up */ 63 | @media screen and (min-width: 768px) { 64 | /* Remove the padding we set earlier */ 65 | .header, 66 | .marketing, 67 | .footer { 68 | padding-right: 0; 69 | padding-left: 0; 70 | } 71 | /* Space out the masthead */ 72 | .header { 73 | margin-bottom: 30px; 74 | } 75 | /* Remove the bottom border on the jumbotron for visual effect */ 76 | .jumbotron { 77 | border-bottom: 0; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata 19 | 20 | ## Other 21 | *.xccheckout 22 | *.moved-aside 23 | *.xcuserstate 24 | *.xcscmblueprint 25 | 26 | ## Obj-C/Swift specific 27 | *.hmap 28 | *.ipa 29 | 30 | ## Playgrounds 31 | timeline.xctimeline 32 | playground.xcworkspace 33 | 34 | # Swift Package Manager 35 | # 36 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 37 | # Packages/ 38 | .build/ 39 | 40 | # CocoaPods 41 | # 42 | # We recommend against adding the Pods directory to your .gitignore. However 43 | # you should judge for yourself, the pros and cons are mentioned at: 44 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 45 | # 46 | # Pods/ 47 | 48 | # Carthage 49 | # 50 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 51 | # Carthage/Checkouts 52 | 53 | Carthage/Build 54 | 55 | # fastlane 56 | # 57 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 58 | # screenshots whenever they are needed. 59 | # For more information about the recommended setup visit: 60 | # https://github.com/fastlane/fastlane/blob/master/docs/Gitignore.md 61 | 62 | fastlane/report.xml 63 | fastlane/screenshots 64 | 65 | Packages/ 66 | *.xcodeproj 67 | buildlinux 68 | /.packages_lin 69 | /.build_lin 70 | Package.swift.orig 71 | Package.resolved 72 | PADockerfile_build 73 | requests.log 74 | StORMlog.txt 75 | -------------------------------------------------------------------------------- /Sources/main.swift: -------------------------------------------------------------------------------- 1 | // 2 | // main.swift 3 | // PerfectTurnstileSQLiteDemo 4 | // 5 | // Created by Jonathan Guthrie on 2016-10-11. 6 | // Copyright (C) 2015 PerfectlySoft, Inc. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This source file is part of the Perfect.org open source project 11 | // 12 | // Copyright (c) 2015 - 2016 PerfectlySoft Inc. and the Perfect project authors 13 | // Licensed under Apache License v2.0 14 | // 15 | // See http://perfect.org/licensing.html for license information 16 | // 17 | //===----------------------------------------------------------------------===// 18 | // 19 | 20 | import PerfectLib 21 | import PerfectHTTP 22 | import PerfectHTTPServer 23 | 24 | import StORM 25 | import PostgresStORM 26 | import PerfectTurnstilePostgreSQL 27 | import PerfectRequestLogger 28 | import TurnstilePerfect 29 | 30 | 31 | //StORMdebug = true 32 | RequestLogFile.location = "./requests.log" 33 | 34 | // Used later in script for the Realm and how the user authenticates. 35 | let pturnstile = TurnstilePerfectRealm() 36 | 37 | 38 | PostgresConnector.host = "localhost" 39 | PostgresConnector.username = "perfect" 40 | PostgresConnector.password = "perfect" 41 | PostgresConnector.database = "perfect_testing" 42 | PostgresConnector.port = 5432 43 | 44 | 45 | // Set up the Authentication table 46 | let auth = AuthAccount() 47 | try? auth.setup() 48 | 49 | // Connect the AccessTokenStore 50 | tokenStore = AccessTokenStore() 51 | try? tokenStore?.setup() 52 | 53 | //let facebook = Facebook(clientID: "CLIENT_ID", clientSecret: "CLIENT_SECRET") 54 | //let google = Google(clientID: "CLIENT_ID", clientSecret: "CLIENT_SECRET") 55 | 56 | // Create HTTP server. 57 | let server = HTTPServer() 58 | 59 | // Register routes and handlers 60 | let authWebRoutes = makeWebAuthRoutes() 61 | let authJSONRoutes = makeJSONAuthRoutes("/api/v1") 62 | 63 | // Add the routes to the server. 64 | server.addRoutes(authWebRoutes) 65 | server.addRoutes(authJSONRoutes) 66 | 67 | // Adding a test route 68 | var routes = Routes() 69 | routes.add(method: .get, uri: "/api/v1/test", handler: AuthHandlersJSON.testHandler) 70 | 71 | 72 | 73 | 74 | // An example route where authentication will be enforced 75 | routes.add(method: .get, uri: "/api/v1/check", handler: { 76 | request, response in 77 | response.setHeader(.contentType, value: "application/json") 78 | 79 | var resp = [String: String]() 80 | resp["authenticated"] = "AUTHED: \(request.user.authenticated)" 81 | resp["SessionID"] = "SessionID: \(request.user.authDetails?.account.uniqueID)" 82 | 83 | do { 84 | try response.setBody(json: resp) 85 | } catch { 86 | print(error) 87 | } 88 | response.completed() 89 | }) 90 | 91 | 92 | // An example route where auth will not be enforced 93 | routes.add(method: .get, uri: "/api/v1/nocheck", handler: { 94 | request, response in 95 | response.setHeader(.contentType, value: "application/json") 96 | 97 | var resp = [String: String]() 98 | resp["authenticated"] = "AUTHED: \(request.user.authenticated)" 99 | resp["authDetails"] = "DETAILS: \(request.user.authDetails)" 100 | 101 | do { 102 | try response.setBody(json: resp) 103 | } catch { 104 | print(error) 105 | } 106 | response.completed() 107 | }) 108 | 109 | 110 | 111 | // Add the routes to the server. 112 | server.addRoutes(routes) 113 | 114 | 115 | // Setup logging 116 | let myLogger = RequestLogger() 117 | 118 | // add routes to be checked for auth 119 | var authenticationConfig = AuthenticationConfig() 120 | authenticationConfig.include("/api/v1/check") 121 | authenticationConfig.exclude("/api/v1/login") 122 | authenticationConfig.exclude("/api/v1/register") 123 | 124 | let authFilter = AuthFilter(authenticationConfig) 125 | 126 | // Note that order matters when the filters are of the same priority level 127 | server.setRequestFilters([pturnstile.requestFilter]) 128 | server.setResponseFilters([pturnstile.responseFilter]) 129 | 130 | server.setRequestFilters([(authFilter, .high)]) 131 | 132 | server.setRequestFilters([(myLogger, .high)]) 133 | server.setResponseFilters([(myLogger, .low)]) 134 | 135 | // Set a listen port of 8181 136 | server.serverPort = 8181 137 | 138 | // Where to serve static files from 139 | server.documentRoot = "./webroot" 140 | 141 | do { 142 | // Launch the HTTP server. 143 | try server.start() 144 | } catch PerfectError.networkError(let err, let msg) { 145 | print("Network error thrown: \(err) \(msg)") 146 | } 147 | --------------------------------------------------------------------------------