Skip to content

Commit

Permalink
Add shared link downscoping (#695)
Browse files Browse the repository at this point in the history
  • Loading branch information
sujaygarlanka authored and PJSimon committed Jan 9, 2020
1 parent 0267a75 commit db31404
Show file tree
Hide file tree
Showing 9 changed files with 26 additions and 11 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ __Breaking Changes:__


__New Features and Enhancements:__

- Add shared link downscoping
- Add marker based pagination to list users endpoint

## v3.0.0 [2019-11-18]
Expand Down
4 changes: 3 additions & 1 deletion Sources/Client/BoxClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -121,13 +121,15 @@ public class BoxClient {
/// - Parameters:
/// - scope: Scope or scopes that you want to apply to the resulting token.
/// - resource: Full url path to the file that the token should be generated for, eg: https://api.box.com/2.0/files/{file_id}
/// - sharedLink: Shared link to get a token for.
/// - completion: Returns the success or an error.
public func exchangeToken(
scope: Set<TokenScope>,
resource: String? = nil,
sharedLink: String? = nil,
completion: @escaping TokenInfoClosure
) {
session.downscopeToken(scope: scope, resource: resource, completion: completion)
session.downscopeToken(scope: scope, resource: resource, sharedLink: sharedLink, completion: completion)
}
}

Expand Down
7 changes: 6 additions & 1 deletion Sources/Modules/AuthModule.swift
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,9 @@ public class AuthModule: TokenRefreshing {
/// - parentToken: Fully-scoped access token. This can be an OAuth (Managed User), JWT (App User or Service Account) or an App Token (New Box View) token.
/// - scope: Scope or scopes that you want to apply to the resulting token.
/// - resource: Full url path to the file that the token should be generated for, eg: https://api.box.com/2.0/files/{file_id}
/// - sharedLink: Shared link to get a token for.
/// - completion: Returns the token data or an error.
public func downscopeToken(parentToken: String, scope: Set<TokenScope>, resource: String? = nil, completion: @escaping TokenInfoClosure) {
public func downscopeToken(parentToken: String, scope: Set<TokenScope>, resource: String? = nil, sharedLink: String? = nil, completion: @escaping TokenInfoClosure) {

let scopeList = Array(scope).map { $0.description }.joined(separator: " ")

Expand All @@ -145,6 +146,10 @@ public class AuthModule: TokenRefreshing {
params["resource"] = unwrappedResource
}

if let unwrappedSharedLink = sharedLink {
params["box_shared_link"] = unwrappedSharedLink
}

networkAgent.send(
request: BoxRequest(
httpMethod: HTTPMethod.post,
Expand Down
4 changes: 2 additions & 2 deletions Sources/Network/BoxNetworkAgent.swift
Original file line number Diff line number Diff line change
Expand Up @@ -168,12 +168,12 @@ public class BoxNetworkAgent: NSObject, NetworkAgentProtocol {

let urlRequest = createRequest(for: updatedRequest)
var observation: NSKeyValueObservation?

let task = session.dataTask(with: urlRequest) { [weak self] data, response, error in
guard let self = self else {
return
}

observation?.invalidate()

if let unwrappedError = error {
Expand Down
4 changes: 3 additions & 1 deletion Sources/Sessions/DelegatedAuth/DelegatedAuthSession.swift
Original file line number Diff line number Diff line change
Expand Up @@ -135,10 +135,12 @@ public class DelegatedAuthSession: SessionProtocol {
/// - Parameters:
/// - scope: Scope or scopes that you want to apply to the resulting token.
/// - resource: Full url path to the file that the token should be generated for, eg: https://api.box.com/2.0/files/{file_id}
/// - sharedLink: Shared link to get a token for.
/// - completion: Returns the success or an error.
public func downscopeToken(
scope: Set<TokenScope>,
resource: String? = nil,
sharedLink: String? = nil,
completion: @escaping TokenInfoClosure
) {
getAccessToken { [weak self] result in
Expand All @@ -149,7 +151,7 @@ public class DelegatedAuthSession: SessionProtocol {

switch result {
case let .success(accessToken):
self.authModule.downscopeToken(parentToken: accessToken, scope: scope, resource: resource, completion: completion)
self.authModule.downscopeToken(parentToken: accessToken, scope: scope, resource: resource, sharedLink: sharedLink, completion: completion)
case let .failure(error):
completion(.failure(error))
}
Expand Down
4 changes: 3 additions & 1 deletion Sources/Sessions/OAuth2/OAuth2Session.swift
Original file line number Diff line number Diff line change
Expand Up @@ -127,13 +127,15 @@ class OAuth2Session: SessionProtocol, ExpiredTokenHandling {
/// - Parameters:
/// - scope: Scope or scopes that you want to apply to the resulting token.
/// - resource: Full url path to the file that the token should be generated for, eg: https://api.box.com/2.0/files/{file_id}
/// - sharedLink: Shared link to get a token for.
/// - completion: Returns the success or an error.
func downscopeToken(
scope: Set<TokenScope>,
resource: String? = nil,
sharedLink: String? = nil,
completion: @escaping TokenInfoClosure
) {
authModule.downscopeToken(parentToken: tokenInfo.accessToken, scope: scope, resource: resource, completion: completion)
authModule.downscopeToken(parentToken: tokenInfo.accessToken, scope: scope, resource: resource, sharedLink: sharedLink, completion: completion)
}
}

Expand Down
3 changes: 2 additions & 1 deletion Sources/Sessions/SessionProtocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,9 @@ public protocol SessionProtocol {
/// - Parameters:
/// - scope: Scope or scopes that you want to apply to the resulting token.
/// - resource: Full url path to the file that the token should be generated for, eg: https://api.box.com/2.0/files/{file_id}
/// - sharedLink: Shared link to get a token for.
/// - completion: Returns the success or an error.
func downscopeToken(scope: Set<TokenScope>, resource: String?, completion: @escaping TokenInfoClosure)
func downscopeToken(scope: Set<TokenScope>, resource: String?, sharedLink: String?, completion: @escaping TokenInfoClosure)
}

/// Defines handler for expired token.
Expand Down
4 changes: 3 additions & 1 deletion Sources/Sessions/SingleToken/SingleTokenSession.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,14 @@ class SingleTokenSession: SessionProtocol {
/// - Parameters:
/// - scope: Scope or scopes that you want to apply to the resulting token.
/// - resource: Full url path to the file that the token should be generated for, eg: https://api.box.com/2.0/files/{file_id}
/// - sharedLink: Shared link to get a token for.
/// - completion: Returns the success or an error.
func downscopeToken(
scope: Set<TokenScope>,
resource: String? = nil,
sharedLink: String? = nil,
completion: @escaping TokenInfoClosure
) {
authModule.downscopeToken(parentToken: token, scope: scope, resource: resource, completion: completion)
authModule.downscopeToken(parentToken: token, scope: scope, resource: resource, sharedLink: sharedLink, completion: completion)
}
}
5 changes: 3 additions & 2 deletions Tests/Modules/AuthModuleSpecs.swift
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,8 @@ class AuthModuleSpecs: QuickSpec {
"subject_token_type": "urn:ietf:params:oauth:token-type:access_token",
"scope": "item_preview item_upload",
"grant_type": "urn:ietf:params:oauth:grant-type:token-exchange",
"resource": "https://api.box.com/2.0/files/123"
"resource": "https://api.box.com/2.0/files/123",
"box_shared_link": "https://app.box.com/s/xyz"
],
checkClosure: { (checkTuple: CheckClosureTuple) in
if let lastPathElement = checkTuple.path.last {
Expand All @@ -196,7 +197,7 @@ class AuthModuleSpecs: QuickSpec {
}

waitUntil(timeout: 10) { done in
self.sut.downscopeToken(parentToken: tokenToDownscope, scope: [.itemPreview, .itemUpload], resource: "https://api.box.com/2.0/files/123") { result in
self.sut.downscopeToken(parentToken: tokenToDownscope, scope: [.itemPreview, .itemUpload], resource: "https://api.box.com/2.0/files/123", sharedLink: "https://app.box.com/s/xyz") { result in
switch result {
case let .success(tokenInfo):
expect(tokenInfo).to(beAKindOf(TokenInfo.self))
Expand Down

0 comments on commit db31404

Please sign in to comment.