コード例 #1
0
        /// <summary>
        /// Create the specified user. User can also have a custom user profile
        /// definition or a custom profile can be set at a later time with the update
        /// user profile function. This function creates the user but doesn't log the
        /// user in automatically.
        /// </summary>
        /// <param name="user">Instance of the user to be created</param>
        /// <param name="opts">Optional Request parameters for things like post execution snippet params.</param>
        public Task <CMUserResponse> Create(CMUser user, CMRequestOptions opts = null)
        {
            if (opts == null)
            {
                opts = new CMRequestOptions(user);
            }
            else
            {
                opts = new CMRequestOptions(opts, user);
            }

            string reqData = JsonConvert.SerializeObject(user);

            byte[]       byteArray = Encoding.UTF8.GetBytes(reqData);
            MemoryStream stream    = new MemoryStream(byteArray);

            opts.Data = stream;

            Task <CMUserResponse> createUser = APIService.Request <CMUserResponse>(this.Application, "account/create", HttpMethod.Post, stream, opts);

            createUser.ContinueWith(result => {
                if (result.IsCompleted)
                {
                    // sets the user id of the user object passed in
                    if (!result.Result.HasErrors)
                    {
                        user.UserID = result.Result.CMUser.UserID;
                    }
                }
            });

            return(createUser);
        }
コード例 #2
0
        public ActionResult Register(Register model)
        {
            if (ModelState.IsValid)
            {
                var user = new CMUser()
                {
                    UserName = model.UserName,
                    Company  = new Company()
                    {
                        Name = model.CompanyName,
                    },
                };

                var result = userManager.Create(user, model.Password);

                if (result.Succeeded)
                {
                    //kullanıcı başarılı şekilde oluşturulmuş ise login sayfasına gönderebiliriz.
                    return(RedirectToAction("Login"));
                }
                else
                {
                    foreach (var error in result.Errors)
                    {
                        ModelState.AddModelError("", error);
                    }
                }
            }
            //kullanıcı modelstate.ısvalid false gelse bile doldurdugu özellikler Viev(model) sayesinde register.htmlde gözükecek
            return(View(model));
        }
コード例 #3
0
        public async Task <AuthenticationResponseVM> Post([FromForm] string username, [FromForm] string password, [FromForm] string email)
        {
            AuthenticationResponseVM model = new AuthenticationResponseVM();

            try
            {
                var query    = "SELECT * FROM c";
                var allItems = await _cosmosDbService.GetItemsAsync(query);

                var count = allItems.Count();

                CMUser user = new CMUser();
                user.ID           = (count + 1).ToString();
                user.DbGrouping   = "User";
                user.UserID       = username;
                user.Password     = password;
                user.Email        = email;
                user.EntryDt      = DateTime.Today;
                user.ModifyDt     = DateTime.Today;
                user.PartitionKey = 1;

                await _cosmosDbService.AddItemAsync(user, user.DbGrouping);

                model.IsSuccess = true;
            }
            catch (Exception ex)
            {
                model.IsSuccess = false;
            }

            return(model);
        }
コード例 #4
0
        //[ValidateAntiForgeryToken]
        public ActionResult Edit(CMUser cMUser, HttpPostedFileBase ProfileImage)
        {
            ModelState.Remove("CreatedOn");
            ModelState.Remove("ModifiedOn");
            ModelState.Remove("ModifiedUsername");
            if (ModelState.IsValid)
            {
                if (ProfileImage != null &&
                    (ProfileImage.ContentType == "image/jpeg" ||
                     ProfileImage.ContentType == "image/jpg" ||
                     ProfileImage.ContentType == "image/png"))
                {
                    string filename = $"user_{cMUser.ActivateGuid}.{ProfileImage.ContentType.Split('/')[1]}";

                    ProfileImage.SaveAs(Server.MapPath($"~/Image/{filename}"));
                    cMUser.ProfileImageFilename = filename;
                }

                BusinessLayerResult <CMUser> res = cmUserManager.UpdateProfile(cMUser);

                if (res.Errors.Count > 0)
                {
                    res.Errors.ForEach(x => ModelState.AddModelError("", x.Message));
                    return(RedirectToAction("Index"));
                }

                // Profil güncellendiği için session güncellendi.
                CurrentSession.Set <CMUser>("login", res.Result);

                return(RedirectToAction("Details", new { activateGuid = res.Result.ActivateGuid }));
            }

            return(View(cMUser));
        }
