MCDO fixes

add groups to individuals stuff

don't show your own data lmao

don't allow to share to not joined groups

fix shared bug maybe

fucking braces

improve CharaDataGetShared()

remove unnecessary double-query on get shared data

optimize

remove shit
This commit is contained in:
Stanley Dimant
2025-01-12 12:46:26 +01:00
committed by Loporrit
parent f225323c40
commit 156c3d80ed
9 changed files with 1327 additions and 65 deletions

Submodule MareAPI updated: c8cc217d66...4d8c380dab

View File

@@ -5,7 +5,6 @@ using MareSynchronosShared.Models;
using MareSynchronosShared.Utils; using MareSynchronosShared.Utils;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using System.Text;
using System.Text.Json; using System.Text.Json;
namespace MareSynchronosServer.Hubs; namespace MareSynchronosServer.Hubs;
@@ -116,6 +115,8 @@ public partial class MareHub
.Include(u => u.OriginalFiles) .Include(u => u.OriginalFiles)
.Include(u => u.AllowedIndividiuals) .Include(u => u.AllowedIndividiuals)
.ThenInclude(u => u.AllowedUser) .ThenInclude(u => u.AllowedUser)
.Include(u => u.AllowedIndividiuals)
.ThenInclude(u => u.AllowedGroup)
.Include(u => u.Poses) .Include(u => u.Poses)
.AsSplitQuery() .AsSplitQuery()
.Where(c => c.UploaderUID == UserUID).ToListAsync().ConfigureAwait(false); .Where(c => c.UploaderUID == UserUID).ToListAsync().ConfigureAwait(false);
@@ -128,48 +129,34 @@ public partial class MareHub
{ {
_logger.LogCallInfo(); _logger.LogCallInfo();
var allPairedUsers = await GetAllPairedUnpausedUsers().ConfigureAwait(false);
List<CharaData> sharedCharaData = []; List<CharaData> sharedCharaData = [];
foreach (var pair in allPairedUsers) var groups = await DbContext.GroupPairs
.Where(u => u.GroupUserUID == UserUID)
.Select(k => k.GroupGID)
.AsNoTracking()
.ToListAsync()
.ConfigureAwait(false);
var validPairs = await GetAllPairedUnpausedUsers().ConfigureAwait(false);
var allSharedDataByPair = await DbContext.CharaData
.Include(u => u.Files)
.Include(u => u.OriginalFiles)
.Include(u => u.AllowedIndividiuals)
.Include(u => u.Poses)
.Include(u => u.Uploader)
.Where(p => p.UploaderUID != UserUID && p.ShareType == CharaDataShare.Shared)
.Where(p => (validPairs.Contains(p.UploaderUID)
|| (p.AllowedIndividiuals.Any(u => u.AllowedUserUID == UserUID || (u.AllowedGroupGID != null && groups.Contains(u.AllowedGroupGID))))))
.AsSplitQuery()
.AsNoTracking()
.ToListAsync()
.ConfigureAwait(false);
foreach (var charaData in allSharedDataByPair)
{ {
var allSharedDataByPair = await DbContext.CharaData sharedCharaData.Add(charaData);
.Include(u => u.Files)
.Include(u => u.OriginalFiles)
.Include(u => u.AllowedIndividiuals)
.Include(u => u.Poses)
.Include(u => u.Uploader)
.Where(p => p.ShareType == CharaDataShare.Shared && p.UploaderUID == pair)
.AsSplitQuery()
.AsNoTracking()
.ToListAsync()
.ConfigureAwait(false);
foreach (var charaData in allSharedDataByPair)
{
if (await CheckCharaDataAllowance(charaData).ConfigureAwait(false))
{
sharedCharaData.Add(charaData);
}
}
}
var charaDataDirectlyShared = await DbContext.CharaData.Include(u => u.Files)
.Include(u => u.OriginalFiles)
.Include(u => u.AllowedIndividiuals)
.Include(u => u.Poses)
.Include(u => u.Uploader)
.Where(p => p.ShareType == CharaDataShare.Shared && p.AllowedIndividiuals.Any(u => u.AllowedUserUID == UserUID))
.AsSplitQuery()
.AsNoTracking()
.ToListAsync()
.ConfigureAwait(false);
foreach (var data in charaDataDirectlyShared)
{
if (sharedCharaData.Exists(d => string.Equals(d.Id, data.Id, StringComparison.Ordinal)
&& string.Equals(d.UploaderUID, d.UploaderUID, StringComparison.Ordinal)))
continue;
sharedCharaData.Add(data);
} }
_logger.LogCallInfo(MareHubLogger.Args("SUCCESS", sharedCharaData.Count)); _logger.LogCallInfo(MareHubLogger.Args("SUCCESS", sharedCharaData.Count));
@@ -185,6 +172,8 @@ public partial class MareHub
.Include(u => u.OriginalFiles) .Include(u => u.OriginalFiles)
.Include(u => u.AllowedIndividiuals) .Include(u => u.AllowedIndividiuals)
.ThenInclude(u => u.AllowedUser) .ThenInclude(u => u.AllowedUser)
.Include(u => u.AllowedIndividiuals)
.ThenInclude(u => u.AllowedGroup)
.Include(u => u.FileSwaps) .Include(u => u.FileSwaps)
.Include(u => u.Poses) .Include(u => u.Poses)
.AsSplitQuery() .AsSplitQuery()
@@ -239,29 +228,67 @@ public partial class MareHub
if (updateDto.AllowedUsers != null) if (updateDto.AllowedUsers != null)
{ {
var individuals = charaData.AllowedIndividiuals.ToList(); var individuals = charaData.AllowedIndividiuals.Where(k => k.AllowedGroup == null).ToList();
charaData.AllowedIndividiuals.Clear();
DbContext.RemoveRange(individuals);
var allowedUserList = updateDto.AllowedUsers.ToList(); var allowedUserList = updateDto.AllowedUsers.ToList();
foreach (var user in updateDto.AllowedUsers) foreach (var user in updateDto.AllowedUsers)
{ {
var dbUser = await DbContext.Users.SingleOrDefaultAsync(u => u.UID == user || u.Alias == user).ConfigureAwait(false); if (charaData.AllowedIndividiuals.Any(k => k.AllowedUser != null && (string.Equals(k.AllowedUser.UID, user, StringComparison.Ordinal) || string.Equals(k.AllowedUser.Alias, user, StringComparison.Ordinal))))
if (dbUser != null)
{ {
if (!allowedUserList.Contains(dbUser.UID, StringComparer.Ordinal) && !allowedUserList.Contains(dbUser.Alias, StringComparer.Ordinal)) continue;
}
else
{
var dbUser = await DbContext.Users.SingleOrDefaultAsync(u => u.UID == user || u.Alias == user).ConfigureAwait(false);
if (dbUser != null)
{ {
continue; charaData.AllowedIndividiuals.Add(new CharaDataAllowance()
{
AllowedUser = dbUser,
Parent = charaData
});
} }
allowedUserList.RemoveAll(u => string.Equals(u, dbUser.UID, StringComparison.Ordinal));
allowedUserList.RemoveAll(u => string.Equals(u, dbUser.Alias, StringComparison.Ordinal));
charaData.AllowedIndividiuals.Add(new CharaDataAllowance()
{
AllowedUser = dbUser,
Parent = charaData
});
} }
} }
foreach (var dataUser in individuals.Where(k => !updateDto.AllowedUsers.Contains(k.AllowedUser.UID, StringComparer.Ordinal) && !updateDto.AllowedUsers.Contains(k.AllowedUser.Alias, StringComparer.Ordinal)))
{
DbContext.Remove(dataUser);
charaData.AllowedIndividiuals.Remove(dataUser);
}
anyChanges = true;
}
if (updateDto.AllowedGroups != null)
{
var individualGroups = charaData.AllowedIndividiuals.Where(k => k.AllowedUser == null).ToList();
var allowedGroups = updateDto.AllowedGroups.ToList();
foreach (var group in updateDto.AllowedGroups)
{
if (charaData.AllowedIndividiuals.Any(k => k.AllowedGroup != null && (string.Equals(k.AllowedGroup.GID, group, StringComparison.Ordinal) || string.Equals(k.AllowedGroup.Alias, group, StringComparison.Ordinal))))
{
continue;
}
else
{
var groupUser = await DbContext.GroupPairs.Include(u => u.Group).SingleOrDefaultAsync(u => (u.Group.GID == group || u.Group.Alias == group) && u.GroupUserUID == UserUID).ConfigureAwait(false);
if (groupUser != null)
{
charaData.AllowedIndividiuals.Add(new CharaDataAllowance()
{
AllowedGroup = groupUser.Group,
Parent = charaData
});
}
}
}
foreach (var dataGroup in individualGroups.Where(k => !updateDto.AllowedGroups.Contains(k.AllowedGroup.GID, StringComparer.Ordinal) && !updateDto.AllowedGroups.Contains(k.AllowedGroup.Alias, StringComparer.Ordinal)))
{
DbContext.Remove(dataGroup);
charaData.AllowedIndividiuals.Remove(dataGroup);
}
anyChanges = true; anyChanges = true;
} }
@@ -411,7 +438,8 @@ public partial class MareHub
{ {
AccessType = GetAccessTypeDto(charaData.AccessType), AccessType = GetAccessTypeDto(charaData.AccessType),
ShareType = GetShareTypeDto(charaData.ShareType), ShareType = GetShareTypeDto(charaData.ShareType),
AllowedUsers = [.. charaData.AllowedIndividiuals.Select(u => new UserData(u.AllowedUser.UID, u.AllowedUser.Alias))], AllowedUsers = [.. charaData.AllowedIndividiuals.Where(k => !string.IsNullOrEmpty(k.AllowedUserUID)).Select(u => new UserData(u.AllowedUser.UID, u.AllowedUser.Alias))],
AllowedGroups = [.. charaData.AllowedIndividiuals.Where(k => !string.IsNullOrEmpty(k.AllowedGroupGID)).Select(k => new GroupData(k.AllowedGroup.GID, k.AllowedGroup.Alias))],
CustomizeData = charaData.CustomizeData, CustomizeData = charaData.CustomizeData,
Description = charaData.Description, Description = charaData.Description,
ExpiryDate = charaData.ExpiryDate ?? DateTime.MaxValue, ExpiryDate = charaData.ExpiryDate ?? DateTime.MaxValue,
@@ -477,7 +505,7 @@ public partial class MareHub
_ => throw new NotSupportedException(), _ => throw new NotSupportedException(),
}; };
private async Task<bool> CheckCharaDataAllowance(CharaData charaData) private async Task<bool> CheckCharaDataAllowance(CharaData charaData, List<string> joinedGroups)
{ {
// check for self // check for self
if (string.Equals(charaData.UploaderUID, UserUID, StringComparison.Ordinal)) if (string.Equals(charaData.UploaderUID, UserUID, StringComparison.Ordinal))
@@ -544,7 +572,10 @@ public partial class MareHub
throw new InvalidDataException($"No chara data with {id} found"); throw new InvalidDataException($"No chara data with {id} found");
} }
if (!await CheckCharaDataAllowance(charaData).ConfigureAwait(false)) var groups = await DbContext.GroupPairs.Where(u => u.GroupUserUID == UserUID).Select(k => k.GroupGID).ToListAsync()
.ConfigureAwait(false);
if (!await CheckCharaDataAllowance(charaData, groups).ConfigureAwait(false))
{ {
_logger.LogCallWarning(MareHubLogger.Args("UNAUTHORIZED", id)); _logger.LogCallWarning(MareHubLogger.Args("UNAUTHORIZED", id));
throw new UnauthorizedAccessException($"User is not allowed to download {id}"); throw new UnauthorizedAccessException($"User is not allowed to download {id}");

View File

@@ -262,6 +262,9 @@ public partial class MareHub
} }
} }
var sharedData = await DbContext.CharaDataAllowances.Where(u => u.AllowedGroup != null && u.AllowedGroupGID == dto.GID && u.ParentUploaderUID == userUid).ToListAsync().ConfigureAwait(false);
DbContext.CharaDataAllowances.RemoveRange(sharedData);
await DbContext.SaveChangesAsync().ConfigureAwait(false); await DbContext.SaveChangesAsync().ConfigureAwait(false);
_logger.LogCallInfo(MareHubLogger.Args(dto, "Success")); _logger.LogCallInfo(MareHubLogger.Args(dto, "Success"));

