Add UserSettingsController

This commit is contained in:
ngfrolov 2022-07-27 18:14:07 +05:00
parent ed364112cb
commit b7af07f995
11 changed files with 12564 additions and 2 deletions

View File

@ -0,0 +1,15 @@
using System.Threading;
using System.Threading.Tasks;
namespace AsbCloudApp.Services
{
public interface IUserSettingsRepository
{
public const int ErrorKeyNotFound = -1;
public const int ErrorKeyIsUsed = -2;
Task<object> GetOrDefaultAsync(int userId, string key, CancellationToken token);
Task<int> InsertAsync(int userId, string key, object value, CancellationToken token);
Task<int> UpdateAsync(int userId, string key, object value, CancellationToken token);
Task<int> DeleteAsync(int userId, string key, CancellationToken token);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,38 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace AsbCloudDb.Migrations
{
public partial class Add_user_settings : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "t_user_settings",
columns: table => new
{
idUser = table.Column<int>(type: "integer", nullable: false),
key = table.Column<string>(type: "text", nullable: false, comment: "Ключ настроек пользователя"),
setting_value = table.Column<object>(type: "jsonb", nullable: true, comment: "Значение настроек пользователя")
},
constraints: table =>
{
table.PrimaryKey("PK_t_user_settings", x => new { x.idUser, x.key });
table.ForeignKey(
name: "FK_t_user_settings_t_user_idUser",
column: x => x.idUser,
principalTable: "t_user",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
},
comment: "настройки интерфейса пользователя");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "t_user_settings");
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,37 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace AsbCloudDb.Migrations
{
public partial class Add_user_settings_key_size_limit : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<string>(
name: "key",
table: "t_user_settings",
type: "character varying(255)",
maxLength: 255,
nullable: false,
comment: "Ключ настроек пользователя",
oldClrType: typeof(string),
oldType: "text",
oldComment: "Ключ настроек пользователя");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<string>(
name: "key",
table: "t_user_settings",
type: "text",
nullable: false,
comment: "Ключ настроек пользователя",
oldClrType: typeof(string),
oldType: "character varying(255)",
oldMaxLength: 255,
oldComment: "Ключ настроек пользователя");
}
}
}

View File

@ -3872,6 +3872,30 @@ namespace AsbCloudDb.Migrations
});
});
modelBuilder.Entity("AsbCloudDb.Model.UserSetting", b =>
{
b.Property<int>("IdUser")
.HasColumnType("integer")
.HasColumnName("idUser");
b.Property<string>("Key")
.HasMaxLength(255)
.HasColumnType("character varying(255)")
.HasColumnName("key")
.HasComment("Ключ настроек пользователя");
b.Property<object>("Value")
.HasColumnType("jsonb")
.HasColumnName("setting_value")
.HasComment("Значение настроек пользователя");
b.HasKey("IdUser", "Key");
b.ToTable("t_user_settings");
b.HasComment("настройки интерфейса пользователя");
});
modelBuilder.Entity("AsbCloudDb.Model.Well", b =>
{
b.Property<int>("Id")
@ -5810,6 +5834,17 @@ namespace AsbCloudDb.Migrations
b.Navigation("Company");
});
modelBuilder.Entity("AsbCloudDb.Model.UserSetting", b =>
{
b.HasOne("AsbCloudDb.Model.User", "User")
.WithMany()
.HasForeignKey("IdUser")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("AsbCloudDb.Model.Well", b =>
{
b.HasOne("AsbCloudDb.Model.Cluster", "Cluster")

View File

@ -38,6 +38,7 @@ namespace AsbCloudDb.Model
public virtual DbSet<TelemetryUser> TelemetryUsers => Set<TelemetryUser>();
public virtual DbSet<User> Users => Set<User>();
public virtual DbSet<UserRole> UserRoles => Set<UserRole>();
public virtual DbSet<UserSetting> UserSettings => Set<UserSetting>();
public virtual DbSet<Well> Wells => Set<Well>();
public virtual DbSet<WellComposite> WellComposites => Set<WellComposite>();
public virtual DbSet<WellOperation> WellOperations => Set<WellOperation>();
@ -837,6 +838,10 @@ namespace AsbCloudDb.Model
});
});
modelBuilder.Entity<UserSetting>(entity =>
{
entity.HasKey(nameof(UserSetting.IdUser), nameof(UserSetting.Key));
});
}
public Task<int> RefreshMaterializedViewAsync<TEntity>(string? mwName = null, CancellationToken token = default) where TEntity : class

View File

@ -0,0 +1,24 @@
using Microsoft.EntityFrameworkCore;
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace AsbCloudDb.Model
{
[Table("t_user_settings"), Comment("настройки интерфейса пользователя")]
public class UserSetting
{
[Column("idUser")]
public int IdUser { get; set; }
[Column("key"), Comment("Ключ настроек пользователя"), StringLength(255)]
public string Key { get; set; } = null!;
[Column("setting_value", TypeName = "jsonb"), Comment("Значение настроек пользователя")]
public object? Value { get; set; }
[ForeignKey(nameof(IdUser))]
public User User { get; set; } = null!;
}
}

View File

