/// <summary>
        /// Ensure that we have a valid subscription to receive webhooks for the target folder
        /// on this account.
        /// </summary>
        /// <param name="account"></param>
        /// <param name="log"></param>
        /// <returns></returns>
        public static async Task SubscribeToWebhooksForAccount(Account account, WebJobLogger log)
        {
            try
            {
                log.WriteLog(ActivityEventCode.CreatingSubscription, "Creating subscription on OneDrive service.");

                log.WriteLog("Connecting to OneDrive...");

                // Build a new OneDriveClient with the account information
                var client = await SharedConfig.GetOneDriveClientForAccountAsync(account);

                await CreateNewSubscriptionAsync(account, client, log);

                account.WebhooksReceived += 1;
                await AzureStorage.UpdateAccountAsync(account);

                log.WriteLog("Updated account {0} with hooks received: {1}", account.Id, account.WebhooksReceived);
            }
            catch (Exception ex)
            {
                log.WriteLog("Exception: {0}", ex);
            }
            finally
            {
                AccountLocker.ReleaseLock(account.Id);
            }
        }
        public async Task <IHttpActionResult> CreateFile()
        {
            var cookies = Request.Headers.GetCookies("session").FirstOrDefault();

            if (cookies == null)
            {
                return(JsonResponseEx.Create(HttpStatusCode.Unauthorized, new { message = "Session cookie is missing." }));
            }
            var sessionCookieValue = cookies["session"].Values;
            var account            = await AuthorizationController.AccountFromCookie(sessionCookieValue, false);

            if (null == account)
            {
                return(JsonResponseEx.Create(HttpStatusCode.Unauthorized, new { message = "Failed to locate an account for the auth cookie." }));
            }

            var client = await SharedConfig.GetOneDriveClientForAccountAsync(account);

            var item = await client.Drive.Special[account.SourceFolder].ItemWithPath("test_file.txt").Content.Request().PutAsync <Item>(this.TestFileStream());

            await AzureStorage.InsertActivityAsync(
                new Activity
            {
                UserId  = account.Id,
                Type    = ActivityEventCode.FileChanged,
                Message = string.Format("Creating test file test_file.txt with resource id: {0}", item.Id)
            });

            return(JsonResponseEx.Create(HttpStatusCode.OK, item));
        }
        public async Task <IHttpActionResult> FetchStatisticsAsync()
        {
            var cookies = Request.Headers.GetCookies("session").FirstOrDefault();

            if (cookies == null)
            {
                return(JsonResponseEx.Create(HttpStatusCode.Unauthorized, new { message = "Session cookie is missing." }));
            }
            var sessionCookieValue = cookies["session"].Values;
            var account            = await AuthorizationController.AccountFromCookie(sessionCookieValue, false);

            if (null == account)
            {
                return(JsonResponseEx.Create(HttpStatusCode.Unauthorized, new { message = "Failed to locate an account for the auth cookie." }));
            }

            var client = await SharedConfig.GetOneDriveClientForAccountAsync(account);

            var cameraRollFolder = await client.Drive.Special["cameraroll"].Request().GetAsync();


            var responseObj = new
            {
                itemCount    = cameraRollFolder.Folder.ChildCount,
                totalSize    = cameraRollFolder.Size,
                lastModified = cameraRollFolder.LastModifiedDateTime
            };

            return(JsonResponseEx.Create(HttpStatusCode.OK, responseObj));
        }
        /// <summary>
        /// Process the changes for an account's OneDrive and organize any new files returned.
        /// </summary>
        /// <returns></returns>
        public static async Task ProcessChangesInOneDriveAsync(Account account, WebJobLogger log)
        {
            #region Acquire lock for account or abort processing
            // Acquire a simple lock to ensure that only one thread is processing
            // an account at the same time to avoid concurrency issues.
            // NOTE: If the web job is running on multiple VMs, this will not be sufficent to
            // ensure errors don't occur from one account being processed multiple times.
            bool acquiredLock = AccountLocker.TryAcquireLock(account.Id);
            if (!acquiredLock || !account.Enabled)
            {
                log.WriteLog("Failed to acquire lock for account. Another thread is already processing updates for this account or the account is disabled.");
                return;
            }
            log.WriteLog("Account lock acquired. Connecting to OneDrive.");
            #endregion

            try
            {
                // Build a new OneDriveClient with the account information
                var client = await SharedConfig.GetOneDriveClientForAccountAsync(account);

                // Execute our organization code
                FolderOrganizer organizer = new FolderOrganizer(client, account, log);
                await organizer.OrganizeSourceFolderItemChangesAsync();

                // Record that we received another webhook and save the account back to table storage
                account.WebhooksReceived += 1;
                await AzureStorage.UpdateAccountAsync(account);

                log.WriteLog("Updated account {0} with hooks received: {1}", account.Id, account.WebhooksReceived);
            }
            #region Error Handling
            catch (Exception ex)
            {
                log.WriteLog("Exception: {0}", ex);
            }
            finally
            {
                AccountLocker.ReleaseLock(account.Id);
            }

            log.WriteLog("Processing completed for account: {0}", account.Id);
            #endregion
        }
        public async Task <IHttpActionResult> AuthRedirect(string code)
        {
            // Redeem authorization code for account information

            OAuthHelper helper = new OAuthHelper(SharedConfig.TokenService,
                                                 SharedConfig.AppClientID,
                                                 SharedConfig.AppClientSecret,
                                                 SharedConfig.RedirectUri);

            var token = await helper.RedeemAuthorizationCodeAsync(code);

            if (null == token)
            {
                return(JsonResponseEx.Create(HttpStatusCode.InternalServerError, new { message = "Invalid response from token service.", code = "tokenServiceNullResponse" }));
            }

            Account account = new Account(token);
            var     client  = await SharedConfig.GetOneDriveClientForAccountAsync(account);

            var rootDrive = await client.Drive.Request().GetAsync();

            account.Id          = rootDrive.Id;
            account.DisplayName = rootDrive.Owner.User.DisplayName;

            var existingAccount = await AzureStorage.LookupAccountAsync(rootDrive.Id);

            if (null == existingAccount)
            {
                await AzureStorage.InsertAccountAsync(account);

                existingAccount = account;
            }
            else
            {
                existingAccount.SetTokenResponse(token);
                await AzureStorage.UpdateAccountAsync(existingAccount);
            }

            var authCookie = CookieForAccount(existingAccount);

            return(RedirectResponse.Create("/default.aspx", authCookie));
        }