View File

@@ -191,6 +191,9 @@ public partial class MareHub
var allUserPairs = await GetAllPairedClientsWithPauseState(pair.GroupUserUID).ConfigureAwait(false); var allUserPairs = await GetAllPairedClientsWithPauseState(pair.GroupUserUID).ConfigureAwait(false);
var sharedData = await DbContext.CharaDataAllowances.Where(u => u.AllowedGroup != null && u.AllowedGroupGID == dto.GID && u.ParentUploaderUID == pair.GroupUserUID).ToListAsync().ConfigureAwait(false);
DbContext.CharaDataAllowances.RemoveRange(sharedData);
foreach (var groupUserPair in groupPairs.Where(p => !string.Equals(p.GroupUserUID, pair.GroupUserUID, StringComparison.Ordinal))) foreach (var groupUserPair in groupPairs.Where(p => !string.Equals(p.GroupUserUID, pair.GroupUserUID, StringComparison.Ordinal)))
{ {
await UserGroupLeave(groupUserPair, allUserPairs, pairIdent).ConfigureAwait(false); await UserGroupLeave(groupUserPair, allUserPairs, pairIdent).ConfigureAwait(false);
@@ -463,6 +466,11 @@ public partial class MareHub
var groupPairs = DbContext.GroupPairs.Where(p => p.GroupGID == group.GID).AsNoTracking().ToList(); var groupPairs = DbContext.GroupPairs.Where(p => p.GroupGID == group.GID).AsNoTracking().ToList();
await Clients.Users(groupPairs.Select(p => p.GroupUserUID)).Client_GroupPairLeft(dto).ConfigureAwait(false); await Clients.Users(groupPairs.Select(p => p.GroupUserUID)).Client_GroupPairLeft(dto).ConfigureAwait(false);
var sharedData = await DbContext.CharaDataAllowances.Where(u => u.AllowedGroup != null && u.AllowedGroupGID == dto.GID && u.ParentUploaderUID == dto.UID).ToListAsync().ConfigureAwait(false);
DbContext.CharaDataAllowances.RemoveRange(sharedData);
await DbContext.SaveChangesAsync().ConfigureAwait(false);
var userIdent = await GetUserIdent(dto.User.UID).ConfigureAwait(false); var userIdent = await GetUserIdent(dto.User.UID).ConfigureAwait(false);
if (userIdent == null) return; if (userIdent == null) return;

View File

@@ -122,7 +122,10 @@ public class MareDbContext : DbContext
mb.Entity<CharaDataOriginalFile>().HasKey(c => new { c.ParentId, c.ParentUploaderUID, c.GamePath }); mb.Entity<CharaDataOriginalFile>().HasKey(c => new { c.ParentId, c.ParentUploaderUID, c.GamePath });
mb.Entity<CharaDataOriginalFile>().HasIndex(c => c.ParentId); mb.Entity<CharaDataOriginalFile>().HasIndex(c => c.ParentId);
mb.Entity<CharaDataAllowance>().ToTable("chara_data_allowance"); mb.Entity<CharaDataAllowance>().ToTable("chara_data_allowance");
mb.Entity<CharaDataAllowance>().HasKey(c => new { c.ParentId, c.ParentUploaderUID, c.AllowedUserUID }); mb.Entity<CharaDataAllowance>().HasKey(c => new { c.ParentId, c.ParentUploaderUID, c.Id });
mb.Entity<CharaDataAllowance>().Property(p => p.Id).ValueGeneratedOnAdd();
mb.Entity<CharaDataAllowance>().HasIndex(c => c.ParentId); mb.Entity<CharaDataAllowance>().HasIndex(c => c.ParentId);
mb.Entity<CharaDataAllowance>().HasOne(u => u.AllowedGroup).WithMany().HasForeignKey(u => u.AllowedGroupGID).OnDelete(DeleteBehavior.Cascade);
mb.Entity<CharaDataAllowance>().HasOne(u => u.AllowedUser).WithMany().HasForeignKey(u => u.AllowedUserUID).OnDelete(DeleteBehavior.Cascade);
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,98 @@
using Microsoft.EntityFrameworkCore.Migrations;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace MareSynchronosServer.Migrations
{
/// <inheritdoc />
public partial class AllowedGroup : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropPrimaryKey(
name: "pk_chara_data_allowance",
table: "chara_data_allowance");
migrationBuilder.AlterColumn<string>(
name: "allowed_user_uid",
table: "chara_data_allowance",
type: "character varying(10)",
nullable: true,
oldClrType: typeof(string),
oldType: "character varying(10)");
migrationBuilder.AddColumn<long>(
name: "id",
table: "chara_data_allowance",
type: "bigint",
nullable: false,
defaultValue: 0L)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
migrationBuilder.AddColumn<string>(
name: "allowed_group_gid",
table: "chara_data_allowance",
type: "character varying(20)",
nullable: true);
migrationBuilder.AddPrimaryKey(
name: "pk_chara_data_allowance",
table: "chara_data_allowance",
columns: new[] { "parent_id", "parent_uploader_uid", "id" });
migrationBuilder.CreateIndex(
name: "ix_chara_data_allowance_allowed_group_gid",
table: "chara_data_allowance",
column: "allowed_group_gid");
migrationBuilder.AddForeignKey(
name: "fk_chara_data_allowance_groups_allowed_group_gid",
table: "chara_data_allowance",
column: "allowed_group_gid",
principalTable: "groups",
principalColumn: "gid",
onDelete: ReferentialAction.Cascade);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "fk_chara_data_allowance_groups_allowed_group_gid",
table: "chara_data_allowance");
migrationBuilder.DropPrimaryKey(
name: "pk_chara_data_allowance",
table: "chara_data_allowance");
migrationBuilder.DropIndex(
name: "ix_chara_data_allowance_allowed_group_gid",
table: "chara_data_allowance");
migrationBuilder.DropColumn(
name: "id",
table: "chara_data_allowance");
migrationBuilder.DropColumn(
name: "allowed_group_gid",
table: "chara_data_allowance");
migrationBuilder.AlterColumn<string>(
name: "allowed_user_uid",
table: "chara_data_allowance",
type: "character varying(10)",
nullable: false,
defaultValue: "",
oldClrType: typeof(string),
oldType: "character varying(10)",
oldNullable: true);
migrationBuilder.AddPrimaryKey(
name: "pk_chara_data_allowance",
table: "chara_data_allowance",
columns: new[] { "parent_id", "parent_uploader_uid", "allowed_user_uid" });
}
}
}

