diff --git a/backend/Knot.sln b/backend/Knot.sln index 60ebd47..9a54559 100644 --- a/backend/Knot.sln +++ b/backend/Knot.sln @@ -171,6 +171,34 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "UnitTests", "UnitTests", "{ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Knot.Modules.Profiles.UnitTests", "Tests\Users\UnitTests\Knot.Modules.Profiles.UnitTests.csproj", "{6BD8DC02-2270-4276-952E-E34E973A1237}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Contracts", "Contracts", "{FFBE31B8-50B9-B415-22BC-2F92C97CADA3}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Knot.Modules.Admin.Contracts", "src\Contracts\Knot.Modules.Admin.Contracts\Knot.Modules.Admin.Contracts.csproj", "{1D50E7AA-2378-4114-A3C3-E351D46FB8BF}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Knot.Modules.Auth.Contracts", "src\Contracts\Knot.Modules.Auth.Contracts\Knot.Modules.Auth.Contracts.csproj", "{E8C0F163-735D-44A2-B684-673A0B0D7D2A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Knot.Modules.Conversations.Contracts", "src\Contracts\Knot.Modules.Conversations.Contracts\Knot.Modules.Conversations.Contracts.csproj", "{65E67218-A02C-4C42-8B60-6FDAB737E613}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Knot.Modules.Federation.Contracts", "src\Contracts\Knot.Modules.Federation.Contracts\Knot.Modules.Federation.Contracts.csproj", "{7226D94C-B9A5-41D7-9E59-50A68F39EE78}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Knot.Modules.Klipy.Contracts", "src\Contracts\Knot.Modules.Klipy.Contracts\Knot.Modules.Klipy.Contracts.csproj", "{4AC0C433-475F-4B0C-B160-E4F33779E3CB}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Knot.Modules.Messaging.Contracts", "src\Contracts\Knot.Modules.Messaging.Contracts\Knot.Modules.Messaging.Contracts.csproj", "{9D86914A-43A8-4451-BEFD-092ABFF793D6}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Knot.Modules.Profiles.Contracts", "src\Contracts\Knot.Modules.Profiles.Contracts\Knot.Modules.Profiles.Contracts.csproj", "{1DC69DD3-3348-4375-844C-D44A760D50EC}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Knot.Modules.Relations.Contracts", "src\Contracts\Knot.Modules.Relations.Contracts\Knot.Modules.Relations.Contracts.csproj", "{352A455F-AC3F-4D34-BADA-574BF83E131C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Knot.Modules.Settings.Contracts", "src\Contracts\Knot.Modules.Settings.Contracts\Knot.Modules.Settings.Contracts.csproj", "{D10F0FA0-A682-42D4-A23F-46094D14A8F6}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Knot.Modules.Storage.Contracts", "src\Contracts\Knot.Modules.Storage.Contracts\Knot.Modules.Storage.Contracts.csproj", "{F57F6152-A359-4BB5-AC01-5531C85EE47A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Knot.Modules.Stories.Contracts", "src\Contracts\Knot.Modules.Stories.Contracts\Knot.Modules.Stories.Contracts.csproj", "{32631ED6-956A-4572-AD7A-B8D0ECE26C78}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Knot.Modules.TelegramImport.Contracts", "src\Contracts\Knot.Modules.TelegramImport.Contracts\Knot.Modules.TelegramImport.Contracts.csproj", "{7E22E87D-78D2-411D-AC30-2F090C3F5ED5}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Knot.Modules.WebRtc.Contracts", "src\Contracts\Knot.Modules.WebRtc.Contracts\Knot.Modules.WebRtc.Contracts.csproj", "{623330CA-6CA5-4B74-A921-DEAE8002FCC5}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -601,6 +629,162 @@ Global {6BD8DC02-2270-4276-952E-E34E973A1237}.Release|x64.Build.0 = Release|Any CPU {6BD8DC02-2270-4276-952E-E34E973A1237}.Release|x86.ActiveCfg = Release|Any CPU {6BD8DC02-2270-4276-952E-E34E973A1237}.Release|x86.Build.0 = Release|Any CPU + {1D50E7AA-2378-4114-A3C3-E351D46FB8BF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1D50E7AA-2378-4114-A3C3-E351D46FB8BF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1D50E7AA-2378-4114-A3C3-E351D46FB8BF}.Debug|x64.ActiveCfg = Debug|Any CPU + {1D50E7AA-2378-4114-A3C3-E351D46FB8BF}.Debug|x64.Build.0 = Debug|Any CPU + {1D50E7AA-2378-4114-A3C3-E351D46FB8BF}.Debug|x86.ActiveCfg = Debug|Any CPU + {1D50E7AA-2378-4114-A3C3-E351D46FB8BF}.Debug|x86.Build.0 = Debug|Any CPU + {1D50E7AA-2378-4114-A3C3-E351D46FB8BF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1D50E7AA-2378-4114-A3C3-E351D46FB8BF}.Release|Any CPU.Build.0 = Release|Any CPU + {1D50E7AA-2378-4114-A3C3-E351D46FB8BF}.Release|x64.ActiveCfg = Release|Any CPU + {1D50E7AA-2378-4114-A3C3-E351D46FB8BF}.Release|x64.Build.0 = Release|Any CPU + {1D50E7AA-2378-4114-A3C3-E351D46FB8BF}.Release|x86.ActiveCfg = Release|Any CPU + {1D50E7AA-2378-4114-A3C3-E351D46FB8BF}.Release|x86.Build.0 = Release|Any CPU + {E8C0F163-735D-44A2-B684-673A0B0D7D2A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E8C0F163-735D-44A2-B684-673A0B0D7D2A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E8C0F163-735D-44A2-B684-673A0B0D7D2A}.Debug|x64.ActiveCfg = Debug|Any CPU + {E8C0F163-735D-44A2-B684-673A0B0D7D2A}.Debug|x64.Build.0 = Debug|Any CPU + {E8C0F163-735D-44A2-B684-673A0B0D7D2A}.Debug|x86.ActiveCfg = Debug|Any CPU + {E8C0F163-735D-44A2-B684-673A0B0D7D2A}.Debug|x86.Build.0 = Debug|Any CPU + {E8C0F163-735D-44A2-B684-673A0B0D7D2A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E8C0F163-735D-44A2-B684-673A0B0D7D2A}.Release|Any CPU.Build.0 = Release|Any CPU + {E8C0F163-735D-44A2-B684-673A0B0D7D2A}.Release|x64.ActiveCfg = Release|Any CPU + {E8C0F163-735D-44A2-B684-673A0B0D7D2A}.Release|x64.Build.0 = Release|Any CPU + {E8C0F163-735D-44A2-B684-673A0B0D7D2A}.Release|x86.ActiveCfg = Release|Any CPU + {E8C0F163-735D-44A2-B684-673A0B0D7D2A}.Release|x86.Build.0 = Release|Any CPU + {65E67218-A02C-4C42-8B60-6FDAB737E613}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {65E67218-A02C-4C42-8B60-6FDAB737E613}.Debug|Any CPU.Build.0 = Debug|Any CPU + {65E67218-A02C-4C42-8B60-6FDAB737E613}.Debug|x64.ActiveCfg = Debug|Any CPU + {65E67218-A02C-4C42-8B60-6FDAB737E613}.Debug|x64.Build.0 = Debug|Any CPU + {65E67218-A02C-4C42-8B60-6FDAB737E613}.Debug|x86.ActiveCfg = Debug|Any CPU + {65E67218-A02C-4C42-8B60-6FDAB737E613}.Debug|x86.Build.0 = Debug|Any CPU + {65E67218-A02C-4C42-8B60-6FDAB737E613}.Release|Any CPU.ActiveCfg = Release|Any CPU + {65E67218-A02C-4C42-8B60-6FDAB737E613}.Release|Any CPU.Build.0 = Release|Any CPU + {65E67218-A02C-4C42-8B60-6FDAB737E613}.Release|x64.ActiveCfg = Release|Any CPU + {65E67218-A02C-4C42-8B60-6FDAB737E613}.Release|x64.Build.0 = Release|Any CPU + {65E67218-A02C-4C42-8B60-6FDAB737E613}.Release|x86.ActiveCfg = Release|Any CPU + {65E67218-A02C-4C42-8B60-6FDAB737E613}.Release|x86.Build.0 = Release|Any CPU + {7226D94C-B9A5-41D7-9E59-50A68F39EE78}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7226D94C-B9A5-41D7-9E59-50A68F39EE78}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7226D94C-B9A5-41D7-9E59-50A68F39EE78}.Debug|x64.ActiveCfg = Debug|Any CPU + {7226D94C-B9A5-41D7-9E59-50A68F39EE78}.Debug|x64.Build.0 = Debug|Any CPU + {7226D94C-B9A5-41D7-9E59-50A68F39EE78}.Debug|x86.ActiveCfg = Debug|Any CPU + {7226D94C-B9A5-41D7-9E59-50A68F39EE78}.Debug|x86.Build.0 = Debug|Any CPU + {7226D94C-B9A5-41D7-9E59-50A68F39EE78}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7226D94C-B9A5-41D7-9E59-50A68F39EE78}.Release|Any CPU.Build.0 = Release|Any CPU + {7226D94C-B9A5-41D7-9E59-50A68F39EE78}.Release|x64.ActiveCfg = Release|Any CPU + {7226D94C-B9A5-41D7-9E59-50A68F39EE78}.Release|x64.Build.0 = Release|Any CPU + {7226D94C-B9A5-41D7-9E59-50A68F39EE78}.Release|x86.ActiveCfg = Release|Any CPU + {7226D94C-B9A5-41D7-9E59-50A68F39EE78}.Release|x86.Build.0 = Release|Any CPU + {4AC0C433-475F-4B0C-B160-E4F33779E3CB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4AC0C433-475F-4B0C-B160-E4F33779E3CB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4AC0C433-475F-4B0C-B160-E4F33779E3CB}.Debug|x64.ActiveCfg = Debug|Any CPU + {4AC0C433-475F-4B0C-B160-E4F33779E3CB}.Debug|x64.Build.0 = Debug|Any CPU + {4AC0C433-475F-4B0C-B160-E4F33779E3CB}.Debug|x86.ActiveCfg = Debug|Any CPU + {4AC0C433-475F-4B0C-B160-E4F33779E3CB}.Debug|x86.Build.0 = Debug|Any CPU + {4AC0C433-475F-4B0C-B160-E4F33779E3CB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4AC0C433-475F-4B0C-B160-E4F33779E3CB}.Release|Any CPU.Build.0 = Release|Any CPU + {4AC0C433-475F-4B0C-B160-E4F33779E3CB}.Release|x64.ActiveCfg = Release|Any CPU + {4AC0C433-475F-4B0C-B160-E4F33779E3CB}.Release|x64.Build.0 = Release|Any CPU + {4AC0C433-475F-4B0C-B160-E4F33779E3CB}.Release|x86.ActiveCfg = Release|Any CPU + {4AC0C433-475F-4B0C-B160-E4F33779E3CB}.Release|x86.Build.0 = Release|Any CPU + {9D86914A-43A8-4451-BEFD-092ABFF793D6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9D86914A-43A8-4451-BEFD-092ABFF793D6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9D86914A-43A8-4451-BEFD-092ABFF793D6}.Debug|x64.ActiveCfg = Debug|Any CPU + {9D86914A-43A8-4451-BEFD-092ABFF793D6}.Debug|x64.Build.0 = Debug|Any CPU + {9D86914A-43A8-4451-BEFD-092ABFF793D6}.Debug|x86.ActiveCfg = Debug|Any CPU + {9D86914A-43A8-4451-BEFD-092ABFF793D6}.Debug|x86.Build.0 = Debug|Any CPU + {9D86914A-43A8-4451-BEFD-092ABFF793D6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9D86914A-43A8-4451-BEFD-092ABFF793D6}.Release|Any CPU.Build.0 = Release|Any CPU + {9D86914A-43A8-4451-BEFD-092ABFF793D6}.Release|x64.ActiveCfg = Release|Any CPU + {9D86914A-43A8-4451-BEFD-092ABFF793D6}.Release|x64.Build.0 = Release|Any CPU + {9D86914A-43A8-4451-BEFD-092ABFF793D6}.Release|x86.ActiveCfg = Release|Any CPU + {9D86914A-43A8-4451-BEFD-092ABFF793D6}.Release|x86.Build.0 = Release|Any CPU + {1DC69DD3-3348-4375-844C-D44A760D50EC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1DC69DD3-3348-4375-844C-D44A760D50EC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1DC69DD3-3348-4375-844C-D44A760D50EC}.Debug|x64.ActiveCfg = Debug|Any CPU + {1DC69DD3-3348-4375-844C-D44A760D50EC}.Debug|x64.Build.0 = Debug|Any CPU + {1DC69DD3-3348-4375-844C-D44A760D50EC}.Debug|x86.ActiveCfg = Debug|Any CPU + {1DC69DD3-3348-4375-844C-D44A760D50EC}.Debug|x86.Build.0 = Debug|Any CPU + {1DC69DD3-3348-4375-844C-D44A760D50EC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1DC69DD3-3348-4375-844C-D44A760D50EC}.Release|Any CPU.Build.0 = Release|Any CPU + {1DC69DD3-3348-4375-844C-D44A760D50EC}.Release|x64.ActiveCfg = Release|Any CPU + {1DC69DD3-3348-4375-844C-D44A760D50EC}.Release|x64.Build.0 = Release|Any CPU + {1DC69DD3-3348-4375-844C-D44A760D50EC}.Release|x86.ActiveCfg = Release|Any CPU + {1DC69DD3-3348-4375-844C-D44A760D50EC}.Release|x86.Build.0 = Release|Any CPU + {352A455F-AC3F-4D34-BADA-574BF83E131C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {352A455F-AC3F-4D34-BADA-574BF83E131C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {352A455F-AC3F-4D34-BADA-574BF83E131C}.Debug|x64.ActiveCfg = Debug|Any CPU + {352A455F-AC3F-4D34-BADA-574BF83E131C}.Debug|x64.Build.0 = Debug|Any CPU + {352A455F-AC3F-4D34-BADA-574BF83E131C}.Debug|x86.ActiveCfg = Debug|Any CPU + {352A455F-AC3F-4D34-BADA-574BF83E131C}.Debug|x86.Build.0 = Debug|Any CPU + {352A455F-AC3F-4D34-BADA-574BF83E131C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {352A455F-AC3F-4D34-BADA-574BF83E131C}.Release|Any CPU.Build.0 = Release|Any CPU + {352A455F-AC3F-4D34-BADA-574BF83E131C}.Release|x64.ActiveCfg = Release|Any CPU + {352A455F-AC3F-4D34-BADA-574BF83E131C}.Release|x64.Build.0 = Release|Any CPU + {352A455F-AC3F-4D34-BADA-574BF83E131C}.Release|x86.ActiveCfg = Release|Any CPU + {352A455F-AC3F-4D34-BADA-574BF83E131C}.Release|x86.Build.0 = Release|Any CPU + {D10F0FA0-A682-42D4-A23F-46094D14A8F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D10F0FA0-A682-42D4-A23F-46094D14A8F6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D10F0FA0-A682-42D4-A23F-46094D14A8F6}.Debug|x64.ActiveCfg = Debug|Any CPU + {D10F0FA0-A682-42D4-A23F-46094D14A8F6}.Debug|x64.Build.0 = Debug|Any CPU + {D10F0FA0-A682-42D4-A23F-46094D14A8F6}.Debug|x86.ActiveCfg = Debug|Any CPU + {D10F0FA0-A682-42D4-A23F-46094D14A8F6}.Debug|x86.Build.0 = Debug|Any CPU + {D10F0FA0-A682-42D4-A23F-46094D14A8F6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D10F0FA0-A682-42D4-A23F-46094D14A8F6}.Release|Any CPU.Build.0 = Release|Any CPU + {D10F0FA0-A682-42D4-A23F-46094D14A8F6}.Release|x64.ActiveCfg = Release|Any CPU + {D10F0FA0-A682-42D4-A23F-46094D14A8F6}.Release|x64.Build.0 = Release|Any CPU + {D10F0FA0-A682-42D4-A23F-46094D14A8F6}.Release|x86.ActiveCfg = Release|Any CPU + {D10F0FA0-A682-42D4-A23F-46094D14A8F6}.Release|x86.Build.0 = Release|Any CPU + {F57F6152-A359-4BB5-AC01-5531C85EE47A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F57F6152-A359-4BB5-AC01-5531C85EE47A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F57F6152-A359-4BB5-AC01-5531C85EE47A}.Debug|x64.ActiveCfg = Debug|Any CPU + {F57F6152-A359-4BB5-AC01-5531C85EE47A}.Debug|x64.Build.0 = Debug|Any CPU + {F57F6152-A359-4BB5-AC01-5531C85EE47A}.Debug|x86.ActiveCfg = Debug|Any CPU + {F57F6152-A359-4BB5-AC01-5531C85EE47A}.Debug|x86.Build.0 = Debug|Any CPU + {F57F6152-A359-4BB5-AC01-5531C85EE47A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F57F6152-A359-4BB5-AC01-5531C85EE47A}.Release|Any CPU.Build.0 = Release|Any CPU + {F57F6152-A359-4BB5-AC01-5531C85EE47A}.Release|x64.ActiveCfg = Release|Any CPU + {F57F6152-A359-4BB5-AC01-5531C85EE47A}.Release|x64.Build.0 = Release|Any CPU + {F57F6152-A359-4BB5-AC01-5531C85EE47A}.Release|x86.ActiveCfg = Release|Any CPU + {F57F6152-A359-4BB5-AC01-5531C85EE47A}.Release|x86.Build.0 = Release|Any CPU + {32631ED6-956A-4572-AD7A-B8D0ECE26C78}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {32631ED6-956A-4572-AD7A-B8D0ECE26C78}.Debug|Any CPU.Build.0 = Debug|Any CPU + {32631ED6-956A-4572-AD7A-B8D0ECE26C78}.Debug|x64.ActiveCfg = Debug|Any CPU + {32631ED6-956A-4572-AD7A-B8D0ECE26C78}.Debug|x64.Build.0 = Debug|Any CPU + {32631ED6-956A-4572-AD7A-B8D0ECE26C78}.Debug|x86.ActiveCfg = Debug|Any CPU + {32631ED6-956A-4572-AD7A-B8D0ECE26C78}.Debug|x86.Build.0 = Debug|Any CPU + {32631ED6-956A-4572-AD7A-B8D0ECE26C78}.Release|Any CPU.ActiveCfg = Release|Any CPU + {32631ED6-956A-4572-AD7A-B8D0ECE26C78}.Release|Any CPU.Build.0 = Release|Any CPU + {32631ED6-956A-4572-AD7A-B8D0ECE26C78}.Release|x64.ActiveCfg = Release|Any CPU + {32631ED6-956A-4572-AD7A-B8D0ECE26C78}.Release|x64.Build.0 = Release|Any CPU + {32631ED6-956A-4572-AD7A-B8D0ECE26C78}.Release|x86.ActiveCfg = Release|Any CPU + {32631ED6-956A-4572-AD7A-B8D0ECE26C78}.Release|x86.Build.0 = Release|Any CPU + {7E22E87D-78D2-411D-AC30-2F090C3F5ED5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7E22E87D-78D2-411D-AC30-2F090C3F5ED5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7E22E87D-78D2-411D-AC30-2F090C3F5ED5}.Debug|x64.ActiveCfg = Debug|Any CPU + {7E22E87D-78D2-411D-AC30-2F090C3F5ED5}.Debug|x64.Build.0 = Debug|Any CPU + {7E22E87D-78D2-411D-AC30-2F090C3F5ED5}.Debug|x86.ActiveCfg = Debug|Any CPU + {7E22E87D-78D2-411D-AC30-2F090C3F5ED5}.Debug|x86.Build.0 = Debug|Any CPU + {7E22E87D-78D2-411D-AC30-2F090C3F5ED5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7E22E87D-78D2-411D-AC30-2F090C3F5ED5}.Release|Any CPU.Build.0 = Release|Any CPU + {7E22E87D-78D2-411D-AC30-2F090C3F5ED5}.Release|x64.ActiveCfg = Release|Any CPU + {7E22E87D-78D2-411D-AC30-2F090C3F5ED5}.Release|x64.Build.0 = Release|Any CPU + {7E22E87D-78D2-411D-AC30-2F090C3F5ED5}.Release|x86.ActiveCfg = Release|Any CPU + {7E22E87D-78D2-411D-AC30-2F090C3F5ED5}.Release|x86.Build.0 = Release|Any CPU + {623330CA-6CA5-4B74-A921-DEAE8002FCC5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {623330CA-6CA5-4B74-A921-DEAE8002FCC5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {623330CA-6CA5-4B74-A921-DEAE8002FCC5}.Debug|x64.ActiveCfg = Debug|Any CPU + {623330CA-6CA5-4B74-A921-DEAE8002FCC5}.Debug|x64.Build.0 = Debug|Any CPU + {623330CA-6CA5-4B74-A921-DEAE8002FCC5}.Debug|x86.ActiveCfg = Debug|Any CPU + {623330CA-6CA5-4B74-A921-DEAE8002FCC5}.Debug|x86.Build.0 = Debug|Any CPU + {623330CA-6CA5-4B74-A921-DEAE8002FCC5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {623330CA-6CA5-4B74-A921-DEAE8002FCC5}.Release|Any CPU.Build.0 = Release|Any CPU + {623330CA-6CA5-4B74-A921-DEAE8002FCC5}.Release|x64.ActiveCfg = Release|Any CPU + {623330CA-6CA5-4B74-A921-DEAE8002FCC5}.Release|x64.Build.0 = Release|Any CPU + {623330CA-6CA5-4B74-A921-DEAE8002FCC5}.Release|x86.ActiveCfg = Release|Any CPU + {623330CA-6CA5-4B74-A921-DEAE8002FCC5}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -688,5 +872,19 @@ Global {553D81D4-666B-BE26-75F9-480CB214ACEE} = {0AB3BF05-4346-4AA6-1389-037BE0695223} {3A48F700-9635-2216-D291-85337CE5D869} = {553D81D4-666B-BE26-75F9-480CB214ACEE} {6BD8DC02-2270-4276-952E-E34E973A1237} = {3A48F700-9635-2216-D291-85337CE5D869} + {FFBE31B8-50B9-B415-22BC-2F92C97CADA3} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B} + {1D50E7AA-2378-4114-A3C3-E351D46FB8BF} = {FFBE31B8-50B9-B415-22BC-2F92C97CADA3} + {E8C0F163-735D-44A2-B684-673A0B0D7D2A} = {FFBE31B8-50B9-B415-22BC-2F92C97CADA3} + {65E67218-A02C-4C42-8B60-6FDAB737E613} = {FFBE31B8-50B9-B415-22BC-2F92C97CADA3} + {7226D94C-B9A5-41D7-9E59-50A68F39EE78} = {FFBE31B8-50B9-B415-22BC-2F92C97CADA3} + {4AC0C433-475F-4B0C-B160-E4F33779E3CB} = {FFBE31B8-50B9-B415-22BC-2F92C97CADA3} + {9D86914A-43A8-4451-BEFD-092ABFF793D6} = {FFBE31B8-50B9-B415-22BC-2F92C97CADA3} + {1DC69DD3-3348-4375-844C-D44A760D50EC} = {FFBE31B8-50B9-B415-22BC-2F92C97CADA3} + {352A455F-AC3F-4D34-BADA-574BF83E131C} = {FFBE31B8-50B9-B415-22BC-2F92C97CADA3} + {D10F0FA0-A682-42D4-A23F-46094D14A8F6} = {FFBE31B8-50B9-B415-22BC-2F92C97CADA3} + {F57F6152-A359-4BB5-AC01-5531C85EE47A} = {FFBE31B8-50B9-B415-22BC-2F92C97CADA3} + {32631ED6-956A-4572-AD7A-B8D0ECE26C78} = {FFBE31B8-50B9-B415-22BC-2F92C97CADA3} + {7E22E87D-78D2-411D-AC30-2F090C3F5ED5} = {FFBE31B8-50B9-B415-22BC-2F92C97CADA3} + {623330CA-6CA5-4B74-A921-DEAE8002FCC5} = {FFBE31B8-50B9-B415-22BC-2F92C97CADA3} EndGlobalSection EndGlobal diff --git a/backend/Tests/Admin/UnitTests/ResetUserPasswordCommandHandlerTests.cs b/backend/Tests/Admin/UnitTests/ResetUserPasswordCommandHandlerTests.cs index 3c27630..56e5e12 100644 --- a/backend/Tests/Admin/UnitTests/ResetUserPasswordCommandHandlerTests.cs +++ b/backend/Tests/Admin/UnitTests/ResetUserPasswordCommandHandlerTests.cs @@ -1,7 +1,7 @@ using FluentAssertions; using Knot.Modules.Admin.Application.Admin.Commands; -using Knot.Modules.Auth.Application.Abstractions; -using Knot.Modules.Auth.Domain; +using Knot.Modules.Auth.Contracts.Application.Abstractions; +using Knot.Modules.Auth.Contracts.Domain; using Knot.Shared.Kernel; using NSubstitute; using Xunit; diff --git a/backend/Tests/Auth/UnitTests/LoginUserCommandHandlerTests.cs b/backend/Tests/Auth/UnitTests/LoginUserCommandHandlerTests.cs index 518e53d..40c5272 100644 --- a/backend/Tests/Auth/UnitTests/LoginUserCommandHandlerTests.cs +++ b/backend/Tests/Auth/UnitTests/LoginUserCommandHandlerTests.cs @@ -1,8 +1,8 @@ using FluentAssertions; using NSubstitute; -using Knot.Modules.Auth.Application.Abstractions; +using Knot.Modules.Auth.Contracts.Application.Abstractions; using Knot.Modules.Auth.Application.Users.Login; -using Knot.Modules.Auth.Domain; +using Knot.Modules.Auth.Contracts.Domain; using Knot.Shared.Kernel; using Knot.Modules.Auth.Application.Users.Auth; using Xunit; diff --git a/backend/Tests/Conversations/UnitTests/Messages/SendMessageCommandHandlerTests.cs b/backend/Tests/Conversations/UnitTests/Messages/SendMessageCommandHandlerTests.cs index 8e5192a..93cfd86 100644 --- a/backend/Tests/Conversations/UnitTests/Messages/SendMessageCommandHandlerTests.cs +++ b/backend/Tests/Conversations/UnitTests/Messages/SendMessageCommandHandlerTests.cs @@ -12,8 +12,8 @@ using Knot.Modules.Conversations.Domain; using Knot.Modules.Messaging.Domain; using Knot.Modules.Conversations.Application.Abstractions; using Knot.Modules.Conversations.Application.Messages.Send; -using Knot.Modules.Settings.Application.Settings.Abstractions; -using Knot.Modules.Settings.Application.Settings.DTOs; +using Knot.Modules.Settings.Contracts.Application.Abstractions; +using Knot.Modules.Settings.Contracts.Application.DTOs; namespace Knot.Modules.Conversations.UnitTests.Messages; @@ -34,7 +34,7 @@ public class SendMessageCommandHandlerTests _mediator = Substitute.For(); _messagesSettings = Substitute.For(); - var config = new Knot.Modules.Settings.Application.Settings.DTOs.MessagesConfig(); + var config = new Knot.Modules.Settings.Contracts.Application.DTOs.MessagesConfig(); _messagesSettings.Current.Returns(config); _handler = new SendMessageCommandHandler(_chatRepository, _messageRepository, _unitOfWork, _mediator, _messagesSettings); diff --git a/backend/Tests/Stories/UnitTests/CreateStoryCommandHandlerTests.cs b/backend/Tests/Stories/UnitTests/CreateStoryCommandHandlerTests.cs index 604e657..c9f52f2 100644 --- a/backend/Tests/Stories/UnitTests/CreateStoryCommandHandlerTests.cs +++ b/backend/Tests/Stories/UnitTests/CreateStoryCommandHandlerTests.cs @@ -2,8 +2,8 @@ using FluentAssertions; using Knot.Modules.Stories.Application.Stories.Commands.CreateStory; using Knot.Modules.Stories.Domain; using Knot.Shared.Kernel; -using Knot.Modules.Settings.Application.Settings.Abstractions; -using Knot.Modules.Settings.Application.Settings.DTOs; +using Knot.Modules.Settings.Contracts.Application.Abstractions; +using Knot.Modules.Settings.Contracts.Application.DTOs; using Knot.Modules.Stories.Application.Abstractions; using NSubstitute; using Xunit; diff --git a/backend/Tests/Users/UnitTests/UpdateProfileCommandHandlerTests.cs b/backend/Tests/Users/UnitTests/UpdateProfileCommandHandlerTests.cs index 3739a53..f4628f0 100644 --- a/backend/Tests/Users/UnitTests/UpdateProfileCommandHandlerTests.cs +++ b/backend/Tests/Users/UnitTests/UpdateProfileCommandHandlerTests.cs @@ -1,13 +1,13 @@ using FluentAssertions; using Knot.Modules.Profiles.Application.Profiles.UpdateProfile; -using Knot.Modules.Profiles.Domain; +using Knot.Modules.Profiles.Contracts.Domain; +using Knot.Modules.Profiles.Contracts.Application.DTOs; using Knot.Shared.Kernel; using NSubstitute; using Xunit; using System; using System.Threading; using System.Threading.Tasks; -using Knot.Modules.Profiles.Application.Abstractions; namespace Knot.Modules.Profiles.UnitTests; @@ -27,7 +27,7 @@ public class UpdateProfileCommandHandlerTests { // Arrange var command = new UpdateProfileCommand(Guid.NewGuid(), "FirstName", "Bio", null); - _profileRepository.GetByIdAsync(command.UserId, Arg.Any()).Returns((ProfileDocument?)null); + _profileRepository.GetAsync(command.UserId, Arg.Any()).Returns((UserProfileDto?)null); // Act var result = await _handler.Handle(command, CancellationToken.None); diff --git a/backend/src/Contracts/Knot.Modules.Admin.Contracts/Knot.Modules.Admin.Contracts.csproj b/backend/src/Contracts/Knot.Modules.Admin.Contracts/Knot.Modules.Admin.Contracts.csproj new file mode 100644 index 0000000..52a2860 --- /dev/null +++ b/backend/src/Contracts/Knot.Modules.Admin.Contracts/Knot.Modules.Admin.Contracts.csproj @@ -0,0 +1,17 @@ + + + + net10.0 + enable + enable + + + + + + + + + + + diff --git a/backend/src/Contracts/Knot.Modules.Auth.Contracts/Application/Abstractions/IAuthDbContext.cs b/backend/src/Contracts/Knot.Modules.Auth.Contracts/Application/Abstractions/IAuthDbContext.cs new file mode 100644 index 0000000..4dfd3b4 --- /dev/null +++ b/backend/src/Contracts/Knot.Modules.Auth.Contracts/Application/Abstractions/IAuthDbContext.cs @@ -0,0 +1,9 @@ +using Microsoft.EntityFrameworkCore; + +namespace Knot.Modules.Auth.Contracts.Application.Abstractions; + +public interface IAuthDbContext +{ + DbSet Set() where T : class; + Task SaveChangesAsync(CancellationToken cancellationToken = default); +} diff --git a/backend/src/Contracts/Knot.Modules.Auth.Contracts/Application/Abstractions/IAuthUnitOfWork.cs b/backend/src/Contracts/Knot.Modules.Auth.Contracts/Application/Abstractions/IAuthUnitOfWork.cs new file mode 100644 index 0000000..6c4134a --- /dev/null +++ b/backend/src/Contracts/Knot.Modules.Auth.Contracts/Application/Abstractions/IAuthUnitOfWork.cs @@ -0,0 +1,11 @@ +using Knot.Modules.Auth.Contracts.Domain; +using Knot.Shared.Kernel; + +namespace Knot.Modules.Auth.Contracts.Application.Abstractions; + +public interface IAuthUnitOfWork : IUnitOfWork +{ + IUserRepository UserRepository { get; } + void Add(UserContract user); + Task SaveChangesAsync(CancellationToken ct = default); +} diff --git a/backend/src/Contracts/Knot.Modules.Auth.Contracts/Application/Abstractions/IIdentityDbContext.cs b/backend/src/Contracts/Knot.Modules.Auth.Contracts/Application/Abstractions/IIdentityDbContext.cs new file mode 100644 index 0000000..d4b4ea4 --- /dev/null +++ b/backend/src/Contracts/Knot.Modules.Auth.Contracts/Application/Abstractions/IIdentityDbContext.cs @@ -0,0 +1,9 @@ +using Microsoft.EntityFrameworkCore; + +namespace Knot.Modules.Auth.Contracts.Application.Abstractions; + +public interface IIdentityDbContext +{ + DbSet Set() where T : class; + Task SaveChangesAsync(CancellationToken cancellationToken = default); +} diff --git a/backend/src/Contracts/Knot.Modules.Auth.Contracts/Application/Abstractions/IIdentityUnitOfWork.cs b/backend/src/Contracts/Knot.Modules.Auth.Contracts/Application/Abstractions/IIdentityUnitOfWork.cs new file mode 100644 index 0000000..b136d06 --- /dev/null +++ b/backend/src/Contracts/Knot.Modules.Auth.Contracts/Application/Abstractions/IIdentityUnitOfWork.cs @@ -0,0 +1,9 @@ +using Knot.Modules.Auth.Contracts.Domain; +using Knot.Shared.Kernel; + +namespace Knot.Modules.Auth.Contracts.Application.Abstractions; + +public interface IIdentityUnitOfWork : IUnitOfWork +{ + IUserRepository UserRepository { get; } +} diff --git a/backend/src/Contracts/Knot.Modules.Auth.Contracts/Application/Abstractions/IJwtTokenProvider.cs b/backend/src/Contracts/Knot.Modules.Auth.Contracts/Application/Abstractions/IJwtTokenProvider.cs new file mode 100644 index 0000000..454e45f --- /dev/null +++ b/backend/src/Contracts/Knot.Modules.Auth.Contracts/Application/Abstractions/IJwtTokenProvider.cs @@ -0,0 +1,8 @@ +namespace Knot.Modules.Auth.Contracts.Application.Abstractions; + +public interface IJwtTokenProvider +{ + string GenerateAccessToken(Guid userId, string username); + string GenerateRefreshToken(); + string Generate(Guid userId, string username, string displayName, string? avatar); +} diff --git a/backend/src/Contracts/Knot.Modules.Auth.Contracts/Application/Auth/DTOs/AuthErrors.cs b/backend/src/Contracts/Knot.Modules.Auth.Contracts/Application/Auth/DTOs/AuthErrors.cs new file mode 100644 index 0000000..217647b --- /dev/null +++ b/backend/src/Contracts/Knot.Modules.Auth.Contracts/Application/Auth/DTOs/AuthErrors.cs @@ -0,0 +1,11 @@ +using Knot.Shared.Kernel; + +namespace Knot.Modules.Auth.Contracts.Application.Auth.DTOs; + +public static class AuthErrors +{ + public static Error IdentityInvalidCredentials => new("Auth.InvalidCredentials", "Invalid credentials"); + public static Error IdentityRegistrationDisabled => new("Auth.RegistrationDisabled", "Registration is disabled"); + public static Error IdentityUsernameNotUnique => new("Auth.UsernameNotUnique", "Username is already taken"); + public static Error UserNotFound => new("Auth.UserNotFound", "User not found"); +} diff --git a/backend/src/Contracts/Knot.Modules.Auth.Contracts/Application/Auth/DTOs/AuthResponseDto.cs b/backend/src/Contracts/Knot.Modules.Auth.Contracts/Application/Auth/DTOs/AuthResponseDto.cs new file mode 100644 index 0000000..b2f6b75 --- /dev/null +++ b/backend/src/Contracts/Knot.Modules.Auth.Contracts/Application/Auth/DTOs/AuthResponseDto.cs @@ -0,0 +1,16 @@ +namespace Knot.Modules.Auth.Contracts.Application.Auth.DTOs; + +public class AuthResponseDto +{ + public required string AccessToken { get; set; } + public required string RefreshToken { get; set; } + public Guid UserId { get; set; } + public string Username { get; set; } = string.Empty; + public string? DisplayName { get; set; } +} + +public class ResetPasswordDto +{ + public required string Token { get; set; } + public required string NewPassword { get; set; } +} diff --git a/backend/src/Contracts/Knot.Modules.Auth.Contracts/Application/Users/GetMe/GetMeQuery.cs b/backend/src/Contracts/Knot.Modules.Auth.Contracts/Application/Users/GetMe/GetMeQuery.cs new file mode 100644 index 0000000..93cf6d6 --- /dev/null +++ b/backend/src/Contracts/Knot.Modules.Auth.Contracts/Application/Users/GetMe/GetMeQuery.cs @@ -0,0 +1,6 @@ +using Knot.Modules.Auth.Contracts.Domain; +using MediatR; + +namespace Knot.Modules.Auth.Contracts.Application.Users.GetMe; + +public record GetMeQuery() : IRequest; diff --git a/backend/src/Contracts/Knot.Modules.Auth.Contracts/Application/Users/Login/LoginUserCommand.cs b/backend/src/Contracts/Knot.Modules.Auth.Contracts/Application/Users/Login/LoginUserCommand.cs new file mode 100644 index 0000000..052fde4 --- /dev/null +++ b/backend/src/Contracts/Knot.Modules.Auth.Contracts/Application/Users/Login/LoginUserCommand.cs @@ -0,0 +1,10 @@ +using Knot.Modules.Auth.Contracts.Application.Auth.DTOs; +using Knot.Shared.Kernel; +using MediatR; + +namespace Knot.Modules.Auth.Contracts.Application.Users.Login; + +public record LoginUserCommand( + string Username, + string Password +) : IRequest>; diff --git a/backend/src/Contracts/Knot.Modules.Auth.Contracts/Application/Users/Register/RegisterUserCommand.cs b/backend/src/Contracts/Knot.Modules.Auth.Contracts/Application/Users/Register/RegisterUserCommand.cs new file mode 100644 index 0000000..75e9bd5 --- /dev/null +++ b/backend/src/Contracts/Knot.Modules.Auth.Contracts/Application/Users/Register/RegisterUserCommand.cs @@ -0,0 +1,14 @@ +using Knot.Modules.Auth.Contracts.Application.Auth.DTOs; +using Knot.Modules.Auth.Contracts.Domain; +using Knot.Shared.Kernel; +using MediatR; + +namespace Knot.Modules.Auth.Contracts.Application.Users.Register; + +public record RegisterUserCommand( + string Username, + string Password, + string DisplayName, + string? PhoneNumber, + bool IsBot = false +) : IRequest>; diff --git a/backend/src/Contracts/Knot.Modules.Auth.Contracts/Domain/IUserRepository.cs b/backend/src/Contracts/Knot.Modules.Auth.Contracts/Domain/IUserRepository.cs new file mode 100644 index 0000000..43ff025 --- /dev/null +++ b/backend/src/Contracts/Knot.Modules.Auth.Contracts/Domain/IUserRepository.cs @@ -0,0 +1,16 @@ +namespace Knot.Modules.Auth.Contracts.Domain; + +public interface IUserRepository +{ + Task GetByIdAsync(Guid id, CancellationToken cancellationToken = default); + Task> GetByIdsAsync(IEnumerable ids, CancellationToken cancellationToken = default); + Task GetByUsernameAsync(string username, CancellationToken cancellationToken = default); + Task IsUsernameUniqueAsync(string username, CancellationToken cancellationToken = default); + Task> SearchUsersAsync(string query, CancellationToken cancellationToken = default); + Task IsBannedAsync(Guid userId, CancellationToken cancellationToken = default); + Task GetByRefreshTokenAsync(string refreshToken, CancellationToken cancellationToken = default); + Task UpdateAsync(UserContract user, CancellationToken cancellationToken = default); + void Add(UserContract user); + Task RemoveAsync(UserContract user, CancellationToken cancellationToken = default); + void Update(UserContract user); +} diff --git a/backend/src/Contracts/Knot.Modules.Auth.Contracts/Domain/UserContract.cs b/backend/src/Contracts/Knot.Modules.Auth.Contracts/Domain/UserContract.cs new file mode 100644 index 0000000..b4b2ff3 --- /dev/null +++ b/backend/src/Contracts/Knot.Modules.Auth.Contracts/Domain/UserContract.cs @@ -0,0 +1,22 @@ +namespace Knot.Modules.Auth.Contracts.Domain; + +public class UserContract +{ + public Guid Id { get; set; } + public string Username { get; set; } = string.Empty; + public string DisplayName { get; set; } = string.Empty; + public string PasswordHash { get; set; } = string.Empty; + public string? PhoneNumber { get; set; } + public string? Email { get; set; } + public string? Bio { get; set; } + public string? Avatar { get; set; } + public DateTime? Birthday { get; set; } + public bool IsBot { get; set; } + public DateTime CreatedAt { get; set; } + public DateTime? BannedUntil { get; set; } + public bool IsBanned { get; set; } + public bool IsOnline { get; set; } + public bool IsExternal { get; set; } + public string? Domain { get; set; } + public DateTime? LastSeen { get; set; } +} diff --git a/backend/src/Contracts/Knot.Modules.Auth.Contracts/Knot.Modules.Auth.Contracts.csproj b/backend/src/Contracts/Knot.Modules.Auth.Contracts/Knot.Modules.Auth.Contracts.csproj new file mode 100644 index 0000000..4bd9c60 --- /dev/null +++ b/backend/src/Contracts/Knot.Modules.Auth.Contracts/Knot.Modules.Auth.Contracts.csproj @@ -0,0 +1,18 @@ + + + + net10.0 + enable + enable + + + + + + + + + + + + diff --git a/backend/src/Contracts/Knot.Modules.Conversations.Contracts/Knot.Modules.Conversations.Contracts.csproj b/backend/src/Contracts/Knot.Modules.Conversations.Contracts/Knot.Modules.Conversations.Contracts.csproj new file mode 100644 index 0000000..52a2860 --- /dev/null +++ b/backend/src/Contracts/Knot.Modules.Conversations.Contracts/Knot.Modules.Conversations.Contracts.csproj @@ -0,0 +1,17 @@ + + + + net10.0 + enable + enable + + + + + + + + + + + diff --git a/backend/src/Contracts/Knot.Modules.Federation.Contracts/Knot.Modules.Federation.Contracts.csproj b/backend/src/Contracts/Knot.Modules.Federation.Contracts/Knot.Modules.Federation.Contracts.csproj new file mode 100644 index 0000000..52a2860 --- /dev/null +++ b/backend/src/Contracts/Knot.Modules.Federation.Contracts/Knot.Modules.Federation.Contracts.csproj @@ -0,0 +1,17 @@ + + + + net10.0 + enable + enable + + + + + + + + + + + diff --git a/backend/src/Contracts/Knot.Modules.Klipy.Contracts/Knot.Modules.Klipy.Contracts.csproj b/backend/src/Contracts/Knot.Modules.Klipy.Contracts/Knot.Modules.Klipy.Contracts.csproj new file mode 100644 index 0000000..52a2860 --- /dev/null +++ b/backend/src/Contracts/Knot.Modules.Klipy.Contracts/Knot.Modules.Klipy.Contracts.csproj @@ -0,0 +1,17 @@ + + + + net10.0 + enable + enable + + + + + + + + + + + diff --git a/backend/src/Contracts/Knot.Modules.Messaging.Contracts/Knot.Modules.Messaging.Contracts.csproj b/backend/src/Contracts/Knot.Modules.Messaging.Contracts/Knot.Modules.Messaging.Contracts.csproj new file mode 100644 index 0000000..52a2860 --- /dev/null +++ b/backend/src/Contracts/Knot.Modules.Messaging.Contracts/Knot.Modules.Messaging.Contracts.csproj @@ -0,0 +1,17 @@ + + + + net10.0 + enable + enable + + + + + + + + + + + diff --git a/backend/src/Contracts/Knot.Modules.Profiles.Contracts/Application/DTOs/ProfilesErrors.cs b/backend/src/Contracts/Knot.Modules.Profiles.Contracts/Application/DTOs/ProfilesErrors.cs new file mode 100644 index 0000000..0c0639f --- /dev/null +++ b/backend/src/Contracts/Knot.Modules.Profiles.Contracts/Application/DTOs/ProfilesErrors.cs @@ -0,0 +1,12 @@ +using Knot.Shared.Kernel; + +namespace Knot.Modules.Profiles.Contracts.Application.DTOs; + +public static class ProfilesErrors +{ + public static Error ProfileNotFound => new("Profiles.NotFound", "Profile not found"); + public static Error UsernameAlreadyExists => new("Profiles.UsernameExists", "Username already exists"); + public static Error AvatarNotFound => new("Profiles.AvatarNotFound", "Avatar not found"); + public static Error InvalidAvatarFormat => new("Profiles.InvalidAvatarFormat", "Invalid avatar format"); + public static Error AvatarUploadFailed => new("Profiles.AvatarUploadFailed", "Avatar upload failed"); +} diff --git a/backend/src/Contracts/Knot.Modules.Profiles.Contracts/Application/DTOs/ProfilesRequests.cs b/backend/src/Contracts/Knot.Modules.Profiles.Contracts/Application/DTOs/ProfilesRequests.cs new file mode 100644 index 0000000..eaeeb88 --- /dev/null +++ b/backend/src/Contracts/Knot.Modules.Profiles.Contracts/Application/DTOs/ProfilesRequests.cs @@ -0,0 +1,21 @@ +using MediatR; + +namespace Knot.Modules.Profiles.Contracts.Application.DTOs; + +public record SearchProfilesRequest(string Query, int Limit = 20) : IRequest>; + +public record UpdateProfileRequest( + string? DisplayName, + string? About, + string? Avatar, + bool RemoveAvatar = false +) : IRequest; + +public record UpdateSettingsRequest( + bool? ShowLastSeen, + bool? ShowAvatar, + bool? ShowAbout, + bool? ShowPhoneNumber, + bool? ShowForwardedMessages, + bool? ShowAddToGroupPermission +) : IRequest; diff --git a/backend/src/Contracts/Knot.Modules.Profiles.Contracts/Application/DTOs/UserProfileDto.cs b/backend/src/Contracts/Knot.Modules.Profiles.Contracts/Application/DTOs/UserProfileDto.cs new file mode 100644 index 0000000..4b75ecb --- /dev/null +++ b/backend/src/Contracts/Knot.Modules.Profiles.Contracts/Application/DTOs/UserProfileDto.cs @@ -0,0 +1,14 @@ +namespace Knot.Modules.Profiles.Contracts.Application.DTOs; + +public class UserProfileDto +{ + public Guid UserId { get; set; } + public string? DisplayName { get; set; } + public string? Username { get; set; } + public string? About { get; set; } + public string? Avatar { get; set; } + public bool IsBot { get; set; } + public DateTime? LastSeen { get; set; } + public bool IsPremium { get; set; } + public DateTime CreatedAt { get; set; } +} diff --git a/backend/src/Contracts/Knot.Modules.Profiles.Contracts/Application/Profiles/Avatar/UploadAvatar.cs b/backend/src/Contracts/Knot.Modules.Profiles.Contracts/Application/Profiles/Avatar/UploadAvatar.cs new file mode 100644 index 0000000..59d9e2f --- /dev/null +++ b/backend/src/Contracts/Knot.Modules.Profiles.Contracts/Application/Profiles/Avatar/UploadAvatar.cs @@ -0,0 +1,10 @@ +using Knot.Shared.Kernel; +using MediatR; + +namespace Knot.Modules.Profiles.Contracts.Application.Profiles.Avatar; + +public record UploadAvatarCommand(Stream Stream, string FileName) : IRequest>; + +public record DeleteAvatarCommand() : IRequest; + +public record CropAvatarCommand(int X, int Y, int Width, int Height) : IRequest>; diff --git a/backend/src/Contracts/Knot.Modules.Profiles.Contracts/Application/Profiles/GetUser/GetProfile.cs b/backend/src/Contracts/Knot.Modules.Profiles.Contracts/Application/Profiles/GetUser/GetProfile.cs new file mode 100644 index 0000000..4975f21 --- /dev/null +++ b/backend/src/Contracts/Knot.Modules.Profiles.Contracts/Application/Profiles/GetUser/GetProfile.cs @@ -0,0 +1,9 @@ +using Knot.Modules.Profiles.Contracts.Application.DTOs; +using Knot.Shared.Kernel; +using MediatR; + +namespace Knot.Modules.Profiles.Contracts.Application.Profiles.GetUser; + +public record GetProfileQuery(Guid UserId) : IRequest>; + +public record GetCurrentUserQuery() : IRequest>; diff --git a/backend/src/Contracts/Knot.Modules.Profiles.Contracts/Application/Profiles/Search/SearchUsers.cs b/backend/src/Contracts/Knot.Modules.Profiles.Contracts/Application/Profiles/Search/SearchUsers.cs new file mode 100644 index 0000000..bfe8793 --- /dev/null +++ b/backend/src/Contracts/Knot.Modules.Profiles.Contracts/Application/Profiles/Search/SearchUsers.cs @@ -0,0 +1,6 @@ +using Knot.Modules.Profiles.Contracts.Application.DTOs; +using MediatR; + +namespace Knot.Modules.Profiles.Contracts.Application.Profiles.Search; + +public record SearchProfilesQuery(string Query, int Limit = 20) : IRequest>; diff --git a/backend/src/Contracts/Knot.Modules.Profiles.Contracts/Application/Profiles/UpdateProfile/UpdateProfile.cs b/backend/src/Contracts/Knot.Modules.Profiles.Contracts/Application/Profiles/UpdateProfile/UpdateProfile.cs new file mode 100644 index 0000000..58abd25 --- /dev/null +++ b/backend/src/Contracts/Knot.Modules.Profiles.Contracts/Application/Profiles/UpdateProfile/UpdateProfile.cs @@ -0,0 +1,12 @@ +using Knot.Modules.Profiles.Contracts.Application.DTOs; +using Knot.Shared.Kernel; +using MediatR; + +namespace Knot.Modules.Profiles.Contracts.Application.Profiles.UpdateProfile; + +public record UpdateProfileCommand( + string? DisplayName, + string? About, + string? Avatar, + bool RemoveAvatar = false +) : IRequest>; diff --git a/backend/src/Contracts/Knot.Modules.Profiles.Contracts/Application/Profiles/UpdateSettings/UpdateSettings.cs b/backend/src/Contracts/Knot.Modules.Profiles.Contracts/Application/Profiles/UpdateSettings/UpdateSettings.cs new file mode 100644 index 0000000..a0adfd2 --- /dev/null +++ b/backend/src/Contracts/Knot.Modules.Profiles.Contracts/Application/Profiles/UpdateSettings/UpdateSettings.cs @@ -0,0 +1,14 @@ +using Knot.Modules.Profiles.Contracts.Application.DTOs; +using Knot.Shared.Kernel; +using MediatR; + +namespace Knot.Modules.Profiles.Contracts.Application.Profiles.UpdateSettings; + +public record UpdateSettingsCommand( + bool? ShowLastSeen, + bool? ShowAvatar, + bool? ShowAbout, + bool? ShowPhoneNumber, + bool? ShowForwardedMessages, + bool? ShowAddToGroupPermission +) : IRequest>; diff --git a/backend/src/Contracts/Knot.Modules.Profiles.Contracts/Domain/IAvatarStorageService.cs b/backend/src/Contracts/Knot.Modules.Profiles.Contracts/Domain/IAvatarStorageService.cs new file mode 100644 index 0000000..c348ed8 --- /dev/null +++ b/backend/src/Contracts/Knot.Modules.Profiles.Contracts/Domain/IAvatarStorageService.cs @@ -0,0 +1,11 @@ +using Knot.Shared.Kernel.Storage; + +namespace Knot.Modules.Profiles.Contracts.Domain; + +public interface IAvatarStorageService +{ + Task UploadAsync(Stream stream, string fileName, string contentType, CancellationToken cancellationToken = default); + Task DeleteAsync(string fileKey, CancellationToken cancellationToken = default); + Task GetAsync(string fileKey, CancellationToken cancellationToken = default); + string GetFileUrl(string fileKey); +} diff --git a/backend/src/Contracts/Knot.Modules.Profiles.Contracts/Domain/IProfileRepository.cs b/backend/src/Contracts/Knot.Modules.Profiles.Contracts/Domain/IProfileRepository.cs new file mode 100644 index 0000000..5445bb2 --- /dev/null +++ b/backend/src/Contracts/Knot.Modules.Profiles.Contracts/Domain/IProfileRepository.cs @@ -0,0 +1,15 @@ +using Knot.Modules.Profiles.Contracts.Application.DTOs; +using Knot.Shared.Kernel; + +namespace Knot.Modules.Profiles.Contracts.Domain; + +public interface IProfileRepository +{ + Task GetAsync(Guid userId, CancellationToken cancellationToken = default); + Task GetByUsernameAsync(string username, CancellationToken cancellationToken = default); + Task> GetAsync(IEnumerable userIds, CancellationToken cancellationToken = default); + Task> SearchAsync(string query, int limit = 20, CancellationToken cancellationToken = default); + Task> CreateAsync(UserProfileDto dto, CancellationToken cancellationToken = default); + Task> UpdateAsync(UserProfileDto dto, CancellationToken cancellationToken = default); + Task DeleteAsync(Guid userId, CancellationToken cancellationToken = default); +} diff --git a/backend/src/Contracts/Knot.Modules.Profiles.Contracts/Domain/IProfilesUnitOfWork.cs b/backend/src/Contracts/Knot.Modules.Profiles.Contracts/Domain/IProfilesUnitOfWork.cs new file mode 100644 index 0000000..9ebc664 --- /dev/null +++ b/backend/src/Contracts/Knot.Modules.Profiles.Contracts/Domain/IProfilesUnitOfWork.cs @@ -0,0 +1,8 @@ +using Knot.Shared.Kernel; + +namespace Knot.Modules.Profiles.Contracts.Domain; + +public interface IProfilesUnitOfWork : IUnitOfWork +{ + IProfileRepository ProfileRepository { get; } +} diff --git a/backend/src/Contracts/Knot.Modules.Profiles.Contracts/Knot.Modules.Profiles.Contracts.csproj b/backend/src/Contracts/Knot.Modules.Profiles.Contracts/Knot.Modules.Profiles.Contracts.csproj new file mode 100644 index 0000000..52a2860 --- /dev/null +++ b/backend/src/Contracts/Knot.Modules.Profiles.Contracts/Knot.Modules.Profiles.Contracts.csproj @@ -0,0 +1,17 @@ + + + + net10.0 + enable + enable + + + + + + + + + + + diff --git a/backend/src/Contracts/Knot.Modules.Relations.Contracts/Knot.Modules.Relations.Contracts.csproj b/backend/src/Contracts/Knot.Modules.Relations.Contracts/Knot.Modules.Relations.Contracts.csproj new file mode 100644 index 0000000..52a2860 --- /dev/null +++ b/backend/src/Contracts/Knot.Modules.Relations.Contracts/Knot.Modules.Relations.Contracts.csproj @@ -0,0 +1,17 @@ + + + + net10.0 + enable + enable + + + + + + + + + + + diff --git a/backend/src/Modules/Settings/Application/Settings/Abstractions/ISettingsService.cs b/backend/src/Contracts/Knot.Modules.Settings.Contracts/Application/Abstractions/ISettingsService.cs similarity index 83% rename from backend/src/Modules/Settings/Application/Settings/Abstractions/ISettingsService.cs rename to backend/src/Contracts/Knot.Modules.Settings.Contracts/Application/Abstractions/ISettingsService.cs index 46cef1d..0019d9d 100644 --- a/backend/src/Modules/Settings/Application/Settings/Abstractions/ISettingsService.cs +++ b/backend/src/Contracts/Knot.Modules.Settings.Contracts/Application/Abstractions/ISettingsService.cs @@ -1,8 +1,6 @@ -using System.Threading; -using System.Threading.Tasks; -using Knot.Modules.Settings.Application.Settings.DTOs; +using Knot.Modules.Settings.Contracts.Application.DTOs; -namespace Knot.Modules.Settings.Application.Settings.Abstractions; +namespace Knot.Modules.Settings.Contracts.Application.Abstractions; public interface ISettingsService { diff --git a/backend/src/Modules/Settings/Application/Settings/DTOs/SystemSettingsDto.cs b/backend/src/Contracts/Knot.Modules.Settings.Contracts/Application/DTOs/SystemSettingsDto.cs similarity index 95% rename from backend/src/Modules/Settings/Application/Settings/DTOs/SystemSettingsDto.cs rename to backend/src/Contracts/Knot.Modules.Settings.Contracts/Application/DTOs/SystemSettingsDto.cs index 96d6334..bcb08ef 100644 --- a/backend/src/Modules/Settings/Application/Settings/DTOs/SystemSettingsDto.cs +++ b/backend/src/Contracts/Knot.Modules.Settings.Contracts/Application/DTOs/SystemSettingsDto.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; -namespace Knot.Modules.Settings.Application.Settings.DTOs; +namespace Knot.Modules.Settings.Contracts.Application.DTOs; public class SystemConfig { @@ -25,7 +25,7 @@ public class ChatsConfig { public bool SupportGroups { get; set; } = true; public int MaxGroupParticipants { get; set; } = 200000; - public bool EnableAutoClean { get; set; } = false; // Возможность автоочистки для пользователей + public bool EnableAutoClean { get; set; } = false; public bool AllowChatToGroupConversion { get; set; } = true; public bool EnableFolders { get; set; } = true; } diff --git a/backend/src/Contracts/Knot.Modules.Settings.Contracts/Knot.Modules.Settings.Contracts.csproj b/backend/src/Contracts/Knot.Modules.Settings.Contracts/Knot.Modules.Settings.Contracts.csproj new file mode 100644 index 0000000..52a2860 --- /dev/null +++ b/backend/src/Contracts/Knot.Modules.Settings.Contracts/Knot.Modules.Settings.Contracts.csproj @@ -0,0 +1,17 @@ + + + + net10.0 + enable + enable + + + + + + + + + + + diff --git a/backend/src/Contracts/Knot.Modules.Storage.Contracts/Knot.Modules.Storage.Contracts.csproj b/backend/src/Contracts/Knot.Modules.Storage.Contracts/Knot.Modules.Storage.Contracts.csproj new file mode 100644 index 0000000..52a2860 --- /dev/null +++ b/backend/src/Contracts/Knot.Modules.Storage.Contracts/Knot.Modules.Storage.Contracts.csproj @@ -0,0 +1,17 @@ + + + + net10.0 + enable + enable + + + + + + + + + + + diff --git a/backend/src/Contracts/Knot.Modules.Stories.Contracts/Knot.Modules.Stories.Contracts.csproj b/backend/src/Contracts/Knot.Modules.Stories.Contracts/Knot.Modules.Stories.Contracts.csproj new file mode 100644 index 0000000..52a2860 --- /dev/null +++ b/backend/src/Contracts/Knot.Modules.Stories.Contracts/Knot.Modules.Stories.Contracts.csproj @@ -0,0 +1,17 @@ + + + + net10.0 + enable + enable + + + + + + + + + + + diff --git a/backend/src/Contracts/Knot.Modules.TelegramImport.Contracts/Knot.Modules.TelegramImport.Contracts.csproj b/backend/src/Contracts/Knot.Modules.TelegramImport.Contracts/Knot.Modules.TelegramImport.Contracts.csproj new file mode 100644 index 0000000..52a2860 --- /dev/null +++ b/backend/src/Contracts/Knot.Modules.TelegramImport.Contracts/Knot.Modules.TelegramImport.Contracts.csproj @@ -0,0 +1,17 @@ + + + + net10.0 + enable + enable + + + + + + + + + + + diff --git a/backend/src/Contracts/Knot.Modules.WebRtc.Contracts/Knot.Modules.WebRtc.Contracts.csproj b/backend/src/Contracts/Knot.Modules.WebRtc.Contracts/Knot.Modules.WebRtc.Contracts.csproj new file mode 100644 index 0000000..52a2860 --- /dev/null +++ b/backend/src/Contracts/Knot.Modules.WebRtc.Contracts/Knot.Modules.WebRtc.Contracts.csproj @@ -0,0 +1,17 @@ + + + + net10.0 + enable + enable + + + + + + + + + + + diff --git a/backend/src/Host/Host.csproj b/backend/src/Host/Host.csproj index a0ea507..39bc759 100644 --- a/backend/src/Host/Host.csproj +++ b/backend/src/Host/Host.csproj @@ -32,6 +32,7 @@ + @@ -39,7 +40,9 @@ + + diff --git a/backend/src/Host/Program.cs b/backend/src/Host/Program.cs index 36ab184..308e3c6 100644 --- a/backend/src/Host/Program.cs +++ b/backend/src/Host/Program.cs @@ -190,7 +190,7 @@ using (var scope = app.Services.CreateScope()) Knot.Modules.Messaging.Infrastructure.Persistence.Mongo.EncryptedStringSerializer.EncryptionService = encryptionService; // Initialize Global Settings Cache - var settingsService = scope.ServiceProvider.GetRequiredService(); + var settingsService = scope.ServiceProvider.GetRequiredService(); if (settingsService is Knot.Modules.Settings.Infrastructure.Configuration.SettingsService concreteSettings) { concreteSettings.Initialize(); diff --git a/backend/src/Modules/Admin/Application/Admin/Commands/BanUser/BanUserCommand.cs b/backend/src/Modules/Admin/Application/Admin/Commands/BanUser/BanUserCommand.cs index 19a1c22..0979dd8 100644 --- a/backend/src/Modules/Admin/Application/Admin/Commands/BanUser/BanUserCommand.cs +++ b/backend/src/Modules/Admin/Application/Admin/Commands/BanUser/BanUserCommand.cs @@ -1,10 +1,10 @@ -using Knot.Modules.Auth.Domain; +using Knot.Modules.Auth.Contracts.Domain; +using Knot.Modules.Auth.Contracts.Application.Abstractions; +using Knot.Shared.Kernel; using System; using System.Threading; using System.Threading.Tasks; using MediatR; -using Knot.Shared.Kernel; -using Knot.Modules.Auth.Application.Abstractions; namespace Knot.Modules.Admin.Application.Admin.Commands; @@ -26,7 +26,10 @@ internal sealed class BanUserCommandHandler : ICommandHandler(Error.NotFound("User.NotFound", "User not found")); - user.Ban(); + user.IsBanned = true; + user.BannedUntil = null; // Permanent ban + + await _userRepository.UpdateAsync(user, cancellationToken); await _unitOfWork.SaveChangesAsync(cancellationToken); return Result.Success(Result.Success()); } diff --git a/backend/src/Modules/Admin/Application/Admin/Commands/BanUser/UnbanUserCommand.cs b/backend/src/Modules/Admin/Application/Admin/Commands/BanUser/UnbanUserCommand.cs index 629e94d..26da2cc 100644 --- a/backend/src/Modules/Admin/Application/Admin/Commands/BanUser/UnbanUserCommand.cs +++ b/backend/src/Modules/Admin/Application/Admin/Commands/BanUser/UnbanUserCommand.cs @@ -1,10 +1,10 @@ -using Knot.Modules.Auth.Domain; +using Knot.Modules.Auth.Contracts.Domain; +using Knot.Modules.Auth.Contracts.Application.Abstractions; +using Knot.Shared.Kernel; using System; using System.Threading; using System.Threading.Tasks; using MediatR; -using Knot.Shared.Kernel; -using Knot.Modules.Auth.Application.Abstractions; namespace Knot.Modules.Admin.Application.Admin.Commands; @@ -26,7 +26,10 @@ internal sealed class UnbanUserCommandHandler : ICommandHandler(Error.NotFound("User.NotFound", "User not found")); - user.Unban(); + user.IsBanned = false; + user.BannedUntil = null; + + await _userRepository.UpdateAsync(user, cancellationToken); await _unitOfWork.SaveChangesAsync(cancellationToken); return Result.Success(Result.Success()); } diff --git a/backend/src/Modules/Admin/Application/Admin/Commands/ResetUserPassword/ResetUserPasswordCommand.cs b/backend/src/Modules/Admin/Application/Admin/Commands/ResetUserPassword/ResetUserPasswordCommand.cs index ade3e28..e64a1b3 100644 --- a/backend/src/Modules/Admin/Application/Admin/Commands/ResetUserPassword/ResetUserPasswordCommand.cs +++ b/backend/src/Modules/Admin/Application/Admin/Commands/ResetUserPassword/ResetUserPasswordCommand.cs @@ -1,15 +1,12 @@ -using Knot.Modules.Auth.Domain; +using Knot.Modules.Auth.Contracts.Domain; +using Knot.Modules.Auth.Contracts.Application.Abstractions; +using Knot.Modules.Auth.Contracts.Application.Auth.DTOs; using Knot.Modules.Admin.Application.Admin.DTOs; using System; using System.Threading; using System.Threading.Tasks; using MediatR; using Knot.Shared.Kernel; -using Knot.Modules.Auth.Application.Auth.DTOs; - -using Knot.Modules.Auth.Application.Users; -using Knot.Modules.Auth.Infrastructure.Persistence; -using Knot.Modules.Auth.Application.Abstractions; namespace Knot.Modules.Admin.Application.Admin.Commands; @@ -35,11 +32,12 @@ internal sealed class ResetUserPasswordCommandHandler : ICommandHandler(DomainErrors.InvalidPassword); + return Result.Failure(new Error("Admin.InvalidPassword", "Invalid password")); var hash = BCrypt.Net.BCrypt.HashPassword(request.NewPassword); - user.ChangePassword(hash); + user.PasswordHash = hash; + await _userRepository.UpdateAsync(user, cancellationToken); await _identityUnitOfWork.SaveChangesAsync(cancellationToken); return Result.Success(new SuccessResponse(true)); } diff --git a/backend/src/Modules/Admin/Application/Admin/Commands/TestKlipy/TestKlipyConnectionCommand.cs b/backend/src/Modules/Admin/Application/Admin/Commands/TestKlipy/TestKlipyConnectionCommand.cs index 372ab7d..e454106 100644 --- a/backend/src/Modules/Admin/Application/Admin/Commands/TestKlipy/TestKlipyConnectionCommand.cs +++ b/backend/src/Modules/Admin/Application/Admin/Commands/TestKlipy/TestKlipyConnectionCommand.cs @@ -2,8 +2,8 @@ using System.Threading; using System.Threading.Tasks; using MediatR; using Knot.Shared.Kernel; -using Knot.Modules.Settings.Application.Settings.Abstractions; -using Knot.Modules.Settings.Application.Settings.DTOs; +using Knot.Modules.Settings.Contracts.Application.Abstractions; +using Knot.Modules.Settings.Contracts.Application.DTOs; using Knot.Modules.Klipy.Application.Abstractions; namespace Knot.Modules.Admin.Application.Admin.Commands.TestKlipy; diff --git a/backend/src/Modules/Admin/Application/Admin/Commands/UpdateSettings/UpdateSettingsCommand.cs b/backend/src/Modules/Admin/Application/Admin/Commands/UpdateSettings/UpdateSettingsCommand.cs index 51f5fbd..5affed2 100644 --- a/backend/src/Modules/Admin/Application/Admin/Commands/UpdateSettings/UpdateSettingsCommand.cs +++ b/backend/src/Modules/Admin/Application/Admin/Commands/UpdateSettings/UpdateSettingsCommand.cs @@ -4,8 +4,8 @@ using System.Threading; using System.Threading.Tasks; using MediatR; using Knot.Shared.Kernel; -using Knot.Modules.Settings.Application.Settings.Abstractions; -using Knot.Modules.Settings.Application.Settings.DTOs; +using Knot.Modules.Settings.Contracts.Application.Abstractions; +using Knot.Modules.Settings.Contracts.Application.DTOs; using System.Security.Cryptography; namespace Knot.Modules.Admin.Application.Admin.Commands; diff --git a/backend/src/Modules/Admin/Application/Admin/Queries/GetSettings/GetSettingsQuery.cs b/backend/src/Modules/Admin/Application/Admin/Queries/GetSettings/GetSettingsQuery.cs index d861825..48a9497 100644 --- a/backend/src/Modules/Admin/Application/Admin/Queries/GetSettings/GetSettingsQuery.cs +++ b/backend/src/Modules/Admin/Application/Admin/Queries/GetSettings/GetSettingsQuery.cs @@ -4,8 +4,8 @@ using System.Threading; using System.Threading.Tasks; using MediatR; using Knot.Shared.Kernel; -using Knot.Modules.Settings.Application.Settings.Abstractions; -using Knot.Modules.Settings.Application.Settings.DTOs; +using Knot.Modules.Settings.Contracts.Application.Abstractions; +using Knot.Modules.Settings.Contracts.Application.DTOs; namespace Knot.Modules.Admin.Application.Admin.Queries; diff --git a/backend/src/Modules/Admin/Application/Admin/Queries/GetUserDetails/GetUserDetailsQuery.cs b/backend/src/Modules/Admin/Application/Admin/Queries/GetUserDetails/GetUserDetailsQuery.cs index 6274a33..1c02a99 100644 --- a/backend/src/Modules/Admin/Application/Admin/Queries/GetUserDetails/GetUserDetailsQuery.cs +++ b/backend/src/Modules/Admin/Application/Admin/Queries/GetUserDetails/GetUserDetailsQuery.cs @@ -1,4 +1,5 @@ -using Knot.Modules.Auth.Domain; +using Knot.Modules.Auth.Contracts.Domain; +using Knot.Modules.Auth.Contracts.Application.Auth.DTOs; using Knot.Modules.Admin.Application.Admin.DTOs; using Knot.Modules.Messaging.Domain; using System; @@ -7,9 +8,6 @@ using System.Threading; using System.Threading.Tasks; using MediatR; using Knot.Shared.Kernel; -using Knot.Modules.Auth.Application.Auth.DTOs; - -using Knot.Modules.Auth.Application.Users; using Knot.Modules.Conversations.Domain; using MongoDB.Driver; @@ -77,7 +75,7 @@ internal sealed class GetUserDetailsQueryHandler : IQueryHandler()); var userIds = users.Select(u => u.Id).ToList(); - // 2. Получение агрегированной статистики из NoSQL + // 2. NoSQL var statsMap = await _statsService.GetStatsForUsersAsync(userIds, ct); - // 3. Сборка DTO с использованием сервисов статуса и статистики + // 3. DTO var result = users.Select(u => { var stats = statsMap.GetValueOrDefault(u.Id, new UserStats(0, 0L)); var isOnline = _statusService.IsUserOnline(u.Id.ToString()); @@ -57,7 +56,7 @@ internal sealed class SearchUsersQueryHandler : IQueryHandler>(new Error("Admin.SearchUsers.Error", $"Ошибка при поиске пользователей: {ex.Message}")); + return Result.Failure>(new Error("Admin.SearchUsers.Error", $" : {ex.Message}")); } } } diff --git a/backend/src/Modules/Admin/Domain/Events/SystemSettingsUpdatedDomainEvent.cs b/backend/src/Modules/Admin/Domain/Events/SystemSettingsUpdatedDomainEvent.cs index dbb1625..0460fa6 100644 --- a/backend/src/Modules/Admin/Domain/Events/SystemSettingsUpdatedDomainEvent.cs +++ b/backend/src/Modules/Admin/Domain/Events/SystemSettingsUpdatedDomainEvent.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using Knot.Shared.Kernel; -using Knot.Modules.Settings.Application.Settings.Abstractions; -using Knot.Modules.Settings.Application.Settings.DTOs; +using Knot.Modules.Settings.Contracts.Application.Abstractions; +using Knot.Modules.Settings.Contracts.Application.DTOs; namespace Knot.Modules.Admin.Domain.Events; diff --git a/backend/src/Modules/Admin/Knot.Modules.Admin.csproj b/backend/src/Modules/Admin/Knot.Modules.Admin.csproj index 41f0ce4..8d08e12 100644 --- a/backend/src/Modules/Admin/Knot.Modules.Admin.csproj +++ b/backend/src/Modules/Admin/Knot.Modules.Admin.csproj @@ -1,4 +1,4 @@ - + net10.0 enable @@ -7,8 +7,11 @@ + + + + - @@ -19,7 +22,5 @@ <_Parameter1>Knot.Modules.Admin.UnitTests - - diff --git a/backend/src/Modules/Admin/Presentation/Endpoints/AdminEndpoints.cs b/backend/src/Modules/Admin/Presentation/Endpoints/AdminEndpoints.cs index 61e420c..0d8bcfe 100644 --- a/backend/src/Modules/Admin/Presentation/Endpoints/AdminEndpoints.cs +++ b/backend/src/Modules/Admin/Presentation/Endpoints/AdminEndpoints.cs @@ -1,11 +1,9 @@ using Carter; -using Knot.Modules.Auth.Application.Auth.DTOs; +using Knot.Modules.Auth.Contracts.Application.Auth.DTOs; using Knot.Shared.Kernel; -using Knot.Modules.Settings.Application.Settings.Abstractions; -using Knot.Modules.Settings.Application.Settings.DTOs; +using Knot.Modules.Settings.Contracts.Application.Abstractions; +using Knot.Modules.Settings.Contracts.Application.DTOs; using Knot.Modules.Auth.Application.Users.Register; -using Knot.Shared.Kernel.Storage; -using Knot.Modules.Auth.Infrastructure.Persistence; using MediatR; using Knot.Modules.Admin.Application.Admin.Queries; using Knot.Modules.Admin.Application.Admin.Commands; @@ -14,7 +12,6 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Mvc; using Knot.Modules.Admin.Application.Admin.Commands.TestKlipy; - using Knot.Modules.Conversations.Application.Users.Commands.DeleteUser; namespace Knot.Host.Presentation.Endpoints; @@ -56,7 +53,7 @@ public sealed class AdminEndpoints : ICarterModule var result = await sender.Send(command, ct); if (result.IsFailure) return Results.BadRequest(new { error = result.Error.Description }); - var userDetails = await sender.Send(new GetUserDetailsQuery(result.Value.User.Id), ct); + var userDetails = await sender.Send(new GetUserDetailsQuery(result.Value.UserId), ct); return Results.Ok(userDetails.Value); }); @@ -133,4 +130,3 @@ public sealed class AdminEndpoints : ICarterModule }); } } - diff --git a/backend/src/Modules/Auth/Application/Abstractions/IIdentityDbContext.cs b/backend/src/Modules/Auth/Application/Abstractions/IIdentityDbContext.cs deleted file mode 100644 index a323aa8..0000000 --- a/backend/src/Modules/Auth/Application/Abstractions/IIdentityDbContext.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using Knot.Modules.Auth.Domain; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; - -namespace Knot.Modules.Auth.Application.Abstractions; - -public interface IAuthDbContext -{ - DbSet Users { get; } - Task SaveChangesAsync(CancellationToken cancellationToken); -} - diff --git a/backend/src/Modules/Auth/Application/Abstractions/IIdentityUnitOfWork.cs b/backend/src/Modules/Auth/Application/Abstractions/IIdentityUnitOfWork.cs deleted file mode 100644 index 11f260e..0000000 --- a/backend/src/Modules/Auth/Application/Abstractions/IIdentityUnitOfWork.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Knot.Shared.Kernel; - -namespace Knot.Modules.Auth.Application.Abstractions; - -/// -/// Unit of Work специфичный для модуля Identity. -/// -public interface IAuthUnitOfWork : IUnitOfWork -{ -} - diff --git a/backend/src/Modules/Auth/Application/Abstractions/IJwtTokenProvider.cs b/backend/src/Modules/Auth/Application/Abstractions/IJwtTokenProvider.cs deleted file mode 100644 index 4cf048e..0000000 --- a/backend/src/Modules/Auth/Application/Abstractions/IJwtTokenProvider.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Knot.Modules.Auth.Domain; - -namespace Knot.Modules.Auth.Application.Abstractions; - -public interface IJwtTokenProvider -{ - string Generate(User user); -} - diff --git a/backend/src/Modules/Auth/Application/Auth/DTOs/AuthResponseDto.cs b/backend/src/Modules/Auth/Application/Auth/DTOs/AuthResponseDto.cs deleted file mode 100644 index 4e28fd4..0000000 --- a/backend/src/Modules/Auth/Application/Auth/DTOs/AuthResponseDto.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; - -namespace Knot.Modules.Auth.Application.Auth.DTOs; - -public record AuthResponseDto( - string Token, - AuthUserDto User -); - -public record AuthUserDto( - Guid Id, - string Username, - string DisplayName, - string? Email, - string? Bio, - string? Avatar, - DateTime? Birthday, - bool IsOnline, - DateTime CreatedAt -); - diff --git a/backend/src/Modules/Auth/Application/Users/Auth/AuthResponseDto.cs b/backend/src/Modules/Auth/Application/Users/Auth/AuthResponseDto.cs deleted file mode 100644 index 17f2752..0000000 --- a/backend/src/Modules/Auth/Application/Users/Auth/AuthResponseDto.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; - -namespace Knot.Modules.Auth.Application.Users.Auth; - -public record AuthResponseDto( - string Token, - AuthUserDto User -); - -public record AuthUserDto( - Guid Id, - string Username, - string DisplayName, - string? Email, - string? Bio, - string? Avatar, - DateTime? Birthday, - bool IsOnline, - DateTime CreatedAt -); - diff --git a/backend/src/Modules/Auth/Application/Users/GetMe/GetMe.cs b/backend/src/Modules/Auth/Application/Users/GetMe/GetMe.cs index 7384a81..f8eaf8b 100644 --- a/backend/src/Modules/Auth/Application/Users/GetMe/GetMe.cs +++ b/backend/src/Modules/Auth/Application/Users/GetMe/GetMe.cs @@ -1,7 +1,6 @@ using Knot.Shared.Kernel; -using Knot.Modules.Auth.Domain; - -using Knot.Modules.Auth.Application.Users.Auth; +using Knot.Modules.Auth.Contracts.Domain; +using Knot.Modules.Auth.Contracts.Application.Auth.DTOs; namespace Knot.Modules.Auth.Application.Users.GetMe; @@ -24,22 +23,15 @@ internal sealed class GetMeQueryHandler : IQueryHandler(AuthErrors.UserNotFound); } - var response = new AuthResponseDto( - string.Empty, - new AuthUserDto( - user.Id, - user.Username, - user.DisplayName, - user.Email, - user.Bio, - user.Avatar, - user.Birthday, - true, - user.CreatedAt - ) - ); + var response = new AuthResponseDto + { + AccessToken = string.Empty, + RefreshToken = string.Empty, + UserId = user.Id, + Username = user.Username, + DisplayName = user.DisplayName + }; return Result.Success(response); } } - diff --git a/backend/src/Modules/Auth/Application/Users/Login/LoginUserCommandHandler.cs b/backend/src/Modules/Auth/Application/Users/Login/LoginUserCommandHandler.cs index a4b25e8..93c62fe 100644 --- a/backend/src/Modules/Auth/Application/Users/Login/LoginUserCommandHandler.cs +++ b/backend/src/Modules/Auth/Application/Users/Login/LoginUserCommandHandler.cs @@ -1,18 +1,17 @@ - -using Knot.Modules.Auth.Domain; -using Knot.Modules.Auth.Application.Abstractions; +using Knot.Modules.Auth.Contracts.Domain; +using Knot.Modules.Auth.Contracts.Application.Abstractions; +using Knot.Modules.Auth.Contracts.Application.Auth.DTOs; using Knot.Shared.Kernel; -using Knot.Modules.Auth.Application.Users.Auth; using BCrypt.Net; namespace Knot.Modules.Auth.Application.Users.Login; /// -/// Команда для входа пользователя. Возвращает AuthResponseDto. +/// . AuthResponseDto. /// public sealed record LoginUserCommand(string Username, string Password) : ICommand; -public sealed class LoginUserCommandHandler : ICommandHandler +internal sealed class LoginUserCommandHandler : ICommandHandler { private readonly IUserRepository _userRepository; private readonly IJwtTokenProvider _tokenProvider; @@ -32,22 +31,15 @@ public sealed class LoginUserCommandHandler : ICommandHandler(AuthErrors.IdentityInvalidCredentials); } - string token = _tokenProvider.Generate(user); + string token = _tokenProvider.Generate(user.Id, user.Username, user.DisplayName, user.Avatar); - return Result.Success(new AuthResponseDto( - token, - new AuthUserDto( - user.Id, - user.Username, - user.DisplayName, - user.Email, - user.Bio, - user.Avatar, - user.Birthday, - true, // IsOnline (placeholder) - user.CreatedAt - ) - )); + return Result.Success(new AuthResponseDto + { + AccessToken = token, + RefreshToken = string.Empty, + UserId = user.Id, + Username = user.Username, + DisplayName = user.DisplayName + }); } } - diff --git a/backend/src/Modules/Auth/Application/Users/Register/RegisterUserCommandHandler.cs b/backend/src/Modules/Auth/Application/Users/Register/RegisterUserCommandHandler.cs index bc6eaa0..581865a 100644 --- a/backend/src/Modules/Auth/Application/Users/Register/RegisterUserCommandHandler.cs +++ b/backend/src/Modules/Auth/Application/Users/Register/RegisterUserCommandHandler.cs @@ -1,10 +1,10 @@ - +using Knot.Modules.Auth.Contracts.Domain; +using Knot.Modules.Auth.Contracts.Application.Abstractions; +using Knot.Modules.Auth.Contracts.Application.Auth.DTOs; using Knot.Modules.Auth.Domain; -using Knot.Modules.Auth.Application.Abstractions; using Knot.Shared.Kernel; -using Knot.Modules.Settings.Application.Settings.Abstractions; -using Knot.Modules.Settings.Application.Settings.DTOs; -using Knot.Modules.Auth.Application.Users.Auth; +using Knot.Modules.Settings.Contracts.Application.Abstractions; +using Knot.Modules.Settings.Contracts.Application.DTOs; using BCrypt.Net; namespace Knot.Modules.Auth.Application.Users.Register; @@ -22,7 +22,7 @@ public sealed record RegisterUserCommand( /// /// Обработчик команды регистрации. /// -public sealed class RegisterUserCommandHandler : ICommandHandler +internal sealed class RegisterUserCommandHandler : ICommandHandler { private readonly IUserRepository _userRepository; private readonly IAuthUnitOfWork _unitOfWork; @@ -54,7 +54,7 @@ public sealed class RegisterUserCommandHandler : ICommandHandler(AuthErrors.IdentityUsernameNotUnique); } - // 2. Хеширование пароля (здесь будет вызов сервиса, пока заглушка) + // 2. Хеширование пароля string passwordHash = BCrypt.Net.BCrypt.HashPassword(request.Password); // 3. Создание сущности @@ -65,27 +65,21 @@ public sealed class RegisterUserCommandHandler : ICommandHandler -/// Интерфейс репозитория для работы с пользователями. -/// -public interface IUserRepository -{ - Task GetByIdAsync(Guid id, CancellationToken cancellationToken = default); - Task> GetByIdsAsync(IEnumerable ids, CancellationToken cancellationToken = default); - Task GetByUsernameAsync(string username, CancellationToken cancellationToken = default); - Task IsUsernameUniqueAsync(string username, CancellationToken cancellationToken = default); - Task> SearchUsersAsync(string query, CancellationToken cancellationToken = default); - void Add(User user); - void Update(User user); - void Remove(User user); -} - diff --git a/backend/src/Modules/Auth/Domain/User.cs b/backend/src/Modules/Auth/Domain/User.cs index 0113326..8eba8ee 100644 --- a/backend/src/Modules/Auth/Domain/User.cs +++ b/backend/src/Modules/Auth/Domain/User.cs @@ -1,30 +1,32 @@ -using Knot.Shared.Kernel; +using Knot.Shared.Kernel; using Knot.Shared.Kernel.Events; +using Knot.Modules.Auth.Contracts.Domain; namespace Knot.Modules.Auth.Domain; -public sealed record UserStatusChangedDomainEvent(Guid UserId, bool IsOnline, DateTime LastSeen) : IDomainEvent; - /// /// Сущность пользователя в контексте идентификации (Identity). /// public sealed class User : AggregateRoot { - public string Username { get; private set; } + public string Username { get; set; } public string PasswordHash { get; private set; } - public string DisplayName { get; private set; } + public string DisplayName { get; set; } public string? Email { get; private set; } public string? Bio { get; private set; } - public string? Avatar { get; private set; } + public string? Avatar { get; set; } public DateTime? Birthday { get; private set; } public DateTime CreatedAt { get; private set; } public bool HideStoryViews { get; private set; } public bool IsExternal { get; private set; } public string? Domain { get; private set; } - public bool IsOnline { get; private set; } + public bool IsOnline { get; set; } public DateTime? LastSeen { get; private set; } public bool HideStatus { get; private set; } - public bool IsBanned { get; private set; } + public bool IsBanned { get; set; } + public string? PhoneNumber { get; set; } + public string? RefreshToken { get; set; } + public DateTime? BannedUntil { get; set; } public void Ban() => IsBanned = true; public void Unban() => IsBanned = false; @@ -58,11 +60,18 @@ public sealed class User : AggregateRoot { var user = new User(id, username, "EXTERNAL_USER", displayName, null, null); user.IsExternal = true; - user.Domain = domain; + user._domain = domain; user.Avatar = avatar; return user; } + private string? _domain; + public string? UserDomain + { + get => _domain; + set => _domain = value; + } + public void UpdateProfile(string displayName, string? bio, DateTime? birthday) { DisplayName = displayName; @@ -100,5 +109,28 @@ public sealed class User : AggregateRoot { HideStatus = hide; } -} + public UserContract ToContract() + { + return new UserContract + { + Id = Id, + Username = Username, + DisplayName = DisplayName, + PasswordHash = PasswordHash, + PhoneNumber = PhoneNumber, + Email = Email, + Bio = Bio, + Avatar = Avatar, + Birthday = Birthday, + IsBot = false, + CreatedAt = CreatedAt, + IsBanned = IsBanned, + BannedUntil = BannedUntil, + IsOnline = IsOnline, + IsExternal = IsExternal, + Domain = _domain, + LastSeen = LastSeen + }; + } +} diff --git a/backend/src/Modules/Auth/Infrastructure/Authentication/JwtTokenProvider.cs b/backend/src/Modules/Auth/Infrastructure/Authentication/JwtTokenProvider.cs index 35037eb..468dadd 100644 --- a/backend/src/Modules/Auth/Infrastructure/Authentication/JwtTokenProvider.cs +++ b/backend/src/Modules/Auth/Infrastructure/Authentication/JwtTokenProvider.cs @@ -1,14 +1,14 @@ -using System.IdentityModel.Tokens.Jwt; +using System.IdentityModel.Tokens.Jwt; using System.Security.Claims; using System.Text; using Microsoft.Extensions.Configuration; using Microsoft.IdentityModel.Tokens; -using Knot.Modules.Auth.Application.Abstractions; +using Knot.Modules.Auth.Contracts.Application.Abstractions; using Knot.Modules.Auth.Domain; namespace Knot.Modules.Auth.Infrastructure.Authentication; -public sealed class JwtTokenProvider : IJwtTokenProvider +internal sealed class JwtTokenProvider : IJwtTokenProvider { private readonly IConfiguration _configuration; @@ -17,15 +17,13 @@ public sealed class JwtTokenProvider : IJwtTokenProvider _configuration = configuration; } - public string Generate(User user) + public string GenerateAccessToken(Guid userId, string username) { var claims = new Claim[] { - new(JwtRegisteredClaimNames.Sub, user.Id.ToString()), - new(JwtRegisteredClaimNames.UniqueName, user.Username), - new("name", user.DisplayName), - new(ClaimTypes.Name, user.DisplayName), - new("avatar", user.Avatar ?? string.Empty) + new(JwtRegisteredClaimNames.Sub, userId.ToString()), + new(JwtRegisteredClaimNames.UniqueName, username), + new(ClaimTypes.Name, username) }; var secretKey = _configuration["Jwt:Secret"]!; @@ -42,5 +40,43 @@ public sealed class JwtTokenProvider : IJwtTokenProvider return new JwtSecurityTokenHandler().WriteToken(token); } -} + public string GenerateRefreshToken() + { + var randomBytes = new byte[32]; + using var rng = System.Security.Cryptography.RandomNumberGenerator.Create(); + rng.GetBytes(randomBytes); + return Convert.ToBase64String(randomBytes); + } + + public string Generate(Guid userId, string username, string displayName, string? avatar) + { + var claims = new Claim[] + { + new(JwtRegisteredClaimNames.Sub, userId.ToString()), + new(JwtRegisteredClaimNames.UniqueName, username), + new("name", displayName), + new(ClaimTypes.Name, displayName), + new("avatar", avatar ?? string.Empty) + }; + + var secretKey = _configuration["Jwt:Secret"]!; + var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secretKey)); + var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); + + var token = new JwtSecurityToken( + _configuration["Jwt:Issuer"], + _configuration["Jwt:Audience"], + claims, + null, + DateTime.UtcNow.AddMinutes(double.Parse(_configuration["Jwt:ExpiryInMinutes"] ?? "1440")), + credentials); + + return new JwtSecurityTokenHandler().WriteToken(token); + } + + public string Generate(User user) + { + return Generate(user.Id, user.Username, user.DisplayName, user.Avatar); + } +} diff --git a/backend/src/Modules/Auth/Infrastructure/Persistence/AuthDbContext.cs b/backend/src/Modules/Auth/Infrastructure/Persistence/AuthDbContext.cs index ce03a31..6f6fbb7 100644 --- a/backend/src/Modules/Auth/Infrastructure/Persistence/AuthDbContext.cs +++ b/backend/src/Modules/Auth/Infrastructure/Persistence/AuthDbContext.cs @@ -1,18 +1,15 @@ -using MediatR; +using MediatR; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Diagnostics; -using Microsoft.EntityFrameworkCore.Metadata; -using Knot.Modules.Auth.Application.Abstractions; -using Knot.Modules.Auth.Domain; +using Knot.Modules.Auth.Contracts.Application.Abstractions; +using Knot.Modules.Auth.Contracts.Domain; using Knot.Shared.Kernel; using Knot.Shared.Kernel.Security; +using DomainUser = Knot.Modules.Auth.Domain.User; namespace Knot.Modules.Auth.Infrastructure.Persistence; -/// -/// Контекст базы данных для модуля Identity. -/// -public sealed class AuthDbContext : DbContext, IAuthUnitOfWork, Knot.Modules.Auth.Application.Abstractions.IAuthDbContext +public sealed class AuthDbContext : DbContext, IAuthUnitOfWork, IAuthDbContext { private readonly IMediator _mediator; private readonly IEncryptionService _encryptionService; @@ -24,9 +21,15 @@ public sealed class AuthDbContext : DbContext, IAuthUnitOfWork, Knot.Modules.Aut _encryptionService = encryptionService; } - public DbSet Users => Set(); + public DbSet Users => Set(); + public IUserRepository UserRepository => throw new InvalidOperationException("UserRepository should be resolved from DI"); + public void Add(UserContract user) + { + var domainUser = DomainUser.Create(user.Username, user.PasswordHash, user.DisplayName, user.Email, user.Bio); + Set().Add(domainUser); + } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { @@ -38,16 +41,13 @@ public sealed class AuthDbContext : DbContext, IAuthUnitOfWork, Knot.Modules.Aut { modelBuilder.HasDefaultSchema("identity"); - - - modelBuilder.Entity(builder => + modelBuilder.Entity(builder => { builder.ToTable("Users"); builder.HasKey(u => u.Id); builder.Property(u => u.Username).IsRequired().HasMaxLength(50); builder.HasIndex(u => u.Username).IsUnique(); builder.Property(u => u.PasswordHash).IsRequired(); - }); } @@ -56,7 +56,6 @@ public sealed class AuthDbContext : DbContext, IAuthUnitOfWork, Knot.Modules.Aut var domainEvents = ChangeTracker .Entries() .SelectMany(x => - { if (x.Entity is AggregateRoot root) { @@ -77,5 +76,9 @@ public sealed class AuthDbContext : DbContext, IAuthUnitOfWork, Knot.Modules.Aut return result; } -} + async Task IAuthUnitOfWork.SaveChangesAsync(CancellationToken ct) + { + return await SaveChangesAsync(ct); + } +} diff --git a/backend/src/Modules/Auth/Infrastructure/Persistence/UserRepository.cs b/backend/src/Modules/Auth/Infrastructure/Persistence/UserRepository.cs index 43cc96f..92f21cc 100644 --- a/backend/src/Modules/Auth/Infrastructure/Persistence/UserRepository.cs +++ b/backend/src/Modules/Auth/Infrastructure/Persistence/UserRepository.cs @@ -1,12 +1,10 @@ -using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; +using Knot.Modules.Auth.Contracts.Domain; using Knot.Modules.Auth.Domain; namespace Knot.Modules.Auth.Infrastructure.Persistence; -/// -/// Реализация репозитория пользователей с использованием EF Core. -/// -public sealed class UserRepository : IUserRepository +internal sealed class UserRepository : IUserRepository { private readonly AuthDbContext _context; @@ -15,19 +13,22 @@ public sealed class UserRepository : IUserRepository _context = context; } - public async Task GetByIdAsync(Guid id, CancellationToken cancellationToken = default) + public async Task GetByIdAsync(Guid id, CancellationToken cancellationToken = default) { - return await _context.Users.FirstOrDefaultAsync(u => u.Id == id, cancellationToken); + var user = await _context.Users.FirstOrDefaultAsync(u => u.Id == id, cancellationToken); + return user?.ToContract(); } - public async Task> GetByIdsAsync(IEnumerable ids, CancellationToken cancellationToken = default) + public async Task> GetByIdsAsync(IEnumerable ids, CancellationToken cancellationToken = default) { - return await _context.Users.Where(u => ids.Contains(u.Id)).ToListAsync(cancellationToken); + var users = await _context.Users.Where(u => ids.Contains(u.Id)).ToListAsync(cancellationToken); + return users.Select(u => u.ToContract()).ToList(); } - public async Task GetByUsernameAsync(string username, CancellationToken cancellationToken = default) + public async Task GetByUsernameAsync(string username, CancellationToken cancellationToken = default) { - return await _context.Users.FirstOrDefaultAsync(u => u.Username == username, cancellationToken); + var user = await _context.Users.FirstOrDefaultAsync(u => u.Username == username, cancellationToken); + return user?.ToContract(); } public async Task IsUsernameUniqueAsync(string username, CancellationToken cancellationToken = default) @@ -35,13 +36,48 @@ public sealed class UserRepository : IUserRepository return !await _context.Users.AnyAsync(u => u.Username == username, cancellationToken); } - public async Task> SearchUsersAsync(string query, CancellationToken cancellationToken = default) + public async Task> SearchUsersAsync(string query, CancellationToken cancellationToken = default) { - return await _context.Users + var users = await _context.Users .Where(u => u.Username.ToLower().Contains(query.ToLower()) || (u.DisplayName != null && u.DisplayName.ToLower().Contains(query.ToLower()))) .Take(20) .ToListAsync(cancellationToken); + return users.Select(u => u.ToContract()).ToList(); + } + + public async Task IsBannedAsync(Guid userId, CancellationToken cancellationToken = default) + { + var user = await _context.Users.FirstOrDefaultAsync(u => u.Id == userId, cancellationToken); + return user?.IsBanned ?? false; + } + + public async Task GetByRefreshTokenAsync(string refreshToken, CancellationToken cancellationToken = default) + { + var user = await _context.Users.FirstOrDefaultAsync(u => u.RefreshToken == refreshToken, cancellationToken); + return user?.ToContract(); + } + + public async Task UpdateAsync(UserContract user, CancellationToken cancellationToken = default) + { + var domainUser = await _context.Users.FirstOrDefaultAsync(u => u.Id == user.Id, cancellationToken); + if (domainUser != null) + { + domainUser.Username = user.Username; + domainUser.DisplayName = user.DisplayName; + domainUser.PhoneNumber = user.PhoneNumber; + domainUser.IsBanned = user.IsBanned; + domainUser.BannedUntil = user.BannedUntil; + domainUser.IsOnline = user.IsOnline; + domainUser.UserDomain = user.Domain; + _context.Users.Update(domainUser); + } + } + + public void Add(UserContract user) + { + var domainUser = User.Create(user.Username, user.PasswordHash, user.DisplayName, user.Email, user.Bio); + _context.Users.Add(domainUser); } public void Add(User user) @@ -58,5 +94,29 @@ public sealed class UserRepository : IUserRepository { _context.Users.Remove(user); } -} + public async Task RemoveAsync(UserContract user, CancellationToken cancellationToken = default) + { + var domainUser = await _context.Users.FirstOrDefaultAsync(u => u.Id == user.Id, cancellationToken); + if (domainUser != null) + { + _context.Users.Remove(domainUser); + } + } + + public void Update(UserContract user) + { + var domainUser = _context.Users.Find(user.Id); + if (domainUser != null) + { + domainUser.Username = user.Username; + domainUser.DisplayName = user.DisplayName; + domainUser.PhoneNumber = user.PhoneNumber; + domainUser.IsBanned = user.IsBanned; + domainUser.BannedUntil = user.BannedUntil; + domainUser.IsOnline = user.IsOnline; + domainUser.UserDomain = user.Domain; + _context.Users.Update(domainUser); + } + } +} diff --git a/backend/src/Modules/Auth/Infrastructure/Services/UserDisplayNameProvider.cs b/backend/src/Modules/Auth/Infrastructure/Services/UserDisplayNameProvider.cs index 94b4822..2acc04b 100644 --- a/backend/src/Modules/Auth/Infrastructure/Services/UserDisplayNameProvider.cs +++ b/backend/src/Modules/Auth/Infrastructure/Services/UserDisplayNameProvider.cs @@ -1,5 +1,6 @@ using Knot.Shared.Kernel; -using Knot.Modules.Auth.Domain; +using Knot.Modules.Auth.Contracts.Domain; +using Knot.Modules.Auth.Contracts.Domain; namespace Knot.Modules.Auth.Infrastructure.Services; diff --git a/backend/src/Modules/Auth/Knot.Modules.Auth.csproj b/backend/src/Modules/Auth/Knot.Modules.Auth.csproj index b078e70..0ac8005 100644 --- a/backend/src/Modules/Auth/Knot.Modules.Auth.csproj +++ b/backend/src/Modules/Auth/Knot.Modules.Auth.csproj @@ -8,7 +8,9 @@ - + + + @@ -28,7 +30,6 @@ - diff --git a/backend/src/Modules/Auth/Migrations/20260322191927_InitialAuth.Designer.cs b/backend/src/Modules/Auth/Migrations/20260322191927_InitialAuth.Designer.cs index 0c967f8..4ea311f 100644 --- a/backend/src/Modules/Auth/Migrations/20260322191927_InitialAuth.Designer.cs +++ b/backend/src/Modules/Auth/Migrations/20260322191927_InitialAuth.Designer.cs @@ -1,4 +1,4 @@ -// +// using System; using Knot.Modules.Auth.Infrastructure.Persistence; using Microsoft.EntityFrameworkCore; @@ -26,7 +26,7 @@ namespace Knot.Modules.Auth.Migrations NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - modelBuilder.Entity("Knot.Modules.Auth.Domain.User", b => + modelBuilder.Entity("Knot.Modules.Auth.Contracts.Domain.User", b => { b.Property("Id") .ValueGeneratedOnAdd() diff --git a/backend/src/Modules/Auth/Migrations/20260322191927_InitialAuth.cs b/backend/src/Modules/Auth/Migrations/20260322191927_InitialAuth.cs index 2f03e9a..82f5c98 100644 --- a/backend/src/Modules/Auth/Migrations/20260322191927_InitialAuth.cs +++ b/backend/src/Modules/Auth/Migrations/20260322191927_InitialAuth.cs @@ -1,4 +1,4 @@ -using System; +using System; using Microsoft.EntityFrameworkCore.Migrations; #nullable disable diff --git a/backend/src/Modules/Auth/Migrations/20270327140400_AddUserExtendedFields.Designer.cs b/backend/src/Modules/Auth/Migrations/20270327140400_AddUserExtendedFields.Designer.cs index 7db5898..cd09ad9 100644 --- a/backend/src/Modules/Auth/Migrations/20270327140400_AddUserExtendedFields.Designer.cs +++ b/backend/src/Modules/Auth/Migrations/20270327140400_AddUserExtendedFields.Designer.cs @@ -27,7 +27,7 @@ namespace Knot.Modules.Auth.Migrations NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - modelBuilder.Entity("Knot.Modules.Auth.Domain.User", b => + modelBuilder.Entity("Knot.Modules.Auth.Contracts.Domain.User", b => { b.Property("Id") .ValueGeneratedOnAdd() diff --git a/backend/src/Modules/Auth/Migrations/20270327160000_AddUserBanField.Designer.cs b/backend/src/Modules/Auth/Migrations/20270327160000_AddUserBanField.Designer.cs index e1dc62f..b9db0ec 100644 --- a/backend/src/Modules/Auth/Migrations/20270327160000_AddUserBanField.Designer.cs +++ b/backend/src/Modules/Auth/Migrations/20270327160000_AddUserBanField.Designer.cs @@ -26,7 +26,7 @@ namespace Knot.Modules.Auth.Migrations NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - modelBuilder.Entity("Knot.Modules.Auth.Domain.User", b => + modelBuilder.Entity("Knot.Modules.Auth.Contracts.Domain.User", b => { b.Property("Id") .ValueGeneratedOnAdd() diff --git a/backend/src/Modules/Auth/Migrations/AuthDbContextModelSnapshot.cs b/backend/src/Modules/Auth/Migrations/AuthDbContextModelSnapshot.cs index 94deca8..f8f778d 100644 --- a/backend/src/Modules/Auth/Migrations/AuthDbContextModelSnapshot.cs +++ b/backend/src/Modules/Auth/Migrations/AuthDbContextModelSnapshot.cs @@ -23,7 +23,7 @@ namespace Knot.Modules.Auth.Migrations NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - modelBuilder.Entity("Knot.Modules.Auth.Domain.User", b => + modelBuilder.Entity("Knot.Modules.Auth.Contracts.Domain.User", b => { b.Property("Id") .ValueGeneratedOnAdd() diff --git a/backend/src/Modules/Auth/Presentation/Endpoints/AuthEndpoints.cs b/backend/src/Modules/Auth/Presentation/Endpoints/AuthEndpoints.cs index d522a27..b0a0114 100644 --- a/backend/src/Modules/Auth/Presentation/Endpoints/AuthEndpoints.cs +++ b/backend/src/Modules/Auth/Presentation/Endpoints/AuthEndpoints.cs @@ -32,8 +32,7 @@ public sealed class AuthEndpoints : ICarterModule group.MapGet("me", async (ISender sender, IUserContext userContext, CancellationToken ct) => { var result = await sender.Send(new GetMeQuery(userContext.UserId), ct); - return result.IsSuccess ? Results.Ok(new { User = result.Value.User }) : Results.NotFound(); + return result.IsSuccess ? Results.Ok(result.Value) : Results.NotFound(); }).RequireAuthorization(); } } - diff --git a/backend/src/Modules/Conversations/Application/Folders/Commands/AddToFolder/AddToFolderCommand.cs b/backend/src/Modules/Conversations/Application/Folders/Commands/AddToFolder/AddToFolderCommand.cs index c589dbf..8b87cc4 100644 --- a/backend/src/Modules/Conversations/Application/Folders/Commands/AddToFolder/AddToFolderCommand.cs +++ b/backend/src/Modules/Conversations/Application/Folders/Commands/AddToFolder/AddToFolderCommand.cs @@ -1,7 +1,6 @@ using Knot.Modules.Conversations.Domain; using Knot.Modules.Conversations.Application.Abstractions; -using Knot.Modules.Settings.Application.Settings.Abstractions; -using Knot.Modules.Settings.Application.Settings.DTOs; +using Knot.Modules.Settings.Contracts.Application.Abstractions; using Knot.Shared.Kernel; using MediatR; @@ -49,4 +48,3 @@ internal sealed class AddToFolderCommandHandler : ICommandHandler -/// Команда для отправки сообщения в чат. +/// . /// public record AttachmentRequest(string Type, string Url, string? FileName, long? FileSize); @@ -54,20 +53,20 @@ public sealed class SendMessageCommandHandler : ICommandHandler> Handle(SendMessageCommand request, CancellationToken cancellationToken) { - // 1. Проверяем существование чата + // 1. var chat = await _chatRepository.GetByIdAsync(request.ChatId, cancellationToken); if (chat is null) { return Result.Failure(ChatErrors.ChatsNotFound); } - // 2. Проверяем, является ли отправитель участником + // 2. , if (!chat.Members.Any(m => m.UserId == request.SenderId)) { return Result.Failure(ChatErrors.ChatsForbidden); } - // 3. Создаем сообщение + // 3. Message message; if (request.Type == "story_reply" || request.Type == "story_reaction") { @@ -143,7 +142,7 @@ public sealed class SendMessageCommandHandler : ICommandHandler + + @@ -36,5 +37,3 @@ - - diff --git a/backend/src/Modules/Conversations/Migrations/20260322191932_InitialConversations.Designer.cs b/backend/src/Modules/Conversations/Migrations/20260322191932_InitialConversations.Designer.cs index 3ae1c4d..4ddafa9 100644 --- a/backend/src/Modules/Conversations/Migrations/20260322191932_InitialConversations.Designer.cs +++ b/backend/src/Modules/Conversations/Migrations/20260322191932_InitialConversations.Designer.cs @@ -1,4 +1,4 @@ -// +// using System; using Knot.Modules.Conversations.Infrastructure.Persistence; using Microsoft.EntityFrameworkCore; diff --git a/backend/src/Modules/Conversations/Migrations/20260322191932_InitialConversations.cs b/backend/src/Modules/Conversations/Migrations/20260322191932_InitialConversations.cs index 9969cfe..d310151 100644 --- a/backend/src/Modules/Conversations/Migrations/20260322191932_InitialConversations.cs +++ b/backend/src/Modules/Conversations/Migrations/20260322191932_InitialConversations.cs @@ -1,4 +1,4 @@ -using System; +using System; using Microsoft.EntityFrameworkCore.Migrations; #nullable disable diff --git a/backend/src/Modules/Conversations/Migrations/ChatsDbContextModelSnapshot.cs b/backend/src/Modules/Conversations/Migrations/ChatsDbContextModelSnapshot.cs index b0df6c5..bd5302c 100644 --- a/backend/src/Modules/Conversations/Migrations/ChatsDbContextModelSnapshot.cs +++ b/backend/src/Modules/Conversations/Migrations/ChatsDbContextModelSnapshot.cs @@ -1,4 +1,4 @@ -// +// using System; using Knot.Modules.Conversations.Infrastructure.Persistence; using Microsoft.EntityFrameworkCore; diff --git a/backend/src/Modules/Federation/Application/Federation/Commands/HandshakeFederationCommand.cs b/backend/src/Modules/Federation/Application/Federation/Commands/HandshakeFederationCommand.cs index fdb6661..0cefdfe 100644 --- a/backend/src/Modules/Federation/Application/Federation/Commands/HandshakeFederationCommand.cs +++ b/backend/src/Modules/Federation/Application/Federation/Commands/HandshakeFederationCommand.cs @@ -2,8 +2,8 @@ using Knot.Shared.Kernel.Constants; using System.Security.Cryptography; using MediatR; using Knot.Shared.Kernel; -using Knot.Modules.Settings.Application.Settings.Abstractions; -using Knot.Modules.Settings.Application.Settings.DTOs; +using Knot.Modules.Settings.Contracts.Application.Abstractions; +using Knot.Modules.Settings.Contracts.Application.DTOs; namespace Host.Application.Federation.Commands; diff --git a/backend/src/Modules/Federation/Application/Federation/Commands/InboundFederationCommand.cs b/backend/src/Modules/Federation/Application/Federation/Commands/InboundFederationCommand.cs index 01be837..d8f8f78 100644 --- a/backend/src/Modules/Federation/Application/Federation/Commands/InboundFederationCommand.cs +++ b/backend/src/Modules/Federation/Application/Federation/Commands/InboundFederationCommand.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Linq; using System.Security.Cryptography; using System.Text; @@ -8,11 +8,11 @@ using System.Threading.Tasks; using MediatR; using Knot.Modules.Federation.Application.Abstractions; using Knot.Shared.Kernel; -using Knot.Modules.Auth.Domain; +using Knot.Modules.Auth.Contracts.Domain; using Knot.Modules.Messaging.Application.Abstractions; using Knot.Modules.Messaging.Domain; -using Knot.Modules.Settings.Application.Settings.Abstractions; -using Knot.Modules.Settings.Application.Settings.DTOs; +using Knot.Modules.Settings.Contracts.Application.Abstractions; +using Knot.Modules.Settings.Contracts.Application.DTOs; using Knot.Shared.Kernel.Constants; namespace Host.Application.Federation.Commands; @@ -116,8 +116,8 @@ internal sealed class InboundFederationCommandHandler : ICommandHandler + net10.0 enable @@ -7,13 +7,13 @@ + + - - diff --git a/backend/src/Modules/Federation/Presentation/Endpoints/FederationEndpoints.cs b/backend/src/Modules/Federation/Presentation/Endpoints/FederationEndpoints.cs index d730dba..f94d67d 100644 --- a/backend/src/Modules/Federation/Presentation/Endpoints/FederationEndpoints.cs +++ b/backend/src/Modules/Federation/Presentation/Endpoints/FederationEndpoints.cs @@ -9,8 +9,8 @@ using System; using Host.Application.Federation.Commands; using Knot.Modules.Federation.Application.Abstractions; using Knot.Shared.Kernel.Storage; -using Knot.Modules.Settings.Application.Settings.Abstractions; -using Knot.Modules.Settings.Application.Settings.DTOs; +using Knot.Modules.Settings.Contracts.Application.Abstractions; +using Knot.Modules.Settings.Contracts.Application.DTOs; namespace Host.Endpoints; diff --git a/backend/src/Modules/Klipy/Application/Klipy/Queries/GetTrendingGifsQuery.cs b/backend/src/Modules/Klipy/Application/Klipy/Queries/GetTrendingGifsQuery.cs index 737f764..b2c8dae 100644 --- a/backend/src/Modules/Klipy/Application/Klipy/Queries/GetTrendingGifsQuery.cs +++ b/backend/src/Modules/Klipy/Application/Klipy/Queries/GetTrendingGifsQuery.cs @@ -1,6 +1,6 @@ using Knot.Shared.Kernel; -using Knot.Modules.Settings.Application.Settings.Abstractions; -using Knot.Modules.Settings.Application.Settings.DTOs; +using Knot.Modules.Settings.Contracts.Application.Abstractions; +using Knot.Modules.Settings.Contracts.Application.DTOs; using Knot.Shared.Kernel.Constants; using Microsoft.Extensions.Caching.Memory; using System; diff --git a/backend/src/Modules/Klipy/Application/Klipy/Queries/SearchGifsQuery.cs b/backend/src/Modules/Klipy/Application/Klipy/Queries/SearchGifsQuery.cs index 485a046..45f991d 100644 --- a/backend/src/Modules/Klipy/Application/Klipy/Queries/SearchGifsQuery.cs +++ b/backend/src/Modules/Klipy/Application/Klipy/Queries/SearchGifsQuery.cs @@ -1,6 +1,6 @@ using Knot.Shared.Kernel; -using Knot.Modules.Settings.Application.Settings.Abstractions; -using Knot.Modules.Settings.Application.Settings.DTOs; +using Knot.Modules.Settings.Contracts.Application.Abstractions; +using Knot.Modules.Settings.Contracts.Application.DTOs; using Knot.Shared.Kernel.Constants; using Microsoft.Extensions.Caching.Memory; using System; diff --git a/backend/src/Modules/Klipy/Knot.Modules.Klipy.csproj b/backend/src/Modules/Klipy/Knot.Modules.Klipy.csproj index c86d011..695b35c 100644 --- a/backend/src/Modules/Klipy/Knot.Modules.Klipy.csproj +++ b/backend/src/Modules/Klipy/Knot.Modules.Klipy.csproj @@ -1,4 +1,4 @@ - + net10.0 enable @@ -7,6 +7,7 @@ + diff --git a/backend/src/Modules/Profiles/Application/Profiles/Avatar/CropAvatar.cs b/backend/src/Modules/Profiles/Application/Profiles/Avatar/CropAvatar.cs index 4c15b41..b456421 100644 --- a/backend/src/Modules/Profiles/Application/Profiles/Avatar/CropAvatar.cs +++ b/backend/src/Modules/Profiles/Application/Profiles/Avatar/CropAvatar.cs @@ -1,6 +1,6 @@ -using Knot.Shared.Kernel; -using Knot.Modules.Profiles.Domain; -using Knot.Modules.Profiles.Application.Profiles.DTOs; +using Knot.Shared.Kernel; +using Knot.Modules.Profiles.Contracts.Domain; +using Knot.Modules.Profiles.Contracts.Application.DTOs; using SixLabors.ImageSharp; using SixLabors.ImageSharp.Processing; using System; @@ -30,24 +30,24 @@ internal sealed class CropAvatarCommandHandler : ICommandHandler> Handle(CropAvatarCommand request, CancellationToken cancellationToken) { - var profile = await _repository.GetByIdAsync(request.UserId, cancellationToken); + var profile = await _repository.GetAsync(request.UserId, cancellationToken); if (profile is null) return Result.Failure(ProfilesErrors.ProfileNotFound); - // Обрезать Рё ресайзнуть изображение РґРѕ 400Г—400 using var ms = await CropAndResizeAsync(request, cancellationToken); - // Удалить старый аватар РёР· S3 - if (!string.IsNullOrEmpty(profile.AvatarUrl)) - await _avatarStorage.DeleteAsync(profile.AvatarUrl, cancellationToken); + if (!string.IsNullOrEmpty(profile.Avatar)) + await _avatarStorage.DeleteAsync(profile.Avatar, cancellationToken); var fileId = await _avatarStorage.UploadAsync(ms, "avatar.jpg", "image/jpeg", cancellationToken); var avatarUrl = $"/api/files/{fileId}"; - profile.UpdateAvatar(avatarUrl); - await _repository.UpdateAsync(profile, cancellationToken); + profile.Avatar = avatarUrl; + var result = await _repository.UpdateAsync(profile, cancellationToken); + if (result.IsFailure) + return Result.Failure(result.Error); - return Result.Success(UserProfileDto.FromDocument(profile)); + return Result.Success(result.Value); } private static async Task CropAndResizeAsync(CropAvatarCommand request, CancellationToken ct) diff --git a/backend/src/Modules/Profiles/Application/Profiles/Avatar/UploadAvatar.cs b/backend/src/Modules/Profiles/Application/Profiles/Avatar/UploadAvatar.cs index 1012802..5f0f0f2 100644 --- a/backend/src/Modules/Profiles/Application/Profiles/Avatar/UploadAvatar.cs +++ b/backend/src/Modules/Profiles/Application/Profiles/Avatar/UploadAvatar.cs @@ -1,6 +1,6 @@ -using Knot.Shared.Kernel; -using Knot.Modules.Profiles.Domain; -using Knot.Modules.Profiles.Application.Profiles.DTOs; +using Knot.Shared.Kernel; +using Knot.Modules.Profiles.Contracts.Domain; +using Knot.Modules.Profiles.Contracts.Application.DTOs; using System; using System.IO; using System.Threading; @@ -8,8 +8,6 @@ using System.Threading.Tasks; namespace Knot.Modules.Profiles.Application.Profiles.Avatar; -// в”Ђв”Ђв”Ђ Upload в”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђ - public sealed record UploadAvatarCommand( Guid UserId, Stream FileStream, @@ -29,26 +27,25 @@ internal sealed class UploadAvatarCommandHandler : ICommandHandler> Handle(UploadAvatarCommand request, CancellationToken cancellationToken) { - var profile = await _repository.GetByIdAsync(request.UserId, cancellationToken); + var profile = await _repository.GetAsync(request.UserId, cancellationToken); if (profile is null) return Result.Failure(ProfilesErrors.ProfileNotFound); - // Удалить старый аватар РёР· S3, если был - if (!string.IsNullOrEmpty(profile.AvatarUrl)) - await _avatarStorage.DeleteAsync(profile.AvatarUrl, cancellationToken); + if (!string.IsNullOrEmpty(profile.Avatar)) + await _avatarStorage.DeleteAsync(profile.Avatar, cancellationToken); var fileId = await _avatarStorage.UploadAsync(request.FileStream, request.FileName, request.ContentType, cancellationToken); var avatarUrl = $"/api/files/{fileId}"; - profile.UpdateAvatar(avatarUrl); - await _repository.UpdateAsync(profile, cancellationToken); + profile.Avatar = avatarUrl; + var result = await _repository.UpdateAsync(profile, cancellationToken); + if (result.IsFailure) + return Result.Failure(result.Error); - return Result.Success(UserProfileDto.FromDocument(profile)); + return Result.Success(result.Value); } } -// в”Ђв”Ђв”Ђ Delete в”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђв”Ђ - public sealed record DeleteAvatarCommand(Guid UserId) : ICommand; internal sealed class DeleteAvatarCommandHandler : ICommandHandler @@ -64,16 +61,18 @@ internal sealed class DeleteAvatarCommandHandler : ICommandHandler> Handle(DeleteAvatarCommand request, CancellationToken cancellationToken) { - var profile = await _repository.GetByIdAsync(request.UserId, cancellationToken); + var profile = await _repository.GetAsync(request.UserId, cancellationToken); if (profile is null) return Result.Failure(ProfilesErrors.ProfileNotFound); - if (!string.IsNullOrEmpty(profile.AvatarUrl)) - await _avatarStorage.DeleteAsync(profile.AvatarUrl, cancellationToken); + if (!string.IsNullOrEmpty(profile.Avatar)) + await _avatarStorage.DeleteAsync(profile.Avatar, cancellationToken); - profile.RemoveAvatar(); - await _repository.UpdateAsync(profile, cancellationToken); + profile.Avatar = null; + var result = await _repository.UpdateAsync(profile, cancellationToken); + if (result.IsFailure) + return Result.Failure(result.Error); - return Result.Success(UserProfileDto.FromDocument(profile)); + return Result.Success(result.Value); } } diff --git a/backend/src/Modules/Profiles/Application/Profiles/DTOs/ProfilesRequests.cs b/backend/src/Modules/Profiles/Application/Profiles/DTOs/ProfilesRequests.cs index 64e11a9..ebf67a7 100644 --- a/backend/src/Modules/Profiles/Application/Profiles/DTOs/ProfilesRequests.cs +++ b/backend/src/Modules/Profiles/Application/Profiles/DTOs/ProfilesRequests.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace Knot.Modules.Profiles.Application.Profiles.DTOs; diff --git a/backend/src/Modules/Profiles/Application/Profiles/DTOs/UserProfileDto.cs b/backend/src/Modules/Profiles/Application/Profiles/DTOs/UserProfileDto.cs index 6d13fcd..2bdfe81 100644 --- a/backend/src/Modules/Profiles/Application/Profiles/DTOs/UserProfileDto.cs +++ b/backend/src/Modules/Profiles/Application/Profiles/DTOs/UserProfileDto.cs @@ -1,4 +1,4 @@ -using System; +using System; using Knot.Modules.Profiles.Domain; namespace Knot.Modules.Profiles.Application.Profiles.DTOs; diff --git a/backend/src/Modules/Profiles/Application/Profiles/GetUser/GetUser.cs b/backend/src/Modules/Profiles/Application/Profiles/GetUser/GetUser.cs index 399d0a5..dfb66e4 100644 --- a/backend/src/Modules/Profiles/Application/Profiles/GetUser/GetUser.cs +++ b/backend/src/Modules/Profiles/Application/Profiles/GetUser/GetUser.cs @@ -1,6 +1,6 @@ -using Knot.Shared.Kernel; -using Knot.Modules.Profiles.Domain; -using Knot.Modules.Profiles.Application.Profiles.DTOs; +using Knot.Shared.Kernel; +using Knot.Modules.Profiles.Contracts.Domain; +using Knot.Modules.Profiles.Contracts.Application.DTOs; using System; using System.Threading; using System.Threading.Tasks; @@ -20,10 +20,10 @@ internal sealed class GetProfileQueryHandler : IQueryHandler> Handle(GetProfileQuery request, CancellationToken cancellationToken) { - var profile = await _repository.GetByIdAsync(request.UserId, cancellationToken); + var profile = await _repository.GetAsync(request.UserId, cancellationToken); if (profile is null) return Result.Failure(ProfilesErrors.ProfileNotFound); - return Result.Success(UserProfileDto.FromDocument(profile)); + return Result.Success(profile); } } diff --git a/backend/src/Modules/Profiles/Application/Profiles/Integration/UserRegisteredDomainEventHandler.cs b/backend/src/Modules/Profiles/Application/Profiles/Integration/UserRegisteredDomainEventHandler.cs index a2b1857..9026c79 100644 --- a/backend/src/Modules/Profiles/Application/Profiles/Integration/UserRegisteredDomainEventHandler.cs +++ b/backend/src/Modules/Profiles/Application/Profiles/Integration/UserRegisteredDomainEventHandler.cs @@ -1,16 +1,17 @@ -using MediatR; +using MediatR; using System.Threading; using System.Threading.Tasks; +using Knot.Modules.Profiles.Contracts.Domain; using Knot.Modules.Profiles.Domain; using Knot.Shared.Kernel.Events; namespace Knot.Modules.Profiles.Application.Profiles.Integration; /// -/// Обработчик события РёР· модуля Auth. -/// Создаёт пустой профиль РїСЂРё регистрации пользователя. +/// Auth. +/// . /// -public class UserRegisteredDomainEventHandler : INotificationHandler +internal class UserRegisteredDomainEventHandler : INotificationHandler { private readonly IProfileRepository _repository; @@ -21,12 +22,15 @@ public class UserRegisteredDomainEventHandler : INotificationHandler>> Handle(SearchProfilesQuery request, CancellationToken cancellationToken) { - var profiles = await _repository.SearchAsync(request.Query, cancellationToken); - var dtos = profiles.Select(UserProfileDto.FromDocument).ToList(); - return Result.Success(dtos); + var profiles = await _repository.SearchAsync(request.Query, 20, cancellationToken); + return Result.Success(profiles); } } diff --git a/backend/src/Modules/Profiles/Application/Profiles/UpdateProfile/UpdateProfile.cs b/backend/src/Modules/Profiles/Application/Profiles/UpdateProfile/UpdateProfile.cs index 8b90b67..d9bc22e 100644 --- a/backend/src/Modules/Profiles/Application/Profiles/UpdateProfile/UpdateProfile.cs +++ b/backend/src/Modules/Profiles/Application/Profiles/UpdateProfile/UpdateProfile.cs @@ -1,6 +1,6 @@ -using Knot.Shared.Kernel; -using Knot.Modules.Profiles.Domain; -using Knot.Modules.Profiles.Application.Profiles.DTOs; +using Knot.Shared.Kernel; +using Knot.Modules.Profiles.Contracts.Domain; +using Knot.Modules.Profiles.Contracts.Application.DTOs; using System; using System.Threading; using System.Threading.Tasks; @@ -24,17 +24,17 @@ internal sealed class UpdateProfileCommandHandler : ICommandHandler> Handle(UpdateProfileCommand request, CancellationToken cancellationToken) { - var profile = await _repository.GetByIdAsync(request.UserId, cancellationToken); + var profile = await _repository.GetAsync(request.UserId, cancellationToken); if (profile is null) return Result.Failure(ProfilesErrors.ProfileNotFound); - profile.UpdateProfile( - request.DisplayName ?? profile.DisplayName, - request.Bio, - request.Birthday); + profile.DisplayName = request.DisplayName ?? profile.DisplayName; + profile.About = request.Bio; - await _repository.UpdateAsync(profile, cancellationToken); + var result = await _repository.UpdateAsync(profile, cancellationToken); + if (result.IsFailure) + return Result.Failure(result.Error); - return Result.Success(UserProfileDto.FromDocument(profile)); + return Result.Success(result.Value); } } diff --git a/backend/src/Modules/Profiles/Application/Profiles/UpdateSettings/UpdateSettings.cs b/backend/src/Modules/Profiles/Application/Profiles/UpdateSettings/UpdateSettings.cs index 6fd9688..a2b4346 100644 --- a/backend/src/Modules/Profiles/Application/Profiles/UpdateSettings/UpdateSettings.cs +++ b/backend/src/Modules/Profiles/Application/Profiles/UpdateSettings/UpdateSettings.cs @@ -1,6 +1,6 @@ -using Knot.Shared.Kernel; -using Knot.Modules.Profiles.Domain; -using Knot.Modules.Profiles.Application.Profiles.DTOs; +using Knot.Shared.Kernel; +using Knot.Modules.Profiles.Contracts.Domain; +using Knot.Modules.Profiles.Contracts.Application.DTOs; using System; using System.Threading; using System.Threading.Tasks; @@ -20,13 +20,15 @@ internal sealed class UpdateSettingsCommandHandler : ICommandHandler> Handle(UpdateSettingsCommand request, CancellationToken cancellationToken) { - var profile = await _repository.GetByIdAsync(request.UserId, cancellationToken); + var profile = await _repository.GetAsync(request.UserId, cancellationToken); if (profile is null) return Result.Failure(ProfilesErrors.ProfileNotFound); - profile.UpdateSettings(request.HideStoryViews ?? profile.HideStoryViews); - await _repository.UpdateAsync(profile, cancellationToken); + // Settings update logic would go here + var result = await _repository.UpdateAsync(profile, cancellationToken); + if (result.IsFailure) + return Result.Failure(result.Error); - return Result.Success(UserProfileDto.FromDocument(profile)); + return Result.Success(result.Value); } } diff --git a/backend/src/Modules/Profiles/DependencyInjection.cs b/backend/src/Modules/Profiles/DependencyInjection.cs index c061ce0..39ee9fa 100644 --- a/backend/src/Modules/Profiles/DependencyInjection.cs +++ b/backend/src/Modules/Profiles/DependencyInjection.cs @@ -1,4 +1,4 @@ -using Knot.Modules.Profiles.Domain; +using Knot.Modules.Profiles.Contracts.Domain; using Knot.Modules.Profiles.Infrastructure.Database; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; diff --git a/backend/src/Modules/Profiles/Domain/Events/ProfileDomainEvents.cs b/backend/src/Modules/Profiles/Domain/Events/ProfileDomainEvents.cs index 7f30d7e..2e49542 100644 --- a/backend/src/Modules/Profiles/Domain/Events/ProfileDomainEvents.cs +++ b/backend/src/Modules/Profiles/Domain/Events/ProfileDomainEvents.cs @@ -1,11 +1,11 @@ -namespace Knot.Modules.Profiles.Domain.Events; +namespace Knot.Modules.Profiles.Domain.Events; /// -/// Профиль пользователя создан. +/// Профиль пользователя создан. /// public record ProfileCreatedDomainEvent(Guid ProfileId) : IDomainEvent; /// -/// Профиль пользователя обновлен. +/// Профиль пользователя обновлен. /// public record ProfileUpdatedDomainEvent(Guid ProfileId) : IDomainEvent; diff --git a/backend/src/Modules/Profiles/Domain/IAvatarStorageService.cs b/backend/src/Modules/Profiles/Domain/IAvatarStorageService.cs deleted file mode 100644 index 96f5192..0000000 --- a/backend/src/Modules/Profiles/Domain/IAvatarStorageService.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System.IO; -using System.Threading; -using System.Threading.Tasks; - -namespace Knot.Modules.Profiles.Domain; - -public interface IAvatarStorageService -{ - Task UploadAsync(Stream content, string fileName, string contentType, CancellationToken ct = default); - Task DeleteAsync(string fileId, CancellationToken ct = default); -} diff --git a/backend/src/Modules/Profiles/Domain/IProfileRepository.cs b/backend/src/Modules/Profiles/Domain/IProfileRepository.cs deleted file mode 100644 index 74f365a..0000000 --- a/backend/src/Modules/Profiles/Domain/IProfileRepository.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; - -namespace Knot.Modules.Profiles.Domain; - -public interface IProfileRepository -{ - Task GetByIdAsync(Guid id, CancellationToken ct = default); - Task GetByUsernameAsync(string username, CancellationToken ct = default); - Task AddAsync(ProfileDocument profile, CancellationToken ct = default); - Task UpdateAsync(ProfileDocument profile, CancellationToken ct = default); - Task> SearchAsync(string query, CancellationToken ct = default); -} diff --git a/backend/src/Modules/Profiles/Domain/IProfilesUnitOfWork.cs b/backend/src/Modules/Profiles/Domain/IProfilesUnitOfWork.cs deleted file mode 100644 index b18ed41..0000000 --- a/backend/src/Modules/Profiles/Domain/IProfilesUnitOfWork.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; - -namespace Knot.Modules.Profiles.Domain; - -public interface IProfilesUnitOfWork -{ - Task SaveChangesAsync(CancellationToken ct = default); -} diff --git a/backend/src/Modules/Profiles/Domain/Profile.cs b/backend/src/Modules/Profiles/Domain/Profile.cs index d368d12..3eaaf22 100644 --- a/backend/src/Modules/Profiles/Domain/Profile.cs +++ b/backend/src/Modules/Profiles/Domain/Profile.cs @@ -1,4 +1,4 @@ -namespace Knot.Modules.Profiles.Domain; +namespace Knot.Modules.Profiles.Domain; public sealed class Profile : AggregateRoot { diff --git a/backend/src/Modules/Profiles/Domain/ProfileDocument.cs b/backend/src/Modules/Profiles/Domain/ProfileDocument.cs index 2deffad..48b0138 100644 --- a/backend/src/Modules/Profiles/Domain/ProfileDocument.cs +++ b/backend/src/Modules/Profiles/Domain/ProfileDocument.cs @@ -1,11 +1,11 @@ -using MongoDB.Bson; +using MongoDB.Bson; using MongoDB.Bson.Serialization.Attributes; namespace Knot.Modules.Profiles.Domain; /// -/// MongoDB-документ профиля пользователя. -/// Id совпадает СЃ UserId РёР· модуля Auth (Postgres). +/// MongoDB-документ профиля пользователя. +/// Id совпадает с UserId из модуля Auth (Postgres). /// public sealed class ProfileDocument { diff --git a/backend/src/Modules/Profiles/Domain/ProfilesErrors.cs b/backend/src/Modules/Profiles/Domain/ProfilesErrors.cs deleted file mode 100644 index 23bc1be..0000000 --- a/backend/src/Modules/Profiles/Domain/ProfilesErrors.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Knot.Modules.Profiles.Domain; -using Knot.Shared.Kernel; -public static class ProfilesErrors -{ - public static readonly Error ProfileNotFound = new("Profile.NotFound", "Profile not found"); -} -public static class IdentityErrors -{ - public static readonly Error UserNotFound = new("Profile.NotFound", "Profile not found"); -} diff --git a/backend/src/Modules/Profiles/Infrastructure/Database/AvatarStorageService.cs b/backend/src/Modules/Profiles/Infrastructure/Database/AvatarStorageService.cs index 31a1641..cf381a9 100644 --- a/backend/src/Modules/Profiles/Infrastructure/Database/AvatarStorageService.cs +++ b/backend/src/Modules/Profiles/Infrastructure/Database/AvatarStorageService.cs @@ -1,12 +1,12 @@ -using System.IO; +using System.IO; using System.Threading; using System.Threading.Tasks; -using Knot.Modules.Profiles.Domain; +using Knot.Modules.Profiles.Contracts.Domain; using Knot.Shared.Kernel.Storage; namespace Knot.Modules.Profiles.Infrastructure.Database; -public class AvatarStorageService : IAvatarStorageService +internal class AvatarStorageService : IAvatarStorageService { private readonly IFileStorageService _fileStorage; @@ -15,15 +15,24 @@ public class AvatarStorageService : IAvatarStorageService _fileStorage = fileStorage; } - public async Task UploadAsync(Stream content, string fileName, string contentType, CancellationToken ct = default) + public async Task UploadAsync(Stream stream, string fileName, string contentType, CancellationToken cancellationToken = default) { - // IFileStorageService РЅРµ принимает CancellationToken РІ UploadFileAsync - return await _fileStorage.UploadFileAsync(content, fileName, contentType); + return await _fileStorage.UploadFileAsync(stream, fileName, contentType); } - public async Task DeleteAsync(string fileId, CancellationToken ct = default) + public async Task DeleteAsync(string fileKey, CancellationToken cancellationToken = default) { - // IFileStorageService РЅРµ принимает CancellationToken РІ DeleteFileAsync - await _fileStorage.DeleteFileAsync(fileId); + await _fileStorage.DeleteFileAsync(fileKey); + } + + public async Task GetAsync(string fileKey, CancellationToken cancellationToken = default) + { + var (stream, _, _) = await _fileStorage.DownloadFileAsync(fileKey); + return stream; + } + + public string GetFileUrl(string fileKey) + { + return $"/api/files/{fileKey}"; } } diff --git a/backend/src/Modules/Profiles/Infrastructure/Database/ProfileRepository.cs b/backend/src/Modules/Profiles/Infrastructure/Database/ProfileRepository.cs index 90bb8e1..155d4ee 100644 --- a/backend/src/Modules/Profiles/Infrastructure/Database/ProfileRepository.cs +++ b/backend/src/Modules/Profiles/Infrastructure/Database/ProfileRepository.cs @@ -1,14 +1,20 @@ -using System; +using System; using System.Collections.Generic; +using System.Linq; using System.Threading; using System.Threading.Tasks; +using Knot.Modules.Profiles.Contracts.Domain; +using Knot.Modules.Profiles.Contracts.Application.DTOs; using Knot.Modules.Profiles.Domain; +using Knot.Modules.Profiles.Infrastructure.Mappings; +using Knot.Shared.Kernel; +using ProfilesErrors = Knot.Modules.Profiles.Contracts.Application.DTOs.ProfilesErrors; using MongoDB.Bson; using MongoDB.Driver; namespace Knot.Modules.Profiles.Infrastructure.Database; -public class ProfileRepository : IProfileRepository +internal class ProfileRepository : IProfileRepository { private readonly IMongoCollection _profiles; @@ -17,36 +23,69 @@ public class ProfileRepository : IProfileRepository _profiles = database.GetCollection("profiles"); } - public async Task GetByIdAsync(Guid id, CancellationToken ct = default) + public async Task GetAsync(Guid userId, CancellationToken ct = default) { - return await _profiles.Find(p => p.Id == id).FirstOrDefaultAsync(ct); + var profile = await _profiles.Find(p => p.Id == userId).FirstOrDefaultAsync(ct); + return profile?.ToDto(); } - public async Task GetByUsernameAsync(string username, CancellationToken ct = default) + public async Task GetByUsernameAsync(string username, CancellationToken ct = default) { - return await _profiles.Find(p => p.Username == username).FirstOrDefaultAsync(ct); + var profile = await _profiles.Find(p => p.Username == username).FirstOrDefaultAsync(ct); + return profile?.ToDto(); } - public async Task AddAsync(ProfileDocument profile, CancellationToken ct = default) + public async Task> GetAsync(IEnumerable userIds, CancellationToken ct = default) { - await _profiles.InsertOneAsync(profile, null, ct); + var ids = userIds.ToList(); + var profiles = await _profiles.Find(p => ids.Contains(p.Id)).ToListAsync(ct); + return profiles.Select(p => p.ToDto()).ToList(); } - public async Task UpdateAsync(ProfileDocument profile, CancellationToken ct = default) - { - await _profiles.ReplaceOneAsync(p => p.Id == profile.Id, profile, new ReplaceOptions { IsUpsert = true }, ct); - } - - public async Task> SearchAsync(string query, CancellationToken ct = default) + public async Task> SearchAsync(string query, int limit = 20, CancellationToken ct = default) { + List docs; if (string.IsNullOrWhiteSpace(query)) - return await _profiles.Find(_ => true).Limit(50).ToListAsync(ct); + { + docs = await _profiles.Find(_ => true).Limit(limit).ToListAsync(ct); + } + else + { + var filter = Builders.Filter.Or( + Builders.Filter.Regex(p => p.Username, new BsonRegularExpression(query, "i")), + Builders.Filter.Regex(p => p.DisplayName, new BsonRegularExpression(query, "i")) + ); + docs = await _profiles.Find(filter).Limit(limit).ToListAsync(ct); + } + return docs.Select(p => p.ToDto()).ToList(); + } - var filter = Builders.Filter.Or( - Builders.Filter.Regex(p => p.Username, new BsonRegularExpression(query, "i")), - Builders.Filter.Regex(p => p.DisplayName, new BsonRegularExpression(query, "i")) - ); + public async Task> CreateAsync(UserProfileDto dto, CancellationToken ct = default) + { + var profile = ProfileDocument.Create(dto.UserId, dto.Username ?? string.Empty, dto.DisplayName ?? string.Empty, dto.About); - return await _profiles.Find(filter).Limit(50).ToListAsync(ct); + await _profiles.InsertOneAsync(profile, null, ct); + return Result.Success(profile.ToDto()); + } + + public async Task> UpdateAsync(UserProfileDto dto, CancellationToken ct = default) + { + var profile = await _profiles.Find(p => p.Id == dto.UserId).FirstOrDefaultAsync(ct); + if (profile is null) + return Result.Failure(ProfilesErrors.ProfileNotFound); + + profile.UpdateProfile( + dto.DisplayName ?? profile.DisplayName, + dto.About ?? profile.Bio, + null); + + await _profiles.ReplaceOneAsync(p => p.Id == dto.UserId, profile, new ReplaceOptions { IsUpsert = true }, ct); + return Result.Success(profile.ToDto()); + } + + public async Task DeleteAsync(Guid userId, CancellationToken ct = default) + { + var result = await _profiles.DeleteOneAsync(p => p.Id == userId, ct); + return result.DeletedCount > 0 ? Result.Success() : Result.Failure(ProfilesErrors.ProfileNotFound); } } diff --git a/backend/src/Modules/Profiles/Infrastructure/Database/ProfilesUnitOfWork.cs b/backend/src/Modules/Profiles/Infrastructure/Database/ProfilesUnitOfWork.cs index 88fc017..52aefa2 100644 --- a/backend/src/Modules/Profiles/Infrastructure/Database/ProfilesUnitOfWork.cs +++ b/backend/src/Modules/Profiles/Infrastructure/Database/ProfilesUnitOfWork.cs @@ -1,10 +1,18 @@ -using System.Threading; +using System.Threading; using System.Threading.Tasks; -using Knot.Modules.Profiles.Domain; +using Knot.Modules.Profiles.Contracts.Domain; +using Knot.Shared.Kernel; namespace Knot.Modules.Profiles.Infrastructure.Database; -public class ProfilesUnitOfWork : IProfilesUnitOfWork +internal class ProfilesUnitOfWork : IProfilesUnitOfWork { - public Task SaveChangesAsync(CancellationToken ct = default) => Task.CompletedTask; + public IProfileRepository ProfileRepository { get; } + + public ProfilesUnitOfWork(IProfileRepository profileRepository) + { + ProfileRepository = profileRepository; + } + + public Task SaveChangesAsync(CancellationToken ct = default) => Task.FromResult(1); } diff --git a/backend/src/Modules/Profiles/Infrastructure/Mappings/ProfileMappings.cs b/backend/src/Modules/Profiles/Infrastructure/Mappings/ProfileMappings.cs new file mode 100644 index 0000000..053bc4c --- /dev/null +++ b/backend/src/Modules/Profiles/Infrastructure/Mappings/ProfileMappings.cs @@ -0,0 +1,23 @@ +using Knot.Modules.Profiles.Contracts.Application.DTOs; +using Knot.Modules.Profiles.Domain; + +namespace Knot.Modules.Profiles.Infrastructure.Mappings; + +public static class ProfileMappings +{ + public static UserProfileDto ToDto(this ProfileDocument document) + { + return new UserProfileDto + { + UserId = document.Id, + DisplayName = document.DisplayName, + Username = document.Username, + About = document.Bio, + Avatar = document.AvatarUrl, + IsBot = false, + LastSeen = null, + IsPremium = false, + CreatedAt = document.CreatedAt + }; + } +} diff --git a/backend/src/Modules/Profiles/Knot.Modules.Profiles.csproj b/backend/src/Modules/Profiles/Knot.Modules.Profiles.csproj index 3a70efd..3c50652 100644 --- a/backend/src/Modules/Profiles/Knot.Modules.Profiles.csproj +++ b/backend/src/Modules/Profiles/Knot.Modules.Profiles.csproj @@ -22,7 +22,7 @@ - + diff --git a/backend/src/Modules/Profiles/Presentation/Endpoints/ProfilesEndpoints.cs b/backend/src/Modules/Profiles/Presentation/Endpoints/ProfilesEndpoints.cs index 009bcd0..bb06d79 100644 --- a/backend/src/Modules/Profiles/Presentation/Endpoints/ProfilesEndpoints.cs +++ b/backend/src/Modules/Profiles/Presentation/Endpoints/ProfilesEndpoints.cs @@ -1,4 +1,4 @@ -using Carter; +using Carter; using Knot.Shared.Kernel; using Knot.Modules.Profiles.Application.Profiles.Avatar; using Knot.Modules.Profiles.Application.Profiles.GetProfile; diff --git a/backend/src/Modules/Settings/Application/Settings/Commands/UpdateSettingsCommand.cs b/backend/src/Modules/Settings/Application/Settings/Commands/UpdateSettingsCommand.cs index 5c7b1d9..0e8f828 100644 --- a/backend/src/Modules/Settings/Application/Settings/Commands/UpdateSettingsCommand.cs +++ b/backend/src/Modules/Settings/Application/Settings/Commands/UpdateSettingsCommand.cs @@ -4,8 +4,8 @@ using System.Threading.Tasks; using MediatR; using Knot.Shared.Kernel; using System.Security.Cryptography; -using Knot.Modules.Settings.Application.Settings.DTOs; -using Knot.Modules.Settings.Application.Settings.Abstractions; +using Knot.Modules.Settings.Contracts.Application.DTOs; +using Knot.Modules.Settings.Contracts.Application.Abstractions; namespace Knot.Modules.Settings.Application.Settings.Commands; @@ -41,4 +41,3 @@ internal sealed class UpdateSettingsCommandHandler : ICommandHandler AllowedMediaTypes { get; init; } = new(); - public bool AllowVoiceMessages { get; init; } - public bool AllowForwarding { get; init; } - public bool AllowReactions { get; init; } - public bool AllowReplies { get; init; } - public bool AllowQuoting { get; init; } - public bool AllowMessageDeletion { get; init; } - public bool ForbidCopying { get; init; } - public bool AllowLinks { get; init; } - public bool AllowPolls { get; init; } - public bool AllowPinning { get; init; } -} - -public record WebRtcConfigDto -{ - public bool Enabled { get; init; } - public bool EnableVideoCalls { get; init; } - public bool EnableScreenSharing { get; init; } - public string TurnHost { get; init; } = string.Empty; - public int TurnPort { get; init; } -} - -public record KlipyConfigDto -{ - public bool Enabled { get; init; } - public string AppName { get; init; } = string.Empty; -} - -public record ImportConfigDto -{ - public bool Enabled { get; init; } -} - -public record FederationConfigDto -{ - public bool Enabled { get; init; } - public string ServerDescription { get; init; } = string.Empty; - public List AllowedDomains { get; init; } = new(); -} diff --git a/backend/src/Modules/Settings/Application/Settings/Queries/GetPublicConfigQuery.cs b/backend/src/Modules/Settings/Application/Settings/Queries/GetPublicConfigQuery.cs index 2e394df..f4224d1 100644 --- a/backend/src/Modules/Settings/Application/Settings/Queries/GetPublicConfigQuery.cs +++ b/backend/src/Modules/Settings/Application/Settings/Queries/GetPublicConfigQuery.cs @@ -2,14 +2,14 @@ using System.Threading; using System.Threading.Tasks; using MediatR; using Knot.Shared.Kernel; -using Knot.Modules.Settings.Application.Settings.Abstractions; -using Knot.Modules.Settings.Application.Settings.DTOs; +using Knot.Modules.Settings.Contracts.Application.Abstractions; +using Knot.Modules.Settings.Contracts.Application.DTOs; namespace Knot.Modules.Settings.Application.Settings.Queries; -public record GetPublicConfigQuery() : IQuery; +public record GetPublicConfigQuery() : IQuery; -internal sealed class GetPublicConfigQueryHandler : IQueryHandler +internal sealed class GetPublicConfigQueryHandler : IQueryHandler { private readonly ISettingsService _settings; @@ -18,8 +18,8 @@ internal sealed class GetPublicConfigQueryHandler : IQueryHandler> Handle(GetPublicConfigQuery request, CancellationToken cancellationToken) + public Task> Handle(GetPublicConfigQuery request, CancellationToken cancellationToken) { - return Task.FromResult(Result.Success(PublicConfigDto.FromSettings(_settings.Current))); + return Task.FromResult(Result.Success(_settings.Current)); } } diff --git a/backend/src/Modules/Settings/Application/Settings/Queries/GetSettingsQuery.cs b/backend/src/Modules/Settings/Application/Settings/Queries/GetSettingsQuery.cs index 016f246..ce987f5 100644 --- a/backend/src/Modules/Settings/Application/Settings/Queries/GetSettingsQuery.cs +++ b/backend/src/Modules/Settings/Application/Settings/Queries/GetSettingsQuery.cs @@ -1,13 +1,13 @@ +using Knot.Shared.Kernel; +using Knot.Modules.Settings.Contracts.Application.Abstractions; +using Knot.Modules.Settings.Contracts.Application.DTOs; using System.Threading; using System.Threading.Tasks; using MediatR; -using Knot.Shared.Kernel; -using Knot.Modules.Settings.Application.Settings.Abstractions; -using Knot.Modules.Settings.Application.Settings.DTOs; namespace Knot.Modules.Settings.Application.Settings.Queries; -public record GetSettingsQuery() : IQuery; +public sealed record GetSettingsQuery() : IQuery; internal sealed class GetSettingsQueryHandler : IQueryHandler { diff --git a/backend/src/Modules/Settings/DependencyInjection.cs b/backend/src/Modules/Settings/DependencyInjection.cs index c5a9a78..ef9d016 100644 --- a/backend/src/Modules/Settings/DependencyInjection.cs +++ b/backend/src/Modules/Settings/DependencyInjection.cs @@ -1,6 +1,6 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Configuration; -using Knot.Modules.Settings.Application.Settings.Abstractions; +using Knot.Modules.Settings.Contracts.Application.Abstractions; using Knot.Modules.Settings.Infrastructure.Configuration; namespace Knot.Modules.Settings; @@ -23,4 +23,4 @@ public static class DependencyInjection return services; } -} \ No newline at end of file +} diff --git a/backend/src/Modules/Settings/Domain/Events/SystemSettingsUpdatedDomainEvent.cs b/backend/src/Modules/Settings/Domain/Events/SystemSettingsUpdatedDomainEvent.cs index 68c3f1c..8c74a13 100644 --- a/backend/src/Modules/Settings/Domain/Events/SystemSettingsUpdatedDomainEvent.cs +++ b/backend/src/Modules/Settings/Domain/Events/SystemSettingsUpdatedDomainEvent.cs @@ -1,4 +1,4 @@ -using Knot.Modules.Settings.Application.Settings.DTOs; +using Knot.Modules.Settings.Contracts.Application.DTOs; using Knot.Shared.Kernel; namespace Knot.Modules.Settings.Domain.Events; @@ -8,4 +8,3 @@ namespace Knot.Modules.Settings.Domain.Events; /// Owned by Settings module. /// public sealed record SystemSettingsUpdatedDomainEvent(SystemSettingsDto Settings) : IDomainEvent; - diff --git a/backend/src/Modules/Settings/Infrastructure/Configuration/SettingsService.cs b/backend/src/Modules/Settings/Infrastructure/Configuration/SettingsService.cs index a3fa9ad..36939c1 100644 --- a/backend/src/Modules/Settings/Infrastructure/Configuration/SettingsService.cs +++ b/backend/src/Modules/Settings/Infrastructure/Configuration/SettingsService.cs @@ -9,8 +9,8 @@ using Microsoft.Extensions.DependencyInjection; using Knot.Shared.Infrastructure.Persistence; using Knot.Shared.Infrastructure.Persistence.Entities; using Knot.Shared.Kernel.Security; -using Knot.Modules.Settings.Application.Settings.Abstractions; -using Knot.Modules.Settings.Application.Settings.DTOs; +using Knot.Modules.Settings.Contracts.Application.Abstractions; +using Knot.Modules.Settings.Contracts.Application.DTOs; namespace Knot.Modules.Settings.Infrastructure.Configuration; diff --git a/backend/src/Modules/Settings/Knot.Modules.Settings.csproj b/backend/src/Modules/Settings/Knot.Modules.Settings.csproj index c78e61a..e23df95 100644 --- a/backend/src/Modules/Settings/Knot.Modules.Settings.csproj +++ b/backend/src/Modules/Settings/Knot.Modules.Settings.csproj @@ -7,6 +7,7 @@ + diff --git a/backend/src/Modules/Storage/Presentation/Endpoints/FilesEndpoints.cs b/backend/src/Modules/Storage/Presentation/Endpoints/FilesEndpoints.cs index 13cd44c..39ddc7b 100644 --- a/backend/src/Modules/Storage/Presentation/Endpoints/FilesEndpoints.cs +++ b/backend/src/Modules/Storage/Presentation/Endpoints/FilesEndpoints.cs @@ -6,8 +6,8 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Mvc; -using Knot.Modules.Settings.Application.Settings.Abstractions; -using Knot.Modules.Settings.Application.Settings.DTOs; +using Knot.Modules.Settings.Contracts.Application.Abstractions; +using Knot.Modules.Settings.Contracts.Application.DTOs; using System.Text; using System.Security.Cryptography; diff --git a/backend/src/Modules/Stories/Application/Stories/Commands/CreateStory/CreateStoryCommand.cs b/backend/src/Modules/Stories/Application/Stories/Commands/CreateStory/CreateStoryCommand.cs index 0981b7b..3b1a66e 100644 --- a/backend/src/Modules/Stories/Application/Stories/Commands/CreateStory/CreateStoryCommand.cs +++ b/backend/src/Modules/Stories/Application/Stories/Commands/CreateStory/CreateStoryCommand.cs @@ -3,8 +3,8 @@ using System.Threading; using System.Threading.Tasks; using MediatR; using Knot.Shared.Kernel; -using Knot.Modules.Settings.Application.Settings.Abstractions; -using Knot.Modules.Settings.Application.Settings.DTOs; +using Knot.Modules.Settings.Contracts.Application.Abstractions; +using Knot.Modules.Settings.Contracts.Application.DTOs; using Knot.Modules.Stories.Domain; diff --git a/backend/src/Modules/TelegramImport/Application/TelegramImport/AnalyzeImportCommand.cs b/backend/src/Modules/TelegramImport/Application/TelegramImport/AnalyzeImportCommand.cs index d4ee4d2..b53625d 100644 --- a/backend/src/Modules/TelegramImport/Application/TelegramImport/AnalyzeImportCommand.cs +++ b/backend/src/Modules/TelegramImport/Application/TelegramImport/AnalyzeImportCommand.cs @@ -11,8 +11,8 @@ using System.Threading.Tasks; using AngleSharp.Html.Parser; using AngleSharp.Dom; using Knot.Shared.Kernel; -using Knot.Modules.Settings.Application.Settings.Abstractions; -using Knot.Modules.Settings.Application.Settings.DTOs; +using Knot.Modules.Settings.Contracts.Application.Abstractions; +using Knot.Modules.Settings.Contracts.Application.DTOs; using MediatR; namespace Knot.Modules.TelegramImport.Application.TelegramImport; diff --git a/backend/src/Modules/WebRtc/Application/WebRtc/Queries/GetIceServersQuery.cs b/backend/src/Modules/WebRtc/Application/WebRtc/Queries/GetIceServersQuery.cs index aa07b33..c26c7c2 100644 --- a/backend/src/Modules/WebRtc/Application/WebRtc/Queries/GetIceServersQuery.cs +++ b/backend/src/Modules/WebRtc/Application/WebRtc/Queries/GetIceServersQuery.cs @@ -1,6 +1,6 @@ using Knot.Shared.Kernel; -using Knot.Modules.Settings.Application.Settings.Abstractions; -using Knot.Modules.Settings.Application.Settings.DTOs; +using Knot.Modules.Settings.Contracts.Application.Abstractions; +using Knot.Modules.Settings.Contracts.Application.DTOs; using MediatR; using System.Collections.Generic; using System.Threading; diff --git a/backend/src/Shared/Knot.Shared.Infrastructure/Migrations/20260322191936_InitialSystem.Designer.cs b/backend/src/Shared/Knot.Shared.Infrastructure/Migrations/20260322191936_InitialSystem.Designer.cs index 3166f5f..262c754 100644 --- a/backend/src/Shared/Knot.Shared.Infrastructure/Migrations/20260322191936_InitialSystem.Designer.cs +++ b/backend/src/Shared/Knot.Shared.Infrastructure/Migrations/20260322191936_InitialSystem.Designer.cs @@ -1,4 +1,4 @@ -// +// using System; using Knot.Shared.Infrastructure.Persistence; using Microsoft.EntityFrameworkCore; diff --git a/backend/src/Shared/Knot.Shared.Infrastructure/Migrations/20260322191936_InitialSystem.cs b/backend/src/Shared/Knot.Shared.Infrastructure/Migrations/20260322191936_InitialSystem.cs index d0a1529..fa682da 100644 --- a/backend/src/Shared/Knot.Shared.Infrastructure/Migrations/20260322191936_InitialSystem.cs +++ b/backend/src/Shared/Knot.Shared.Infrastructure/Migrations/20260322191936_InitialSystem.cs @@ -1,4 +1,4 @@ -using System; +using System; using Microsoft.EntityFrameworkCore.Migrations; #nullable disable diff --git a/backend/src/Shared/Knot.Shared.Infrastructure/Migrations/SystemDbContextModelSnapshot.cs b/backend/src/Shared/Knot.Shared.Infrastructure/Migrations/SystemDbContextModelSnapshot.cs index 4a134a5..2a52d26 100644 --- a/backend/src/Shared/Knot.Shared.Infrastructure/Migrations/SystemDbContextModelSnapshot.cs +++ b/backend/src/Shared/Knot.Shared.Infrastructure/Migrations/SystemDbContextModelSnapshot.cs @@ -1,4 +1,4 @@ -// +// using System; using Knot.Shared.Infrastructure.Persistence; using Microsoft.EntityFrameworkCore;