Skip to content

Commit

Permalink
Merge pull request #4 from vapor-community/develop
Browse files Browse the repository at this point in the history
Vapor 3
  • Loading branch information
calebkleveter authored Jan 20, 2018
2 parents 496ba09 + 05f0ca2 commit 12dab70
Show file tree
Hide file tree
Showing 22 changed files with 211 additions and 307 deletions.
27 changes: 27 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
version: 2

jobs:
macos:
macos:
xcode: "9.0"
steps:
- run: brew install vapor/tap/vapor
- checkout
- run: swift build
- run: swift test

linux:
docker:
- image: swift:4.0
steps:
- run: apt-get install -yq libssl-dev
- checkout
- run: swift build
- run: swift test

workflows:
version: 2
tests:
jobs:
- macos
- linux
160 changes: 35 additions & 125 deletions Package.resolved
Original file line number Diff line number Diff line change
Expand Up @@ -2,174 +2,84 @@
"object": {
"pins": [
{
"package": "BCrypt",
"repositoryURL": "https://github.com/vapor/bcrypt.git",
"package": "Async",
"repositoryURL": "https://github.com/vapor/async.git",
"state": {
"branch": null,
"revision": "3ee4aca16ba6ebfb1ad48cc5fd4dfb163c6d6be8",
"version": "1.1.0"
}
},
{
"package": "Bits",
"repositoryURL": "https://github.com/vapor/bits.git",
"state": {
"branch": null,
"revision": "c32f5e6ae2007dccd21a92b7e33eba842dd80d2f",
"version": "1.1.0"
}
},
{
"package": "CTLS",
"repositoryURL": "https://github.com/vapor/ctls.git",
"state": {
"branch": null,
"revision": "fddec6a4643d6e85b6bb6dc54b1b5cdbabd395d2",
"version": "1.1.2"
"branch": "beta",
"revision": "fa7aa97c0476fe6da859e5fea35b3f027fcfc4ff",
"version": null
}
},
{
"package": "Console",
"repositoryURL": "https://github.com/vapor/console.git",
"state": {
"branch": null,
"revision": "df9eb9a6afd03851abcb3d8204d04c368729776e",
"version": "2.3.0"
"branch": "beta",
"revision": "2e7266b7c8c08839ea548223579f7ece74905331",
"version": null
}
},
{
"package": "Core",
"repositoryURL": "https://github.com/vapor/core.git",
"state": {
"branch": null,
"revision": "f9f3a585ab0ea5764b46d7a36d9c0d9d508b9c63",
"version": "2.2.0"
"branch": "beta",
"revision": "a848fb34323fa194ba9255df6899dcf9291b00ff",
"version": null
}
},
{
"package": "Crypto",
"repositoryURL": "https://github.com/vapor/crypto.git",
"state": {
"branch": null,
"revision": "bf4470b9da79024aab79c85de80374f6c29e3864",
"version": "2.1.1"
"branch": "beta",
"revision": "b31cdb4ecc32b8f529a6027c1945f404c4a41c1e",
"version": null
}
},
{
"package": "Debugging",
"repositoryURL": "https://github.com/vapor/debugging.git",
"package": "DatabaseKit",
"repositoryURL": "https://github.com/vapor/database-kit.git",
"state": {
"branch": null,
"revision": "49c5e8f0a7cb5456a8f7c72c6cd9f1553e5885a8",
"version": "1.1.0"
"branch": "beta",
"revision": "19af4c3911167a6e0ccf465003b52dea29717429",
"version": null
}
},
{
"package": "Engine",
"repositoryURL": "https://github.com/vapor/engine.git",
"state": {
"branch": null,
"revision": "decf702d774ac630dfe0441ff76b4bb68257b77a",
"version": "2.2.1"
}
},
{
"package": "Fluent",
"repositoryURL": "https://github.com/vapor/fluent.git",
"state": {
"branch": null,
"revision": "2c66e5c6c99dac19554e1cb8957e6de256009efc",
"version": "2.4.2"
}
},
{
"package": "FluentProvider",
"repositoryURL": "https://github.com/vapor/fluent-provider.git",
"state": {
"branch": null,
"revision": "425d973f7cad7bfa987409b9e4a8659c14c6f0e0",
"version": "1.3.0"
}
},
{
"package": "JSON",
"repositoryURL": "https://github.com/vapor/json.git",
"state": {
"branch": null,
"revision": "735800d8f2e75ebe3be25559eb6a781f4666dcfc",
"version": "2.2.1"
}
},
{
"package": "Multipart",
"repositoryURL": "https://github.com/vapor/multipart.git",
"state": {
"branch": null,
"revision": "8e541b2e6fc64a3741eca2aa48ee2c3f23cbe17c",
"version": "2.1.1"
}
},
{
"package": "Node",
"repositoryURL": "https://github.com/vapor/node.git",
"state": {
"branch": null,
"revision": "642f357d08ec5aa335ae2e3c4633c72da7b5a0c4",
"version": "2.1.1"
}
},
{
"package": "Random",
"repositoryURL": "https://github.com/vapor/random.git",
"state": {
"branch": null,
"revision": "d7c4397d125caba795d14d956efacfe2a27a63d0",
"version": "1.2.0"
}
},
{
"package": "Routing",
"repositoryURL": "https://github.com/vapor/routing.git",
"state": {
"branch": null,
"revision": "cb9d78aca2540c1a6b45b0ab43e5b0c50f29d216",
"version": "2.2.0"
}
},
{
"package": "SQLite",
"repositoryURL": "https://github.com/vapor/sqlite.git",
"state": {
"branch": null,
"revision": "9aceb6a0d7b1698a557647493bd78b030dad468b",
"version": "2.3.1"
"branch": "beta",
"revision": "dce3bbcd3bf9cca676bcbf41a849bc392ea50076",
"version": null
}
},
{
"package": "Sockets",
"repositoryURL": "https://github.com/vapor/sockets.git",
"package": "Service",
"repositoryURL": "https://github.com/vapor/service.git",
"state": {
"branch": null,
"revision": "70d14c0e223257176f5ef69a595f7cad5de7a88b",
"version": "2.2.1"
"branch": "beta",
"revision": "ae18f072da312710506802e557dc552d3c68bd34",
"version": null
}
},
{
"package": "TLS",
"repositoryURL": "https://github.com/vapor/tls.git",
"package": "TemplateKit",
"repositoryURL": "https://github.com/vapor/template-kit.git",
"state": {
"branch": null,
"revision": "6c6eedb6761cddc6b6c87142a27eec13fa1701ec",
"version": "2.1.1"
"branch": "beta",
"revision": "56990033c17006e7d1ae9c78abc3da1654d79fe6",
"version": null
}
},
{
"package": "Vapor",
"repositoryURL": "https://github.com/vapor/vapor.git",
"state": {
"branch": null,
"revision": "63768e7f56e58dbfa4288e16ad2e4003bfd8dcde",
"version": "2.4.0"
"branch": "beta",
"revision": "24e66402cd89ab039ff95f48dec87406e7865395",
"version": null
}
}
]
Expand Down
5 changes: 2 additions & 3 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,10 @@ let package = Package(
.library(name: "Imperial", targets: ["Imperial"]),
],
dependencies: [
.package(url: "https://github.com/vapor/vapor.git", .exact("2.4.0")),
.package(url: "https://github.com/vapor/fluent-provider.git", .exact("1.3.0"))
.package(url: "https://github.com/vapor/vapor.git", .branch("beta"))
],
targets: [
.target(name: "Imperial", dependencies: ["Vapor", "FluentProvider"]),
.target(name: "Imperial", dependencies: ["Vapor"]),
.testTarget(name: "ImperialTests", dependencies: ["Imperial"]),
]
)
8 changes: 1 addition & 7 deletions Sources/Imperial/Errors/ImperialError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,11 @@ public enum ImperialError: Error, CustomStringConvertible {
/// - warning: This error is never thrown; rather, the application will fatal error.
case missingEnvVar(String)

/// Thrown when no service is registered with a given name.
case noServiceFound(String)

/// Thrown when we attempt to create a `FederatedCreatable` model and there is
/// no JSON in the response from the the request to `dataUri`.
case missingJSONFromResponse(String)

/// Thrown when a `FederatedCreatable` type has a `serviceKey` that does not match any available endpoints in the service.
case noServiceEndpoint(String)


/// Thrown when `request.fetch` is called with a type that has not been run through `request.create`.
case typeNotInitialized(String)
Expand All @@ -22,9 +18,7 @@ public enum ImperialError: Error, CustomStringConvertible {
public var description: String {
switch self {
case let .missingEnvVar(variable): return "Missing enviroment variable '\(variable)'"
case let .noServiceFound(name): return "No service was found with the name '\(name)'"
case let .missingJSONFromResponse(uri): return "Reponse returned from '\(uri)' does not contain JSON"
case let .noServiceEndpoint(endpoint): return "Service does not have available endpoint for key '\(endpoint)'"
case let .typeNotInitialized(type): return "No instence of type '\(type)' has been created"
}
}
Expand Down
20 changes: 20 additions & 0 deletions Sources/Imperial/Errors/ServiceError.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/// Represents an error that occurs during a service action.
public enum ServiceError: Error, CustomStringConvertible {

/// Thrown when no service is registered with a given name.
case noServiceFound(String)

/// Thrown when no `FederatedSewrvice` type is found whgen creating a `Service` from JSON.
case noExistingService(String)

/// Thrown when a `FederatedCreatable` type has a `serviceKey` that does not match any available endpoints in the service.
case noServiceEndpoint(String)

public var description: String {
switch self {
case let .noServiceFound(name): return "No service was found with the name '\(name)'"
case let .noExistingService(name): return "No service exists with the name '\(name)'"
case let .noServiceEndpoint(endpoint): return "Service does not have available endpoint for key '\(endpoint)'"
}
}
}
36 changes: 25 additions & 11 deletions Sources/Imperial/Helpers/Request+Imperial.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,36 @@ import Vapor

extension Request {

func send(method: HTTPMethod = .get, url: String, headers: HTTPHeaders.Literal = [:], body: HTTPBody = HTTPBody(), mediaType: MediaType? = nil)throws -> Future<Response> {
let client = try self.make(HTTPClient.self)
var header: HTTPHeaders = HTTPHeaders()
header.append(headers)
var request = HTTPRequest(method: method, uri: URI(url), headers: header, body: body)
request.mediaType = mediaType ?? .urlEncodedForm
return client.send(request).map(to: Response.self, { (res) in
return Response(http: res, using: self.superContainer)
})
}

/// Creates an instance of a `FederatedCreatable` type from JSON fetched from an OAuth provider's API.
///
/// - Parameters:
/// - model: The type to create an instance of.
/// - service: The service to get the data from.
/// - Returns: An instance of the type passed in.
/// - Throws: Errors from trying to get the access token from the request.
func create<T: FederatedCreatable>(_ model: T.Type, with service: Service)throws -> T {
let uri = try service[model.serviceKey] ?? ImperialError.noServiceEndpoint(model.serviceKey)
func create<T: FederatedCreatable>(_ model: T.Type, with service: OAuthService)throws -> Future<T> {
let uri = try service[model.serviceKey] ?? ServiceError.noServiceEndpoint(model.serviceKey)

let token = try service.tokenPrefix + self.getAccessToken()
let noJson = ImperialError.missingJSONFromResponse(uri)

let response = try drop.client.get(uri, [.authorization: token])
let new = try model.create(with: response.json ?? noJson, for: service)

self.storage["imperial-\(model)"] = new
return new
return try self.send(url: uri, headers: [.authorization: token]).flatMap(to: T.self, { (response) -> Future<T> in
return try model.create(from: response)
}).map(to: T.self, { (instance) -> T in
let session = try self.session()
session.data.storage["imperial-\(model)"] = instance
return instance
})
}

/// Gets an instance of a `FederatedCreatable` type that is stored in the request.
Expand All @@ -30,9 +42,11 @@ extension Request {
/// - Throws:
/// - `ImperialError.typeNotInitialized`: If there is no value stored in the request for the type passed in.
func fetch<T: FederatedCreatable>(_ model: T.Type)throws -> T {
if let new = self.storage["imperial-\(model)"] {
return new as! T
let session = try self.session()
guard let fetched = session.data.storage["imperial-\(model)"],
let typed = fetched as? T else {
throw ImperialError.typeNotInitialized("\(model)")
}
throw ImperialError.typeNotInitialized("\(model)")
return typed
}
}
5 changes: 2 additions & 3 deletions Sources/Imperial/Helpers/Sessions+Imperial.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import Vapor
import Sessions

extension Request {

Expand All @@ -10,7 +9,7 @@ extension Request {
/// - `Abort.unauthorized` if no access token exists.
/// - `SessionsError.notConfigured` if session middlware is not configured yet.
public func getAccessToken()throws -> String {
return try self.assertSession().getAccessToken()
return try self.session().getAccessToken()
}
}

Expand All @@ -21,7 +20,7 @@ extension Session {
/// - Returns: The access token stored with the `access_token` key.
/// - Throws: `Abort.unauthorized` if no access token exists.m
public func getAccessToken()throws -> String {
guard let token = self.data["access_token"]?.string else {
guard let token = self["access_token"] else {
throw Abort(.unauthorized, reason: "User currently not authenticated")
}
return token
Expand Down
Loading

0 comments on commit 12dab70

Please sign in to comment.