241 lines
11 KiB
C#
241 lines
11 KiB
C#
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");
|
|
}
|
|
}
|
|
} |