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 })); }