This repository has been archived by the owner on Apr 20, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
46505e1
commit 663d3c7
Showing
3 changed files
with
190 additions
and
5 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,63 @@ | ||
# sanitized | ||
Safely create Vapor models from requests. | ||
[![Language](https://img.shields.io/badge/Swift-3-brightgreen.svg)](http://swift.org) | ||
[![Build Status](https://travis-ci.org/nodes-vapor/sanitized.svg?branch=master)](https://travis-ci.org/nodes-vapor/sanitized) | ||
[![codecov](https://codecov.io/gh/nodes-vapor/sanitized/branch/master/graph/badge.svg)](https://codecov.io/gh/nodes-vapor/sanitized) | ||
[![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/nodes-vapor/sanitized/master/LICENSE) | ||
|
||
Safely extract Vapor models from requests. | ||
|
||
## Integration | ||
Update your `Package.swift` file. | ||
```swift | ||
.Package(url: "https://github.com/nodes-vapor/sanitized", majorVersion: 0) | ||
``` | ||
|
||
## Getting started 🚀 | ||
Before you're able to extract your model from a request it needs to conform to the protocol `Sanitizable`. To be conferment all you need to do is add a `[String]` named `permitted` with a list of keys you wish to allow. | ||
|
||
### User.swift | ||
```swift | ||
struct User: Model, Sanitizable { | ||
var id: Node? | ||
var name: String | ||
var email: String | ||
|
||
// will only allow the keys `name` and `email` | ||
static var permitted = ["name", "email"] | ||
|
||
init(node: Node, in context: Context) throws { | ||
id = node["id"] | ||
name = try node.extract("name") | ||
email = try node.extract("email") | ||
} | ||
|
||
//... | ||
} | ||
``` | ||
|
||
Now that you have a conforming model, you can safely extract it from a `Request`. | ||
|
||
### Request body | ||
```json | ||
{ | ||
"id": 10, | ||
"name": "Brett", | ||
"email": "[email protected]" | ||
} | ||
``` | ||
|
||
### Main.swift | ||
```swift | ||
drop.post("users") { req in | ||
var user: User = try request.extractModel() | ||
print(user.id == nil) // prints `true` | ||
try user.save() | ||
return user | ||
} | ||
``` | ||
|
||
## 🏆 Credits | ||
This package is developed and maintained by the Vapor team at [Nodes](https://www.nodes.dk). | ||
|
||
## 📄 License | ||
This package is open-sourced software licensed under the [MIT license](http://opensource.org/licenses/MIT) |
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 |
---|---|---|
@@ -1,12 +1,89 @@ | ||
import XCTest | ||
import HTTP | ||
import Vapor | ||
|
||
@testable import Sanitized | ||
|
||
class sanitizedTests: XCTestCase { | ||
class SanitizedTests: XCTestCase { | ||
static let allTests = [ | ||
("testExample", testExample) | ||
("testBasic", testBasic) | ||
] | ||
|
||
func testExample() { | ||
XCTAssertEqual(2+2, 4) | ||
func testBasic() { | ||
let request = buildRequest(body: [ | ||
"id": 1, | ||
"name": "Brett", | ||
"email": "[email protected]" | ||
]) | ||
|
||
expectNoThrow() { | ||
let model: TestModel = try request.extractModel() | ||
XCTAssertNil(model.id) | ||
XCTAssertEqual(model.name, "Brett") | ||
XCTAssertEqual(model.email, "[email protected]") | ||
} | ||
} | ||
|
||
func testPermitted() { | ||
let json = JSON([ | ||
"id": 1, | ||
"name": "Brett", | ||
"email": "[email protected]" | ||
]) | ||
|
||
let result = json.permit(["name"]) | ||
XCTAssertNil(result["id"]) | ||
XCTAssertEqual(result["name"]?.string, "Brett") | ||
XCTAssertNil(result["email"]) | ||
} | ||
|
||
func testEmptyPermitted() { | ||
let json = JSON([ | ||
"id": 1, | ||
"name": "Brett", | ||
"email": "[email protected]" | ||
]) | ||
|
||
let result = json.permit([]) | ||
XCTAssertNil(result["id"]) | ||
XCTAssertNil(result["name"]) | ||
XCTAssertNil(result["email"]) | ||
} | ||
} | ||
|
||
extension SanitizedTests { | ||
func buildRequest(body: Node) -> Request { | ||
let body = try! JSON(node: body).makeBytes() | ||
|
||
return try! Request( | ||
method: .post, | ||
uri: "/test", | ||
headers: [ | ||
"Content-Type": "application/json" | ||
], | ||
body: .data(body) | ||
) | ||
} | ||
} | ||
|
||
struct TestModel: Model, Sanitizable { | ||
var id: Node? | ||
|
||
var name: String | ||
var email: String | ||
|
||
static var permitted = ["name", "email"] | ||
|
||
init(node: Node, in context: Context) throws { | ||
id = node["id"] | ||
name = try node.extract("name") | ||
email = try node.extract("email") | ||
} | ||
|
||
func makeNode(context: Context) throws -> Node { | ||
return .null | ||
} | ||
|
||
static func prepare(_ database: Database) throws {} | ||
static func revert(_ database: Database) throws {} | ||
} |
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,47 @@ | ||
import XCTest | ||
|
||
func expect<E: Error, ReturnType>( | ||
toThrow expectedError: E, | ||
file: StaticString = #file, | ||
line: UInt = #line, | ||
from closure: (Void) throws -> ReturnType | ||
) where E: Equatable { | ||
do { | ||
let _ = try closure() | ||
XCTFail("should have thrown", file: file, line: line) | ||
} catch let error as E { | ||
XCTAssertEqual(error, expectedError) | ||
} catch { | ||
XCTFail( | ||
"expected type \(type(of: expectedError)) got \(type(of: error))", | ||
file: file, | ||
line: line | ||
) | ||
} | ||
} | ||
|
||
func expectNoThrow<ReturnType>( | ||
file: StaticString = #file, | ||
line: UInt = #line, | ||
_ closure: (Void) throws -> ReturnType | ||
) { | ||
do { | ||
let _ = try closure() | ||
} catch { | ||
XCTFail("closure threw: \(error)", file: file, line: line) | ||
} | ||
} | ||
|
||
func expect<ReturnType>( | ||
_ closure: (Void) throws -> ReturnType, | ||
file: StaticString = #file, | ||
line: UInt = #line, | ||
toReturn expectedResult: ReturnType | ||
) where ReturnType: Equatable { | ||
do { | ||
let result = try closure() | ||
XCTAssertEqual(result, expectedResult, file: file, line: line) | ||
} catch { | ||
XCTFail("closure threw: \(error)", file: file, line: line) | ||
} | ||
} |