Skip to content
This repository was archived by the owner on Apr 20, 2024. It is now read-only.

Commit a204e03

Browse files
Merge pull request #89 from nodes-vapor/feature/request-creatable
Submissions related update
2 parents 4071e69 + 69b3563 commit a204e03

15 files changed

+248
-247
lines changed

.circleci/config.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ version: 2
22
jobs:
33
MacOS:
44
macos:
5-
xcode: "10.0.0"
5+
xcode: "10.1.0"
66
steps:
77
- checkout
88
- restore_cache:
@@ -36,7 +36,7 @@ jobs:
3636
- checkout
3737
- restore_cache:
3838
keys:
39-
- v2-spm-deps-{{ checksum "Package.swift" }}
39+
- v3-spm-deps-{{ checksum "Package.swift" }}
4040
- run:
4141
name: Copy Package File
4242
command: cp Package.swift res
@@ -49,7 +49,7 @@ jobs:
4949
name: Restoring Package File
5050
command: mv res Package.swift
5151
- save_cache:
52-
key: v2-spm-deps-{{ checksum "Package.swift" }}
52+
key: v3-spm-deps-{{ checksum "Package.swift" }}
5353
paths:
5454
- .build
5555
workflows:

README.md

Lines changed: 1 addition & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,9 @@
1313
Update your `Package.swift` file.
1414

1515
```swift
16-
.package(url: "https://github.com/nodes-vapor/sugar.git", from: "3.0.0-beta")
16+
.package(url: "https://github.com/nodes-vapor/sugar.git", from: "4.0.0")
1717
```
1818

19-
2019
## Getting started 🚀
2120

2221
Make sure that you've imported Sugar everywhere when needed:
@@ -25,41 +24,10 @@ Make sure that you've imported Sugar everywhere when needed:
2524
import Sugar
2625
```
2726

28-
2927
## Helpers
3028

3129
This package contains a lot of misc. functionality that might not fit into it's own package or that would best to get PR'ed into Vapor. Some examples of what this package contains:
3230

33-
#### How to use it in a package
34-
35-
To have your package register the tags to the shared config, you can do the following:
36-
37-
```swift
38-
public func didBoot(_ container: Container) throws -> Future<Void> {
39-
let tags: MutableLeafTagConfig = try container.make()
40-
tags.use(MyTag(), as: "mytag")
41-
42-
return .done(on: container)
43-
}
44-
```
45-
46-
#### How to use it in a project
47-
48-
If you're using a package that uses the shared `MutableLeafTagConfig`, these tags will become available in your project automatically. If you have additional tags you want to add, these has to be registered in `boot.swift` instead of `configure.swift` to allow the different providers to have registered their tags to the config first. Here's how you could do it:
49-
50-
```swift
51-
public func boot(_ app: Application) throws {
52-
// Register Leaf tags using the shared config.
53-
// This allows third party packages to register their own tags.
54-
let tags: MutableLeafTagConfig = try app.make()
55-
tags.use(MyAdditionalTag())
56-
}
57-
```
58-
59-
> You don't have to register `tags` when adding this in `boot.swift`.
60-
61-
In the case where multiple packages is registering a tag using the same name, the tags can be added manually by defining your own name for the tags.
62-
6331
### Environment variables
6432

6533
Access environment variables by writing
@@ -93,13 +61,11 @@ extension MyModel: Migration {
9361
}
9462
```
9563

96-
9764
## 🏆 Credits
9865