コード例 #5
0
        public ActionResult CalısanEkle(EmployeeRegister model)
        {
            if (ModelState.IsValid)
            {
                var user = new CMUser()
                {
                    UserName  = model.UserName,
                    CompanyId = model.CompanyId,
                    Email     = model.Email,
                };

                var result = userManager.Create(user, model.Password);

                if (result.Succeeded)
                {
                    //kullanıcı başarılı şekilde oluşturulmuş ise login sayfasına gönderebiliriz.
                    return(RedirectToAction("Login"));
                }
                else
                {
                    foreach (var error in result.Errors)
                    {
                        ModelState.AddModelError("", error);
                    }
                }
            }
            return(View(model));
        }
コード例 #6
0
        // 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)));
        }
コード例 #7
0
        /// <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)));
        }
コード例 #8
0
        public Task <CMResponse> DeleteUser(CMUser user)
        {
            CMRequestOptions opts = new CMRequestOptions();

            opts.SetCredentials(user.Credentials);

            return(APIService.Request(this.Application, "account", HttpMethod.Delete, null, opts));
        }
コード例 #9
0
 public string GetCurrentUsername()
 {
     if (HttpContext.Current.Session["login"] != null)
     {
         CMUser user = HttpContext.Current.Session["login"] as CMUser;
         return(user.Fullname);
     }
     return("system");
 }
コード例 #10
0
        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));
        }
コード例 #11
0
        /// <summary>
        /// Allows for unregistering a valid logged in CMUser from push notifications.
        /// </summary>
        /// <param name="user">Valid logged in CMUser</param>
        /// <param name="uniqueDeviceId">UIKit.UIDevice.CurrentDevice.IdentifierForVendor.AsString()</param>
        public Task <CMResponse> UnRegisterIOSDevicePushNotifications(CMUser user, string uniqueDeviceId)
        {
            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");

            return(APIService.Request(Application, "device", HttpMethod.Delete, null, options));
        }
コード例 #12
0
        /// <summary>
        /// Unregister WP device push notifications.
        /// </summary>
        /// <returns>The register WP device push notifications.</returns>
        /// <param name="user">User with valid session.</param>
        /// <param name="uniqueDeviceId">Windows.Phone.System.Analytics.HostInformation.PublisherHostId</param>
        public Task <CMResponse> UnRegisterWPDevicePushNotifications(CMUser user, string uniqueDeviceId)
        {
            CMRequestOptions options = new CMRequestOptions(null, user);

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

            throw new NotImplementedException();
        }
コード例 #13
0
        /// <summary>
        /// Deletes all user objects. Deletes objects that match specified keys. If no keys are specified, no action will be taken unless
        /// the all=true parameter is specified in the URL. If that is specified, all data will be deleted.
        /// The purpose of this extra parameter is to avoid accidental total data deletion.
        /// </summary>
        /// <returns>The all user objects.</returns>
        /// <param name="user">User.</param>
        /// <param name="opts">Optional Request parameters for things like post execution snippet params.</param>
        public Task <CMObjectResponse> DeleteAllUserObjects(CMUser user, CMRequestOptions opts = null)
        {
            if (opts == null)
            {
                opts = new CMRequestOptions();
            }

            opts.Query["all"] = true.ToString();
            return(APIService.Request <CMObjectResponse>(this.Application, "user/text", HttpMethod.Delete, null, new CMRequestOptions(opts, user)));
        }
コード例 #14
0
        public ActionResult DeleteConfirmed(Guid activateGuid)
        {
            if (activateGuid == null || activateGuid == Guid.Empty)
            {
                return(new HttpStatusCodeResult(HttpStatusCode.BadRequest));
            }
            CMUser cMUser = cmUserManager.Find(x => x.ActivateGuid == activateGuid);

            cmUserManager.Delete(cMUser);
            return(RedirectToAction("Index"));
        }
コード例 #15
0
        // Search =============
        /// <summary>
        /// Performs a search query based on the string query and ensures the type of the query results
        /// are of the generic type parameter.
        /// </summary>
        /// <typeparam name="T">Becomes the __class__ parameter of the query. Uses Type name as the value</typeparam>
        /// <param name="query">String query for CloudMine search. Please reference dos at: https://cloudmine.io/docs/api#query_syntax </param>
        /// <param name="user"></param>
        /// <param name="opts"></param>
        public Task <CMObjectSearchResponse <T> > SearchUserObjects <T>(CMUser user, string query, CMRequestOptions opts = null) where T : CMObject
        {
            if (opts == null)
            {
                opts = new CMRequestOptions();
            }
            opts.Query["q"] = query;
            // add __class__ of type T name to the query passed in

            return(APIService.Request <CMObjectSearchResponse <T> >(this.Application, "user/search", HttpMethod.Get, null, new CMRequestOptions(opts, user)));
        }
