/// <summary>
        /// Registers the android device push notifications.
        /// </summary>
        /// <returns>The android device push notifications.</returns>
        /// <param name="user">User.</param>
        /// <param name="uniqueDeviceId">Android.OS.Build.Serial</param>
        /// <param name="gcmToken">Device token from Google GCM registration.</param>
        public Task <CMResponse> RegisterAndroidDevicePushNotifications(CMUser user, string uniqueDeviceId, object gcmToken)
        {
            CMRequestOptions options = new CMRequestOptions(null, user);

            options.Headers.Add("device_type", "android");
            options.Headers.Add("HTTP_X_CLOUDMINE_UT", uniqueDeviceId);
            options.Headers.Add("X-CloudMine-Agent", "Android");

            Dictionary <string, object> dataDict = new Dictionary <string, object>();

            dataDict.Add("token", gcmToken);
            dataDict.Add("device_type", "android");
            dataDict.Add("device_id", uniqueDeviceId);

            return(APIService.Request(Application, "device", HttpMethod.Post, CMSerializer.ToStream(dataDict), options));
        }
        /// <summary>
        /// Set executes a PUT request on the object being passed in. PUT requests will create a new object or replace an prior existing object if the
        /// key (__id__, ID) already exists.
        /// </summary>
        /// <typeparam name="T">Any object which derives from CMObject. CMObject auto declares and creates unique identifiers and the class type</typeparam>
        /// <param name="data">CMObject to create.</param>
        /// <param name="opts">Optional Request parameters for things like post execution snippet params.</param>
        public async Task <CMObjectResponse> SetObject <T>(T data, CMRequestOptions opts = null) where T : CMObject
        {
            Dictionary <string, object> dataDict = new Dictionary <string, object>();

            // only set the type if not already set and T is not CMobject
            if (string.IsNullOrEmpty(data.Class) && typeof(T).Name != typeof(CMObject).Name)
            {
                data.Class = typeof(T).Name;
            }

            dataDict.Add(data.ID, data);

            Stream stream = CMSerializer.ToStream(dataDict);

            return(await APIService.Request <CMObjectResponse>(this.Application, "text", HttpMethod.Put, stream, new CMRequestOptions(opts)));
        }
        /// <summary>
        /// Strips the device ID from device token callback value for the method
        /// didRegisterForRemoteNotificationsWithDeviceToken. Requires the Apple device
        /// identification string contained in the callback and an actively logged in
        /// CMUser to register with CloudMine.
        /// </summary>
        /// <param name="user">User with valid session</param>
        /// /// <param name="uniqueDeviceId">UIKit.UIDevice.CurrentDevice.IdentifierForVendor.AsString()</param>
        /// <param name="apnsToken">The token object returned in didRegisterForRemoteNotificationsWithDeviceToken</param>
        public Task <CMResponse> RegisterIOSDevicePushNotifications(CMUser user, string uniqueDeviceId, object apnsToken)
        {
            CMRequestOptions options = new CMRequestOptions(null, user);

            options.Headers.Add("device_type", "ios");
            options.Headers.Add("HTTP_X_CLOUDMINE_UT", uniqueDeviceId);
            options.Headers.Add("X-CloudMine-Agent", "iOS");

            string deviceTokenString = StripIOSDeviceToken(apnsToken.ToString());

            Dictionary <string, string> dataDict = new Dictionary <string, string>();

            dataDict.Add("token", deviceTokenString);
            dataDict.Add("device_type", "ios");
            dataDict.Add("device_id", uniqueDeviceId);

            return(APIService.Request(Application, "device", HttpMethod.Post, CMSerializer.ToStream(dataDict), options));
        }
        /// <summary>
        /// Take a set of request options and extracts the proper query
        /// parameters. Does not deal with the necessary headers used
        /// in a CM REST call.
        /// </summary>
        /// <returns>The cloud mine query.</returns>
        /// <param name="opts">Opts.</param>
        public List <string> GetCloudMineQuery(CMRequestOptions opts)
        {
            List <string> query = new List <string>();

            if (opts.LimitResults > -1)
            {
                opts.Query["limit"] = opts.LimitResults.ToString();
            }
            if (opts.SkipResults > -1)
            {
                opts.Query["skip"] = opts.SkipResults.ToString();
            }
            if (opts.CountResults)
            {
                opts.Query["count"] = true.ToString();
            }
            if (opts.Snippet != null)
            {
                opts.Query["f"] = opts.Snippet;
                if (opts.SnippetResultOnly)
                {
                    opts.Query["result_only"] = "true";
                }
                if (opts.SnippetParams.Count > 0)
                {
                    opts.Query["params"] = CMSerializer.ToString(opts.SnippetParams);
                }
            }

            foreach (string key in opts.Query.Keys)
            {
                query.Add(Uri.EscapeUriString(key) + "=" + Uri.EscapeUriString(opts.Query[key]));
            }

            return(query);
        }
        // Update ===========
        /// <summary>
        /// Updates the user object. The values posted in this request are merged with existing values on the server.
        /// If the key you are creating already exists, isn't a simple value (such as a string or number),
        /// and the new value you send for it also isn't a simple value, its contents will be merged with
        /// the data you send. Otherwise the contents will be replaced. If the key does not exist, the
        /// entry will be created.
        /// </summary>
        /// <returns>The user object.</returns>
        /// <param name="key">Key, __id__ where the data will be indexed</param>
        /// <param name="value">CMObject to be uploaded</param>
        /// <param name="user">User which contains session where the data will reside.</param>
        /// <param name="opts">Optional Request parameters for things like post execution snippet params..</param>
        public Task <CMObjectResponse> UpdateUserObject(CMUser user, string key, object value, CMRequestOptions opts = null)
        {
            Dictionary <string, object> dataDict = new Dictionary <string, object>();

            dataDict[key] = value;

            return(APIService.Request <CMObjectResponse>(this.Application, "user/text", HttpMethod.Post, CMSerializer.ToStream(dataDict), new CMRequestOptions(opts, user)));
        }
        /// <summary>
        /// Resets the password. This request is used to fulfill the password reset once a reset token has been created.
        /// Custom password reset form can be created on the CloudMine dashboard to deep link the token to the app.
        /// Otherwise a default email form is presented to the user.
        /// </summary>
        /// <returns>The password.</returns>
        /// <param name="token">The token sent in the email which is used to set the new password.</param>
        /// <param name="newPassword">New password.</param>
        public Task <CMResponse> ResetPassword(string token, string newPassword)
        {
            Dictionary <string, string> data = new Dictionary <string, string>();

            data["password"] = newPassword;

            return(APIService.Request(this.Application, "account/password/reset/" + token, HttpMethod.Post, CMSerializer.ToStream(data), null));
        }
        /// <summary>
        /// You can use this endpoint to reset user passwords. Use this if the user has
        /// forgotten their password and needs to securely reset it. This requires two API
        /// requests: one to request a password reset for the user (which sends them a
        /// password reset email), and another to fulfill that request and submit the new password.
        /// </summary>
        /// <returns>The password request.</returns>
        /// <param name="email">Email address of the user.</param>
        public Task <CMResponse> ResetPasswordRequest(string email)
        {
            Dictionary <string, string> data = new Dictionary <string, string>();

            data["email"] = email;

            return(APIService.Request(this.Application, "account/password/reset", HttpMethod.Post, CMSerializer.ToStream(data), null));
        }
        /// <summary>
        /// You may submit requests to change user passwords through the API.
        /// Use this method instead of password reset if the user knows their current password and simply wishes to change it.
        /// </summary>
        /// <param name="user">Original user with current credentials prior to change</param>
        /// <param name="newPassword"></param>
        public Task <CMResponse> ChangePassword(CMUser user, string newPassword)
        {
            Dictionary <string, string> data = new Dictionary <string, string>();

            data["password"] = newPassword;

            CMRequestOptions opts = new CMRequestOptions();

            opts.SetCredentials(user.Credentials);

            return(APIService.Request(this.Application, "account/password/change", HttpMethod.Post, CMSerializer.ToStream(data), opts));
        }
        public Task <CMResponse> UnsubscribeToChannel(string channelName, CMUser userToRemove)
        {
            var opts = new CMRequestOptions(userToRemove);

            Dictionary <string, object> dataDict = new Dictionary <string, object>();

            dataDict.Add("user", true);

            return(APIService.Request(Application, string.Format("push/channel/{0}/unsubscribe", channelName), HttpMethod.Post, CMSerializer.ToStream(dataDict), opts));
        }
 public Task <CMResponse> BulkAddChannelDeviceIDs(string channelName, string[] deviceIDs)
 {
     return(APIService.Request(Application, string.Format("push/channel/{0}/device_ids", channelName), HttpMethod.Post, CMSerializer.ToStream(deviceIDs), new CMRequestOptions()));
 }
 public Task <CMResponse> UpdateChannel(CMPushNotificationChannel puchChannel)
 {
     return(APIService.Request(Application, "push/channel", HttpMethod.Post, CMSerializer.ToStream(puchChannel), new CMRequestOptions()));
 }
 public Task <CMResponse> SendNotification(CMPushNotification pushNotification)
 {
     return(APIService.Request(Application, "push", HttpMethod.Post, CMSerializer.ToStream(pushNotification), new CMRequestOptions()));
 }
        /// <summary>
        /// Method to create application level objects. If the id exists already, the object will replace the existing object.
        /// </summary>
        /// <param name="key">the id to classify the object under. defaults to the type of object value being passed in</param>
        /// <param name="value">the cloudmine object being created</param>
        /// <param name="opts">Optional Request parameters for things like post execution snippet params.</param>
        public async Task <CMObjectResponse> SetObject(object value, CMRequestOptions opts = null, string key = null, string type = null)
        {
            Dictionary <string, object> data = new Dictionary <string, object>();

            if (!string.IsNullOrEmpty(key))
            {
                data[key] = value;
            }
            if (!string.IsNullOrEmpty(type))
            {
                data[type] = type;
            }

            return(await APIService.Request <CMObjectResponse>(this.Application, "text", HttpMethod.Put, CMSerializer.ToStream(data), new CMRequestOptions(opts)));
        }
        /// <summary>
        /// Updates the user object. The values posted in this request are merged with existing values on the server.
        /// If the key you are creating already exists, isn't a simple value (such as a string or number),
        /// and the new value you send for it also isn't a simple value, its contents will be merged with
        /// the data you send. Otherwise the contents will be replaced. If the key does not exist, the
        /// entry will be created.
        /// </summary>
        /// <returns>The user object.</returns>
        /// <param name="data">CMObject to be uploaded</param>
        /// <param name="user">User which contains session where the data will reside.</param>
        /// <param name="opts">Optional Request parameters for things like post execution snippet params.</param>
        /// <typeparam name="T">Objects must derive from the CMObject class which ensures proper configuration.</typeparam>
        public Task <CMObjectResponse> UpdateUserObject <T>(CMUser user, T data, CMRequestOptions opts = null) where T : CMObject
        {
            Dictionary <string, T> dataDict = new Dictionary <string, T>();

            dataDict[data.ID] = data;

            return(APIService.Request <CMObjectResponse>(this.Application, "user/text", HttpMethod.Post, CMSerializer.ToStream(dataDict), new CMRequestOptions(opts, user)));
        }
 public Task <CMResponse> BulkAddChannelSubscribers(string channelName, CMPushUser[] usersToAdd)
 {
     return(APIService.Request(Application, string.Format("push/channel/{0}/users", channelName), HttpMethod.Post, CMSerializer.ToStream(usersToAdd), new CMRequestOptions()));
 }
        /// <summary>
        /// Merges the user profile via a POST call.
        /// </summary>
        /// <returns>The user profile.</returns>
        /// <param name="user">User containg the profile to be replaced with valid session token.</param>
        /// <param name="opts">Any custom options for the request such as snippet execution on upload completion.</param>
        /// <typeparam name="T">CMUserprofile type derivative</typeparam>
        public Task <CMResponse> MergeUserProfile <T>(CMUser <T> user, CMRequestOptions opts = null) where T : CMUserProfile
        {
            if (opts == null)
            {
                opts = new CMRequestOptions();
            }

            if (!string.IsNullOrEmpty(user.Session))
            {
                opts.Headers["X-CloudMine-SessionToken"] = user.Session;
                opts.SnippetParams.Add("session_token", user.Session ?? string.Empty);
                opts.SnippetParams.Add("user_id", user.UserID ?? string.Empty);
            }

            return(APIService.Request <CMResponse>(this.Application, "account/", HttpMethod.Post, CMSerializer.ToStream(user.Profile), new CMRequestOptions(opts, user)));
        }
 public Task <CMResponse> ModifyAccessList(CMUser user, CMAccessList acl)
 {
     return(APIService.Request(this.Application, "user/access", HttpMethod.Put, CMSerializer.ToStream(acl), new CMRequestOptions(null, user)));
 }