View File

@@ -161,13 +161,27 @@ namespace MareSynchronosServer.Migrations
.HasColumnType("character varying(10)") .HasColumnType("character varying(10)")
.HasColumnName("parent_uploader_uid"); .HasColumnName("parent_uploader_uid");
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint")
.HasColumnName("id");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
b.Property<string>("AllowedGroupGID")
.HasColumnType("character varying(20)")
.HasColumnName("allowed_group_gid");
b.Property<string>("AllowedUserUID") b.Property<string>("AllowedUserUID")
.HasColumnType("character varying(10)") .HasColumnType("character varying(10)")
.HasColumnName("allowed_user_uid"); .HasColumnName("allowed_user_uid");
b.HasKey("ParentId", "ParentUploaderUID", "AllowedUserUID") b.HasKey("ParentId", "ParentUploaderUID", "Id")
.HasName("pk_chara_data_allowance"); .HasName("pk_chara_data_allowance");
b.HasIndex("AllowedGroupGID")
.HasDatabaseName("ix_chara_data_allowance_allowed_group_gid");
b.HasIndex("AllowedUserUID") b.HasIndex("AllowedUserUID")
.HasDatabaseName("ix_chara_data_allowance_allowed_user_uid"); .HasDatabaseName("ix_chara_data_allowance_allowed_user_uid");
@@ -737,11 +751,16 @@ namespace MareSynchronosServer.Migrations
modelBuilder.Entity("MareSynchronosShared.Models.CharaDataAllowance", b => modelBuilder.Entity("MareSynchronosShared.Models.CharaDataAllowance", b =>
{ {
b.HasOne("MareSynchronosShared.Models.Group", "AllowedGroup")
.WithMany()
.HasForeignKey("AllowedGroupGID")
.OnDelete(DeleteBehavior.Cascade)
.HasConstraintName("fk_chara_data_allowance_groups_allowed_group_gid");
b.HasOne("MareSynchronosShared.Models.User", "AllowedUser") b.HasOne("MareSynchronosShared.Models.User", "AllowedUser")
.WithMany() .WithMany()
.HasForeignKey("AllowedUserUID") .HasForeignKey("AllowedUserUID")
.OnDelete(DeleteBehavior.Cascade) .OnDelete(DeleteBehavior.Cascade)
.IsRequired()
.HasConstraintName("fk_chara_data_allowance_users_allowed_user_uid"); .HasConstraintName("fk_chara_data_allowance_users_allowed_user_uid");
b.HasOne("MareSynchronosShared.Models.CharaData", "Parent") b.HasOne("MareSynchronosShared.Models.CharaData", "Parent")
@@ -751,6 +770,8 @@ namespace MareSynchronosServer.Migrations
.IsRequired() .IsRequired()
.HasConstraintName("fk_chara_data_allowance_chara_data_parent_id_parent_uploader_u"); .HasConstraintName("fk_chara_data_allowance_chara_data_parent_id_parent_uploader_u");
b.Navigation("AllowedGroup");
b.Navigation("AllowedUser"); b.Navigation("AllowedUser");
b.Navigation("Parent"); b.Navigation("Parent");

View File

@@ -40,11 +40,15 @@ public class CharaData
public class CharaDataAllowance public class CharaDataAllowance
{ {
[Key]
public long Id { get; set; }
public virtual CharaData Parent { get; set; } public virtual CharaData Parent { get; set; }
public string ParentId { get; set; } public string ParentId { get; set; }
public string ParentUploaderUID { get; set; } public string ParentUploaderUID { get; set; }
public virtual User AllowedUser { get; set; } public virtual User? AllowedUser { get; set; }
public string AllowedUserUID { get; set; } public string? AllowedUserUID { get; set; }
public virtual Group? AllowedGroup { get; set; }
public string? AllowedGroupGID { get; set; }
} }
public class CharaDataOriginalFile public class CharaDataOriginalFile