コード例 #16
0
        /// <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));
        }
コード例 #17
0
        /// <summary>
        /// Gets the user objects.
        /// </summary>
        /// <returns>The user objects.</returns>
        /// <param name="user">User with session to use in the request.</param>
        /// <param name="keys">Collection of key,__id__,ID</param>
        /// <param name="opts">Optional Request parameters for things like post execution snippet params.</param>
        /// <typeparam name="T">The 1st type parameter.</typeparam>
        public Task <CMObjectFetchResponse <T> > GetUserObjects <T>(CMUser user, string[] keys, CMRequestOptions opts = null) where T : CMObject
        {
            if (keys.Length > 0)
            {
                if (opts == null)
                {
                    opts = new CMRequestOptions(user);
                }
                opts.Headers["keys"] = String.Join(",", keys);
            }

            return(APIService.Request <CMObjectFetchResponse <T> >(this.Application, "user/text", HttpMethod.Get, null, opts));
        }
コード例 #18
0
        // Get ==============
        /// <summary>
        /// Gets an object of type CMObject by (key,__id__) and returns that Type
        /// automatically parsed into the proper type in the Success field of the results.
        /// </summary>
        /// <returns>The user object.</returns>
        /// <param name="user">User with session to use in the request.</param>
        /// <param name="key">key,__id__,ID</param>
        /// <param name="opts">Optional Request parameters for things like post execution snippet params.</param>
        /// <typeparam name="T">a Type which derives from CMObject. Used to parse results</typeparam>
        public Task <CMObjectFetchResponse <T> > GetUserObject <T>(CMUser user, string key, CMRequestOptions opts = null) where T : CMObject
        {
            if (opts == null)
            {
                opts = new CMRequestOptions(user);
            }
            if (key != null)
            {
                opts.Query["keys"] = key;
            }

            return(APIService.Request <CMObjectFetchResponse <T> >(this.Application, "user/text", HttpMethod.Get, null, opts));
        }
コード例 #19
0
        public ActionResult Edit(Guid activateGuid)
        {
            if (activateGuid == null || activateGuid == Guid.Empty)
            {
                return(new HttpStatusCodeResult(HttpStatusCode.BadRequest));
            }
            CMUser cMUser = cmUserManager.Find(x => x.ActivateGuid == activateGuid);

            if (cMUser == null)
            {
                return(HttpNotFound());
            }
            return(View(cMUser));
        }
コード例 #20
0
        /// <summary>
        /// Searchs the user profiles of an application given a CloudMine search query string.
        /// </summary>
        /// <returns>The users.</returns>
        /// <param name="user">User.</param>
        /// <param name="query">Query.</param>
        /// <param name="opts">Any custom options for the request such as snippet execution on upload completion.</param>
        public Task <CMResponse> SearchUsers(CMUser user, string query, CMRequestOptions opts = null)
        {
            if (opts == null)
            {
                opts = new CMRequestOptions();
            }

            if (string.IsNullOrEmpty(opts.Query["q"]))
            {
                opts.Query["q"] = query;
            }

            return(APIService.Request <CMResponse>(this.Application, "account/search/", HttpMethod.Get, null, new CMRequestOptions(opts, user)));
        }
コード例 #21
0
        /// <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 be created at the server</param>
        /// <param name="user">the user for which this object will be created</param>
        /// <param name="opts">Optional Request parameters for things like post execution snippet params.</param>
        public Task <CMObjectResponse> SetUserObject <T>(CMUser user, 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);

            return(APIService.Request <CMObjectResponse>(this.Application, "user/text", HttpMethod.Put, CMSerializer.ToStream(dataDict), new CMRequestOptions(opts, user)));
        }
コード例 #22
0
        /// <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)));
        }
