Перепиливание под чистый DDD
This commit is contained in:
+382
-64
@@ -13,19 +13,79 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Knot.Shared.Infrastructure"
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Modules", "Modules", "{EC447DCF-ABFA-6E24-52A5-D7FD48A5C558}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Modules", "Modules", "{EC447DCF-ABFA-6E24-52A5-D7FD48A5C558}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Identity", "Identity", "{0EC62A1A-9858-3A60-8A0C-FC9AACFA2EC7}"
|
|
||||||
EndProject
|
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Knot.Modules.Identity", "src\Modules\Identity\Knot.Modules.Identity.csproj", "{5BB2F421-C4C4-40A1-8D6E-FEBB79AE7C98}"
|
|
||||||
EndProject
|
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Chats", "Chats", "{B4154CE3-9153-E2B0-0515-138FFCE32938}"
|
|
||||||
EndProject
|
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Knot.Modules.Chats", "src\Modules\Chats\Knot.Modules.Chats.csproj", "{695CC919-E321-4DC0-8D70-C631C51624E1}"
|
|
||||||
EndProject
|
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{0AB3BF05-4346-4AA6-1389-037BE0695223}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{0AB3BF05-4346-4AA6-1389-037BE0695223}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Knot.Modules.Identity.UnitTests", "tests\Knot.Modules.Identity.UnitTests\Knot.Modules.Identity.UnitTests.csproj", "{AB2F334E-DD7C-4314-93B9-941AFC6B2ACD}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Profiles", "Profiles", "{CA5186C2-289A-9324-4152-9805A73A9773}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Knot.Modules.Chats.UnitTests", "tests\Knot.Modules.Chats.UnitTests\Knot.Modules.Chats.UnitTests.csproj", "{F48A3E3A-EEBB-43AA-81AB-7DD7FE5F29B4}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Knot.Modules.Profiles", "src\Modules\Profiles\Knot.Modules.Profiles.csproj", "{CD14770B-8BCD-4D93-AD2C-581ED030E209}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Relations", "Relations", "{10980DF6-D81A-2FEE-4ACB-4D508FA38BC6}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Knot.Modules.Relations", "src\Modules\Relations\Knot.Modules.Relations.csproj", "{B97352F3-709A-42CF-A448-07B9996F5FBE}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Stories", "Stories", "{F83653D1-5494-68B8-6444-7DEF58635BF6}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Knot.Modules.Stories", "src\Modules\Stories\Knot.Modules.Stories.csproj", "{BC98E6FC-B46A-4554-B75E-B912714A915C}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Storage", "Storage", "{AF61C489-0B09-54BC-BD16-4353135E9C4A}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Knot.Modules.Storage", "src\Modules\Storage\Knot.Modules.Storage.csproj", "{D052C05A-CDCD-48DF-8F4F-0B10E3719819}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Auth", "Auth", "{E9D55F35-C373-3DD8-6914-3213F2F582A2}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Knot.Modules.Auth", "src\Modules\Auth\Knot.Modules.Auth.csproj", "{CF08AE9C-B337-47BA-B273-4B8E5610D7BD}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Knot.Modules.Auth.UnitTests", "tests\Knot.Modules.Auth.UnitTests\Knot.Modules.Auth.UnitTests.csproj", "{BA37DF67-98D3-4399-BD68-9679396C1547}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Messaging", "Messaging", "{AE120A0E-5815-2D46-946C-DA544028AD88}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Knot.Modules.Messaging", "src\Modules\Messaging\Knot.Modules.Messaging.csproj", "{C0B5496E-F083-413E-90AE-31282A0ACCA5}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "TelegramImport", "TelegramImport", "{4D5D7319-366D-1BD8-49C5-A840B487E852}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Knot.Modules.TelegramImport", "src\Modules\TelegramImport\Knot.Modules.TelegramImport.csproj", "{C905C120-DE44-4CBC-8F98-5BE148115487}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Conversations", "Conversations", "{138B168B-2473-B06D-4BD5-1B010DA319A1}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Knot.Modules.Conversations", "src\Modules\Conversations\Knot.Modules.Conversations.csproj", "{F3EFD119-44F7-46BF-A03C-060F30A1A1E0}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Knot.Modules.Admin.UnitTests", "Tests\Knot.Modules.Admin.UnitTests\Knot.Modules.Admin.UnitTests.csproj", "{489D5878-3945-4F8E-AD13-E5499A18DFCC}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Admin", "Admin", "{E9E1155A-A339-766C-C185-6698FF423EBC}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Knot.Modules.Admin", "src\Modules\Admin\Knot.Modules.Admin.csproj", "{FFC12440-F128-48F5-9BE5-E5263930F876}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Knot.Modules.Federation.UnitTests", "Tests\Knot.Modules.Federation.UnitTests\Knot.Modules.Federation.UnitTests.csproj", "{7A402C99-2E66-4EBE-A257-0D7923A96DFD}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Federation", "Federation", "{837D2CF4-7AEA-BF76-6362-47ECD7058EEC}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Knot.Modules.Federation", "src\Modules\Federation\Knot.Modules.Federation.csproj", "{716E089D-0661-4D39-813B-063DF9A4C0E4}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Knot.Modules.Klipy.UnitTests", "Tests\Knot.Modules.Klipy.UnitTests\Knot.Modules.Klipy.UnitTests.csproj", "{43E6E19C-39EC-49C8-91EE-49586A4B9D03}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Klipy", "Klipy", "{4BC86D3F-8D7B-ACB9-EA51-9374BC9D421A}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Knot.Modules.Klipy", "src\Modules\Klipy\Knot.Modules.Klipy.csproj", "{2498C58C-53B0-4DF2-B4EA-BA69B35A7488}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Knot.Modules.Stories.UnitTests", "Tests\Knot.Modules.Stories.UnitTests\Knot.Modules.Stories.UnitTests.csproj", "{4394178B-1ADD-478E-BF73-574B31C11292}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Knot.Modules.Relations.UnitTests", "Tests\Knot.Modules.Relations.UnitTests\Knot.Modules.Relations.UnitTests.csproj", "{2F2C7E01-5791-4A6D-9A80-C71CAD846FA8}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Knot.Modules.Settings.UnitTests", "Tests\Knot.Modules.Settings.UnitTests\Knot.Modules.Settings.UnitTests.csproj", "{76706BA9-11E0-463A-AF8E-18DFBD9E95A2}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Settings", "Settings", "{0587C5BB-3015-204D-19B6-EB01E03E48B6}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Knot.Modules.Settings", "src\Modules\Settings\Knot.Modules.Settings.csproj", "{AEFD93B4-59B8-4B02-A694-CA15E4EC1C08}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Knot.Modules.Storage.UnitTests", "Tests\Knot.Modules.Storage.UnitTests\Knot.Modules.Storage.UnitTests.csproj", "{C11BFE93-017D-4538-A61F-A8D98F8D2D75}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Knot.Modules.TelegramImport.UnitTests", "Tests\Knot.Modules.TelegramImport.UnitTests\Knot.Modules.TelegramImport.UnitTests.csproj", "{38276FFF-05D8-4005-8863-018CEE833D66}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Knot.Modules.WebRtc.UnitTests", "Tests\Knot.Modules.WebRtc.UnitTests\Knot.Modules.WebRtc.UnitTests.csproj", "{32AC7906-B197-4628-9C47-9337BB5A53E2}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WebRtc", "WebRtc", "{DD6FAF9E-10A0-95E7-0C06-698A6F70AFEE}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Knot.Modules.WebRtc", "src\Modules\WebRtc\Knot.Modules.WebRtc.csproj", "{03BE4EB1-FD38-445A-9A4B-7B481560E9A2}"
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
@@ -61,54 +121,282 @@ Global
|
|||||||
{6C13E9A4-234C-4BF1-A145-F1BBA2AC56CB}.Release|x64.Build.0 = Release|Any CPU
|
{6C13E9A4-234C-4BF1-A145-F1BBA2AC56CB}.Release|x64.Build.0 = Release|Any CPU
|
||||||
{6C13E9A4-234C-4BF1-A145-F1BBA2AC56CB}.Release|x86.ActiveCfg = Release|Any CPU
|
{6C13E9A4-234C-4BF1-A145-F1BBA2AC56CB}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
{6C13E9A4-234C-4BF1-A145-F1BBA2AC56CB}.Release|x86.Build.0 = Release|Any CPU
|
{6C13E9A4-234C-4BF1-A145-F1BBA2AC56CB}.Release|x86.Build.0 = Release|Any CPU
|
||||||
{5BB2F421-C4C4-40A1-8D6E-FEBB79AE7C98}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{CD14770B-8BCD-4D93-AD2C-581ED030E209}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{5BB2F421-C4C4-40A1-8D6E-FEBB79AE7C98}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{CD14770B-8BCD-4D93-AD2C-581ED030E209}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{5BB2F421-C4C4-40A1-8D6E-FEBB79AE7C98}.Debug|x64.ActiveCfg = Debug|Any CPU
|
{CD14770B-8BCD-4D93-AD2C-581ED030E209}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
{5BB2F421-C4C4-40A1-8D6E-FEBB79AE7C98}.Debug|x64.Build.0 = Debug|Any CPU
|
{CD14770B-8BCD-4D93-AD2C-581ED030E209}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
{5BB2F421-C4C4-40A1-8D6E-FEBB79AE7C98}.Debug|x86.ActiveCfg = Debug|Any CPU
|
{CD14770B-8BCD-4D93-AD2C-581ED030E209}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
{5BB2F421-C4C4-40A1-8D6E-FEBB79AE7C98}.Debug|x86.Build.0 = Debug|Any CPU
|
{CD14770B-8BCD-4D93-AD2C-581ED030E209}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
{5BB2F421-C4C4-40A1-8D6E-FEBB79AE7C98}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{CD14770B-8BCD-4D93-AD2C-581ED030E209}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{5BB2F421-C4C4-40A1-8D6E-FEBB79AE7C98}.Release|Any CPU.Build.0 = Release|Any CPU
|
{CD14770B-8BCD-4D93-AD2C-581ED030E209}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{5BB2F421-C4C4-40A1-8D6E-FEBB79AE7C98}.Release|x64.ActiveCfg = Release|Any CPU
|
{CD14770B-8BCD-4D93-AD2C-581ED030E209}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
{5BB2F421-C4C4-40A1-8D6E-FEBB79AE7C98}.Release|x64.Build.0 = Release|Any CPU
|
{CD14770B-8BCD-4D93-AD2C-581ED030E209}.Release|x64.Build.0 = Release|Any CPU
|
||||||
{5BB2F421-C4C4-40A1-8D6E-FEBB79AE7C98}.Release|x86.ActiveCfg = Release|Any CPU
|
{CD14770B-8BCD-4D93-AD2C-581ED030E209}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
{5BB2F421-C4C4-40A1-8D6E-FEBB79AE7C98}.Release|x86.Build.0 = Release|Any CPU
|
{CD14770B-8BCD-4D93-AD2C-581ED030E209}.Release|x86.Build.0 = Release|Any CPU
|
||||||
{695CC919-E321-4DC0-8D70-C631C51624E1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{B97352F3-709A-42CF-A448-07B9996F5FBE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{695CC919-E321-4DC0-8D70-C631C51624E1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{B97352F3-709A-42CF-A448-07B9996F5FBE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{695CC919-E321-4DC0-8D70-C631C51624E1}.Debug|x64.ActiveCfg = Debug|Any CPU
|
{B97352F3-709A-42CF-A448-07B9996F5FBE}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
{695CC919-E321-4DC0-8D70-C631C51624E1}.Debug|x64.Build.0 = Debug|Any CPU
|
{B97352F3-709A-42CF-A448-07B9996F5FBE}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
{695CC919-E321-4DC0-8D70-C631C51624E1}.Debug|x86.ActiveCfg = Debug|Any CPU
|
{B97352F3-709A-42CF-A448-07B9996F5FBE}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
{695CC919-E321-4DC0-8D70-C631C51624E1}.Debug|x86.Build.0 = Debug|Any CPU
|
{B97352F3-709A-42CF-A448-07B9996F5FBE}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
{695CC919-E321-4DC0-8D70-C631C51624E1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{B97352F3-709A-42CF-A448-07B9996F5FBE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{695CC919-E321-4DC0-8D70-C631C51624E1}.Release|Any CPU.Build.0 = Release|Any CPU
|
{B97352F3-709A-42CF-A448-07B9996F5FBE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{695CC919-E321-4DC0-8D70-C631C51624E1}.Release|x64.ActiveCfg = Release|Any CPU
|
{B97352F3-709A-42CF-A448-07B9996F5FBE}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
{695CC919-E321-4DC0-8D70-C631C51624E1}.Release|x64.Build.0 = Release|Any CPU
|
{B97352F3-709A-42CF-A448-07B9996F5FBE}.Release|x64.Build.0 = Release|Any CPU
|
||||||
{695CC919-E321-4DC0-8D70-C631C51624E1}.Release|x86.ActiveCfg = Release|Any CPU
|
{B97352F3-709A-42CF-A448-07B9996F5FBE}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
{695CC919-E321-4DC0-8D70-C631C51624E1}.Release|x86.Build.0 = Release|Any CPU
|
{B97352F3-709A-42CF-A448-07B9996F5FBE}.Release|x86.Build.0 = Release|Any CPU
|
||||||
{AB2F334E-DD7C-4314-93B9-941AFC6B2ACD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{BC98E6FC-B46A-4554-B75E-B912714A915C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{AB2F334E-DD7C-4314-93B9-941AFC6B2ACD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{BC98E6FC-B46A-4554-B75E-B912714A915C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{AB2F334E-DD7C-4314-93B9-941AFC6B2ACD}.Debug|x64.ActiveCfg = Debug|Any CPU
|
{BC98E6FC-B46A-4554-B75E-B912714A915C}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
{AB2F334E-DD7C-4314-93B9-941AFC6B2ACD}.Debug|x64.Build.0 = Debug|Any CPU
|
{BC98E6FC-B46A-4554-B75E-B912714A915C}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
{AB2F334E-DD7C-4314-93B9-941AFC6B2ACD}.Debug|x86.ActiveCfg = Debug|Any CPU
|
{BC98E6FC-B46A-4554-B75E-B912714A915C}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
{AB2F334E-DD7C-4314-93B9-941AFC6B2ACD}.Debug|x86.Build.0 = Debug|Any CPU
|
{BC98E6FC-B46A-4554-B75E-B912714A915C}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
{AB2F334E-DD7C-4314-93B9-941AFC6B2ACD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{BC98E6FC-B46A-4554-B75E-B912714A915C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{AB2F334E-DD7C-4314-93B9-941AFC6B2ACD}.Release|Any CPU.Build.0 = Release|Any CPU
|
{BC98E6FC-B46A-4554-B75E-B912714A915C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{AB2F334E-DD7C-4314-93B9-941AFC6B2ACD}.Release|x64.ActiveCfg = Release|Any CPU
|
{BC98E6FC-B46A-4554-B75E-B912714A915C}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
{AB2F334E-DD7C-4314-93B9-941AFC6B2ACD}.Release|x64.Build.0 = Release|Any CPU
|
{BC98E6FC-B46A-4554-B75E-B912714A915C}.Release|x64.Build.0 = Release|Any CPU
|
||||||
{AB2F334E-DD7C-4314-93B9-941AFC6B2ACD}.Release|x86.ActiveCfg = Release|Any CPU
|
{BC98E6FC-B46A-4554-B75E-B912714A915C}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
{AB2F334E-DD7C-4314-93B9-941AFC6B2ACD}.Release|x86.Build.0 = Release|Any CPU
|
{BC98E6FC-B46A-4554-B75E-B912714A915C}.Release|x86.Build.0 = Release|Any CPU
|
||||||
{F48A3E3A-EEBB-43AA-81AB-7DD7FE5F29B4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{D052C05A-CDCD-48DF-8F4F-0B10E3719819}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{F48A3E3A-EEBB-43AA-81AB-7DD7FE5F29B4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{D052C05A-CDCD-48DF-8F4F-0B10E3719819}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{F48A3E3A-EEBB-43AA-81AB-7DD7FE5F29B4}.Debug|x64.ActiveCfg = Debug|Any CPU
|
{D052C05A-CDCD-48DF-8F4F-0B10E3719819}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
{F48A3E3A-EEBB-43AA-81AB-7DD7FE5F29B4}.Debug|x64.Build.0 = Debug|Any CPU
|
{D052C05A-CDCD-48DF-8F4F-0B10E3719819}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
{F48A3E3A-EEBB-43AA-81AB-7DD7FE5F29B4}.Debug|x86.ActiveCfg = Debug|Any CPU
|
{D052C05A-CDCD-48DF-8F4F-0B10E3719819}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
{F48A3E3A-EEBB-43AA-81AB-7DD7FE5F29B4}.Debug|x86.Build.0 = Debug|Any CPU
|
{D052C05A-CDCD-48DF-8F4F-0B10E3719819}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
{F48A3E3A-EEBB-43AA-81AB-7DD7FE5F29B4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{D052C05A-CDCD-48DF-8F4F-0B10E3719819}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{F48A3E3A-EEBB-43AA-81AB-7DD7FE5F29B4}.Release|Any CPU.Build.0 = Release|Any CPU
|
{D052C05A-CDCD-48DF-8F4F-0B10E3719819}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{F48A3E3A-EEBB-43AA-81AB-7DD7FE5F29B4}.Release|x64.ActiveCfg = Release|Any CPU
|
{D052C05A-CDCD-48DF-8F4F-0B10E3719819}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
{F48A3E3A-EEBB-43AA-81AB-7DD7FE5F29B4}.Release|x64.Build.0 = Release|Any CPU
|
{D052C05A-CDCD-48DF-8F4F-0B10E3719819}.Release|x64.Build.0 = Release|Any CPU
|
||||||
{F48A3E3A-EEBB-43AA-81AB-7DD7FE5F29B4}.Release|x86.ActiveCfg = Release|Any CPU
|
{D052C05A-CDCD-48DF-8F4F-0B10E3719819}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
{F48A3E3A-EEBB-43AA-81AB-7DD7FE5F29B4}.Release|x86.Build.0 = Release|Any CPU
|
{D052C05A-CDCD-48DF-8F4F-0B10E3719819}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{CF08AE9C-B337-47BA-B273-4B8E5610D7BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{CF08AE9C-B337-47BA-B273-4B8E5610D7BD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{CF08AE9C-B337-47BA-B273-4B8E5610D7BD}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{CF08AE9C-B337-47BA-B273-4B8E5610D7BD}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{CF08AE9C-B337-47BA-B273-4B8E5610D7BD}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{CF08AE9C-B337-47BA-B273-4B8E5610D7BD}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{CF08AE9C-B337-47BA-B273-4B8E5610D7BD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{CF08AE9C-B337-47BA-B273-4B8E5610D7BD}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{CF08AE9C-B337-47BA-B273-4B8E5610D7BD}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{CF08AE9C-B337-47BA-B273-4B8E5610D7BD}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{CF08AE9C-B337-47BA-B273-4B8E5610D7BD}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{CF08AE9C-B337-47BA-B273-4B8E5610D7BD}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{BA37DF67-98D3-4399-BD68-9679396C1547}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{BA37DF67-98D3-4399-BD68-9679396C1547}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{BA37DF67-98D3-4399-BD68-9679396C1547}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{BA37DF67-98D3-4399-BD68-9679396C1547}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{BA37DF67-98D3-4399-BD68-9679396C1547}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{BA37DF67-98D3-4399-BD68-9679396C1547}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{BA37DF67-98D3-4399-BD68-9679396C1547}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{BA37DF67-98D3-4399-BD68-9679396C1547}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{BA37DF67-98D3-4399-BD68-9679396C1547}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{BA37DF67-98D3-4399-BD68-9679396C1547}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{BA37DF67-98D3-4399-BD68-9679396C1547}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{BA37DF67-98D3-4399-BD68-9679396C1547}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{C0B5496E-F083-413E-90AE-31282A0ACCA5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{C0B5496E-F083-413E-90AE-31282A0ACCA5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{C0B5496E-F083-413E-90AE-31282A0ACCA5}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{C0B5496E-F083-413E-90AE-31282A0ACCA5}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{C0B5496E-F083-413E-90AE-31282A0ACCA5}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{C0B5496E-F083-413E-90AE-31282A0ACCA5}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{C0B5496E-F083-413E-90AE-31282A0ACCA5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{C0B5496E-F083-413E-90AE-31282A0ACCA5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{C0B5496E-F083-413E-90AE-31282A0ACCA5}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{C0B5496E-F083-413E-90AE-31282A0ACCA5}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{C0B5496E-F083-413E-90AE-31282A0ACCA5}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{C0B5496E-F083-413E-90AE-31282A0ACCA5}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{C905C120-DE44-4CBC-8F98-5BE148115487}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{C905C120-DE44-4CBC-8F98-5BE148115487}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{C905C120-DE44-4CBC-8F98-5BE148115487}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{C905C120-DE44-4CBC-8F98-5BE148115487}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{C905C120-DE44-4CBC-8F98-5BE148115487}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{C905C120-DE44-4CBC-8F98-5BE148115487}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{C905C120-DE44-4CBC-8F98-5BE148115487}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{C905C120-DE44-4CBC-8F98-5BE148115487}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{C905C120-DE44-4CBC-8F98-5BE148115487}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{C905C120-DE44-4CBC-8F98-5BE148115487}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{C905C120-DE44-4CBC-8F98-5BE148115487}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{C905C120-DE44-4CBC-8F98-5BE148115487}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{F3EFD119-44F7-46BF-A03C-060F30A1A1E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{F3EFD119-44F7-46BF-A03C-060F30A1A1E0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{F3EFD119-44F7-46BF-A03C-060F30A1A1E0}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{F3EFD119-44F7-46BF-A03C-060F30A1A1E0}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{F3EFD119-44F7-46BF-A03C-060F30A1A1E0}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{F3EFD119-44F7-46BF-A03C-060F30A1A1E0}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{F3EFD119-44F7-46BF-A03C-060F30A1A1E0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{F3EFD119-44F7-46BF-A03C-060F30A1A1E0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{F3EFD119-44F7-46BF-A03C-060F30A1A1E0}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{F3EFD119-44F7-46BF-A03C-060F30A1A1E0}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{F3EFD119-44F7-46BF-A03C-060F30A1A1E0}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{F3EFD119-44F7-46BF-A03C-060F30A1A1E0}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{489D5878-3945-4F8E-AD13-E5499A18DFCC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{489D5878-3945-4F8E-AD13-E5499A18DFCC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{489D5878-3945-4F8E-AD13-E5499A18DFCC}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{489D5878-3945-4F8E-AD13-E5499A18DFCC}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{489D5878-3945-4F8E-AD13-E5499A18DFCC}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{489D5878-3945-4F8E-AD13-E5499A18DFCC}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{489D5878-3945-4F8E-AD13-E5499A18DFCC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{489D5878-3945-4F8E-AD13-E5499A18DFCC}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{489D5878-3945-4F8E-AD13-E5499A18DFCC}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{489D5878-3945-4F8E-AD13-E5499A18DFCC}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{489D5878-3945-4F8E-AD13-E5499A18DFCC}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{489D5878-3945-4F8E-AD13-E5499A18DFCC}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{FFC12440-F128-48F5-9BE5-E5263930F876}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{FFC12440-F128-48F5-9BE5-E5263930F876}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{FFC12440-F128-48F5-9BE5-E5263930F876}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{FFC12440-F128-48F5-9BE5-E5263930F876}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{FFC12440-F128-48F5-9BE5-E5263930F876}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{FFC12440-F128-48F5-9BE5-E5263930F876}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{FFC12440-F128-48F5-9BE5-E5263930F876}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{FFC12440-F128-48F5-9BE5-E5263930F876}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{FFC12440-F128-48F5-9BE5-E5263930F876}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{FFC12440-F128-48F5-9BE5-E5263930F876}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{FFC12440-F128-48F5-9BE5-E5263930F876}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{FFC12440-F128-48F5-9BE5-E5263930F876}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{7A402C99-2E66-4EBE-A257-0D7923A96DFD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{7A402C99-2E66-4EBE-A257-0D7923A96DFD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{7A402C99-2E66-4EBE-A257-0D7923A96DFD}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{7A402C99-2E66-4EBE-A257-0D7923A96DFD}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{7A402C99-2E66-4EBE-A257-0D7923A96DFD}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{7A402C99-2E66-4EBE-A257-0D7923A96DFD}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{7A402C99-2E66-4EBE-A257-0D7923A96DFD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{7A402C99-2E66-4EBE-A257-0D7923A96DFD}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{7A402C99-2E66-4EBE-A257-0D7923A96DFD}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{7A402C99-2E66-4EBE-A257-0D7923A96DFD}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{7A402C99-2E66-4EBE-A257-0D7923A96DFD}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{7A402C99-2E66-4EBE-A257-0D7923A96DFD}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{716E089D-0661-4D39-813B-063DF9A4C0E4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{716E089D-0661-4D39-813B-063DF9A4C0E4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{716E089D-0661-4D39-813B-063DF9A4C0E4}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{716E089D-0661-4D39-813B-063DF9A4C0E4}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{716E089D-0661-4D39-813B-063DF9A4C0E4}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{716E089D-0661-4D39-813B-063DF9A4C0E4}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{716E089D-0661-4D39-813B-063DF9A4C0E4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{716E089D-0661-4D39-813B-063DF9A4C0E4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{716E089D-0661-4D39-813B-063DF9A4C0E4}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{716E089D-0661-4D39-813B-063DF9A4C0E4}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{716E089D-0661-4D39-813B-063DF9A4C0E4}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{716E089D-0661-4D39-813B-063DF9A4C0E4}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{43E6E19C-39EC-49C8-91EE-49586A4B9D03}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{43E6E19C-39EC-49C8-91EE-49586A4B9D03}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{43E6E19C-39EC-49C8-91EE-49586A4B9D03}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{43E6E19C-39EC-49C8-91EE-49586A4B9D03}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{43E6E19C-39EC-49C8-91EE-49586A4B9D03}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{43E6E19C-39EC-49C8-91EE-49586A4B9D03}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{43E6E19C-39EC-49C8-91EE-49586A4B9D03}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{43E6E19C-39EC-49C8-91EE-49586A4B9D03}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{43E6E19C-39EC-49C8-91EE-49586A4B9D03}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{43E6E19C-39EC-49C8-91EE-49586A4B9D03}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{43E6E19C-39EC-49C8-91EE-49586A4B9D03}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{43E6E19C-39EC-49C8-91EE-49586A4B9D03}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{2498C58C-53B0-4DF2-B4EA-BA69B35A7488}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{2498C58C-53B0-4DF2-B4EA-BA69B35A7488}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{2498C58C-53B0-4DF2-B4EA-BA69B35A7488}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{2498C58C-53B0-4DF2-B4EA-BA69B35A7488}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{2498C58C-53B0-4DF2-B4EA-BA69B35A7488}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{2498C58C-53B0-4DF2-B4EA-BA69B35A7488}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{2498C58C-53B0-4DF2-B4EA-BA69B35A7488}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{2498C58C-53B0-4DF2-B4EA-BA69B35A7488}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{2498C58C-53B0-4DF2-B4EA-BA69B35A7488}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{2498C58C-53B0-4DF2-B4EA-BA69B35A7488}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{2498C58C-53B0-4DF2-B4EA-BA69B35A7488}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{2498C58C-53B0-4DF2-B4EA-BA69B35A7488}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{4394178B-1ADD-478E-BF73-574B31C11292}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{4394178B-1ADD-478E-BF73-574B31C11292}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{4394178B-1ADD-478E-BF73-574B31C11292}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{4394178B-1ADD-478E-BF73-574B31C11292}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{4394178B-1ADD-478E-BF73-574B31C11292}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{4394178B-1ADD-478E-BF73-574B31C11292}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{4394178B-1ADD-478E-BF73-574B31C11292}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{4394178B-1ADD-478E-BF73-574B31C11292}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{4394178B-1ADD-478E-BF73-574B31C11292}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{4394178B-1ADD-478E-BF73-574B31C11292}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{4394178B-1ADD-478E-BF73-574B31C11292}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{4394178B-1ADD-478E-BF73-574B31C11292}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{2F2C7E01-5791-4A6D-9A80-C71CAD846FA8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{2F2C7E01-5791-4A6D-9A80-C71CAD846FA8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{2F2C7E01-5791-4A6D-9A80-C71CAD846FA8}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{2F2C7E01-5791-4A6D-9A80-C71CAD846FA8}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{2F2C7E01-5791-4A6D-9A80-C71CAD846FA8}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{2F2C7E01-5791-4A6D-9A80-C71CAD846FA8}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{2F2C7E01-5791-4A6D-9A80-C71CAD846FA8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{2F2C7E01-5791-4A6D-9A80-C71CAD846FA8}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{2F2C7E01-5791-4A6D-9A80-C71CAD846FA8}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{2F2C7E01-5791-4A6D-9A80-C71CAD846FA8}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{2F2C7E01-5791-4A6D-9A80-C71CAD846FA8}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{2F2C7E01-5791-4A6D-9A80-C71CAD846FA8}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{76706BA9-11E0-463A-AF8E-18DFBD9E95A2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{76706BA9-11E0-463A-AF8E-18DFBD9E95A2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{76706BA9-11E0-463A-AF8E-18DFBD9E95A2}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{76706BA9-11E0-463A-AF8E-18DFBD9E95A2}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{76706BA9-11E0-463A-AF8E-18DFBD9E95A2}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{76706BA9-11E0-463A-AF8E-18DFBD9E95A2}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{76706BA9-11E0-463A-AF8E-18DFBD9E95A2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{76706BA9-11E0-463A-AF8E-18DFBD9E95A2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{76706BA9-11E0-463A-AF8E-18DFBD9E95A2}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{76706BA9-11E0-463A-AF8E-18DFBD9E95A2}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{76706BA9-11E0-463A-AF8E-18DFBD9E95A2}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{76706BA9-11E0-463A-AF8E-18DFBD9E95A2}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{AEFD93B4-59B8-4B02-A694-CA15E4EC1C08}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{AEFD93B4-59B8-4B02-A694-CA15E4EC1C08}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{AEFD93B4-59B8-4B02-A694-CA15E4EC1C08}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{AEFD93B4-59B8-4B02-A694-CA15E4EC1C08}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{AEFD93B4-59B8-4B02-A694-CA15E4EC1C08}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{AEFD93B4-59B8-4B02-A694-CA15E4EC1C08}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{AEFD93B4-59B8-4B02-A694-CA15E4EC1C08}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{AEFD93B4-59B8-4B02-A694-CA15E4EC1C08}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{AEFD93B4-59B8-4B02-A694-CA15E4EC1C08}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{AEFD93B4-59B8-4B02-A694-CA15E4EC1C08}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{AEFD93B4-59B8-4B02-A694-CA15E4EC1C08}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{AEFD93B4-59B8-4B02-A694-CA15E4EC1C08}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{C11BFE93-017D-4538-A61F-A8D98F8D2D75}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{C11BFE93-017D-4538-A61F-A8D98F8D2D75}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{C11BFE93-017D-4538-A61F-A8D98F8D2D75}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{C11BFE93-017D-4538-A61F-A8D98F8D2D75}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{C11BFE93-017D-4538-A61F-A8D98F8D2D75}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{C11BFE93-017D-4538-A61F-A8D98F8D2D75}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{C11BFE93-017D-4538-A61F-A8D98F8D2D75}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{C11BFE93-017D-4538-A61F-A8D98F8D2D75}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{C11BFE93-017D-4538-A61F-A8D98F8D2D75}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{C11BFE93-017D-4538-A61F-A8D98F8D2D75}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{C11BFE93-017D-4538-A61F-A8D98F8D2D75}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{C11BFE93-017D-4538-A61F-A8D98F8D2D75}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{38276FFF-05D8-4005-8863-018CEE833D66}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{38276FFF-05D8-4005-8863-018CEE833D66}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{38276FFF-05D8-4005-8863-018CEE833D66}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{38276FFF-05D8-4005-8863-018CEE833D66}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{38276FFF-05D8-4005-8863-018CEE833D66}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{38276FFF-05D8-4005-8863-018CEE833D66}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{38276FFF-05D8-4005-8863-018CEE833D66}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{38276FFF-05D8-4005-8863-018CEE833D66}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{38276FFF-05D8-4005-8863-018CEE833D66}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{38276FFF-05D8-4005-8863-018CEE833D66}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{38276FFF-05D8-4005-8863-018CEE833D66}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{38276FFF-05D8-4005-8863-018CEE833D66}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{32AC7906-B197-4628-9C47-9337BB5A53E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{32AC7906-B197-4628-9C47-9337BB5A53E2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{32AC7906-B197-4628-9C47-9337BB5A53E2}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{32AC7906-B197-4628-9C47-9337BB5A53E2}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{32AC7906-B197-4628-9C47-9337BB5A53E2}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{32AC7906-B197-4628-9C47-9337BB5A53E2}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{32AC7906-B197-4628-9C47-9337BB5A53E2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{32AC7906-B197-4628-9C47-9337BB5A53E2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{32AC7906-B197-4628-9C47-9337BB5A53E2}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{32AC7906-B197-4628-9C47-9337BB5A53E2}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{32AC7906-B197-4628-9C47-9337BB5A53E2}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{32AC7906-B197-4628-9C47-9337BB5A53E2}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{03BE4EB1-FD38-445A-9A4B-7B481560E9A2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{03BE4EB1-FD38-445A-9A4B-7B481560E9A2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{03BE4EB1-FD38-445A-9A4B-7B481560E9A2}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{03BE4EB1-FD38-445A-9A4B-7B481560E9A2}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{03BE4EB1-FD38-445A-9A4B-7B481560E9A2}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{03BE4EB1-FD38-445A-9A4B-7B481560E9A2}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{03BE4EB1-FD38-445A-9A4B-7B481560E9A2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{03BE4EB1-FD38-445A-9A4B-7B481560E9A2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{03BE4EB1-FD38-445A-9A4B-7B481560E9A2}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{03BE4EB1-FD38-445A-9A4B-7B481560E9A2}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{03BE4EB1-FD38-445A-9A4B-7B481560E9A2}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{03BE4EB1-FD38-445A-9A4B-7B481560E9A2}.Release|x86.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
@@ -118,11 +406,41 @@ Global
|
|||||||
{C829F859-FF48-4025-BF22-8E63672D113C} = {C8E42992-5E42-0C2B-DBFE-AA848D06431C}
|
{C829F859-FF48-4025-BF22-8E63672D113C} = {C8E42992-5E42-0C2B-DBFE-AA848D06431C}
|
||||||
{6C13E9A4-234C-4BF1-A145-F1BBA2AC56CB} = {C8E42992-5E42-0C2B-DBFE-AA848D06431C}
|
{6C13E9A4-234C-4BF1-A145-F1BBA2AC56CB} = {C8E42992-5E42-0C2B-DBFE-AA848D06431C}
|
||||||
{EC447DCF-ABFA-6E24-52A5-D7FD48A5C558} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
|
{EC447DCF-ABFA-6E24-52A5-D7FD48A5C558} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
|
||||||
{0EC62A1A-9858-3A60-8A0C-FC9AACFA2EC7} = {EC447DCF-ABFA-6E24-52A5-D7FD48A5C558}
|
{CA5186C2-289A-9324-4152-9805A73A9773} = {EC447DCF-ABFA-6E24-52A5-D7FD48A5C558}
|
||||||
{5BB2F421-C4C4-40A1-8D6E-FEBB79AE7C98} = {0EC62A1A-9858-3A60-8A0C-FC9AACFA2EC7}
|
{CD14770B-8BCD-4D93-AD2C-581ED030E209} = {CA5186C2-289A-9324-4152-9805A73A9773}
|
||||||
{B4154CE3-9153-E2B0-0515-138FFCE32938} = {EC447DCF-ABFA-6E24-52A5-D7FD48A5C558}
|
{10980DF6-D81A-2FEE-4ACB-4D508FA38BC6} = {EC447DCF-ABFA-6E24-52A5-D7FD48A5C558}
|
||||||
{695CC919-E321-4DC0-8D70-C631C51624E1} = {B4154CE3-9153-E2B0-0515-138FFCE32938}
|
{B97352F3-709A-42CF-A448-07B9996F5FBE} = {10980DF6-D81A-2FEE-4ACB-4D508FA38BC6}
|
||||||
{AB2F334E-DD7C-4314-93B9-941AFC6B2ACD} = {0AB3BF05-4346-4AA6-1389-037BE0695223}
|
{F83653D1-5494-68B8-6444-7DEF58635BF6} = {EC447DCF-ABFA-6E24-52A5-D7FD48A5C558}
|
||||||
{F48A3E3A-EEBB-43AA-81AB-7DD7FE5F29B4} = {0AB3BF05-4346-4AA6-1389-037BE0695223}
|
{BC98E6FC-B46A-4554-B75E-B912714A915C} = {F83653D1-5494-68B8-6444-7DEF58635BF6}
|
||||||
|
{AF61C489-0B09-54BC-BD16-4353135E9C4A} = {EC447DCF-ABFA-6E24-52A5-D7FD48A5C558}
|
||||||
|
{D052C05A-CDCD-48DF-8F4F-0B10E3719819} = {AF61C489-0B09-54BC-BD16-4353135E9C4A}
|
||||||
|
{E9D55F35-C373-3DD8-6914-3213F2F582A2} = {EC447DCF-ABFA-6E24-52A5-D7FD48A5C558}
|
||||||
|
{CF08AE9C-B337-47BA-B273-4B8E5610D7BD} = {E9D55F35-C373-3DD8-6914-3213F2F582A2}
|
||||||
|
{BA37DF67-98D3-4399-BD68-9679396C1547} = {0AB3BF05-4346-4AA6-1389-037BE0695223}
|
||||||
|
{AE120A0E-5815-2D46-946C-DA544028AD88} = {EC447DCF-ABFA-6E24-52A5-D7FD48A5C558}
|
||||||
|
{C0B5496E-F083-413E-90AE-31282A0ACCA5} = {AE120A0E-5815-2D46-946C-DA544028AD88}
|
||||||
|
{4D5D7319-366D-1BD8-49C5-A840B487E852} = {EC447DCF-ABFA-6E24-52A5-D7FD48A5C558}
|
||||||
|
{C905C120-DE44-4CBC-8F98-5BE148115487} = {4D5D7319-366D-1BD8-49C5-A840B487E852}
|
||||||
|
{138B168B-2473-B06D-4BD5-1B010DA319A1} = {EC447DCF-ABFA-6E24-52A5-D7FD48A5C558}
|
||||||
|
{F3EFD119-44F7-46BF-A03C-060F30A1A1E0} = {138B168B-2473-B06D-4BD5-1B010DA319A1}
|
||||||
|
{489D5878-3945-4F8E-AD13-E5499A18DFCC} = {0AB3BF05-4346-4AA6-1389-037BE0695223}
|
||||||
|
{E9E1155A-A339-766C-C185-6698FF423EBC} = {EC447DCF-ABFA-6E24-52A5-D7FD48A5C558}
|
||||||
|
{FFC12440-F128-48F5-9BE5-E5263930F876} = {E9E1155A-A339-766C-C185-6698FF423EBC}
|
||||||
|
{7A402C99-2E66-4EBE-A257-0D7923A96DFD} = {0AB3BF05-4346-4AA6-1389-037BE0695223}
|
||||||
|
{837D2CF4-7AEA-BF76-6362-47ECD7058EEC} = {EC447DCF-ABFA-6E24-52A5-D7FD48A5C558}
|
||||||
|
{716E089D-0661-4D39-813B-063DF9A4C0E4} = {837D2CF4-7AEA-BF76-6362-47ECD7058EEC}
|
||||||
|
{43E6E19C-39EC-49C8-91EE-49586A4B9D03} = {0AB3BF05-4346-4AA6-1389-037BE0695223}
|
||||||
|
{4BC86D3F-8D7B-ACB9-EA51-9374BC9D421A} = {EC447DCF-ABFA-6E24-52A5-D7FD48A5C558}
|
||||||
|
{2498C58C-53B0-4DF2-B4EA-BA69B35A7488} = {4BC86D3F-8D7B-ACB9-EA51-9374BC9D421A}
|
||||||
|
{4394178B-1ADD-478E-BF73-574B31C11292} = {0AB3BF05-4346-4AA6-1389-037BE0695223}
|
||||||
|
{2F2C7E01-5791-4A6D-9A80-C71CAD846FA8} = {0AB3BF05-4346-4AA6-1389-037BE0695223}
|
||||||
|
{76706BA9-11E0-463A-AF8E-18DFBD9E95A2} = {0AB3BF05-4346-4AA6-1389-037BE0695223}
|
||||||
|
{0587C5BB-3015-204D-19B6-EB01E03E48B6} = {EC447DCF-ABFA-6E24-52A5-D7FD48A5C558}
|
||||||
|
{AEFD93B4-59B8-4B02-A694-CA15E4EC1C08} = {0587C5BB-3015-204D-19B6-EB01E03E48B6}
|
||||||
|
{C11BFE93-017D-4538-A61F-A8D98F8D2D75} = {0AB3BF05-4346-4AA6-1389-037BE0695223}
|
||||||
|
{38276FFF-05D8-4005-8863-018CEE833D66} = {0AB3BF05-4346-4AA6-1389-037BE0695223}
|
||||||
|
{32AC7906-B197-4628-9C47-9337BB5A53E2} = {0AB3BF05-4346-4AA6-1389-037BE0695223}
|
||||||
|
{DD6FAF9E-10A0-95E7-0C06-698A6F70AFEE} = {EC447DCF-ABFA-6E24-52A5-D7FD48A5C558}
|
||||||
|
{03BE4EB1-FD38-445A-9A4B-7B481560E9A2} = {DD6FAF9E-10A0-95E7-0C06-698A6F70AFEE}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net10.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="coverlet.collector" Version="6.0.4" />
|
||||||
|
<PackageReference Include="FluentAssertions" Version="8.0.1" />
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.0" />
|
||||||
|
<PackageReference Include="NSubstitute" Version="5.3.0" />
|
||||||
|
<PackageReference Include="xunit" Version="2.9.2" />
|
||||||
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Using Include="Xunit" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\src\Modules\Admin\Knot.Modules.Admin.csproj" />
|
||||||
|
<ProjectReference Include="..\..\src\Shared\Knot.Shared.Kernel\Knot.Shared.Kernel.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
using FluentAssertions;
|
||||||
|
using Host.Application.Admin.Commands;
|
||||||
|
using Knot.Modules.Auth.Application.Abstractions;
|
||||||
|
using Knot.Modules.Auth.Domain;
|
||||||
|
using Knot.Shared.Kernel;
|
||||||
|
using NSubstitute;
|
||||||
|
using Xunit;
|
||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Knot.Modules.Admin.UnitTests;
|
||||||
|
|
||||||
|
public class ResetUserPasswordCommandHandlerTests
|
||||||
|
{
|
||||||
|
private readonly IAuthUnitOfWork _authUnitOfWork;
|
||||||
|
private readonly IUserRepository _userRepository;
|
||||||
|
private readonly ResetUserPasswordCommandHandler _handler;
|
||||||
|
|
||||||
|
public ResetUserPasswordCommandHandlerTests()
|
||||||
|
{
|
||||||
|
_authUnitOfWork = Substitute.For<IAuthUnitOfWork>();
|
||||||
|
_userRepository = Substitute.For<IUserRepository>();
|
||||||
|
_handler = new ResetUserPasswordCommandHandler(_userRepository, _authUnitOfWork);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Handle_ShouldReturnError_WhenUserNotFound()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var command = new ResetUserPasswordCommand(Guid.NewGuid(), "NewP@ssw0rd");
|
||||||
|
_userRepository.GetByIdAsync(command.UserId, Arg.Any<CancellationToken>()).Returns((User?)null);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = await _handler.Handle(command, CancellationToken.None);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
result.IsFailure.Should().BeTrue();
|
||||||
|
result.Error.Should().Be(AuthErrors.UserNotFound);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Handle_ShouldSucceed_WhenUserFound()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var user = User.Create("User", "pass", "salt", "admin");
|
||||||
|
var command = new ResetUserPasswordCommand(user.Id, "NewP@ssw0rd");
|
||||||
|
|
||||||
|
_userRepository.GetByIdAsync(command.UserId, Arg.Any<CancellationToken>()).Returns(user);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = await _handler.Handle(command, CancellationToken.None);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
result.IsSuccess.Should().BeTrue();
|
||||||
|
await _authUnitOfWork.Received(1).SaveChangesAsync(Arg.Any<CancellationToken>());
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
-1
@@ -23,7 +23,9 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\..\src\Modules\Identity\Knot.Modules.Identity.csproj" />
|
<ProjectReference Include="..\..\src\Modules\Identity\Knot.Modules.Auth.csproj" />
|
||||||
|
<ProjectReference Include="..\..\src\Modules\Auth\Knot.Modules.Auth.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
||||||
+8
-7
@@ -1,15 +1,15 @@
|
|||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using NSubstitute;
|
using NSubstitute;
|
||||||
using Knot.Modules.Identity.Application.Abstractions;
|
using Knot.Modules.Auth.Application.Abstractions;
|
||||||
using Knot.Modules.Identity.Application.Users.Login;
|
using Knot.Modules.Auth.Application.Users.Login;
|
||||||
using Knot.Modules.Identity.Domain;
|
using Knot.Modules.Auth.Domain;
|
||||||
using Knot.Shared.Kernel;
|
using Knot.Shared.Kernel;
|
||||||
using Knot.Modules.Identity.Application.Users.Auth;
|
using Knot.Modules.Auth.Application.Users.Auth;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Knot.Modules.Identity.UnitTests;
|
namespace Knot.Modules.Auth.UnitTests;
|
||||||
|
|
||||||
public class LoginUserCommandHandlerTests
|
public class LoginUserCommandHandlerTests
|
||||||
{
|
{
|
||||||
@@ -61,7 +61,7 @@ public class LoginUserCommandHandlerTests
|
|||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
result.IsFailure.Should().BeTrue();
|
result.IsFailure.Should().BeTrue();
|
||||||
result.Error.Code.Should().Be(IdentityErrors.IdentityInvalidCredentials.Code);
|
result.Error.Code.Should().Be(AuthErrors.IdentityInvalidCredentials.Code);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@@ -82,6 +82,7 @@ public class LoginUserCommandHandlerTests
|
|||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
result.IsFailure.Should().BeTrue();
|
result.IsFailure.Should().BeTrue();
|
||||||
result.Error.Code.Should().Be(IdentityErrors.IdentityInvalidCredentials.Code);
|
result.Error.Code.Should().Be(AuthErrors.IdentityInvalidCredentials.Code);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
+7
-4
@@ -7,11 +7,12 @@ using FluentAssertions;
|
|||||||
using NSubstitute;
|
using NSubstitute;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
using Knot.Shared.Kernel;
|
using Knot.Shared.Kernel;
|
||||||
using Knot.Modules.Chats.Domain;
|
using Knot.Modules.Conversations.Domain;
|
||||||
using Knot.Modules.Chats.Application.Abstractions;
|
using Knot.Modules.Messaging.Domain;
|
||||||
using Knot.Modules.Chats.Application.Chats.Create;
|
using Knot.Modules.Conversations.Application.Abstractions;
|
||||||
|
using Knot.Modules.Conversations.Application.Chats.Create;
|
||||||
|
|
||||||
namespace Knot.Modules.Chats.UnitTests.Chats;
|
namespace Knot.Modules.Conversations.UnitTests.Chats;
|
||||||
|
|
||||||
public class CreateChatCommandHandlerTests
|
public class CreateChatCommandHandlerTests
|
||||||
{
|
{
|
||||||
@@ -49,3 +50,5 @@ public class CreateChatCommandHandlerTests
|
|||||||
await _unitOfWork.Received(1).SaveChangesAsync(Arg.Any<CancellationToken>());
|
await _unitOfWork.Received(1).SaveChangesAsync(Arg.Any<CancellationToken>());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
+8
-5
@@ -7,12 +7,13 @@ using FluentAssertions;
|
|||||||
using NSubstitute;
|
using NSubstitute;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
using Knot.Shared.Kernel;
|
using Knot.Shared.Kernel;
|
||||||
using Knot.Modules.Chats.Domain;
|
using Knot.Modules.Conversations.Domain;
|
||||||
using Knot.Modules.Chats.Application.Abstractions;
|
using Knot.Modules.Messaging.Domain;
|
||||||
using Knot.Modules.Chats.Application.Chats.GetChats;
|
using Knot.Modules.Conversations.Application.Abstractions;
|
||||||
using Knot.Modules.Chats.Application.DTOs;
|
using Knot.Modules.Conversations.Application.Chats.GetChats;
|
||||||
|
using Knot.Modules.Conversations.Application.DTOs;
|
||||||
|
|
||||||
namespace Knot.Modules.Chats.UnitTests.Chats;
|
namespace Knot.Modules.Conversations.UnitTests.Chats;
|
||||||
|
|
||||||
public class GetChatsQueryHandlerTests
|
public class GetChatsQueryHandlerTests
|
||||||
{
|
{
|
||||||
@@ -69,3 +70,5 @@ public class GetChatsQueryHandlerTests
|
|||||||
result.Value.Any(c => c.Type == "favorites").Should().BeTrue();
|
result.Value.Any(c => c.Type == "favorites").Should().BeTrue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
+42
@@ -0,0 +1,42 @@
|
|||||||
|
using FluentAssertions;
|
||||||
|
using Knot.Modules.Conversations.Application.Chats.Commands.CreatePersonalChat;
|
||||||
|
using Knot.Modules.Conversations.Domain;
|
||||||
|
using Knot.Modules.Conversations.Application.Abstractions;
|
||||||
|
using Knot.Shared.Kernel;
|
||||||
|
using NSubstitute;
|
||||||
|
using Xunit;
|
||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Knot.Modules.Conversations.UnitTests;
|
||||||
|
|
||||||
|
public class CreatePersonalChatCommandHandlerTests
|
||||||
|
{
|
||||||
|
private readonly IChatRepository _chatRepository;
|
||||||
|
private readonly IChatsUnitOfWork _unitOfWork;
|
||||||
|
private readonly CreatePersonalChatCommandHandler _handler;
|
||||||
|
|
||||||
|
public CreatePersonalChatCommandHandlerTests()
|
||||||
|
{
|
||||||
|
_chatRepository = Substitute.For<IChatRepository>();
|
||||||
|
_unitOfWork = Substitute.For<IChatsUnitOfWork>();
|
||||||
|
_handler = new CreatePersonalChatCommandHandler(_chatRepository, _unitOfWork);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Handle_ShouldReturnError_WhenChatAlreadyExists()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var command = new CreatePersonalChatCommand(Guid.NewGuid(), Guid.NewGuid());
|
||||||
|
_chatRepository.GetPersonalChatAsync(command.InitiatorId, command.TargetUserId, Arg.Any<CancellationToken>())
|
||||||
|
.Returns(PersonalChat.Create(command.InitiatorId, command.TargetUserId));
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = await _handler.Handle(command, CancellationToken.None);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
result.IsFailure.Should().BeTrue();
|
||||||
|
result.Error.Should().Be(ChatErrors.PersonalChatAlreadyExists);
|
||||||
|
}
|
||||||
|
}
|
||||||
+7
-4
@@ -1,12 +1,13 @@
|
|||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using NSubstitute;
|
using NSubstitute;
|
||||||
using Knot.Modules.Chats.Application.Abstractions;
|
using Knot.Modules.Conversations.Application.Abstractions;
|
||||||
using Knot.Modules.Chats.Application.Chats.GetOrCreateFavorites;
|
using Knot.Modules.Conversations.Application.Chats.GetOrCreateFavorites;
|
||||||
using Knot.Modules.Chats.Domain;
|
using Knot.Modules.Conversations.Domain;
|
||||||
|
using Knot.Modules.Messaging.Domain;
|
||||||
using Knot.Shared.Kernel;
|
using Knot.Shared.Kernel;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Knot.Modules.Chats.UnitTests;
|
namespace Knot.Modules.Conversations.UnitTests;
|
||||||
|
|
||||||
public class GetOrCreateFavoritesCommandHandlerTests
|
public class GetOrCreateFavoritesCommandHandlerTests
|
||||||
{
|
{
|
||||||
@@ -69,3 +70,5 @@ public class GetOrCreateFavoritesCommandHandlerTests
|
|||||||
await _unitOfWork.Received(1).SaveChangesAsync(Arg.Any<CancellationToken>());
|
await _unitOfWork.Received(1).SaveChangesAsync(Arg.Any<CancellationToken>());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
+3
-1
@@ -23,7 +23,9 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\..\src\Modules\Chats\Knot.Modules.Chats.csproj" />
|
<ProjectReference Include="..\..\src\Modules\Chats\Knot.Modules.Conversations.csproj" />
|
||||||
|
<ProjectReference Include="..\..\src\Modules\Messaging\Knot.Modules.Messaging.csproj" />
|
||||||
|
<ProjectReference Include="..\..\src\Modules\Conversations\Knot.Modules.Conversations.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
+7
-4
@@ -8,11 +8,12 @@ using MediatR;
|
|||||||
using NSubstitute;
|
using NSubstitute;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
using Knot.Shared.Kernel;
|
using Knot.Shared.Kernel;
|
||||||
using Knot.Modules.Chats.Domain;
|
using Knot.Modules.Conversations.Domain;
|
||||||
using Knot.Modules.Chats.Application.Abstractions;
|
using Knot.Modules.Messaging.Domain;
|
||||||
using Knot.Modules.Chats.Application.Messages.Send;
|
using Knot.Modules.Conversations.Application.Abstractions;
|
||||||
|
using Knot.Modules.Conversations.Application.Messages.Send;
|
||||||
|
|
||||||
namespace Knot.Modules.Chats.UnitTests.Messages;
|
namespace Knot.Modules.Conversations.UnitTests.Messages;
|
||||||
|
|
||||||
public class SendMessageCommandHandlerTests
|
public class SendMessageCommandHandlerTests
|
||||||
{
|
{
|
||||||
@@ -95,3 +96,5 @@ public class SendMessageCommandHandlerTests
|
|||||||
await _unitOfWork.Received(1).SaveChangesAsync(Arg.Any<CancellationToken>());
|
await _unitOfWork.Received(1).SaveChangesAsync(Arg.Any<CancellationToken>());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
+28
@@ -0,0 +1,28 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net10.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="coverlet.collector" Version="6.0.4" />
|
||||||
|
<PackageReference Include="FluentAssertions" Version="8.0.1" />
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.0" />
|
||||||
|
<PackageReference Include="NSubstitute" Version="5.3.0" />
|
||||||
|
<PackageReference Include="xunit" Version="2.9.2" />
|
||||||
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Using Include="Xunit" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\src\Modules\Federation\Knot.Modules.Federation.csproj" />
|
||||||
|
<ProjectReference Include="..\..\src\Shared\Knot.Shared.Kernel\Knot.Shared.Kernel.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net10.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="coverlet.collector" Version="6.0.4" />
|
||||||
|
<PackageReference Include="FluentAssertions" Version="8.0.1" />
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.0" />
|
||||||
|
<PackageReference Include="NSubstitute" Version="5.3.0" />
|
||||||
|
<PackageReference Include="xunit" Version="2.9.2" />
|
||||||
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Using Include="Xunit" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\src\Modules\Klipy\Knot.Modules.Klipy.csproj" />
|
||||||
|
<ProjectReference Include="..\..\src\Shared\Knot.Shared.Kernel\Knot.Shared.Kernel.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
+22
@@ -0,0 +1,22 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net10.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="coverlet.collector" Version="6.0.4" />
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.0" />
|
||||||
|
<PackageReference Include="NSubstitute" Version="5.3.0" />
|
||||||
|
<PackageReference Include="xunit" Version="2.9.2" />
|
||||||
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Using Include="Xunit" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net10.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="coverlet.collector" Version="6.0.4" />
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.0" />
|
||||||
|
<PackageReference Include="NSubstitute" Version="5.3.0" />
|
||||||
|
<PackageReference Include="xunit" Version="2.9.2" />
|
||||||
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Using Include="Xunit" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
using FluentAssertions;
|
||||||
|
using Knot.Modules.Profiles.Application.Profiles.Commands.UpdateProfile;
|
||||||
|
using Knot.Modules.Profiles.Domain;
|
||||||
|
using Knot.Modules.Profiles.Application.Abstractions;
|
||||||
|
using Knot.Shared.Kernel;
|
||||||
|
using NSubstitute;
|
||||||
|
using Xunit;
|
||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Knot.Modules.Profiles.UnitTests;
|
||||||
|
|
||||||
|
public class UpdateProfileCommandHandlerTests
|
||||||
|
{
|
||||||
|
private readonly IProfileRepository _profileRepository;
|
||||||
|
private readonly IProfilesUnitOfWork _unitOfWork;
|
||||||
|
private readonly UpdateProfileCommandHandler _handler;
|
||||||
|
|
||||||
|
public UpdateProfileCommandHandlerTests()
|
||||||
|
{
|
||||||
|
_profileRepository = Substitute.For<IProfileRepository>();
|
||||||
|
_unitOfWork = Substitute.For<IProfilesUnitOfWork>();
|
||||||
|
_handler = new UpdateProfileCommandHandler(_profileRepository, _unitOfWork);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Handle_ShouldReturnError_WhenProfileNotFound()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var command = new UpdateProfileCommand(Guid.NewGuid(), "FirstName", "LastName", "Bio");
|
||||||
|
_profileRepository.GetByIdAsync(command.UserId, Arg.Any<CancellationToken>()).Returns((UserProfile?)null);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = await _handler.Handle(command, CancellationToken.None);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
result.IsFailure.Should().BeTrue();
|
||||||
|
result.Error.Should().Be(ProfileErrors.NotFound);
|
||||||
|
}
|
||||||
|
}
|
||||||
+28
@@ -0,0 +1,28 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net10.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="coverlet.collector" Version="6.0.4" />
|
||||||
|
<PackageReference Include="FluentAssertions" Version="8.0.1" />
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.0" />
|
||||||
|
<PackageReference Include="NSubstitute" Version="5.3.0" />
|
||||||
|
<PackageReference Include="xunit" Version="2.9.2" />
|
||||||
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Using Include="Xunit" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\src\Modules\Relations\Knot.Modules.Relations.csproj" />
|
||||||
|
<ProjectReference Include="..\..\src\Shared\Knot.Shared.Kernel\Knot.Shared.Kernel.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
namespace Knot.Modules.Relations.UnitTests;
|
||||||
|
|
||||||
|
public class UnitTest1
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void Test1()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net10.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="coverlet.collector" Version="6.0.4" />
|
||||||
|
<PackageReference Include="FluentAssertions" Version="8.0.1" />
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.0" />
|
||||||
|
<PackageReference Include="NSubstitute" Version="5.3.0" />
|
||||||
|
<PackageReference Include="xunit" Version="2.9.2" />
|
||||||
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Using Include="Xunit" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\src\Modules\Settings\Knot.Modules.Settings.csproj" />
|
||||||
|
<ProjectReference Include="..\..\src\Shared\Knot.Shared.Kernel\Knot.Shared.Kernel.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
namespace Knot.Modules.Settings.UnitTests;
|
||||||
|
|
||||||
|
public class UnitTest1
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void Test1()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net10.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="coverlet.collector" Version="6.0.4" />
|
||||||
|
<PackageReference Include="FluentAssertions" Version="8.0.1" />
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.0" />
|
||||||
|
<PackageReference Include="NSubstitute" Version="5.3.0" />
|
||||||
|
<PackageReference Include="xunit" Version="2.9.2" />
|
||||||
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Using Include="Xunit" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\src\Modules\Storage\Knot.Modules.Storage.csproj" />
|
||||||
|
<ProjectReference Include="..\..\src\Shared\Knot.Shared.Kernel\Knot.Shared.Kernel.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
namespace Knot.Modules.Storage.UnitTests;
|
||||||
|
|
||||||
|
public class UnitTest1
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void Test1()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net10.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="coverlet.collector" Version="6.0.4" />
|
||||||
|
<PackageReference Include="FluentAssertions" Version="8.0.1" />
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.0" />
|
||||||
|
<PackageReference Include="NSubstitute" Version="5.3.0" />
|
||||||
|
<PackageReference Include="xunit" Version="2.9.2" />
|
||||||
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Using Include="Xunit" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\src\Modules\Stories\Knot.Modules.Stories.csproj" />
|
||||||
|
<ProjectReference Include="..\..\src\Shared\Knot.Shared.Kernel\Knot.Shared.Kernel.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
namespace Knot.Modules.Stories.UnitTests;
|
||||||
|
|
||||||
|
public class UnitTest1
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void Test1()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
+28
@@ -0,0 +1,28 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net10.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="coverlet.collector" Version="6.0.4" />
|
||||||
|
<PackageReference Include="FluentAssertions" Version="8.0.1" />
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.0" />
|
||||||
|
<PackageReference Include="NSubstitute" Version="5.3.0" />
|
||||||
|
<PackageReference Include="xunit" Version="2.9.2" />
|
||||||
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Using Include="Xunit" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\src\Modules\TelegramImport\Knot.Modules.TelegramImport.csproj" />
|
||||||
|
<ProjectReference Include="..\..\src\Shared\Knot.Shared.Kernel\Knot.Shared.Kernel.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
namespace Knot.Modules.TelegramImport.UnitTests;
|
||||||
|
|
||||||
|
public class UnitTest1
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void Test1()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net10.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="coverlet.collector" Version="6.0.4" />
|
||||||
|
<PackageReference Include="FluentAssertions" Version="8.0.1" />
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.0" />
|
||||||
|
<PackageReference Include="NSubstitute" Version="5.3.0" />
|
||||||
|
<PackageReference Include="xunit" Version="2.9.2" />
|
||||||
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Using Include="Xunit" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\src\Modules\WebRtc\Knot.Modules.WebRtc.csproj" />
|
||||||
|
<ProjectReference Include="..\..\src\Shared\Knot.Shared.Kernel\Knot.Shared.Kernel.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
namespace Knot.Modules.WebRtc.UnitTests;
|
||||||
|
|
||||||
|
public class UnitTest1
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void Test1()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,110 +0,0 @@
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Host.Models;
|
|
||||||
using Knot.Shared.Kernel.Configuration;
|
|
||||||
using Knot.Modules.Identity.Application.Users.Register;
|
|
||||||
using Knot.Shared.Kernel.Storage;
|
|
||||||
using Knot.Modules.Identity.Infrastructure.Persistence;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System;
|
|
||||||
using MediatR;
|
|
||||||
using Host.Application.Admin.Queries;
|
|
||||||
using Host.Application.Admin.Commands;
|
|
||||||
|
|
||||||
using Microsoft.AspNetCore.Authorization;
|
|
||||||
|
|
||||||
namespace Host.Controllers;
|
|
||||||
|
|
||||||
[AllowAnonymous]
|
|
||||||
[ApiController]
|
|
||||||
[Route("api/[controller]")]
|
|
||||||
public class AdminController : ControllerBase
|
|
||||||
{
|
|
||||||
private readonly ISender _sender;
|
|
||||||
|
|
||||||
public AdminController(ISender sender)
|
|
||||||
{
|
|
||||||
_sender = sender;
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpGet("settings")]
|
|
||||||
public async Task<IActionResult> GetSettings(CancellationToken ct)
|
|
||||||
{
|
|
||||||
var result = await _sender.Send(new GetSettingsQuery(), ct);
|
|
||||||
return Ok(result.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpPut("settings")]
|
|
||||||
public async Task<IActionResult> UpdateSettings([FromBody] SystemSettingsDto settings, CancellationToken ct)
|
|
||||||
{
|
|
||||||
var result = await _sender.Send(new UpdateSettingsCommand(settings), ct);
|
|
||||||
return Ok(result.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpGet("dashboard")]
|
|
||||||
public async Task<IActionResult> GetDashboardStats(CancellationToken ct)
|
|
||||||
{
|
|
||||||
var result = await _sender.Send(new GetDashboardStatsQuery(), ct);
|
|
||||||
return Ok(result.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpPost("users")]
|
|
||||||
public async Task<IActionResult> CreateUser([FromBody] RegisterUserCommand command, CancellationToken ct)
|
|
||||||
{
|
|
||||||
var result = await _sender.Send(command, ct);
|
|
||||||
if (result.IsFailure) return BadRequest(new { error = result.Error.Description });
|
|
||||||
|
|
||||||
var userDetails = await _sender.Send(new GetUserDetailsQuery(result.Value.User.Id), ct);
|
|
||||||
return Ok(userDetails.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpPost("users/{userId:guid}/reset-password")]
|
|
||||||
public async Task<IActionResult> ResetUserPassword(Guid userId, [FromBody] ResetPasswordDto dto, CancellationToken ct)
|
|
||||||
{
|
|
||||||
var result = await _sender.Send(new ResetUserPasswordCommand(userId, dto.NewPassword), ct);
|
|
||||||
if (result.IsFailure)
|
|
||||||
{
|
|
||||||
if (result.Error.Code == "User.NotFound") return NotFound(new { error = "User not found" });
|
|
||||||
return BadRequest(new { error = result.Error.Description });
|
|
||||||
}
|
|
||||||
return Ok(result.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpGet("users")]
|
|
||||||
public async Task<IActionResult> SearchUsers([FromQuery] string query = "", CancellationToken ct = default)
|
|
||||||
{
|
|
||||||
var result = await _sender.Send(new SearchUsersQuery(query), ct);
|
|
||||||
return Ok(result.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpGet("users/{id:guid}")]
|
|
||||||
public async Task<IActionResult> GetUserDetails(Guid id, CancellationToken ct)
|
|
||||||
{
|
|
||||||
var result = await _sender.Send(new GetUserDetailsQuery(id), ct);
|
|
||||||
if (result.IsFailure)
|
|
||||||
{
|
|
||||||
return NotFound("User not found");
|
|
||||||
}
|
|
||||||
return Ok(result.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpGet("clean/dry-run")]
|
|
||||||
public async Task<IActionResult> CleanDryRun(
|
|
||||||
[FromServices] IFileStorageService fileStorage,
|
|
||||||
[FromServices] IdentityDbContext identityDb,
|
|
||||||
CancellationToken ct)
|
|
||||||
{
|
|
||||||
var result = await _sender.Send(new CleanDryRunQuery(fileStorage, identityDb), ct);
|
|
||||||
return Ok(result.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpPost("clean/run")]
|
|
||||||
public async Task<IActionResult> CleanRun(
|
|
||||||
[FromServices] IFileStorageService fileStorage,
|
|
||||||
[FromServices] IdentityDbContext identityDb,
|
|
||||||
CancellationToken ct)
|
|
||||||
{
|
|
||||||
var result = await _sender.Send(new CleanRunCommand(fileStorage, identityDb), ct);
|
|
||||||
return Ok(result.Value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.AspNetCore.Authorization;
|
|
||||||
using Knot.Shared.Kernel;
|
|
||||||
using Knot.Modules.Identity.Application.Users.Auth;
|
|
||||||
using Knot.Modules.Identity.Application.Users.Register;
|
|
||||||
using Knot.Modules.Identity.Application.Users.Login;
|
|
||||||
using Knot.Modules.Identity.Application.Users.GetMe;
|
|
||||||
using MediatR;
|
|
||||||
|
|
||||||
namespace Host.Controllers;
|
|
||||||
|
|
||||||
[ApiController]
|
|
||||||
[Route("api/[controller]")]
|
|
||||||
public sealed class AuthController : ControllerBase
|
|
||||||
{
|
|
||||||
private readonly ISender _sender;
|
|
||||||
|
|
||||||
public AuthController(ISender sender)
|
|
||||||
{
|
|
||||||
_sender = sender;
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpPost("register")]
|
|
||||||
public async Task<IActionResult> Register([FromBody] RegisterUserCommand command, CancellationToken ct)
|
|
||||||
{
|
|
||||||
var result = await _sender.Send(command, ct);
|
|
||||||
if (result.IsFailure) return BadRequest(new { error = result.Error.Code ?? result.Error.Description });
|
|
||||||
return Ok(result.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpGet("me")]
|
|
||||||
[Authorize]
|
|
||||||
public async Task<IActionResult> GetMe([FromServices] IUserContext userContext, CancellationToken ct)
|
|
||||||
{
|
|
||||||
var result = await _sender.Send(new GetMeQuery(userContext.UserId), ct);
|
|
||||||
if (result.IsFailure)
|
|
||||||
{
|
|
||||||
return NotFound();
|
|
||||||
}
|
|
||||||
return Ok(new { User = result.Value.User });
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpPost("login")]
|
|
||||||
public async Task<IActionResult> Login([FromBody] LoginUserCommand command, CancellationToken ct)
|
|
||||||
{
|
|
||||||
var result = await _sender.Send(command, ct);
|
|
||||||
if (result.IsFailure) return Unauthorized(new { error = result.Error.Code ?? result.Error.Description });
|
|
||||||
return Ok(result.Value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,241 +0,0 @@
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.AspNetCore.Authorization;
|
|
||||||
using Knot.Shared.Kernel;
|
|
||||||
using Knot.Modules.Chats.Application.DTOs;
|
|
||||||
using Knot.Shared.Kernel.Storage;
|
|
||||||
using Knot.Modules.Chats.Application.Chats.GetChats;
|
|
||||||
using Knot.Modules.Chats.Application.Chats.GetChatById;
|
|
||||||
using Knot.Modules.Chats.Application.Chats.Create;
|
|
||||||
using Knot.Modules.Chats.Application.Chats.GetOrCreateFavorites;
|
|
||||||
using Knot.Modules.Chats.Application.Chats.Update;
|
|
||||||
using Knot.Modules.Chats.Application.Chats.LeaveOrDelete;
|
|
||||||
using Knot.Modules.Chats.Application.Chats.Clear;
|
|
||||||
using Knot.Modules.Chats.Application.Chats.TogglePin;
|
|
||||||
using Knot.Modules.Chats.Application.Chats.Members;
|
|
||||||
using Knot.Modules.Chats.Application.Chats.Avatar;
|
|
||||||
using Knot.Modules.Chats.Domain;
|
|
||||||
using MediatR;
|
|
||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Host.Controllers;
|
|
||||||
|
|
||||||
[Authorize]
|
|
||||||
[ApiController]
|
|
||||||
[Route("api/chats")]
|
|
||||||
public sealed class ChatsController : ControllerBase
|
|
||||||
{
|
|
||||||
private readonly ISender _sender;
|
|
||||||
private readonly IUserContext _userContext;
|
|
||||||
|
|
||||||
public ChatsController(ISender sender, IUserContext userContext)
|
|
||||||
{
|
|
||||||
_sender = sender;
|
|
||||||
_userContext = userContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpGet]
|
|
||||||
public async Task<IActionResult> GetChats(CancellationToken ct)
|
|
||||||
{
|
|
||||||
var result = await _sender.Send(new GetChatsQuery(_userContext.UserId), ct);
|
|
||||||
if (result.IsFailure)
|
|
||||||
{
|
|
||||||
return BadRequest(result.Error.Description);
|
|
||||||
}
|
|
||||||
return Ok(result.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpPost]
|
|
||||||
public async Task<IActionResult> Create([FromBody] CreateChatRequest request, CancellationToken ct)
|
|
||||||
{
|
|
||||||
var command = new CreateChatCommand(request.Name, request.Type, request.MemberIds);
|
|
||||||
var result = await _sender.Send(command, ct);
|
|
||||||
if (result.IsFailure)
|
|
||||||
{
|
|
||||||
return BadRequest(result.Error.Description);
|
|
||||||
}
|
|
||||||
|
|
||||||
var chatResult = await _sender.Send(new GetChatByIdQuery(_userContext.UserId, result.Value), ct);
|
|
||||||
return Ok(chatResult.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpPost("personal")]
|
|
||||||
public async Task<IActionResult> CreatePersonal([FromBody] CreatePersonalChatRequest request, CancellationToken ct)
|
|
||||||
{
|
|
||||||
var command = new CreateChatCommand(string.Empty, ChatType.Personal, new List<Guid> { _userContext.UserId, request.UserId });
|
|
||||||
var result = await _sender.Send(command, ct);
|
|
||||||
if (result.IsFailure)
|
|
||||||
{
|
|
||||||
return BadRequest(result.Error.Description);
|
|
||||||
}
|
|
||||||
|
|
||||||
var chatResult = await _sender.Send(new GetChatByIdQuery(_userContext.UserId, result.Value), ct);
|
|
||||||
return Ok(chatResult.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpPost("group")]
|
|
||||||
public async Task<IActionResult> CreateGroup([FromBody] CreateGroupChatRequest request, CancellationToken ct)
|
|
||||||
{
|
|
||||||
var memberIds = request.MemberIds.ToList();
|
|
||||||
if (memberIds.Contains(_userContext.UserId))
|
|
||||||
{
|
|
||||||
memberIds.Remove(_userContext.UserId);
|
|
||||||
}
|
|
||||||
memberIds.Insert(0, _userContext.UserId);
|
|
||||||
|
|
||||||
var command = new CreateChatCommand(request.Name, ChatType.Group, memberIds);
|
|
||||||
var result = await _sender.Send(command, ct);
|
|
||||||
if (result.IsFailure)
|
|
||||||
{
|
|
||||||
return BadRequest(result.Error.Description);
|
|
||||||
}
|
|
||||||
|
|
||||||
var chatResult = await _sender.Send(new GetChatByIdQuery(_userContext.UserId, result.Value), ct);
|
|
||||||
return Ok(chatResult.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpPost("favorites")]
|
|
||||||
public async Task<IActionResult> GetOrCreateFavorites(CancellationToken ct)
|
|
||||||
{
|
|
||||||
var result = await _sender.Send(new GetOrCreateFavoritesCommand(_userContext.UserId), ct);
|
|
||||||
if (result.IsFailure)
|
|
||||||
{
|
|
||||||
return BadRequest(result.Error.Description);
|
|
||||||
}
|
|
||||||
|
|
||||||
var chatResult = await _sender.Send(new GetChatByIdQuery(_userContext.UserId, result.Value), ct);
|
|
||||||
return Ok(chatResult.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpPut("{id:guid}")]
|
|
||||||
public async Task<IActionResult> UpdateChat(Guid id, [FromBody] UpdateChatRequest request, CancellationToken ct)
|
|
||||||
{
|
|
||||||
var result = await _sender.Send(new UpdateChatCommand(id, _userContext.UserId, request.Name, request.Description), ct);
|
|
||||||
if (result.IsFailure)
|
|
||||||
{
|
|
||||||
return NotFound();
|
|
||||||
}
|
|
||||||
|
|
||||||
var chatResult = await _sender.Send(new GetChatByIdQuery(_userContext.UserId, result.Value), ct);
|
|
||||||
return Ok(chatResult.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpDelete("{id:guid}")]
|
|
||||||
public async Task<IActionResult> LeaveOrDeleteChat(Guid id, CancellationToken ct)
|
|
||||||
{
|
|
||||||
var result = await _sender.Send(new LeaveOrDeleteChatCommand(id, _userContext.UserId), ct);
|
|
||||||
if (result.IsFailure)
|
|
||||||
{
|
|
||||||
if (result.Error.Code == "Unauthorized")
|
|
||||||
{
|
|
||||||
return Forbid();
|
|
||||||
}
|
|
||||||
return NotFound();
|
|
||||||
}
|
|
||||||
return Ok(result.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpPost("{id:guid}/clear")]
|
|
||||||
public async Task<IActionResult> ClearChat(Guid id, CancellationToken ct)
|
|
||||||
{
|
|
||||||
var result = await _sender.Send(new ClearChatCommand(id, _userContext.UserId), ct);
|
|
||||||
if (result.IsFailure)
|
|
||||||
{
|
|
||||||
return NotFound();
|
|
||||||
}
|
|
||||||
return Ok(result.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpPost("{id:guid}/pin")]
|
|
||||||
public async Task<IActionResult> TogglePin(Guid id, CancellationToken ct)
|
|
||||||
{
|
|
||||||
var result = await _sender.Send(new TogglePinCommand(id, _userContext.UserId), ct);
|
|
||||||
if (result.IsFailure)
|
|
||||||
{
|
|
||||||
return NotFound();
|
|
||||||
}
|
|
||||||
return Ok(result.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpPost("{id:guid}/members")]
|
|
||||||
public async Task<IActionResult> AddMembers(Guid id, [FromBody] AddMembersRequest request, CancellationToken ct)
|
|
||||||
{
|
|
||||||
var result = await _sender.Send(new AddMembersCommand(id, _userContext.UserId, request.UserIds.ToList()), ct);
|
|
||||||
if (result.IsFailure)
|
|
||||||
{
|
|
||||||
return NotFound();
|
|
||||||
}
|
|
||||||
|
|
||||||
var chatResult = await _sender.Send(new GetChatByIdQuery(_userContext.UserId, result.Value), ct);
|
|
||||||
return Ok(chatResult.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpDelete("{id:guid}/members/{userId:guid}")]
|
|
||||||
public async Task<IActionResult> RemoveMember(Guid id, Guid userId, CancellationToken ct)
|
|
||||||
{
|
|
||||||
var result = await _sender.Send(new RemoveMemberCommand(id, _userContext.UserId, userId), ct);
|
|
||||||
if (result.IsFailure)
|
|
||||||
{
|
|
||||||
return NotFound();
|
|
||||||
}
|
|
||||||
|
|
||||||
var chatResult = await _sender.Send(new GetChatByIdQuery(_userContext.UserId, result.Value), ct);
|
|
||||||
return Ok(chatResult.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpPost("{id:guid}/avatar")]
|
|
||||||
public async Task<IActionResult> UploadGroupAvatar(Guid id, Microsoft.AspNetCore.Http.IFormFile avatar, CancellationToken ct)
|
|
||||||
{
|
|
||||||
if (avatar == null || avatar.Length == 0)
|
|
||||||
{
|
|
||||||
return BadRequest("No file");
|
|
||||||
}
|
|
||||||
|
|
||||||
using var stream = avatar.OpenReadStream();
|
|
||||||
var result = await _sender.Send(new UploadGroupAvatarCommand(id, _userContext.UserId, avatar.FileName, avatar.ContentType, stream), ct);
|
|
||||||
|
|
||||||
if (result.IsFailure)
|
|
||||||
{
|
|
||||||
return NotFound();
|
|
||||||
}
|
|
||||||
|
|
||||||
var chatResult = await _sender.Send(new GetChatByIdQuery(_userContext.UserId, result.Value), ct);
|
|
||||||
return Ok(chatResult.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpPost("{id:guid}/avatar/crop")]
|
|
||||||
public async Task<IActionResult> CropGroupAvatar(Guid id, [FromForm] Microsoft.AspNetCore.Http.IFormFile avatar, [FromForm] int x, [FromForm] int y, [FromForm] int width, [FromForm] int height, CancellationToken ct)
|
|
||||||
{
|
|
||||||
if (avatar == null || avatar.Length == 0)
|
|
||||||
{
|
|
||||||
return BadRequest("No file");
|
|
||||||
}
|
|
||||||
|
|
||||||
using var stream = avatar.OpenReadStream();
|
|
||||||
var result = await _sender.Send(new CropGroupAvatarCommand(id, _userContext.UserId, avatar.FileName, avatar.ContentType, stream, x, y, width, height), ct);
|
|
||||||
|
|
||||||
if (result.IsFailure)
|
|
||||||
{
|
|
||||||
return NotFound();
|
|
||||||
}
|
|
||||||
|
|
||||||
var chatResult = await _sender.Send(new GetChatByIdQuery(_userContext.UserId, result.Value), ct);
|
|
||||||
return Ok(chatResult.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpDelete("{id:guid}/avatar")]
|
|
||||||
public async Task<IActionResult> RemoveGroupAvatar(Guid id, CancellationToken ct)
|
|
||||||
{
|
|
||||||
var result = await _sender.Send(new RemoveGroupAvatarCommand(id, _userContext.UserId), ct);
|
|
||||||
if (result.IsFailure)
|
|
||||||
{
|
|
||||||
return NotFound();
|
|
||||||
}
|
|
||||||
|
|
||||||
var chatResult = await _sender.Send(new GetChatByIdQuery(_userContext.UserId, result.Value), ct);
|
|
||||||
return Ok(chatResult.Value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.AspNetCore.Authorization;
|
|
||||||
using Knot.Shared.Kernel.Storage;
|
|
||||||
|
|
||||||
namespace Host.Controllers;
|
|
||||||
|
|
||||||
[Authorize]
|
|
||||||
[ApiController]
|
|
||||||
[Route("api/files")]
|
|
||||||
public sealed class FilesController : ControllerBase
|
|
||||||
{
|
|
||||||
private readonly IFileStorageService _fileStorage;
|
|
||||||
|
|
||||||
public FilesController(IFileStorageService fileStorage)
|
|
||||||
{
|
|
||||||
_fileStorage = fileStorage;
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpGet("{id}")]
|
|
||||||
[AllowAnonymous]
|
|
||||||
public async Task<IActionResult> DownloadFile(string id, [FromQuery] bool download = false)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var result = await _fileStorage.DownloadFileAsync(id);
|
|
||||||
if (download && !string.IsNullOrEmpty(result.FileName))
|
|
||||||
{
|
|
||||||
return File(result.Stream, result.ContentType, result.FileName, enableRangeProcessing: true);
|
|
||||||
}
|
|
||||||
|
|
||||||
return File(result.Stream, result.ContentType, enableRangeProcessing: true);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
return NotFound(new { error = "Файл не найден или ошибка доступа.", message = ex.Message });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,113 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Knot.Modules.Identity.Application.Friends;
|
|
||||||
using Knot.Shared.Kernel;
|
|
||||||
using MediatR;
|
|
||||||
using Microsoft.AspNetCore.Authorization;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
|
|
||||||
namespace Host.Controllers;
|
|
||||||
|
|
||||||
[Authorize]
|
|
||||||
[ApiController]
|
|
||||||
[Route("api/friends")]
|
|
||||||
public sealed class FriendsController : ControllerBase
|
|
||||||
{
|
|
||||||
private readonly ISender _sender;
|
|
||||||
private readonly IUserContext _userContext;
|
|
||||||
|
|
||||||
public FriendsController(ISender sender, IUserContext userContext)
|
|
||||||
{
|
|
||||||
_sender = sender;
|
|
||||||
_userContext = userContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpGet]
|
|
||||||
public async Task<IActionResult> GetFriends(CancellationToken ct)
|
|
||||||
{
|
|
||||||
var result = await _sender.Send(new GetFriendsQuery(_userContext.UserId), ct);
|
|
||||||
if (result.IsFailure)
|
|
||||||
{
|
|
||||||
return BadRequest(result.Error);
|
|
||||||
}
|
|
||||||
return Ok(result.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpGet("requests")]
|
|
||||||
public async Task<IActionResult> GetRequests(CancellationToken ct)
|
|
||||||
{
|
|
||||||
var result = await _sender.Send(new GetIncomingRequestsQuery(_userContext.UserId), ct);
|
|
||||||
if (result.IsFailure)
|
|
||||||
{
|
|
||||||
return BadRequest(result.Error);
|
|
||||||
}
|
|
||||||
return Ok(result.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpGet("outgoing")]
|
|
||||||
public async Task<IActionResult> GetOutgoingRequests(CancellationToken ct)
|
|
||||||
{
|
|
||||||
var result = await _sender.Send(new GetOutgoingRequestsQuery(_userContext.UserId), ct);
|
|
||||||
if (result.IsFailure)
|
|
||||||
{
|
|
||||||
return BadRequest(result.Error);
|
|
||||||
}
|
|
||||||
return Ok(result.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpPost("request")]
|
|
||||||
public async Task<IActionResult> SendRequest([FromBody] Host.Models.SendFriendRequest request, CancellationToken ct)
|
|
||||||
{
|
|
||||||
var result = await _sender.Send(new SendFriendRequestCommand(_userContext.UserId, request.FriendId), ct);
|
|
||||||
if (result.IsFailure)
|
|
||||||
{
|
|
||||||
return BadRequest(result.Error.Description);
|
|
||||||
}
|
|
||||||
return Ok(new { status = "pending" });
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpPost("{id:guid}/accept")]
|
|
||||||
public async Task<IActionResult> AcceptRequest(Guid id, CancellationToken ct)
|
|
||||||
{
|
|
||||||
var result = await _sender.Send(new AcceptFriendRequestCommand(_userContext.UserId, id), ct);
|
|
||||||
if (result.IsFailure)
|
|
||||||
{
|
|
||||||
return NotFound(result.Error.Description);
|
|
||||||
}
|
|
||||||
return Ok(new { id = result.Value });
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpPost("{id:guid}/decline")]
|
|
||||||
public async Task<IActionResult> DeclineRequest(Guid id, CancellationToken ct)
|
|
||||||
{
|
|
||||||
var result = await _sender.Send(new DeclineFriendRequestCommand(_userContext.UserId, id), ct);
|
|
||||||
if (result.IsFailure)
|
|
||||||
{
|
|
||||||
return NotFound(result.Error.Description);
|
|
||||||
}
|
|
||||||
return Ok(new Knot.Shared.Kernel.SuccessResponse(true));
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpGet("status/{userId:guid}")]
|
|
||||||
public async Task<IActionResult> GetStatus(Guid userId, CancellationToken ct)
|
|
||||||
{
|
|
||||||
var result = await _sender.Send(new GetFriendshipStatusQuery(_userContext.UserId, userId), ct);
|
|
||||||
if (result.IsFailure)
|
|
||||||
{
|
|
||||||
return BadRequest(result.Error);
|
|
||||||
}
|
|
||||||
return Ok(result.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpDelete("{id:guid}")]
|
|
||||||
public async Task<IActionResult> RemoveFriend(Guid id, CancellationToken ct)
|
|
||||||
{
|
|
||||||
var result = await _sender.Send(new RemoveFriendCommand(_userContext.UserId, id), ct);
|
|
||||||
if (result.IsFailure)
|
|
||||||
{
|
|
||||||
return NotFound(result.Error.Description);
|
|
||||||
}
|
|
||||||
return Ok(new Knot.Shared.Kernel.SuccessResponse(true));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,116 +0,0 @@
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.AspNetCore.Authorization;
|
|
||||||
using Knot.Modules.Chats.Application.DTOs;
|
|
||||||
using Knot.Shared.Kernel;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System;
|
|
||||||
using Microsoft.AspNetCore.Http;
|
|
||||||
using MediatR;
|
|
||||||
using Knot.Modules.Chats.Application.Messages.GetMessages;
|
|
||||||
using Knot.Modules.Chats.Application.Messages.SearchMessages;
|
|
||||||
using Knot.Modules.Chats.Application.Messages.UploadFile;
|
|
||||||
using Knot.Modules.Chats.Application.Messages.GetSharedMedia;
|
|
||||||
using Knot.Modules.Chats.Application.Messages.Send;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace Host.Controllers;
|
|
||||||
|
|
||||||
[Authorize]
|
|
||||||
[ApiController]
|
|
||||||
[Route("api/messages")]
|
|
||||||
public sealed class MessagesController : ControllerBase
|
|
||||||
{
|
|
||||||
private readonly ISender _sender;
|
|
||||||
private readonly IUserContext _userContext;
|
|
||||||
|
|
||||||
public MessagesController(ISender sender, IUserContext userContext)
|
|
||||||
{
|
|
||||||
_sender = sender;
|
|
||||||
_userContext = userContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpGet("chat/{chatId:guid}")]
|
|
||||||
public async Task<IActionResult> GetMessages(Guid chatId, [FromQuery] string? cursor, CancellationToken ct = default)
|
|
||||||
{
|
|
||||||
var result = await _sender.Send(new GetMessagesQuery(_userContext.UserId, chatId, cursor), ct);
|
|
||||||
if (result.IsFailure)
|
|
||||||
{
|
|
||||||
return BadRequest(result.Error.Description);
|
|
||||||
}
|
|
||||||
return Ok(result.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpGet("search")]
|
|
||||||
public async Task<IActionResult> GetSearch([FromQuery] string q, [FromQuery] Guid? chatId, CancellationToken ct)
|
|
||||||
{
|
|
||||||
var result = await _sender.Send(new SearchMessagesQuery(_userContext.UserId, q, chatId), ct);
|
|
||||||
if (result.IsFailure)
|
|
||||||
{
|
|
||||||
return BadRequest(result.Error.Description);
|
|
||||||
}
|
|
||||||
return Ok(result.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpPost("upload")]
|
|
||||||
[DisableRequestSizeLimit]
|
|
||||||
[RequestFormLimits(MultipartBodyLengthLimit = 10L * 1024 * 1024 * 1024)] // 10 GB limit for form body
|
|
||||||
public async Task<IActionResult> UploadFile(IFormFile file, CancellationToken ct)
|
|
||||||
{
|
|
||||||
if (file == null || file.Length == 0)
|
|
||||||
{
|
|
||||||
return BadRequest("No file uploaded");
|
|
||||||
}
|
|
||||||
|
|
||||||
using var stream = file.OpenReadStream();
|
|
||||||
var result = await _sender.Send(new UploadFileCommand(file.FileName, file.ContentType, file.Length, stream), ct);
|
|
||||||
|
|
||||||
if (result.IsFailure)
|
|
||||||
{
|
|
||||||
if (result.Error.Code == "File.TooLarge")
|
|
||||||
{
|
|
||||||
return StatusCode(413, result.Error.Description);
|
|
||||||
}
|
|
||||||
return BadRequest(result.Error.Description);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Ok(result.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpGet("chat/{chatId:guid}/shared")]
|
|
||||||
public async Task<IActionResult> GetSharedMedia(Guid chatId, [FromQuery] string? type, CancellationToken ct)
|
|
||||||
{
|
|
||||||
var result = await _sender.Send(new GetSharedMediaQuery(_userContext.UserId, chatId, type), ct);
|
|
||||||
if (result.IsFailure)
|
|
||||||
{
|
|
||||||
return BadRequest(result.Error.Description);
|
|
||||||
}
|
|
||||||
return Ok(result.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpPost("chat/{chatId:guid}")]
|
|
||||||
public async Task<IActionResult> SendMessage(Guid chatId, [FromBody] SendMessageRequest request, CancellationToken ct)
|
|
||||||
{
|
|
||||||
var attachments = request.Attachments?.Select(a =>
|
|
||||||
new AttachmentRequest(a.Type, a.Url, a.FileName, a.FileSize)).ToList();
|
|
||||||
|
|
||||||
var command = new SendMessageCommand(
|
|
||||||
chatId,
|
|
||||||
_userContext.UserId,
|
|
||||||
request.Content,
|
|
||||||
request.Type,
|
|
||||||
attachments,
|
|
||||||
request.ReplyToId,
|
|
||||||
request.Quote,
|
|
||||||
request.ForwardedFromId);
|
|
||||||
|
|
||||||
var result = await _sender.Send(command, ct);
|
|
||||||
|
|
||||||
if (result.IsFailure)
|
|
||||||
{
|
|
||||||
return BadRequest(result.Error.Description);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Ok(result.Value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,149 +0,0 @@
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.AspNetCore.Authorization;
|
|
||||||
using Host.Models;
|
|
||||||
using Knot.Shared.Kernel;
|
|
||||||
using System;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using MediatR;
|
|
||||||
using Host.Application.Stories.Queries.GetStories;
|
|
||||||
using Host.Application.Stories.Commands.CreateStory;
|
|
||||||
using Host.Application.Stories.Queries.GetUserStories;
|
|
||||||
using Host.Application.Stories.Commands.ViewStory;
|
|
||||||
using Host.Application.Stories.Queries.GetStoryViewers;
|
|
||||||
using Host.Application.Stories.Commands.AddStoryReaction;
|
|
||||||
using Host.Application.Stories.Commands.RemoveStoryReaction;
|
|
||||||
using Host.Application.Stories.Commands.AddStoryReply;
|
|
||||||
using Host.Application.Stories.Queries.GetStoryReplies;
|
|
||||||
using Host.Application.Stories.Commands.DeleteStory;
|
|
||||||
|
|
||||||
namespace Host.Controllers;
|
|
||||||
|
|
||||||
[Authorize]
|
|
||||||
[ApiController]
|
|
||||||
[Route("api/stories")]
|
|
||||||
public sealed class StoriesController : ControllerBase
|
|
||||||
{
|
|
||||||
private readonly ISender _sender;
|
|
||||||
private readonly IUserContext _userContext;
|
|
||||||
|
|
||||||
public StoriesController(ISender sender, IUserContext userContext)
|
|
||||||
{
|
|
||||||
_sender = sender;
|
|
||||||
_userContext = userContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpGet]
|
|
||||||
public async Task<IActionResult> GetStories(CancellationToken ct)
|
|
||||||
{
|
|
||||||
var result = await _sender.Send(new GetStoriesQuery(_userContext.UserId), ct);
|
|
||||||
return Ok(result.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpPost]
|
|
||||||
public async Task<IActionResult> CreateStory([FromBody] CreateStoryRequest request, CancellationToken ct)
|
|
||||||
{
|
|
||||||
var result = await _sender.Send(new CreateStoryCommand(_userContext.UserId, request.Type, request.MediaUrl, request.Content, request.BgColor), ct);
|
|
||||||
return Ok(new { id = result.Value });
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpGet("user/{userId}")]
|
|
||||||
public async Task<IActionResult> GetUserStories(Guid userId, CancellationToken ct)
|
|
||||||
{
|
|
||||||
var result = await _sender.Send(new GetUserStoriesQuery(_userContext.UserId, userId), ct);
|
|
||||||
if (result.IsFailure)
|
|
||||||
{
|
|
||||||
return NotFound();
|
|
||||||
}
|
|
||||||
return Ok(result.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpPost("{id}/view")]
|
|
||||||
public async Task<IActionResult> ViewStory(Guid id, CancellationToken ct)
|
|
||||||
{
|
|
||||||
var result = await _sender.Send(new ViewStoryCommand(_userContext.UserId, id), ct);
|
|
||||||
if (result.IsFailure)
|
|
||||||
{
|
|
||||||
return NotFound();
|
|
||||||
}
|
|
||||||
return Ok(result.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpGet("{id}/viewers")]
|
|
||||||
public async Task<IActionResult> GetStoryViewers(Guid id, CancellationToken ct)
|
|
||||||
{
|
|
||||||
var result = await _sender.Send(new GetStoryViewersQuery(_userContext.UserId, id), ct);
|
|
||||||
if (result.IsFailure)
|
|
||||||
{
|
|
||||||
if (result.Error.Code == "Unauthorized")
|
|
||||||
{
|
|
||||||
return Forbid();
|
|
||||||
}
|
|
||||||
return NotFound();
|
|
||||||
}
|
|
||||||
return Ok(result.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpPost("{id}/reaction")]
|
|
||||||
public async Task<IActionResult> AddReaction(Guid id, [FromBody] AddStoryReactionRequest request, CancellationToken ct)
|
|
||||||
{
|
|
||||||
var result = await _sender.Send(new AddStoryReactionCommand(_userContext.UserId, id, request.Emoji), ct);
|
|
||||||
if (result.IsFailure)
|
|
||||||
{
|
|
||||||
return NotFound();
|
|
||||||
}
|
|
||||||
return Ok(result.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpDelete("{id}/reaction")]
|
|
||||||
public async Task<IActionResult> RemoveReaction(Guid id, [FromBody] RemoveStoryReactionRequest request, CancellationToken ct)
|
|
||||||
{
|
|
||||||
var result = await _sender.Send(new RemoveStoryReactionCommand(_userContext.UserId, id, request.Emoji), ct);
|
|
||||||
if (result.IsFailure)
|
|
||||||
{
|
|
||||||
return NotFound();
|
|
||||||
}
|
|
||||||
return Ok(result.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpPost("{id}/reply")]
|
|
||||||
public async Task<IActionResult> AddReply(Guid id, [FromBody] AddStoryReplyRequest request, CancellationToken ct)
|
|
||||||
{
|
|
||||||
var result = await _sender.Send(new AddStoryReplyCommand(_userContext.UserId, id, request.Content), ct);
|
|
||||||
if (result.IsFailure)
|
|
||||||
{
|
|
||||||
return NotFound();
|
|
||||||
}
|
|
||||||
return Ok(result.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpGet("{id}/replies")]
|
|
||||||
public async Task<IActionResult> GetReplies(Guid id, CancellationToken ct)
|
|
||||||
{
|
|
||||||
var result = await _sender.Send(new GetStoryRepliesQuery(_userContext.UserId, id), ct);
|
|
||||||
if (result.IsFailure)
|
|
||||||
{
|
|
||||||
if (result.Error.Code == "Unauthorized")
|
|
||||||
{
|
|
||||||
return Forbid();
|
|
||||||
}
|
|
||||||
return NotFound();
|
|
||||||
}
|
|
||||||
return Ok(result.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpDelete("{id}")]
|
|
||||||
public async Task<IActionResult> DeleteStory(Guid id, CancellationToken ct)
|
|
||||||
{
|
|
||||||
var result = await _sender.Send(new DeleteStoryCommand(_userContext.UserId, id), ct);
|
|
||||||
if (result.IsFailure)
|
|
||||||
{
|
|
||||||
if (result.Error.Code == "Unauthorized")
|
|
||||||
{
|
|
||||||
return Forbid();
|
|
||||||
}
|
|
||||||
return NotFound();
|
|
||||||
}
|
|
||||||
return Ok(result.Value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.AspNetCore.Authorization;
|
|
||||||
using Microsoft.AspNetCore.Http;
|
|
||||||
using MediatR;
|
|
||||||
using Host.Models;
|
|
||||||
using Knot.Shared.Kernel;
|
|
||||||
using Knot.Modules.Chats.Application.TelegramImport;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Host.Controllers;
|
|
||||||
|
|
||||||
[Authorize]
|
|
||||||
[ApiController]
|
|
||||||
[Route("api/import/telegram")]
|
|
||||||
public sealed class TelegramImportController : ControllerBase
|
|
||||||
{
|
|
||||||
private readonly ISender _sender;
|
|
||||||
private readonly IUserContext _userContext;
|
|
||||||
|
|
||||||
public TelegramImportController(ISender sender, IUserContext userContext)
|
|
||||||
{
|
|
||||||
_sender = sender;
|
|
||||||
_userContext = userContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpPost("analyze")]
|
|
||||||
[DisableRequestSizeLimit]
|
|
||||||
[RequestFormLimits(MultipartBodyLengthLimit = 10L * 1024 * 1024 * 1024)] // 10GB for big exports
|
|
||||||
public async Task<IActionResult> Analyze(IFormFile file, CancellationToken ct)
|
|
||||||
{
|
|
||||||
if (file == null)
|
|
||||||
{
|
|
||||||
return BadRequest("No file uploaded.");
|
|
||||||
}
|
|
||||||
|
|
||||||
using var stream = file.OpenReadStream();
|
|
||||||
var command = new AnalyzeImportCommand(stream, file.FileName);
|
|
||||||
|
|
||||||
var result = await _sender.Send(command, ct);
|
|
||||||
|
|
||||||
if (result.IsFailure)
|
|
||||||
{
|
|
||||||
return BadRequest(result.Error.Description ?? result.Error.Code);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Ok(result.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpPost("execute")]
|
|
||||||
public async Task<IActionResult> Execute([FromBody] ExecuteImportRequest req, CancellationToken ct)
|
|
||||||
{
|
|
||||||
var command = new ExecuteImportCommand(_userContext.UserId, req.Token, req.Mapping, req.GroupName);
|
|
||||||
|
|
||||||
var result = await _sender.Send(command, ct);
|
|
||||||
|
|
||||||
if (result.IsFailure)
|
|
||||||
{
|
|
||||||
return BadRequest(result.Error.Description ?? result.Error.Code);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Ok(result.Value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,134 +0,0 @@
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.AspNetCore.Authorization;
|
|
||||||
using Knot.Shared.Kernel;
|
|
||||||
using Host.Models;
|
|
||||||
using Knot.Shared.Kernel.Storage;
|
|
||||||
using MediatR;
|
|
||||||
using Knot.Modules.Identity.Application.Users;
|
|
||||||
using Knot.Modules.Identity.Application.Users.Avatar;
|
|
||||||
using Knot.Modules.Identity.Application.Users.GetUser;
|
|
||||||
using Knot.Modules.Identity.Application.Users.Search;
|
|
||||||
using Knot.Modules.Identity.Application.Users.UpdateProfile;
|
|
||||||
using Knot.Modules.Identity.Application.Users.UpdateSettings;
|
|
||||||
|
|
||||||
namespace Host.Controllers;
|
|
||||||
|
|
||||||
[Authorize]
|
|
||||||
[ApiController]
|
|
||||||
[Route("api/users")]
|
|
||||||
public sealed class UsersController : ControllerBase
|
|
||||||
{
|
|
||||||
private readonly ISender _sender;
|
|
||||||
private readonly IUserContext _userContext;
|
|
||||||
|
|
||||||
public UsersController(ISender sender, IUserContext userContext)
|
|
||||||
{
|
|
||||||
_sender = sender;
|
|
||||||
_userContext = userContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpGet("search")]
|
|
||||||
public async Task<IActionResult> Search([FromQuery] string q, CancellationToken ct)
|
|
||||||
{
|
|
||||||
var result = await _sender.Send(new SearchUsersQuery(q), ct);
|
|
||||||
if (result.IsFailure)
|
|
||||||
{
|
|
||||||
return BadRequest(result.Error);
|
|
||||||
}
|
|
||||||
return Ok(result.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpPut("settings")]
|
|
||||||
public async Task<IActionResult> UpdateSettings([FromBody] UpdateSettingsRequest request, CancellationToken ct)
|
|
||||||
{
|
|
||||||
var result = await _sender.Send(new UpdateSettingsCommand(_userContext.UserId, request.HideStoryViews), ct);
|
|
||||||
if (result.IsFailure)
|
|
||||||
{
|
|
||||||
return NotFound(result.Error);
|
|
||||||
}
|
|
||||||
return Ok(result.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpPost("avatar")]
|
|
||||||
public async Task<IActionResult> UploadAvatar(IFormFile avatar, CancellationToken ct)
|
|
||||||
{
|
|
||||||
var fileToUpload = avatar ?? Request.Form.Files.FirstOrDefault();
|
|
||||||
if (fileToUpload == null || fileToUpload.Length == 0)
|
|
||||||
{
|
|
||||||
return BadRequest("No file uploaded");
|
|
||||||
}
|
|
||||||
|
|
||||||
using var stream = fileToUpload.OpenReadStream();
|
|
||||||
var command = new UploadAvatarCommand(
|
|
||||||
_userContext.UserId,
|
|
||||||
stream,
|
|
||||||
fileToUpload.FileName,
|
|
||||||
fileToUpload.ContentType
|
|
||||||
);
|
|
||||||
|
|
||||||
var result = await _sender.Send(command, ct);
|
|
||||||
if (result.IsFailure)
|
|
||||||
{
|
|
||||||
return NotFound(result.Error);
|
|
||||||
}
|
|
||||||
return Ok(result.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpPost("avatar/crop")]
|
|
||||||
public async Task<IActionResult> CropAvatar([FromForm] IFormFile avatar, [FromForm] int x, [FromForm] int y, [FromForm] int width, [FromForm] int height, CancellationToken ct)
|
|
||||||
{
|
|
||||||
if (avatar == null || avatar.Length == 0)
|
|
||||||
{
|
|
||||||
return BadRequest("No file uploaded");
|
|
||||||
}
|
|
||||||
|
|
||||||
using var stream = avatar.OpenReadStream();
|
|
||||||
var command = new CropAvatarCommand(
|
|
||||||
_userContext.UserId,
|
|
||||||
stream,
|
|
||||||
avatar.FileName ?? "avatar.jpg",
|
|
||||||
avatar.ContentType,
|
|
||||||
x, y, width, height
|
|
||||||
);
|
|
||||||
|
|
||||||
var result = await _sender.Send(command, ct);
|
|
||||||
if (result.IsFailure)
|
|
||||||
{
|
|
||||||
return NotFound(result.Error);
|
|
||||||
}
|
|
||||||
return Ok(result.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpDelete("avatar")]
|
|
||||||
public async Task<IActionResult> DeleteAvatar(CancellationToken ct)
|
|
||||||
{
|
|
||||||
var result = await _sender.Send(new DeleteAvatarCommand(_userContext.UserId), ct);
|
|
||||||
if (result.IsFailure)
|
|
||||||
{
|
|
||||||
return NotFound(result.Error);
|
|
||||||
}
|
|
||||||
return Ok(result.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpPut("profile")]
|
|
||||||
public async Task<IActionResult> UpdateProfile([FromBody] UpdateProfileRequest request, CancellationToken ct)
|
|
||||||
{
|
|
||||||
var result = await _sender.Send(new UpdateProfileCommand(_userContext.UserId, request.DisplayName, request.Bio, request.Birthday), ct);
|
|
||||||
if (result.IsFailure)
|
|
||||||
{
|
|
||||||
return NotFound(result.Error);
|
|
||||||
}
|
|
||||||
return Ok(result.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpGet("{id:guid}")]
|
|
||||||
public async Task<IActionResult> GetUser(Guid id, CancellationToken ct)
|
|
||||||
{
|
|
||||||
var result = await _sender.Send(new GetUserQuery(id), ct);
|
|
||||||
if (result.IsFailure)
|
|
||||||
{
|
|
||||||
return NotFound(result.Error);
|
|
||||||
}
|
|
||||||
return Ok(result.Value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
using Carter;
|
|
||||||
using MediatR;
|
|
||||||
using Knot.Shared.Kernel.Constants;
|
|
||||||
using Microsoft.AspNetCore.Builder;
|
|
||||||
using Microsoft.AspNetCore.Http;
|
|
||||||
using Microsoft.AspNetCore.Routing;
|
|
||||||
|
|
||||||
namespace Host.Endpoints;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Регистрация эндпоинтов для конфигурации приложения.
|
|
||||||
/// </summary>
|
|
||||||
public sealed class ConfigEndpoints : ICarterModule
|
|
||||||
{
|
|
||||||
public void AddRoutes(IEndpointRouteBuilder app)
|
|
||||||
{
|
|
||||||
var group = app.MapGroup(Routes.ApiConfig);
|
|
||||||
|
|
||||||
group.MapGet("/", async (ISender sender, CancellationToken ct) =>
|
|
||||||
{
|
|
||||||
var result = await sender.Send(new Host.Application.Config.Queries.GetPublicConfigQuery(), ct);
|
|
||||||
return result.IsSuccess ? Results.Ok(result.Value) : Results.BadRequest(result.Error);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
using Carter;
|
|
||||||
using MediatR;
|
|
||||||
using Knot.Shared.Kernel.Constants;
|
|
||||||
using Microsoft.AspNetCore.Builder;
|
|
||||||
using Microsoft.AspNetCore.Http;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.AspNetCore.Routing;
|
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace Host.Endpoints;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Регистрация эндпоинтов федерации.
|
|
||||||
/// </summary>
|
|
||||||
public sealed class FederationEndpoints : ICarterModule
|
|
||||||
{
|
|
||||||
public void AddRoutes(IEndpointRouteBuilder app)
|
|
||||||
{
|
|
||||||
var group = app.MapGroup(Routes.ApiFederation);
|
|
||||||
|
|
||||||
group.MapPost("/handshake", async ([FromBody] Host.Application.Federation.Commands.HandshakeRequest request, ISender sender, CancellationToken ct) =>
|
|
||||||
{
|
|
||||||
var result = await sender.Send(new Host.Application.Federation.Commands.HandshakeFederationCommand(request), ct);
|
|
||||||
if (result.IsSuccess)
|
|
||||||
{
|
|
||||||
return Results.Ok(result.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result.Error.Code == "Unauthorized")
|
|
||||||
{
|
|
||||||
return Results.Forbid();
|
|
||||||
}
|
|
||||||
if (result.Error.Code == Knot.Shared.Kernel.Constants.Errors.DisabledByAdmin)
|
|
||||||
{
|
|
||||||
return Results.StatusCode(503);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Results.BadRequest(new { error = result.Error.Description });
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
using Carter;
|
|
||||||
using MediatR;
|
|
||||||
using Knot.Shared.Kernel;
|
|
||||||
using Microsoft.AspNetCore.Builder;
|
|
||||||
using Microsoft.AspNetCore.Http;
|
|
||||||
using Microsoft.AspNetCore.Routing;
|
|
||||||
|
|
||||||
namespace Host.Endpoints;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Регистрация эндпоинтов WebRTC
|
|
||||||
/// </summary>
|
|
||||||
public sealed class WebRtcEndpoints : ICarterModule
|
|
||||||
{
|
|
||||||
public void AddRoutes(IEndpointRouteBuilder app)
|
|
||||||
{
|
|
||||||
var group = app.MapGroup(Knot.Shared.Kernel.Constants.Routes.ApiWebRtc)
|
|
||||||
.RequireAuthorization();
|
|
||||||
|
|
||||||
group.MapGet("/ice-servers", async (ISender sender, CancellationToken ct) =>
|
|
||||||
{
|
|
||||||
var result = await sender.Send(new Host.Application.WebRtc.Queries.GetIceServersQuery(), ct);
|
|
||||||
return result.IsSuccess ? Results.Ok(result.Value) : Results.BadRequest(result.Error);
|
|
||||||
})
|
|
||||||
.WithName("GetIceServers")
|
|
||||||
.WithOpenApi();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -28,9 +28,18 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Modules\Identity\Knot.Modules.Identity.csproj" />
|
|
||||||
<ProjectReference Include="..\Modules\Chats\Knot.Modules.Chats.csproj" />
|
|
||||||
<ProjectReference Include="..\Shared\Knot.Shared.Infrastructure\Knot.Shared.Infrastructure.csproj" />
|
<ProjectReference Include="..\Shared\Knot.Shared.Infrastructure\Knot.Shared.Infrastructure.csproj" />
|
||||||
|
<ProjectReference Include="..\Modules\Storage\Knot.Modules.Storage.csproj" />
|
||||||
|
<ProjectReference Include="..\Modules\Auth\Knot.Modules.Auth.csproj" />
|
||||||
|
<ProjectReference Include="..\Modules\Messaging\Knot.Modules.Messaging.csproj" />
|
||||||
|
<ProjectReference Include="..\Modules\TelegramImport\Knot.Modules.TelegramImport.csproj" />
|
||||||
|
<ProjectReference Include="..\Modules\Conversations\Knot.Modules.Conversations.csproj" />
|
||||||
|
<ProjectReference Include="..\Modules\Admin\Knot.Modules.Admin.csproj" />
|
||||||
|
<ProjectReference Include="..\Modules\WebRtc\Knot.Modules.WebRtc.csproj" />
|
||||||
|
<ProjectReference Include="..\Modules\Federation\Knot.Modules.Federation.csproj" />
|
||||||
|
<ProjectReference Include="..\Modules\Klipy\Knot.Modules.Klipy.csproj" />
|
||||||
|
<ProjectReference Include="..\Modules\Settings\Knot.Modules.Settings.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace Host.Models;
|
|
||||||
|
|
||||||
public record SendFriendRequest(Guid FriendId);
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace Host.Models;
|
|
||||||
|
|
||||||
public record AddStoryReactionRequest(string Emoji);
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace Host.Models;
|
|
||||||
|
|
||||||
public record AddStoryReplyRequest(string Content);
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace Host.Models;
|
|
||||||
|
|
||||||
public record RemoveStoryReactionRequest(string Emoji);
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace Host.Models;
|
|
||||||
|
|
||||||
public sealed record UpdateProfileRequest(string? DisplayName, string? Bio, DateTime? Birthday);
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
namespace Host.Models;
|
|
||||||
|
|
||||||
public sealed record UpdateSettingsRequest(bool? HideStoryViews);
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace Host.Models;
|
|
||||||
|
|
||||||
public record UserDto(
|
|
||||||
Guid Id,
|
|
||||||
string Username,
|
|
||||||
string DisplayName,
|
|
||||||
string? Avatar,
|
|
||||||
bool IsOnline,
|
|
||||||
DateTime LastSeen
|
|
||||||
);
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace Host.Models;
|
|
||||||
|
|
||||||
public record UserProfileDto(
|
|
||||||
Guid Id,
|
|
||||||
string Username,
|
|
||||||
string DisplayName,
|
|
||||||
string? Avatar,
|
|
||||||
string? Bio,
|
|
||||||
DateTime? Birthday,
|
|
||||||
DateTime CreatedAt,
|
|
||||||
bool? HideStoryViews = null,
|
|
||||||
bool IsOnline = false,
|
|
||||||
DateTime? LastSeen = null
|
|
||||||
);
|
|
||||||
+13
-18
@@ -1,10 +1,11 @@
|
|||||||
|
using Knot.Modules.Messaging;
|
||||||
using Carter;
|
using Carter;
|
||||||
using Knot.Shared.Infrastructure;
|
using Knot.Shared.Infrastructure;
|
||||||
using Knot.Modules.Identity;
|
using Knot.Modules.Auth;
|
||||||
using Knot.Modules.Chats;
|
using Knot.Modules.Conversations;
|
||||||
using Knot.Modules.Chats.Infrastructure.SignalR;
|
using Knot.Modules.Conversations.Infrastructure.SignalR;
|
||||||
using Knot.Modules.Identity.Infrastructure.Persistence;
|
using Knot.Modules.Auth.Infrastructure.Persistence;
|
||||||
using Knot.Modules.Chats.Infrastructure.Persistence;
|
using Knot.Modules.Conversations.Infrastructure.Persistence;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||||
using Microsoft.IdentityModel.Tokens;
|
using Microsoft.IdentityModel.Tokens;
|
||||||
@@ -26,7 +27,7 @@ var builder = WebApplication.CreateBuilder(args);
|
|||||||
// Маппинг стандартных переменных окружения в иерархию .NET
|
// Маппинг стандартных переменных окружения в иерархию .NET
|
||||||
var envMappings = new Dictionary<string, string?>
|
var envMappings = new Dictionary<string, string?>
|
||||||
{
|
{
|
||||||
["ConnectionStrings:DefaultConnection"] = builder.Configuration["DATABASE_URL"],
|
["ConnectionStrings:DefaultConnection"] = builder.Configuration["DATABASE_URL"] ?? "Host=localhost;Database=knot;Username=postgres;Password=postgres",
|
||||||
["ConnectionStrings:MongoConnection"] = builder.Configuration["MONGO_CONNECTION"],
|
["ConnectionStrings:MongoConnection"] = builder.Configuration["MONGO_CONNECTION"],
|
||||||
["Jwt:Secret"] = builder.Configuration["JWT_SECRET"],
|
["Jwt:Secret"] = builder.Configuration["JWT_SECRET"],
|
||||||
["Jwt:Issuer"] = builder.Configuration["JWT_ISSUER"],
|
["Jwt:Issuer"] = builder.Configuration["JWT_ISSUER"],
|
||||||
@@ -48,8 +49,8 @@ builder.Configuration.AddInMemoryCollection(
|
|||||||
envMappings.Where(kv => !string.IsNullOrEmpty(kv.Value))
|
envMappings.Where(kv => !string.IsNullOrEmpty(kv.Value))
|
||||||
.ToDictionary(kv => kv.Key, kv => kv.Value));
|
.ToDictionary(kv => kv.Key, kv => kv.Value));
|
||||||
|
|
||||||
builder.Services.AddIdentityModule(builder.Configuration);
|
builder.Services.AddAuthModule(builder.Configuration);
|
||||||
builder.Services.AddChatsModule(builder.Configuration);
|
builder.Services.AddConversationsModule(builder.Configuration);
|
||||||
builder.Services.AddSharedInfrastructure(builder.Configuration);
|
builder.Services.AddSharedInfrastructure(builder.Configuration);
|
||||||
|
|
||||||
// CQRS / MediatR для команд в Host (например, AdminController)
|
// CQRS / MediatR для команд в Host (например, AdminController)
|
||||||
@@ -98,12 +99,7 @@ builder.Services.AddRouting(options =>
|
|||||||
builder.Services.AddMemoryCache();
|
builder.Services.AddMemoryCache();
|
||||||
builder.Services.AddHttpClient();
|
builder.Services.AddHttpClient();
|
||||||
|
|
||||||
builder.Services.AddControllers()
|
|
||||||
.AddJsonOptions(options =>
|
|
||||||
{
|
|
||||||
options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
|
|
||||||
options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
|
|
||||||
});
|
|
||||||
|
|
||||||
builder.Services.AddSignalR()
|
builder.Services.AddSignalR()
|
||||||
.AddJsonProtocol(options =>
|
.AddJsonProtocol(options =>
|
||||||
@@ -152,10 +148,10 @@ var app = builder.Build();
|
|||||||
// Применяем миграции при старте
|
// Применяем миграции при старте
|
||||||
using (var scope = app.Services.CreateScope())
|
using (var scope = app.Services.CreateScope())
|
||||||
{
|
{
|
||||||
var identityDb = scope.ServiceProvider.GetRequiredService<IdentityDbContext>();
|
var identityDb = scope.ServiceProvider.GetRequiredService<AuthDbContext>();
|
||||||
await identityDb.Database.MigrateAsync();
|
await identityDb.Database.MigrateAsync();
|
||||||
|
|
||||||
var chatsDb = scope.ServiceProvider.GetRequiredService<ChatsDbContext>();
|
var chatsDb = scope.ServiceProvider.GetRequiredService<Knot.Modules.Conversations.Infrastructure.Persistence.ConversationsDbContext>();
|
||||||
await chatsDb.Database.MigrateAsync();
|
await chatsDb.Database.MigrateAsync();
|
||||||
|
|
||||||
var systemDb = scope.ServiceProvider.GetRequiredService<Knot.Shared.Infrastructure.Persistence.SystemDbContext>();
|
var systemDb = scope.ServiceProvider.GetRequiredService<Knot.Shared.Infrastructure.Persistence.SystemDbContext>();
|
||||||
@@ -163,7 +159,7 @@ using (var scope = app.Services.CreateScope())
|
|||||||
|
|
||||||
// Set Encryption Service for MongoDB serializers
|
// Set Encryption Service for MongoDB serializers
|
||||||
var encryptionService = scope.ServiceProvider.GetRequiredService<Knot.Shared.Kernel.Security.IEncryptionService>();
|
var encryptionService = scope.ServiceProvider.GetRequiredService<Knot.Shared.Kernel.Security.IEncryptionService>();
|
||||||
Knot.Modules.Chats.Infrastructure.Persistence.Mongo.EncryptedStringSerializer.EncryptionService = encryptionService;
|
Knot.Modules.Messaging.Infrastructure.Persistence.Mongo.EncryptedStringSerializer.EncryptionService = encryptionService;
|
||||||
|
|
||||||
// Initialize Global Settings Cache
|
// Initialize Global Settings Cache
|
||||||
var settingsService = scope.ServiceProvider.GetRequiredService<Knot.Shared.Kernel.Configuration.ISettingsService>();
|
var settingsService = scope.ServiceProvider.GetRequiredService<Knot.Shared.Kernel.Configuration.ISettingsService>();
|
||||||
@@ -193,7 +189,6 @@ app.UseAuthentication();
|
|||||||
app.UseAuthorization();
|
app.UseAuthorization();
|
||||||
|
|
||||||
// Добавляем контроллеры и Carter (Minimal APIs)
|
// Добавляем контроллеры и Carter (Minimal APIs)
|
||||||
app.MapControllers();
|
|
||||||
app.MapCarter();
|
app.MapCarter();
|
||||||
|
|
||||||
// Добавляем SignalR хабы
|
// Добавляем SignalR хабы
|
||||||
|
|||||||
+6
-4
@@ -1,3 +1,5 @@
|
|||||||
|
using Knot.Modules.Admin.Application.Admin.DTOs;
|
||||||
|
using Knot.Modules.Messaging.Domain;
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@@ -6,15 +8,15 @@ using System.Threading.Tasks;
|
|||||||
using MediatR;
|
using MediatR;
|
||||||
using Knot.Shared.Kernel;
|
using Knot.Shared.Kernel;
|
||||||
using Knot.Shared.Kernel.Storage;
|
using Knot.Shared.Kernel.Storage;
|
||||||
using Knot.Modules.Identity.Infrastructure.Persistence;
|
using Knot.Modules.Auth.Infrastructure.Persistence;
|
||||||
using Knot.Modules.Chats.Infrastructure.Persistence;
|
using Knot.Modules.Conversations.Infrastructure.Persistence;
|
||||||
using Knot.Modules.Chats.Domain;
|
using Knot.Modules.Conversations.Domain;
|
||||||
using MongoDB.Driver;
|
using MongoDB.Driver;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
namespace Host.Application.Admin.Commands;
|
namespace Host.Application.Admin.Commands;
|
||||||
|
|
||||||
public record CleanRunCommand(IFileStorageService FileStorage, IdentityDbContext IdentityDb) : ICommand<MessageResponse>;
|
public record CleanRunCommand(IFileStorageService FileStorage, AuthDbContext IdentityDb) : ICommand<MessageResponse>;
|
||||||
|
|
||||||
internal sealed class CleanRunCommandHandler : ICommandHandler<CleanRunCommand, MessageResponse>
|
internal sealed class CleanRunCommandHandler : ICommandHandler<CleanRunCommand, MessageResponse>
|
||||||
{
|
{
|
||||||
+11
-7
@@ -1,12 +1,16 @@
|
|||||||
|
using Knot.Modules.Auth.Domain;
|
||||||
|
using Knot.Modules.Admin.Application.Admin.DTOs;
|
||||||
using System;
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediatR;
|
using MediatR;
|
||||||
using Knot.Shared.Kernel;
|
using Knot.Shared.Kernel;
|
||||||
using Host.Models;
|
using Knot.Modules.Auth.Application.Auth.DTOs;
|
||||||
using Knot.Modules.Identity.Domain;
|
|
||||||
using Knot.Modules.Identity.Infrastructure.Persistence;
|
using Knot.Modules.Auth.Application.Users;
|
||||||
using Knot.Modules.Identity.Application.Abstractions;
|
using Knot.Modules.Auth.Domain;
|
||||||
|
using Knot.Modules.Auth.Infrastructure.Persistence;
|
||||||
|
using Knot.Modules.Auth.Application.Abstractions;
|
||||||
|
|
||||||
namespace Host.Application.Admin.Commands;
|
namespace Host.Application.Admin.Commands;
|
||||||
|
|
||||||
@@ -15,9 +19,9 @@ public record ResetUserPasswordCommand(Guid UserId, string NewPassword) : IComma
|
|||||||
internal sealed class ResetUserPasswordCommandHandler : ICommandHandler<ResetUserPasswordCommand, SuccessResponse>
|
internal sealed class ResetUserPasswordCommandHandler : ICommandHandler<ResetUserPasswordCommand, SuccessResponse>
|
||||||
{
|
{
|
||||||
private readonly IUserRepository _userRepository;
|
private readonly IUserRepository _userRepository;
|
||||||
private readonly IIdentityUnitOfWork _identityUnitOfWork;
|
private readonly IAuthUnitOfWork _identityUnitOfWork;
|
||||||
|
|
||||||
public ResetUserPasswordCommandHandler(IUserRepository userRepository, IIdentityUnitOfWork identityUnitOfWork)
|
public ResetUserPasswordCommandHandler(IUserRepository userRepository, IAuthUnitOfWork identityUnitOfWork)
|
||||||
{
|
{
|
||||||
_userRepository = userRepository;
|
_userRepository = userRepository;
|
||||||
_identityUnitOfWork = identityUnitOfWork;
|
_identityUnitOfWork = identityUnitOfWork;
|
||||||
@@ -28,7 +32,7 @@ internal sealed class ResetUserPasswordCommandHandler : ICommandHandler<ResetUse
|
|||||||
var user = await _userRepository.GetByIdAsync(request.UserId, cancellationToken);
|
var user = await _userRepository.GetByIdAsync(request.UserId, cancellationToken);
|
||||||
if (user == null)
|
if (user == null)
|
||||||
{
|
{
|
||||||
return Result.Failure<SuccessResponse>(IdentityErrors.UserNotFound);
|
return Result.Failure<SuccessResponse>(AuthErrors.UserNotFound);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(request.NewPassword))
|
if (string.IsNullOrWhiteSpace(request.NewPassword))
|
||||||
+2
-1
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using Knot.Modules.Admin.Application.Admin.DTOs;
|
||||||
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediatR;
|
using MediatR;
|
||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Host.Models;
|
namespace Knot.Modules.Admin.Application.Admin.DTOs;
|
||||||
|
|
||||||
public record AdminUserDetailsDto(
|
public record AdminUserDetailsDto(
|
||||||
Guid Id,
|
Guid Id,
|
||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Host.Models;
|
namespace Knot.Modules.Admin.Application.Admin.DTOs;
|
||||||
|
|
||||||
public record AdminUserDto(
|
public record AdminUserDto(
|
||||||
Guid Id,
|
Guid Id,
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
namespace Host.Models;
|
namespace Knot.Modules.Admin.Application.Admin.DTOs;
|
||||||
|
|
||||||
public record AdminUserStatsDto(
|
public record AdminUserStatsDto(
|
||||||
int MessagesCount,
|
int MessagesCount,
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
namespace Host.Models;
|
namespace Knot.Modules.Admin.Application.Admin.DTOs;
|
||||||
|
|
||||||
public class CleanupDryRunResultDto
|
public class CleanupDryRunResultDto
|
||||||
{
|
{
|
||||||
+9
-5
@@ -1,3 +1,5 @@
|
|||||||
|
using Knot.Modules.Admin.Application.Admin.DTOs;
|
||||||
|
using Knot.Modules.Messaging.Domain;
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@@ -6,16 +8,18 @@ using System.Threading.Tasks;
|
|||||||
using MediatR;
|
using MediatR;
|
||||||
using Knot.Shared.Kernel;
|
using Knot.Shared.Kernel;
|
||||||
using Knot.Shared.Kernel.Storage;
|
using Knot.Shared.Kernel.Storage;
|
||||||
using Knot.Modules.Identity.Infrastructure.Persistence;
|
using Knot.Modules.Auth.Infrastructure.Persistence;
|
||||||
using Knot.Modules.Chats.Infrastructure.Persistence;
|
using Knot.Modules.Conversations.Infrastructure.Persistence;
|
||||||
using Knot.Modules.Chats.Domain;
|
using Knot.Modules.Conversations.Domain;
|
||||||
using MongoDB.Driver;
|
using MongoDB.Driver;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Host.Models;
|
using Knot.Modules.Auth.Application.Auth.DTOs;
|
||||||
|
|
||||||
|
using Knot.Modules.Auth.Application.Users;
|
||||||
|
|
||||||
namespace Host.Application.Admin.Queries;
|
namespace Host.Application.Admin.Queries;
|
||||||
|
|
||||||
public record CleanDryRunQuery(IFileStorageService FileStorage, IdentityDbContext IdentityDb) : IQuery<CleanupDryRunResultDto>;
|
public record CleanDryRunQuery(IFileStorageService FileStorage, AuthDbContext IdentityDb) : IQuery<CleanupDryRunResultDto>;
|
||||||
|
|
||||||
internal sealed class CleanDryRunQueryHandler : IQueryHandler<CleanDryRunQuery, CleanupDryRunResultDto>
|
internal sealed class CleanDryRunQueryHandler : IQueryHandler<CleanDryRunQuery, CleanupDryRunResultDto>
|
||||||
{
|
{
|
||||||
+2
-1
@@ -1,4 +1,5 @@
|
|||||||
using System.Threading;
|
using Knot.Modules.Admin.Application.Admin.DTOs;
|
||||||
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediatR;
|
using MediatR;
|
||||||
using Knot.Shared.Kernel;
|
using Knot.Shared.Kernel;
|
||||||
+2
-1
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using Knot.Modules.Admin.Application.Admin.DTOs;
|
||||||
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediatR;
|
using MediatR;
|
||||||
+11
-6
@@ -1,12 +1,17 @@
|
|||||||
|
using Knot.Modules.Auth.Domain;
|
||||||
|
using Knot.Modules.Admin.Application.Admin.DTOs;
|
||||||
|
using Knot.Modules.Messaging.Domain;
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediatR;
|
using MediatR;
|
||||||
using Knot.Shared.Kernel;
|
using Knot.Shared.Kernel;
|
||||||
using Host.Models;
|
using Knot.Modules.Auth.Application.Auth.DTOs;
|
||||||
using Knot.Modules.Identity.Domain;
|
|
||||||
using Knot.Modules.Chats.Domain;
|
using Knot.Modules.Auth.Application.Users;
|
||||||
|
using Knot.Modules.Auth.Domain;
|
||||||
|
using Knot.Modules.Conversations.Domain;
|
||||||
using MongoDB.Driver;
|
using MongoDB.Driver;
|
||||||
|
|
||||||
namespace Host.Application.Admin.Queries;
|
namespace Host.Application.Admin.Queries;
|
||||||
@@ -29,7 +34,7 @@ internal sealed class GetUserDetailsQueryHandler : IQueryHandler<GetUserDetailsQ
|
|||||||
var targetUser = await _userRepository.GetByIdAsync(request.UserId, cancellationToken);
|
var targetUser = await _userRepository.GetByIdAsync(request.UserId, cancellationToken);
|
||||||
if (targetUser == null)
|
if (targetUser == null)
|
||||||
{
|
{
|
||||||
return Result.Failure<AdminUserDetailsDto>(IdentityErrors.UserNotFound);
|
return Result.Failure<AdminUserDetailsDto>(AuthErrors.UserNotFound);
|
||||||
}
|
}
|
||||||
|
|
||||||
var filter = Builders<Message>.Filter.Eq(m => m.SenderId, request.UserId);
|
var filter = Builders<Message>.Filter.Eq(m => m.SenderId, request.UserId);
|
||||||
@@ -56,8 +61,8 @@ internal sealed class GetUserDetailsQueryHandler : IQueryHandler<GetUserDetailsQ
|
|||||||
targetUser.Bio,
|
targetUser.Bio,
|
||||||
targetUser.Avatar,
|
targetUser.Avatar,
|
||||||
targetUser.CreatedAt,
|
targetUser.CreatedAt,
|
||||||
Knot.Modules.Chats.Infrastructure.SignalR.ChatHub.IsUserOnline(targetUser.Id.ToString()),
|
Knot.Modules.Conversations.Infrastructure.SignalR.ChatHub.IsUserOnline(targetUser.Id.ToString()),
|
||||||
Knot.Modules.Chats.Infrastructure.SignalR.ChatHub.IsUserOnline(targetUser.Id.ToString()) ? DateTime.UtcNow : targetUser.CreatedAt,
|
Knot.Modules.Conversations.Infrastructure.SignalR.ChatHub.IsUserOnline(targetUser.Id.ToString()) ? DateTime.UtcNow : targetUser.CreatedAt,
|
||||||
new AdminUserStatsDto(
|
new AdminUserStatsDto(
|
||||||
messagesCount,
|
messagesCount,
|
||||||
mediaCount,
|
mediaCount,
|
||||||
+8
-5
@@ -1,12 +1,15 @@
|
|||||||
using System;
|
using Knot.Modules.Admin.Application.Admin.DTOs;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediatR;
|
using MediatR;
|
||||||
using Knot.Shared.Kernel;
|
using Knot.Shared.Kernel;
|
||||||
using Host.Models;
|
using Knot.Modules.Auth.Application.Auth.DTOs;
|
||||||
using Knot.Modules.Identity.Domain;
|
|
||||||
|
using Knot.Modules.Auth.Application.Users;
|
||||||
|
using Knot.Modules.Auth.Domain;
|
||||||
|
|
||||||
namespace Host.Application.Admin.Queries;
|
namespace Host.Application.Admin.Queries;
|
||||||
|
|
||||||
@@ -34,8 +37,8 @@ internal sealed class SearchUsersQueryHandler : IQueryHandler<SearchUsersQuery,
|
|||||||
u.Email,
|
u.Email,
|
||||||
u.Avatar,
|
u.Avatar,
|
||||||
u.CreatedAt,
|
u.CreatedAt,
|
||||||
Knot.Modules.Chats.Infrastructure.SignalR.ChatHub.IsUserOnline(u.Id.ToString()),
|
Knot.Modules.Conversations.Infrastructure.SignalR.ChatHub.IsUserOnline(u.Id.ToString()),
|
||||||
Knot.Modules.Chats.Infrastructure.SignalR.ChatHub.IsUserOnline(u.Id.ToString()) ? DateTime.UtcNow : u.CreatedAt
|
Knot.Modules.Conversations.Infrastructure.SignalR.ChatHub.IsUserOnline(u.Id.ToString()) ? DateTime.UtcNow : u.CreatedAt
|
||||||
)).ToList();
|
)).ToList();
|
||||||
|
|
||||||
return Result.Success(result);
|
return Result.Success(result);
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
namespace Knot.Modules.Admin;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
public static class DependencyInjection {
|
||||||
|
public static IServiceCollection AddAdminModule(this IServiceCollection services) {
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net10.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\Shared\Knot.Shared.Kernel\Knot.Shared.Kernel.csproj" />
|
||||||
|
<ProjectReference Include="..\..\Shared\Knot.Shared.Infrastructure\Knot.Shared.Infrastructure.csproj" />
|
||||||
|
<ProjectReference Include="..\Conversations\Knot.Modules.Conversations.csproj" />
|
||||||
|
<ProjectReference Include="..\Auth\Knot.Modules.Auth.csproj" />
|
||||||
|
<ProjectReference Include="..\Stories\Knot.Modules.Stories.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Carter" Version="10.0.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleToAttribute">
|
||||||
|
<_Parameter1>Knot.Modules.Admin.UnitTests</_Parameter1>
|
||||||
|
</AssemblyAttribute>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
using Carter;
|
||||||
|
using Knot.Modules.Auth.Application.Auth.DTOs;
|
||||||
|
using Knot.Shared.Kernel;
|
||||||
|
using Knot.Shared.Kernel.Configuration;
|
||||||
|
using Knot.Modules.Auth.Application.Users.Register;
|
||||||
|
using Knot.Shared.Kernel.Storage;
|
||||||
|
using Knot.Modules.Auth.Infrastructure.Persistence;
|
||||||
|
using MediatR;
|
||||||
|
using Host.Application.Admin.Queries;
|
||||||
|
using Host.Application.Admin.Commands;
|
||||||
|
using Microsoft.AspNetCore.Builder;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Routing;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
|
namespace Knot.Host.Presentation.Endpoints;
|
||||||
|
|
||||||
|
public sealed class AdminEndpoints : ICarterModule
|
||||||
|
{
|
||||||
|
public void AddRoutes(IEndpointRouteBuilder app)
|
||||||
|
{
|
||||||
|
var group = app.MapGroup("api/admin"); // Middleware handles auth
|
||||||
|
|
||||||
|
group.MapGet("settings", async (ISender sender, CancellationToken ct) =>
|
||||||
|
{
|
||||||
|
var result = await sender.Send(new GetSettingsQuery(), ct);
|
||||||
|
return Results.Ok(result.Value);
|
||||||
|
});
|
||||||
|
|
||||||
|
group.MapPut("settings", async ([FromBody] SystemSettingsDto settings, ISender sender, CancellationToken ct) =>
|
||||||
|
{
|
||||||
|
var result = await sender.Send(new UpdateSettingsCommand(settings), ct);
|
||||||
|
return Results.Ok(result.Value);
|
||||||
|
});
|
||||||
|
|
||||||
|
group.MapGet("dashboard", async (ISender sender, CancellationToken ct) =>
|
||||||
|
{
|
||||||
|
var result = await sender.Send(new GetDashboardStatsQuery(), ct);
|
||||||
|
return Results.Ok(result.Value);
|
||||||
|
});
|
||||||
|
|
||||||
|
group.MapPost("users", async ([FromBody] RegisterUserCommand command, ISender sender, CancellationToken ct) =>
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
return Results.Ok(userDetails.Value);
|
||||||
|
});
|
||||||
|
|
||||||
|
group.MapPost("users/{userId:guid}/reset-password", async (Guid userId, [FromBody] ResetPasswordDto dto, ISender sender, CancellationToken ct) =>
|
||||||
|
{
|
||||||
|
var result = await sender.Send(new ResetUserPasswordCommand(userId, dto.NewPassword), ct);
|
||||||
|
if (result.IsFailure)
|
||||||
|
{
|
||||||
|
if (result.Error.Code == "User.NotFound") return Results.NotFound(new { error = "User not found" });
|
||||||
|
return Results.BadRequest(new { error = result.Error.Description });
|
||||||
|
}
|
||||||
|
return Results.Ok(result.Value);
|
||||||
|
});
|
||||||
|
|
||||||
|
group.MapGet("users", async (ISender sender, [FromQuery] string query = "", CancellationToken ct = default) =>
|
||||||
|
{
|
||||||
|
var result = await sender.Send(new SearchUsersQuery(query), ct);
|
||||||
|
return Results.Ok(result.Value);
|
||||||
|
});
|
||||||
|
|
||||||
|
group.MapGet("users/{id:guid}", async (Guid id, ISender sender, CancellationToken ct) =>
|
||||||
|
{
|
||||||
|
var result = await sender.Send(new GetUserDetailsQuery(id), ct);
|
||||||
|
return result.IsSuccess ? Results.Ok(result.Value) : Results.NotFound("User not found");
|
||||||
|
});
|
||||||
|
|
||||||
|
group.MapGet("clean/dry-run", async (IFileStorageService fileStorage, AuthDbContext identityDb, ISender sender, CancellationToken ct) =>
|
||||||
|
{
|
||||||
|
var result = await sender.Send(new CleanDryRunQuery(fileStorage, identityDb), ct);
|
||||||
|
return Results.Ok(result.Value);
|
||||||
|
});
|
||||||
|
|
||||||
|
group.MapPost("clean/run", async (IFileStorageService fileStorage, AuthDbContext identityDb, ISender sender, CancellationToken ct) =>
|
||||||
|
{
|
||||||
|
var result = await sender.Send(new CleanRunCommand(fileStorage, identityDb), ct);
|
||||||
|
return Results.Ok(result.Value);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
+4
-4
@@ -1,14 +1,14 @@
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Knot.Modules.Identity.Domain;
|
using Knot.Modules.Auth.Domain;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
|
||||||
namespace Knot.Modules.Identity.Application.Abstractions;
|
namespace Knot.Modules.Auth.Application.Abstractions;
|
||||||
|
|
||||||
public interface IIdentityDbContext
|
public interface IAuthDbContext
|
||||||
{
|
{
|
||||||
DbSet<User> Users { get; }
|
DbSet<User> Users { get; }
|
||||||
DbSet<Friendship> Friendships { get; }
|
|
||||||
Task<int> SaveChangesAsync(CancellationToken cancellationToken);
|
Task<int> SaveChangesAsync(CancellationToken cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
+3
-2
@@ -1,10 +1,11 @@
|
|||||||
using Knot.Shared.Kernel;
|
using Knot.Shared.Kernel;
|
||||||
|
|
||||||
namespace Knot.Modules.Identity.Application.Abstractions;
|
namespace Knot.Modules.Auth.Application.Abstractions;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Unit of Work специфичный для модуля Identity.
|
/// Unit of Work специфичный для модуля Identity.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IIdentityUnitOfWork : IUnitOfWork
|
public interface IAuthUnitOfWork : IUnitOfWork
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
using Knot.Modules.Auth.Domain;
|
||||||
|
|
||||||
|
namespace Knot.Modules.Auth.Application.Abstractions;
|
||||||
|
|
||||||
|
public interface IJwtTokenProvider
|
||||||
|
{
|
||||||
|
string Generate(User user);
|
||||||
|
}
|
||||||
|
|
||||||
+2
-1
@@ -1,6 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Host.Models;
|
namespace Knot.Modules.Auth.Application.Auth.DTOs;
|
||||||
|
|
||||||
public record AuthResponseDto(
|
public record AuthResponseDto(
|
||||||
string Token,
|
string Token,
|
||||||
@@ -18,3 +18,4 @@ public record AuthUserDto(
|
|||||||
bool IsOnline,
|
bool IsOnline,
|
||||||
DateTime CreatedAt
|
DateTime CreatedAt
|
||||||
);
|
);
|
||||||
|
|
||||||
+2
-1
@@ -1,6 +1,7 @@
|
|||||||
namespace Host.Models;
|
namespace Knot.Modules.Auth.Application.Auth.DTOs;
|
||||||
|
|
||||||
public class ResetPasswordDto
|
public class ResetPasswordDto
|
||||||
{
|
{
|
||||||
public string NewPassword { get; set; } = string.Empty;
|
public string NewPassword { get; set; } = string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
+2
-1
@@ -1,6 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Knot.Modules.Identity.Application.Users.Auth;
|
namespace Knot.Modules.Auth.Application.Users.Auth;
|
||||||
|
|
||||||
public record AuthResponseDto(
|
public record AuthResponseDto(
|
||||||
string Token,
|
string Token,
|
||||||
@@ -18,3 +18,4 @@ public record AuthUserDto(
|
|||||||
bool IsOnline,
|
bool IsOnline,
|
||||||
DateTime CreatedAt
|
DateTime CreatedAt
|
||||||
);
|
);
|
||||||
|
|
||||||
+6
-5
@@ -1,9 +1,9 @@
|
|||||||
using Knot.Shared.Kernel;
|
using Knot.Shared.Kernel;
|
||||||
using Knot.Modules.Identity.Domain;
|
using Knot.Modules.Auth.Domain;
|
||||||
using Knot.Modules.Identity.Application.Abstractions;
|
|
||||||
using Knot.Modules.Identity.Application.Users.Auth;
|
|
||||||
|
|
||||||
namespace Knot.Modules.Identity.Application.Users.GetMe;
|
using Knot.Modules.Auth.Application.Users.Auth;
|
||||||
|
|
||||||
|
namespace Knot.Modules.Auth.Application.Users.GetMe;
|
||||||
|
|
||||||
public sealed record GetMeQuery(Guid UserId) : IQuery<AuthResponseDto>;
|
public sealed record GetMeQuery(Guid UserId) : IQuery<AuthResponseDto>;
|
||||||
|
|
||||||
@@ -21,7 +21,7 @@ internal sealed class GetMeQueryHandler : IQueryHandler<GetMeQuery, AuthResponse
|
|||||||
var user = await _userRepository.GetByIdAsync(request.UserId, cancellationToken);
|
var user = await _userRepository.GetByIdAsync(request.UserId, cancellationToken);
|
||||||
if (user == null)
|
if (user == null)
|
||||||
{
|
{
|
||||||
return Result.Failure<AuthResponseDto>(IdentityErrors.UserNotFound);
|
return Result.Failure<AuthResponseDto>(AuthErrors.UserNotFound);
|
||||||
}
|
}
|
||||||
|
|
||||||
var response = new AuthResponseDto(
|
var response = new AuthResponseDto(
|
||||||
@@ -42,3 +42,4 @@ internal sealed class GetMeQueryHandler : IQueryHandler<GetMeQuery, AuthResponse
|
|||||||
return Result.Success(response);
|
return Result.Success(response);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
+7
-5
@@ -1,10 +1,11 @@
|
|||||||
using Knot.Modules.Identity.Application.Abstractions;
|
|
||||||
using Knot.Modules.Identity.Domain;
|
using Knot.Modules.Auth.Domain;
|
||||||
|
using Knot.Modules.Auth.Application.Abstractions;
|
||||||
using Knot.Shared.Kernel;
|
using Knot.Shared.Kernel;
|
||||||
using Knot.Modules.Identity.Application.Users.Auth;
|
using Knot.Modules.Auth.Application.Users.Auth;
|
||||||
using BCrypt.Net;
|
using BCrypt.Net;
|
||||||
|
|
||||||
namespace Knot.Modules.Identity.Application.Users.Login;
|
namespace Knot.Modules.Auth.Application.Users.Login;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Команда для входа пользователя. Возвращает AuthResponseDto.
|
/// Команда для входа пользователя. Возвращает AuthResponseDto.
|
||||||
@@ -28,7 +29,7 @@ public sealed class LoginUserCommandHandler : ICommandHandler<LoginUserCommand,
|
|||||||
|
|
||||||
if (user is null || !BCrypt.Net.BCrypt.Verify(request.Password, user.PasswordHash))
|
if (user is null || !BCrypt.Net.BCrypt.Verify(request.Password, user.PasswordHash))
|
||||||
{
|
{
|
||||||
return Result.Failure<AuthResponseDto>(IdentityErrors.IdentityInvalidCredentials);
|
return Result.Failure<AuthResponseDto>(AuthErrors.IdentityInvalidCredentials);
|
||||||
}
|
}
|
||||||
|
|
||||||
string token = _tokenProvider.Generate(user);
|
string token = _tokenProvider.Generate(user);
|
||||||
@@ -49,3 +50,4 @@ public sealed class LoginUserCommandHandler : ICommandHandler<LoginUserCommand,
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
+10
-8
@@ -1,11 +1,12 @@
|
|||||||
using Knot.Modules.Identity.Application.Abstractions;
|
|
||||||
using Knot.Modules.Identity.Domain;
|
using Knot.Modules.Auth.Domain;
|
||||||
|
using Knot.Modules.Auth.Application.Abstractions;
|
||||||
using Knot.Shared.Kernel;
|
using Knot.Shared.Kernel;
|
||||||
using Knot.Shared.Kernel.Configuration;
|
using Knot.Shared.Kernel.Configuration;
|
||||||
using Knot.Modules.Identity.Application.Users.Auth;
|
using Knot.Modules.Auth.Application.Users.Auth;
|
||||||
using BCrypt.Net;
|
using BCrypt.Net;
|
||||||
|
|
||||||
namespace Knot.Modules.Identity.Application.Users.Register;
|
namespace Knot.Modules.Auth.Application.Users.Register;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Команда для регистрации нового пользователя.
|
/// Команда для регистрации нового пользователя.
|
||||||
@@ -23,13 +24,13 @@ public sealed record RegisterUserCommand(
|
|||||||
public sealed class RegisterUserCommandHandler : ICommandHandler<RegisterUserCommand, AuthResponseDto>
|
public sealed class RegisterUserCommandHandler : ICommandHandler<RegisterUserCommand, AuthResponseDto>
|
||||||
{
|
{
|
||||||
private readonly IUserRepository _userRepository;
|
private readonly IUserRepository _userRepository;
|
||||||
private readonly IIdentityUnitOfWork _unitOfWork;
|
private readonly IAuthUnitOfWork _unitOfWork;
|
||||||
private readonly ISettingsService _settings;
|
private readonly ISettingsService _settings;
|
||||||
private readonly IJwtTokenProvider _tokenProvider;
|
private readonly IJwtTokenProvider _tokenProvider;
|
||||||
|
|
||||||
public RegisterUserCommandHandler(
|
public RegisterUserCommandHandler(
|
||||||
IUserRepository userRepository,
|
IUserRepository userRepository,
|
||||||
IIdentityUnitOfWork unitOfWork,
|
IAuthUnitOfWork unitOfWork,
|
||||||
ISettingsService settings,
|
ISettingsService settings,
|
||||||
IJwtTokenProvider tokenProvider)
|
IJwtTokenProvider tokenProvider)
|
||||||
{
|
{
|
||||||
@@ -43,13 +44,13 @@ public sealed class RegisterUserCommandHandler : ICommandHandler<RegisterUserCom
|
|||||||
{
|
{
|
||||||
if (!_settings.Current.EnableRegistration)
|
if (!_settings.Current.EnableRegistration)
|
||||||
{
|
{
|
||||||
return Result.Failure<AuthResponseDto>(IdentityErrors.IdentityRegistrationDisabled);
|
return Result.Failure<AuthResponseDto>(AuthErrors.IdentityRegistrationDisabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1. Проверка уникальности username
|
// 1. Проверка уникальности username
|
||||||
if (!await _userRepository.IsUsernameUniqueAsync(request.Username, cancellationToken))
|
if (!await _userRepository.IsUsernameUniqueAsync(request.Username, cancellationToken))
|
||||||
{
|
{
|
||||||
return Result.Failure<AuthResponseDto>(IdentityErrors.IdentityUsernameNotUnique);
|
return Result.Failure<AuthResponseDto>(AuthErrors.IdentityUsernameNotUnique);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. Хеширование пароля (здесь будет вызов сервиса, пока заглушка)
|
// 2. Хеширование пароля (здесь будет вызов сервиса, пока заглушка)
|
||||||
@@ -85,3 +86,4 @@ public sealed class RegisterUserCommandHandler : ICommandHandler<RegisterUserCom
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
+11
-10
@@ -1,35 +1,35 @@
|
|||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Knot.Modules.Identity.Infrastructure.Persistence;
|
using Knot.Modules.Auth.Infrastructure.Persistence;
|
||||||
using Knot.Modules.Identity.Domain;
|
using Knot.Modules.Auth.Domain;
|
||||||
using Knot.Modules.Identity.Application.Abstractions;
|
using Knot.Modules.Auth.Application.Abstractions;
|
||||||
using Knot.Modules.Identity.Infrastructure.Authentication;
|
using Knot.Modules.Auth.Infrastructure.Authentication;
|
||||||
using Knot.Shared.Kernel;
|
using Knot.Shared.Kernel;
|
||||||
|
|
||||||
namespace Knot.Modules.Identity;
|
namespace Knot.Modules.Auth;
|
||||||
|
|
||||||
public static class DependencyInjection
|
public static class DependencyInjection
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Регистрация сервисов модуля Identity.
|
/// Регистрация сервисов модуля Identity.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static IServiceCollection AddIdentityModule(
|
public static IServiceCollection AddAuthModule(
|
||||||
this IServiceCollection services,
|
this IServiceCollection services,
|
||||||
IConfiguration configuration)
|
IConfiguration configuration)
|
||||||
{
|
{
|
||||||
// Настройка базы данных
|
// Настройка базы данных
|
||||||
string connectionString = configuration.GetConnectionString("DefaultConnection")!;
|
string connectionString = configuration.GetConnectionString("DefaultConnection")!;
|
||||||
|
|
||||||
services.AddDbContext<IdentityDbContext>(options =>
|
services.AddDbContext<AuthDbContext>(options =>
|
||||||
options.UseNpgsql(connectionString));
|
options.UseNpgsql(connectionString));
|
||||||
|
|
||||||
// Регистрация Unit of Work и Репозиториев
|
// Регистрация Unit of Work и Репозиториев
|
||||||
services.AddScoped<IIdentityUnitOfWork>(sp => sp.GetRequiredService<IdentityDbContext>());
|
services.AddScoped<IAuthUnitOfWork>(sp => sp.GetRequiredService<AuthDbContext>());
|
||||||
services.AddScoped<IIdentityDbContext>(sp => sp.GetRequiredService<IdentityDbContext>());
|
services.AddScoped<IAuthDbContext>(sp => sp.GetRequiredService<AuthDbContext>());
|
||||||
services.AddScoped<IUserRepository, UserRepository>();
|
services.AddScoped<IUserRepository, UserRepository>();
|
||||||
services.AddScoped<IJwtTokenProvider, JwtTokenProvider>();
|
services.AddScoped<IJwtTokenProvider, JwtTokenProvider>();
|
||||||
services.AddScoped<IUserDisplayNameProvider, Knot.Modules.Identity.Infrastructure.Services.UserDisplayNameProvider>();
|
services.AddScoped<IUserDisplayNameProvider, Knot.Modules.Auth.Infrastructure.Services.UserDisplayNameProvider>();
|
||||||
|
|
||||||
// Регистрация MediatR для этого модуля
|
// Регистрация MediatR для этого модуля
|
||||||
services.AddMediatR(config =>
|
services.AddMediatR(config =>
|
||||||
@@ -38,3 +38,4 @@ public static class DependencyInjection
|
|||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
+3
-2
@@ -1,8 +1,8 @@
|
|||||||
using Knot.Shared.Kernel;
|
using Knot.Shared.Kernel;
|
||||||
|
|
||||||
namespace Knot.Modules.Identity.Domain;
|
namespace Knot.Modules.Auth.Domain;
|
||||||
|
|
||||||
public static class IdentityErrors
|
public static class AuthErrors
|
||||||
{
|
{
|
||||||
public static readonly Error FriendsNotFound = new Error("Friends.NotFound", "Friendship not found");
|
public static readonly Error FriendsNotFound = new Error("Friends.NotFound", "Friendship not found");
|
||||||
public static readonly Error FriendsSelf = new Error("Friends.Self", "Cannot add yourself");
|
public static readonly Error FriendsSelf = new Error("Friends.Self", "Cannot add yourself");
|
||||||
@@ -12,3 +12,4 @@ public static class IdentityErrors
|
|||||||
public static readonly Error IdentityRegistrationDisabled = new Error("Identity.RegistrationDisabled", "Registration is disabled by the administrator.");
|
public static readonly Error IdentityRegistrationDisabled = new Error("Identity.RegistrationDisabled", "Registration is disabled by the administrator.");
|
||||||
public static readonly Error IdentityUsernameNotUnique = new Error("Identity.UsernameNotUnique", "Это имя пользователя уже занято.");
|
public static readonly Error IdentityUsernameNotUnique = new Error("Identity.UsernameNotUnique", "Это имя пользователя уже занято.");
|
||||||
}
|
}
|
||||||
|
|
||||||
+3
-2
@@ -1,6 +1,6 @@
|
|||||||
using Knot.Modules.Identity.Domain;
|
using Knot.Modules.Auth.Domain;
|
||||||
|
|
||||||
namespace Knot.Modules.Identity.Domain;
|
namespace Knot.Modules.Auth.Domain;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Интерфейс репозитория для работы с пользователями.
|
/// Интерфейс репозитория для работы с пользователями.
|
||||||
@@ -15,3 +15,4 @@ public interface IUserRepository
|
|||||||
void Add(User user);
|
void Add(User user);
|
||||||
void Update(User user);
|
void Update(User user);
|
||||||
}
|
}
|
||||||
|
|
||||||
+2
-1
@@ -1,6 +1,6 @@
|
|||||||
using Knot.Shared.Kernel;
|
using Knot.Shared.Kernel;
|
||||||
|
|
||||||
namespace Knot.Modules.Identity.Domain;
|
namespace Knot.Modules.Auth.Domain;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Сущность пользователя в контексте идентификации (Identity).
|
/// Сущность пользователя в контексте идентификации (Identity).
|
||||||
@@ -58,3 +58,4 @@ public sealed class User : AggregateRoot<Guid>
|
|||||||
PasswordHash = newPasswordHash;
|
PasswordHash = newPasswordHash;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
+4
-3
@@ -3,10 +3,10 @@ using System.Security.Claims;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.IdentityModel.Tokens;
|
using Microsoft.IdentityModel.Tokens;
|
||||||
using Knot.Modules.Identity.Application.Abstractions;
|
using Knot.Modules.Auth.Application.Abstractions;
|
||||||
using Knot.Modules.Identity.Domain;
|
using Knot.Modules.Auth.Domain;
|
||||||
|
|
||||||
namespace Knot.Modules.Identity.Infrastructure.Authentication;
|
namespace Knot.Modules.Auth.Infrastructure.Authentication;
|
||||||
|
|
||||||
public sealed class JwtTokenProvider : IJwtTokenProvider
|
public sealed class JwtTokenProvider : IJwtTokenProvider
|
||||||
{
|
{
|
||||||
@@ -43,3 +43,4 @@ public sealed class JwtTokenProvider : IJwtTokenProvider
|
|||||||
return new JwtSecurityTokenHandler().WriteToken(token);
|
return new JwtSecurityTokenHandler().WriteToken(token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
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.Shared.Kernel;
|
||||||
|
using Knot.Shared.Kernel.Security;
|
||||||
|
|
||||||
|
namespace Knot.Modules.Auth.Infrastructure.Persistence;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Контекст базы данных для модуля Identity.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class AuthDbContext : DbContext, IAuthUnitOfWork, Knot.Modules.Auth.Application.Abstractions.IAuthDbContext
|
||||||
|
{
|
||||||
|
private readonly IMediator _mediator;
|
||||||
|
private readonly IEncryptionService _encryptionService;
|
||||||
|
|
||||||
|
public AuthDbContext(DbContextOptions<AuthDbContext> options, IMediator mediator, IEncryptionService encryptionService)
|
||||||
|
: base(options)
|
||||||
|
{
|
||||||
|
_mediator = mediator;
|
||||||
|
_encryptionService = encryptionService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DbSet<User> Users => Set<User>();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||||
|
{
|
||||||
|
base.OnConfiguring(optionsBuilder);
|
||||||
|
optionsBuilder.ConfigureWarnings(w => w.Ignore(RelationalEventId.PendingModelChangesWarning));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
modelBuilder.HasDefaultSchema("identity");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
modelBuilder.Entity<User>(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();
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
var domainEvents = ChangeTracker
|
||||||
|
.Entries<IAggregateRoot>()
|
||||||
|
.SelectMany(x =>
|
||||||
|
|
||||||
|
{
|
||||||
|
if (x.Entity is AggregateRoot<Guid> root)
|
||||||
|
{
|
||||||
|
var events = root.GetDomainEvents().ToList();
|
||||||
|
root.ClearDomainEvents();
|
||||||
|
return events;
|
||||||
|
}
|
||||||
|
return Enumerable.Empty<IDomainEvent>();
|
||||||
|
})
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
int result = await base.SaveChangesAsync(cancellationToken);
|
||||||
|
|
||||||
|
foreach (var domainEvent in domainEvents)
|
||||||
|
{
|
||||||
|
await _mediator.Publish(domainEvent, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
+5
-4
@@ -1,16 +1,16 @@
|
|||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Knot.Modules.Identity.Domain;
|
using Knot.Modules.Auth.Domain;
|
||||||
|
|
||||||
namespace Knot.Modules.Identity.Infrastructure.Persistence;
|
namespace Knot.Modules.Auth.Infrastructure.Persistence;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Реализация репозитория пользователей с использованием EF Core.
|
/// Реализация репозитория пользователей с использованием EF Core.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class UserRepository : IUserRepository
|
public sealed class UserRepository : IUserRepository
|
||||||
{
|
{
|
||||||
private readonly IdentityDbContext _context;
|
private readonly AuthDbContext _context;
|
||||||
|
|
||||||
public UserRepository(IdentityDbContext context)
|
public UserRepository(AuthDbContext context)
|
||||||
{
|
{
|
||||||
_context = context;
|
_context = context;
|
||||||
}
|
}
|
||||||
@@ -54,3 +54,4 @@ public sealed class UserRepository : IUserRepository
|
|||||||
_context.Users.Update(user);
|
_context.Users.Update(user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
+3
-2
@@ -1,7 +1,7 @@
|
|||||||
using Knot.Shared.Kernel;
|
using Knot.Shared.Kernel;
|
||||||
using Knot.Modules.Identity.Domain;
|
using Knot.Modules.Auth.Domain;
|
||||||
|
|
||||||
namespace Knot.Modules.Identity.Infrastructure.Services;
|
namespace Knot.Modules.Auth.Infrastructure.Services;
|
||||||
|
|
||||||
public sealed class UserDisplayNameProvider : IUserDisplayNameProvider
|
public sealed class UserDisplayNameProvider : IUserDisplayNameProvider
|
||||||
{
|
{
|
||||||
@@ -40,3 +40,4 @@ public sealed class UserDisplayNameProvider : IUserDisplayNameProvider
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
+2
@@ -8,10 +8,12 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\..\Shared\Knot.Shared.Kernel\Knot.Shared.Kernel.csproj" />
|
<ProjectReference Include="..\..\Shared\Knot.Shared.Kernel\Knot.Shared.Kernel.csproj" />
|
||||||
|
<ProjectReference Include="..\Profiles\Knot.Modules.Profiles.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="BCrypt.Net-Next" Version="4.1.0" />
|
<PackageReference Include="BCrypt.Net-Next" Version="4.1.0" />
|
||||||
|
<PackageReference Include="Carter" Version="10.0.0" />
|
||||||
<PackageReference Include="MediatR" Version="12.0.1" />
|
<PackageReference Include="MediatR" Version="12.0.1" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="10.0.4" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="10.0.4" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="10.0.4" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="10.0.4" />
|
||||||
+24
-11
@@ -1,19 +1,19 @@
|
|||||||
// <auto-generated />
|
// <auto-generated />
|
||||||
using System;
|
using System;
|
||||||
|
using Knot.Modules.Auth.Infrastructure.Persistence;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||||
using Knot.Modules.Identity.Infrastructure.Persistence;
|
|
||||||
|
|
||||||
#nullable disable
|
#nullable disable
|
||||||
|
|
||||||
namespace Knot.Modules.Identity.Infrastructure.Persistence.Migrations
|
namespace Knot.Modules.Auth.Migrations
|
||||||
{
|
{
|
||||||
[DbContext(typeof(IdentityDbContext))]
|
[DbContext(typeof(AuthDbContext))]
|
||||||
[Migration("20260311180816_InitialIdentity")]
|
[Migration("20260322191927_InitialAuth")]
|
||||||
partial class InitialIdentity
|
partial class InitialAuth
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
@@ -26,20 +26,33 @@ namespace Knot.Modules.Identity.Infrastructure.Persistence.Migrations
|
|||||||
|
|
||||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||||
|
|
||||||
modelBuilder.Entity("Knot.Modules.Identity.Domain.User", b =>
|
modelBuilder.Entity("Knot.Modules.Auth.Domain.User", b =>
|
||||||
{
|
{
|
||||||
b.Property<Guid>("Id")
|
b.Property<Guid>("Id")
|
||||||
.ValueGeneratedOnAdd()
|
.ValueGeneratedOnAdd()
|
||||||
.HasColumnType("uuid");
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<string>("Avatar")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Bio")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("Birthday")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
b.Property<string>("DisplayName")
|
b.Property<string>("DisplayName")
|
||||||
.IsRequired()
|
.IsRequired()
|
||||||
.HasMaxLength(100)
|
.HasColumnType("text");
|
||||||
.HasColumnType("character varying(100)");
|
|
||||||
|
|
||||||
b.Property<string>("Email")
|
b.Property<string>("Email")
|
||||||
.HasMaxLength(255)
|
.HasColumnType("text");
|
||||||
.HasColumnType("character varying(255)");
|
|
||||||
|
b.Property<bool>("HideStoryViews")
|
||||||
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
b.Property<string>("PasswordHash")
|
b.Property<string>("PasswordHash")
|
||||||
.IsRequired()
|
.IsRequired()
|
||||||
+10
-5
@@ -1,12 +1,12 @@
|
|||||||
using System;
|
using System;
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
#nullable disable
|
#nullable disable
|
||||||
|
|
||||||
namespace Knot.Modules.Identity.Infrastructure.Persistence.Migrations
|
namespace Knot.Modules.Auth.Migrations
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public partial class InitialIdentity : Migration
|
public partial class InitialAuth : Migration
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
@@ -22,8 +22,13 @@ namespace Knot.Modules.Identity.Infrastructure.Persistence.Migrations
|
|||||||
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
Username = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: false),
|
Username = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: false),
|
||||||
PasswordHash = table.Column<string>(type: "text", nullable: false),
|
PasswordHash = table.Column<string>(type: "text", nullable: false),
|
||||||
DisplayName = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: false),
|
DisplayName = table.Column<string>(type: "text", nullable: false),
|
||||||
Email = table.Column<string>(type: "character varying(255)", maxLength: 255, nullable: true)
|
Email = table.Column<string>(type: "text", nullable: true),
|
||||||
|
Bio = table.Column<string>(type: "text", nullable: true),
|
||||||
|
Avatar = table.Column<string>(type: "text", nullable: true),
|
||||||
|
Birthday = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
|
||||||
|
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
|
||||||
|
HideStoryViews = table.Column<bool>(type: "boolean", nullable: false)
|
||||||
},
|
},
|
||||||
constraints: table =>
|
constraints: table =>
|
||||||
{
|
{
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using Knot.Modules.Auth.Infrastructure.Persistence;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Knot.Modules.Auth.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(AuthDbContext))]
|
||||||
|
partial class AuthDbContextModelSnapshot : ModelSnapshot
|
||||||
|
{
|
||||||
|
protected override void BuildModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasDefaultSchema("identity")
|
||||||
|
.HasAnnotation("ProductVersion", "10.0.4")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||||
|
|
||||||
|
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("Knot.Modules.Auth.Domain.User", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<string>("Avatar")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Bio")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("Birthday")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<string>("DisplayName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Email")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<bool>("HideStoryViews")
|
||||||
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
|
b.Property<string>("PasswordHash")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Username")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(50)
|
||||||
|
.HasColumnType("character varying(50)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("Username")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("Users", "identity");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
using Carter;
|
||||||
|
using Knot.Shared.Kernel;
|
||||||
|
using Knot.Modules.Auth.Application.Users.Login;
|
||||||
|
using Knot.Modules.Auth.Application.Users.Register;
|
||||||
|
using Knot.Modules.Auth.Application.Users.GetMe;
|
||||||
|
using MediatR;
|
||||||
|
using Microsoft.AspNetCore.Builder;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Routing;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
|
namespace Knot.Modules.Auth.Presentation.Endpoints;
|
||||||
|
|
||||||
|
public sealed class AuthEndpoints : ICarterModule
|
||||||
|
{
|
||||||
|
public void AddRoutes(IEndpointRouteBuilder app)
|
||||||
|
{
|
||||||
|
var group = app.MapGroup("api/auth");
|
||||||
|
|
||||||
|
group.MapPost("register", async ([FromBody] RegisterUserCommand command, ISender sender, CancellationToken ct) =>
|
||||||
|
{
|
||||||
|
var result = await sender.Send(command, ct);
|
||||||
|
return result.IsSuccess ? Results.Ok(result.Value) : Results.BadRequest(new { error = result.Error.Code ?? result.Error.Description });
|
||||||
|
});
|
||||||
|
|
||||||
|
group.MapPost("login", async ([FromBody] LoginUserCommand command, ISender sender, CancellationToken ct) =>
|
||||||
|
{
|
||||||
|
var result = await sender.Send(command, ct);
|
||||||
|
return result.IsSuccess ? Results.Ok(result.Value) : Results.Unauthorized();
|
||||||
|
});
|
||||||
|
|
||||||
|
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();
|
||||||
|
}).RequireAuthorization();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace Knot.Modules.Chats.Application.DTOs;
|
|
||||||
|
|
||||||
public sealed record CreatePersonalChatRequest(Guid UserId);
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
namespace Knot.Modules.Chats.Application.DTOs;
|
|
||||||
|
|
||||||
public record TogglePinResponse(bool IsPinned);
|
|
||||||
-99
@@ -1,99 +0,0 @@
|
|||||||
// <auto-generated />
|
|
||||||
using System;
|
|
||||||
using Knot.Modules.Chats.Infrastructure.Persistence;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
|
||||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace Knot.Modules.Chats.Migrations
|
|
||||||
{
|
|
||||||
[DbContext(typeof(ChatsDbContext))]
|
|
||||||
[Migration("20260319124845_InitialChats")]
|
|
||||||
partial class InitialChats
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
|
||||||
{
|
|
||||||
#pragma warning disable 612, 618
|
|
||||||
modelBuilder
|
|
||||||
.HasDefaultSchema("chats")
|
|
||||||
.HasAnnotation("ProductVersion", "10.0.4")
|
|
||||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
|
||||||
|
|
||||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
|
||||||
|
|
||||||
modelBuilder.Entity("Knot.Modules.Chats.Domain.Chat", b =>
|
|
||||||
{
|
|
||||||
b.Property<Guid>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("uuid");
|
|
||||||
|
|
||||||
b.Property<string>("Avatar")
|
|
||||||
.HasColumnType("text");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreatedAt")
|
|
||||||
.HasColumnType("timestamp with time zone");
|
|
||||||
|
|
||||||
b.Property<string>("Description")
|
|
||||||
.HasColumnType("text");
|
|
||||||
|
|
||||||
b.Property<string>("Name")
|
|
||||||
.HasColumnType("text");
|
|
||||||
|
|
||||||
b.Property<string>("Type")
|
|
||||||
.IsRequired()
|
|
||||||
.HasColumnType("text");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.ToTable("Chats", "chats");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Knot.Modules.Chats.Domain.Chat", b =>
|
|
||||||
{
|
|
||||||
b.OwnsMany("Knot.Modules.Chats.Domain.ChatMember", "Members", b1 =>
|
|
||||||
{
|
|
||||||
b1.Property<Guid>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("uuid");
|
|
||||||
|
|
||||||
b1.Property<Guid>("ChatId")
|
|
||||||
.HasColumnType("uuid");
|
|
||||||
|
|
||||||
b1.Property<bool>("IsMuted")
|
|
||||||
.HasColumnType("boolean");
|
|
||||||
|
|
||||||
b1.Property<bool>("IsPinned")
|
|
||||||
.HasColumnType("boolean");
|
|
||||||
|
|
||||||
b1.Property<DateTime>("JoinedAt")
|
|
||||||
.HasColumnType("timestamp with time zone");
|
|
||||||
|
|
||||||
b1.Property<string>("Role")
|
|
||||||
.IsRequired()
|
|
||||||
.HasColumnType("text");
|
|
||||||
|
|
||||||
b1.Property<Guid>("UserId")
|
|
||||||
.HasColumnType("uuid");
|
|
||||||
|
|
||||||
b1.HasKey("Id");
|
|
||||||
|
|
||||||
b1.HasIndex("ChatId", "UserId")
|
|
||||||
.IsUnique();
|
|
||||||
|
|
||||||
b1.ToTable("ChatMembers", "chats");
|
|
||||||
|
|
||||||
b1.WithOwner()
|
|
||||||
.HasForeignKey("ChatId");
|
|
||||||
});
|
|
||||||
|
|
||||||
b.Navigation("Members");
|
|
||||||
});
|
|
||||||
#pragma warning restore 612, 618
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace Knot.Modules.Chats.Migrations
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public partial class AddHighWaterMark : Migration
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.AddColumn<long>(
|
|
||||||
name: "LastMessageSequenceId",
|
|
||||||
schema: "chats",
|
|
||||||
table: "Chats",
|
|
||||||
type: "bigint",
|
|
||||||
nullable: false,
|
|
||||||
defaultValue: 0L);
|
|
||||||
|
|
||||||
migrationBuilder.AddColumn<Guid>(
|
|
||||||
name: "LastDeliveredMessageId",
|
|
||||||
schema: "chats",
|
|
||||||
table: "ChatMembers",
|
|
||||||
type: "uuid",
|
|
||||||
nullable: true);
|
|
||||||
|
|
||||||
migrationBuilder.AddColumn<Guid>(
|
|
||||||
name: "LastReadMessageId",
|
|
||||||
schema: "chats",
|
|
||||||
table: "ChatMembers",
|
|
||||||
type: "uuid",
|
|
||||||
nullable: true);
|
|
||||||
|
|
||||||
migrationBuilder.AddColumn<long>(
|
|
||||||
name: "LastReadSequenceId",
|
|
||||||
schema: "chats",
|
|
||||||
table: "ChatMembers",
|
|
||||||
type: "bigint",
|
|
||||||
nullable: false,
|
|
||||||
defaultValue: 0L);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "LastMessageSequenceId",
|
|
||||||
schema: "chats",
|
|
||||||
table: "Chats");
|
|
||||||
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "LastDeliveredMessageId",
|
|
||||||
schema: "chats",
|
|
||||||
table: "ChatMembers");
|
|
||||||
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "LastReadMessageId",
|
|
||||||
schema: "chats",
|
|
||||||
table: "ChatMembers");
|
|
||||||
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "LastReadSequenceId",
|
|
||||||
schema: "chats",
|
|
||||||
table: "ChatMembers");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+2
-1
@@ -1,6 +1,6 @@
|
|||||||
using Knot.Shared.Kernel;
|
using Knot.Shared.Kernel;
|
||||||
|
|
||||||
namespace Knot.Modules.Chats.Application.Abstractions;
|
namespace Knot.Modules.Conversations.Application.Abstractions;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Unit of Work специфичный для модуля Chats.
|
/// Unit of Work специфичный для модуля Chats.
|
||||||
@@ -8,3 +8,4 @@ namespace Knot.Modules.Chats.Application.Abstractions;
|
|||||||
public interface IChatsUnitOfWork : IUnitOfWork
|
public interface IChatsUnitOfWork : IUnitOfWork
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
+4
-3
@@ -4,14 +4,14 @@ using System.Threading;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Knot.Shared.Kernel;
|
using Knot.Shared.Kernel;
|
||||||
using Knot.Shared.Kernel.Storage;
|
using Knot.Shared.Kernel.Storage;
|
||||||
using Knot.Modules.Chats.Domain;
|
using Knot.Modules.Conversations.Domain;
|
||||||
using Knot.Modules.Chats.Application.Abstractions;
|
using Knot.Modules.Conversations.Application.Abstractions;
|
||||||
using MediatR;
|
using MediatR;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using SixLabors.ImageSharp;
|
using SixLabors.ImageSharp;
|
||||||
using SixLabors.ImageSharp.Processing;
|
using SixLabors.ImageSharp.Processing;
|
||||||
|
|
||||||
namespace Knot.Modules.Chats.Application.Chats.Avatar;
|
namespace Knot.Modules.Conversations.Application.Chats.Avatar;
|
||||||
|
|
||||||
public record UploadGroupAvatarCommand(Guid ChatId, Guid UserId, string FileName, string ContentType, Stream FileStream) : ICommand<Guid>;
|
public record UploadGroupAvatarCommand(Guid ChatId, Guid UserId, string FileName, string ContentType, Stream FileStream) : ICommand<Guid>;
|
||||||
|
|
||||||
@@ -127,3 +127,4 @@ internal sealed class RemoveGroupAvatarCommandHandler : ICommandHandler<RemoveGr
|
|||||||
return Result.Success(request.ChatId);
|
return Result.Success(request.ChatId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
+4
-3
@@ -2,12 +2,12 @@ using System;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Knot.Shared.Kernel;
|
using Knot.Shared.Kernel;
|
||||||
using Knot.Modules.Chats.Domain;
|
using Knot.Modules.Conversations.Domain;
|
||||||
using Knot.Modules.Chats.Application.Abstractions;
|
using Knot.Modules.Conversations.Application.Abstractions;
|
||||||
using MediatR;
|
using MediatR;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace Knot.Modules.Chats.Application.Chats.Clear;
|
namespace Knot.Modules.Conversations.Application.Chats.Clear;
|
||||||
|
|
||||||
public record ClearChatCommand(Guid ChatId, Guid UserId) : ICommand<MessageResponse>;
|
public record ClearChatCommand(Guid ChatId, Guid UserId) : ICommand<MessageResponse>;
|
||||||
|
|
||||||
@@ -32,3 +32,4 @@ internal sealed class ClearChatCommandHandler : ICommandHandler<ClearChatCommand
|
|||||||
return Result.Success(new MessageResponse("Cleared"));
|
return Result.Success(new MessageResponse("Cleared"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
+4
-3
@@ -1,9 +1,9 @@
|
|||||||
using Knot.Modules.Chats.Domain;
|
using Knot.Modules.Conversations.Domain;
|
||||||
using Knot.Shared.Kernel;
|
using Knot.Shared.Kernel;
|
||||||
|
|
||||||
using Knot.Modules.Chats.Application.Abstractions;
|
using Knot.Modules.Conversations.Application.Abstractions;
|
||||||
|
|
||||||
namespace Knot.Modules.Chats.Application.Chats.Create;
|
namespace Knot.Modules.Conversations.Application.Chats.Create;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Команда для создания чата.
|
/// Команда для создания чата.
|
||||||
@@ -41,3 +41,4 @@ public sealed class CreateChatCommandHandler : ICommandHandler<CreateChatCommand
|
|||||||
return Result.Success(chat.Id);
|
return Result.Success(chat.Id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
+8
-4
@@ -1,3 +1,5 @@
|
|||||||
|
using Knot.Modules.Messaging.Application.Abstractions;
|
||||||
|
using Knot.Modules.Messaging.Domain;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@@ -5,11 +7,11 @@ using System.Threading;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediatR;
|
using MediatR;
|
||||||
using Knot.Shared.Kernel;
|
using Knot.Shared.Kernel;
|
||||||
using Knot.Modules.Chats.Application.DTOs;
|
using Knot.Modules.Conversations.Application.DTOs;
|
||||||
using Knot.Modules.Chats.Domain;
|
using Knot.Modules.Conversations.Domain;
|
||||||
using Knot.Modules.Chats.Application.Abstractions;
|
using Knot.Modules.Conversations.Application.Abstractions;
|
||||||
|
|
||||||
namespace Knot.Modules.Chats.Application.Chats.GetChatById;
|
namespace Knot.Modules.Conversations.Application.Chats.GetChatById;
|
||||||
|
|
||||||
public record GetChatByIdQuery(Guid UserId, Guid ChatId) : IQuery<ChatDto?>;
|
public record GetChatByIdQuery(Guid UserId, Guid ChatId) : IQuery<ChatDto?>;
|
||||||
|
|
||||||
@@ -153,3 +155,5 @@ internal sealed class GetChatByIdQueryHandler : IQueryHandler<GetChatByIdQuery,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
+8
-4
@@ -1,3 +1,5 @@
|
|||||||
|
using Knot.Modules.Messaging.Application.Abstractions;
|
||||||
|
using Knot.Modules.Messaging.Domain;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@@ -5,12 +7,12 @@ using System.Threading;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediatR;
|
using MediatR;
|
||||||
using Knot.Shared.Kernel;
|
using Knot.Shared.Kernel;
|
||||||
using Knot.Modules.Chats.Application.DTOs;
|
using Knot.Modules.Conversations.Application.DTOs;
|
||||||
using Knot.Modules.Chats.Domain;
|
using Knot.Modules.Conversations.Domain;
|
||||||
using Knot.Modules.Chats.Application.Abstractions;
|
using Knot.Modules.Conversations.Application.Abstractions;
|
||||||
|
|
||||||
|
|
||||||
namespace Knot.Modules.Chats.Application.Chats.GetChats;
|
namespace Knot.Modules.Conversations.Application.Chats.GetChats;
|
||||||
|
|
||||||
public record GetChatsQuery(Guid UserId) : IQuery<List<ChatDto>>;
|
public record GetChatsQuery(Guid UserId) : IQuery<List<ChatDto>>;
|
||||||
|
|
||||||
@@ -147,3 +149,5 @@ internal sealed class GetChatsQueryHandler : IQueryHandler<GetChatsQuery, List<C
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
+4
-3
@@ -1,8 +1,8 @@
|
|||||||
using Knot.Modules.Chats.Domain;
|
using Knot.Modules.Conversations.Domain;
|
||||||
using Knot.Shared.Kernel;
|
using Knot.Shared.Kernel;
|
||||||
using Knot.Modules.Chats.Application.Abstractions;
|
using Knot.Modules.Conversations.Application.Abstractions;
|
||||||
|
|
||||||
namespace Knot.Modules.Chats.Application.Chats.GetOrCreateFavorites;
|
namespace Knot.Modules.Conversations.Application.Chats.GetOrCreateFavorites;
|
||||||
|
|
||||||
public sealed record GetOrCreateFavoritesCommand(Guid UserId) : ICommand<Guid>;
|
public sealed record GetOrCreateFavoritesCommand(Guid UserId) : ICommand<Guid>;
|
||||||
|
|
||||||
@@ -36,3 +36,4 @@ public sealed class GetOrCreateFavoritesCommandHandler : ICommandHandler<GetOrCr
|
|||||||
return Result.Success(chat.Id);
|
return Result.Success(chat.Id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
+4
-3
@@ -3,12 +3,12 @@ using System;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Knot.Shared.Kernel;
|
using Knot.Shared.Kernel;
|
||||||
using Knot.Modules.Chats.Domain;
|
using Knot.Modules.Conversations.Domain;
|
||||||
using Knot.Modules.Chats.Application.Abstractions;
|
using Knot.Modules.Conversations.Application.Abstractions;
|
||||||
using MediatR;
|
using MediatR;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace Knot.Modules.Chats.Application.Chats.LeaveOrDelete;
|
namespace Knot.Modules.Conversations.Application.Chats.LeaveOrDelete;
|
||||||
|
|
||||||
public record LeaveOrDeleteChatCommand(Guid ChatId, Guid UserId) : ICommand<SuccessResponse>;
|
public record LeaveOrDeleteChatCommand(Guid ChatId, Guid UserId) : ICommand<SuccessResponse>;
|
||||||
|
|
||||||
@@ -51,3 +51,4 @@ internal sealed class LeaveOrDeleteChatCommandHandler : ICommandHandler<LeaveOrD
|
|||||||
return Result.Success(new SuccessResponse(true));
|
return Result.Success(new SuccessResponse(true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user