@ -67,8 +67,6 @@ namespace AsbCloudInfrastructure
.ForType<ClusterDto, Cluster>()
.Ignore(dst => dst.Deposit,
dst => dst.Wells);
}
public static IServiceCollection AddInfrastructure(this IServiceCollection services, IConfiguration configuration)
@ -119,6 +117,7 @@ namespace AsbCloudInfrastructure
services.AddTransient<IDrillerService, DrillerService>();
services.AddTransient<IScheduleService, ScheduleService>();
services.AddTransient<IOperationValueService, OperationValueService>();
services.AddTransient<IUserSettingsRepository, UserSettingsRepository>();
// admin crud services:
services.AddTransient<ICrudService<TelemetryDto>, CrudServiceBase<TelemetryDto, Telemetry>>(s =>

View File

@ -0,0 +1,72 @@
using AsbCloudApp.Services;
using AsbCloudDb.Model;
using Microsoft.EntityFrameworkCore;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace AsbCloudInfrastructure.Services
{
public class UserSettingsRepository : IUserSettingsRepository
{
private readonly IAsbCloudDbContext context;
public UserSettingsRepository(IAsbCloudDbContext context)
{
this.context = context;
}
public Task<object> GetOrDefaultAsync(int userId, string key, CancellationToken token)
=> context.Set<UserSetting>()
.Where(s => s.IdUser == userId && s.Key == key)
.Select(s=>s.Value)
.FirstOrDefaultAsync(token);
public async Task<int> InsertAsync(int userId, string key, object value, CancellationToken token)
{
var set = context.Set<UserSetting>();
if (await set.AnyAsync(s=>s.IdUser == userId && s.Key == key, token))
return IUserSettingsRepository.ErrorKeyIsUsed;
var entity = new UserSetting
{
IdUser = userId,
Key = key,
Value = value,
};
context.Set<UserSetting>()
.Add(entity);
return await context.SaveChangesAsync(token);
}
public async Task<int> UpdateAsync(int userId, string key, object value, CancellationToken token)
{
var set = context.Set<UserSetting>();
var updatingItem = await set
.FirstOrDefaultAsync(s => s.IdUser == userId && s.Key == key, token);
if (updatingItem is null)
return IUserSettingsRepository.ErrorKeyNotFound;
updatingItem.Value = value;
set.Update(updatingItem);
return await context.SaveChangesAsync(token);
}
public async Task<int> DeleteAsync(int userId, string key, CancellationToken token)
{
var set = context.Set<UserSetting>();
var removingItem = await set
.FirstOrDefaultAsync(s=>s.IdUser == userId && s.Key ==key, token);
if(removingItem is null)
return IUserSettingsRepository.ErrorKeyNotFound;
set.Remove(removingItem);
return await context.SaveChangesAsync(token);
}
}
}

View File

@ -0,0 +1,78 @@
using AsbCloudApp.Exceptions;
using AsbCloudApp.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.ComponentModel.DataAnnotations;
using System.Threading;
using System.Threading.Tasks;
namespace AsbCloudWebApi.Controllers
{
[Route("api/[controller]")]
[ApiController]
[Authorize]
public class UserSettingsController : ControllerBase
{
private readonly IUserSettingsRepository service;
public UserSettingsController(IUserSettingsRepository service)
{
this.service = service;
}
[HttpGet("{key}")]
[Permission]
public virtual async Task<IActionResult> GetAsync(
[StringLength(255, MinimumLength = 1, ErrorMessage = "The key value cannot less then 1 character and greater then 255. ")]
string key,
CancellationToken token)
{
var userId = User.GetUserId();
if (userId is null)
return Forbid();
var result = await service.GetOrDefaultAsync((int)userId, key, token).ConfigureAwait(false);
return Ok(result);
}
[HttpPost("{key}")]
[Permission]
public virtual async Task<ActionResult<int>> InsertAsync(string key, [FromBody] object value, CancellationToken token)
{
var userId = User.GetUserId();
if (userId is null)
return Forbid();
var result = await service.InsertAsync((int)userId, key, value, token).ConfigureAwait(false);
if (result == IUserSettingsRepository.ErrorKeyIsUsed)
return BadRequest(ArgumentInvalidException.MakeValidationError(nameof(key), "is already used"));
return Ok(result);
}
[HttpPut("{key}")]
public virtual async Task<ActionResult<int>> UpdateAsync(string key, [FromBody] object value, CancellationToken token)
{
var userId = User.GetUserId();
if (userId is null)
return Forbid();
var result = await service.UpdateAsync((int)userId, key, value, token).ConfigureAwait(false);
if (result < 0)
return BadRequest(ArgumentInvalidException.MakeValidationError(nameof(key), "not found"));
return Ok(result);
}
[HttpDelete("{key}")]
public virtual async Task<ActionResult<int>> DeleteAsync(string key, CancellationToken token)
{
var userId = User.GetUserId();
if (userId is null)
return Forbid();
var result = await service.DeleteAsync((int)userId, key, token).ConfigureAwait(false);
if (result < 0)
return BadRequest(ArgumentInvalidException.MakeValidationError(nameof(key), "not found"));
return Ok(result);
}
}
}