Beispiel #1
0
        public async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "subscribe")] SubscribeModel subscribeModel,
            [OrchestrationClient] DurableOrchestrationClient starter,
            ILogger log)
        {
            // validate model
            if (!subscribeModel.IsValid())
            {
                log.LogError("Validating model failed.");
                return(new BadRequestResult());
            }

            // validate with JDA
            var credentials = subscribeModel.AsCredentialsModel();

            _scheduleSourceService.SetCredentials(subscribeModel.TeamId, credentials);

            StoreModel store;

            try
            {
                store = await _scheduleSourceService.GetStoreAsync(subscribeModel.TeamId, subscribeModel.StoreId).ConfigureAwait(false);
            }
            catch (ArgumentException e)
            {
                log.LogError(e, "Subscribe failed - JDA store id incorrect.");
                return(new BadRequestResult());
            }
            catch (KeyNotFoundException e)
            {
                log.LogError(e, "Subscribe failed - JDA store not found.");
                return(new NotFoundResult());
            }
            catch (UnauthorizedAccessException e)
            {
                log.LogError(e, "Subscribe failed - Invalid url or credentials.");
                return(new UnauthorizedResult());
            }

            // ensure that we can map the timezone for the store
            var timeZoneInfoId = await TimeZoneHelper.GetTimeZoneAsync(subscribeModel.TeamId, store.TimeZoneId, _timeZoneService, _scheduleSourceService, _scheduleConnectorService, log).ConfigureAwait(false);

            if (timeZoneInfoId == null)
            {
                log.LogError($"Subscribe failed - No time zone mapping found for store TimeZoneId={store.TimeZoneId}.");
                return(new InternalServerErrorResult());
            }

            // exchange and save access token
            if (!string.IsNullOrEmpty(subscribeModel.AuthorizationCode))
            {
                var tokenResponse = await _httpClientFactory.Client.RequestTokenAsync(_options, subscribeModel.RedirectUri, subscribeModel.AuthorizationCode).ConfigureAwait(false);

                if (tokenResponse.IsError)
                {
                    log.LogError("Subscribe failed - Invalid authorization code.");
                    return(new ForbidResult());
                }

                var tokenModel = tokenResponse.AsTokenModel();

                await _secretsService.SaveTokenAsync(subscribeModel.TeamId, tokenModel).ConfigureAwait(false);
            }
            else if (!string.IsNullOrEmpty(subscribeModel.AccessToken))
            {
                var tokenModel = subscribeModel.AsTokenModel();

                await _secretsService.SaveTokenAsync(subscribeModel.TeamId, tokenModel).ConfigureAwait(false);
            }

            // save JDA creds
            await _secretsService.SaveCredentialsAsync(subscribeModel.TeamId, credentials).ConfigureAwait(false);

            // get the team from Teams
            GroupModel team;

            try
            {
                team = await _scheduleDestinationService.GetTeamAsync(subscribeModel.TeamId).ConfigureAwait(false);
            }
            catch (Exception e)
            {
                log.LogError(e, "Subscribe failed - Not authorized to access details for the team.");
                return(new ForbidResult());
            }

            var teamModel = subscribeModel.AsTeamModel();

            teamModel.TimeZoneInfoId = timeZoneInfoId;

            var connectionModel = subscribeModel.AsConnectionModel();

            connectionModel.TimeZoneInfoId = timeZoneInfoId;
            connectionModel.StoreName      = store.StoreName;
            connectionModel.TeamName       = team.Name;

            try
            {
                // ensure that if the team is re-subscribing, that they haven't changed the store
                // that they are connecting to
                var existingModel = await _scheduleConnectorService.GetConnectionAsync(subscribeModel.TeamId).ConfigureAwait(false);

                if (connectionModel.StoreId != existingModel.StoreId)
                {
                    log.LogError("Re-subscribe failed - JDA store id changed.");
                    return(new BadRequestResult());
                }
                else
                {
                    // as the team is re-subscribing, ensure that the schedule is not re-initialized
                    teamModel.Initialized = true;
                }
            }
            catch { /* nothing to do - new subscription */ }

            // save connection settings
            await _scheduleConnectorService.SaveConnectionAsync(connectionModel).ConfigureAwait(false);

            // start singleton team orchestrator
            await starter.TryStartSingletonAsync(nameof(TeamOrchestrator), teamModel.TeamId, teamModel).ConfigureAwait(false);

            return(new OkObjectResult(new StoreModel
            {
                StoreId = connectionModel.StoreId,
                StoreName = connectionModel.StoreName
            }));
        }
        public async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "subscribe")] SubscribeModel subscribeModel,
            [DurableClient] IDurableOrchestrationClient starter,
            ILogger log)
        {
            // validate model
            if (!subscribeModel.IsValid())
            {
                log.LogError("Validating model failed.");
                return(new BadRequestResult());
            }

            // validate with WFM Provider
            BusinessUnitModel businessUnit;

            try
            {
                businessUnit = await _wfmDataService.GetBusinessUnitAsync(subscribeModel.WfmBuId, log).ConfigureAwait(false);
            }
            catch (ArgumentException e)
            {
                log.LogError(e, "Subscribe failed - business unit id invalid.");
                return(new BadRequestResult());
            }
            catch (KeyNotFoundException e)
            {
                log.LogError(e, "Subscribe failed - business unit not found.");
                return(new NotFoundResult());
            }
            catch (UnauthorizedAccessException e)
            {
                log.LogError(e, "Subscribe failed - invalid credentials.");
                return(new UnauthorizedResult());
            }

            // get the team from Teams
            GroupModel team;

            try
            {
                team = await _teamsService.GetTeamAsync(subscribeModel.TeamId).ConfigureAwait(false);
            }
            catch (Exception e)
            {
                log.LogError(e, "Subscribe failed - Not authorized to access details for the team.");
                return(new ForbidResult());
            }

            var teamModel = subscribeModel.AsTeamModel();

            teamModel.TimeZoneInfoId = businessUnit.TimeZoneInfoId;

            var connectionModel = subscribeModel.AsConnectionModel();

            connectionModel.TimeZoneInfoId = businessUnit.TimeZoneInfoId;
            connectionModel.WfmBuName      = businessUnit.WfmBuName;
            connectionModel.TeamName       = team.Name;
            connectionModel.Enabled        = true;

            try
            {
                // ensure that if the team is re-subscribing, that they haven't changed the business
                // unit that they are connecting to
                var existingModel = await _scheduleConnectorService.GetConnectionAsync(subscribeModel.TeamId).ConfigureAwait(false);

                if (connectionModel.WfmBuId != existingModel.WfmBuId)
                {
                    log.LogError("Re-subscribe failed - WFM business unit id changed.");
                    return(new BadRequestResult());
                }
            }
            catch
            {
                // as this is a new subscription, we need to initialize the team with a new schedule
                await starter.StartNewAsync(nameof(InitializeOrchestrator), teamModel).ConfigureAwait(false);

                // and delay the first execution of the sync orchestrators by at least 5 minutes
                DelayOrchestratorsFirstExecution(connectionModel, 5);
            }

            // save connection settings
            await _scheduleConnectorService.SaveConnectionAsync(connectionModel).ConfigureAwait(false);

            log.LogSubscribeTeam(connectionModel);

            return(new OkObjectResult(new BusinessUnitModel
            {
                WfmBuId = connectionModel.WfmBuId,
                WfmBuName = connectionModel.WfmBuName
            }));
        }