feat: initial commit
This commit is contained in:
@@ -0,0 +1,122 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Strata.Analytics.Biz.ContentMigration.Services;
|
||||
using Strata.Analytics.Biz.ContentMigration.Models;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Strata.Analytics.Api.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
using Strata.Analytics.Biz.ContentMigration.Models.MigrationPlan;
|
||||
|
||||
namespace Strata.Analytics.Api.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
[ApiVersion("1.0")]
|
||||
[Route("api/v{api-version:apiVersion}/[controller]")]
|
||||
public class ContentMigrationController : ControllerBase
|
||||
{
|
||||
private readonly IContentMigrationService _contentMigrationService;
|
||||
|
||||
public ContentMigrationController(IContentMigrationService contentMigrationService)
|
||||
{
|
||||
_contentMigrationService = contentMigrationService;
|
||||
}
|
||||
|
||||
[HttpGet("legacy-reports")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
public async Task<IEnumerable<ReReportDisplay>> GetAdHocReports(CancellationToken cancellationToken)
|
||||
{
|
||||
return await _contentMigrationService.GetAdHocReports(cancellationToken);
|
||||
}
|
||||
|
||||
[HttpPost("{reportGuid}/migrate")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
public async Task<ActionResult<AdhocMigrationResult>> MigrateReport([FromRoute] Guid reportGuid, [FromQuery, BindRequired] int workbookId, [FromQuery, BindRequired] int dataSourceId, [FromBody] Plan plan, CancellationToken cancellationToken)
|
||||
{
|
||||
var migratedReport = await _contentMigrationService.MigrateReport(reportGuid, workbookId, dataSourceId, plan, cancellationToken);
|
||||
if (migratedReport == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
return Ok(migratedReport);
|
||||
}
|
||||
|
||||
[HttpPost("{reportGuid}/migrateExtract")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
public async Task<ActionResult<ExtractMigrationResult>> MigrateReportToExtract([FromRoute] Guid reportGuid, [FromQuery, BindRequired] int dataSourceId, [FromBody] Plan plan, CancellationToken cancellationToken)
|
||||
{
|
||||
var migratedReport = await _contentMigrationService.MigrateReportToExtract(reportGuid, dataSourceId, plan, cancellationToken);
|
||||
if (migratedReport == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
return Ok(migratedReport);
|
||||
}
|
||||
|
||||
[HttpGet("migrationPlan")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
public async Task<ActionResult<Plan>> GetMigrationPlan([FromQuery, BindRequired] Guid reportGuid, [FromQuery, BindRequired] int dataSourceId, CancellationToken cancellationToken)
|
||||
{
|
||||
var migrationPlan = await _contentMigrationService.GetMigrationPlan(reportGuid, dataSourceId, cancellationToken);
|
||||
if (migrationPlan == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
return Ok(migrationPlan);
|
||||
}
|
||||
|
||||
[HttpPut("dataMappings")]
|
||||
[Authorize(Policy = Policies.StrataOnly)]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
public async Task<ActionResult<DataMapping>> UpdateDataMapping([FromBody] DataMapping dataMapping, CancellationToken cancellationToken)
|
||||
{
|
||||
var updatedDataMapping = await _contentMigrationService.UpdateDataMapping(dataMapping, cancellationToken);
|
||||
if (updatedDataMapping == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
return Ok(updatedDataMapping);
|
||||
}
|
||||
|
||||
[HttpGet("dataMappings")]
|
||||
[Authorize(Policy = Policies.StrataOnly)]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<IEnumerable<DataMapping>>> GetDataMappings(CancellationToken cancellationToken)
|
||||
{
|
||||
var dataMappings = await _contentMigrationService.GetDataMappings(cancellationToken);
|
||||
return Ok(dataMappings);
|
||||
}
|
||||
|
||||
[HttpPost("dataMappings")]
|
||||
[Authorize(Policy = Policies.StrataOnly)]
|
||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||
public async Task<ActionResult> AddDataMappings([FromBody] IEnumerable<DataMapping> dataMappings, CancellationToken cancellationToken)
|
||||
{
|
||||
await _contentMigrationService.AddDataMappings(dataMappings, cancellationToken);
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
[HttpDelete("dataMappings/{dataMappingId}")]
|
||||
[Authorize(Policy = Policies.StrataOnly)]
|
||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
public async Task<ActionResult> DeleteDataMapping([FromRoute] int dataMappingId, CancellationToken cancellationToken)
|
||||
{
|
||||
var mapping = await _contentMigrationService.GetDataMapping(dataMappingId, cancellationToken);
|
||||
if (mapping == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
await _contentMigrationService.DeleteDataMapping(mapping, cancellationToken);
|
||||
return NoContent();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,241 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Strata.Analytics.Api.Authorization;
|
||||
using Strata.Analytics.Biz.DataQuery;
|
||||
using Strata.Analytics.Biz.DataSources.Models;
|
||||
using Strata.Analytics.Biz.DataSources.Services;
|
||||
using Strata.Analytics.Biz.Export.Models;
|
||||
using Strata.Analytics.Biz.Export.Services;
|
||||
using Strata.Analytics.Models.Utils;
|
||||
using Strata.DataSchema.Models.Query;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Strata.Analytics.Api.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
[ApiVersion("1.0")]
|
||||
[Route("api/v{api-version:apiVersion}/[controller]")]
|
||||
public class DataSourcesController : ControllerBase
|
||||
{
|
||||
private readonly IDataSourceService _dataSourceService;
|
||||
private readonly IDataQueryService _dataQueryService;
|
||||
private readonly IExportService _exportService;
|
||||
private readonly ILogger<DataSourcesController> _logger;
|
||||
|
||||
public DataSourcesController(IDataSourceService dataSourceService, IDataQueryService dataQueryService, IExportService exportService, ILogger<DataSourcesController> logger)
|
||||
{
|
||||
_dataSourceService = dataSourceService;
|
||||
_dataQueryService = dataQueryService;
|
||||
_exportService = exportService;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public async Task<IEnumerable<DataSource>> GetDataSourcesAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
|
||||
return await _dataSourceService.GetAllAsync(cancellationToken);
|
||||
}
|
||||
|
||||
[HttpGet("{dataSourceId}")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
[ProducesDefaultResponseType]
|
||||
public async Task<ActionResult<DataSource>> GetById(int dataSourceId, CancellationToken cancellationToken)
|
||||
{
|
||||
var dataSource = await _dataSourceService.GetByIdAsync(dataSourceId, cancellationToken);
|
||||
if (dataSource == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
return Ok(dataSource);
|
||||
}
|
||||
|
||||
[HttpPut("{dataSourceId}")]
|
||||
[Authorize(Policy = Policies.DataSourceEditor)]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status403Forbidden)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
[ProducesDefaultResponseType]
|
||||
public async Task<ActionResult<DataSource>> Update(int dataSourceId, DataSourceSaveInfo dataSourceSaveInfo, CancellationToken cancellationToken)
|
||||
{
|
||||
var isFound = await _dataSourceService.ContainsAsync(dataSourceId, cancellationToken);
|
||||
if (!isFound)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
var updatedDataSource = await _dataSourceService.UpdateAsync(dataSourceId, dataSourceSaveInfo, cancellationToken);
|
||||
|
||||
return Ok(updatedDataSource);
|
||||
}
|
||||
|
||||
[HttpPut("")]
|
||||
[Authorize(Policy = Policies.DataSourceEditor)]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status403Forbidden)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
[ProducesDefaultResponseType]
|
||||
public async Task<ActionResult<DataSource>> Save(DataSourceSaveInfo dataSourceSaveInfo, CancellationToken cancellationToken)
|
||||
{
|
||||
var isFound = await _dataSourceService.ContainsAsync(dataSourceSaveInfo.DataSourceId, cancellationToken);
|
||||
if (!isFound)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
var updatedDataSource = await _dataSourceService.SaveAsync(dataSourceSaveInfo, cancellationToken);
|
||||
|
||||
return Ok(updatedDataSource);
|
||||
}
|
||||
|
||||
[HttpDelete("{dataSourceId}")]
|
||||
[Authorize(Policy = Policies.DataSourceEditor)]
|
||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||
[ProducesResponseType(StatusCodes.Status403Forbidden)]
|
||||
[ProducesDefaultResponseType]
|
||||
public async Task<IActionResult> Delete(int dataSourceId, CancellationToken cancellationToken)
|
||||
{
|
||||
await _dataSourceService.DeleteAsync(dataSourceId, cancellationToken);
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
[HttpPost("")]
|
||||
[Authorize(Policy = Policies.StrataOnly)]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status403Forbidden)]
|
||||
public async Task<ActionResult<DataSource>> Create(DataSourceSaveInfo dataSourceSaveInfo, CancellationToken cancellationToken)
|
||||
{
|
||||
return await _dataSourceService.CreateAsync(dataSourceSaveInfo, cancellationToken);
|
||||
}
|
||||
|
||||
[HttpPost("{dataSourceId}/tables/{dataTableId}")]
|
||||
[Authorize(Policy = Policies.DataSourceEditor)]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status403Forbidden)]
|
||||
[ProducesDefaultResponseType]
|
||||
public async Task<ActionResult<DataSourceTable>> AddDataTableLink([FromRoute] int dataSourceId, [FromRoute] int dataTableId, CancellationToken cancellationToken)
|
||||
{
|
||||
return await _dataSourceService.AddDataTableAsync(dataSourceId, dataTableId, cancellationToken);
|
||||
}
|
||||
|
||||
[HttpDelete("{dataSourceId}/tables/{dataTableId}")]
|
||||
[Authorize(Policy = Policies.DataSourceEditor)]
|
||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||
[ProducesResponseType(StatusCodes.Status403Forbidden)]
|
||||
[ProducesDefaultResponseType]
|
||||
public async Task<ActionResult> DeleteDataTableLink([FromRoute] int dataSourceId, [FromRoute] int dataTableId, CancellationToken cancellationToken)
|
||||
{
|
||||
await _dataSourceService.DeleteDataTableAsync(dataSourceId, dataTableId, cancellationToken);
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
[HttpGet("{dataSourceId}/role-assignments")]
|
||||
[Authorize(Policy = Policies.DataSourceViewer)]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status403Forbidden)]
|
||||
[ProducesDefaultResponseType]
|
||||
public async Task<ActionResult<IEnumerable<DataSourceRoleAssignment>>> GetRoleAssignments([FromRoute] int dataSourceId, CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await _dataSourceService.GetRoleAssignmentsAsync(new List<int> { dataSourceId }, cancellationToken));
|
||||
}
|
||||
|
||||
[HttpPost("{dataSourceId}/role-assignments/batch")]
|
||||
[Authorize(Policy = Policies.DataSourceEditor)]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status403Forbidden)]
|
||||
[ProducesDefaultResponseType]
|
||||
public async Task<ActionResult<IEnumerable<DataSourceRoleAssignment>>> SaveRoleAssignments([FromRoute] int dataSourceId, [FromBody] Batch<DataSourceRoleAssignmentSaveInfo, Guid> roleAssignments, CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await _dataSourceService.SaveRoleAssignmentsAsync(dataSourceId, roleAssignments, cancellationToken));
|
||||
}
|
||||
|
||||
[HttpPost("{dataSourceId}/datacolumn/values")]
|
||||
[Authorize(Policy = Policies.DataSourceViewer)]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||
[ProducesResponseType(StatusCodes.Status403Forbidden)]
|
||||
[ProducesDefaultResponseType]
|
||||
public async Task<ActionResult<IEnumerable<dynamic>>> GetColumnValues([FromRoute] int dataSourceId, [FromBody] ColumnQueryConfig columnQueryConfig, CancellationToken cancellationToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Ok(await _dataQueryService.GetColumnValues(columnQueryConfig, cancellationToken));
|
||||
}
|
||||
catch (UnauthorizedAccessException)
|
||||
{
|
||||
var dataColumnIds = new List<int> { columnQueryConfig.DataColumnId };
|
||||
if (columnQueryConfig.Filter != null)
|
||||
dataColumnIds.Add(columnQueryConfig.Filter.DataColumnId);
|
||||
_logger.LogWarning(
|
||||
"Attempted to {method} for data source {dataSourceId} with the following data column ids {dataColumnIds}",
|
||||
nameof(GetColumnValues),
|
||||
dataSourceId,
|
||||
dataColumnIds);
|
||||
return Forbid();
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPost("{dataSourceId}/query")]
|
||||
[Authorize(Policy = Policies.DataSourceViewer)]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status403Forbidden)]
|
||||
[ProducesDefaultResponseType]
|
||||
public async Task<ActionResult<IEnumerable<dynamic>>> QueryData([FromRoute] int dataSourceId, [FromBody] QueryConfig query, CancellationToken cancellationToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Ok(await _dataQueryService.QueryData(query, cancellationToken));
|
||||
}
|
||||
catch (UnauthorizedAccessException)
|
||||
{
|
||||
_logger.LogWarning(
|
||||
"Attempted to {method} for data source {dataSourceId} with the following data column ids {dataColumnIds}",
|
||||
nameof(QueryData),
|
||||
dataSourceId,
|
||||
query.GetAllColumnIds());
|
||||
return Forbid();
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPost("query")]
|
||||
[Authorize(Policy = Policies.StrataOnly)]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status403Forbidden)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
[ProducesDefaultResponseType]
|
||||
public async Task<ActionResult<SqlResponse>> GetSqlQuery(QueryConfig queryConfig, CancellationToken cancellationToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Ok(await _dataQueryService.BuildSqlQuery(queryConfig, cancellationToken));
|
||||
}
|
||||
catch (UnauthorizedAccessException)
|
||||
{
|
||||
_logger.LogWarning(
|
||||
"Attempted to {method} with the following data column ids {dataColumnIds}",
|
||||
nameof(GetSqlQuery),
|
||||
queryConfig.GetAllColumnIds());
|
||||
return Forbid();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[HttpPost("{dataSourceId}/download")]
|
||||
[Authorize(Policy = Policies.DataSourceViewer)]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status403Forbidden)]
|
||||
[ProducesDefaultResponseType]
|
||||
public async Task<ActionResult> DownloadDataSheet([FromRoute] int dataSourceId, [FromBody] ExportDataSheetRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var stream = await _exportService.DownloadDataSheet(request, cancellationToken);
|
||||
return File(stream, "application/octet-stream");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Collections.Generic;
|
||||
using Strata.Analytics.Biz.Database;
|
||||
|
||||
namespace Strata.Analytics.Api.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
[ApiVersion("1.0")]
|
||||
[Route("api/v{api-version:apiVersion}/[controller]")]
|
||||
public class DatabasesController : ControllerBase
|
||||
{
|
||||
private readonly IDatabaseService _databaseService;
|
||||
|
||||
public DatabasesController(IDatabaseService databaseService)
|
||||
{
|
||||
_databaseService = databaseService;
|
||||
}
|
||||
|
||||
[HttpGet("")]
|
||||
public async Task<IEnumerable<Database>> GetDatabases(CancellationToken cancellationToken)
|
||||
{
|
||||
return await _databaseService.GetDatabasesAsync(cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Strata.Analytics.Biz.Encounters;
|
||||
using Strata.Analytics.Api.Models;
|
||||
|
||||
namespace Strata.Analytics.Api.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
[ApiVersion("1.0")]
|
||||
[Route("api/v{api-version:apiVersion}/[controller]")]
|
||||
public class EncountersController : ControllerBase
|
||||
{
|
||||
private readonly IEncounterService _encounterService;
|
||||
|
||||
public EncountersController(IEncounterService encounterService)
|
||||
{
|
||||
_encounterService = encounterService;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Given an encounter record number, return the encounter id
|
||||
/// </summary>
|
||||
[HttpPost("encounter-id")]
|
||||
public async Task<int> GetEncounterId([FromBody] EncounterInfo encounterInfo, CancellationToken cancellationToken)
|
||||
{
|
||||
// Needs to be POST to prevent PHI data in url string
|
||||
return await _encounterService.GetEncounterIdAsync(encounterInfo.EncounterRecordNumber, cancellationToken);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,236 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Strata.Analytics.Biz.Extracts.Models;
|
||||
using Strata.Analytics.Biz.Extracts.Services;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Hangfire;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Strata.Analytics.Api.Authorization;
|
||||
using Strata.Analytics.Models.Utils;
|
||||
using System;
|
||||
using Strata.Analytics.Biz.Extracts.Jobs;
|
||||
using System.Security.Claims;
|
||||
using Hangfire.States;
|
||||
using Strata.CoreLib.Claims;
|
||||
using Strata.CoreLib.Claims.Extensions;
|
||||
|
||||
namespace Strata.Analytics.Api.Controllers
|
||||
{
|
||||
[Authorize(Policy = Policies.IsAdmin)]
|
||||
[ApiController]
|
||||
[ApiVersion("1.0")]
|
||||
[Route("api/v{api-version:apiVersion}/[controller]")]
|
||||
public class ExtractsController : ControllerBase
|
||||
{
|
||||
private readonly IExtractService _extractService;
|
||||
private readonly IBackgroundJobClient _backgroundJobClient;
|
||||
private readonly IExtractExportHistoryService _historyService;
|
||||
private readonly IExtractScheduleService _extractScheduleService;
|
||||
private readonly ClaimsPrincipal _user;
|
||||
|
||||
public ExtractsController(IExtractService extractService, IBackgroundJobClient backgroundJobClient, IExtractExportHistoryService historyService, IExtractScheduleService extractScheduleService, IClaimsPrincipalAccessor claimsPrincipalAccessor)
|
||||
{
|
||||
_extractService = extractService;
|
||||
_backgroundJobClient = backgroundJobClient;
|
||||
_historyService = historyService;
|
||||
_extractScheduleService = extractScheduleService;
|
||||
_user = claimsPrincipalAccessor.GetCurrentClaimsPrincipal();
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public async Task<IEnumerable<Extract>> GetExtractsAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
return await _extractService.GetAllAsync(cancellationToken);
|
||||
}
|
||||
|
||||
[HttpGet("{extractId}")]
|
||||
[Authorize(Policy = Policies.ExtractViewer)]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
[ProducesDefaultResponseType]
|
||||
public async Task<ActionResult<Extract>> GetExtractById(int extractId, CancellationToken cancellationToken)
|
||||
{
|
||||
|
||||
var extract = await _extractService.GetByIdAsync(extractId, cancellationToken);
|
||||
if (extract == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
return Ok(extract);
|
||||
}
|
||||
|
||||
[HttpDelete("{extractId}")]
|
||||
[Authorize(Policy = Policies.CustomSqlAccess)]
|
||||
[Authorize(Policy = Policies.ExtractEditor)]
|
||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
[ProducesDefaultResponseType]
|
||||
public async Task<IActionResult> DeleteExtract(int extractId, CancellationToken cancellationToken)
|
||||
{
|
||||
if (!await _extractService.ContainsAsync(extractId, cancellationToken))
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
await _extractScheduleService.DeleteByExtractIdAsync(extractId, cancellationToken);
|
||||
await _extractService.DeleteAsync(extractId, cancellationToken);
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public async Task<ActionResult<Extract>> CreateExtract(ExtractCreateInfo extractCreateInfo, CancellationToken cancellationToken)
|
||||
{
|
||||
return await _extractService.CreateAsync(extractCreateInfo, cancellationToken);
|
||||
}
|
||||
|
||||
[HttpPut("{extractId}")]
|
||||
[Authorize(Policy = Policies.CustomSqlAccess)]
|
||||
[Authorize(Policy = Policies.ExtractEditor)]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
[ProducesDefaultResponseType]
|
||||
public async Task<ActionResult<Extract>> UpdateExtract([FromRoute] int extractId, [FromBody] ExtractSaveInfo extractSaveInfo, CancellationToken cancellationToken)
|
||||
{
|
||||
if (!await _extractService.ContainsAsync(extractId, cancellationToken))
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
return Ok(await _extractService.UpdateAsync(extractId, extractSaveInfo, cancellationToken));
|
||||
}
|
||||
|
||||
|
||||
[HttpPost("export/{extractId}")]
|
||||
[ProducesResponseType(StatusCodes.Status202Accepted)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
|
||||
[ProducesDefaultResponseType]
|
||||
[Authorize(Policy = Policies.ExtractEditor)]
|
||||
public async Task<IActionResult> ExportExtract(int extractId, [FromBody] ExtractExportRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
if (!await _extractService.ContainsAsync(request.ExtractId, cancellationToken))
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
request.Timezone = _user.GetTimezone();
|
||||
|
||||
var jobId = _backgroundJobClient.Enqueue<IExtractExportJob>(job =>
|
||||
job.ExecuteExport(request.OutputFileName, _user.GetDatabaseGuid(), _user.GetStrataId(), _user.GetUserGuid(), request, null, cancellationToken));
|
||||
|
||||
return Accepted(new { jobId });
|
||||
}
|
||||
|
||||
[HttpDelete("{extractId}/history/{extractHistoryId}/cancel/")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
|
||||
[ProducesDefaultResponseType]
|
||||
[Authorize(Policy = Policies.ExtractEditor)]
|
||||
public async Task<ActionResult<ExtractExportHistory>> CancelExportExtract([FromRoute] int extractId, [FromRoute] int extractHistoryId, CancellationToken cancellationToken)
|
||||
{
|
||||
var history = await _historyService.CancelExtractExport(extractHistoryId, cancellationToken);
|
||||
|
||||
if (history == null) return NotFound();
|
||||
|
||||
_backgroundJobClient.ChangeState(history.JobId, new DeletedState {Reason = "Job cancelled manually" });
|
||||
|
||||
return Ok(history);
|
||||
}
|
||||
|
||||
[HttpGet("history/{extractId}")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
[ProducesDefaultResponseType]
|
||||
[Authorize(Policy = Policies.ExtractViewer)]
|
||||
public async Task<ActionResult<List<ExtractExportHistory>>> GetHistoryById(int extractId, CancellationToken cancellationToken)
|
||||
{
|
||||
if (!await _extractService.ContainsAsync(extractId, cancellationToken))
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
return Ok(await _historyService.GetByExtractIdAsync(extractId, cancellationToken));
|
||||
}
|
||||
|
||||
[HttpGet("{extractId}/role-assignments")]
|
||||
[Authorize(Policy = Policies.ExtractViewer)]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status403Forbidden)]
|
||||
[ProducesDefaultResponseType]
|
||||
public async Task<ActionResult<IEnumerable<ExtractRoleAssignment>>> GetRoleAssignments([FromRoute] int extractId, CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await _extractService.GetRoleAssignmentsAsync(extractId, cancellationToken));
|
||||
}
|
||||
|
||||
[HttpPost("{extractId}/role-assignments/batch")]
|
||||
[Authorize(Policy = Policies.ExtractEditor)]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status403Forbidden)]
|
||||
[ProducesDefaultResponseType]
|
||||
public async Task<ActionResult<IEnumerable<ExtractRoleAssignment>>> SaveRoleAssignments(
|
||||
[FromRoute] int extractId, [FromBody] Batch<ExtractRoleAssignmentSaveInfo, Guid> roleAssignments, CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await _extractService.SaveRoleAssignmentsAsync(extractId, roleAssignments, cancellationToken));
|
||||
}
|
||||
|
||||
[HttpPost("{extractId}/schedule")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
[ProducesDefaultResponseType]
|
||||
[Authorize(Policy = Policies.ExtractEditor)]
|
||||
public async Task<ActionResult<ExtractSchedule>> CreateExtractSchedule([FromRoute] int extractId, [FromBody] ExtractScheduleSaveInfo saveInfo, CancellationToken cancellationToken)
|
||||
{
|
||||
if (!await _extractService.ContainsAsync(extractId, cancellationToken))
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
return Ok(await _extractScheduleService.CreateAsync(saveInfo, cancellationToken));
|
||||
}
|
||||
|
||||
[HttpPut("{extractId}/schedule/{extractScheduleId}")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
[ProducesDefaultResponseType]
|
||||
[Authorize(Policy = Policies.ExtractEditor)]
|
||||
public async Task<ActionResult<ExtractSchedule>> UpdateExtractSchedule([FromRoute] int extractId, [FromRoute] int extractScheduleId, [FromBody] ExtractScheduleSaveInfo saveInfo, CancellationToken cancellationToken)
|
||||
{
|
||||
if (!await _extractScheduleService.ContainsAsync(extractScheduleId, cancellationToken))
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
return Ok(await _extractScheduleService.UpdateAsync(extractScheduleId, saveInfo, cancellationToken));
|
||||
}
|
||||
|
||||
[HttpGet("{extractId}/schedule")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesDefaultResponseType]
|
||||
[Authorize(Policy = Policies.ExtractEditor)]
|
||||
public async Task<ActionResult<ExtractSchedule>> GetScheduleByExtractId([FromRoute] int extractId, CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await _extractScheduleService.GetByExtractIdAsync(extractId, cancellationToken));
|
||||
}
|
||||
|
||||
[HttpDelete("{extractId}/schedule/{extractScheduleId}")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
[ProducesDefaultResponseType]
|
||||
[Authorize(Policy = Policies.ExtractEditor)]
|
||||
public async Task<ActionResult> DeleteExtractSchedule([FromRoute] int extractId, [FromRoute] int extractScheduleId, CancellationToken cancellationToken)
|
||||
{
|
||||
if (!await _extractScheduleService.ContainsAsync(extractScheduleId, cancellationToken))
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
await _extractScheduleService.DeleteAsync(extractScheduleId, cancellationToken);
|
||||
|
||||
return Ok();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Threading.Tasks;
|
||||
using Strata.FeatureFlags.Client;
|
||||
using System.Security.Claims;
|
||||
using Strata.CoreLib.Claims;
|
||||
using Strata.CoreLib.Claims.Extensions;
|
||||
|
||||
namespace Strata.Analytics.Api.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
[ApiVersion("1.0")]
|
||||
[Route("api/v{api-version:apiVersion}/[controller]")]
|
||||
public class FeatureController : ControllerBase
|
||||
{
|
||||
private readonly IFeatureFlagServiceClient _featureFlagService;
|
||||
private readonly ClaimsPrincipal _user;
|
||||
|
||||
public FeatureController(IFeatureFlagServiceClient featureFlagService, IClaimsPrincipalAccessor claimsPrincipalAccessor)
|
||||
{
|
||||
_featureFlagService = featureFlagService;
|
||||
_user = claimsPrincipalAccessor.GetCurrentClaimsPrincipal();
|
||||
}
|
||||
|
||||
[HttpGet("dashboards-enabled")]
|
||||
public async Task<bool> IsDashboardsEnabled()
|
||||
{
|
||||
return await _featureFlagService.IsEnabledAsync("analytics-dashboards", _user.GetDatabaseGuid());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Strata.Analytics.Biz.Workbooks.Services;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Strata.Analytics.Models.Workbooks;
|
||||
|
||||
namespace Strata.Analytics.Api.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
[ApiVersion("1.0")]
|
||||
[Route("api/v{api-version:apiVersion}/[controller]")]
|
||||
public class SavedFiltersController : ControllerBase
|
||||
{
|
||||
private readonly ISavedFilterService _savedFilterService;
|
||||
|
||||
public SavedFiltersController(ISavedFilterService savedFiltersService)
|
||||
{
|
||||
_savedFilterService = savedFiltersService;
|
||||
}
|
||||
|
||||
[HttpGet("{savedFilterId}")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
[ProducesDefaultResponseType]
|
||||
public async Task<ActionResult<SavedFilterInfo>> GetSavedFiltersAsync(int savedFilterId, CancellationToken cancellationToken)
|
||||
{
|
||||
var savedFilters = await _savedFilterService.GetSavedFiltersAsync(savedFilterId, cancellationToken);
|
||||
if (savedFilters == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
return Ok(savedFilters);
|
||||
}
|
||||
|
||||
[HttpDelete("{savedFilterId}")]
|
||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
[ProducesDefaultResponseType]
|
||||
public async Task<IActionResult> Delete(int savedFilterId, CancellationToken cancellationToken)
|
||||
{
|
||||
await _savedFilterService.DeleteSavedFiltersAsync(savedFilterId, cancellationToken);
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public async Task<ActionResult<int>> Create(SavedFilterInfo savedFilters, CancellationToken cancellationToken)
|
||||
{
|
||||
var cache = await _savedFilterService.CreateSavedFiltersAsync(savedFilters, cancellationToken);
|
||||
|
||||
return cache.SavedFilterId;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,279 @@
|
||||
using Hangfire;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Strata.Analytics.Api.Authorization;
|
||||
using Strata.Analytics.Api.Models;
|
||||
using Strata.Analytics.Biz.Database;
|
||||
using Strata.Analytics.Biz.DataQuery;
|
||||
using Strata.Analytics.Biz.DataSources.Models;
|
||||
using Strata.Analytics.Biz.Schema;
|
||||
using Strata.Analytics.Biz.Schema.Jobs;
|
||||
using Strata.Analytics.Biz.StandardDataSources.Jobs;
|
||||
using Strata.Analytics.Biz.StandardDataSources.Models;
|
||||
using Strata.Analytics.Biz.StandardDataSources.Services;
|
||||
using Strata.Analytics.Models;
|
||||
using Strata.Analytics.Models.Utils;
|
||||
using Strata.CoreLib.Claims.Extensions;
|
||||
using Strata.DataSchema.Models.Query;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Strata.Analytics.Api.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
[ApiVersion("1.0")]
|
||||
[Route("api/v{api-version:apiVersion}/[controller]")]
|
||||
public class StandardDataSourcesController : ControllerBase
|
||||
{
|
||||
private readonly IStandardDataSourceService _standardDataSourceService;
|
||||
private readonly IDataQueryService _dataQueryService;
|
||||
private readonly IDatabaseService _databaseService;
|
||||
private readonly IStandardDataSourcePublishService _standardDataSourcePublishService;
|
||||
private readonly IBackgroundJobClient _backgroundJobClient;
|
||||
private readonly IPublishStandardDataSourcesJob _publishStandardDataSourcesJob;
|
||||
private readonly ILogger<StandardDataSourcesController> _logger;
|
||||
|
||||
public StandardDataSourcesController(
|
||||
IStandardDataSourceService standardDataSourceService,
|
||||
IDataQueryService dataQueryService,
|
||||
IDatabaseService databaseService,
|
||||
IStandardDataSourcePublishService standardDataSourcePublishService,
|
||||
IBackgroundJobClient backgroundJobClient,
|
||||
IPublishStandardDataSourcesJob publishStandardDataSourcesJob,
|
||||
ILogger<StandardDataSourcesController> logger)
|
||||
{
|
||||
_standardDataSourceService = standardDataSourceService;
|
||||
_dataQueryService = dataQueryService;
|
||||
_databaseService = databaseService;
|
||||
_standardDataSourcePublishService = standardDataSourcePublishService;
|
||||
_backgroundJobClient = backgroundJobClient;
|
||||
_publishStandardDataSourcesJob = publishStandardDataSourcesJob;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public async Task<IEnumerable<StandardDataSource>> GetDataSourcesAsync(bool includeTableLinks = false, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return await _standardDataSourceService.GetAllAsync(includeTableLinks, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
[HttpGet("{standardDataSourceId}")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
[ProducesDefaultResponseType]
|
||||
public async Task<ActionResult<StandardDataSource>> GetById(int standardDataSourceId, CancellationToken cancellationToken)
|
||||
{
|
||||
var standardDataSource = await _standardDataSourceService.GetByIdAsync(standardDataSourceId, cancellationToken);
|
||||
if (standardDataSource == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
return Ok(standardDataSource);
|
||||
}
|
||||
|
||||
[HttpPut("")]
|
||||
[Authorize(Policy = Policies.StrataOnly)]
|
||||
[Authorize(Policy = Policies.AuthorizedDbOnly)]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status403Forbidden)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
[ProducesDefaultResponseType]
|
||||
public async Task<ActionResult<StandardDataSource>> Save(StandardDataSourceSaveInfo standardDataSourceSaveInfo, CancellationToken cancellationToken)
|
||||
{
|
||||
var isFound = await _standardDataSourceService.ContainsAsync(standardDataSourceSaveInfo.StandardDataSourceId, cancellationToken);
|
||||
if (!isFound)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
var updatedDataSource = await _standardDataSourceService.SaveAsync(standardDataSourceSaveInfo, cancellationToken);
|
||||
|
||||
return Ok(updatedDataSource);
|
||||
}
|
||||
|
||||
[HttpDelete("{standardDataSourceId}")]
|
||||
[Authorize(Policy = Policies.StrataOnly)]
|
||||
[Authorize(Policy = Policies.AuthorizedDbOnly)]
|
||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||
[ProducesResponseType(StatusCodes.Status403Forbidden)]
|
||||
[ProducesDefaultResponseType]
|
||||
public async Task<IActionResult> Delete(int standardDataSourceId, CancellationToken cancellationToken)
|
||||
{
|
||||
await _standardDataSourceService.DeleteAsync(standardDataSourceId, cancellationToken);
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
[HttpPost("")]
|
||||
[Authorize(Policy = Policies.StrataOnly)]
|
||||
[Authorize(Policy = Policies.AuthorizedDbOnly)]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status403Forbidden)]
|
||||
public async Task<ActionResult<StandardDataSource>> Create(StandardDataSourceSaveInfo standardDataSourceSaveInfo, CancellationToken cancellationToken)
|
||||
{
|
||||
return await _standardDataSourceService.CreateAsync(standardDataSourceSaveInfo, cancellationToken);
|
||||
}
|
||||
|
||||
[HttpGet("{standardDataSourceId}/role-assignments")]
|
||||
[Authorize(Policy = Policies.StrataOnly)]
|
||||
[Authorize(Policy = Policies.AuthorizedDbOnly)]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status403Forbidden)]
|
||||
[ProducesDefaultResponseType]
|
||||
public async Task<ActionResult<IEnumerable<StandardDataSourceRoleAssignment>>> GetRoleAssignments([FromRoute] int standardDataSourceId, CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await _standardDataSourceService.GetRoleAssignmentsAsync(new List<int> { standardDataSourceId }, cancellationToken));
|
||||
}
|
||||
|
||||
[HttpPost("{standardDataSourceId}/role-assignments/batch")]
|
||||
[Authorize(Policy = Policies.StrataOnly)]
|
||||
[Authorize(Policy = Policies.AuthorizedDbOnly)]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status403Forbidden)]
|
||||
[ProducesDefaultResponseType]
|
||||
public async Task<ActionResult<IEnumerable<DataSourceRoleAssignment>>> SaveRoleAssignments([FromRoute] int standardDataSourceId, [FromBody] Batch<StandardDataSourceRoleAssignmentSaveInfo, Guid> roleAssignments, CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await _standardDataSourceService.SaveRoleAssignmentsAsync(standardDataSourceId, roleAssignments, cancellationToken));
|
||||
}
|
||||
|
||||
[HttpPost("{standardDataSourceId}/datacolumn/values")]
|
||||
[Authorize(Policy = Policies.StrataOnly)]
|
||||
[Authorize(Policy = Policies.AuthorizedDbOnly)]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||
[ProducesResponseType(StatusCodes.Status403Forbidden)]
|
||||
[ProducesDefaultResponseType]
|
||||
public async Task<ActionResult<IEnumerable<dynamic>>> GetColumnValues([FromRoute] int standardDataSourceId, [FromBody] ColumnQueryConfig columnQueryConfig, CancellationToken cancellationToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Ok(await _dataQueryService.GetColumnValues(columnQueryConfig, cancellationToken));
|
||||
}
|
||||
catch (UnauthorizedAccessException)
|
||||
{
|
||||
var dataColumnIds = new List<int> { columnQueryConfig.DataColumnId };
|
||||
if (columnQueryConfig.Filter != null)
|
||||
dataColumnIds.Add(columnQueryConfig.Filter.DataColumnId);
|
||||
_logger.LogWarning(
|
||||
"Attempted to {method} for standard data source {standardDataSourceId} with the following data column ids {dataColumnIds}",
|
||||
nameof(GetColumnValues),
|
||||
standardDataSourceId,
|
||||
dataColumnIds);
|
||||
return Forbid();
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPost("{standardDataSourceId}/query")]
|
||||
[Authorize(Policy = Policies.StrataOnly)]
|
||||
[Authorize(Policy = Policies.AuthorizedDbOnly)]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status403Forbidden)]
|
||||
[ProducesDefaultResponseType]
|
||||
public async Task<ActionResult<IEnumerable<dynamic>>> QueryData([FromRoute] int standardDataSourceId, [FromBody] QueryConfig query, CancellationToken cancellationToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Ok(await _dataQueryService.QueryData(query, cancellationToken));
|
||||
}
|
||||
catch (UnauthorizedAccessException)
|
||||
{
|
||||
_logger.LogWarning(
|
||||
"Attempted to {method} for standard data source {standardDataSourceId} with the following data column ids {dataColumnsIds}",
|
||||
nameof(QueryData),
|
||||
standardDataSourceId,
|
||||
query.GetAllColumnIds());
|
||||
return Forbid();
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPost("query")]
|
||||
[Authorize(Policy = Policies.StrataOnly)]
|
||||
[Authorize(Policy = Policies.AuthorizedDbOnly)]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status403Forbidden)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
[ProducesDefaultResponseType]
|
||||
public async Task<ActionResult<SqlResponse>> GetSqlQuery(QueryConfig queryConfig, CancellationToken cancellationToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Ok(await _dataQueryService.BuildSqlQuery(queryConfig, cancellationToken));
|
||||
}
|
||||
catch (UnauthorizedAccessException)
|
||||
{
|
||||
_logger.LogWarning(
|
||||
"Attempted to {method} with the following data column ids {dataColumnIds}",
|
||||
nameof(GetSqlQuery),
|
||||
queryConfig.GetAllColumnIds());
|
||||
return Forbid();
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPost("{standardDataSourceId}/include-in-publish")]
|
||||
[Authorize(Policy = Policies.StrataOnly)]
|
||||
[Authorize(Policy = Policies.AuthorizedDbOnly)]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
[ProducesDefaultResponseType]
|
||||
public async Task<ActionResult<StandardDataSource>> IncludeDataSourceInPublish([FromRoute] int standardDataSourceId, CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await _standardDataSourceService.SetIsIncludedInStandardModel(standardDataSourceId, true, cancellationToken));
|
||||
|
||||
}
|
||||
|
||||
[HttpPost("{standardDataSourceId}/exclude-from-publish")]
|
||||
[Authorize(Policy = Policies.StrataOnly)]
|
||||
[Authorize(Policy = Policies.AuthorizedDbOnly)]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
[ProducesDefaultResponseType]
|
||||
public async Task<ActionResult<StandardDataSource>> ExcludeDataSourceInPublish([FromRoute] int standardDataSourceId, CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await _standardDataSourceService.SetIsIncludedInStandardModel(standardDataSourceId, false, cancellationToken));
|
||||
|
||||
}
|
||||
|
||||
[HttpPost("publish")]
|
||||
[Authorize(Policy = Policies.AuthorizedDbOnly)]
|
||||
public async Task<string> PublishAsync([FromBody] PublishConfig publishConfig, CancellationToken cancellationToken)
|
||||
{
|
||||
if (publishConfig.StrataId == 0)
|
||||
{
|
||||
var databases = await _databaseService.GetDatabasesAsync(cancellationToken);
|
||||
return _backgroundJobClient.Enqueue<PublishStandardDataSourcesAllClientsJob>(job => job.ExecuteAsync(databases.ToList(), User.GetUsername(), DateTime.UtcNow, CancellationToken.None));
|
||||
}
|
||||
|
||||
if (Debugger.IsAttached && publishConfig.StrataId == User.GetStrataId())
|
||||
{
|
||||
await _publishStandardDataSourcesJob.ExecuteAsync(User.GetDatabaseGuid(), User.GetStrataId(), Guid.NewGuid().ToString(), User.GetUsername(), DateTime.UtcNow, cancellationToken);
|
||||
return "";
|
||||
}
|
||||
var database = await _databaseService.GetDatabaseByStrataId(publishConfig.StrataId, cancellationToken);
|
||||
var parentJobId = _backgroundJobClient.Enqueue<PublishStandardDataSourcesJob>(job => job.ExecuteAsync(database.DatabaseGuid, database.StrataId, Guid.NewGuid().ToString(), User.GetUsername(), DateTime.UtcNow, CancellationToken.None));
|
||||
|
||||
return parentJobId;
|
||||
}
|
||||
|
||||
[HttpGet("publish-history")]
|
||||
public async Task<ActionResult<IEnumerable<PublicationEvent>>> GetPublicationHistory(CancellationToken cancellationToken)
|
||||
{
|
||||
var publications = await _standardDataSourcePublishService.GetPublicationsAsync(cancellationToken);
|
||||
|
||||
return Ok(publications
|
||||
.GroupBy(x => x.RequestCorrelationId)
|
||||
.Select(x => new PublicationEvent
|
||||
{
|
||||
RequestDate = x.FirstOrDefault().RequestDate,
|
||||
RequestedBy = x.FirstOrDefault().RequestedBy,
|
||||
StandardDataSourceIds = x.Select(y => y.StandardDataSourceId).Distinct(),
|
||||
StrataIds = x.Select(y => y.ClientId).Distinct()
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Strata.Users.Client;
|
||||
using Strata.Users.Client.UserGroups.Models;
|
||||
using System.Linq;
|
||||
|
||||
namespace Strata.Analytics.Api.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
[ApiVersion("1.0")]
|
||||
[Route("api/v{api-version:apiVersion}/[controller]")]
|
||||
public class UserGroupsController : ControllerBase
|
||||
{
|
||||
private readonly IUsersServiceClient _usersService;
|
||||
|
||||
public UserGroupsController(IUsersServiceClient usersService)
|
||||
{
|
||||
_usersService = usersService;
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public async Task<IEnumerable<UserGroup>> GetUserGroups(CancellationToken cancellationToken)
|
||||
{
|
||||
var userGroups = await _usersService.GetAllUserGroupsAsync(cancellationToken);
|
||||
return userGroups.Where(ug => !ug.IsHidden);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Strata.Users.Client;
|
||||
using Strata.Users.Client.Users.Models;
|
||||
|
||||
namespace Strata.Analytics.Api.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
[ApiVersion("1.0")]
|
||||
[Route("api/v{api-version:apiVersion}/[controller]")]
|
||||
public class UsersController : ControllerBase
|
||||
{
|
||||
private readonly IUsersServiceClient _usersService;
|
||||
|
||||
public UsersController(IUsersServiceClient usersService)
|
||||
{
|
||||
_usersService = usersService;
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public async Task<IEnumerable<User>> GetUsers(CancellationToken cancellationToken)
|
||||
{
|
||||
return await _usersService.GetAllUsersAsync(cancellationToken);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Strata.Analytics.Biz.Workbooks.Services;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Strata.Analytics.Api.Authorization;
|
||||
using Strata.Analytics.Models.Utils;
|
||||
using System;
|
||||
using Strata.Analytics.Models.Workbooks;
|
||||
|
||||
namespace Strata.Analytics.Api.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
[ApiVersion("1.0")]
|
||||
[Route("api/v{api-version:apiVersion}/[controller]")]
|
||||
public class WorkbooksController : ControllerBase
|
||||
{
|
||||
private readonly IWorkbookService _workbookService;
|
||||
|
||||
public WorkbooksController(IWorkbookService workbookService)
|
||||
{
|
||||
_workbookService = workbookService;
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public async Task<IEnumerable<Workbook>> GetWorkbooksAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
|
||||
return await _workbookService.GetAllAsync(cancellationToken);
|
||||
}
|
||||
|
||||
[HttpGet("{workbookId}")]
|
||||
[Authorize(Policy = Policies.WorkbookViewer)]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
[ProducesDefaultResponseType]
|
||||
public async Task<ActionResult<Workbook>> GetById(int workbookId, CancellationToken cancellationToken)
|
||||
{
|
||||
|
||||
var workbook = await _workbookService.GetByIdAsync(workbookId, cancellationToken);
|
||||
if (workbook == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
return Ok(workbook);
|
||||
}
|
||||
|
||||
// Delete should return 404 if id doesn't exist. Use Contains instead of loading entire object into memory to check for existence.
|
||||
[HttpDelete("{workbookId}")]
|
||||
[Authorize(Policy = Policies.WorkbookEditor)]
|
||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
[ProducesDefaultResponseType]
|
||||
public async Task<IActionResult> Delete(int workbookId, CancellationToken cancellationToken)
|
||||
{
|
||||
if (!await _workbookService.ContainsAsync(workbookId, cancellationToken))
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
await _workbookService.DeleteAsync(workbookId, cancellationToken);
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public async Task<ActionResult<Workbook>> Create(WorkbookCreateInfo workbookCreateInfo, CancellationToken cancellationToken)
|
||||
{
|
||||
return await _workbookService.CreateAsync(workbookCreateInfo, cancellationToken);
|
||||
}
|
||||
|
||||
[HttpPut("{workbookId}")]
|
||||
[Authorize(Policy = Policies.WorkbookEditor)]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
[ProducesDefaultResponseType]
|
||||
public async Task<ActionResult<Workbook>> UpdateWorkbook([FromRoute] int workbookId, [FromBody] WorkbookSaveInfo workbookSaveInfo, CancellationToken cancellationToken)
|
||||
{
|
||||
if (!await _workbookService.ContainsAsync(workbookId, cancellationToken))
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
return await _workbookService.UpdateAsync(workbookId, workbookSaveInfo, cancellationToken);
|
||||
}
|
||||
|
||||
|
||||
[HttpGet("{workbookId}/role-assignments")]
|
||||
[Authorize(Policy = "WorkbookViewer")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status403Forbidden)]
|
||||
[ProducesDefaultResponseType]
|
||||
public async Task<ActionResult<IEnumerable<WorkbookRoleAssignment>>> GetRoleAssignments([FromRoute] int workbookId, CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await _workbookService.GetRoleAssignmentsAsync(workbookId, cancellationToken));
|
||||
}
|
||||
|
||||
[HttpPost("{workbookId}/role-assignments/batch")]
|
||||
[Authorize(Policy = Policies.WorkbookEditor)]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status403Forbidden)]
|
||||
[ProducesDefaultResponseType]
|
||||
public async Task<ActionResult<IEnumerable<WorkbookRoleAssignment>>> SaveRoleAssignments([FromRoute] int workbookId, [FromBody] Batch<WorkbookRoleAssignmentSaveInfo, Guid> roleAssignments, CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await _workbookService.SaveRoleAssignmentsAsync(workbookId, roleAssignments, cancellationToken));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user