9966
This package is developed and maintained by the Vapor team at [Nodes](https://www.nodesagency.com).
10067
The package owner for this project is [Siemen](https://github.com/siemensikkema).
10168

102-
10369
## 📄 License
10470

10571
This package is open-sourced software licensed under the [MIT license](http://opensource.org/licenses/MIT)
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/// Types conforming to this protocol can be used for login or register requests.
2-
public protocol HasReadablePassword: Decodable {
2+
public protocol HasReadablePassword {
33
/// Key path to the readable password.
44
static var readablePasswordKey: KeyPath<Self, String> { get }
55
}

Sources/Sugar/Authentication/JWTAuthenticatable.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,20 @@ extension JWTAuthenticatable {
5050
}.unwrap(or: AuthenticationError.signingError)
5151
}
5252
}
53+
54+
extension JWTAuthenticatable where
55+
Self: Model,
56+
Self.ID: LosslessStringConvertible
57+
{
58+
/// See `JWTAuthenticatable`.
59+
public static func authenticate(
60+
using payload: JWTPayload,
61+
on connection: DatabaseConnectable
62+
) throws -> Future<Self?> {
63+
guard let id = ID(payload.sub.value) else {
64+
throw Sugar.AuthenticationError.malformedPayload
65+
}
66+
67+
return find(id, on: connection)
68+
}
69+
}

Sources/Sugar/Authentication/JWTAuthenticationMiddleware.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ public final class JWTAuthenticationMiddleware<A: JWTAuthenticatable>: Middlewar
4242
jwt = try JWT<A.JWTPayload>(from: bearer.token, verifiedUsing: signer)
4343
} catch let error as JWTError where error.identifier == "exp" {
4444
return try Future
45-
.transform(to: HTTPResponse.init(status: .unauthorized), on: req)
45+
.transform(to: HTTPResponse(status: .unauthorized), on: req)
4646
.encode(for: req)
4747
}
4848

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import Authentication
2+
import Vapor
3+
4+
/// Expresses the ability for a type (e.g. a user type) to be logged in.
5+
public protocol Loginable {
6+
7+
/// Payload containing the information required to perform a login.
8+
associatedtype Login: HasReadablePassword
9+
10+
/// Used to perform any pre-login steps such as validation.
11+
///
12+
/// - Parameter req: the request.
13+
/// - Returns: a `Future<Void>` signaling success or failure.
14+
static func preLogin(on req: Request) -> Future<Void>
15+
16+
/// Performs the actual login. Called after `preLogin(on:)`.
17+
///
18+
/// - Parameters:
19+
/// - login: the login information.
20+
/// - worker: a worker on which to perform any database related actions like user lookup.
21+
/// - Returns: an instance of self in the `Future` on successful login.
22+
static func logIn(with login: Login, on worker: DatabaseConnectable) -> Future<Self>
23+
}
24+
25+
extension Loginable {
26+
27+
/// Default implementation that does nothing.
28+
/// See `Loginable`.
29+
public static func preLogin(on req: Request) -> Future<Void> {
30+
return req.future()
31+
}
32+
}
33+
34+
extension Loginable where
35+
Self: PasswordAuthenticatable,
36+
Self.Login: HasReadableUsername
37+
{
38+
/// Default implementation that uses functionality provided by `PasswordAuthenticatable`.
39+
/// See `Loginable`.
40+
public static func logIn(with login: Login, on worker: DatabaseConnectable) -> Future<Self> {
41+
return Self
42+
.authenticate(
43+
username: login[keyPath: Login.readableUsernameKey],
44+
password: login[keyPath: Login.readablePasswordKey],
45+
using: BCrypt,
46+
on: worker
47+
)
48+
.unwrap(or: AuthenticationError.userNotFound)
49+
}
50+
}
51+
52+
extension Loginable where Self.Login: Decodable {
53+
54+
/// Convenience function that combines `preLogin` and `logIn`.
55+
///
56+
/// - Parameter req: the request.
57+
/// - Returns: an instance of self in the `Future` on successful login.
58+
public static func logIn(on req: Request) -> Future<Self> {
59+
return preLogin(on: req)
60+
.flatMap {
61+
try req.content.decode(Login.self)
62+
}
63+
.flatMap(to: Self.self) { login in
64+
Self.logIn(with: login, on: req)
65+
}
66+
}
67+
}

Sources/Sugar/Authentication/UserType.swift

Lines changed: 0 additions & 187 deletions
This file was deleted.

0 commit comments

Comments
 (0)