diff --git a/Bynder/Api/BynderApiFactory.cs b/Bynder/Api/BynderApiFactory.cs
deleted file mode 100644
index 97abdff..0000000
--- a/Bynder/Api/BynderApiFactory.cs
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright (c) Bynder. All rights reserved.
-// Licensed under the MIT License. See LICENSE file in the project root for full license information.
-
-using Bynder.Api.Impl;
-
-namespace Bynder.Api
-{
- ///
- /// Static class to create a instance
- ///
- public static class BynderApiFactory
- {
- ///
- /// Create a using the given settings
- ///
- /// Settings to configure Bynder API
- /// instance
- public static IBynderApi Create(Settings settings)
- {
- return BynderApi.Create(settings);
- }
- }
-}
diff --git a/Bynder/Api/IBynderAPI.cs b/Bynder/Api/IBynderAPI.cs
deleted file mode 100644
index ab8240e..0000000
--- a/Bynder/Api/IBynderAPI.cs
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright (c) Bynder. All rights reserved.
-// Licensed under the MIT License. See LICENSE file in the project root for full license information.
-
-using System;
-using System.Threading.Tasks;
-using Bynder.Models;
-
-namespace Bynder.Api
-{
- ///
- /// Interface to login to Bynder and then get instance of
- ///
- public interface IBynderApi : IDisposable
- {
- ///
- /// Log in using API. To be able to use this method we need to provide an access token/secret with login permissions in
- ///
- /// email/username
- /// password
- /// Task with the user information
- /// Can be thrown when requests to server can't be completed or HTTP code returned by server is an error
- Task LoginAsync(string email, string password);
-
- /*
- To Login using the browser so only consumer key/secret are needed. Client has to do the following:
- 1. Request temporary Tokens -> GetRequestTokenAsync
- 2. Get Authorized Url to open the browser -> GetAuthorizeUrl
- 3. Wait until user enters credentials and browser is redirected to callback Url.
- 4. Request final access tokens -> GetAccessTokenAsync
-
- Example can be found in Bynder.Sample project
- */
-
- ///
- /// Gets access token once the user has already logged in through the browser,
- ///
- /// Task to represent the access token process
- /// Can be thrown when requests to server can't be completed or HTTP code returned by server is an error
- Task GetAccessTokenAsync();
-
- ///
- /// Gets temporary tokens to use when login through the browser
- ///
- /// Task to represent the request of temp tokens
- /// Can be thrown when requests to server can't be completed or HTTP code returned by server is an error
- Task GetRequestTokenAsync();
-
- ///
- /// Gets the Url we need to open with the browser so the user can login and
- /// we can exchange temp tokes for final access tokens
- ///
- /// Callback Url to be redirected when login is successful
- /// string with the Url we need to open the browser with
- string GetAuthorizeUrl(string callbackUrl);
-
- ///
- /// Logout resets your credential. If the access token/secret provided in the have full permission,
- /// even after this call, calls to all API functions will still work
- ///
- void Logout();
-
- ///
- /// Get asset bank manager to perform asset bank operations
- ///
- /// instance of asset manager.
- IAssetBankManager GetAssetBankManager();
-
- ///
- /// Get collection manager to perform collections operations
- ///
- /// instance of collections manager
- ICollectionsManager GetCollectionsManager();
- }
-}
diff --git a/Bynder/Api/Impl/AssetBankManager.cs b/Bynder/Api/Impl/AssetBankManager.cs
deleted file mode 100644
index 35427e3..0000000
--- a/Bynder/Api/Impl/AssetBankManager.cs
+++ /dev/null
@@ -1,159 +0,0 @@
-// Copyright (c) Bynder. All rights reserved.
-// Licensed under the MIT License. See LICENSE file in the project root for full license information.
-
-using System;
-using System.Collections.Generic;
-using System.Net.Http;
-using System.Threading.Tasks;
-using Bynder.Api.Impl.Oauth;
-using Bynder.Api.Impl.Upload;
-using Bynder.Api.Queries;
-using Bynder.Models;
-
-namespace Bynder.Api.Impl
-{
- ///
- /// Implementation of
- ///
- internal class AssetBankManager : IAssetBankManager
- {
- ///
- /// Request sender to communicate with the Bynder API
- ///
- private IOauthRequestSender _requestSender;
-
- ///
- /// Instance to upload file to Bynder
- ///
- private FileUploader _uploader;
-
- ///
- /// Initializes a new instance of the class
- ///
- /// instance to communicate with the Bynder API
- public AssetBankManager(IOauthRequestSender requestSender)
- {
- _requestSender = requestSender;
- _uploader = FileUploader.Create(_requestSender);
- }
-
- ///
- /// Check for more information
- ///
- /// Check for more information
- public Task> GetBrandsAsync()
- {
- var request = new Request>
- {
- Uri = "/api/v4/brands/",
- HTTPMethod = HttpMethod.Get
- };
-
- return _requestSender.SendRequestAsync(request);
- }
-
- ///
- /// Check for more information
- ///
- /// Check for more information
- public Task> GetMetapropertiesAsync()
- {
- var request = new Request>
- {
- Uri = "/api/v4/metaproperties/",
- HTTPMethod = HttpMethod.Get
- };
-
- return _requestSender.SendRequestAsync(request);
- }
-
- ///
- /// Check for more information
- ///
- /// Check for more information
- /// Check for more information
- public Task> RequestMediaListAsync(MediaQuery query)
- {
- var request = new Request>
- {
- Uri = "/api/v4/media/",
- HTTPMethod = HttpMethod.Get,
- Query = query
- };
-
- return _requestSender.SendRequestAsync(request);
- }
-
- ///
- /// Check for more information
- ///
- /// Check for more information
- /// Check for more information
- public async Task GetDownloadFileUrlAsync(DownloadMediaQuery query)
- {
- string uri = string.Empty;
- if (query.MediaItemId == null)
- {
- uri = $"/api/v4/media/{query.MediaId}/download/";
- }
- else
- {
- uri = $"/api/v4/media/{query.MediaId}/download/{query.MediaItemId}/";
- }
-
- var request = new Request
- {
- Uri = uri,
- HTTPMethod = HttpMethod.Get
- };
-
- var downloadFileInformation = await _requestSender.SendRequestAsync(request).ConfigureAwait(false);
- return downloadFileInformation.S3File;
- }
-
- ///
- /// Check for more information
- ///
- /// Check for more information
- /// Check for more information
- public Task UploadFileAsync(UploadQuery query)
- {
- return _uploader.UploadFile(query);
- }
-
- ///
- /// Check for more information
- ///
- /// Check for more information
- /// Check for more information
- public Task RequestMediaInfoAsync(MediaInformationQuery query)
- {
- var request = new Request
- {
- Uri = $"/api/v4/media/{query.MediaId}/",
- HTTPMethod = HttpMethod.Get,
- Query = query
- };
-
- return _requestSender.SendRequestAsync(request);
- }
-
- ///
- /// Check for more information
- ///
- /// Check for more information
- /// Check for more information
- public Task ModifyMediaAsync(ModifyMediaQuery query)
- {
- var request = new Request
- {
- Uri = $"/api/v4/media/{query.MediaId}/",
- HTTPMethod = HttpMethod.Post,
- Query = query,
- DeserializeResponse = false
- };
-
- return _requestSender.SendRequestAsync(request);
- }
- }
-}
diff --git a/Bynder/Api/Impl/BynderAPI.cs b/Bynder/Api/Impl/BynderAPI.cs
deleted file mode 100644
index 9fbde31..0000000
--- a/Bynder/Api/Impl/BynderAPI.cs
+++ /dev/null
@@ -1,225 +0,0 @@
-// Copyright (c) Bynder. All rights reserved.
-// Licensed under the MIT License. See LICENSE file in the project root for full license information.
-
-using System;
-using System.Collections.Specialized;
-using System.Net.Http;
-using System.Threading.Tasks;
-using System.Web;
-using Bynder.Api.Impl.Oauth;
-using Bynder.Api.Queries;
-using Bynder.Models;
-
-namespace Bynder.Api.Impl
-{
- ///
- /// Implementation of
- ///
- internal class BynderApi : IBynderApi
- {
- ///
- /// Instance to communicate with the Bynder API
- ///
- private IOauthRequestSender _requestSender;
-
- ///
- /// Credentials to use to login and to generate the AuthorizeUrl
- ///
- private Credentials _credentials;
-
- ///
- /// Base Url needed to generate AuthorizeUrl
- ///
- private string _baseUrl;
-
- ///
- /// Instance of the asset bank manager
- ///
- private IAssetBankManager _assetBankManager;
-
- ///
- /// Instance of the collections manager
- ///
- private ICollectionsManager _mediaCollectionsManager;
-
- ///
- /// Initializes a new instance of the class
- ///
- /// Credentials to use to call the API
- /// Base Url where we want to point API calls
- /// Instance to communicate with Bynder API
- public BynderApi(Credentials credentials, string baseUrl, IOauthRequestSender requestSender)
- {
- _credentials = credentials;
- _baseUrl = baseUrl;
- _requestSender = requestSender;
- }
-
- ///
- /// Creates an instance of using settins parameter
- ///
- /// settings to correctly configure instance
- /// Bynder API instance to communicate with Bynder
- public static IBynderApi Create(Settings settings)
- {
- var credentials = new Credentials(
- settings.CONSUMER_KEY,
- settings.CONSUMER_SECRET,
- settings.TOKEN,
- settings.TOKEN_SECRET);
-
- return new BynderApi(credentials, settings.URL, new OauthRequestSender(credentials, settings.URL));
- }
-
- ///
- /// Check for more information
- ///
- /// Check for more information
- public async Task GetRequestTokenAsync()
- {
- var request = new Request
- {
- Uri = "/api/v4/oauth/request_token",
- HTTPMethod = HttpMethod.Post,
- DeserializeResponse = false
- };
-
- var response = await _requestSender.SendRequestAsync(request).ConfigureAwait(false);
- SetCredentialsFromResponse(response);
- }
-
- ///
- /// Check for more information
- ///
- /// Check for more information
- public async Task GetAccessTokenAsync()
- {
- var request = new Request
- {
- Uri = "/api/v4/oauth/access_token",
- HTTPMethod = HttpMethod.Post,
- DeserializeResponse = false
- };
-
- var response = await _requestSender.SendRequestAsync(request).ConfigureAwait(false);
- SetCredentialsFromResponse(response);
- }
-
- ///
- /// Check for more information
- ///
- /// Check for more information
- public IAssetBankManager GetAssetBankManager()
- {
- if (_assetBankManager == null)
- {
- _assetBankManager = new AssetBankManager(_requestSender);
- }
-
- return _assetBankManager;
- }
-
- ///
- /// Check for more information
- ///
- /// Check for more information
- public ICollectionsManager GetCollectionsManager()
- {
- if (_mediaCollectionsManager == null)
- {
- _mediaCollectionsManager = new CollectionsManager(_requestSender);
- }
-
- return _mediaCollectionsManager;
- }
-
- ///
- /// Check for more information
- ///
- /// Check for more information
- /// Check for more information
- public string GetAuthorizeUrl(string callbackUrl)
- {
- UriBuilder builder = new UriBuilder(_baseUrl);
- NameValueCollection parameters = HttpUtility.ParseQueryString(string.Empty);
- parameters.Add("oauth_token", _credentials.ACCESS_TOKEN);
-
- if (!string.IsNullOrEmpty(callbackUrl))
- {
- parameters.Add("callback", callbackUrl);
- }
-
- builder.Path += "api/v4/oauth/authorise/";
- builder.Query = parameters.ToString();
- return builder.ToString();
- }
-
- ///
- /// Check for more information
- ///
- /// Check for more information
- /// Check for more information
- /// Check for more information
- [Obsolete("This method of login is deprecated. We should login through the browser")]
- public Task LoginAsync(string email, string password)
- {
- return LoginAsync(new LoginQuery
- {
- Username = email,
- Password = password,
- ConsumerId = _credentials.CONSUMER_KEY
- });
- }
-
- ///
- /// Check for more information
- ///
- public void Logout()
- {
- _credentials.Reset();
- }
-
- ///
- /// Disposes the request sender
- ///
- public void Dispose()
- {
- _requestSender.Dispose();
- }
-
- ///
- /// Helper method to get string response and update the credentials
- ///
- /// response string
- private void SetCredentialsFromResponse(string response)
- {
- string token = HttpUtility.ParseQueryString(response).Get("oauth_token");
- string tokenSecret = HttpUtility.ParseQueryString(response).Get("oauth_token_secret");
- if (token != null
- && tokenSecret != null)
- {
- _credentials.Set(token, tokenSecret);
- }
- }
-
- ///
- /// Returns Task containing user information. Sends the request to
- ///
- /// information to call login API
- /// Task with User information
- private async Task LoginAsync(LoginQuery query)
- {
- var request = new Request
- {
- Uri = "/api/v4/users/login/",
- HTTPMethod = HttpMethod.Post,
- Query = query
- };
-
- var user = await _requestSender.SendRequestAsync(request);
- _credentials.Set(user.TokenKey, user.TokenSecret);
-
- return user;
- }
- }
-}
diff --git a/Bynder/Api/Impl/CollectionsManager.cs b/Bynder/Api/Impl/CollectionsManager.cs
deleted file mode 100644
index 5e0a21c..0000000
--- a/Bynder/Api/Impl/CollectionsManager.cs
+++ /dev/null
@@ -1,169 +0,0 @@
-// Copyright (c) Bynder. All rights reserved.
-// Licensed under the MIT License. See LICENSE file in the project root for full license information.
-
-using System.Collections.Generic;
-using System.Net.Http;
-using System.Threading.Tasks;
-using Bynder.Api.Impl.Oauth;
-using Bynder.Api.Queries;
-using Bynder.Api.Queries.Collections;
-using Bynder.Models;
-
-namespace Bynder.Api.Impl
-{
- ///
- /// Implementation of
- ///
- internal class CollectionsManager : ICollectionsManager
- {
- ///
- /// Request sender to communicate with the Bynder API
- ///
- private IOauthRequestSender _requestSender;
-
- ///
- /// Initializes a new instance of the class
- ///
- /// instance to communicate with the Bynder API
- public CollectionsManager(IOauthRequestSender requestSender)
- {
- _requestSender = requestSender;
- }
-
- ///
- /// Check for more information
- ///
- /// Check for more information
- /// Check for more information
- public Task CreateCollectionAsync(CreateCollectionQuery query)
- {
- var request = new Request
- {
- Uri = $"/api/v4/collections/",
- HTTPMethod = HttpMethod.Post,
- Query = query,
- DeserializeResponse = false
- };
-
- return _requestSender.SendRequestAsync(request);
- }
-
- ///
- /// Check for more information
- ///
- /// Check for more information
- /// Check for more information
- public Task DeleteCollectionAsync(string id)
- {
- var request = new Request
- {
- Uri = $"/api/v4/collections/{id}/",
- HTTPMethod = HttpMethod.Delete
- };
-
- return _requestSender.SendRequestAsync(request);
- }
-
- ///
- /// Check for more information
- ///
- /// Check for more information
- /// Check for more information
- public Task GetCollectionAsync(string id)
- {
- var request = new Request
- {
- Uri = $"/api/v4/collections/{id}/",
- HTTPMethod = HttpMethod.Get
- };
-
- return _requestSender.SendRequestAsync(request);
- }
-
- ///
- /// Check for more information
- ///
- /// Check for more information
- /// Check for more information
- public Task> GetCollectionsAsync(GetCollectionsQuery query)
- {
- var request = new Request>
- {
- Uri = "/api/v4/collections/",
- HTTPMethod = HttpMethod.Get,
- Query = query
- };
-
- return _requestSender.SendRequestAsync(request);
- }
-
- ///
- /// Check for more information
- ///
- /// Check for more information
- /// Check for more information
- public Task> GetMediaAsync(GetMediaQuery query)
- {
- var request = new Request>
- {
- Uri = $"/api/v4/collections/{query.CollectionId}/media/",
- HTTPMethod = HttpMethod.Get
- };
-
- return _requestSender.SendRequestAsync(request);
- }
-
- ///
- /// Check for more information
- ///
- /// Check for more information
- /// Check for more information
- public Task AddMediaAsync(AddMediaQuery query)
- {
- var request = new Request
- {
- Uri = $"/api/v4/collections/{query.CollectionId}/media/",
- HTTPMethod = HttpMethod.Post,
- Query = query,
- DeserializeResponse = false
- };
-
- return _requestSender.SendRequestAsync(request);
- }
-
- ///
- /// Check for more information
- ///
- /// Check for more information
- /// Check for more information
- public Task RemoveMediaAsync(RemoveMediaQuery query)
- {
- var request = new Request
- {
- Uri = $"/api/v4/collections/{query.CollectionId}/media/",
- HTTPMethod = HttpMethod.Delete,
- Query = query
- };
-
- return _requestSender.SendRequestAsync(request);
- }
-
- ///
- /// Check for more information
- ///
- /// Check for more information
- /// Check for more information
- public Task ShareCollectionAsync(ShareQuery query)
- {
- var request = new Request
- {
- Uri = $"/api/v4/collections/{query.CollectionId}/share/",
- HTTPMethod = HttpMethod.Post,
- Query = query,
- DeserializeResponse = false
- };
-
- return _requestSender.SendRequestAsync(request);
- }
- }
-}
diff --git a/Bynder/Api/Impl/Oauth/Credentials.cs b/Bynder/Api/Impl/Oauth/Credentials.cs
deleted file mode 100644
index 499656a..0000000
--- a/Bynder/Api/Impl/Oauth/Credentials.cs
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright (c) Bynder. All rights reserved.
-// Licensed under the MIT License. See LICENSE file in the project root for full license information.
-
-namespace Bynder.Api.Impl.Oauth
-{
- ///
- /// Class to hold token credentials to call the API.
- ///
- internal class Credentials
- {
- ///
- /// Initializes new instance with specified values
- ///
- /// consumer key
- /// consumer secret
- /// token. This can be null if we are going to log in into Bynder through the browser
- /// token secret. This can be null if we are going to log in into Bynder through the browser
- public Credentials(string consumerKey, string consumerSecret, string token, string tokenSecret)
- {
- CONSUMER_KEY = consumerKey;
- CONSUMER_SECRET = consumerSecret;
- ACCESS_TOKEN = token;
- ACCESS_TOKEN_SECRET = tokenSecret;
-
- INITIAL_TOKEN = token;
- INITIAL_SECRET = tokenSecret;
- }
-
- ///
- /// Gets the consumer key
- ///
- public string CONSUMER_KEY { get; private set; }
-
- ///
- /// Gets the consumer secret
- ///
- public string CONSUMER_SECRET { get; private set; }
-
- ///
- /// Gets the access token
- ///
- public string ACCESS_TOKEN { get; private set; }
-
- ///
- /// Gets the access token secret
- ///
- public string ACCESS_TOKEN_SECRET { get; private set; }
-
- ///
- /// Initial token. Used when we want to reset credentials
- ///
- private string INITIAL_TOKEN { get; set; }
-
- ///
- /// Initial token secret. Used when we want to reset credentials
- ///
- private string INITIAL_SECRET { get; set; }
-
- ///
- /// Resets access token/secret to the initial ones.
- ///
- public void Reset()
- {
- ACCESS_TOKEN = INITIAL_TOKEN;
- ACCESS_TOKEN_SECRET = INITIAL_SECRET;
- }
-
- ///
- /// Sets new access token/secret
- ///
- /// new access token
- /// new access secret
- public void Set(string token, string secret)
- {
- ACCESS_TOKEN = token;
- ACCESS_TOKEN_SECRET = secret;
- }
- }
-}
diff --git a/Bynder/Api/Impl/Oauth/IOauthRequestSender.cs b/Bynder/Api/Impl/Oauth/IOauthRequestSender.cs
deleted file mode 100644
index 497a0ab..0000000
--- a/Bynder/Api/Impl/Oauth/IOauthRequestSender.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright (c) Bynder. All rights reserved.
-// Licensed under the MIT License. See LICENSE file in the project root for full license information.
-
-using System;
-using System.Threading.Tasks;
-using Bynder.Api.Queries;
-
-namespace Bynder.Api.Impl.Oauth
-{
- ///
- /// Interface to send oauth to the API.
- ///
- internal interface IOauthRequestSender : IDisposable
- {
- ///
- /// Sends the request to Bynder API. It gets all necessary information from
- /// and deserializes response if needed to specific object.
- ///
- /// Type we want to deserialize response to
- /// Request with the information to do the API call
- /// Task returning T
- Task SendRequestAsync(Request request);
- }
-}
\ No newline at end of file
diff --git a/Bynder/Api/Impl/Oauth/OAuthBase.cs b/Bynder/Api/Impl/Oauth/OAuthBase.cs
deleted file mode 100644
index d4c5f71..0000000
--- a/Bynder/Api/Impl/Oauth/OAuthBase.cs
+++ /dev/null
@@ -1,373 +0,0 @@
-// Copyright (c) Bynder. All rights reserved.
-// Licensed under the MIT License. See LICENSE file in the project root for full license information.
-
-using System;
-using System.Collections.Generic;
-using System.Security.Cryptography;
-using System.Text;
-
-namespace Bynder.Api.Impl.Oauth
-{
- ///
- /// Class to compute the OAuth header to sign requests.
- /// Implementation from https://code.msdn.microsoft.com/Extending-HttpClient-with-8739f267/view/SourceCode
- ///
- internal class OAuthBase
- {
- private const string OAuthVersion = "1.0";
- private const string OAuthParameterPrefix = "oauth_";
-
- // List of known and used oauth parameters' names
- private const string OAuthConsumerKeyKey = "oauth_consumer_key";
- private const string OAuthVersionKey = "oauth_version";
- private const string OAuthSignatureMethodKey = "oauth_signature_method";
- private const string OAuthSignatureKey = "oauth_signature";
- private const string OAuthTimestampKey = "oauth_timestamp";
- private const string OAuthNonceKey = "oauth_nonce";
- private const string OAuthTokenKey = "oauth_token";
- private const string OAuthTokenSecretKey = "oauth_token_secret";
-
- private const string HMACSHA1SignatureType = "HMAC-SHA1";
- private const string PlainTextSignatureType = "PLAINTEXT";
- private const string RSASHA1SignatureType = "RSA-SHA1";
- private const string UnreservedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~";
-
- private Random random = new Random();
-
- ///
- /// Provides a predefined set of algorithms that are supported officially by the protocol
- ///
- public enum SignatureTypes
- {
- HMACSHA1,
- PLAINTEXT,
- RSASHA1
- }
-
- ///
- /// Generate the signature base that is used to produce the signature
- ///
- /// The full url that needs to be signed including its non OAuth url parameters
- /// The consumer key
- /// The token, if available. If not available pass null or an empty string
- /// The token secret, if available. If not available pass null or an empty string
- /// The http method used. Must be a valid HTTP method verb (POST,GET,PUT, etc)
- /// The signature type. To use the default values use OAuthBase.SignatureTypes.
- /// The signature base
- public string GenerateSignatureBase(Uri url, string consumerKey, string token, string tokenSecret, string httpMethod, string timeStamp, string nonce, string signatureType, out string normalizedUrl, out string normalizedRequestParameters)
- {
- if (token == null)
- {
- token = string.Empty;
- }
-
- if (tokenSecret == null)
- {
- tokenSecret = string.Empty;
- }
-
- if (string.IsNullOrEmpty(consumerKey))
- {
- throw new ArgumentNullException("consumerKey");
- }
-
- if (string.IsNullOrEmpty(httpMethod))
- {
- throw new ArgumentNullException("httpMethod");
- }
-
- if (string.IsNullOrEmpty(signatureType))
- {
- throw new ArgumentNullException("signatureType");
- }
-
- normalizedUrl = null;
- normalizedRequestParameters = null;
-
- List parameters = GetQueryParameters(url.Query);
- parameters.Add(new QueryParameter(OAuthVersionKey, OAuthVersion));
- parameters.Add(new QueryParameter(OAuthNonceKey, nonce));
- parameters.Add(new QueryParameter(OAuthTimestampKey, timeStamp));
- parameters.Add(new QueryParameter(OAuthSignatureMethodKey, signatureType));
- parameters.Add(new QueryParameter(OAuthConsumerKeyKey, consumerKey));
-
- if (!string.IsNullOrEmpty(token))
- {
- parameters.Add(new QueryParameter(OAuthTokenKey, token));
- }
-
- parameters.Sort(new QueryParameterComparer());
-
- normalizedUrl = string.Format("{0}://{1}", url.Scheme, url.Host);
- if (!((url.Scheme == "http" && url.Port == 80) || (url.Scheme == "https" && url.Port == 443)))
- {
- normalizedUrl += ":" + url.Port;
- }
-
- normalizedUrl += url.AbsolutePath;
- normalizedRequestParameters = NormalizeRequestParameters(parameters);
-
- StringBuilder signatureBase = new StringBuilder();
- signatureBase.AppendFormat("{0}&", httpMethod.ToUpper());
- signatureBase.AppendFormat("{0}&", UrlEncode(normalizedUrl));
- signatureBase.AppendFormat("{0}", UrlEncode(normalizedRequestParameters));
-
- return signatureBase.ToString();
- }
-
- ///
- /// Generate the signature value based on the given signature base and hash algorithm
- ///
- /// The signature based as produced by the GenerateSignatureBase method or by any other means
- /// The hash algorithm used to perform the hashing. If the hashing algorithm requires initialization or a key it should be set prior to calling this method
- /// A base64 string of the hash value
- public string GenerateSignatureUsingHash(string signatureBase, HashAlgorithm hash)
- {
- return ComputeHash(hash, signatureBase);
- }
-
- ///
- /// Generates a signature using the HMAC-SHA1 algorithm
- ///
- /// The full url that needs to be signed including its non OAuth url parameters
- /// The consumer key
- /// The consumer secret
- /// The token, if available. If not available pass null or an empty string
- /// The token secret, if available. If not available pass null or an empty string
- /// The http method used. Must be a valid HTTP method verb (POST,GET,PUT,etc)
- /// A base64 string of the hash value
- public string GenerateSignature(Uri url, string consumerKey, string consumerSecret, string token, string tokenSecret, string httpMethod, string timeStamp, string nonce, out string normalizedUrl, out string normalizedRequestParameters, out string authHeader)
- {
- return GenerateSignature(url, consumerKey, consumerSecret, token, tokenSecret, httpMethod, timeStamp, nonce, SignatureTypes.HMACSHA1, out normalizedUrl, out normalizedRequestParameters, out authHeader);
- }
-
- ///
- /// Generates a signature using the specified signatureType
- ///
- /// The full url that needs to be signed including its non OAuth url parameters
- /// The consumer key
- /// The consumer secret
- /// The token, if available. If not available pass null or an empty string
- /// The token secret, if available. If not available pass null or an empty string
- /// The http method used. Must be a valid HTTP method verb (POST,GET,PUT,etc)
- /// The type of signature to use
- /// A base64 string of the hash value
- public string GenerateSignature(Uri url, string consumerKey, string consumerSecret, string token, string tokenSecret, string httpMethod, string timeStamp, string nonce, SignatureTypes signatureType, out string normalizedUrl, out string normalizedRequestParameters, out string authHeader)
- {
- normalizedUrl = null;
- normalizedRequestParameters = null;
- authHeader = null;
-
- switch (signatureType)
- {
- case SignatureTypes.PLAINTEXT:
- return UrlEncode(string.Format("{0}&{1}", consumerSecret, tokenSecret));
- case SignatureTypes.HMACSHA1:
- string signatureBase = GenerateSignatureBase(url, consumerKey, token, tokenSecret, httpMethod, timeStamp, nonce, HMACSHA1SignatureType, out normalizedUrl, out normalizedRequestParameters);
-
- HMACSHA1 hmacsha1 = new HMACSHA1();
- hmacsha1.Key = Encoding.ASCII.GetBytes(string.Format("{0}&{1}", UrlEncode(consumerSecret), string.IsNullOrEmpty(tokenSecret) ? string.Empty : UrlEncode(tokenSecret)));
-
- string signature = GenerateSignatureUsingHash(signatureBase, hmacsha1);
-
- StringBuilder auth = new StringBuilder();
- auth.AppendFormat("{0}=\"{1}\", ", OAuthConsumerKeyKey, UrlEncode(consumerKey));
- if (!string.IsNullOrEmpty(token))
- {
- auth.AppendFormat("{0}=\"{1}\", ", OAuthTokenKey, UrlEncode(token));
- }
- auth.AppendFormat("{0}=\"{1}\", ", OAuthSignatureMethodKey, "HMAC-SHA1");
- auth.AppendFormat("{0}=\"{1}\", ", OAuthTimestampKey, timeStamp);
- auth.AppendFormat("{0}=\"{1}\", ", OAuthNonceKey, UrlEncode(nonce));
- auth.AppendFormat("{0}=\"{1}\", ", OAuthVersionKey, "1.0");
- auth.AppendFormat("{0}=\"{1}\"", OAuthSignatureKey, UrlEncode(signature));
-
- authHeader = auth.ToString();
-
- return signature;
-
- case SignatureTypes.RSASHA1:
- throw new NotImplementedException();
- default:
- throw new ArgumentException("Unknown signature type", "signatureType");
- }
- }
-
- ///
- /// Generate the timestamp for the signature
- ///
- ///
- public virtual string GenerateTimeStamp()
- {
- // Default implementation of UNIX time of the current UTC time
- TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
- return Convert.ToInt64(ts.TotalSeconds).ToString();
- }
-
- ///
- /// Generate a nonce
- ///
- /// Nonce string
- public virtual string GenerateNonce()
- {
- // Just a simple implementation of a random number between 123400 and 9999999
- return random.Next(123400, 9999999).ToString();
- }
-
- ///
- /// This is a different Url Encode implementation since the default .NET one outputs the percent encoding in lower case.
- /// While this is not a problem with the percent encoding spec, it is used in upper case throughout OAuth
- ///
- /// The value to Url encode
- /// Returns a Url encoded string
- protected string UrlEncode(string value)
- {
- StringBuilder result = new StringBuilder();
-
- foreach (char symbol in value)
- {
- if (UnreservedChars.IndexOf(symbol) != -1)
- {
- result.Append(symbol);
- }
- else
- {
- result.Append('%' + string.Format("{0:X2}", (int)symbol));
- }
- }
-
- return result.ToString();
- }
-
- ///
- /// Normalizes the request parameters according to the spec
- ///
- /// The list of parameters already sorted
- /// a string representing the normalized parameters
- protected string NormalizeRequestParameters(IList parameters)
- {
- StringBuilder sb = new StringBuilder();
- QueryParameter p = null;
- for (int i = 0; i < parameters.Count; i++)
- {
- p = parameters[i];
- sb.AppendFormat("{0}={1}", p.Name, p.Value);
-
- if (i < parameters.Count - 1)
- {
- sb.Append("&");
- }
- }
-
- return sb.ToString();
- }
-
- ///
- /// Helper function to compute a hash value
- ///
- /// The hashing algorithm used. If that algorithm needs some initialization, like HMAC and its derivatives, they should be initialized prior to passing it to this function
- /// The data to hash
- /// a Base64 string of the hash value
- private string ComputeHash(HashAlgorithm hashAlgorithm, string data)
- {
- if (hashAlgorithm == null)
- {
- throw new ArgumentNullException("hashAlgorithm");
- }
-
- if (string.IsNullOrEmpty(data))
- {
- throw new ArgumentNullException("data");
- }
-
- byte[] dataBuffer = System.Text.Encoding.ASCII.GetBytes(data);
- byte[] hashBytes = hashAlgorithm.ComputeHash(dataBuffer);
-
- return Convert.ToBase64String(hashBytes);
- }
-
- ///
- /// Internal function to cut out all non oauth query string parameters (all parameters not beginning with "oauth_")
- ///
- /// The query string part of the Url
- /// A list of QueryParameter each containing the parameter name and value
- private List GetQueryParameters(string parameters)
- {
- if (parameters.StartsWith("?"))
- {
- parameters = parameters.Remove(0, 1);
- }
-
- List result = new List();
-
- if (!string.IsNullOrEmpty(parameters))
- {
- string[] p = parameters.Split('&');
- foreach (string s in p)
- {
- if (!string.IsNullOrEmpty(s) && !s.StartsWith(OAuthParameterPrefix))
- {
- if (s.IndexOf('=') > -1)
- {
- string[] temp = s.Split('=');
- result.Add(new QueryParameter(temp[0], temp[1]));
- }
- else
- {
- result.Add(new QueryParameter(s, string.Empty));
- }
- }
- }
- }
-
- return result;
- }
-
- ///
- /// Provides an internal structure to sort the query parameter
- ///
- protected class QueryParameter
- {
- private string name = null;
- private string value = null;
-
- public QueryParameter(string name, string value)
- {
- this.name = name;
- this.value = value;
- }
-
- public string Name
- {
- get { return name; }
- }
-
- public string Value
- {
- get { return value; }
- }
- }
-
- ///
- /// Comparer class used to perform the sorting of the query parameters
- ///
- protected class QueryParameterComparer : IComparer
- {
- #region IComparer Members
-
- public int Compare(QueryParameter x, QueryParameter y)
- {
- if (x.Name == y.Name)
- {
- return string.Compare(x.Value, y.Value);
- }
- else
- {
- return string.Compare(x.Name, y.Name);
- }
- }
-
- #endregion
- }
- }
-}
diff --git a/Bynder/Api/Impl/Oauth/OAuthMessageHandler.cs b/Bynder/Api/Impl/Oauth/OAuthMessageHandler.cs
deleted file mode 100644
index 1624d2a..0000000
--- a/Bynder/Api/Impl/Oauth/OAuthMessageHandler.cs
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright (c) Bynder. All rights reserved.
-// Licensed under the MIT License. See LICENSE file in the project root for full license information.
-
-using System.Net.Http;
-using System.Net.Http.Headers;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace Bynder.Api.Impl.Oauth
-{
- ///
- /// Class to sign requests.
- /// Implementation from https://code.msdn.microsoft.com/Extending-HttpClient-with-8739f267/view/SourceCode
- ///
- internal class OAuthMessageHandler : DelegatingHandler
- {
- ///
- /// Credentials to sign request
- ///
- private Credentials _credentials;
-
- ///
- /// Oauth logic to generate the oauth header.
- ///
- private OAuthBase _oauthBase = new OAuthBase();
-
- ///
- /// Creates a new handler to sign requests using OAuth 1.0
- ///
- /// credentials to sign requests
- /// next handler
- public OAuthMessageHandler(Credentials credentials, HttpMessageHandler innerHandler)
- : base(innerHandler)
- {
- _credentials = credentials;
- }
-
- ///
- /// Adds Authorization header to the request
- ///
- /// HTTP request to sign
- /// Cancellation token
- /// Task with
- protected override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
- {
- // Compute OAuth header
- string normalizedUri;
- string normalizedParameters;
- string authHeader;
-
- string signature = _oauthBase.GenerateSignature(
- request.RequestUri,
- _credentials.CONSUMER_KEY,
- _credentials.CONSUMER_SECRET,
- _credentials.ACCESS_TOKEN,
- _credentials.ACCESS_TOKEN_SECRET,
- request.Method.Method,
- _oauthBase.GenerateTimeStamp(),
- _oauthBase.GenerateNonce(),
- out normalizedUri,
- out normalizedParameters,
- out authHeader);
-
- request.Headers.Authorization = new AuthenticationHeaderValue("OAuth", authHeader);
- return base.SendAsync(request, cancellationToken);
- }
- }
-}
diff --git a/Bynder/Api/Impl/Oauth/OauthRequestSender.cs b/Bynder/Api/Impl/Oauth/OauthRequestSender.cs
deleted file mode 100644
index 85ce727..0000000
--- a/Bynder/Api/Impl/Oauth/OauthRequestSender.cs
+++ /dev/null
@@ -1,168 +0,0 @@
-// Copyright (c) Bynder. All rights reserved.
-// Licensed under the MIT License. See LICENSE file in the project root for full license information.
-
-using System;
-using System.Collections.Specialized;
-using System.Linq;
-using System.Net;
-using System.Net.Http;
-using System.Net.Http.Headers;
-using System.Text;
-using System.Text.RegularExpressions;
-using System.Threading.Tasks;
-using System.Web;
-using Bynder.Api.Queries;
-using Newtonsoft.Json;
-
-namespace Bynder.Api.Impl.Oauth
-{
- ///
- /// Implementation for
- ///
- internal class OauthRequestSender : IOauthRequestSender
- {
- ///
- /// Base Url where API requests will be sent
- ///
- private readonly string _baseUrl;
-
- ///
- /// Credentials used to generate oauth header
- ///
- private Credentials _credentials;
-
- ///
- /// Query decoder to get parameters from query objects
- ///
- private QueryDecoder _queryDecoder = new QueryDecoder();
-
- ///
- /// HttpClient to send the API requests.
- ///
- private HttpClient _httpClient;
-
- ///
- /// Creates a new instance of the class
- ///
- /// Credentials need to authenticate request
- /// base Url where to send API requests
- public OauthRequestSender(Credentials credentials, string baseUrl)
- {
- _credentials = credentials;
- _baseUrl = baseUrl;
- _httpClient = new HttpClient(new OAuthMessageHandler(credentials, new HttpClientHandler()));
- _httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
- ServicePointManager.SecurityProtocol = ServicePointManager.SecurityProtocol | SecurityProtocolType.Tls12;
- }
-
- ///
- /// Disposes httpClient instance
- ///
- public void Dispose()
- {
- _httpClient.Dispose();
- }
-
- ///
- /// Check
- ///
- /// Check
- /// Check
- /// Check
- public Task SendRequestAsync(Request request)
- {
- var parameters = _queryDecoder.GetParameters(request.Query);
- return BynderRestCallAsync(request.HTTPMethod, request.Uri, parameters, request.DeserializeResponse);
- }
-
- ///
- /// Gets response to an API call and deserialize response to object if needed
- ///
- /// Object type we want to deserialize to
- /// HTTP Method to use (GET, POST,...)
- /// Uri to be appended to to do the request
- /// Parameters to be used for the request
- /// if T is a string we maybe don't want to deserialize to JSON. If T is string and this parameter is false, response is not deserialized
- /// Task with response as T
- private async Task BynderRestCallAsync(HttpMethod method, string uri, NameValueCollection requestParams, bool deserializeToJson)
- {
- var responseString = await BynderRestCallAsync(method, uri, requestParams).ConfigureAwait(false);
- if (!string.IsNullOrEmpty(responseString))
- {
- if (typeof(T) == typeof(string)
- && !deserializeToJson)
- {
- // We can't return responseString directly.
- return (T)Convert.ChangeType(responseString, typeof(T));
- }
-
- return JsonConvert.DeserializeObject(responseString);
- }
-
- return default(T);
- }
-
- ///
- /// Gets reponse as raw string to an API call
- ///
- /// HTTP Method to use (GET, POST,...)
- /// Uri to be appended to to do the request
- /// Parameters to be used for the request
- /// Task returning raw response string
- private async Task BynderRestCallAsync(HttpMethod method, string uri, NameValueCollection requestParams)
- {
- Uri baseUri = new Uri(_baseUrl);
- Uri uploadUri = new Uri(baseUri, uri);
-
- using (var httpResponseMessage = await SendOauthRequestAsync(method, uploadUri, requestParams).ConfigureAwait(false))
- {
- var content = await httpResponseMessage.Content.ReadAsStringAsync().ConfigureAwait(false);
- if (httpResponseMessage.IsSuccessStatusCode)
- {
- return content;
- }
-
- throw new HttpRequestException(content);
- }
- }
-
- ///
- /// Sends an API request adding appropriate Oauth headers. It returns a task with the HttpResponseMessage received.
- ///
- /// HTTP Method to use (GET, POST,...)
- /// Uri to be appended to to do the request
- /// Parameters to be used for the request
- /// Task returning HttpResponseMessage received
- private async Task SendOauthRequestAsync(HttpMethod method, Uri uri, NameValueCollection requestParams)
- {
- string parametersUrlEncoded = ConvertToUrlQuery(requestParams);
- uri = new Uri(uri, $"?{parametersUrlEncoded}");
- using (HttpRequestMessage request = new HttpRequestMessage(method, uri))
- {
- if (method == HttpMethod.Post)
- {
- request.Content = new StringContent(parametersUrlEncoded, Encoding.UTF8, "application/x-www-form-urlencoded");
- }
-
- // We need to await here so request is not disposed before the call finishes
- return await _httpClient.SendAsync(request).ConfigureAwait(false);
- }
- }
-
- ///
- /// Converts parameters collection to Url query string
- ///
- /// parameters collection
- /// URL Encoded string
- private string ConvertToUrlQuery(NameValueCollection parameters)
- {
- var encodedValues = parameters.AllKeys
- .OrderBy(key => key)
- .Select(key => $"{Uri.EscapeDataString(key)}={Uri.EscapeDataString(parameters[key])}");
- var queryUri = string.Join("&", encodedValues);
-
- // We need encoded values to be uppercase.
- return Regex.Replace(queryUri, "(%[0-9a-f][0-9a-f])", c => c.Value.ToUpper());
- }
- }
-}
diff --git a/Bynder/Api/Queries/LoginQuery.cs b/Bynder/Api/Queries/LoginQuery.cs
deleted file mode 100644
index e84ab47..0000000
--- a/Bynder/Api/Queries/LoginQuery.cs
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright (c) Bynder. All rights reserved.
-// Licensed under the MIT License. See LICENSE file in the project root for full license information.
-
-namespace Bynder.Api.Queries
-{
- ///
- /// Object used internally to login
- ///
- internal class LoginQuery
- {
- ///
- /// Username
- ///
- [APIField("username")]
- public string Username { get; set; }
-
- ///
- /// Password
- ///
- [APIField("password")]
- public string Password { get; set; }
-
- ///
- /// Consumer id that corresponds to consumer key.
- ///
- [APIField("consumerId")]
- public string ConsumerId { get; set; }
- }
-}
diff --git a/Bynder/Api/Settings.cs b/Bynder/Api/Settings.cs
deleted file mode 100644
index 0a45069..0000000
--- a/Bynder/Api/Settings.cs
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright (c) Bynder. All rights reserved.
-// Licensed under the MIT License. See LICENSE file in the project root for full license information.
-
-using Newtonsoft.Json;
-using System.IO;
-
-namespace Bynder.Api
-{
- ///
- /// Settings needed to configure
- ///
- public class Settings
- {
- ///
- /// Oauth Consumer key
- ///
- [JsonProperty("consumer_key")]
- public string CONSUMER_KEY { get; set; }
-
- ///
- /// Oauth Consumer secret
- ///
- [JsonProperty("consumer_secret")]
- public string CONSUMER_SECRET { get; set; }
-
- ///
- /// Oauth token
- ///
- [JsonProperty("token")]
- public string TOKEN { get; set; }
-
- ///
- /// Oauth secret
- ///
- [JsonProperty("token_secret")]
- public string TOKEN_SECRET { get; set; }
-
- ///
- /// Bynder domain Url we want to communicate with
- ///
- [JsonProperty("api_base_url")]
- public string URL { get; set; }
-
- ///
- /// Create a using the given filepath
- ///
- /// JSON file path
- /// instance
- public static Settings FromJson(string filepath)
- {
- return JsonConvert.DeserializeObject(File.ReadAllText(filepath));
- }
- }
-}
diff --git a/Bynder/Models/App.config b/Bynder/Models/App.config
deleted file mode 100644
index 2d2a12d..0000000
--- a/Bynder/Models/App.config
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
diff --git a/Bynder/Models/Bynder.Models.csproj b/Bynder/Models/Bynder.Models.csproj
deleted file mode 100644
index 9e1d4e9..0000000
--- a/Bynder/Models/Bynder.Models.csproj
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
- netstandard2.0
- 1.3.0
- 1.3.0
- Bynder
- Bynder.Models
- Copyright © Bynder
-
-
-
-
-
diff --git a/Bynder/Models/User.cs b/Bynder/Models/User.cs
deleted file mode 100644
index 528cdd1..0000000
--- a/Bynder/Models/User.cs
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright (c) Bynder. All rights reserved.
-// Licensed under the MIT License. See LICENSE file in the project root for full license information.
-
-using Newtonsoft.Json;
-
-namespace Bynder.Models
-{
- ///
- /// Model returned when success login through API /login
- ///
- public class User
- {
- ///
- /// True if access was given to the username/password pair
- ///
- [JsonProperty("access")]
- public bool Access { get; set; }
-
- ///
- /// User id logged in
- ///
- [JsonProperty("userId")]
- public string UserId { get; set; }
-
- ///
- /// Token key returned by API
- ///
- [JsonProperty("tokenKey")]
- public string TokenKey { get; set; }
-
- ///
- /// Token secret returned by API
- ///
- [JsonProperty("tokenSecret")]
- public string TokenSecret { get; set; }
- }
-}
diff --git a/Bynder/Sample/ApiSample.cs b/Bynder/Sample/ApiSample.cs
index a9a056b..6aad6d4 100644
--- a/Bynder/Sample/ApiSample.cs
+++ b/Bynder/Sample/ApiSample.cs
@@ -3,9 +3,13 @@
using System;
using System.Configuration;
-using Bynder.Api;
-using Bynder.Api.Queries;
-using Bynder.Sample.OauthUtils;
+using Bynder.Sdk;
+using Bynder.Sdk.Service;
+using Bynder.Sample;
+using Bynder.Sample.Utils;
+using Bynder.Sdk.Query.Asset;
+using Bynder.Sdk.Query.Collection;
+using Bynder.Sdk.Settings;
namespace Bynder.Sample
{
@@ -21,44 +25,33 @@ public class ApiSample
/// arguments to main
public static void Main(string[] args)
{
- using (IBynderApi bynderApi = BynderApiFactory.Create(Settings.FromJson("Config.json")))
+ using(var waitForToken = new WaitForToken())
{
- // We login using the browser. To do that we have to do the following:
- // 1. Request temporary tokens
- // 2. Get an authorized Url passing a callback where we will be redirected when login is successful.
- // 3. Open a browser with the authorized Url and start listening to the callback url.
- // 4. User logs in.
- // 5. We request final access tokens.
- bynderApi.GetRequestTokenAsync().Wait();
- string token = null;
-
- using (var listener = new OauthHttpListener("http://localhost:8891/"))
+ using (var listener = new UrlHttpListener("http://localhost:8888/", waitForToken))
{
- var browser = new Browser(bynderApi.GetAuthorizeUrl("http://localhost:8891/"));
- var waitForToken = listener.WaitForToken();
- waitForToken.Wait();
- token = waitForToken.Result;
- }
+ using (var client = ClientFactory.Create(Configuration.FromJson("Config.json")))
+ {
+ Browser.Launch(client.GetOAuthService().GetAuthorisationUrl("state example", "openid offline"));
+ waitForToken.WaitHandle.WaitOne(50000);
- if (token != null)
- {
- bynderApi.GetAccessTokenAsync().Wait();
+ if (waitForToken.Success)
+ {
+ client.GetOAuthService().GetAccessTokenAsync(waitForToken.Token, "openid offline").Wait();
- // Once the user has logged in we can start doing calls to asset bank manager to
- // get media information or upload new files.
- var assetBankManager = bynderApi.GetAssetBankManager();
+ var mediaList = client.GetAssetService().GetMediaListAsync(new MediaQuery()).Result;
- var mediaList = assetBankManager.RequestMediaListAsync(new MediaQuery
- {
- Page = 1,
- Limit = 1
- }).Result;
+ foreach (var media in mediaList)
+ {
+ Console.WriteLine(media.Name);
+ }
- if (mediaList.Count > 0)
- {
- var media = assetBankManager.RequestMediaInfoAsync(new MediaInformationQuery { MediaId = mediaList[0].Id, Versions = 0 }).Result;
- assetBankManager.UploadFileAsync(new UploadQuery { Filepath = @"Image/bynder-logo.png", BrandId = media.BrandId }).Wait();
- Console.WriteLine("Uploaded file to Bynder");
+ var collectionList = client.GetCollectionService().GetCollectionsAsync(new GetCollectionsQuery()).Result;
+
+ foreach (var collection in collectionList)
+ {
+ Console.WriteLine(collection.Name);
+ }
+ }
}
}
}
diff --git a/Bynder/Sample/Bynder.Sample.csproj b/Bynder/Sample/Bynder.Sample.csproj
index da8117e..4d4b1f6 100644
--- a/Bynder/Sample/Bynder.Sample.csproj
+++ b/Bynder/Sample/Bynder.Sample.csproj
@@ -2,8 +2,8 @@
Exe
netcoreapp2.0
- 1.3.0
- 1.3.0
+ 2.0.0
+ 2.0.0
Bynder
Bynder.Sample
Copyright © Bynder
@@ -12,7 +12,7 @@
-
+
diff --git a/Bynder/Sample/Config.json b/Bynder/Sample/Config.json
index 7c25edc..f3524fa 100644
--- a/Bynder/Sample/Config.json
+++ b/Bynder/Sample/Config.json
@@ -1,5 +1,6 @@
{
- "api_base_url": "",
- "consumer_key": "",
- "consumer_secret": ""
+ "base_url": "https://example.bynder.com",
+ "client_id": "your oauth app client id",
+ "client_secret": "your oauth app client secret",
+ "redirect_uri": "your oauth app redirect uri"
}
diff --git a/Bynder/Sample/OauthUtils/OauthHttpListener.cs b/Bynder/Sample/OauthUtils/OauthHttpListener.cs
deleted file mode 100644
index e9bf69c..0000000
--- a/Bynder/Sample/OauthUtils/OauthHttpListener.cs
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright (c) Bynder. All rights reserved.
-// Licensed under the MIT License. See LICENSE file in the project root for full license information.
-
-using System;
-using System.Net;
-using System.Threading.Tasks;
-
-namespace Bynder.Sample.OauthUtils
-{
- ///
- /// Util class to listen to specific Url.
- /// It is used to login to Bynder through the browser when we specify the callback Url without the need to add any custom UI.
- ///
- public sealed class OauthHttpListener : IDisposable
- {
- ///
- /// HttpListener that listens to Url passed in the constructor
- ///
- private readonly HttpListener _listener;
-
- ///
- /// Creates a new OauthHttpListener that will listen to the Url and will notify waiting threads
- /// when oauth login has completed
- ///
- /// Url we want to listen to
- /// instance to pass token back and to notify waiting threads
- public OauthHttpListener(string url)
- {
- _listener = new HttpListener();
- _listener.Prefixes.Add(url);
- _listener.Start();
- }
-
- ///
- /// Disposes de listener
- ///
- public void Dispose()
- {
- _listener.Close();
- }
-
- ///
- /// Function that waits utils we start receiving data.
- /// We keep listening until we find oauth_token parameter in the Url.
- ///
- /// async result
- public async Task WaitForToken()
- {
- string token = null;
- HttpListenerContext context = null;
-
- // Need to check if we are being requested with oauth_token. Because sometimes we
- // would recieve the favicon call before, so we have to continue listening.
- while (token == null)
- {
- context = await _listener.GetContextAsync();
- token = context.Request.QueryString.Get("oauth_token");
- }
-
- // Obtain a response object.
- HttpListenerResponse response = context.Response;
-
- // Construct a response.
- response.RedirectLocation = @"http://www.getbynder.com/en/";
- response.StatusCode = (int)HttpStatusCode.Redirect;
- response.Close();
-
- return token;
- }
- }
-}
diff --git a/Bynder/Sample/OauthUtils/Browser.cs b/Bynder/Sample/Utils/Browser.cs
similarity index 57%
rename from Bynder/Sample/OauthUtils/Browser.cs
rename to Bynder/Sample/Utils/Browser.cs
index b1f1351..b34ac3c 100644
--- a/Bynder/Sample/OauthUtils/Browser.cs
+++ b/Bynder/Sample/Utils/Browser.cs
@@ -1,27 +1,26 @@
-// Copyright (c) Bynder. All rights reserved.
+// Copyright (c) Bynder. All rights reserved.
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
-using System;
+using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
-namespace Bynder.Sample.OauthUtils
+namespace Bynder.Sample.Utils
{
///
- /// Class to open the Browser with a specific Url.
+ /// Helper class to launch a Browser in different platforms.
///
- public sealed class Browser
+ public class Browser
{
///
- /// Creates an instance of browser that will open the default browser pointing to the Url passed.
+ /// Launch a browser using the specified URL.
///
- /// Url we want to open the browser with
- /// token to notify if possible, if the user closes the browser
- public Browser(string url)
+ /// URL.
+ public static void Launch(string url)
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
- Process.Start(new ProcessStartInfo("cmd", $"/c start {url}"));
+ Process.Start(new ProcessStartInfo("cmd", $"/c start {url}")); // Works ok on windows
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
diff --git a/Bynder/Sample/Utils/UrlHttpListener.cs b/Bynder/Sample/Utils/UrlHttpListener.cs
new file mode 100644
index 0000000..e9ae49d
--- /dev/null
+++ b/Bynder/Sample/Utils/UrlHttpListener.cs
@@ -0,0 +1,96 @@
+// Copyright (c) Bynder. All rights reserved.
+// Licensed under the MIT License. See LICENSE file in the project root for full license information.
+
+using System;
+using System.Net;
+
+namespace Bynder.Sample.Utils
+{
+ ///
+ /// Helper class to be able to catch the redirect response.
+ ///
+ public class UrlHttpListener : IDisposable
+ {
+ ///
+ /// HttpListener that listens to URL passed in the constructor.
+ ///
+ private readonly HttpListener _listener;
+
+ ///
+ /// We use this class to notify waiting threads that a call with oauth_token is done
+ /// to the URL we are listening to.
+ ///
+ private readonly WaitForToken _waitForTokenHandle;
+
+ ///
+ /// Creates a new OAuthHttpListener that will listen to the URL and will notify waiting threads
+ /// when oauth login has completed
+ ///
+ /// URL we want to listen to
+ /// instance to pass token back and to notify waiting threads
+ public UrlHttpListener(string url, WaitForToken waitForTokenHandle)
+ {
+ _listener = new HttpListener();
+ _listener.Prefixes.Add(url);
+ _waitForTokenHandle = waitForTokenHandle;
+ _listener.Start();
+ _listener.BeginGetContext(new AsyncCallback(BeginContextCallback), _listener);
+ }
+
+ ///
+ /// Disposes the listener
+ ///
+ public void Dispose()
+ {
+ _listener.Close();
+ }
+
+ ///
+ /// Function callback that is called when we start receiving data.
+ /// We keep listening until we find oauth_token parameter in the URL.
+ ///
+ /// async result
+ private void BeginContextCallback(IAsyncResult result)
+ {
+ HttpListener listener = (HttpListener)result.AsyncState;
+
+ // Call EndGetContext to complete the asynchronous operation.
+ HttpListenerContext context;
+ try
+ {
+ context = listener.EndGetContext(result);
+ }
+ catch (ObjectDisposedException)
+ {
+ // When Close this method is called with disposed object. Just swallow the exception
+ return;
+ }
+
+ HttpListenerRequest request = context.Request;
+
+ // Need to check if we are being requested with oauth_token. Because sometimes we
+ // would recieve the favicon call before, so we have to continue listening.
+ if (!request.RawUrl.Contains("code"))
+ {
+ _listener.BeginGetContext(new AsyncCallback(BeginContextCallback), _listener);
+ return;
+ }
+
+ var token = request.QueryString["code"];
+ _waitForTokenHandle.Success = token != null;
+ if (token != null)
+ {
+ _waitForTokenHandle.Token = token;
+ }
+
+ // Obtain a response object.
+ HttpListenerResponse response = context.Response;
+
+ // Construct a response.
+ response.StatusCode = (int)HttpStatusCode.Redirect;
+ response.Close();
+
+ _waitForTokenHandle.WaitHandle.Set();
+ }
+ }
+}
diff --git a/Bynder/Sample/OauthUtils/WaitForToken.cs b/Bynder/Sample/Utils/WaitForToken.cs
similarity index 90%
rename from Bynder/Sample/OauthUtils/WaitForToken.cs
rename to Bynder/Sample/Utils/WaitForToken.cs
index c990f42..80f8fe2 100644
--- a/Bynder/Sample/OauthUtils/WaitForToken.cs
+++ b/Bynder/Sample/Utils/WaitForToken.cs
@@ -4,7 +4,7 @@
using System;
using System.Threading;
-namespace Bynder.Sample.OauthUtils
+namespace Bynder.Sample.Utils
{
///
/// Class to notify waiting threads when oauth login proccess ended.
@@ -17,7 +17,7 @@ public sealed class WaitForToken : IDisposable
public bool Success { get; set; } = false;
///
- /// Token passed in the Url when login is successful
+ /// Token passed in the URL when login is successful.
///
public string Token { get; set; }
diff --git a/Bynder/Models/Converter/BooleanJsonConverter.cs b/Bynder/Sdk/Api/Converters/BooleanJsonConverter.cs
similarity index 94%
rename from Bynder/Models/Converter/BooleanJsonConverter.cs
rename to Bynder/Sdk/Api/Converters/BooleanJsonConverter.cs
index d9726f9..cdde87e 100644
--- a/Bynder/Models/Converter/BooleanJsonConverter.cs
+++ b/Bynder/Sdk/Api/Converters/BooleanJsonConverter.cs
@@ -4,13 +4,13 @@
using System;
using Newtonsoft.Json;
-namespace Bynder.Models.Converter
+namespace Bynder.Sdk.Api.Converters
{
///
/// Class used during Json deserialization to convert 0/1 to boolean members. We need it because the default bool converter only works if
/// value to convert is "true"/"false".
///
- internal class BooleanJsonConverter : JsonConverter
+ internal class BooleanJsonConverter : Newtonsoft.Json.JsonConverter
{
///
/// Checks if this converter can convert to a specific type.
diff --git a/Bynder/Api/Converters/DateTimeOffsetConverter.cs b/Bynder/Sdk/Api/Converters/DateTimeOffsetConverter.cs
similarity index 97%
rename from Bynder/Api/Converters/DateTimeOffsetConverter.cs
rename to Bynder/Sdk/Api/Converters/DateTimeOffsetConverter.cs
index 3e506b3..3f9d824 100644
--- a/Bynder/Api/Converters/DateTimeOffsetConverter.cs
+++ b/Bynder/Sdk/Api/Converters/DateTimeOffsetConverter.cs
@@ -3,7 +3,7 @@
using System;
-namespace Bynder.Api.Converters
+namespace Bynder.Sdk.Api.Converters
{
///
/// Class to convert DateTime to a string formated as followed yyyy-MM-ddTHH:mm:ssZ
diff --git a/Bynder/Api/Converters/ITypeToStringConverter.cs b/Bynder/Sdk/Api/Converters/ITypeToStringConverter.cs
similarity index 96%
rename from Bynder/Api/Converters/ITypeToStringConverter.cs
rename to Bynder/Sdk/Api/Converters/ITypeToStringConverter.cs
index edc0289..63b6b83 100644
--- a/Bynder/Api/Converters/ITypeToStringConverter.cs
+++ b/Bynder/Sdk/Api/Converters/ITypeToStringConverter.cs
@@ -3,7 +3,7 @@
using System;
-namespace Bynder.Api.Converters
+namespace Bynder.Sdk.Api.Converters
{
///
/// Interface for type converters used to decode specific
diff --git a/Bynder/Api/Converters/JsonConverter.cs b/Bynder/Sdk/Api/Converters/JsonConverter.cs
similarity index 96%
rename from Bynder/Api/Converters/JsonConverter.cs
rename to Bynder/Sdk/Api/Converters/JsonConverter.cs
index 4113109..04a474d 100644
--- a/Bynder/Api/Converters/JsonConverter.cs
+++ b/Bynder/Sdk/Api/Converters/JsonConverter.cs
@@ -4,7 +4,7 @@
using System;
using Newtonsoft.Json;
-namespace Bynder.Api.Converters
+namespace Bynder.Sdk.Api.Converters
{
///
/// Class to convert objects to their Json string representation
diff --git a/Bynder/Api/Converters/ListConverter.cs b/Bynder/Sdk/Api/Converters/ListConverter.cs
similarity index 97%
rename from Bynder/Api/Converters/ListConverter.cs
rename to Bynder/Sdk/Api/Converters/ListConverter.cs
index 55f37d1..1d50e88 100644
--- a/Bynder/Api/Converters/ListConverter.cs
+++ b/Bynder/Sdk/Api/Converters/ListConverter.cs
@@ -4,7 +4,7 @@
using System;
using System.Collections.Generic;
-namespace Bynder.Api.Converters
+namespace Bynder.Sdk.Api.Converters
{
///
/// Class used to convert IEnumerable{string} to string.
diff --git a/Bynder/Api/Converters/LowerCaseEnumConverter.cs b/Bynder/Sdk/Api/Converters/LowerCaseEnumConverter.cs
similarity index 97%
rename from Bynder/Api/Converters/LowerCaseEnumConverter.cs
rename to Bynder/Sdk/Api/Converters/LowerCaseEnumConverter.cs
index adce29f..24d4a25 100644
--- a/Bynder/Api/Converters/LowerCaseEnumConverter.cs
+++ b/Bynder/Sdk/Api/Converters/LowerCaseEnumConverter.cs
@@ -3,7 +3,7 @@
using System;
-namespace Bynder.Api.Converters
+namespace Bynder.Sdk.Api.Converters
{
///
/// Class used to convert Enums or nullable Enums to their enumerator's name lowered case string.
diff --git a/Bynder/Sdk/Api/RequestSender/ApiRequestSender.cs b/Bynder/Sdk/Api/RequestSender/ApiRequestSender.cs
new file mode 100644
index 0000000..076388d
--- /dev/null
+++ b/Bynder/Sdk/Api/RequestSender/ApiRequestSender.cs
@@ -0,0 +1,166 @@
+// Copyright (c) Bynder. All rights reserved.
+// Licensed under the MIT License. See LICENSE file in the project root for full license information.
+
+using System;
+using System.Collections.Generic;
+using System.Net.Http;
+using System.Net.Http.Headers;
+using System.Threading;
+using System.Threading.Tasks;
+using Bynder.Sdk.Model;
+using Bynder.Sdk.Api.Requests;
+using Bynder.Sdk.Service;
+using Newtonsoft.Json;
+using Bynder.Sdk.Query.Decoder;
+using Bynder.Sdk.Query;
+using Bynder.Sdk.Settings;
+
+namespace Bynder.Sdk.Api.RequestSender
+{
+ ///
+ /// Implementation of interface.
+ ///
+ internal class ApiRequestSender : IApiRequestSender
+ {
+ private readonly Configuration _configuration;
+ private readonly QueryDecoder _queryDecoder = new QueryDecoder();
+ private readonly ICredentials _credentials;
+ private SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1);
+ private IHttpRequestSender _httpSender;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Configuration.
+ /// Credentials to use in authorized requests and to refresh tokens
+ /// HTTP instance to send API requests
+ internal ApiRequestSender(Configuration configuration, ICredentials credentials, IHttpRequestSender httpSender)
+ {
+ _configuration = configuration;
+ _httpSender = httpSender;
+ _credentials = credentials;
+ }
+
+ ///
+ /// Create an instance of given the specified configuration and credentials.
+ ///
+ /// The instance.
+ /// Configuration.
+ /// Credentials.
+ public static IApiRequestSender Create(Configuration configuration, ICredentials credentials)
+ {
+ return new ApiRequestSender(configuration, credentials, new HttpRequestSender());
+ }
+
+ ///
+ /// Releases all resources used by the object.
+ ///
+ /// Call when you are finished using the . The
+ /// method leaves the in an unusable state. After
+ /// calling , you must release all references to the
+ /// so the garbage collector can reclaim the memory that the
+ /// was occupying.
+ public void Dispose()
+ {
+ _httpSender.Dispose();
+ }
+
+ ///
+ /// Check .
+ ///
+ /// Check .
+ /// Check .
+ /// Check .
+ public async Task SendRequestAsync(Requests.Request request)
+ {
+ if (request.Authenticated && !_credentials.AreValid())
+ {
+ await _semaphore.WaitAsync().ConfigureAwait(false);
+ if (!_credentials.AreValid())
+ {
+ try
+ {
+ await RefreshToken().ConfigureAwait(false);
+ }
+ finally
+ {
+ _semaphore.Release();
+ }
+ }
+ }
+
+ var httpRequest = CreateHttpRequest(request);
+ var responseString = await _httpSender.SendHttpRequest(httpRequest).ConfigureAwait(false);
+ if (!string.IsNullOrEmpty(responseString))
+ {
+ return JsonConvert.DeserializeObject(responseString);
+ }
+
+ return default(T);
+ }
+
+ private HttpRequestMessage CreateHttpRequest(Requests.Request request)
+ {
+ var parameters = _queryDecoder.GetParameters(request.Query);
+ var httpRequestMessage = HttpRequestMessageFactory.Create(
+ _configuration.BaseUrl.ToString(),
+ request.HTTPMethod,
+ parameters,
+ request.Path);
+
+ if (request.Authenticated)
+ {
+ httpRequestMessage.Headers.Authorization =
+ new AuthenticationHeaderValue(_credentials.TokenType, _credentials.AccessToken);
+ }
+
+ return httpRequestMessage;
+ }
+
+ private async Task RefreshToken()
+ {
+ TokenQuery query = new TokenQuery
+ {
+ ClientId = _configuration.ClientId,
+ ClientSecret = _configuration.ClientSecret,
+ RefreshToken = _credentials.RefreshToken,
+ GrantType = "refresh_token"
+ };
+
+ var request = new OAuthRequest
+ {
+ Authenticated = false,
+ Query = query,
+ Path = $"/oauth2/token",
+ HTTPMethod = HttpMethod.Post
+ };
+
+ var newToken = await SendRequestAsync(request).ConfigureAwait(false);
+
+ _credentials.Update(newToken);
+ }
+
+ private static class HttpRequestMessageFactory
+ {
+ internal static HttpRequestMessage Create(
+ string baseUrl, HttpMethod method, IDictionary requestParams, string urlPath)
+ {
+ var builder = new UriBuilder(baseUrl);
+ builder.Path = urlPath;
+
+ if (HttpMethod.Get == method)
+ {
+ builder.Query = Utils.Url.ConvertToQuery(requestParams);
+ }
+
+ HttpRequestMessage requestMessage = new HttpRequestMessage(method, builder.ToString());
+ if (HttpMethod.Post == method)
+ {
+ requestMessage.Content = new FormUrlEncodedContent(requestParams);
+ }
+
+ return requestMessage;
+ }
+ }
+ }
+}
diff --git a/Bynder/Sdk/Api/RequestSender/HttpRequestSender.cs b/Bynder/Sdk/Api/RequestSender/HttpRequestSender.cs
new file mode 100644
index 0000000..efafd6c
--- /dev/null
+++ b/Bynder/Sdk/Api/RequestSender/HttpRequestSender.cs
@@ -0,0 +1,43 @@
+// Copyright (c) Bynder. All rights reserved.
+// Licensed under the MIT License. See LICENSE file in the project root for full license information.
+
+using System.Net.Http;
+using System.Threading.Tasks;
+
+namespace Bynder.Sdk.Api.RequestSender
+{
+ ///
+ /// HTTP request sender. Used to send HTTP Requests.
+ /// It eases unit testing of other components checking that correct requests are being sent.
+ ///
+ internal class HttpRequestSender : IHttpRequestSender
+ {
+ private readonly HttpClient _httpClient = new HttpClient();
+
+ ///
+ /// Sends the HTTP request and returns the content as string.
+ ///
+ /// The HTTP request response.
+ /// HTTP request.
+ public async Task SendHttpRequest(HttpRequestMessage httpRequest)
+ {
+ var response = await _httpClient.SendAsync(httpRequest).ConfigureAwait(false);
+
+ response.EnsureSuccessStatusCode();
+ return await response.Content.ReadAsStringAsync().ConfigureAwait(false);
+ }
+
+ ///
+ /// Releases all resources used by the object.
+ ///
+ /// Call when you are finished using the . The
+ /// method leaves the in an unusable state. After
+ /// calling , you must release all references to the
+ /// so the garbage collector can reclaim the memory that the
+ /// was occupying.
+ public void Dispose()
+ {
+ _httpClient.Dispose();
+ }
+ }
+}
diff --git a/Bynder/Sdk/Api/RequestSender/IApiRequestSender.cs b/Bynder/Sdk/Api/RequestSender/IApiRequestSender.cs
new file mode 100644
index 0000000..4b289cf
--- /dev/null
+++ b/Bynder/Sdk/Api/RequestSender/IApiRequestSender.cs
@@ -0,0 +1,25 @@
+// Copyright (c) Bynder. All rights reserved.
+// Licensed under the MIT License. See LICENSE file in the project root for full license information.
+
+
+using System;
+using System.Threading.Tasks;
+using Bynder.Sdk.Api.Requests;
+
+namespace Bynder.Sdk.Api.RequestSender
+{
+ ///
+ /// API request sender interface. All requests to Bynder are done using
+ /// this request sender.
+ ///
+ internal interface IApiRequestSender : IDisposable
+ {
+ ///
+ /// Sends the request async.
+ ///
+ /// The deserialized response.
+ /// Request.
+ /// Type we want to deserialize response to.
+ Task SendRequestAsync(Request request);
+ }
+}
diff --git a/Bynder/Sdk/Api/RequestSender/IHttpRequestSender.cs b/Bynder/Sdk/Api/RequestSender/IHttpRequestSender.cs
new file mode 100644
index 0000000..7b52963
--- /dev/null
+++ b/Bynder/Sdk/Api/RequestSender/IHttpRequestSender.cs
@@ -0,0 +1,23 @@
+// Copyright (c) Bynder. All rights reserved.
+// Licensed under the MIT License. See LICENSE file in the project root for full license information.
+
+using System;
+using System.Net.Http;
+using System.Threading.Tasks;
+
+namespace Bynder.Sdk.Api.RequestSender
+{
+ ///
+ /// HTTP request sender. Used to send HTTP Requests.
+ /// It eases unit testing of other components checking that correct requests are being sent.
+ ///
+ internal interface IHttpRequestSender : IDisposable
+ {
+ ///
+ /// Sends the HTTP request and returns the content as string.
+ ///
+ /// The HTTP request response.
+ /// HTTP request.
+ Task SendHttpRequest(HttpRequestMessage httpRequest);
+ }
+}
diff --git a/Bynder/Sdk/Api/Requests/ApiRequest.cs b/Bynder/Sdk/Api/Requests/ApiRequest.cs
new file mode 100644
index 0000000..d83f23b
--- /dev/null
+++ b/Bynder/Sdk/Api/Requests/ApiRequest.cs
@@ -0,0 +1,13 @@
+// Copyright (c) Bynder. All rights reserved.
+// Licensed under the MIT License. See LICENSE file in the project root for full license information.
+
+namespace Bynder.Sdk.Api.Requests
+{
+ ///
+ /// API request.
+ ///
+ /// Type to which the response will be deserialized
+ internal class ApiRequest : Request
+ {
+ }
+}
diff --git a/Bynder/Sdk/Api/Requests/OAuthRequest.cs b/Bynder/Sdk/Api/Requests/OAuthRequest.cs
new file mode 100644
index 0000000..8ac502d
--- /dev/null
+++ b/Bynder/Sdk/Api/Requests/OAuthRequest.cs
@@ -0,0 +1,13 @@
+// Copyright (c) Bynder. All rights reserved.
+// Licensed under the MIT License. See LICENSE file in the project root for full license information.
+
+namespace Bynder.Sdk.Api.Requests
+{
+ ///
+ /// OAuth request.
+ ///
+ /// Type to which the response will be deserialized
+ internal class OAuthRequest : Request
+ {
+ }
+}
diff --git a/Bynder/Api/Queries/Request.cs b/Bynder/Sdk/Api/Requests/Request.cs
similarity index 60%
rename from Bynder/Api/Queries/Request.cs
rename to Bynder/Sdk/Api/Requests/Request.cs
index bc14aa8..2666939 100644
--- a/Bynder/Api/Queries/Request.cs
+++ b/Bynder/Sdk/Api/Requests/Request.cs
@@ -3,14 +3,13 @@
using System.Net.Http;
-namespace Bynder.Api.Queries
+namespace Bynder.Sdk.Api.Requests
{
///
- /// Class that contains all information to do an API request to Bynder
- /// through
+ /// API Request representation.
///
- /// type we want the response to be deserialized to
- internal class Request
+ /// Type to which the response will be deserialized
+ internal abstract class Request
{
///
/// Object with information about the API parameters to send.
@@ -18,15 +17,21 @@ internal class Request
public object Query { get; set; }
///
- /// Uri of the endpoint to call
+ /// Path of the endpoint to call.
///
- public string Uri { get; set; }
+ public string Path { get; set; }
///
- /// HttpMethod to use
+ /// HttpMethod to use.
///
public HttpMethod HTTPMethod { get; set; }
+ ///
+ /// Gets or sets a value indicating whether this is authenticated.
+ ///
+ /// true if authenticated; otherwise, false.
+ public bool Authenticated { get; set; } = true;
+
///
/// True if we want to deserialize response to .
/// However if is a string and this property has value false, we might want to get the raw string response without
diff --git a/Bynder/Api/Bynder.Api.csproj b/Bynder/Sdk/Bynder.Sdk.csproj
similarity index 77%
rename from Bynder/Api/Bynder.Api.csproj
rename to Bynder/Sdk/Bynder.Sdk.csproj
index 29b20eb..f279f63 100644
--- a/Bynder/Api/Bynder.Api.csproj
+++ b/Bynder/Sdk/Bynder.Sdk.csproj
@@ -1,19 +1,16 @@
netstandard2.0
- 1.3.0
- 1.3.0
+ 2.0.0
+ 2.0.0
Bynder
- Bynder.Api
+ Bynder.Sdk
Copyright © Bynder
-
-
-
<_Parameter1>Bynder.Test
diff --git a/Bynder/Api/Bynder.Api.nuspec b/Bynder/Sdk/Bynder.Sdk.nuspec
similarity index 96%
rename from Bynder/Api/Bynder.Api.nuspec
rename to Bynder/Sdk/Bynder.Sdk.nuspec
index ec2fc33..fe8c1c6 100644
--- a/Bynder/Api/Bynder.Api.nuspec
+++ b/Bynder/Sdk/Bynder.Sdk.nuspec
@@ -2,7 +2,7 @@
Bynder.Sdk
- 1.3.0
+ 2.0.0
Bynder.Sdk
Bynder B.V.
Bynder B.V.
diff --git a/Bynder/Api/BynderUploadException.cs b/Bynder/Sdk/Exceptions/BynderUploadException.cs
similarity index 95%
rename from Bynder/Api/BynderUploadException.cs
rename to Bynder/Sdk/Exceptions/BynderUploadException.cs
index 3010cb4..698999f 100644
--- a/Bynder/Api/BynderUploadException.cs
+++ b/Bynder/Sdk/Exceptions/BynderUploadException.cs
@@ -3,7 +3,7 @@
using System;
-namespace Bynder.Api
+namespace Bynder.Sdk.Exceptions
{
///
/// Exception thrown when Upload does not finish
diff --git a/Bynder/Sdk/Exceptions/InvalidConfigurationException.cs b/Bynder/Sdk/Exceptions/InvalidConfigurationException.cs
new file mode 100644
index 0000000..0638265
--- /dev/null
+++ b/Bynder/Sdk/Exceptions/InvalidConfigurationException.cs
@@ -0,0 +1,23 @@
+// Copyright (c) Bynder. All rights reserved.
+// Licensed under the MIT License. See LICENSE file in the project root for full license information.
+
+using System;
+
+namespace Bynder.Sdk.Exceptions
+{
+ ///
+ /// Invalid configuration exception. Raised when an invalid configuration
+ /// is passed to .
+ ///
+ public class InvalidConfigurationException : Exception
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Reason of the exception.
+ public InvalidConfigurationException(string message)
+ : base(message)
+ {
+ }
+ }
+}
diff --git a/Bynder/Sdk/Exceptions/MissingTokenException.cs b/Bynder/Sdk/Exceptions/MissingTokenException.cs
new file mode 100644
index 0000000..b089bfe
--- /dev/null
+++ b/Bynder/Sdk/Exceptions/MissingTokenException.cs
@@ -0,0 +1,23 @@
+// Copyright (c) Bynder. All rights reserved.
+// Licensed under the MIT License. See LICENSE file in the project root for full license information.
+
+using System;
+
+namespace Bynder.Sdk.Exceptions
+{
+ ///
+ /// Missing token exception. Exception raised when trying to use
+ /// without a valid token
+ ///
+ public class MissingTokenException : Exception
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Exception reason
+ public MissingTokenException(string message)
+ : base(message)
+ {
+ }
+ }
+}
diff --git a/Bynder/Models/AssetType.cs b/Bynder/Sdk/Model/AssetType.cs
similarity index 95%
rename from Bynder/Models/AssetType.cs
rename to Bynder/Sdk/Model/AssetType.cs
index cc2be18..e527a9f 100644
--- a/Bynder/Models/AssetType.cs
+++ b/Bynder/Sdk/Model/AssetType.cs
@@ -1,7 +1,7 @@
// Copyright (c) Bynder. All rights reserved.
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
-namespace Bynder.Models
+namespace Bynder.Sdk.Model
{
///
/// Possible types of assets
diff --git a/Bynder/Models/Brand.cs b/Bynder/Sdk/Model/Brand.cs
similarity index 96%
rename from Bynder/Models/Brand.cs
rename to Bynder/Sdk/Model/Brand.cs
index e1536ae..e1de3f5 100644
--- a/Bynder/Models/Brand.cs
+++ b/Bynder/Sdk/Model/Brand.cs
@@ -3,7 +3,7 @@
using Newtonsoft.Json;
-namespace Bynder.Models
+namespace Bynder.Sdk.Model
{
///
/// Brand information.
diff --git a/Bynder/Models/Collection.cs b/Bynder/Sdk/Model/Collection.cs
similarity index 98%
rename from Bynder/Models/Collection.cs
rename to Bynder/Sdk/Model/Collection.cs
index 9ebca2a..8eaffe3 100644
--- a/Bynder/Models/Collection.cs
+++ b/Bynder/Sdk/Model/Collection.cs
@@ -4,7 +4,7 @@
using System;
using Newtonsoft.Json;
-namespace Bynder.Models
+namespace Bynder.Sdk.Model
{
///
/// Model describing a collection
diff --git a/Bynder/Models/CollectionCover.cs b/Bynder/Sdk/Model/CollectionCover.cs
similarity index 96%
rename from Bynder/Models/CollectionCover.cs
rename to Bynder/Sdk/Model/CollectionCover.cs
index d0e8708..47cbc7b 100644
--- a/Bynder/Models/CollectionCover.cs
+++ b/Bynder/Sdk/Model/CollectionCover.cs
@@ -5,7 +5,7 @@
using System.Collections.Generic;
using Newtonsoft.Json;
-namespace Bynder.Models
+namespace Bynder.Sdk.Model
{
///
/// Model describing the cover of a collection
diff --git a/Bynder/Models/DownloadFileUrl.cs b/Bynder/Sdk/Model/DownloadFileUrl.cs
similarity index 94%
rename from Bynder/Models/DownloadFileUrl.cs
rename to Bynder/Sdk/Model/DownloadFileUrl.cs
index 43b7bf9..c5c6803 100644
--- a/Bynder/Models/DownloadFileUrl.cs
+++ b/Bynder/Sdk/Model/DownloadFileUrl.cs
@@ -4,7 +4,7 @@
using System;
using Newtonsoft.Json;
-namespace Bynder.Models
+namespace Bynder.Sdk.Model
{
///
/// Model returned by media_id/download/item_id
diff --git a/Bynder/Models/FinalizeResponse.cs b/Bynder/Sdk/Model/FinalizeResponse.cs
similarity index 94%
rename from Bynder/Models/FinalizeResponse.cs
rename to Bynder/Sdk/Model/FinalizeResponse.cs
index 46ba869..1b27117 100644
--- a/Bynder/Models/FinalizeResponse.cs
+++ b/Bynder/Sdk/Model/FinalizeResponse.cs
@@ -3,7 +3,7 @@
using Newtonsoft.Json;
-namespace Bynder.Models
+namespace Bynder.Sdk.Model
{
///
/// Model returned by /finalize for uploads
diff --git a/Bynder/Models/Media.cs b/Bynder/Sdk/Model/Media.cs
similarity index 98%
rename from Bynder/Models/Media.cs
rename to Bynder/Sdk/Model/Media.cs
index 0f7eae0..d8220dd 100644
--- a/Bynder/Models/Media.cs
+++ b/Bynder/Sdk/Model/Media.cs
@@ -3,10 +3,10 @@
using System.Collections.Generic;
using Newtonsoft.Json;
-using Bynder.Models.Converter;
using Newtonsoft.Json.Linq;
+using Bynder.Sdk.Api.Converters;
-namespace Bynder.Models
+namespace Bynder.Sdk.Model
{
///
/// Media model returned by API /media
diff --git a/Bynder/Models/MediaItem.cs b/Bynder/Sdk/Model/MediaItem.cs
similarity index 96%
rename from Bynder/Models/MediaItem.cs
rename to Bynder/Sdk/Model/MediaItem.cs
index 0716216..be46cc7 100644
--- a/Bynder/Models/MediaItem.cs
+++ b/Bynder/Sdk/Model/MediaItem.cs
@@ -2,10 +2,10 @@
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
using System.ComponentModel;
-using Bynder.Models.Converter;
+using Bynder.Sdk.Api.Converters;
using Newtonsoft.Json;
-namespace Bynder.Models
+namespace Bynder.Sdk.Model
{
///
/// Media Item specific information received from of IAssetBankManager
diff --git a/Bynder/Models/MetaProperty.cs b/Bynder/Sdk/Model/Metaproperty.cs
similarity index 97%
rename from Bynder/Models/MetaProperty.cs
rename to Bynder/Sdk/Model/Metaproperty.cs
index 3028027..ce101e2 100644
--- a/Bynder/Models/MetaProperty.cs
+++ b/Bynder/Sdk/Model/Metaproperty.cs
@@ -2,10 +2,10 @@
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
using System.Collections.Generic;
-using Bynder.Models.Converter;
+using Bynder.Sdk.Api.Converters;
using Newtonsoft.Json;
-namespace Bynder.Models
+namespace Bynder.Sdk.Model
{
///
/// Model to represent a metaproperty
diff --git a/Bynder/Models/MetapropertyOption.cs b/Bynder/Sdk/Model/MetapropertyOption.cs
similarity index 96%
rename from Bynder/Models/MetapropertyOption.cs
rename to Bynder/Sdk/Model/MetapropertyOption.cs
index ae25448..c4f17e3 100644
--- a/Bynder/Models/MetapropertyOption.cs
+++ b/Bynder/Sdk/Model/MetapropertyOption.cs
@@ -2,10 +2,10 @@
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
using System.Collections.Generic;
-using Bynder.Models.Converter;
+using Bynder.Sdk.Api.Converters;
using Newtonsoft.Json;
-namespace Bynder.Models
+namespace Bynder.Sdk.Model
{
///
/// Model to represent metaproperty options
diff --git a/Bynder/Models/MultipartParameters.cs b/Bynder/Sdk/Model/MultipartParameters.cs
similarity index 98%
rename from Bynder/Models/MultipartParameters.cs
rename to Bynder/Sdk/Model/MultipartParameters.cs
index 924933a..583624b 100644
--- a/Bynder/Models/MultipartParameters.cs
+++ b/Bynder/Sdk/Model/MultipartParameters.cs
@@ -3,7 +3,7 @@
using Newtonsoft.Json;
-namespace Bynder.Models
+namespace Bynder.Sdk.Model
{
///
/// Parameters needed to upload a part to Amazon. This model is only and should
diff --git a/Bynder/Models/PollStatus.cs b/Bynder/Sdk/Model/PollStatus.cs
similarity index 96%
rename from Bynder/Models/PollStatus.cs
rename to Bynder/Sdk/Model/PollStatus.cs
index 3ac2318..e3ceb30 100644
--- a/Bynder/Models/PollStatus.cs
+++ b/Bynder/Sdk/Model/PollStatus.cs
@@ -4,7 +4,7 @@
using System.Collections.Generic;
using Newtonsoft.Json;
-namespace Bynder.Models
+namespace Bynder.Sdk.Model
{
///
/// Model for the/poll response of the API. This model is only and should
diff --git a/Bynder/Models/S3File.cs b/Bynder/Sdk/Model/S3File.cs
similarity index 96%
rename from Bynder/Models/S3File.cs
rename to Bynder/Sdk/Model/S3File.cs
index a4d3310..25f9fef 100644
--- a/Bynder/Models/S3File.cs
+++ b/Bynder/Sdk/Model/S3File.cs
@@ -3,7 +3,7 @@
using Newtonsoft.Json;
-namespace Bynder.Models
+namespace Bynder.Sdk.Model
{
///
/// Model for the /upload/init/ response of the API. This model is only and should
diff --git a/Bynder/Models/Thumbnails.cs b/Bynder/Sdk/Model/Thumbnails.cs
similarity index 97%
rename from Bynder/Models/Thumbnails.cs
rename to Bynder/Sdk/Model/Thumbnails.cs
index 8145b8b..7eab247 100644
--- a/Bynder/Models/Thumbnails.cs
+++ b/Bynder/Sdk/Model/Thumbnails.cs
@@ -5,7 +5,7 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
-namespace Bynder.Models
+namespace Bynder.Sdk.Model
{
///
/// Model to represent the thumbnails of a media asset
diff --git a/Bynder/Sdk/Model/Token.cs b/Bynder/Sdk/Model/Token.cs
new file mode 100644
index 0000000..08542de
--- /dev/null
+++ b/Bynder/Sdk/Model/Token.cs
@@ -0,0 +1,77 @@
+// Copyright (c) Bynder. All rights reserved.
+// Licensed under the MIT License. See LICENSE file in the project root for full license information.
+
+using System;
+using Newtonsoft.Json;
+
+namespace Bynder.Sdk.Model
+{
+ ///
+ /// Token Model returned when OAuth2 flow finishes or when
+ /// the access token is refreshed
+ ///
+ public class Token
+ {
+ ///
+ /// Gets the access token. Used to do authenticated requests to the API.
+ ///
+ /// The access token.
+ [JsonProperty("access_token")]
+ public string AccessToken { get; set; }
+
+ ///
+ /// Gets the number of milliseconds it will take for the access token to expire.
+ ///
+ /// Number of milliseconds
+ [JsonProperty("expires_in")]
+ public int ExpiresIn { get; set; }
+
+ ///
+ /// Gets or sets the id of the token.
+ ///
+ /// The id of the token.
+ [JsonProperty("id_token")]
+ public string TokenId { get; set; }
+
+ ///
+ /// Gets or sets the type of the token.
+ ///
+ /// The type of the token.
+ [JsonProperty("token_type")]
+ public string TokenType { get; set; }
+
+ ///
+ /// Gets or sets the scope.
+ ///
+ /// The scope.
+ [JsonProperty("scope")]
+ public string Scope { get; set; }
+
+ ///
+ /// Gets the refresh token. Used to get new access tokens
+ ///
+ /// The refresh token.
+ [JsonProperty("refresh_token")]
+ public string RefreshToken { get; set; }
+
+ private DateTimeOffset AccessTokenExpiration;
+
+ ///
+ /// Gets the access token expiration.
+ ///
+ /// The access token expiration.
+ public DateTimeOffset GetAccessTokenExpiration()
+ {
+ return AccessTokenExpiration;
+ }
+
+ ///
+ /// Sets the access token expiration according to its ExpiresIn value.
+ ///
+ /// The access token expiration.
+ public void SetAccessTokenExpiration()
+ {
+ AccessTokenExpiration = DateTimeOffset.Now.AddSeconds(ExpiresIn);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Bynder/Models/UploadRequest.cs b/Bynder/Sdk/Model/UploadRequest.cs
similarity index 97%
rename from Bynder/Models/UploadRequest.cs
rename to Bynder/Sdk/Model/UploadRequest.cs
index 2f7cd0c..929881b 100644
--- a/Bynder/Models/UploadRequest.cs
+++ b/Bynder/Sdk/Model/UploadRequest.cs
@@ -3,7 +3,7 @@
using Newtonsoft.Json;
-namespace Bynder.Models
+namespace Bynder.Sdk.Model
{
///
/// Model to get the information to start an upload /upload/init. This model is only and should
diff --git a/Bynder/Api/Queries/DownloadMediaQuery.cs b/Bynder/Sdk/Query/Asset/DownloadMediaQuery.cs
similarity index 94%
rename from Bynder/Api/Queries/DownloadMediaQuery.cs
rename to Bynder/Sdk/Query/Asset/DownloadMediaQuery.cs
index 34fae76..c90183f 100644
--- a/Bynder/Api/Queries/DownloadMediaQuery.cs
+++ b/Bynder/Sdk/Query/Asset/DownloadMediaQuery.cs
@@ -1,7 +1,7 @@
// Copyright (c) Bynder. All rights reserved.
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
-namespace Bynder.Api.Queries
+namespace Bynder.Sdk.Query.Asset
{
///
/// Query to specify the media from which we want the Url
diff --git a/Bynder/Api/Queries/MediaInformationQuery.cs b/Bynder/Sdk/Query/Asset/MediaInformationQuery.cs
similarity index 86%
rename from Bynder/Api/Queries/MediaInformationQuery.cs
rename to Bynder/Sdk/Query/Asset/MediaInformationQuery.cs
index 97fc1a7..9d5e12a 100644
--- a/Bynder/Api/Queries/MediaInformationQuery.cs
+++ b/Bynder/Sdk/Query/Asset/MediaInformationQuery.cs
@@ -1,7 +1,9 @@
// Copyright (c) Bynder. All rights reserved.
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
-namespace Bynder.Api.Queries
+using Bynder.Sdk.Query.Decoder;
+
+namespace Bynder.Sdk.Query.Asset
{
///
/// Query used to get media information including media items
@@ -16,7 +18,7 @@ public class MediaInformationQuery
///
/// This property has to be set to 1 so API returns media items
///
- [APIField("versions")]
+ [ApiField("versions")]
public int Versions { get; set; } = 1;
}
}
diff --git a/Bynder/Api/Queries/MediaQuery.cs b/Bynder/Sdk/Query/Asset/MediaQuery.cs
similarity index 78%
rename from Bynder/Api/Queries/MediaQuery.cs
rename to Bynder/Sdk/Query/Asset/MediaQuery.cs
index 11c3c51..aa5ffff 100644
--- a/Bynder/Api/Queries/MediaQuery.cs
+++ b/Bynder/Sdk/Query/Asset/MediaQuery.cs
@@ -2,10 +2,11 @@
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
using System.Collections.Generic;
-using Bynder.Api.Converters;
-using Bynder.Models;
+using Bynder.Sdk.Model;
+using Bynder.Sdk.Api.Converters;
+using Bynder.Sdk.Query.Decoder;
-namespace Bynder.Api.Queries
+namespace Bynder.Sdk.Query.Asset
{
///
/// Query to filter media results
@@ -15,43 +16,43 @@ public class MediaQuery
///
/// Brand id. Specify this property if you want only media for specific brand.
///
- [APIField("brandId")]
+ [ApiField("brandId")]
public string BrandId { get; set; }
///
/// SubBrand id. Specify this property if you want only media for specific subBrand.
///
- [APIField("subBrandId")]
+ [ApiField("subBrandId")]
public string SubBrandId { get; set; }
///
/// Limit of results per request. Max 1000. Default 50.
///
- [APIField("limit")]
+ [ApiField("limit")]
public int? Limit { get; set; }
///
/// Page to be retrieved.
///
- [APIField("page")]
+ [ApiField("page")]
public int? Page { get; set; }
///
/// Keyword that the asset has to have to appear in the results
///
- [APIField("keyword")]
+ [ApiField("keyword")]
public string Keyword { get; set; }
///
/// The type of the asset
///
- [APIField("type", Converter = typeof(LowerCaseEnumConverter))]
+ [ApiField("type", Converter = typeof(LowerCaseEnumConverter))]
public AssetType? Type { get; set; }
///
/// Metaproperty option ids that the asset has to have
///
- [APIField("propertyOptionId", Converter = typeof(ListConverter))]
+ [ApiField("propertyOptionId", Converter = typeof(ListConverter))]
public IList PropertyOptionId { get; set; } = new List();
}
}
diff --git a/Bynder/Api/Queries/ModifyMediaQuery.cs b/Bynder/Sdk/Query/Asset/ModifyMediaQuery.cs
similarity index 85%
rename from Bynder/Api/Queries/ModifyMediaQuery.cs
rename to Bynder/Sdk/Query/Asset/ModifyMediaQuery.cs
index 6932775..8c753a6 100644
--- a/Bynder/Api/Queries/ModifyMediaQuery.cs
+++ b/Bynder/Sdk/Query/Asset/ModifyMediaQuery.cs
@@ -1,8 +1,8 @@
using System;
using System.Collections.Generic;
-using Bynder.Api.Converters;
+using Bynder.Sdk.Query.Decoder;
-namespace Bynder.Api.Queries
+namespace Bynder.Sdk.Query.Asset
{
///
/// Query to modify a media with
@@ -26,31 +26,31 @@ public ModifyMediaQuery(string mediaId)
///
/// Name of the media
///
- [APIField("name")]
+ [ApiField("name")]
public string Name { get; set; }
///
/// Description of the media
///
- [APIField("description")]
+ [ApiField("description")]
public string Description { get; set; }
///
/// Copyright information for the media
///
- [APIField("copyright")]
+ [ApiField("copyright")]
public string Copyright { get; set; }
///
/// Indicates if the media is archived
///
- [APIField("archive")]
+ [ApiField("archive")]
public bool Archive { get; set; }
///
/// Indicates if the media is public
///
- [APIField("isPublic")]
+ [ApiField("isPublic")]
public bool IsPublic { get; set; }
}
}
diff --git a/Bynder/Api/Queries/Collections/AddMediaQuery.cs b/Bynder/Sdk/Query/Collection/AddMediaQuery.cs
similarity index 86%
rename from Bynder/Api/Queries/Collections/AddMediaQuery.cs
rename to Bynder/Sdk/Query/Collection/AddMediaQuery.cs
index 2e6700a..da08111 100644
--- a/Bynder/Api/Queries/Collections/AddMediaQuery.cs
+++ b/Bynder/Sdk/Query/Collection/AddMediaQuery.cs
@@ -2,9 +2,10 @@
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
using System.Collections.Generic;
-using Bynder.Api.Converters;
+using Bynder.Sdk.Api.Converters;
+using Bynder.Sdk.Query.Decoder;
-namespace Bynder.Api.Queries.Collections
+namespace Bynder.Sdk.Query.Collection
{
///
/// Query used to add media to a collection
@@ -30,7 +31,7 @@ public AddMediaQuery(string collectionId, IList mediaIds)
///
/// List with the Ids of the media
///
- [APIField("data", Converter = typeof(JsonConverter))]
+ [ApiField("data", Converter = typeof(JsonConverter))]
public IList MediaIds { get; private set; }
}
}
diff --git a/Bynder/Api/Queries/Collections/CreateCollectionQuery.cs b/Bynder/Sdk/Query/Collection/CreateCollectionQuery.cs
similarity index 85%
rename from Bynder/Api/Queries/Collections/CreateCollectionQuery.cs
rename to Bynder/Sdk/Query/Collection/CreateCollectionQuery.cs
index 335e40c..8dec03c 100644
--- a/Bynder/Api/Queries/Collections/CreateCollectionQuery.cs
+++ b/Bynder/Sdk/Query/Collection/CreateCollectionQuery.cs
@@ -1,7 +1,9 @@
// Copyright (c) Bynder. All rights reserved.
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
-namespace Bynder.Api.Queries.Collections
+using Bynder.Sdk.Query.Decoder;
+
+namespace Bynder.Sdk.Query.Collection
{
///
/// Query to create collections
@@ -20,13 +22,13 @@ public CreateCollectionQuery(string name)
///
/// Name of collection
///
- [APIField("name")]
+ [ApiField("name")]
public string Name { get; private set; }
///
/// Description of collection
///
- [APIField("description")]
+ [ApiField("description")]
public string Description { get; set; }
}
}
diff --git a/Bynder/Api/Queries/Collections/GetCollectionsQuery.cs b/Bynder/Sdk/Query/Collection/GetCollectionsQuery.cs
similarity index 81%
rename from Bynder/Api/Queries/Collections/GetCollectionsQuery.cs
rename to Bynder/Sdk/Query/Collection/GetCollectionsQuery.cs
index 9c88ce1..188461c 100644
--- a/Bynder/Api/Queries/Collections/GetCollectionsQuery.cs
+++ b/Bynder/Sdk/Query/Collection/GetCollectionsQuery.cs
@@ -1,7 +1,9 @@
// Copyright (c) Bynder. All rights reserved.
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
-namespace Bynder.Api.Queries.Collections
+using Bynder.Sdk.Query.Decoder;
+
+namespace Bynder.Sdk.Query.Collection
{
///
/// Query to retrieve a list of collections
@@ -11,13 +13,13 @@ public class GetCollectionsQuery
///
/// Limit of results per request. Max 1000. Default 50.
///
- [APIField("limit")]
+ [ApiField("limit")]
public int? Limit { get; set; }
///
/// Page to be retrieved.
///
- [APIField("page")]
+ [ApiField("page")]
public int? Page { get; set; }
}
}
diff --git a/Bynder/Api/Queries/Collections/GetMediaQuery.cs b/Bynder/Sdk/Query/Collection/GetMediaQuery.cs
similarity index 92%
rename from Bynder/Api/Queries/Collections/GetMediaQuery.cs
rename to Bynder/Sdk/Query/Collection/GetMediaQuery.cs
index 04c992b..5a62806 100644
--- a/Bynder/Api/Queries/Collections/GetMediaQuery.cs
+++ b/Bynder/Sdk/Query/Collection/GetMediaQuery.cs
@@ -1,9 +1,9 @@
// Copyright (c) Bynder. All rights reserved.
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
-using Bynder.Models;
+using Bynder.Sdk.Model;
-namespace Bynder.Api.Queries.Collections
+namespace Bynder.Sdk.Query.Collection
{
///
/// Query to get media from a collection
diff --git a/Bynder/Api/Queries/Collections/RemoveMediaQuery.cs b/Bynder/Sdk/Query/Collection/RemoveMediaQuery.cs
similarity index 85%
rename from Bynder/Api/Queries/Collections/RemoveMediaQuery.cs
rename to Bynder/Sdk/Query/Collection/RemoveMediaQuery.cs
index cf2295e..9006396 100644
--- a/Bynder/Api/Queries/Collections/RemoveMediaQuery.cs
+++ b/Bynder/Sdk/Query/Collection/RemoveMediaQuery.cs
@@ -2,10 +2,11 @@
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
using System.Collections.Generic;
-using Bynder.Api.Converters;
-using Bynder.Models;
+using Bynder.Sdk.Model;
+using Bynder.Sdk.Api.Converters;
+using Bynder.Sdk.Query.Decoder;
-namespace Bynder.Api.Queries.Collections
+namespace Bynder.Sdk.Query.Collection
{
///
/// Query to remove media from a collection
@@ -31,7 +32,7 @@ public RemoveMediaQuery(string collectionId, IList mediaIds)
///
/// List with the Ids of the media
///
- [APIField("deleteIds", Converter = typeof(ListConverter))]
+ [ApiField("deleteIds", Converter = typeof(ListConverter))]
public IList MediaIds { get; private set; }
}
}
diff --git a/Bynder/Api/Queries/Collections/ShareQuery.cs b/Bynder/Sdk/Query/Collection/ShareQuery.cs
similarity index 81%
rename from Bynder/Api/Queries/Collections/ShareQuery.cs
rename to Bynder/Sdk/Query/Collection/ShareQuery.cs
index 081712c..31141b6 100644
--- a/Bynder/Api/Queries/Collections/ShareQuery.cs
+++ b/Bynder/Sdk/Query/Collection/ShareQuery.cs
@@ -3,10 +3,10 @@
using System;
using System.Collections.Generic;
-using Bynder.Api.Converters;
-using Bynder.Api.Queries.Collections.PermissionOptions;
+using Bynder.Sdk.Api.Converters;
+using Bynder.Sdk.Query.Decoder;
-namespace Bynder.Api.Queries.Collections
+namespace Bynder.Sdk.Query.Collection
{
///
/// Query to share a collection with
@@ -34,43 +34,43 @@ public ShareQuery(string collectionId, IList recipients, SharingPermissi
///
/// Email addresses of the
///
- [APIField("recipients", Converter = typeof(ListConverter))]
+ [ApiField("recipients", Converter = typeof(ListConverter))]
public IList Recipients { get; private set; }
///
/// Permission rights of the recipients
///
- [APIField("collectionOptions", Converter = typeof(LowerCaseEnumConverter))]
+ [ApiField("collectionOptions", Converter = typeof(LowerCaseEnumConverter))]
public SharingPermission Permission { get; private set; }
///
/// Flags if the recipients should login to view the collection
///
- [APIField("loginRequired")]
+ [ApiField("loginRequired")]
public bool LoginRequired { get; set; }
///
/// Sharing start date
///
- [APIField("dateStart", Converter = typeof(DateTimeOffsetConverter))]
+ [ApiField("dateStart", Converter = typeof(DateTimeOffsetConverter))]
public DateTimeOffset? DateStart { get; set; }
///
/// Sharing end date
///
- [APIField("dateEnd", Converter = typeof(DateTimeOffsetConverter))]
+ [ApiField("dateEnd", Converter = typeof(DateTimeOffsetConverter))]
public DateTimeOffset? DateEnd { get; set; }
///
/// Flags if the recipients should recieve an email
///
- [APIField("sendMail")]
+ [ApiField("sendMail")]
public bool SendMail { get; set; }
///
/// Message to include in the email that will be sent
///
- [APIField("message")]
+ [ApiField("message")]
public string Message { get; set; }
}
}
diff --git a/Bynder/Api/Queries/Collections/PermissionOptions/SharingPermission.cs b/Bynder/Sdk/Query/Collection/SharingPermission.cs
similarity index 89%
rename from Bynder/Api/Queries/Collections/PermissionOptions/SharingPermission.cs
rename to Bynder/Sdk/Query/Collection/SharingPermission.cs
index dd8c0df..3b2f553 100644
--- a/Bynder/Api/Queries/Collections/PermissionOptions/SharingPermission.cs
+++ b/Bynder/Sdk/Query/Collection/SharingPermission.cs
@@ -1,7 +1,7 @@
// Copyright (c) Bynder. All rights reserved.
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
-namespace Bynder.Api.Queries.Collections.PermissionOptions
+namespace Bynder.Sdk.Query.Collection
{
///
/// Enum for Permission Options for sharing a collection
diff --git a/Bynder/Api/Queries/APIField.cs b/Bynder/Sdk/Query/Decoder/ApiField.cs
similarity index 89%
rename from Bynder/Api/Queries/APIField.cs
rename to Bynder/Sdk/Query/Decoder/ApiField.cs
index 189fe65..d9e8ae1 100644
--- a/Bynder/Api/Queries/APIField.cs
+++ b/Bynder/Sdk/Query/Decoder/ApiField.cs
@@ -3,20 +3,20 @@
using System;
-namespace Bynder.Api.Queries
+namespace Bynder.Sdk.Query.Decoder
{
///
/// Class to be used as attributes for properties in queries to specify
/// if property needs to be send as parameter to the API
///
[AttributeUsage(AttributeTargets.Property)]
- public class APIField : Attribute
+ public class ApiField : Attribute
{
///
/// Initializes a new instance of the class
///
/// Name of the field in the API documentation
- public APIField(string name)
+ public ApiField(string name)
{
ApiName = name;
}
diff --git a/Bynder/Sdk/Query/Decoder/IParameterDecoder.cs b/Bynder/Sdk/Query/Decoder/IParameterDecoder.cs
new file mode 100644
index 0000000..3b90f15
--- /dev/null
+++ b/Bynder/Sdk/Query/Decoder/IParameterDecoder.cs
@@ -0,0 +1,27 @@
+// Copyright (c) Bynder. All rights reserved.
+// Licensed under the MIT License. See LICENSE file in the project root for full license information.
+
+using System;
+
+namespace Bynder.Sdk.Query.Decoder
+{
+ ///
+ /// Decoder interface to use in queries to convert from one specific type to string.
+ ///
+ public interface IParameterDecoder
+ {
+ ///
+ /// Checks if the converter can convert a specific type.
+ ///
+ /// Type to convert from
+ /// true if it can convert the type
+ bool CanConvert(Type typeToConvert);
+
+ ///
+ /// Converts the value to string.
+ ///
+ /// value to be converted
+ /// converted string value
+ string Convert(object value);
+ }
+}
\ No newline at end of file
diff --git a/Bynder/Api/Queries/QueryDecoder.cs b/Bynder/Sdk/Query/Decoder/QueryDecoder.cs
similarity index 76%
rename from Bynder/Api/Queries/QueryDecoder.cs
rename to Bynder/Sdk/Query/Decoder/QueryDecoder.cs
index 1f5b854..7ffd5d4 100644
--- a/Bynder/Api/Queries/QueryDecoder.cs
+++ b/Bynder/Sdk/Query/Decoder/QueryDecoder.cs
@@ -2,31 +2,30 @@
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
using System;
+using System.Collections.Generic;
using System.Collections.Specialized;
using System.Reflection;
-using Bynder.Api.Converters;
-namespace Bynder.Api.Queries
+namespace Bynder.Sdk.Query.Decoder
{
///
- /// Class that gets a query and extracts all properties with the
- /// values and returns them in a .
+ /// Decodes query object to a dictionary of parameters.
///
internal class QueryDecoder
{
///
/// Given a query object it gets the parameters. The parameters are basically the properties
- /// of the object query that have attributes.
+ /// of the object query that have attributes.
///
/// query object
/// collection with name and value to send to the API
- public NameValueCollection GetParameters(object query)
+ public IDictionary GetParameters(object query)
{
- NameValueCollection parameters = new NameValueCollection();
+ var parameters = new Dictionary();
if (query != null)
{
- foreach (var propertyInfo in query.GetType().GetProperties())
+ foreach (var propertyInfo in query.GetType().GetTypeInfo().GetProperties())
{
ConvertProperty(propertyInfo, query, parameters);
}
@@ -36,18 +35,18 @@ public NameValueCollection GetParameters(object query)
}
///
- /// Function called for each property in a query object. It extracts the different properties
- /// with attribute and, if needed, calls appropiate converter to convert property value to string
+ /// Function called for each property in a query object. It extracts the different properties
+ /// with attribute and, if needed, calls appropiate converter to convert property value to string.
///
/// property type information
/// query object
/// collection to add the converted values
- private void ConvertProperty(PropertyInfo propertyInfo, object query, NameValueCollection collection)
+ private void ConvertProperty(PropertyInfo propertyInfo, object query, IDictionary collection)
{
var attributes = propertyInfo.GetCustomAttributes(true);
foreach (var attribute in attributes)
{
- APIField nameAttr = attribute as APIField;
+ ApiField nameAttr = attribute as ApiField;
if (nameAttr != null)
{
object value = propertyInfo.GetValue(query);
@@ -60,7 +59,7 @@ private void ConvertProperty(PropertyInfo propertyInfo, object query, NameValueC
}
}
- // No need to continue. Only one APIField attribute per property
+ // No need to continue. Only one ApiField attribute per property
return;
}
}
@@ -68,19 +67,19 @@ private void ConvertProperty(PropertyInfo propertyInfo, object query, NameValueC
///
/// Function called to convert property values to string. If no converter is
- /// specified, then .ToString is called
+ /// specified, then .ToString is called.
///
/// API field attribute
/// property type information
/// current value
/// converted value
- private string ConvertPropertyValue(APIField apiField, Type propertyType, object value)
+ private string ConvertPropertyValue(ApiField apiField, Type propertyType, object value)
{
string convertedValue = null;
bool isConverted = false;
if (apiField.Converter != null)
{
- ITypeToStringConverter converter = Activator.CreateInstance(apiField.Converter) as ITypeToStringConverter;
+ IParameterDecoder converter = Activator.CreateInstance(apiField.Converter) as IParameterDecoder;
if (converter != null
&& converter.CanConvert(propertyType))
diff --git a/Bynder/Sdk/Query/TokenQuery.cs b/Bynder/Sdk/Query/TokenQuery.cs
new file mode 100644
index 0000000..86e6549
--- /dev/null
+++ b/Bynder/Sdk/Query/TokenQuery.cs
@@ -0,0 +1,62 @@
+// Copyright (c) Bynder. All rights reserved.
+// Licensed under the MIT License. See LICENSE file in the project root for full license information.
+
+using Bynder.Sdk.Query.Decoder;
+
+namespace Bynder.Sdk.Query
+{
+ ///
+ /// Query to retrieve and refresh tokens.
+ ///
+ public class TokenQuery
+ {
+ ///
+ /// Gets or sets the client identifier.
+ ///
+ /// The client identifier.
+ [ApiField("client_id")]
+ public string ClientId { get; set; }
+
+ ///
+ /// Gets or sets the client secret.
+ ///
+ /// The client secret.
+ [ApiField("client_secret")]
+ public string ClientSecret { get; set; }
+
+ ///
+ /// Gets or sets the redirect URI.
+ ///
+ /// The redirect URI.
+ [ApiField("redirect_uri")]
+ public string RedirectUri { get; set; }
+
+ ///
+ /// Gets or sets the type of the grant.
+ ///
+ /// The type of the grant.
+ [ApiField("grant_type")]
+ public string GrantType { get; set; }
+
+ ///
+ /// Gets or sets the code.
+ ///
+ /// The code.
+ [ApiField("code")]
+ public string Code { get; set; }
+
+ ///
+ /// Gets or sets the scopes.
+ ///
+ /// The scopes.
+ [ApiField("scope")]
+ public string Scopes { get; set; }
+
+ ///
+ /// Gets or sets the refresh token.
+ ///
+ /// The refresh token.
+ [ApiField("refresh_token")]
+ public string RefreshToken { get; set; }
+ }
+}
diff --git a/Bynder/Api/Queries/FinalizeUploadQuery.cs b/Bynder/Sdk/Query/Upload/FinalizeUploadQuery.cs
similarity index 82%
rename from Bynder/Api/Queries/FinalizeUploadQuery.cs
rename to Bynder/Sdk/Query/Upload/FinalizeUploadQuery.cs
index a19228c..a26e7d0 100644
--- a/Bynder/Api/Queries/FinalizeUploadQuery.cs
+++ b/Bynder/Sdk/Query/Upload/FinalizeUploadQuery.cs
@@ -1,7 +1,9 @@
// Copyright (c) Bynder. All rights reserved.
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
-namespace Bynder.Api.Queries
+using Bynder.Sdk.Query.Decoder;
+
+namespace Bynder.Sdk.Query.Upload
{
///
/// Finalize upload information. This model should only be used by UploadFile
@@ -11,19 +13,19 @@ internal class FinalizeUploadQuery
///
/// Target id
///
- [APIField("targetid")]
+ [ApiField("targetid")]
public string TargetId { get; set; }
///
/// S3 filename
///
- [APIField("s3_filename")]
+ [ApiField("s3_filename")]
public string S3Filename { get; set; }
///
/// Number of chunks
///
- [APIField("chunks")]
+ [ApiField("chunks")]
public string Chunks { get; set; }
///
diff --git a/Bynder/Api/Queries/PollQuery.cs b/Bynder/Sdk/Query/Upload/PollQuery.cs
similarity index 77%
rename from Bynder/Api/Queries/PollQuery.cs
rename to Bynder/Sdk/Query/Upload/PollQuery.cs
index b24a772..8f9283c 100644
--- a/Bynder/Api/Queries/PollQuery.cs
+++ b/Bynder/Sdk/Query/Upload/PollQuery.cs
@@ -2,9 +2,10 @@
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
using System.Collections.Generic;
-using Bynder.Api.Converters;
+using Bynder.Sdk.Api.Converters;
+using Bynder.Sdk.Query.Decoder;
-namespace Bynder.Api.Queries
+namespace Bynder.Sdk.Query.Upload
{
///
/// Class to pass information to poll if asset has finished converting. This
@@ -15,7 +16,7 @@ internal class PollQuery
///
/// Items we want to query the status.
///
- [APIField("items", Converter = typeof(ListConverter))]
+ [ApiField("items", Converter = typeof(ListConverter))]
public IList Items { get; set; } = new List();
}
}
diff --git a/Bynder/Api/Queries/RegisterChunkQuery.cs b/Bynder/Sdk/Query/Upload/RegisterChunkQuery.cs
similarity index 83%
rename from Bynder/Api/Queries/RegisterChunkQuery.cs
rename to Bynder/Sdk/Query/Upload/RegisterChunkQuery.cs
index 13b1588..0da9b62 100644
--- a/Bynder/Api/Queries/RegisterChunkQuery.cs
+++ b/Bynder/Sdk/Query/Upload/RegisterChunkQuery.cs
@@ -1,7 +1,9 @@
// Copyright (c) Bynder. All rights reserved.
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
-namespace Bynder.Api.Queries
+using Bynder.Sdk.Query.Decoder;
+
+namespace Bynder.Sdk.Query.Upload
{
///
/// Class used to represent RegisterChunk response. This
@@ -12,19 +14,19 @@ internal class RegisterChunkQuery
///
/// Target id
///
- [APIField("targetid")]
+ [ApiField("targetid")]
public string TargetId { get; set; }
///
/// S3 filename
///
- [APIField("filename")]
+ [ApiField("filename")]
public string S3Filename { get; set; }
///
/// Chunk number
///
- [APIField("chunkNumber")]
+ [ApiField("chunkNumber")]
public string ChunkNumber { get; set; }
///
diff --git a/Bynder/Api/Queries/RequestUploadQuery.cs b/Bynder/Sdk/Query/Upload/RequestUploadQuery.cs
similarity index 83%
rename from Bynder/Api/Queries/RequestUploadQuery.cs
rename to Bynder/Sdk/Query/Upload/RequestUploadQuery.cs
index 09721f6..7726bb7 100644
--- a/Bynder/Api/Queries/RequestUploadQuery.cs
+++ b/Bynder/Sdk/Query/Upload/RequestUploadQuery.cs
@@ -1,7 +1,9 @@
// Copyright (c) Bynder. All rights reserved.
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
-namespace Bynder.Api.Queries
+using Bynder.Sdk.Query.Decoder;
+
+namespace Bynder.Sdk.Query.Upload
{
///
/// Query with the information to init an upload. This
@@ -12,7 +14,7 @@ internal class RequestUploadQuery
///
/// Filename of the file we want to initialize the upload
///
- [APIField("filename")]
+ [ApiField("filename")]
public string Filename { get; set; }
}
}
diff --git a/Bynder/Api/Queries/SaveMediaQuery.cs b/Bynder/Sdk/Query/Upload/SaveMediaQuery.cs
similarity index 88%
rename from Bynder/Api/Queries/SaveMediaQuery.cs
rename to Bynder/Sdk/Query/Upload/SaveMediaQuery.cs
index e993a18..6559e61 100644
--- a/Bynder/Api/Queries/SaveMediaQuery.cs
+++ b/Bynder/Sdk/Query/Upload/SaveMediaQuery.cs
@@ -1,7 +1,9 @@
// Copyright (c) Bynder. All rights reserved.
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
-namespace Bynder.Api.Queries
+using Bynder.Sdk.Query.Decoder;
+
+namespace Bynder.Sdk.Query.Upload
{
///
/// Query that has the information to save media.
@@ -12,13 +14,13 @@ internal class SaveMediaQuery
///
/// Brand id we want to save media to
///
- [APIField("brandid")]
+ [ApiField("brandid")]
public string BrandId { get; set; }
///
/// Name of the asset
///
- [APIField("name")]
+ [ApiField("name")]
public string Filename { get; set; }
///
diff --git a/Bynder/Api/Queries/UploadQuery.cs b/Bynder/Sdk/Query/Upload/UploadQuery.cs
similarity index 96%
rename from Bynder/Api/Queries/UploadQuery.cs
rename to Bynder/Sdk/Query/Upload/UploadQuery.cs
index 967ee63..ba27503 100644
--- a/Bynder/Api/Queries/UploadQuery.cs
+++ b/Bynder/Sdk/Query/Upload/UploadQuery.cs
@@ -1,7 +1,7 @@
// Copyright (c) Bynder. All rights reserved.
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
-namespace Bynder.Api.Queries
+namespace Bynder.Sdk.Query.Upload
{
///
/// Query with the information to upload a file
diff --git a/Bynder/Sdk/Service/Asset/AssetService.cs b/Bynder/Sdk/Service/Asset/AssetService.cs
new file mode 100644
index 0000000..c177ed7
--- /dev/null
+++ b/Bynder/Sdk/Service/Asset/AssetService.cs
@@ -0,0 +1,161 @@
+// Copyright (c) Bynder. All rights reserved.
+// Licensed under the MIT License. See LICENSE file in the project root for full license information.
+
+using System;
+using System.Collections.Generic;
+using System.Net.Http;
+using System.Threading.Tasks;
+using Bynder.Sdk.Service.Upload;
+using Bynder.Sdk.Api.Requests;
+using Bynder.Sdk.Api.RequestSender;
+using Bynder.Sdk.Model;
+using Bynder.Sdk.Query.Asset;
+using Bynder.Sdk.Query.Upload;
+
+namespace Bynder.Sdk.Service.Asset
+{
+ ///
+ /// Implementation of
+ ///
+ internal class AssetService : IAssetService
+ {
+ ///
+ /// Request sender to communicate with the Bynder API
+ ///
+ private IApiRequestSender _requestSender;
+
+ ///
+ /// Instance to upload file to Bynder
+ ///
+ private FileUploader _uploader;
+
+ ///
+ /// Initializes a new instance of the class
+ ///
+ /// instance to communicate with the Bynder API
+ public AssetService(IApiRequestSender requestSender)
+ {
+ _requestSender = requestSender;
+ _uploader = FileUploader.Create(_requestSender);
+ }
+
+ ///
+ /// Check for more information
+ ///
+ /// Check for more information
+ public Task> GetBrandsAsync()
+ {
+ var request = new ApiRequest>
+ {
+ Path = "/api/v4/brands/",
+ HTTPMethod = HttpMethod.Get
+ };
+
+ return _requestSender.SendRequestAsync(request);
+ }
+
+ ///
+ /// Check for more information
+ ///
+ /// Check for more information
+ public Task> GetMetapropertiesAsync()
+ {
+ var request = new ApiRequest>
+ {
+ Path = "/api/v4/metaproperties/",
+ HTTPMethod = HttpMethod.Get
+ };
+
+ return _requestSender.SendRequestAsync(request);
+ }
+
+ ///
+ /// Check for more information
+ ///
+ /// Check for more information
+ /// Check for more information
+ public Task> GetMediaListAsync(MediaQuery query)
+ {
+ var request = new ApiRequest>
+ {
+ Path = "/api/v4/media/",
+ HTTPMethod = HttpMethod.Get,
+ Query = query
+ };
+
+ return _requestSender.SendRequestAsync(request);
+ }
+
+ ///
+ /// Check for more information
+ ///
+ /// Check for more information
+ /// Check for more information
+ public async Task GetDownloadFileUrlAsync(DownloadMediaQuery query)
+ {
+ string path = string.Empty;
+ if (query.MediaItemId == null)
+ {
+ path = $"/api/v4/media/{query.MediaId}/download/";
+ }
+ else
+ {
+ path = $"/api/v4/media/{query.MediaId}/download/{query.MediaItemId}/";
+ }
+
+ var request = new ApiRequest
+ {
+ Path = path,
+ HTTPMethod = HttpMethod.Get
+ };
+
+ var downloadFileInformation = await _requestSender.SendRequestAsync(request).ConfigureAwait(false);
+ return downloadFileInformation.S3File;
+ }
+
+ ///
+ /// Check for more information
+ ///
+ /// Check for more information
+ /// Check for more information
+ public Task UploadFileAsync(UploadQuery query)
+ {
+ return _uploader.UploadFile(query);
+ }
+
+ ///
+ /// Check for more information
+ ///
+ /// Check for more information
+ /// Check for more information
+ public Task GetMediaInfoAsync(MediaInformationQuery query)
+ {
+ var request = new ApiRequest
+ {
+ Path = $"/api/v4/media/{query.MediaId}/",
+ HTTPMethod = HttpMethod.Get,
+ Query = query
+ };
+
+ return _requestSender.SendRequestAsync(request);
+ }
+
+ ///
+ /// Check for more information
+ ///
+ /// Check for more information
+ /// Check for more information
+ public Task ModifyMediaAsync(ModifyMediaQuery query)
+ {
+ var request = new ApiRequest
+ {
+ Path = $"/api/v4/media/{query.MediaId}/",
+ HTTPMethod = HttpMethod.Post,
+ Query = query,
+ DeserializeResponse = false
+ };
+
+ return _requestSender.SendRequestAsync(request);
+ }
+ }
+}
diff --git a/Bynder/Api/IAssetBankManager.cs b/Bynder/Sdk/Service/Asset/IAssetService.cs
similarity index 92%
rename from Bynder/Api/IAssetBankManager.cs
rename to Bynder/Sdk/Service/Asset/IAssetService.cs
index c14e567..6fc02e6 100644
--- a/Bynder/Api/IAssetBankManager.cs
+++ b/Bynder/Sdk/Service/Asset/IAssetService.cs
@@ -4,15 +4,16 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
-using Bynder.Api.Queries;
-using Bynder.Models;
+using Bynder.Sdk.Model;
+using Bynder.Sdk.Query.Asset;
+using Bynder.Sdk.Query.Upload;
-namespace Bynder.Api
+namespace Bynder.Sdk.Service.Asset
{
///
/// Interface to represent operations that can be done to the Bynder Asset Bank
///
- public interface IAssetBankManager
+ public interface IAssetService
{
///
/// Gets Brands Async
@@ -44,7 +45,7 @@ public interface IAssetBankManager
/// Information about the media we want to get the information of.
/// Task with the Media information
/// Can be thrown when requests to server can't be completed or HTTP code returned by server is an error
- Task RequestMediaInfoAsync(MediaInformationQuery query);
+ Task GetMediaInfoAsync(MediaInformationQuery query);
///
/// Gets a list of media using query information. The media information is not complete, for example
@@ -53,7 +54,7 @@ public interface IAssetBankManager
/// information to correctly filter/paginate media
/// Task with List of media.
/// Can be thrown when requests to server can't be completed or HTTP code returned by server is an error
- Task> RequestMediaListAsync(MediaQuery query);
+ Task> GetMediaListAsync(MediaQuery query);
///
/// Uploads a file async.
diff --git a/Bynder/Sdk/Service/BynderClient.cs b/Bynder/Sdk/Service/BynderClient.cs
new file mode 100644
index 0000000..8db9ac5
--- /dev/null
+++ b/Bynder/Sdk/Service/BynderClient.cs
@@ -0,0 +1,107 @@
+// Copyright (c) Bynder. All rights reserved.
+// Licensed under the MIT License. See LICENSE file in the project root for full license information.
+
+using System;
+using Bynder.Sdk.Exceptions;
+using Bynder.Sdk.Api.RequestSender;
+using Bynder.Sdk.Service.Asset;
+using Bynder.Sdk.Service.Collection;
+using Bynder.Sdk.Service.OAuth;
+using Bynder.Sdk.Settings.Validators;
+using Bynder.Sdk.Model;
+using Bynder.Sdk.Settings;
+
+namespace Bynder.Sdk.Service
+{
+ ///
+ /// Client implementation of .
+ ///
+ internal class BynderClient : IBynderClient
+ {
+ private readonly Configuration _configuration;
+ private readonly IApiRequestSender _requestSender;
+ private ICredentials _credentials;
+ private IOAuthService _oauthService;
+ private IAssetService _assetService;
+ private ICollectionService _collectionService;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Client configuration.
+ public BynderClient(Configuration configuration)
+ {
+ new ConfigurationValidator().Validate(configuration);
+ _configuration = configuration;
+ _credentials = new Credentials(configuration.Token);
+ _requestSender = ApiRequestSender.Create(_configuration, _credentials);
+ }
+
+ ///
+ /// Check
+ ///
+ public event EventHandler OnCredentialsChanged
+ {
+ add
+ {
+ _credentials.OnCredentialsChanged += value;
+ }
+
+ remove
+ {
+ _credentials.OnCredentialsChanged -= value;
+ }
+ }
+
+ ///
+ /// Releases all resource used by the object.
+ ///
+ /// Call when you are finished using the . The
+ /// method leaves the in an unusable state. After
+ /// calling , you must release all references to the so
+ /// the garbage collector can reclaim the memory that the was occupying.
+ public void Dispose()
+ {
+ _requestSender.Dispose();
+ }
+
+ ///
+ /// Check
+ ///
+ /// Check
+ public IAssetService GetAssetService()
+ {
+ if (!_credentials.AreValid() && !_credentials.CanRefresh)
+ {
+ throw new MissingTokenException("Access token expired and refresh token is missing. " +
+ "Either pass a not expited access token through configuration or login through OAuth2");
+ }
+
+ return _assetService ?? (_assetService = new AssetService(_requestSender));
+ }
+
+ ///
+ /// Check
+ ///
+ /// Check
+ public ICollectionService GetCollectionService()
+ {
+ if (!_credentials.AreValid() && !_credentials.CanRefresh)
+ {
+ throw new MissingTokenException("Access token expired and refresh token is missing. " +
+ "Either pass a not expited access token through configuration or login through OAuth2");
+ }
+
+ return _collectionService ?? (_collectionService = new CollectionService(_requestSender));
+ }
+
+ ///
+ /// Check
+ ///
+ /// Check
+ public IOAuthService GetOAuthService()
+ {
+ return _oauthService ?? (_oauthService = new OAuthService(_configuration, _credentials, _requestSender));
+ }
+ }
+}
\ No newline at end of file
diff --git a/Bynder/Sdk/Service/ClientFactory.cs b/Bynder/Sdk/Service/ClientFactory.cs
new file mode 100644
index 0000000..d5887e5
--- /dev/null
+++ b/Bynder/Sdk/Service/ClientFactory.cs
@@ -0,0 +1,23 @@
+// Copyright (c) Bynder. All rights reserved.
+// Licensed under the MIT License. See LICENSE file in the project root for full license information.
+
+using Bynder.Sdk.Settings;
+
+namespace Bynder.Sdk.Service
+{
+ ///
+ /// Factory to create Bynder Client.
+ ///
+ public static class ClientFactory
+ {
+ ///
+ /// Creates the client to be used to communicate with Bynder.
+ ///
+ /// Bynder Client.
+ /// Configuration used to create the client.
+ public static IBynderClient Create(Configuration configuration)
+ {
+ return new BynderClient(configuration);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Bynder/Sdk/Service/Collection/CollectionService.cs b/Bynder/Sdk/Service/Collection/CollectionService.cs
new file mode 100644
index 0000000..145b539
--- /dev/null
+++ b/Bynder/Sdk/Service/Collection/CollectionService.cs
@@ -0,0 +1,169 @@
+// Copyright (c) Bynder. All rights reserved.
+// Licensed under the MIT License. See LICENSE file in the project root for full license information.
+
+using System.Collections.Generic;
+using System.Net.Http;
+using System.Threading.Tasks;
+using Bynder.Sdk.Query.Collection;
+using Bynder.Sdk.Api.Requests;
+using Bynder.Sdk.Api.RequestSender;
+using Bynder.Sdk.Model;
+
+namespace Bynder.Sdk.Service.Collection
+{
+ ///
+ /// Implementation of
+ ///
+ internal class CollectionService : ICollectionService
+ {
+ ///
+ /// Request sender to communicate with the Bynder API
+ ///
+ private IApiRequestSender _requestSender;
+
+ ///
+ /// Initializes a new instance of the class
+ ///
+ /// instance to communicate with the Bynder API
+ public CollectionService(IApiRequestSender requestSender)
+ {
+ _requestSender = requestSender;
+ }
+
+ ///
+ /// Check for more information
+ ///
+ /// Check for more information
+ /// Check for more information
+ public Task CreateCollectionAsync(CreateCollectionQuery query)
+ {
+ var request = new ApiRequest
+ {
+ Path = $"/api/v4/collections/",
+ HTTPMethod = HttpMethod.Post,
+ Query = query,
+ DeserializeResponse = false
+ };
+
+ return _requestSender.SendRequestAsync(request);
+ }
+
+ ///
+ /// Check for more information
+ ///
+ /// Check for more information
+ /// Check for more information
+ public Task DeleteCollectionAsync(string id)
+ {
+ var request = new ApiRequest
+ {
+ Path = $"/api/v4/collections/{id}/",
+ HTTPMethod = HttpMethod.Delete
+ };
+
+ return _requestSender.SendRequestAsync(request);
+ }
+
+ ///
+ /// Check for more information
+ ///
+ /// Check for more information
+ /// Check for more information
+ public Task GetCollectionAsync(string id)
+ {
+ var request = new ApiRequest
+ {
+ Path = $"/api/v4/collections/{id}/",
+ HTTPMethod = HttpMethod.Get
+ };
+
+ return _requestSender.SendRequestAsync(request);
+ }
+
+ ///
+ /// Check for more information
+ ///
+ /// Check for more information
+ /// Check for more information
+ public Task> GetCollectionsAsync(GetCollectionsQuery query)
+ {
+ var request = new ApiRequest>
+ {
+ Path = "/api/v4/collections/",
+ HTTPMethod = HttpMethod.Get,
+ Query = query
+ };
+
+ return _requestSender.SendRequestAsync(request);
+ }
+
+ ///
+ /// Check for more information
+ ///
+ /// Check for more information
+ /// Check for more information
+ public Task> GetMediaAsync(GetMediaQuery query)
+ {
+ var request = new ApiRequest>
+ {
+ Path = $"/api/v4/collections/{query.CollectionId}/media/",
+ HTTPMethod = HttpMethod.Get
+ };
+
+ return _requestSender.SendRequestAsync(request);
+ }
+
+ ///
+ /// Check for more information
+ ///
+ /// Check for more information
+ /// Check for more information
+ public Task AddMediaAsync(AddMediaQuery query)
+ {
+ var request = new ApiRequest
+ {
+ Path = $"/api/v4/collections/{query.CollectionId}/media/",
+ HTTPMethod = HttpMethod.Post,
+ Query = query,
+ DeserializeResponse = false
+ };
+
+ return _requestSender.SendRequestAsync(request);
+ }
+
+ ///
+ /// Check for more information
+ ///
+ /// Check for more information
+ /// Check for more information
+ public Task RemoveMediaAsync(RemoveMediaQuery query)
+ {
+ var request = new ApiRequest
+ {
+ Path = $"/api/v4/collections/{query.CollectionId}/media/",
+ HTTPMethod = HttpMethod.Delete,
+ Query = query
+ };
+
+ return _requestSender.SendRequestAsync(request);
+ }
+
+ ///
+ /// Check for more information
+ ///
+ /// Check for more information
+ /// Check for more information
+ public Task ShareCollectionAsync(ShareQuery query)
+ {
+ var request = new ApiRequest
+ {
+ Path = $"/api/v4/collections/{query.CollectionId}/share/",
+ HTTPMethod = HttpMethod.Post,
+ Query = query,
+ DeserializeResponse = false
+ };
+
+ return _requestSender.SendRequestAsync(request);
+ }
+ }
+}
diff --git a/Bynder/Api/ICollectionsManager.cs b/Bynder/Sdk/Service/Collection/ICollectionService.cs
similarity index 92%
rename from Bynder/Api/ICollectionsManager.cs
rename to Bynder/Sdk/Service/Collection/ICollectionService.cs
index b39426b..52f97df 100644
--- a/Bynder/Api/ICollectionsManager.cs
+++ b/Bynder/Sdk/Service/Collection/ICollectionService.cs
@@ -3,22 +3,22 @@
using System.Collections.Generic;
using System.Threading.Tasks;
-using Bynder.Api.Queries.Collections;
-using Bynder.Models;
+using Bynder.Sdk.Query.Collection;
+using Bynder.Sdk.Model;
-namespace Bynder.Api
+namespace Bynder.Sdk.Service.Collection
{
///
/// Interface to represent operations that can be done to the Bynder Media Collections
///
- public interface ICollectionsManager
+ public interface ICollectionService
{
///
/// Gets Collections Async
///
/// information to correctly filter/paginate
/// Task with a list of items
- Task> GetCollectionsAsync(GetCollectionsQuery query);
+ Task> GetCollectionsAsync(GetCollectionsQuery query);
///
/// Gets a specific colection
@@ -26,7 +26,7 @@ public interface ICollectionsManager
/// The uuid of the specific
/// Task that contains the specific
/// Can be thrown when requests to server can't be completed or HTTP code returned by server is an error
- Task GetCollectionAsync(string id);
+ Task GetCollectionAsync(string id);
///
/// Creates a new Collection
diff --git a/Bynder/Sdk/Service/IBynderClient.cs b/Bynder/Sdk/Service/IBynderClient.cs
new file mode 100644
index 0000000..18b877c
--- /dev/null
+++ b/Bynder/Sdk/Service/IBynderClient.cs
@@ -0,0 +1,41 @@
+// Copyright (c) Bynder. All rights reserved.
+// Licensed under the MIT License. See LICENSE file in the project root for full license information.
+
+using System;
+using Bynder.Sdk.Service.Asset;
+using Bynder.Sdk.Service.Collection;
+using Bynder.Sdk.Service.OAuth;
+using Bynder.Sdk.Model;
+
+namespace Bynder.Sdk.Service
+{
+ ///
+ /// Bynder Client interface.
+ ///
+ public interface IBynderClient : IDisposable
+ {
+ ///
+ /// Occurs when credentials changed, and that happens every time
+ /// the access token is refreshed.
+ ///
+ event EventHandler OnCredentialsChanged;
+
+ ///
+ /// Gets the asset service to interact with assets in your Bynder portal.
+ ///
+ /// The asset service.
+ IAssetService GetAssetService();
+
+ ///
+ /// Gets the collection service to interact with collections in your Bynder portal.
+ ///
+ /// The collection service.
+ ICollectionService GetCollectionService();
+
+ ///
+ /// Gets the OAuth service.
+ ///
+ /// The OAuth service.
+ IOAuthService GetOAuthService();
+ }
+}
\ No newline at end of file
diff --git a/Bynder/Sdk/Service/OAuth/IOAuthService.cs b/Bynder/Sdk/Service/OAuth/IOAuthService.cs
new file mode 100644
index 0000000..4a60792
--- /dev/null
+++ b/Bynder/Sdk/Service/OAuth/IOAuthService.cs
@@ -0,0 +1,29 @@
+// Copyright (c) Bynder. All rights reserved.
+// Licensed under the MIT License. See LICENSE file in the project root for full license information.
+
+using System.Threading.Tasks;
+
+namespace Bynder.Sdk.Service.OAuth
+{
+ ///
+ /// Oauth service interface. Service that handles OAuth logic.
+ ///
+ public interface IOAuthService
+ {
+ ///
+ /// Gets the authorisation URL.
+ ///
+ /// The authorisation URL.
+ /// State string to be checked to avoid CSRF. https://auth0.com/docs/protocols/oauth2/oauth-state
+ /// Scopes to request authorization for
+ string GetAuthorisationUrl(string state, string scopes);
+
+ ///
+ /// Gets an access token using the code authorization grant.
+ ///
+ /// The task to get the access token and update the credentials with it.
+ /// Code received after the redirect
+ /// The authorization scopes
+ Task GetAccessTokenAsync(string code, string scopes);
+ }
+}
diff --git a/Bynder/Sdk/Service/OAuth/OAuthService.cs b/Bynder/Sdk/Service/OAuth/OAuthService.cs
new file mode 100644
index 0000000..b79c284
--- /dev/null
+++ b/Bynder/Sdk/Service/OAuth/OAuthService.cs
@@ -0,0 +1,99 @@
+using System;
+using System.Collections.Generic;
+using System.Net.Http;
+using System.Threading.Tasks;
+using Bynder.Sdk.Api.Requests;
+using Bynder.Sdk.Api.RequestSender;
+using Bynder.Sdk.Model;
+using Bynder.Sdk.Query;
+using Bynder.Sdk.Settings;
+
+namespace Bynder.Sdk.Service.OAuth
+{
+ internal class OAuthService : IOAuthService
+ {
+ private readonly Configuration _configuration;
+ private readonly ICredentials _credentials;
+ ///
+ /// Request sender to communicate with the Bynder API
+ ///
+ private IApiRequestSender _requestSender;
+
+ ///
+ /// Initializes a new instance of the class
+ ///
+ /// instance to communicate with the Bynder API
+ public OAuthService(Configuration configuration, ICredentials credentials, IApiRequestSender requestSender)
+ {
+ _configuration = configuration;
+ _credentials = credentials;
+ _requestSender = requestSender;
+ }
+
+ ///
+ /// Check .
+ ///
+ /// Check .
+ /// Check .
+ /// Check .
+ public string GetAuthorisationUrl(string state, string scopes)
+ {
+ if (string.IsNullOrEmpty(state))
+ {
+ throw new ArgumentNullException(state);
+ }
+
+ var authoriseParams = new Dictionary
+ {
+ { "client_id", _configuration.ClientId },
+ { "redirect_uri", _configuration.RedirectUri },
+ { "scope", scopes },
+ { "response_type", "code" },
+ { "state", state }
+ };
+
+ var builder = new UriBuilder(_configuration.BaseUrl);
+ builder.Path = "/v6/authentication/oauth2/auth";
+
+ builder.Query = Utils.Url.ConvertToQuery(authoriseParams);
+
+ return builder.ToString();
+ }
+
+ ///
+ /// Check .
+ ///
+ /// Check .
+ /// Check .
+ /// Check .
+ public async Task GetAccessTokenAsync(string code, string scopes)
+ {
+ if (string.IsNullOrEmpty(code))
+ {
+ throw new ArgumentNullException(code);
+ }
+
+ TokenQuery query = new TokenQuery
+ {
+ ClientId = _configuration.ClientId,
+ ClientSecret = _configuration.ClientSecret,
+ RedirectUri = _configuration.RedirectUri,
+ GrantType = "authorization_code",
+ Code = code,
+ Scopes = scopes
+ };
+
+ var request = new OAuthRequest
+ {
+ Query = query,
+ Path = "/v6/authentication/oauth2/token",
+ HTTPMethod = HttpMethod.Post,
+ Authenticated = false
+ };
+
+ var token = await _requestSender.SendRequestAsync(request).ConfigureAwait(false);
+ token.SetAccessTokenExpiration();
+ _credentials.Update(token);
+ }
+ }
+}
diff --git a/Bynder/Api/Impl/Upload/AmazonApi.cs b/Bynder/Sdk/Service/Upload/AmazonApi.cs
similarity index 98%
rename from Bynder/Api/Impl/Upload/AmazonApi.cs
rename to Bynder/Sdk/Service/Upload/AmazonApi.cs
index d5b9327..7c44dc1 100644
--- a/Bynder/Api/Impl/Upload/AmazonApi.cs
+++ b/Bynder/Sdk/Service/Upload/AmazonApi.cs
@@ -3,9 +3,9 @@
using System.Net.Http;
using System.Threading.Tasks;
-using Bynder.Models;
+using Bynder.Sdk.Model;
-namespace Bynder.Api.Impl.Upload
+namespace Bynder.Sdk.Service.Upload
{
///
/// Implementation of
diff --git a/Bynder/Api/Impl/Upload/FileUploader.cs b/Bynder/Sdk/Service/Upload/FileUploader.cs
similarity index 91%
rename from Bynder/Api/Impl/Upload/FileUploader.cs
rename to Bynder/Sdk/Service/Upload/FileUploader.cs
index 12bbb4f..e461d14 100644
--- a/Bynder/Api/Impl/Upload/FileUploader.cs
+++ b/Bynder/Sdk/Service/Upload/FileUploader.cs
@@ -5,11 +5,13 @@
using System.IO;
using System.Net.Http;
using System.Threading.Tasks;
-using Bynder.Api.Impl.Oauth;
-using Bynder.Api.Queries;
-using Bynder.Models;
+using Bynder.Sdk.Exceptions;
+using Bynder.Sdk.Api.Requests;
+using Bynder.Sdk.Api.RequestSender;
+using Bynder.Sdk.Model;
+using Bynder.Sdk.Query.Upload;
-namespace Bynder.Api.Impl.Upload
+namespace Bynder.Sdk.Service.Upload
{
///
/// Class used to upload files to Bynder
@@ -34,7 +36,7 @@ internal class FileUploader
///
/// Request sender used to call Bynder API.
///
- private readonly IOauthRequestSender _requestSender;
+ private readonly IApiRequestSender _requestSender;
///
/// Amazon API used to upload parts
@@ -51,7 +53,7 @@ internal class FileUploader
///
/// Request sender to communicate with Bynder API
/// Amazon API to upload parts
- public FileUploader(IOauthRequestSender requestSender, IAmazonApi amazonApi)
+ public FileUploader(IApiRequestSender requestSender, IAmazonApi amazonApi)
{
_requestSender = requestSender;
_amazonApi = amazonApi;
@@ -62,7 +64,7 @@ public FileUploader(IOauthRequestSender requestSender, IAmazonApi amazonApi)
///
/// Request sender to communicate with Bynder API
/// new instance
- public static FileUploader Create(IOauthRequestSender requestSender)
+ public static FileUploader Create(IApiRequestSender requestSender)
{
return new FileUploader(requestSender, new AmazonApi());
}
@@ -117,9 +119,9 @@ private async Task GetClosestS3EndpointAsync()
{
if (string.IsNullOrEmpty(_awsBucket))
{
- var request = new Request
+ var request = new ApiRequest
{
- Uri = "/api/upload/endpoint",
+ Path = "/api/upload/endpoint",
HTTPMethod = HttpMethod.Get
};
@@ -139,19 +141,19 @@ private Task SaveMediaAsync(SaveMediaQuery query)
{
query.Filename = Path.GetFileName(query.Filename);
- string uri = null;
+ string path = null;
if (query.MediaId == null)
{
- uri = $"/api/v4/media/save/{query.ImportId}/";
+ path = $"/api/v4/media/save/{query.ImportId}/";
}
else
{
- uri = $"/api/v4/media/{query.MediaId}/save/{query.ImportId}/";
+ path = $"/api/v4/media/{query.MediaId}/save/{query.ImportId}/";
}
- var request = new Request
+ var request = new ApiRequest
{
- Uri = uri,
+ Path = path,
HTTPMethod = HttpMethod.Post,
Query = query,
DeserializeResponse = false
@@ -183,9 +185,9 @@ private Task PollStatusAsync(FinalizeResponse finalizeResponse)
/// Task with poll status information
private Task PollStatusAsync(PollQuery query)
{
- var request = new Request
+ var request = new ApiRequest
{
- Uri = "/api/v4/upload/poll/",
+ Path = "/api/v4/upload/poll/",
HTTPMethod = HttpMethod.Get,
Query = query
};
@@ -249,9 +251,9 @@ private Task RegisterChunkAsync(RegisterChunkQuery query)
{
query.S3Filename = $"{query.S3Filename}/p{query.ChunkNumber}";
- var request = new Request
+ var request = new ApiRequest
{
- Uri = $"/api/v4/upload/{query.UploadId}/",
+ Path = $"/api/v4/upload/{query.UploadId}/",
HTTPMethod = HttpMethod.Post,
Query = query,
DeserializeResponse = false
@@ -284,9 +286,9 @@ private Task RegisterChunkAsync(UploadRequest uploadRequest, uint chunkNumber)
/// Task containing information
private Task RequestUploadInformationAsync(RequestUploadQuery query)
{
- var request = new Request
+ var request = new ApiRequest
{
- Uri = "/api/upload/init",
+ Path = "/api/upload/init",
HTTPMethod = HttpMethod.Post,
Query = query
};
@@ -321,9 +323,9 @@ private Task FinalizeUploadAsync(FinalizeUploadQuery query)
{
query.S3Filename = $"{query.S3Filename}/p{query.Chunks}";
- var request = new Request
+ var request = new ApiRequest
{
- Uri = $"/api/v4/upload/{query.UploadId}/",
+ Path = $"/api/v4/upload/{query.UploadId}/",
HTTPMethod = HttpMethod.Post,
Query = query
};
diff --git a/Bynder/Api/Impl/Upload/IAmazonApi.cs b/Bynder/Sdk/Service/Upload/IAmazonApi.cs
similarity index 94%
rename from Bynder/Api/Impl/Upload/IAmazonApi.cs
rename to Bynder/Sdk/Service/Upload/IAmazonApi.cs
index 95e2450..b26425a 100644
--- a/Bynder/Api/Impl/Upload/IAmazonApi.cs
+++ b/Bynder/Sdk/Service/Upload/IAmazonApi.cs
@@ -2,9 +2,9 @@
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
using System.Threading.Tasks;
-using Bynder.Models;
+using Bynder.Sdk.Model;
-namespace Bynder.Api.Impl.Upload
+namespace Bynder.Sdk.Service.Upload
{
///
/// Interface to upload file parts to Amazon
diff --git a/Bynder/Sdk/Settings/Configuration.cs b/Bynder/Sdk/Settings/Configuration.cs
new file mode 100644
index 0000000..9821cd7
--- /dev/null
+++ b/Bynder/Sdk/Settings/Configuration.cs
@@ -0,0 +1,57 @@
+// Copyright (c) Bynder. All rights reserved.
+// Licensed under the MIT License. See LICENSE file in the project root for full license information.
+
+using Bynder.Sdk.Model;
+using Newtonsoft.Json;
+using System;
+using System.IO;
+
+namespace Bynder.Sdk.Settings
+{
+ ///
+ /// Settings needed to configure
+ ///
+ public class Configuration
+ {
+ ///
+ /// Bynder domain Url we want to communicate with
+ ///
+ [JsonProperty("base_url")]
+ public Uri BaseUrl { get; set; }
+
+ ///
+ /// OAuth Client id
+ ///
+ [JsonProperty("client_id")]
+ public string ClientId { get; set; }
+
+ ///
+ /// OAuth Client secret
+ ///
+ [JsonProperty("client_secret")]
+ public string ClientSecret { get; set; }
+
+ ///
+ /// Gets or sets the redirect URI. Optional: It is
+ /// only needed if trying to login through OAuth
+ ///
+ /// The redirect URI.
+ [JsonProperty("redirect_uri")]
+ public string RedirectUri { get; set; }
+
+ ///
+ /// OAuth token
+ ///
+ public Token Token { get; set; }
+
+ ///
+ /// Create a using the given filepath
+ ///
+ /// JSON file path
+ /// instance
+ public static Configuration FromJson(string filepath)
+ {
+ return JsonConvert.DeserializeObject(File.ReadAllText(filepath));
+ }
+ }
+}
diff --git a/Bynder/Sdk/Settings/Credentials.cs b/Bynder/Sdk/Settings/Credentials.cs
new file mode 100644
index 0000000..5f170aa
--- /dev/null
+++ b/Bynder/Sdk/Settings/Credentials.cs
@@ -0,0 +1,107 @@
+// Copyright (c) Bynder. All rights reserved.
+// Licensed under the MIT License. See LICENSE file in the project root for full license information.
+
+using System;
+using System.Net;
+using Bynder.Sdk.Model;
+
+namespace Bynder.Sdk.Settings
+{
+ ///
+ /// Credentials implementation.
+ ///
+ internal class Credentials : ICredentials
+ {
+ private Token _token;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Token passed in the configuration.
+ public Credentials(Token token)
+ {
+ _token = token;
+ }
+
+ ///
+ /// Check .
+ ///
+ public event EventHandler OnCredentialsChanged;
+
+ ///
+ /// Check .
+ ///
+ /// Check .
+ public string AccessToken => _token?.AccessToken;
+
+ ///
+ /// Check .
+ ///
+ /// Check .
+ public string RefreshToken => _token?.RefreshToken;
+
+ ///
+ /// Check .
+ ///
+ /// Check .
+ public bool CanRefresh
+ {
+ get
+ {
+ return RefreshToken != null;
+ }
+ }
+
+ ///
+ /// Check .
+ ///
+ /// Check .
+ public string TokenType => _token?.TokenType;
+
+ ///
+ /// Gets or sets the token that will be used to authenticate API calls.
+ ///
+ /// The token.
+ private Token Token
+ {
+ get
+ {
+ return _token;
+ }
+
+ set
+ {
+ if (value != _token)
+ {
+ _token = value;
+ OnCredentialsChanged?.Invoke(this, _token);
+ }
+ }
+ }
+
+ ///
+ /// Check .
+ ///
+ /// Check .
+ public bool AreValid()
+ {
+ if (_token != null
+ && _token.AccessToken != null)
+ {
+ var limitExpiration = DateTimeOffset.UtcNow.AddSeconds(15);
+ return _token.GetAccessTokenExpiration() > limitExpiration;
+ }
+
+ return false;
+ }
+
+ ///
+ /// Check .
+ ///
+ /// Check .
+ public void Update(Token token)
+ {
+ Token = token;
+ }
+ }
+}
diff --git a/Bynder/Sdk/Settings/ICredentials.cs b/Bynder/Sdk/Settings/ICredentials.cs
new file mode 100644
index 0000000..36a0598
--- /dev/null
+++ b/Bynder/Sdk/Settings/ICredentials.cs
@@ -0,0 +1,54 @@
+using System;
+using Bynder.Sdk.Model;
+
+namespace Bynder.Sdk.Settings
+{
+ ///
+ /// Credentials interface. An instance of credentials is created
+ /// when creating a and it is updated when login
+ /// or when refreshing tokens.
+ ///
+ internal interface ICredentials
+ {
+ ///
+ /// Raised when login or when token is refreshed
+ ///
+ event EventHandler OnCredentialsChanged;
+
+ ///
+ /// Gets the access token.
+ ///
+ /// The access token.
+ string AccessToken { get; }
+
+ ///
+ /// Gets the type of the token. In our case Bearer
+ ///
+ /// The type of the token.
+ string TokenType { get; }
+
+ ///
+ /// Gets the refresh token.
+ ///
+ /// The refresh token.
+ string RefreshToken { get; }
+
+ ///
+ /// Gets a value indicating whether this can be refreshed.
+ ///
+ /// true if can be refreshed; otherwise, false.
+ bool CanRefresh { get; }
+
+ ///
+ /// Checks if credentials are valid or expired
+ ///
+ /// true, if credentials are valid, false otherwise.
+ bool AreValid();
+
+ ///
+ /// Update the credentials with the specified token.
+ ///
+ /// Token.
+ void Update(Token token);
+ }
+}
\ No newline at end of file
diff --git a/Bynder/Sdk/Settings/Validators/ConfigurationValidator.cs b/Bynder/Sdk/Settings/Validators/ConfigurationValidator.cs
new file mode 100644
index 0000000..f3904d3
--- /dev/null
+++ b/Bynder/Sdk/Settings/Validators/ConfigurationValidator.cs
@@ -0,0 +1,40 @@
+// Copyright (c) Bynder. All rights reserved.
+// Licensed under the MIT License. See LICENSE file in the project root for full license information.
+
+using Bynder.Sdk.Exceptions;
+using Bynder.Sdk.Service;
+using Bynder.Sdk.Settings;
+
+namespace Bynder.Sdk.Settings.Validators
+{
+ ///
+ /// Configuration validator.
+ ///
+ internal class ConfigurationValidator
+ {
+ ///
+ /// Validate the specified configuration has all the required information for the
+ /// SDK to work.
+ /// Throws if configuration is not valid.
+ ///
+ /// Configuration.
+ public void Validate(Configuration configuration)
+ {
+ if (configuration.ClientId == null)
+ {
+ throw new InvalidConfigurationException("Missing Client Id");
+ }
+
+ if (configuration.ClientSecret == null)
+ {
+ throw new InvalidConfigurationException("Missing Client Secret");
+ }
+
+ if (configuration.Token == null
+ && configuration.RedirectUri == null)
+ {
+ throw new InvalidConfigurationException("Either Token or Redirect Uri need to be passed");
+ }
+ }
+ }
+}
diff --git a/Bynder/Sdk/Settings/Validators/OAuth2ServiceConfigurationValidator.cs b/Bynder/Sdk/Settings/Validators/OAuth2ServiceConfigurationValidator.cs
new file mode 100644
index 0000000..3faf378
--- /dev/null
+++ b/Bynder/Sdk/Settings/Validators/OAuth2ServiceConfigurationValidator.cs
@@ -0,0 +1,27 @@
+// Copyright (c) Bynder. All rights reserved.
+// Licensed under the MIT License. See LICENSE file in the project root for full license information.
+
+using Bynder.Sdk.Exceptions;
+using Bynder.Sdk.Settings;
+
+namespace Bynder.Sdk.Settings.Validators
+{
+ ///
+ /// OAuth2 service configuration validator.
+ ///
+ internal class OAuth2ServiceConfigurationValidator
+ {
+ ///
+ /// Validates the specified configuration is valid to be used by .
+ /// Throws if configuration is not valid.
+ ///
+ /// Configuration.
+ internal void Validate(Configuration configuration)
+ {
+ if (configuration.RedirectUri == null)
+ {
+ throw new InvalidConfigurationException("Missing Client Secret");
+ }
+ }
+ }
+}
diff --git a/Bynder/Sdk/Utils/Url.cs b/Bynder/Sdk/Utils/Url.cs
new file mode 100644
index 0000000..39035e4
--- /dev/null
+++ b/Bynder/Sdk/Utils/Url.cs
@@ -0,0 +1,30 @@
+// Copyright (c) Bynder. All rights reserved.
+// Licensed under the MIT License. See LICENSE file in the project root for full license information.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Bynder.Sdk.Utils
+{
+ ///
+ /// URL Utilities Class.
+ ///
+ public static class Url
+ {
+ ///
+ /// Converts dictionary to query parameters.
+ ///
+ /// Escaped query.
+ /// dictionary with parameters.
+ public static string ConvertToQuery(IDictionary parameters)
+ {
+ var encodedValues = parameters.Keys
+ .OrderBy(key => key)
+ .Select(key => $"{Uri.EscapeDataString(key)}={Uri.EscapeDataString(parameters[key])}");
+ var queryUri = string.Join("&", encodedValues);
+
+ return queryUri;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Bynder/Test/Api/Converters/BooleanJsonConverterTest.cs b/Bynder/Test/Api/Converters/BooleanJsonConverterTest.cs
new file mode 100644
index 0000000..0d1bf38
--- /dev/null
+++ b/Bynder/Test/Api/Converters/BooleanJsonConverterTest.cs
@@ -0,0 +1,23 @@
+// Copyright (c) Bynder. All rights reserved.
+// Licensed under the MIT License. See LICENSE file in the project root for full license information.
+
+using System.IO;
+using Bynder.Sdk.Api.Converters;
+using Moq;
+using Newtonsoft.Json;
+using Xunit;
+
+namespace Bynder.Test.Api.Converters
+{
+ public class BooleanJsonConverterTest
+ {
+ [Fact]
+ public void CanConvertOnlyWhenTypeIsBoolean()
+ {
+ BooleanJsonConverter converter = new BooleanJsonConverter();
+ Assert.False(converter.CanConvert(typeof(int)));
+ Assert.False(converter.CanConvert(typeof(string)));
+ Assert.True(converter.CanConvert(typeof(bool)));
+ }
+ }
+}
\ No newline at end of file
diff --git a/Bynder/Test/Api/Converters/DateTimeOffsetConverterTest.cs b/Bynder/Test/Api/Converters/DateTimeOffsetConverterTest.cs
new file mode 100644
index 0000000..a266d3b
--- /dev/null
+++ b/Bynder/Test/Api/Converters/DateTimeOffsetConverterTest.cs
@@ -0,0 +1,30 @@
+// Copyright (c) Bynder. All rights reserved.
+// Licensed under the MIT License. See LICENSE file in the project root for full license information.
+
+using System;
+using Bynder.Sdk.Api.Converters;
+using Xunit;
+
+namespace Bynder.Test.Api.Converters
+{
+ public class DateTimeOffsetConverterTest
+ {
+ [Fact]
+ public void CanConvertOnlyWhenTypeIsDateTimeOffset()
+ {
+ DateTimeOffsetConverter converter = new DateTimeOffsetConverter();
+ Assert.False(converter.CanConvert(typeof(int)));
+ Assert.False(converter.CanConvert(typeof(string)));
+ Assert.False(converter.CanConvert(typeof(bool)));
+ Assert.True(converter.CanConvert(typeof(DateTimeOffset)));
+ }
+
+ [Fact]
+ public void ConvertReturnsStringWithDate()
+ {
+ DateTimeOffsetConverter converter = new DateTimeOffsetConverter();
+ var date = converter.Convert(new DateTimeOffset(new DateTime(1000, 1, 1)));
+ Assert.Equal("1000-01-01T00:00:00Z", date);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Bynder/Test/Api/Converters/JsonConverterTest.cs b/Bynder/Test/Api/Converters/JsonConverterTest.cs
new file mode 100644
index 0000000..a3519e6
--- /dev/null
+++ b/Bynder/Test/Api/Converters/JsonConverterTest.cs
@@ -0,0 +1,27 @@
+// Copyright (c) Bynder. All rights reserved.
+// Licensed under the MIT License. See LICENSE file in the project root for full license information.
+
+using System;
+using System.Collections.Generic;
+using Bynder.Sdk.Api.Converters;
+using Xunit;
+
+namespace Bynder.Test.Api.Converters
+{
+ public class JsonConverterTest
+ {
+ [Fact]
+ public void ConvertReturnsString()
+ {
+ JsonConverter converter = new JsonConverter();
+ string convertedValue = converter.Convert(new TestClass {
+ Name = "name"
+ });
+ Assert.Equal("{\"Name\":\"name\"}", convertedValue);
+ }
+ }
+
+ public class TestClass {
+ public string Name { get; set; }
+ }
+}
diff --git a/Bynder/Test/Api/Converters/ListConverterTest.cs b/Bynder/Test/Api/Converters/ListConverterTest.cs
new file mode 100644
index 0000000..1076931
--- /dev/null
+++ b/Bynder/Test/Api/Converters/ListConverterTest.cs
@@ -0,0 +1,32 @@
+// Copyright (c) Bynder. All rights reserved.
+// Licensed under the MIT License. See LICENSE file in the project root for full license information.
+
+using System.Collections.Generic;
+using Bynder.Sdk.Api.Converters;
+using Xunit;
+
+namespace Bynder.Test.Api.Converters
+{
+ public class ListConverterTest
+ {
+ [Fact]
+ public void CanConvertOnlyWhenTypeIsEnumerableOfStrings()
+ {
+ ListConverter converter = new ListConverter();
+ Assert.False(converter.CanConvert(typeof(int)));
+ Assert.False(converter.CanConvert(typeof(IEnumerable)));
+ Assert.True(converter.CanConvert(typeof(IEnumerable)));
+ }
+
+ [Fact]
+ public void ConvertReturnsJoinedList()
+ {
+ ListConverter converter = new ListConverter();
+ string convertedList = converter.Convert(new List { "item1" });
+ Assert.Equal("item1", convertedList);
+
+ convertedList = converter.Convert(new List { "item1" , "item2" });
+ Assert.Equal("item1,item2", convertedList);
+ }
+ }
+}
diff --git a/Bynder/Test/Api/Converters/LowerCaseEnumConverterTest.cs b/Bynder/Test/Api/Converters/LowerCaseEnumConverterTest.cs
new file mode 100644
index 0000000..aa8eb08
--- /dev/null
+++ b/Bynder/Test/Api/Converters/LowerCaseEnumConverterTest.cs
@@ -0,0 +1,33 @@
+// Copyright (c) Bynder. All rights reserved.
+// Licensed under the MIT License. See LICENSE file in the project root for full license information.
+
+using System;
+using System.Collections.Generic;
+using Bynder.Sdk.Api.Converters;
+using Xunit;
+
+namespace Bynder.Test.Api.Converters
+{
+ public class LowerCaseEnumConverterTest
+ {
+ [Fact]
+ public void CanConvertOnlyWhenTypeIsEnum()
+ {
+ LowerCaseEnumConverter converter = new LowerCaseEnumConverter();
+ Assert.False(converter.CanConvert(typeof(int)));
+ Assert.False(converter.CanConvert(typeof(bool)));
+ Assert.False(converter.CanConvert(typeof(string)));
+ Assert.True(converter.CanConvert(typeof(Example)));
+ }
+
+ [Fact]
+ public void ConvertReturnsLowerCaseString()
+ {
+ LowerCaseEnumConverter converter = new LowerCaseEnumConverter();
+ string convertedValue = converter.Convert(Example.Example);
+ Assert.Equal("example", convertedValue);
+ }
+ }
+
+ public enum Example { Example };
+}
diff --git a/Bynder/Test/Api/RequestSender/ApiRequestSenderTest.cs b/Bynder/Test/Api/RequestSender/ApiRequestSenderTest.cs
new file mode 100644
index 0000000..4a8bf95
--- /dev/null
+++ b/Bynder/Test/Api/RequestSender/ApiRequestSenderTest.cs
@@ -0,0 +1,179 @@
+// Copyright (c) Bynder. All rights reserved.
+// Licensed under the MIT License. See LICENSE file in the project root for full license information.
+
+using System;
+using System.Net.Http;
+using System.Threading.Tasks;
+using Bynder.Sdk.Api.Requests;
+using Bynder.Sdk.Api.RequestSender;
+using Bynder.Sdk.Query.Decoder;
+using Bynder.Sdk.Settings;
+using Moq;
+using Xunit;
+
+namespace Bynder.Test.Api.RequestSender
+{
+ public class ApiRequestSenderTest
+ {
+ [Fact]
+ public async Task WhenRequestIsPostThenParametersAreAddedToContent()
+ {
+ var httpSenderMock = new Mock();
+ var query = new StubQuery
+ {
+ Item1 = "Value"
+ };
+ var accessToken = "access_token";
+
+ using (ApiRequestSender apiRequestSender = new ApiRequestSender(
+ new Configuration{
+ BaseUrl = new Uri("https://example.bynder.com"),
+ },
+ GetCredentials(true, accessToken),
+ httpSenderMock.Object
+ ))
+ {
+ var apiRequest = new ApiRequest()
+ {
+ Path = "/fake/api",
+ HTTPMethod = HttpMethod.Post,
+ Query = query
+ };
+
+ await apiRequestSender.SendRequestAsync(apiRequest);
+
+ httpSenderMock.Verify(sender => sender.SendHttpRequest(
+ It.Is(
+ req => req.RequestUri.PathAndQuery.Contains("/fake/api")
+ && req.Method == HttpMethod.Post
+ && req.Headers.Authorization.ToString() == $"Bearer {accessToken}"
+ && req.Content.ReadAsStringAsync().Result.Contains("Item1=Value")
+ )));
+
+ httpSenderMock.Verify(sender => sender.SendHttpRequest(
+ It.IsAny()
+ ), Times.Once);
+ }
+ }
+
+
+ [Fact]
+ public async Task WhenCredentialInvalidTwoRequestsSent()
+ {
+ var httpSenderMock = new Mock();
+
+ var query = new StubQuery
+ {
+ Item1 = "Value"
+ };
+ var accessToken = "access_token";
+
+ using (ApiRequestSender apiRequestSender = new ApiRequestSender(
+ new Configuration{
+ BaseUrl = new Uri("https://example.bynder.com"),
+ },
+ GetCredentials(false, accessToken),
+ httpSenderMock.Object
+ ))
+ {
+ var apiRequest = new ApiRequest()
+ {
+ Path = "/fake/api",
+ HTTPMethod = HttpMethod.Get,
+ Query = query
+ };
+
+ await apiRequestSender.SendRequestAsync(apiRequest);
+
+ httpSenderMock.Verify(sender => sender.SendHttpRequest(
+ It.Is(
+ req => req.RequestUri.PathAndQuery.Contains("/oauth2/token")
+ && req.Method == HttpMethod.Post
+ )));
+
+ httpSenderMock.Verify(sender => sender.SendHttpRequest(
+ It.Is(
+ req => req.RequestUri.PathAndQuery.Contains("/fake/api")
+ && req.Method == HttpMethod.Get
+ && req.Headers.Authorization.ToString() == $"Bearer {accessToken}"
+ && req.RequestUri.Query.Contains("Item1=Value")
+ )));
+
+ httpSenderMock.Verify(sender => sender.SendHttpRequest(
+ It.IsAny()
+ ), Times.Exactly(2));
+ }
+ }
+
+ [Fact]
+ public async Task WhenRequestIsGetThenParametersAreAddedToUrl()
+ {
+ var httpSenderMock = new Mock();
+ var query = new StubQuery
+ {
+ Item1 = "Value"
+ };
+ var accessToken = "access_token";
+
+ using (ApiRequestSender apiRequestSender = new ApiRequestSender(
+ new Configuration{
+ BaseUrl = new Uri("https://example.bynder.com"),
+ },
+ GetCredentials(true, accessToken),
+ httpSenderMock.Object
+ ))
+ {
+ var apiRequest = new ApiRequest
+ {
+ Path = "/fake/api",
+ HTTPMethod = HttpMethod.Get,
+ Query = query
+ };
+
+ await apiRequestSender.SendRequestAsync(apiRequest);
+
+ httpSenderMock.Verify(sender => sender.SendHttpRequest(
+ It.Is(
+ req => req.RequestUri.PathAndQuery.Contains("/fake/api")
+ && req.Method == HttpMethod.Get
+ && req.Headers.Authorization.ToString() == $"Bearer {accessToken}"
+ && req.RequestUri.Query.Contains("Item1=Value")
+ )));
+
+ httpSenderMock.Verify(sender => sender.SendHttpRequest(
+ It.IsAny()
+ ), Times.Once);
+ }
+ }
+
+ private ICredentials GetCredentials(bool valid = true, string accessToken = null)
+ {
+ var credentialsMock = new Mock();
+ credentialsMock
+ .Setup(mock => mock.AreValid())
+ .Returns(valid);
+
+ credentialsMock
+ .SetupGet(mock => mock.AccessToken)
+ .Returns(accessToken);
+
+ credentialsMock
+ .SetupGet(mock => mock.TokenType)
+ .Returns("Bearer");
+
+ return credentialsMock.Object;
+ }
+
+ ///
+ /// Stub query for testing purposes.
+ ///
+ private class StubQuery
+ {
+ ///
+ /// Stub property
+ ///
+ [ApiField("Item1")]
+ public string Item1 { get; set; }
+ }
+ }
+}
diff --git a/Bynder/Test/Api/RequestSender/HttpRequestSenderTest.cs b/Bynder/Test/Api/RequestSender/HttpRequestSenderTest.cs
new file mode 100644
index 0000000..82bf28d
--- /dev/null
+++ b/Bynder/Test/Api/RequestSender/HttpRequestSenderTest.cs
@@ -0,0 +1,28 @@
+// Copyright (c) Bynder. All rights reserved.
+// Licensed under the MIT License. See LICENSE file in the project root for full license information.
+
+using System.Net;
+using System.Net.Http;
+using Bynder.Sdk.Api.RequestSender;
+using Bynder.Test.Utils;
+using Xunit;
+
+namespace Bynder.Test.Api.RequestSender
+{
+ public class HttpRequestSenderTest
+ {
+ [Fact]
+ public void WhenErrorReceivedAnExceptionIsThown()
+ {
+ using (var testHttpListener = new TestHttpListener(HttpStatusCode.Forbidden, null))
+ {
+ using (HttpRequestSender apiRequestSender = new HttpRequestSender())
+ {
+ HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Get, testHttpListener.ListeningUrl);
+
+ Assert.ThrowsAsync(async () => await apiRequestSender.SendHttpRequest(requestMessage));
+ }
+ }
+ }
+ }
+}
diff --git a/Bynder/Test/AssetBank/AssetBankTest.cs b/Bynder/Test/AssetBank/AssetBankTest.cs
deleted file mode 100644
index 423ada3..0000000
--- a/Bynder/Test/AssetBank/AssetBankTest.cs
+++ /dev/null
@@ -1,139 +0,0 @@
-// Copyright (c) Bynder. All rights reserved.
-// Licensed under the MIT License. See LICENSE file in the project root for full license information.
-
-using System.Collections.Generic;
-using System.Net.Http;
-using System.Threading.Tasks;
-using Bynder.Api.Impl;
-using Bynder.Api.Impl.Oauth;
-using Bynder.Api.Queries;
-using Bynder.Models;
-using Moq;
-using NUnit.Framework;
-
-namespace Bynder.Test.AssetBank
-{
- ///
- /// Class to test Asset bank implementation
- ///
- [TestFixture]
- public class AssetBankTest
- {
- ///
- /// Tests that when , request has correct values
- /// in Url, and HTTPMethod
- ///
- /// Task to wait
- [Test]
- public async Task WhenGetMediaInformationByIdThenRequestHasCorrectMediaValues()
- {
- const string MediaId = "8888";
- Media returnedMedia = new Media();
- var mock = new Mock();
- mock.Setup(reqSenderMock => reqSenderMock.SendRequestAsync(It.IsAny>())).Returns(Task.FromResult(returnedMedia));
-
- var assetBankManager = new AssetBankManager(mock.Object);
- var media = await assetBankManager.RequestMediaInfoAsync(new MediaInformationQuery { MediaId = MediaId });
- mock.Verify(reqSenderMock
- => reqSenderMock.SendRequestAsync(It.Is>(req => req.Uri == $"/api/v4/media/{MediaId}/"
- && req.HTTPMethod == HttpMethod.Get
- && ((MediaInformationQuery)req.Query).Versions == 1)));
-
- Assert.AreEqual(returnedMedia, media);
- }
-
- ///
- /// Tests that when is called, request has correct values in
- /// Url, HTTPMethod and Query.
- ///
- /// Task to wait
- [Test]
- public async Task WhenGetMediaThenRequestContainsExpectedValues()
- {
- IList returnedMediaList = new List();
-
- var query = new MediaQuery
- {
- PropertyOptionId = { "12345", "123123" },
- Limit = 50,
- Page = 1
- };
-
- var mock = new Mock();
- mock.Setup(reqSenderMock => reqSenderMock.SendRequestAsync(It.IsAny>>())).Returns(Task.FromResult(returnedMediaList));
-
- var assetBankManager = new AssetBankManager(mock.Object);
- var mediaList = await assetBankManager.RequestMediaListAsync(query);
-
- mock.Verify(reqSenderMock
- => reqSenderMock.SendRequestAsync(It.Is>>(req => req.Uri == $"/api/v4/media/"
- && req.HTTPMethod == HttpMethod.Get
- && req.Query == query)));
- Assert.AreEqual(returnedMediaList, mediaList);
- }
-
- ///
- /// Tests that when "/>, request has correct
- /// values in Url and HTTPMethod
- ///
- /// Task to wait
- [Test]
- public async Task WhenGetMetapropertiesThenRequestContainsExpectedValues()
- {
- var metaproperty = new Metaproperty();
-
- var mock = new Mock();
- mock.Setup(reqSenderMock => reqSenderMock.SendRequestAsync(It.IsAny>>()))
- .Returns(Task.FromResult>(new Dictionary
- {
- { "metaproperty1", metaproperty }
- }));
-
- var assetBankManager = new AssetBankManager(mock.Object);
- var metaproperties = await assetBankManager.GetMetapropertiesAsync();
-
- mock.Verify(reqSenderMock
- => reqSenderMock.SendRequestAsync(It.Is>>(req => req.Uri == $"/api/v4/metaproperties/"
- && req.HTTPMethod == HttpMethod.Get
- && req.Query == null)));
-
- Assert.AreEqual(1, metaproperties.Count);
- Assert.AreEqual(metaproperties["metaproperty1"], metaproperty);
- }
-
- ///
- /// Tests that when Download Url is called then request has correct values.
- /// It tests when MediaItemId is specified and when it's not.
- ///
- /// Task to wait
- [Test]
- public async Task WhenDownloadUrlIsRequestedThenRequestContainsExpectedValues()
- {
- const string MediaId = "MediaId";
- const string MediaItemId = "MediaItemId";
- var mock = new Mock();
- mock.Setup(reqSenderMock => reqSenderMock.SendRequestAsync(It.IsAny>()))
- .Returns(Task.FromResult(new DownloadFileUrl()));
-
- var assetBankManager = new AssetBankManager(mock.Object);
- var downloadFileUrl = await assetBankManager.GetDownloadFileUrlAsync(new DownloadMediaQuery
- {
- MediaId = MediaId
- });
-
- mock.Verify(reqSenderMock
- => reqSenderMock.SendRequestAsync(It.Is>(req => req.Uri == $"/api/v4/media/{MediaId}/download/"
- && req.HTTPMethod == HttpMethod.Get)));
-
- downloadFileUrl = await assetBankManager.GetDownloadFileUrlAsync(new DownloadMediaQuery
- {
- MediaId = MediaId,
- MediaItemId = MediaItemId
- });
-
- mock.Verify(reqSenderMock
- => reqSenderMock.SendRequestAsync(It.Is>(req => req.Uri == $"/api/v4/media/{MediaId}/download/{MediaItemId}/"
- && req.HTTPMethod == HttpMethod.Get)));
- }
- }
-}
diff --git a/Bynder/Test/AssetBank/FileUploaderTest.cs b/Bynder/Test/AssetBank/FileUploaderTest.cs
deleted file mode 100644
index 4d498da..0000000
--- a/Bynder/Test/AssetBank/FileUploaderTest.cs
+++ /dev/null
@@ -1,254 +0,0 @@
-// Copyright (c) Bynder. All rights reserved.
-// Licensed under the MIT License. See LICENSE file in the project root for full license information.
-
-using System.Collections.Generic;
-using System.IO;
-using System.Net.Http;
-using System.Text;
-using System.Threading.Tasks;
-using Bynder.Api.Impl.Oauth;
-using Bynder.Api.Impl.Upload;
-using Bynder.Api.Queries;
-using Bynder.Models;
-using Moq;
-using NUnit.Framework;
-
-namespace Bynder.Test.AssetBank
-{
- ///
- /// File to test implementation
- ///
- [TestFixture]
- public class FileUploaderTest
- {
- ///
- /// Import id to return from finalize upload and poll status
- ///
- private const string ImportId = "ImportId";
-
- ///
- /// Tests that correct sequence is called when
- /// The order it tests is:
- /// 1. Init upload
- /// 2. Get closest s3 endpoint
- /// 3. Upload part to Amazon
- /// 4. Register chunk in Bynder
- /// 5. Finalize upload.
- /// 6. Poll status
- /// 7. Save
- ///
- /// Task to wait
- [Test]
- public async Task WhenFileUploadedThenUploadSequenceIsCalled()
- {
- var mock = new Mock(MockBehavior.Strict);
- var awsmock = new Mock(MockBehavior.Strict);
- var sequence = new MockSequence();
-
- var filename = Path.GetTempFileName();
- var uploadRequest = GetUploadRequest();
- var finalizeResponse = GetFinalizeResponse();
-
- // Init upload
- mock.InSequence(sequence).Setup(reqSenderMock => reqSenderMock.SendRequestAsync(GetValidUploadRequest(filename)))
- .Returns(Task.FromResult(uploadRequest));
-
- // Get Closest s3 endpoint to upload parts
- mock.InSequence(sequence).Setup(reqSenderMock => reqSenderMock.SendRequestAsync(GetValidClosestS3EndpointRequest()))
- .Returns(Task.FromResult("\"http://test.amazon.com/\""));
-
- // Upload Part to Amazon
- awsmock.InSequence(sequence).Setup(amazonApiMock => amazonApiMock.UploadPartToAmazon(
- It.IsAny(),
- It.IsAny(),
- It.IsAny(),
- It.IsAny(),
- It.IsAny(),
- It.IsAny(),
- It.IsAny())).Returns(Task.FromResult(true));
-
- // Register chunk in bynder
- mock.InSequence(sequence).Setup(reqSenderMock => reqSenderMock.SendRequestAsync(GetValidRegisterChunkRequest(uploadRequest)))
- .Returns(Task.FromResult(string.Empty));
-
- // Finalizes the upload
- mock.InSequence(sequence).Setup(reqSenderMock => reqSenderMock.SendRequestAsync(GetValidFinalizeResponseRequest(uploadRequest)))
- .Returns(Task.FromResult(finalizeResponse));
-
- // Poll status
- mock.InSequence(sequence).Setup(reqSenderMock => reqSenderMock.SendRequestAsync(GetValidPollStatus(finalizeResponse)))
- .Returns(Task.FromResult(GetPollStatus()));
-
- // Saves media
- mock.InSequence(sequence).Setup(reqSenderMock => reqSenderMock.SendRequestAsync(GetSaveMediaRequest(filename, finalizeResponse)))
- .Returns(Task.FromResult(string.Empty));
-
- FileUploader uploader = new FileUploader(mock.Object, awsmock.Object);
- using (var fileStream = File.OpenWrite(filename))
- {
- var bytes = Encoding.UTF8.GetBytes("mockdata");
- await fileStream.WriteAsync(bytes, 0, bytes.Length);
- }
-
- try
- {
- await uploader.UploadFile(new UploadQuery
- {
- Filepath = filename
- });
- }
- finally
- {
- File.Delete(filename);
- }
- }
-
- ///
- /// Returns Request that has valid values for upload request
- ///
- /// filename of the file we want to upload
- /// request to initialize upload
- private Request GetValidUploadRequest(string filename)
- {
- return It.Is>(req =>
- req.Uri == "/api/upload/init"
- && req.HTTPMethod == HttpMethod.Post
- && ((RequestUploadQuery)req.Query).Filename == filename);
- }
-
- ///
- /// Returns Request that has valid values to get Closest S3 enpdoint
- ///
- /// request to get closest endpoint
- private Request GetValidClosestS3EndpointRequest()
- {
- return It.Is>(req =>
- req.Uri == "/api/upload/endpoint"
- && req.HTTPMethod == HttpMethod.Get
- && req.Query == null);
- }
-
- ///
- /// Returns Request that has valid values to register chunk
- ///
- /// upload request. Needed to validate request values
- /// request to register chunk
- private Request GetValidRegisterChunkRequest(UploadRequest uploadRequest)
- {
- return It.Is>(req =>
- IsRegisterChunkValid(req, uploadRequest));
- }
-
- ///
- /// Returns Request that has valid values to finalize response
- ///
- /// upload request. Needed to validate request values
- /// request to finalize upload
- private Request GetValidFinalizeResponseRequest(UploadRequest uploadRequest)
- {
- return It.Is>(req => IsFinalizeResponseValid(req, uploadRequest));
- }
-
- ///
- /// Returns Request that has valid values to poll status
- ///
- /// Finalize response. Needed to validate request values
- /// Request to poll status
- private Request GetValidPollStatus(FinalizeResponse finalizeResponse)
- {
- return It.Is>(req =>
- req.Uri == "/api/v4/upload/poll/"
- && req.HTTPMethod == HttpMethod.Get
- && ((PollQuery)req.Query).Items.Contains(finalizeResponse.ImportId));
- }
-
- ///
- /// Returns Request that has valid values to save media
- ///
- /// filename of the media. Needed to validate request values
- /// finalize response. Needed to validate request values
- /// Request to save media
- private Request GetSaveMediaRequest(string filename, FinalizeResponse finalizeResponse)
- {
- return It.Is