コード例 #23
0
 /// <summary>
 /// Deletes the user objects. Deletes objects that match specified keys. If no keys are specified, no action will be taken unless
 /// the all=true parameter is specified in the URL. If that is specified, all data will be deleted.
 /// The purpose of this extra parameter is to avoid accidental total data deletion.
 /// </summary>
 /// <returns>The user objects.</returns>
 /// <param name="keys">Keys for the user objects to be deleted. Also known as ID, __id__</param>
 /// <param name="user">User.</param>
 /// <param name="opts">Optional Request parameters for things like post execution snippet params.</param>
 public Task <CMObjectResponse> DeleteUserObjects(CMUser user, string[] keys, CMRequestOptions opts = null)
 {
     if (keys != null && keys.Length > 0)
     {
         if (opts == null)
         {
             opts = new CMRequestOptions();
         }
         opts.Query["keys"] = String.Join(",", keys);
         return(APIService.Request <CMObjectResponse>(this.Application, "user/text", HttpMethod.Delete, null, new CMRequestOptions(opts, user)));
     }
     else
     {
         throw new InvalidOperationException("Cannot delete empty data. At least one item must be present to delete.");
     }
 }
コード例 #24
0
        /// <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));
        }
コード例 #25
0
        /// <summary>
        /// Registers the WP device push notifications.
        /// </summary>
        /// <returns>The WP device push notifications.</returns>
        /// <param name="user">User with valid session.</param>
        /// <param name="uniqueDeviceId">Windows.Phone.System.Analytics.HostInformation.PublisherHostId</param>
        /// <param name="wpToken">Device token.</param>
        public Task <CMResponse> RegisterWPDevicePushNotifications(CMUser user, string uniqueDeviceId, object wpToken)
        {
            CMRequestOptions options = new CMRequestOptions(null, user);

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

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

            dataDict.Add("token", wpToken);
            dataDict.Add("device_type", "wp");
            dataDict.Add("device_id", uniqueDeviceId);

            throw new NotImplementedException();
        }
コード例 #26
0
        // Download file ========
        public Task <CMFileResponse> Download(CMUser user, string key, CMRequestOptions opts)
        {
            if (opts == null)
            {
                opts             = new CMRequestOptions();
                opts.ContentType = "application/octet-stream";
            }

            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 <CMFileResponse>(this.Application, "user/binary/" + key, HttpMethod.Get, null, new CMRequestOptions(opts, user)));
        }
コード例 #27
0
        /// <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));
        }
コード例 #28
0
        public async Task UpdateItemAsync(object obj, string dbGrouping)
        {
            if (dbGrouping == "ExistingInvestment")
            {
                ExistingInvestment investment = new ExistingInvestment();

                investment = (ExistingInvestment)obj;

                await this._container.UpsertItemAsync <ExistingInvestment>(investment, new PartitionKey(investment.PartitionKey));
            }
            else if (dbGrouping == "User")
            {
                CMUser user = new CMUser();

                user = (CMUser)obj;

                await this._container.UpsertItemAsync <CMUser>(user, new PartitionKey(user.PartitionKey));
            }
        }
コード例 #29
0
        public ActionResult Create(CMUser cMUser)
        {
            ModelState.Remove("CreatedOn");
            ModelState.Remove("ModifiedOn");
            ModelState.Remove("ModifiedUsername");

            if (ModelState.IsValid)
            {
                BusinessLayerResult <CMUser> res = cmUserManager.RegisterUser(cMUser);

                if (res.Errors.Count > 0)
                {
                    res.Errors.ForEach(x => ModelState.AddModelError("", x.Message));
                    return(RedirectToAction("Index"));
                }
            }

            return(View(cMUser));
        }
コード例 #30
0
        /// <summary>
        /// Logoff the specified user and options. Leverages the credentials or session token
        /// available on the user object to invalidate user login. Will also set the current
        /// session token and sesssion expiration to empty on a successful request.
        /// </summary>
        /// <param name="user">User.</param>
        /// <param name="options">Any additional options like snippet execution parameters.</param>
        public Task <CMLogoutResponse> Logoff(CMUser user, CMRequestOptions options = null)
        {
            if (options == null)
            {
                options = new CMRequestOptions(null, user);
            }

            var logout = APIService.Request <CMLogoutResponse>(this.Application, "account/logout", HttpMethod.Post, null, options);

            // TODO: Stuff in the await which invalidates the session on the user param obj
            logout.ContinueWith(result => {
                if (result.IsCompleted)
                {
                    // erase the session token
                    user.Session        = string.Empty;
                    user.SessionExpires = DateTime.MinValue;
                }
            }).Wait();             // ensures the continue with happens before user defined things

            return(logout);
        }