Compare commits
63
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8399d32490 | ||
|
|
3905094ff4 | ||
|
|
9e8625aea1 | ||
|
|
5b905c94da | ||
|
|
0eecc01374 | ||
|
|
c37e1723d4 | ||
|
|
02043d4d97 | ||
|
|
852efa090e | ||
|
|
c45f4db61c | ||
|
|
02a85fc587 | ||
|
|
e09860700c | ||
|
|
32c9bc43cf | ||
|
|
d96e4ec7d4 | ||
|
|
1558b20470 | ||
|
|
fa185afc73 | ||
|
|
90096ce2bc | ||
|
|
65d5f5fee9 | ||
|
|
e11240f78f | ||
|
|
53f193970c | ||
|
|
f41ad0bcf8 | ||
|
|
b49ff47762 | ||
|
|
182bbe2ad8 | ||
|
|
a04f04a448 | ||
|
|
2ab5b295e8 | ||
|
|
1b8abbc995 | ||
|
|
943699139b | ||
|
|
757142eda7 | ||
|
|
a42007df2d | ||
|
|
9df7d7aaf1 | ||
|
|
4ae7dd60ce | ||
|
|
249c344df8 | ||
|
|
2c6d6f831f | ||
|
|
bce8f92101 | ||
|
|
aa69c44a64 | ||
|
|
4faa7561a0 | ||
|
|
8025340e45 | ||
|
|
60d3cf12ae | ||
|
|
b09e197626 | ||
|
|
f1f8f6e012 | ||
|
|
d3f1e3f361 | ||
|
|
ce212c11c1 | ||
|
|
143c0b7dc4 | ||
|
|
cb93ff7240 | ||
|
|
09e5cbaa76 | ||
|
|
465e84e686 | ||
|
|
44d59dab2a | ||
|
|
b719c50413 | ||
|
|
9438cf1b35 | ||
|
|
89b2eeea6c | ||
|
|
0209802e9e | ||
|
|
22bc964f27 | ||
|
|
9bae9752cc | ||
|
|
ba5c5210d4 | ||
|
|
030ae1e4e4 | ||
|
|
28fb8c25de | ||
|
|
11f2b232a3 | ||
|
|
16978c423c | ||
|
|
b399649cfd | ||
|
|
7ef73b414c | ||
|
|
7cb6ac61dd | ||
|
|
6e532b021d | ||
|
|
5da1a2f45d | ||
|
|
f3e0941647 |
+479
-61
@@ -13,19 +13,113 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Knot.Shared.Infrastructure"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Modules", "Modules", "{EC447DCF-ABFA-6E24-52A5-D7FD48A5C558}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Identity", "Identity", "{0EC62A1A-9858-3A60-8A0C-FC9AACFA2EC7}"
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Profiles", "Profiles", "{CA5186C2-289A-9324-4152-9805A73A9773}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Knot.Modules.Identity", "src\Modules\Identity\Knot.Modules.Identity.csproj", "{5BB2F421-C4C4-40A1-8D6E-FEBB79AE7C98}"
|
||||
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}") = "Chats", "Chats", "{B4154CE3-9153-E2B0-0515-138FFCE32938}"
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Relations", "Relations", "{10980DF6-D81A-2FEE-4ACB-4D508FA38BC6}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Knot.Modules.Chats", "src\Modules\Chats\Knot.Modules.Chats.csproj", "{695CC919-E321-4DC0-8D70-C631C51624E1}"
|
||||
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}") = "tests", "tests", "{0AB3BF05-4346-4AA6-1389-037BE0695223}"
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Stories", "Stories", "{F83653D1-5494-68B8-6444-7DEF58635BF6}"
|
||||
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("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Knot.Modules.Stories", "src\Modules\Stories\Knot.Modules.Stories.csproj", "{BC98E6FC-B46A-4554-B75E-B912714A915C}"
|
||||
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("{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("{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("{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("{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("{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("{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("{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
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Host", "src\Host\Host.csproj", "{98ABB710-9106-4E5C-AA04-D19D5E92EDC1}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Contracts", "Contracts", "{FFBE31B8-50B9-B415-22BC-2F92C97CADA3}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Admin", "Admin", "{1C8A9B45-FCC1-A5B3-3601-CB39D7CED4E3}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Knot.Contracts.Admin", "src\Contracts\Admin\Knot.Contracts.Admin.csproj", "{D3C7D267-5646-4907-A451-E7CFA853BBF5}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Auth", "Auth", "{28F8F726-0D9B-F051-A252-088B861055C6}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Knot.Contracts.Auth", "src\Contracts\Auth\Knot.Contracts.Auth.csproj", "{D65EE034-84B9-4EBE-BC1F-5606AB4524A4}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Conversations", "Conversations", "{19B3F750-A3A3-3AEB-CE4F-46FB52BB3151}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Knot.Contracts.Conversations", "src\Contracts\Conversations\Knot.Contracts.Conversations.csproj", "{17B31CB0-F2C5-47A6-9BF2-C55403C97DC7}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Federation", "Federation", "{E97EBA1B-122C-1D64-94D9-187425FF5DF0}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Knot.Contracts.Federation", "src\Contracts\Federation\Knot.Contracts.Federation.csproj", "{62A821F2-F296-4888-8AB1-A80ED514AC08}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Klipy", "Klipy", "{7555181C-EB04-A6C5-D475-6FC0320F57B5}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Knot.Contracts.Klipy", "src\Contracts\Klipy\Knot.Contracts.Klipy.csproj", "{D0CE2D52-EC1C-444E-A5C5-79813E1814D4}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Messaging", "Messaging", "{3E835F76-AFEE-6419-1441-2CED62F241B2}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Knot.Contracts.Messaging", "src\Contracts\Messaging\Knot.Contracts.Messaging.csproj", "{87048157-DF94-49E6-A34F-7DEF3255FA35}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Profiles", "Profiles", "{0286CA1A-73E9-C153-D97B-31BA60AC101B}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Knot.Contracts.Profiles", "src\Contracts\Profiles\Knot.Contracts.Profiles.csproj", "{D28F8DB7-077E-47F6-B07D-BB93AF950A0D}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Relations", "Relations", "{319B016B-E46C-7232-249F-DBE50922C757}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Knot.Contracts.Relations", "src\Contracts\Relations\Knot.Contracts.Relations.csproj", "{75CDF4D0-53B2-4FCE-9C2D-06940FD2E817}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Settings", "Settings", "{C91F5B42-26A0-36B8-1C54-AE965E022F68}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Knot.Contracts.Settings", "src\Contracts\Settings\Knot.Contracts.Settings.csproj", "{338C69EA-F921-41B3-BB6C-116AADEBF356}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Storage", "Storage", "{6F45E82C-238A-FDE4-59E5-CCCD65D77EB8}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Knot.Contracts.Storage", "src\Contracts\Storage\Knot.Contracts.Storage.csproj", "{531F88C6-B9A5-4BF6-A121-AAA95DE4A288}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Stories", "Stories", "{3DE423CC-7CB5-260E-2A62-D5E89000EF8F}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Knot.Contracts.Stories", "src\Contracts\Stories\Knot.Contracts.Stories.csproj", "{613354F0-3B35-4406-8250-C8E88A0DECF6}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "TelegramImport", "TelegramImport", "{5C1B4B87-5A65-F9C7-EAA3-6456BCBFD6EC}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Knot.Contracts.TelegramImport", "src\Contracts\TelegramImport\Knot.Contracts.TelegramImport.csproj", "{A47CCC4C-8B19-4A12-8B05-BE4AAEABB1BA}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WebRtc", "WebRtc", "{6DD751EB-CB14-7F42-4B4B-7E4DCC49705A}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Knot.Contracts.WebRtc", "src\Contracts\WebRtc\Knot.Contracts.WebRtc.csproj", "{D939680D-864D-4FED-A81D-8F30EE6A97A0}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
@@ -61,54 +155,330 @@ Global
|
||||
{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.Build.0 = Release|Any CPU
|
||||
{5BB2F421-C4C4-40A1-8D6E-FEBB79AE7C98}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{5BB2F421-C4C4-40A1-8D6E-FEBB79AE7C98}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{5BB2F421-C4C4-40A1-8D6E-FEBB79AE7C98}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{5BB2F421-C4C4-40A1-8D6E-FEBB79AE7C98}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{5BB2F421-C4C4-40A1-8D6E-FEBB79AE7C98}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{5BB2F421-C4C4-40A1-8D6E-FEBB79AE7C98}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{5BB2F421-C4C4-40A1-8D6E-FEBB79AE7C98}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{5BB2F421-C4C4-40A1-8D6E-FEBB79AE7C98}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{5BB2F421-C4C4-40A1-8D6E-FEBB79AE7C98}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{5BB2F421-C4C4-40A1-8D6E-FEBB79AE7C98}.Release|x64.Build.0 = Release|Any CPU
|
||||
{5BB2F421-C4C4-40A1-8D6E-FEBB79AE7C98}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{5BB2F421-C4C4-40A1-8D6E-FEBB79AE7C98}.Release|x86.Build.0 = Release|Any CPU
|
||||
{695CC919-E321-4DC0-8D70-C631C51624E1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{695CC919-E321-4DC0-8D70-C631C51624E1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{695CC919-E321-4DC0-8D70-C631C51624E1}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{695CC919-E321-4DC0-8D70-C631C51624E1}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{695CC919-E321-4DC0-8D70-C631C51624E1}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{695CC919-E321-4DC0-8D70-C631C51624E1}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{695CC919-E321-4DC0-8D70-C631C51624E1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{695CC919-E321-4DC0-8D70-C631C51624E1}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{695CC919-E321-4DC0-8D70-C631C51624E1}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{695CC919-E321-4DC0-8D70-C631C51624E1}.Release|x64.Build.0 = Release|Any CPU
|
||||
{695CC919-E321-4DC0-8D70-C631C51624E1}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{695CC919-E321-4DC0-8D70-C631C51624E1}.Release|x86.Build.0 = Release|Any CPU
|
||||
{AB2F334E-DD7C-4314-93B9-941AFC6B2ACD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AB2F334E-DD7C-4314-93B9-941AFC6B2ACD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AB2F334E-DD7C-4314-93B9-941AFC6B2ACD}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{AB2F334E-DD7C-4314-93B9-941AFC6B2ACD}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{AB2F334E-DD7C-4314-93B9-941AFC6B2ACD}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{AB2F334E-DD7C-4314-93B9-941AFC6B2ACD}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{AB2F334E-DD7C-4314-93B9-941AFC6B2ACD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{AB2F334E-DD7C-4314-93B9-941AFC6B2ACD}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{AB2F334E-DD7C-4314-93B9-941AFC6B2ACD}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{AB2F334E-DD7C-4314-93B9-941AFC6B2ACD}.Release|x64.Build.0 = Release|Any CPU
|
||||
{AB2F334E-DD7C-4314-93B9-941AFC6B2ACD}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{AB2F334E-DD7C-4314-93B9-941AFC6B2ACD}.Release|x86.Build.0 = Release|Any CPU
|
||||
{F48A3E3A-EEBB-43AA-81AB-7DD7FE5F29B4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{F48A3E3A-EEBB-43AA-81AB-7DD7FE5F29B4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{F48A3E3A-EEBB-43AA-81AB-7DD7FE5F29B4}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{F48A3E3A-EEBB-43AA-81AB-7DD7FE5F29B4}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{F48A3E3A-EEBB-43AA-81AB-7DD7FE5F29B4}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{F48A3E3A-EEBB-43AA-81AB-7DD7FE5F29B4}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{F48A3E3A-EEBB-43AA-81AB-7DD7FE5F29B4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F48A3E3A-EEBB-43AA-81AB-7DD7FE5F29B4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{F48A3E3A-EEBB-43AA-81AB-7DD7FE5F29B4}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{F48A3E3A-EEBB-43AA-81AB-7DD7FE5F29B4}.Release|x64.Build.0 = Release|Any CPU
|
||||
{F48A3E3A-EEBB-43AA-81AB-7DD7FE5F29B4}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{F48A3E3A-EEBB-43AA-81AB-7DD7FE5F29B4}.Release|x86.Build.0 = Release|Any CPU
|
||||
{CD14770B-8BCD-4D93-AD2C-581ED030E209}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{CD14770B-8BCD-4D93-AD2C-581ED030E209}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{CD14770B-8BCD-4D93-AD2C-581ED030E209}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{CD14770B-8BCD-4D93-AD2C-581ED030E209}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{CD14770B-8BCD-4D93-AD2C-581ED030E209}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{CD14770B-8BCD-4D93-AD2C-581ED030E209}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{CD14770B-8BCD-4D93-AD2C-581ED030E209}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{CD14770B-8BCD-4D93-AD2C-581ED030E209}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{CD14770B-8BCD-4D93-AD2C-581ED030E209}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{CD14770B-8BCD-4D93-AD2C-581ED030E209}.Release|x64.Build.0 = Release|Any CPU
|
||||
{CD14770B-8BCD-4D93-AD2C-581ED030E209}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{CD14770B-8BCD-4D93-AD2C-581ED030E209}.Release|x86.Build.0 = Release|Any CPU
|
||||
{B97352F3-709A-42CF-A448-07B9996F5FBE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B97352F3-709A-42CF-A448-07B9996F5FBE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B97352F3-709A-42CF-A448-07B9996F5FBE}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{B97352F3-709A-42CF-A448-07B9996F5FBE}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{B97352F3-709A-42CF-A448-07B9996F5FBE}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{B97352F3-709A-42CF-A448-07B9996F5FBE}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{B97352F3-709A-42CF-A448-07B9996F5FBE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B97352F3-709A-42CF-A448-07B9996F5FBE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B97352F3-709A-42CF-A448-07B9996F5FBE}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{B97352F3-709A-42CF-A448-07B9996F5FBE}.Release|x64.Build.0 = Release|Any CPU
|
||||
{B97352F3-709A-42CF-A448-07B9996F5FBE}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{B97352F3-709A-42CF-A448-07B9996F5FBE}.Release|x86.Build.0 = Release|Any CPU
|
||||
{BC98E6FC-B46A-4554-B75E-B912714A915C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{BC98E6FC-B46A-4554-B75E-B912714A915C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BC98E6FC-B46A-4554-B75E-B912714A915C}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{BC98E6FC-B46A-4554-B75E-B912714A915C}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{BC98E6FC-B46A-4554-B75E-B912714A915C}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{BC98E6FC-B46A-4554-B75E-B912714A915C}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{BC98E6FC-B46A-4554-B75E-B912714A915C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{BC98E6FC-B46A-4554-B75E-B912714A915C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{BC98E6FC-B46A-4554-B75E-B912714A915C}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{BC98E6FC-B46A-4554-B75E-B912714A915C}.Release|x64.Build.0 = Release|Any CPU
|
||||
{BC98E6FC-B46A-4554-B75E-B912714A915C}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{BC98E6FC-B46A-4554-B75E-B912714A915C}.Release|x86.Build.0 = Release|Any CPU
|
||||
{D052C05A-CDCD-48DF-8F4F-0B10E3719819}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D052C05A-CDCD-48DF-8F4F-0B10E3719819}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D052C05A-CDCD-48DF-8F4F-0B10E3719819}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{D052C05A-CDCD-48DF-8F4F-0B10E3719819}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{D052C05A-CDCD-48DF-8F4F-0B10E3719819}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{D052C05A-CDCD-48DF-8F4F-0B10E3719819}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{D052C05A-CDCD-48DF-8F4F-0B10E3719819}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D052C05A-CDCD-48DF-8F4F-0B10E3719819}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D052C05A-CDCD-48DF-8F4F-0B10E3719819}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{D052C05A-CDCD-48DF-8F4F-0B10E3719819}.Release|x64.Build.0 = Release|Any CPU
|
||||
{D052C05A-CDCD-48DF-8F4F-0B10E3719819}.Release|x86.ActiveCfg = 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
|
||||
{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
|
||||
{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
|
||||
{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
|
||||
{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
|
||||
{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
|
||||
{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
|
||||
{98ABB710-9106-4E5C-AA04-D19D5E92EDC1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{98ABB710-9106-4E5C-AA04-D19D5E92EDC1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{98ABB710-9106-4E5C-AA04-D19D5E92EDC1}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{98ABB710-9106-4E5C-AA04-D19D5E92EDC1}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{98ABB710-9106-4E5C-AA04-D19D5E92EDC1}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{98ABB710-9106-4E5C-AA04-D19D5E92EDC1}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{98ABB710-9106-4E5C-AA04-D19D5E92EDC1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{98ABB710-9106-4E5C-AA04-D19D5E92EDC1}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{98ABB710-9106-4E5C-AA04-D19D5E92EDC1}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{98ABB710-9106-4E5C-AA04-D19D5E92EDC1}.Release|x64.Build.0 = Release|Any CPU
|
||||
{98ABB710-9106-4E5C-AA04-D19D5E92EDC1}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{98ABB710-9106-4E5C-AA04-D19D5E92EDC1}.Release|x86.Build.0 = Release|Any CPU
|
||||
{D3C7D267-5646-4907-A451-E7CFA853BBF5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D3C7D267-5646-4907-A451-E7CFA853BBF5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D3C7D267-5646-4907-A451-E7CFA853BBF5}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{D3C7D267-5646-4907-A451-E7CFA853BBF5}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{D3C7D267-5646-4907-A451-E7CFA853BBF5}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{D3C7D267-5646-4907-A451-E7CFA853BBF5}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{D3C7D267-5646-4907-A451-E7CFA853BBF5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D3C7D267-5646-4907-A451-E7CFA853BBF5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D3C7D267-5646-4907-A451-E7CFA853BBF5}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{D3C7D267-5646-4907-A451-E7CFA853BBF5}.Release|x64.Build.0 = Release|Any CPU
|
||||
{D3C7D267-5646-4907-A451-E7CFA853BBF5}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{D3C7D267-5646-4907-A451-E7CFA853BBF5}.Release|x86.Build.0 = Release|Any CPU
|
||||
{D65EE034-84B9-4EBE-BC1F-5606AB4524A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D65EE034-84B9-4EBE-BC1F-5606AB4524A4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D65EE034-84B9-4EBE-BC1F-5606AB4524A4}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{D65EE034-84B9-4EBE-BC1F-5606AB4524A4}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{D65EE034-84B9-4EBE-BC1F-5606AB4524A4}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{D65EE034-84B9-4EBE-BC1F-5606AB4524A4}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{D65EE034-84B9-4EBE-BC1F-5606AB4524A4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D65EE034-84B9-4EBE-BC1F-5606AB4524A4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D65EE034-84B9-4EBE-BC1F-5606AB4524A4}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{D65EE034-84B9-4EBE-BC1F-5606AB4524A4}.Release|x64.Build.0 = Release|Any CPU
|
||||
{D65EE034-84B9-4EBE-BC1F-5606AB4524A4}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{D65EE034-84B9-4EBE-BC1F-5606AB4524A4}.Release|x86.Build.0 = Release|Any CPU
|
||||
{17B31CB0-F2C5-47A6-9BF2-C55403C97DC7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{17B31CB0-F2C5-47A6-9BF2-C55403C97DC7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{17B31CB0-F2C5-47A6-9BF2-C55403C97DC7}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{17B31CB0-F2C5-47A6-9BF2-C55403C97DC7}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{17B31CB0-F2C5-47A6-9BF2-C55403C97DC7}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{17B31CB0-F2C5-47A6-9BF2-C55403C97DC7}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{17B31CB0-F2C5-47A6-9BF2-C55403C97DC7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{17B31CB0-F2C5-47A6-9BF2-C55403C97DC7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{17B31CB0-F2C5-47A6-9BF2-C55403C97DC7}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{17B31CB0-F2C5-47A6-9BF2-C55403C97DC7}.Release|x64.Build.0 = Release|Any CPU
|
||||
{17B31CB0-F2C5-47A6-9BF2-C55403C97DC7}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{17B31CB0-F2C5-47A6-9BF2-C55403C97DC7}.Release|x86.Build.0 = Release|Any CPU
|
||||
{62A821F2-F296-4888-8AB1-A80ED514AC08}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{62A821F2-F296-4888-8AB1-A80ED514AC08}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{62A821F2-F296-4888-8AB1-A80ED514AC08}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{62A821F2-F296-4888-8AB1-A80ED514AC08}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{62A821F2-F296-4888-8AB1-A80ED514AC08}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{62A821F2-F296-4888-8AB1-A80ED514AC08}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{62A821F2-F296-4888-8AB1-A80ED514AC08}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{62A821F2-F296-4888-8AB1-A80ED514AC08}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{62A821F2-F296-4888-8AB1-A80ED514AC08}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{62A821F2-F296-4888-8AB1-A80ED514AC08}.Release|x64.Build.0 = Release|Any CPU
|
||||
{62A821F2-F296-4888-8AB1-A80ED514AC08}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{62A821F2-F296-4888-8AB1-A80ED514AC08}.Release|x86.Build.0 = Release|Any CPU
|
||||
{D0CE2D52-EC1C-444E-A5C5-79813E1814D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D0CE2D52-EC1C-444E-A5C5-79813E1814D4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D0CE2D52-EC1C-444E-A5C5-79813E1814D4}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{D0CE2D52-EC1C-444E-A5C5-79813E1814D4}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{D0CE2D52-EC1C-444E-A5C5-79813E1814D4}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{D0CE2D52-EC1C-444E-A5C5-79813E1814D4}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{D0CE2D52-EC1C-444E-A5C5-79813E1814D4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D0CE2D52-EC1C-444E-A5C5-79813E1814D4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D0CE2D52-EC1C-444E-A5C5-79813E1814D4}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{D0CE2D52-EC1C-444E-A5C5-79813E1814D4}.Release|x64.Build.0 = Release|Any CPU
|
||||
{D0CE2D52-EC1C-444E-A5C5-79813E1814D4}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{D0CE2D52-EC1C-444E-A5C5-79813E1814D4}.Release|x86.Build.0 = Release|Any CPU
|
||||
{87048157-DF94-49E6-A34F-7DEF3255FA35}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{87048157-DF94-49E6-A34F-7DEF3255FA35}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{87048157-DF94-49E6-A34F-7DEF3255FA35}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{87048157-DF94-49E6-A34F-7DEF3255FA35}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{87048157-DF94-49E6-A34F-7DEF3255FA35}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{87048157-DF94-49E6-A34F-7DEF3255FA35}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{87048157-DF94-49E6-A34F-7DEF3255FA35}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{87048157-DF94-49E6-A34F-7DEF3255FA35}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{87048157-DF94-49E6-A34F-7DEF3255FA35}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{87048157-DF94-49E6-A34F-7DEF3255FA35}.Release|x64.Build.0 = Release|Any CPU
|
||||
{87048157-DF94-49E6-A34F-7DEF3255FA35}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{87048157-DF94-49E6-A34F-7DEF3255FA35}.Release|x86.Build.0 = Release|Any CPU
|
||||
{D28F8DB7-077E-47F6-B07D-BB93AF950A0D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D28F8DB7-077E-47F6-B07D-BB93AF950A0D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D28F8DB7-077E-47F6-B07D-BB93AF950A0D}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{D28F8DB7-077E-47F6-B07D-BB93AF950A0D}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{D28F8DB7-077E-47F6-B07D-BB93AF950A0D}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{D28F8DB7-077E-47F6-B07D-BB93AF950A0D}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{D28F8DB7-077E-47F6-B07D-BB93AF950A0D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D28F8DB7-077E-47F6-B07D-BB93AF950A0D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D28F8DB7-077E-47F6-B07D-BB93AF950A0D}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{D28F8DB7-077E-47F6-B07D-BB93AF950A0D}.Release|x64.Build.0 = Release|Any CPU
|
||||
{D28F8DB7-077E-47F6-B07D-BB93AF950A0D}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{D28F8DB7-077E-47F6-B07D-BB93AF950A0D}.Release|x86.Build.0 = Release|Any CPU
|
||||
{75CDF4D0-53B2-4FCE-9C2D-06940FD2E817}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{75CDF4D0-53B2-4FCE-9C2D-06940FD2E817}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{75CDF4D0-53B2-4FCE-9C2D-06940FD2E817}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{75CDF4D0-53B2-4FCE-9C2D-06940FD2E817}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{75CDF4D0-53B2-4FCE-9C2D-06940FD2E817}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{75CDF4D0-53B2-4FCE-9C2D-06940FD2E817}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{75CDF4D0-53B2-4FCE-9C2D-06940FD2E817}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{75CDF4D0-53B2-4FCE-9C2D-06940FD2E817}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{75CDF4D0-53B2-4FCE-9C2D-06940FD2E817}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{75CDF4D0-53B2-4FCE-9C2D-06940FD2E817}.Release|x64.Build.0 = Release|Any CPU
|
||||
{75CDF4D0-53B2-4FCE-9C2D-06940FD2E817}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{75CDF4D0-53B2-4FCE-9C2D-06940FD2E817}.Release|x86.Build.0 = Release|Any CPU
|
||||
{338C69EA-F921-41B3-BB6C-116AADEBF356}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{338C69EA-F921-41B3-BB6C-116AADEBF356}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{338C69EA-F921-41B3-BB6C-116AADEBF356}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{338C69EA-F921-41B3-BB6C-116AADEBF356}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{338C69EA-F921-41B3-BB6C-116AADEBF356}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{338C69EA-F921-41B3-BB6C-116AADEBF356}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{338C69EA-F921-41B3-BB6C-116AADEBF356}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{338C69EA-F921-41B3-BB6C-116AADEBF356}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{338C69EA-F921-41B3-BB6C-116AADEBF356}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{338C69EA-F921-41B3-BB6C-116AADEBF356}.Release|x64.Build.0 = Release|Any CPU
|
||||
{338C69EA-F921-41B3-BB6C-116AADEBF356}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{338C69EA-F921-41B3-BB6C-116AADEBF356}.Release|x86.Build.0 = Release|Any CPU
|
||||
{531F88C6-B9A5-4BF6-A121-AAA95DE4A288}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{531F88C6-B9A5-4BF6-A121-AAA95DE4A288}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{531F88C6-B9A5-4BF6-A121-AAA95DE4A288}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{531F88C6-B9A5-4BF6-A121-AAA95DE4A288}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{531F88C6-B9A5-4BF6-A121-AAA95DE4A288}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{531F88C6-B9A5-4BF6-A121-AAA95DE4A288}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{531F88C6-B9A5-4BF6-A121-AAA95DE4A288}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{531F88C6-B9A5-4BF6-A121-AAA95DE4A288}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{531F88C6-B9A5-4BF6-A121-AAA95DE4A288}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{531F88C6-B9A5-4BF6-A121-AAA95DE4A288}.Release|x64.Build.0 = Release|Any CPU
|
||||
{531F88C6-B9A5-4BF6-A121-AAA95DE4A288}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{531F88C6-B9A5-4BF6-A121-AAA95DE4A288}.Release|x86.Build.0 = Release|Any CPU
|
||||
{613354F0-3B35-4406-8250-C8E88A0DECF6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{613354F0-3B35-4406-8250-C8E88A0DECF6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{613354F0-3B35-4406-8250-C8E88A0DECF6}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{613354F0-3B35-4406-8250-C8E88A0DECF6}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{613354F0-3B35-4406-8250-C8E88A0DECF6}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{613354F0-3B35-4406-8250-C8E88A0DECF6}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{613354F0-3B35-4406-8250-C8E88A0DECF6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{613354F0-3B35-4406-8250-C8E88A0DECF6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{613354F0-3B35-4406-8250-C8E88A0DECF6}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{613354F0-3B35-4406-8250-C8E88A0DECF6}.Release|x64.Build.0 = Release|Any CPU
|
||||
{613354F0-3B35-4406-8250-C8E88A0DECF6}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{613354F0-3B35-4406-8250-C8E88A0DECF6}.Release|x86.Build.0 = Release|Any CPU
|
||||
{A47CCC4C-8B19-4A12-8B05-BE4AAEABB1BA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A47CCC4C-8B19-4A12-8B05-BE4AAEABB1BA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A47CCC4C-8B19-4A12-8B05-BE4AAEABB1BA}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{A47CCC4C-8B19-4A12-8B05-BE4AAEABB1BA}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{A47CCC4C-8B19-4A12-8B05-BE4AAEABB1BA}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{A47CCC4C-8B19-4A12-8B05-BE4AAEABB1BA}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{A47CCC4C-8B19-4A12-8B05-BE4AAEABB1BA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A47CCC4C-8B19-4A12-8B05-BE4AAEABB1BA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{A47CCC4C-8B19-4A12-8B05-BE4AAEABB1BA}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{A47CCC4C-8B19-4A12-8B05-BE4AAEABB1BA}.Release|x64.Build.0 = Release|Any CPU
|
||||
{A47CCC4C-8B19-4A12-8B05-BE4AAEABB1BA}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{A47CCC4C-8B19-4A12-8B05-BE4AAEABB1BA}.Release|x86.Build.0 = Release|Any CPU
|
||||
{D939680D-864D-4FED-A81D-8F30EE6A97A0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D939680D-864D-4FED-A81D-8F30EE6A97A0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D939680D-864D-4FED-A81D-8F30EE6A97A0}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{D939680D-864D-4FED-A81D-8F30EE6A97A0}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{D939680D-864D-4FED-A81D-8F30EE6A97A0}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{D939680D-864D-4FED-A81D-8F30EE6A97A0}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{D939680D-864D-4FED-A81D-8F30EE6A97A0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D939680D-864D-4FED-A81D-8F30EE6A97A0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D939680D-864D-4FED-A81D-8F30EE6A97A0}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{D939680D-864D-4FED-A81D-8F30EE6A97A0}.Release|x64.Build.0 = Release|Any CPU
|
||||
{D939680D-864D-4FED-A81D-8F30EE6A97A0}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{D939680D-864D-4FED-A81D-8F30EE6A97A0}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@@ -118,11 +488,59 @@ Global
|
||||
{C829F859-FF48-4025-BF22-8E63672D113C} = {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}
|
||||
{0EC62A1A-9858-3A60-8A0C-FC9AACFA2EC7} = {EC447DCF-ABFA-6E24-52A5-D7FD48A5C558}
|
||||
{5BB2F421-C4C4-40A1-8D6E-FEBB79AE7C98} = {0EC62A1A-9858-3A60-8A0C-FC9AACFA2EC7}
|
||||
{B4154CE3-9153-E2B0-0515-138FFCE32938} = {EC447DCF-ABFA-6E24-52A5-D7FD48A5C558}
|
||||
{695CC919-E321-4DC0-8D70-C631C51624E1} = {B4154CE3-9153-E2B0-0515-138FFCE32938}
|
||||
{AB2F334E-DD7C-4314-93B9-941AFC6B2ACD} = {0AB3BF05-4346-4AA6-1389-037BE0695223}
|
||||
{F48A3E3A-EEBB-43AA-81AB-7DD7FE5F29B4} = {0AB3BF05-4346-4AA6-1389-037BE0695223}
|
||||
{CA5186C2-289A-9324-4152-9805A73A9773} = {EC447DCF-ABFA-6E24-52A5-D7FD48A5C558}
|
||||
{CD14770B-8BCD-4D93-AD2C-581ED030E209} = {CA5186C2-289A-9324-4152-9805A73A9773}
|
||||
{10980DF6-D81A-2FEE-4ACB-4D508FA38BC6} = {EC447DCF-ABFA-6E24-52A5-D7FD48A5C558}
|
||||
{B97352F3-709A-42CF-A448-07B9996F5FBE} = {10980DF6-D81A-2FEE-4ACB-4D508FA38BC6}
|
||||
{F83653D1-5494-68B8-6444-7DEF58635BF6} = {EC447DCF-ABFA-6E24-52A5-D7FD48A5C558}
|
||||
{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}
|
||||
{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}
|
||||
{E9E1155A-A339-766C-C185-6698FF423EBC} = {EC447DCF-ABFA-6E24-52A5-D7FD48A5C558}
|
||||
{FFC12440-F128-48F5-9BE5-E5263930F876} = {E9E1155A-A339-766C-C185-6698FF423EBC}
|
||||
{837D2CF4-7AEA-BF76-6362-47ECD7058EEC} = {EC447DCF-ABFA-6E24-52A5-D7FD48A5C558}
|
||||
{716E089D-0661-4D39-813B-063DF9A4C0E4} = {837D2CF4-7AEA-BF76-6362-47ECD7058EEC}
|
||||
{4BC86D3F-8D7B-ACB9-EA51-9374BC9D421A} = {EC447DCF-ABFA-6E24-52A5-D7FD48A5C558}
|
||||
{2498C58C-53B0-4DF2-B4EA-BA69B35A7488} = {4BC86D3F-8D7B-ACB9-EA51-9374BC9D421A}
|
||||
{0587C5BB-3015-204D-19B6-EB01E03E48B6} = {EC447DCF-ABFA-6E24-52A5-D7FD48A5C558}
|
||||
{AEFD93B4-59B8-4B02-A694-CA15E4EC1C08} = {0587C5BB-3015-204D-19B6-EB01E03E48B6}
|
||||
{DD6FAF9E-10A0-95E7-0C06-698A6F70AFEE} = {EC447DCF-ABFA-6E24-52A5-D7FD48A5C558}
|
||||
{03BE4EB1-FD38-445A-9A4B-7B481560E9A2} = {DD6FAF9E-10A0-95E7-0C06-698A6F70AFEE}
|
||||
{98ABB710-9106-4E5C-AA04-D19D5E92EDC1} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
|
||||
{FFBE31B8-50B9-B415-22BC-2F92C97CADA3} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
|
||||
{1C8A9B45-FCC1-A5B3-3601-CB39D7CED4E3} = {FFBE31B8-50B9-B415-22BC-2F92C97CADA3}
|
||||
{D3C7D267-5646-4907-A451-E7CFA853BBF5} = {1C8A9B45-FCC1-A5B3-3601-CB39D7CED4E3}
|
||||
{28F8F726-0D9B-F051-A252-088B861055C6} = {FFBE31B8-50B9-B415-22BC-2F92C97CADA3}
|
||||
{D65EE034-84B9-4EBE-BC1F-5606AB4524A4} = {28F8F726-0D9B-F051-A252-088B861055C6}
|
||||
{19B3F750-A3A3-3AEB-CE4F-46FB52BB3151} = {FFBE31B8-50B9-B415-22BC-2F92C97CADA3}
|
||||
{17B31CB0-F2C5-47A6-9BF2-C55403C97DC7} = {19B3F750-A3A3-3AEB-CE4F-46FB52BB3151}
|
||||
{E97EBA1B-122C-1D64-94D9-187425FF5DF0} = {FFBE31B8-50B9-B415-22BC-2F92C97CADA3}
|
||||
{62A821F2-F296-4888-8AB1-A80ED514AC08} = {E97EBA1B-122C-1D64-94D9-187425FF5DF0}
|
||||
{7555181C-EB04-A6C5-D475-6FC0320F57B5} = {FFBE31B8-50B9-B415-22BC-2F92C97CADA3}
|
||||
{D0CE2D52-EC1C-444E-A5C5-79813E1814D4} = {7555181C-EB04-A6C5-D475-6FC0320F57B5}
|
||||
{3E835F76-AFEE-6419-1441-2CED62F241B2} = {FFBE31B8-50B9-B415-22BC-2F92C97CADA3}
|
||||
{87048157-DF94-49E6-A34F-7DEF3255FA35} = {3E835F76-AFEE-6419-1441-2CED62F241B2}
|
||||
{0286CA1A-73E9-C153-D97B-31BA60AC101B} = {FFBE31B8-50B9-B415-22BC-2F92C97CADA3}
|
||||
{D28F8DB7-077E-47F6-B07D-BB93AF950A0D} = {0286CA1A-73E9-C153-D97B-31BA60AC101B}
|
||||
{319B016B-E46C-7232-249F-DBE50922C757} = {FFBE31B8-50B9-B415-22BC-2F92C97CADA3}
|
||||
{75CDF4D0-53B2-4FCE-9C2D-06940FD2E817} = {319B016B-E46C-7232-249F-DBE50922C757}
|
||||
{C91F5B42-26A0-36B8-1C54-AE965E022F68} = {FFBE31B8-50B9-B415-22BC-2F92C97CADA3}
|
||||
{338C69EA-F921-41B3-BB6C-116AADEBF356} = {C91F5B42-26A0-36B8-1C54-AE965E022F68}
|
||||
{6F45E82C-238A-FDE4-59E5-CCCD65D77EB8} = {FFBE31B8-50B9-B415-22BC-2F92C97CADA3}
|
||||
{531F88C6-B9A5-4BF6-A121-AAA95DE4A288} = {6F45E82C-238A-FDE4-59E5-CCCD65D77EB8}
|
||||
{3DE423CC-7CB5-260E-2A62-D5E89000EF8F} = {FFBE31B8-50B9-B415-22BC-2F92C97CADA3}
|
||||
{613354F0-3B35-4406-8250-C8E88A0DECF6} = {3DE423CC-7CB5-260E-2A62-D5E89000EF8F}
|
||||
{5C1B4B87-5A65-F9C7-EAA3-6456BCBFD6EC} = {FFBE31B8-50B9-B415-22BC-2F92C97CADA3}
|
||||
{A47CCC4C-8B19-4A12-8B05-BE4AAEABB1BA} = {5C1B4B87-5A65-F9C7-EAA3-6456BCBFD6EC}
|
||||
{6DD751EB-CB14-7F42-4B4B-7E4DCC49705A} = {FFBE31B8-50B9-B415-22BC-2F92C97CADA3}
|
||||
{D939680D-864D-4FED-A81D-8F30EE6A97A0} = {6DD751EB-CB14-7F42-4B4B-7E4DCC49705A}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Shared\IntegrationTests.Shared\Knot.IntegrationTests.Shared.csproj" />
|
||||
<ProjectReference Include="..\..\..\src\Modules\Admin\Knot.Modules.Admin.csproj" />
|
||||
<ProjectReference Include="..\..\..\src\Shared\Knot.Shared.Kernel\Knot.Shared.Kernel.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="Xunit" />
|
||||
<ProjectReference Include="..\..\..\src\Modules\Settings\Knot.Modules.Settings.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
<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" />
|
||||
<ProjectReference Include="..\..\..\src\Modules\Settings\Knot.Modules.Settings.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\Settings\Knot.Modules.Settings.csproj" />
|
||||
<ProjectReference Include="..\..\..\src\Shared\Knot.Shared.Kernel\Knot.Shared.Kernel.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,58 @@
|
||||
using FluentAssertions;
|
||||
using Knot.Modules.Admin.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>());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<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="xunit" Version="2.9.2" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="Xunit" />
|
||||
<ProjectReference Include="..\..\..\src\Modules\Settings\Knot.Modules.Settings.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
+4
-1
@@ -23,7 +23,10 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Modules\Chats\Knot.Modules.Chats.csproj" />
|
||||
<ProjectReference Include="..\..\..\src\Modules\Auth\Knot.Modules.Auth.csproj" />
|
||||
<ProjectReference Include="..\..\..\src\Modules\Settings\Knot.Modules.Settings.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
|
||||
+8
-7
@@ -1,15 +1,15 @@
|
||||
using FluentAssertions;
|
||||
using NSubstitute;
|
||||
using Knot.Modules.Identity.Application.Abstractions;
|
||||
using Knot.Modules.Identity.Application.Users.Login;
|
||||
using Knot.Modules.Identity.Domain;
|
||||
using Knot.Modules.Auth.Application.Abstractions;
|
||||
using Knot.Modules.Auth.Application.Users.Login;
|
||||
using Knot.Modules.Auth.Domain;
|
||||
using Knot.Shared.Kernel;
|
||||
using Knot.Modules.Identity.Application.Users.Auth;
|
||||
using Knot.Modules.Auth.Application.Users.Auth;
|
||||
using Xunit;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Knot.Modules.Identity.UnitTests;
|
||||
namespace Knot.Modules.Auth.UnitTests;
|
||||
|
||||
public class LoginUserCommandHandlerTests
|
||||
{
|
||||
@@ -61,7 +61,7 @@ public class LoginUserCommandHandlerTests
|
||||
|
||||
// Assert
|
||||
result.IsFailure.Should().BeTrue();
|
||||
result.Error.Code.Should().Be(IdentityErrors.IdentityInvalidCredentials.Code);
|
||||
result.Error.Code.Should().Be(AuthErrors.IdentityInvalidCredentials.Code);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -82,6 +82,7 @@ public class LoginUserCommandHandlerTests
|
||||
|
||||
// Assert
|
||||
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 Xunit;
|
||||
using Knot.Shared.Kernel;
|
||||
using Knot.Modules.Chats.Domain;
|
||||
using Knot.Modules.Chats.Application.Abstractions;
|
||||
using Knot.Modules.Chats.Application.Chats.Create;
|
||||
using Knot.Modules.Conversations.Domain;
|
||||
using Knot.Modules.Messaging.Domain;
|
||||
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
|
||||
{
|
||||
@@ -49,3 +50,5 @@ public class CreateChatCommandHandlerTests
|
||||
await _unitOfWork.Received(1).SaveChangesAsync(Arg.Any<CancellationToken>());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+12
-10
@@ -7,18 +7,20 @@ using FluentAssertions;
|
||||
using NSubstitute;
|
||||
using Xunit;
|
||||
using Knot.Shared.Kernel;
|
||||
using Knot.Modules.Chats.Domain;
|
||||
using Knot.Modules.Chats.Application.Abstractions;
|
||||
using Knot.Modules.Chats.Application.Chats.GetChats;
|
||||
using Knot.Modules.Chats.Application.DTOs;
|
||||
using Knot.Modules.Conversations.Domain;
|
||||
using Knot.Modules.Messaging.Domain;
|
||||
using Knot.Modules.Conversations.Application.Abstractions;
|
||||
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
|
||||
{
|
||||
private readonly IChatRepository _chatRepository;
|
||||
private readonly IUserDisplayNameProvider _userProvider;
|
||||
private readonly IMessageRepository _messageRepository;
|
||||
private readonly IMessageReactionRepository _reactionRepository;
|
||||
private readonly GetChatsQueryHandler _handler;
|
||||
|
||||
public GetChatsQueryHandlerTests()
|
||||
@@ -26,8 +28,9 @@ public class GetChatsQueryHandlerTests
|
||||
_chatRepository = Substitute.For<IChatRepository>();
|
||||
_userProvider = Substitute.For<IUserDisplayNameProvider>();
|
||||
_messageRepository = Substitute.For<IMessageRepository>();
|
||||
_reactionRepository = Substitute.For<IMessageReactionRepository>();
|
||||
|
||||
_handler = new GetChatsQueryHandler(_chatRepository, _userProvider, _messageRepository);
|
||||
_handler = new GetChatsQueryHandler(_chatRepository, _userProvider, _messageRepository, _reactionRepository);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -54,9 +57,6 @@ public class GetChatsQueryHandlerTests
|
||||
_userProvider.GetUsersInfoAsync(Arg.Any<IEnumerable<Guid>>(), Arg.Any<CancellationToken>())
|
||||
.Returns(new Dictionary<Guid, UserInfo>());
|
||||
|
||||
_messageRepository.GetUnreadCountAsync(Arg.Any<Guid>(), userId, Arg.Any<CancellationToken>())
|
||||
.Returns(0);
|
||||
|
||||
// Act
|
||||
var result = await _handler.Handle(request, CancellationToken.None);
|
||||
|
||||
@@ -65,8 +65,10 @@ public class GetChatsQueryHandlerTests
|
||||
result.Value.Should().NotBeNull();
|
||||
|
||||
// It always appends synthetic "favorites" chat at the end if not found
|
||||
result.Value.Count.Should().Be(3);
|
||||
result.Value.Count.Should().Be(2);
|
||||
result.Value.Any(c => c.Name == "Test Chat").Should().BeTrue();
|
||||
result.Value.Any(c => c.Type == "favorites").Should().BeTrue();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+7
-4
@@ -1,12 +1,13 @@
|
||||
using FluentAssertions;
|
||||
using NSubstitute;
|
||||
using Knot.Modules.Chats.Application.Abstractions;
|
||||
using Knot.Modules.Chats.Application.Chats.GetOrCreateFavorites;
|
||||
using Knot.Modules.Chats.Domain;
|
||||
using Knot.Modules.Conversations.Application.Abstractions;
|
||||
using Knot.Modules.Conversations.Application.Chats.GetOrCreateFavorites;
|
||||
using Knot.Modules.Conversations.Domain;
|
||||
using Knot.Modules.Messaging.Domain;
|
||||
using Knot.Shared.Kernel;
|
||||
using Xunit;
|
||||
|
||||
namespace Knot.Modules.Chats.UnitTests;
|
||||
namespace Knot.Modules.Conversations.UnitTests;
|
||||
|
||||
public class GetOrCreateFavoritesCommandHandlerTests
|
||||
{
|
||||
@@ -69,3 +70,5 @@ public class GetOrCreateFavoritesCommandHandlerTests
|
||||
await _unitOfWork.Received(1).SaveChangesAsync(Arg.Any<CancellationToken>());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+5
-1
@@ -23,7 +23,11 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Modules\Identity\Knot.Modules.Identity.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" />
|
||||
<ProjectReference Include="..\..\..\src\Modules\Settings\Knot.Modules.Settings.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
+15
-5
@@ -8,11 +8,14 @@ using MediatR;
|
||||
using NSubstitute;
|
||||
using Xunit;
|
||||
using Knot.Shared.Kernel;
|
||||
using Knot.Modules.Chats.Domain;
|
||||
using Knot.Modules.Chats.Application.Abstractions;
|
||||
using Knot.Modules.Chats.Application.Messages.Send;
|
||||
using Knot.Modules.Conversations.Domain;
|
||||
using Knot.Modules.Messaging.Domain;
|
||||
using Knot.Modules.Conversations.Application.Abstractions;
|
||||
using Knot.Modules.Conversations.Application.Messages.Send;
|
||||
using Knot.Modules.Settings.Application.Settings.Abstractions;
|
||||
using Knot.Modules.Settings.Application.Settings.DTOs;
|
||||
|
||||
namespace Knot.Modules.Chats.UnitTests.Messages;
|
||||
namespace Knot.Modules.Conversations.UnitTests.Messages;
|
||||
|
||||
public class SendMessageCommandHandlerTests
|
||||
{
|
||||
@@ -20,6 +23,7 @@ public class SendMessageCommandHandlerTests
|
||||
private readonly IMessageRepository _messageRepository;
|
||||
private readonly IChatsUnitOfWork _unitOfWork;
|
||||
private readonly IMediator _mediator;
|
||||
private readonly IMessagesSettings _messagesSettings;
|
||||
private readonly SendMessageCommandHandler _handler;
|
||||
|
||||
public SendMessageCommandHandlerTests()
|
||||
@@ -28,8 +32,12 @@ public class SendMessageCommandHandlerTests
|
||||
_messageRepository = Substitute.For<IMessageRepository>();
|
||||
_unitOfWork = Substitute.For<IChatsUnitOfWork>();
|
||||
_mediator = Substitute.For<IMediator>();
|
||||
_messagesSettings = Substitute.For<IMessagesSettings>();
|
||||
|
||||
_handler = new SendMessageCommandHandler(_chatRepository, _messageRepository, _unitOfWork, _mediator);
|
||||
var config = new Knot.Modules.Settings.Application.Settings.DTOs.MessagesConfig();
|
||||
_messagesSettings.Current.Returns(config);
|
||||
|
||||
_handler = new SendMessageCommandHandler(_chatRepository, _messageRepository, _unitOfWork, _mediator, _messagesSettings);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -95,3 +103,5 @@ public class SendMessageCommandHandlerTests
|
||||
await _unitOfWork.Received(1).SaveChangesAsync(Arg.Any<CancellationToken>());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<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="xunit" Version="2.9.2" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="Xunit" />
|
||||
<ProjectReference Include="..\..\..\src\Modules\Settings\Knot.Modules.Settings.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
<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" />
|
||||
<ProjectReference Include="..\..\..\src\Modules\Settings\Knot.Modules.Settings.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
<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" />
|
||||
<ProjectReference Include="..\..\..\src\Modules\Settings\Knot.Modules.Settings.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<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="xunit" Version="2.9.2" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="Xunit" />
|
||||
<ProjectReference Include="..\..\..\src\Modules\Settings\Knot.Modules.Settings.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
<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" />
|
||||
<ProjectReference Include="..\..\..\src\Modules\Settings\Knot.Modules.Settings.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<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="xunit" Version="2.9.2" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="Xunit" />
|
||||
<ProjectReference Include="..\..\..\src\Modules\Settings\Knot.Modules.Settings.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
<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" />
|
||||
<ProjectReference Include="..\..\..\src\Modules\Settings\Knot.Modules.Settings.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Mvc.Testing;
|
||||
using Microsoft.AspNetCore.TestHost;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System.Net.Http;
|
||||
using Testcontainers.PostgreSql;
|
||||
using Testcontainers.MongoDb;
|
||||
using Xunit;
|
||||
using System.Threading.Tasks;
|
||||
using System.Collections.Generic;
|
||||
using Knot.Shared.Kernel;
|
||||
using NSubstitute;
|
||||
|
||||
namespace Knot.IntegrationTests;
|
||||
|
||||
public abstract class BaseIntegrationTest : IAsyncLifetime
|
||||
{
|
||||
protected readonly PostgreSqlContainer _postgresContainer = new PostgreSqlBuilder()
|
||||
.WithImage("postgres:15-alpine")
|
||||
.Build();
|
||||
|
||||
protected readonly MongoDbContainer _mongoContainer = new MongoDbBuilder()
|
||||
.WithImage("mongo:6.0")
|
||||
.Build();
|
||||
|
||||
protected HttpClient _client;
|
||||
protected WebApplicationFactory<Program> _factory;
|
||||
protected readonly Guid _userId = Guid.NewGuid();
|
||||
protected readonly IUserContext _userContextMock = Substitute.For<IUserContext>();
|
||||
|
||||
public virtual async Task InitializeAsync()
|
||||
{
|
||||
await _postgresContainer.StartAsync();
|
||||
await _mongoContainer.StartAsync();
|
||||
|
||||
_userContextMock.UserId.Returns(_userId);
|
||||
_userContextMock.IsAuthenticated.Returns(true);
|
||||
|
||||
_factory = new IntegrationTestWebApplicationFactory(
|
||||
_postgresContainer.GetConnectionString(),
|
||||
_mongoContainer.GetConnectionString(),
|
||||
_userContextMock);
|
||||
|
||||
_client = _factory.CreateClient();
|
||||
}
|
||||
|
||||
public virtual async Task DisposeAsync()
|
||||
{
|
||||
await _postgresContainer.StopAsync();
|
||||
await _mongoContainer.StopAsync();
|
||||
_factory?.Dispose();
|
||||
_client?.Dispose();
|
||||
}
|
||||
|
||||
private class IntegrationTestWebApplicationFactory : WebApplicationFactory<Program>
|
||||
{
|
||||
private readonly string _pgConnectionString;
|
||||
private readonly string _mongoConnectionString;
|
||||
private readonly IUserContext _userContext;
|
||||
|
||||
public IntegrationTestWebApplicationFactory(string pg, string mongo, IUserContext userContext)
|
||||
{
|
||||
_pgConnectionString = pg;
|
||||
_mongoConnectionString = mongo;
|
||||
_userContext = userContext;
|
||||
}
|
||||
|
||||
protected override void ConfigureWebHost(IWebHostBuilder builder)
|
||||
{
|
||||
builder.ConfigureAppConfiguration((context, config) =>
|
||||
{
|
||||
config.AddInMemoryCollection(new Dictionary<string, string?>
|
||||
{
|
||||
["ConnectionStrings:DefaultConnection"] = _pgConnectionString,
|
||||
["ConnectionStrings:MongoConnection"] = _mongoConnectionString,
|
||||
["DATABASE_URL"] = _pgConnectionString,
|
||||
["MONGO_CONNECTION"] = _mongoConnectionString,
|
||||
["KNOT_MASTER_ENCRYPTION_KEY"] = "TestEncryptionKey_32CharactersLong!"
|
||||
});
|
||||
});
|
||||
|
||||
builder.ConfigureTestServices(services => {
|
||||
services.AddScoped(_ => _userContext);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
<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.9.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="10.0.5" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="10.0.5" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.0" />
|
||||
<PackageReference Include="NSubstitute" Version="5.3.0" />
|
||||
<PackageReference Include="Respawn" Version="7.0.0" />
|
||||
<PackageReference Include="Testcontainers.MongoDb" Version="4.11.0" />
|
||||
<PackageReference Include="Testcontainers.PostgreSql" Version="4.11.0" />
|
||||
<PackageReference Include="xunit" Version="2.9.2" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="Xunit" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\src\Host\Host.csproj" />
|
||||
<ProjectReference Include="..\..\..\src\Shared\Knot.Shared.Kernel\Knot.Shared.Kernel.csproj" />
|
||||
<ProjectReference Include="..\..\..\src\Shared\Knot.Shared.Infrastructure\Knot.Shared.Infrastructure.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,30 @@
|
||||
<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" />
|
||||
<ProjectReference Include="..\..\..\src\Modules\Settings\Knot.Modules.Settings.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Shared\IntegrationTests.Shared\Knot.IntegrationTests.Shared.csproj" />
|
||||
<ProjectReference Include="..\..\..\src\Modules\Stories\Knot.Modules.Stories.csproj" />
|
||||
<ProjectReference Include="..\..\..\src\Shared\Knot.Shared.Kernel\Knot.Shared.Kernel.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="Xunit" />
|
||||
<ProjectReference Include="..\..\..\src\Modules\Settings\Knot.Modules.Settings.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
using Knot.IntegrationTests;
|
||||
using FluentAssertions;
|
||||
using Knot.Modules.Stories.Application.Stories.Commands.CreateStory;
|
||||
using Knot.Shared.Kernel;
|
||||
using Microsoft.AspNetCore.TestHost;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using NSubstitute;
|
||||
using System.Net;
|
||||
using System.Net.Http.Json;
|
||||
using Xunit;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Knot.IntegrationTests.Stories;
|
||||
|
||||
public class StoriesTests : BaseIntegrationTest
|
||||
{
|
||||
[Fact]
|
||||
public async Task CreateStory_ShouldReturnOk_WhenValidRequest()
|
||||
{
|
||||
// Arrange
|
||||
var request = new CreateStoryRequest("Text", null, "Hello Integration Test", null);
|
||||
|
||||
// Act
|
||||
var response = await _client.PostAsJsonAsync("api/stories", request);
|
||||
|
||||
// Assert
|
||||
response.StatusCode.Should().Be(HttpStatusCode.OK);
|
||||
|
||||
var content = await response.Content.ReadFromJsonAsync<dynamic>();
|
||||
}
|
||||
}
|
||||
|
||||
public record CreateStoryRequest(string Type, string? MediaUrl, string? Content, string? BgColor);
|
||||
@@ -0,0 +1,76 @@
|
||||
using FluentAssertions;
|
||||
using Knot.Modules.Stories.Application.Stories.Commands.CreateStory;
|
||||
using Knot.Modules.Stories.Domain;
|
||||
using Knot.Shared.Kernel;
|
||||
using Knot.Modules.Settings.Application.Settings.Abstractions;
|
||||
using Knot.Modules.Settings.Application.Settings.DTOs;
|
||||
using Knot.Modules.Stories.Application.Abstractions;
|
||||
using NSubstitute;
|
||||
using Xunit;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Knot.Modules.Stories.UnitTests;
|
||||
|
||||
public class CreateStoryCommandHandlerTests
|
||||
{
|
||||
private readonly IStoryRepository _storyRepository;
|
||||
private readonly ISettingsService _settingsService;
|
||||
private readonly CreateStoryCommandHandler _handler;
|
||||
|
||||
public CreateStoryCommandHandlerTests()
|
||||
{
|
||||
_storyRepository = Substitute.For<IStoryRepository>();
|
||||
_settingsService = Substitute.For<ISettingsService>();
|
||||
_handler = new CreateStoryCommandHandler(_storyRepository, _settingsService);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_ShouldSucceed_WhenValidRequest()
|
||||
{
|
||||
// Arrange
|
||||
var command = new CreateStoryCommand(Guid.NewGuid(), "Text", null, "Hello Story", null);
|
||||
|
||||
// Act
|
||||
var result = await _handler.Handle(command, CancellationToken.None);
|
||||
|
||||
// Assert
|
||||
result.IsSuccess.Should().BeTrue();
|
||||
await _storyRepository.Received(1).AddAsync(Arg.Any<Story>(), Arg.Any<CancellationToken>());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_ShouldFail_WhenKlipyDisabledAndKlipyType()
|
||||
{
|
||||
// Arrange
|
||||
var command = new CreateStoryCommand(Guid.NewGuid(), "Klipy", "http://klipy.com/gif", null, null);
|
||||
var settings = new SystemSettingsDto { Klipy = new KlipyConfig { Enabled = false } };
|
||||
_settingsService.GetSettingsAsync(Arg.Any<CancellationToken>()).Returns(settings);
|
||||
|
||||
// Act
|
||||
var result = await _handler.Handle(command, CancellationToken.None);
|
||||
|
||||
// Assert
|
||||
result.IsFailure.Should().BeTrue();
|
||||
result.Error.Code.Should().Be("Stories.KlipyDisabled");
|
||||
await _storyRepository.DidNotReceive().AddAsync(Arg.Any<Story>(), Arg.Any<CancellationToken>());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_ShouldSucceed_WhenKlipyEnabledAndKlipyType()
|
||||
{
|
||||
// Arrange
|
||||
var command = new CreateStoryCommand(Guid.NewGuid(), "Klipy", "http://klipy.com/gif", null, null);
|
||||
var settings = new SystemSettingsDto { Klipy = new KlipyConfig { Enabled = true } };
|
||||
_settingsService.GetSettingsAsync(Arg.Any<CancellationToken>()).Returns(settings);
|
||||
|
||||
// Act
|
||||
var result = await _handler.Handle(command, CancellationToken.None);
|
||||
|
||||
// Assert
|
||||
result.IsSuccess.Should().BeTrue();
|
||||
await _storyRepository.Received(1).AddAsync(Arg.Any<Story>(), Arg.Any<CancellationToken>());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
using FluentAssertions;
|
||||
using Knot.Modules.Stories.Application.Stories.Commands.DeleteStory;
|
||||
using Knot.Modules.Stories.Domain;
|
||||
using Knot.Shared.Kernel;
|
||||
using Knot.Modules.Stories.Application.Abstractions;
|
||||
using NSubstitute;
|
||||
using Xunit;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Knot.Modules.Stories.UnitTests;
|
||||
|
||||
public class DeleteStoryCommandHandlerTests
|
||||
{
|
||||
private readonly IStoryRepository _storyRepository;
|
||||
private readonly DeleteStoryCommandHandler _handler;
|
||||
|
||||
public DeleteStoryCommandHandlerTests()
|
||||
{
|
||||
_storyRepository = Substitute.For<IStoryRepository>();
|
||||
_handler = new DeleteStoryCommandHandler(_storyRepository);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_ShouldReturnError_WhenStoryNotFound()
|
||||
{
|
||||
// Arrange
|
||||
var command = new DeleteStoryCommand(Guid.NewGuid(), Guid.NewGuid());
|
||||
_storyRepository.GetByIdAsync(command.StoryId, Arg.Any<CancellationToken>()).Returns((Story?)null);
|
||||
|
||||
// Act
|
||||
var result = await _handler.Handle(command, CancellationToken.None);
|
||||
|
||||
// Assert
|
||||
result.IsFailure.Should().BeTrue();
|
||||
result.Error.Should().Be(StoryErrors.StoryNotFound);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_ShouldReturnError_WhenUserIsNotOwner()
|
||||
{
|
||||
// Arrange
|
||||
var ownerId = Guid.NewGuid();
|
||||
var viewerId = Guid.NewGuid();
|
||||
var story = Story.Create(ownerId, StoryType.Text, null, "Content", null);
|
||||
var command = new DeleteStoryCommand(viewerId, story.Id);
|
||||
|
||||
_storyRepository.GetByIdAsync(command.StoryId, Arg.Any<CancellationToken>()).Returns(story);
|
||||
|
||||
// Act
|
||||
var result = await _handler.Handle(command, CancellationToken.None);
|
||||
|
||||
// Assert
|
||||
result.IsFailure.Should().BeTrue();
|
||||
result.Error.Should().Be(StoryErrors.Unauthorized);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_ShouldSucceed_WhenOwnerDeletes()
|
||||
{
|
||||
// Arrange
|
||||
var ownerId = Guid.NewGuid();
|
||||
var story = Story.Create(ownerId, StoryType.Text, null, "Content", null);
|
||||
var command = new DeleteStoryCommand(ownerId, story.Id);
|
||||
|
||||
_storyRepository.GetByIdAsync(command.StoryId, Arg.Any<CancellationToken>()).Returns(story);
|
||||
|
||||
// Act
|
||||
var result = await _handler.Handle(command, CancellationToken.None);
|
||||
|
||||
// Assert
|
||||
result.IsSuccess.Should().BeTrue();
|
||||
await _storyRepository.Received(1).DeleteAsync(story, Arg.Any<CancellationToken>());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<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" />
|
||||
<ProjectReference Include="..\..\..\src\Modules\Settings\Knot.Modules.Settings.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
<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" />
|
||||
<ProjectReference Include="..\..\..\src\Modules\Settings\Knot.Modules.Settings.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
<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" />
|
||||
<PackageReference Include="FluentAssertions" Version="7.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\src\Modules\Profiles\Knot.Modules.Profiles.csproj" />
|
||||
<ProjectReference Include="..\..\..\src\Shared\Knot.Shared.Kernel\Knot.Shared.Kernel.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="Xunit" />
|
||||
<ProjectReference Include="..\..\..\src\Modules\Settings\Knot.Modules.Settings.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
using FluentAssertions;
|
||||
using Knot.Modules.Profiles.Application.Profiles.UpdateProfile;
|
||||
using Knot.Modules.Profiles.Domain;
|
||||
using Knot.Shared.Kernel;
|
||||
using NSubstitute;
|
||||
using Xunit;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Knot.Modules.Profiles.Application.Abstractions;
|
||||
|
||||
namespace Knot.Modules.Profiles.UnitTests;
|
||||
|
||||
public class UpdateProfileCommandHandlerTests
|
||||
{
|
||||
private readonly IProfileRepository _profileRepository;
|
||||
private readonly UpdateProfileCommandHandler _handler;
|
||||
|
||||
public UpdateProfileCommandHandlerTests()
|
||||
{
|
||||
_profileRepository = Substitute.For<IProfileRepository>();
|
||||
_handler = new UpdateProfileCommandHandler(_profileRepository);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_ShouldReturnError_WhenProfileNotFound()
|
||||
{
|
||||
// Arrange
|
||||
var command = new UpdateProfileCommand(Guid.NewGuid(), "FirstName", "Bio", null);
|
||||
_profileRepository.GetByIdAsync(command.UserId, Arg.Any<CancellationToken>()).Returns((ProfileDocument?)null);
|
||||
|
||||
// Act
|
||||
var result = await _handler.Handle(command, CancellationToken.None);
|
||||
|
||||
// Assert
|
||||
result.IsFailure.Should().BeTrue();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<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" />
|
||||
<ProjectReference Include="..\..\..\src\Modules\Settings\Knot.Modules.Settings.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
namespace Knot.Contracts.Admin.Abstractions;
|
||||
|
||||
/// <summary>
|
||||
/// Базовый класс для агрегатов - сущностей с бизнес-логикой и доменными событиями.
|
||||
/// </summary>
|
||||
public abstract class AggregateRoot<TId> : Entity<TId> where TId : notnull
|
||||
{
|
||||
private readonly List<IDomainEvent> _domainEvents = new();
|
||||
public IReadOnlyList<IDomainEvent> DomainEvents => _domainEvents.AsReadOnly();
|
||||
|
||||
protected AggregateRoot(TId id) : base(id) { }
|
||||
|
||||
protected void RaiseDomainEvent(IDomainEvent domainEvent)
|
||||
{
|
||||
_domainEvents.Add(domainEvent);
|
||||
}
|
||||
|
||||
public void ClearDomainEvents()
|
||||
{
|
||||
_domainEvents.Clear();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
namespace Knot.Contracts.Admin.Abstractions;
|
||||
|
||||
/// <summary>
|
||||
/// Базовый класс для сущностей с уникальным идентификатором.
|
||||
/// </summary>
|
||||
public abstract class Entity<TId> where TId : notnull
|
||||
{
|
||||
public TId Id { get; protected set; }
|
||||
|
||||
protected Entity(TId id)
|
||||
{
|
||||
Id = id;
|
||||
}
|
||||
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
if (obj is not Entity<TId> other)
|
||||
return false;
|
||||
|
||||
if (ReferenceEquals(this, other))
|
||||
return true;
|
||||
|
||||
if (GetType() != other.GetType())
|
||||
return false;
|
||||
|
||||
return Id.Equals(other.Id);
|
||||
}
|
||||
|
||||
public override int GetHashCode() => Id.GetHashCode();
|
||||
|
||||
public static bool operator ==(Entity<TId>? a, Entity<TId>? b)
|
||||
{
|
||||
if (a is null && b is null)
|
||||
return true;
|
||||
|
||||
if (a is null || b is null)
|
||||
return false;
|
||||
|
||||
return a.Equals(b);
|
||||
}
|
||||
|
||||
public static bool operator !=(Entity<TId>? a, Entity<TId>? b) => !(a == b);
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using MediatR;
|
||||
|
||||
namespace Knot.Contracts.Admin.Abstractions;
|
||||
|
||||
public interface ICommand : IRequest<Result> { }
|
||||
|
||||
public interface ICommand<TResponse> : IRequest<Result<TResponse>> { }
|
||||
|
||||
public interface ICommandHandler<in TCommand> : IRequestHandler<TCommand, Result>
|
||||
where TCommand : ICommand
|
||||
{ }
|
||||
|
||||
public interface ICommandHandler<in TCommand, TResponse> : IRequestHandler<TCommand, Result<TResponse>>
|
||||
where TCommand : ICommand<TResponse>
|
||||
{ }
|
||||
@@ -0,0 +1,8 @@
|
||||
using MediatR;
|
||||
|
||||
namespace Knot.Contracts.Admin.Abstractions;
|
||||
|
||||
/// <summary>
|
||||
/// Интерфейс для доменных событий.
|
||||
/// </summary>
|
||||
public interface IDomainEvent : INotification { }
|
||||
@@ -0,0 +1,13 @@
|
||||
using MediatR;
|
||||
|
||||
namespace Knot.Contracts.Admin.Abstractions;
|
||||
|
||||
public interface IQuery<TResponse> : IRequest<Result<TResponse>>
|
||||
{
|
||||
}
|
||||
|
||||
public interface IQueryHandler<TQuery, TResponse>
|
||||
: IRequestHandler<TQuery, Result<TResponse>>
|
||||
where TQuery : IQuery<TResponse>
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace Knot.Contracts.Admin.Abstractions;
|
||||
|
||||
public record MessageResponse(string Message);
|
||||
@@ -0,0 +1,63 @@
|
||||
namespace Knot.Contracts.Admin.Abstractions;
|
||||
|
||||
/// <summary>
|
||||
/// Представляет ошибку в доменной логике.
|
||||
/// </summary>
|
||||
public sealed record Error(string Code, string Description)
|
||||
{
|
||||
public static readonly Error None = new(string.Empty, string.Empty);
|
||||
public static Error NotFound(string code, string description) => new(code, description);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Общая обертка для результата операции. Позволяет избегать использования исключений для управления потоком.
|
||||
/// </summary>
|
||||
public class Result
|
||||
{
|
||||
public bool IsSuccess { get; }
|
||||
public bool IsFailure => !IsSuccess;
|
||||
public Error Error { get; }
|
||||
|
||||
protected Result(bool isSuccess, Error error)
|
||||
{
|
||||
if (isSuccess && error != Error.None)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
if (!isSuccess && error == Error.None)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
IsSuccess = isSuccess;
|
||||
Error = error;
|
||||
}
|
||||
|
||||
public static Result Success() => new(true, Error.None);
|
||||
public static Result Failure(Error error) => new(false, error);
|
||||
|
||||
public static Result<TValue> Success<TValue>(TValue value) => Result<TValue>.Success(value);
|
||||
public static Result<TValue> Failure<TValue>(Error error) => Result<TValue>.Failure(error);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Результ операции, содержащий значение.
|
||||
/// </summary>
|
||||
public class Result<TValue> : Result
|
||||
{
|
||||
private readonly TValue? _value;
|
||||
|
||||
protected internal Result(TValue? value, bool isSuccess, Error error)
|
||||
: base(isSuccess, error)
|
||||
{
|
||||
_value = value;
|
||||
}
|
||||
|
||||
public TValue Value => IsSuccess
|
||||
? _value!
|
||||
: throw new InvalidOperationException("Нельзя получить значение ошибочного результата.");
|
||||
|
||||
public static Result<TValue> Success(TValue value) => new(value, true, Error.None);
|
||||
public new static Result<TValue> Failure(Error error) => new(default, false, error);
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace Knot.Contracts.Admin.Abstractions;
|
||||
|
||||
public record SuccessResponse(bool Success);
|
||||
@@ -0,0 +1,14 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MediatR" Version="12.0.1" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="10.0.4" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Knot.Contracts.Auth.Abstractions;
|
||||
|
||||
public interface IUserQueryService
|
||||
{
|
||||
Task<List<UserInfo>> GetAllUsersAsync(CancellationToken cancellationToken);
|
||||
Task<List<UserInfo>> SearchUsersAsync(string query, CancellationToken cancellationToken);
|
||||
}
|
||||
|
||||
public record UserInfo(Guid Id, string? Avatar, string? UserName, string? DisplayName, DateTime CreatedAt, string? PhoneNumber, string? Email);
|
||||
@@ -0,0 +1,7 @@
|
||||
using Knot.Shared.Kernel;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Knot.Contracts.Auth.Application.Abstractions;
|
||||
|
||||
public record GetUsersExistenceQuery(List<Guid> UserIds) : IQuery<List<Guid>>;
|
||||
@@ -0,0 +1,10 @@
|
||||
using Knot.Contracts.Auth.Domain;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Knot.Contracts.Auth.Application.Abstractions;
|
||||
|
||||
public interface IAuthDbContext
|
||||
{
|
||||
DbSet<T> Set<T>() where T : class;
|
||||
Task<int> SaveChangesAsync(CancellationToken cancellationToken = default);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
using Knot.Contracts.Auth.Domain;
|
||||
using Knot.Shared.Kernel;
|
||||
|
||||
namespace Knot.Contracts.Auth.Application.Abstractions;
|
||||
|
||||
public interface IAuthUnitOfWork : IUnitOfWork
|
||||
{
|
||||
IUserRepository UserRepository { get; }
|
||||
void Add(UserContract user);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace Knot.Contracts.Auth.Application.Abstractions;
|
||||
|
||||
public interface IJwtTokenProvider
|
||||
{
|
||||
string GenerateAccessToken(Guid userId, string username);
|
||||
string GenerateRefreshToken();
|
||||
string Generate(Guid userId, string username, string displayName, string? avatar);
|
||||
string Generate(Domain.UserContract user);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
using Knot.Shared.Kernel;
|
||||
|
||||
namespace Knot.Contracts.Auth.Application.Auth.DTOs;
|
||||
|
||||
public static class AuthErrors
|
||||
{
|
||||
public static Error IdentityInvalidCredentials => new("Auth.InvalidCredentials", "Invalid credentials");
|
||||
public static Error IdentityRegistrationDisabled => new("Auth.RegistrationDisabled", "Registration is disabled");
|
||||
public static Error IdentityUsernameNotUnique => new("Auth.UsernameNotUnique", "Username is already taken");
|
||||
public static Error UserNotFound => new("Auth.UserNotFound", "User not found");
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
namespace Knot.Contracts.Auth.Application.Auth.DTOs;
|
||||
|
||||
public class AuthResponseDto
|
||||
{
|
||||
public required string AccessToken { get; set; }
|
||||
public required string RefreshToken { get; set; }
|
||||
public Guid UserId { get; set; }
|
||||
public string Username { get; set; } = string.Empty;
|
||||
public string? DisplayName { get; set; }
|
||||
public string? Avatar { get; set; }
|
||||
}
|
||||
|
||||
public class ResetPasswordDto
|
||||
{
|
||||
public required string Token { get; set; }
|
||||
public required string NewPassword { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
namespace Knot.Contracts.Auth.Domain;
|
||||
|
||||
public interface IUserRepository
|
||||
{
|
||||
Task<UserContract?> GetByIdAsync(Guid id, CancellationToken cancellationToken = default);
|
||||
Task<List<UserContract>> GetByIdsAsync(IEnumerable<Guid> ids, CancellationToken cancellationToken = default);
|
||||
Task<UserContract?> GetByUsernameAsync(string username, CancellationToken cancellationToken = default);
|
||||
Task<bool> IsUsernameUniqueAsync(string username, CancellationToken cancellationToken = default);
|
||||
Task<List<UserContract>> SearchUsersAsync(string query, CancellationToken cancellationToken = default);
|
||||
Task<bool> IsBannedAsync(Guid userId, CancellationToken cancellationToken = default);
|
||||
Task<UserContract?> GetByRefreshTokenAsync(string refreshToken, CancellationToken cancellationToken = default);
|
||||
Task UpdateAsync(UserContract user, CancellationToken cancellationToken = default);
|
||||
void Add(UserContract user);
|
||||
Task RemoveAsync(UserContract user, CancellationToken cancellationToken = default);
|
||||
void Update(UserContract user);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
namespace Knot.Contracts.Auth.Domain;
|
||||
|
||||
public class UserContract
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string Username { get; set; } = string.Empty;
|
||||
public string DisplayName { get; set; } = string.Empty;
|
||||
public string PasswordHash { get; set; } = string.Empty;
|
||||
public string? PhoneNumber { get; set; }
|
||||
public string? Email { get; set; }
|
||||
public string? Bio { get; set; }
|
||||
public string? Avatar { get; set; }
|
||||
public DateTime? Birthday { get; set; }
|
||||
public bool IsBot { get; set; }
|
||||
public DateTime CreatedAt { get; set; }
|
||||
public DateTime? BannedUntil { get; set; }
|
||||
public bool IsBanned { get; set; }
|
||||
public bool IsOnline { get; set; }
|
||||
public bool IsExternal { get; set; }
|
||||
public string? Domain { get; set; }
|
||||
public DateTime? LastSeen { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
using Knot.Shared.Kernel;
|
||||
|
||||
namespace Knot.Contracts.Auth.Domain;
|
||||
|
||||
/// <summary>
|
||||
/// Доменное событие: изменился статус пользователя (онлайн/офлайн).
|
||||
/// </summary>
|
||||
public sealed record UserStatusChangedDomainEvent(Guid UserId, bool IsOnline, DateTime LastSeen) : IDomainEvent;
|
||||
@@ -0,0 +1,13 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Knot.Contracts.Auth.Domain;
|
||||
|
||||
namespace Knot.Contracts.Auth.Infrastructure.Persistence;
|
||||
|
||||
public interface IAuthDbContext
|
||||
{
|
||||
IQueryable<UserContract> Users { get; }
|
||||
Task<int> SaveChangesAsync(CancellationToken cancellationToken = default);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<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" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MediatR" Version="12.0.1" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="10.0.4" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Knot.Contracts.Cleanup.Abstractions;
|
||||
|
||||
public interface ICleanupService
|
||||
{
|
||||
Task<CleanupData> GetCleanupDataAsync(CancellationToken cancellationToken);
|
||||
Task CleanOrphanMessagesAsync(List<Guid> messageIds, CancellationToken cancellationToken);
|
||||
Task CleanOrphanFilesAsync(List<string> fileIds, CancellationToken cancellationToken);
|
||||
}
|
||||
|
||||
public record CleanupData(
|
||||
List<ChatCleanupInfo> Chats,
|
||||
List<MessageCleanupInfo> Messages,
|
||||
List<StoryCleanupInfo> Stories,
|
||||
List<UserCleanupInfo> Users,
|
||||
List<FileCleanupInfo> Files);
|
||||
|
||||
public record ChatCleanupInfo(Guid Id, string? Avatar);
|
||||
|
||||
public record MessageCleanupInfo(Guid Id, Guid ChatId, bool IsDeleted, string? MediaUrl);
|
||||
|
||||
public record StoryCleanupInfo(Guid Id, string? MediaUrl);
|
||||
|
||||
public record UserCleanupInfo(Guid Id, string? Avatar);
|
||||
|
||||
public record FileCleanupInfo(string FileId);
|
||||
@@ -0,0 +1,10 @@
|
||||
<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" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Knot.Contracts.Conversations.Abstractions;
|
||||
|
||||
public interface IChatQueryService
|
||||
{
|
||||
Task<List<ChatInfo>> GetAllChatsAsync(CancellationToken cancellationToken);
|
||||
}
|
||||
|
||||
public record ChatInfo(Guid Id, string? Avatar);
|
||||
@@ -0,0 +1,11 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Knot.Shared.Kernel;
|
||||
|
||||
namespace Knot.Contracts.Conversations.Abstractions;
|
||||
|
||||
public interface IUserDeleterService
|
||||
{
|
||||
Task<Result> DeleteUserAsync(Guid userId, CancellationToken cancellationToken);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Knot.Contracts.Conversations.Abstractions;
|
||||
|
||||
public interface IUserStatusService
|
||||
{
|
||||
bool IsUserOnline(string userId);
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
using Knot.Shared.Kernel;
|
||||
|
||||
namespace Knot.Contracts.Conversations.Application.Abstractions;
|
||||
|
||||
public interface IChatsUnitOfWork : IUnitOfWork
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
|
||||
namespace Knot.Contracts.Conversations.Application.Abstractions;
|
||||
|
||||
public interface IStoryNotificationsClient
|
||||
{
|
||||
Task StoryViewed(Guid storyId, Guid userId);
|
||||
Task StoryReactionAdded(Guid storyId, Guid userId, string reaction);
|
||||
Task StoryReactionRemoved(Guid storyId, Guid userId);
|
||||
}
|
||||
|
||||
public interface IChatHubClient
|
||||
{
|
||||
Task MessageReceived(object message);
|
||||
Task MessageDeleted(Guid messageId);
|
||||
Task MessageEdited(Guid messageId, object newContent);
|
||||
Task ReactionAdded(Guid messageId, string reaction, Guid userId);
|
||||
Task ReactionRemoved(Guid messageId, string reaction, Guid userId);
|
||||
Task UserStatusChanged(Guid userId, bool isOnline);
|
||||
Task ChatUpdated(object chat);
|
||||
Task ChatDeleted(Guid chatId);
|
||||
Task UserJoinedChat(Guid chatId, Guid userId);
|
||||
Task UserLeftChat(Guid chatId, Guid userId);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
using System;
|
||||
|
||||
namespace Knot.Contracts.Conversations.Application.Abstractions;
|
||||
|
||||
public interface IUserStatusService
|
||||
{
|
||||
bool IsUserOnline(string userId);
|
||||
}
|
||||
+37
-14
@@ -1,6 +1,6 @@
|
||||
using Knot.Shared.Kernel;
|
||||
|
||||
namespace Knot.Modules.Chats.Domain;
|
||||
namespace Knot.Contracts.Conversations.Domain;
|
||||
|
||||
public sealed record ChatCreatedDomainEvent(Chat Chat) : IDomainEvent;
|
||||
public sealed record ChatMemberAddedDomainEvent(Guid ChatId, Guid UserId) : IDomainEvent;
|
||||
@@ -35,22 +35,24 @@ public sealed class Chat : AggregateRoot<Guid>
|
||||
public string? Description { get; private set; }
|
||||
public string? Avatar { get; private set; }
|
||||
public DateTime CreatedAt { get; private set; }
|
||||
public long LastMessageSequenceId { get; private set; }
|
||||
public bool IsImporting { get; private set; }
|
||||
public Guid? ImportJobId { get; private set; }
|
||||
|
||||
private readonly List<ChatMember> _members = new();
|
||||
public IReadOnlyCollection<ChatMember> Members => _members.AsReadOnly();
|
||||
|
||||
private Chat(Guid id, ChatType type, string? name, string? avatar, string? description = null) : base(id)
|
||||
private Chat(Guid id, ChatType type, string? name, string? avatar, string? description = null, bool isImporting = false, Guid? importJobId = null) : base(id)
|
||||
{
|
||||
Type = type;
|
||||
Name = name;
|
||||
Avatar = avatar;
|
||||
Description = description;
|
||||
CreatedAt = DateTime.UtcNow;
|
||||
IsImporting = isImporting;
|
||||
ImportJobId = importJobId;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Создает личный чат между двумя пользователями.
|
||||
/// </summary>
|
||||
public static Chat CreatePersonal()
|
||||
{
|
||||
var chat = new Chat(Guid.NewGuid(), ChatType.Personal, null, null);
|
||||
@@ -58,9 +60,6 @@ public sealed class Chat : AggregateRoot<Guid>
|
||||
return chat;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Создает групповой чат.
|
||||
/// </summary>
|
||||
public static Chat CreateGroup(string name, string? avatar = null)
|
||||
{
|
||||
var chat = new Chat(Guid.NewGuid(), ChatType.Group, name, avatar);
|
||||
@@ -68,16 +67,18 @@ public sealed class Chat : AggregateRoot<Guid>
|
||||
return chat;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Фабричный метод для создания чата.
|
||||
/// </summary>
|
||||
public static Chat Create(string? name, ChatType type, string? avatar = null, string? description = null)
|
||||
public static Chat Create(string? name, ChatType type, string? avatar = null, string? description = null, bool isImporting = false, Guid? importJobId = null)
|
||||
{
|
||||
var chat = new Chat(Guid.NewGuid(), type, name, avatar, description);
|
||||
var chat = new Chat(Guid.NewGuid(), type, name, avatar, description, isImporting, importJobId);
|
||||
chat.RaiseDomainEvent(new ChatCreatedDomainEvent(chat));
|
||||
return chat;
|
||||
}
|
||||
|
||||
public void CompleteImport()
|
||||
{
|
||||
IsImporting = false;
|
||||
}
|
||||
|
||||
public void AddMember(Guid userId, string role = "member")
|
||||
{
|
||||
if (_members.Any(m => m.UserId == userId))
|
||||
@@ -103,6 +104,11 @@ public sealed class Chat : AggregateRoot<Guid>
|
||||
public void UpdateDescription(string? description) => Description = description;
|
||||
|
||||
public void UpdateAvatar(string? avatarUrl) => Avatar = avatarUrl;
|
||||
|
||||
public long IncrementSequenceId()
|
||||
{
|
||||
return ++LastMessageSequenceId;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -117,7 +123,10 @@ public sealed class ChatMember : Entity<Guid>
|
||||
public bool IsPinned { get; private set; }
|
||||
public bool IsMuted { get; private set; }
|
||||
|
||||
// For EF Core
|
||||
public Guid? LastReadMessageId { get; private set; }
|
||||
public long LastReadSequenceId { get; private set; }
|
||||
public Guid? LastDeliveredMessageId { get; private set; }
|
||||
|
||||
private ChatMember() : base(Guid.Empty) { Role = "member"; }
|
||||
|
||||
internal ChatMember(Guid chatId, Guid userId, string role) : base(Guid.NewGuid())
|
||||
@@ -129,4 +138,18 @@ public sealed class ChatMember : Entity<Guid>
|
||||
}
|
||||
|
||||
public void TogglePin() => IsPinned = !IsPinned;
|
||||
|
||||
public void UpdateReadCursor(Guid messageId, long sequenceId)
|
||||
{
|
||||
if (sequenceId > LastReadSequenceId)
|
||||
{
|
||||
LastReadMessageId = messageId;
|
||||
LastReadSequenceId = sequenceId;
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateDeliveredCursor(Guid messageId)
|
||||
{
|
||||
LastDeliveredMessageId = messageId;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace Knot.Contracts.Conversations.Domain;
|
||||
|
||||
public static class ChatConstants
|
||||
{
|
||||
public const int DefaultMessageQueryLimit = 50;
|
||||
public const int MaxSharedMediaQueryLimit = 1000;
|
||||
public const int MaxGroupNameLength = 100;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using Knot.Shared.Kernel;
|
||||
|
||||
namespace Knot.Contracts.Conversations.Domain;
|
||||
|
||||
public static class ChatErrors
|
||||
{
|
||||
public static readonly Error ChatNotFound = new Error("Chat.NotFound", "Чат не найден");
|
||||
public static readonly Error OnlyOwnerCanUpdate = new Error("Chat.OnlyOwnerCanUpdate", "Только владелец может редактировать чат");
|
||||
public static readonly Error Unauthorized = new Error("Chat.Unauthorized", "Нет доступа к этому чату");
|
||||
public static readonly Error FoldersDisabled = new Error("Chat.FoldersDisabled", "Папки отключены");
|
||||
public static readonly Error FileEmpty = new Error("Chat.FileEmpty", "Файл пуст");
|
||||
public static Error FileTooLarge(long maxMb) => new Error("Chat.FileTooLarge", $"Файл слишком большой (максимум {maxMb} МБ)");
|
||||
public static readonly Error ChatsNotFound = new Error("Chat.NotFound", "Чат не найден");
|
||||
public static readonly Error ChatsForbidden = new Error("Chat.Forbidden", "Доступ запрещен");
|
||||
public static readonly Error MediaDisabled = new Error("Chat.MediaDisabled", "Медиафайлы отключены");
|
||||
public static readonly Error PollsDisabled = new Error("Chat.PollsDisabled", "Опросы отключены");
|
||||
public static readonly Error NotFound = new Error("Chat.NotFound", "Не найдено");
|
||||
public static readonly Error NotMember = new Error("Chat.NotMember", "Вы не являетесь участником чата");
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Knot.Shared.Kernel;
|
||||
|
||||
namespace Knot.Contracts.Conversations.Domain;
|
||||
|
||||
/// <summary>
|
||||
/// Сущность папки для группировки чатов.
|
||||
/// </summary>
|
||||
public sealed class Folder : AggregateRoot<Guid>
|
||||
{
|
||||
public string Name { get; private set; }
|
||||
public string? Icon { get; private set; }
|
||||
public bool IsDefault { get; private set; }
|
||||
public FolderType Type { get; private set; }
|
||||
|
||||
public Folder(Guid id, string name, string? icon = null, bool isDefault = false, FolderType type = FolderType.Custom)
|
||||
: base(id)
|
||||
{
|
||||
Name = name;
|
||||
Icon = icon;
|
||||
IsDefault = isDefault;
|
||||
Type = type;
|
||||
}
|
||||
|
||||
public void Update(string name, string? icon)
|
||||
{
|
||||
if (IsDefault) throw new InvalidOperationException("Cannot rename default folders.");
|
||||
Name = name;
|
||||
Icon = icon;
|
||||
}
|
||||
}
|
||||
|
||||
public enum FolderType
|
||||
{
|
||||
All,
|
||||
New,
|
||||
Muted,
|
||||
Custom
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Настройки конкретного чата для конкретного пользователя.
|
||||
/// </summary>
|
||||
public sealed class UserChatSettings : Entity<Guid>
|
||||
{
|
||||
public Guid UserId { get; private set; }
|
||||
public Guid ChatId { get; private set; }
|
||||
|
||||
private readonly List<Guid> _folderIds = new();
|
||||
public IReadOnlyCollection<Guid> FolderIds => _folderIds.AsReadOnly();
|
||||
|
||||
public bool IsMuted { get; private set; }
|
||||
|
||||
private UserChatSettings() : base(Guid.NewGuid()) { }
|
||||
|
||||
public UserChatSettings(Guid userId, Guid chatId) : base(Guid.NewGuid())
|
||||
{
|
||||
UserId = userId;
|
||||
ChatId = chatId;
|
||||
}
|
||||
|
||||
public static UserChatSettings Create(Guid userId, Guid chatId) => new(userId, chatId);
|
||||
|
||||
public void AddToFolder(Guid folderId)
|
||||
{
|
||||
if (!_folderIds.Contains(folderId)) _folderIds.Add(folderId);
|
||||
}
|
||||
|
||||
public void RemoveFromFolder(Guid folderId)
|
||||
{
|
||||
_folderIds.Remove(folderId);
|
||||
}
|
||||
|
||||
public void SetMute(bool isMuted) => IsMuted = isMuted;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Глобальные настройки папок пользователя.
|
||||
/// </summary>
|
||||
public sealed class UserFolderSettings : AggregateRoot<Guid>
|
||||
{
|
||||
public Guid UserId { get; private set; }
|
||||
public List<Guid> HiddenDefaultFolderIds { get; private set; } = new();
|
||||
public List<Guid> CustomFolderIds { get; private set; } = new();
|
||||
|
||||
public UserFolderSettings(Guid userId) : base(Guid.NewGuid())
|
||||
{
|
||||
UserId = userId;
|
||||
}
|
||||
|
||||
public void HideFolder(Guid folderId)
|
||||
{
|
||||
if (!HiddenDefaultFolderIds.Contains(folderId)) HiddenDefaultFolderIds.Add(folderId);
|
||||
}
|
||||
|
||||
public void ShowFolder(Guid folderId)
|
||||
{
|
||||
HiddenDefaultFolderIds.Remove(folderId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
using Knot.Contracts.Conversations.Domain;
|
||||
|
||||
namespace Knot.Contracts.Conversations.Domain;
|
||||
|
||||
public interface IChatRepository
|
||||
{
|
||||
void Add(Chat chat);
|
||||
void Update(Chat chat);
|
||||
void Remove(Chat chat);
|
||||
Task<Chat?> GetByIdAsync(Guid id, CancellationToken cancellationToken);
|
||||
Task<Chat?> GetFavoritesAsync(Guid userId, CancellationToken cancellationToken);
|
||||
Task<List<Chat>> GetUserChatsAsync(Guid userId, CancellationToken cancellationToken);
|
||||
}
|
||||
|
||||
public interface IFolderRepository
|
||||
{
|
||||
void Add(Folder folder);
|
||||
void Update(Folder folder);
|
||||
void Remove(Folder folder);
|
||||
Task<Folder?> GetByIdAsync(Guid id, CancellationToken cancellationToken);
|
||||
Task<List<Folder>> GetUserFoldersAsync(Guid userId, CancellationToken cancellationToken);
|
||||
}
|
||||
|
||||
public interface IUserChatSettingsRepository
|
||||
{
|
||||
void Add(UserChatSettings settings);
|
||||
void Update(UserChatSettings settings);
|
||||
void Remove(UserChatSettings settings);
|
||||
void RemoveRange(IEnumerable<UserChatSettings> settings);
|
||||
Task<UserChatSettings?> GetAsync(Guid userId, Guid chatId, CancellationToken cancellationToken);
|
||||
Task<List<UserChatSettings>> GetByUserIdAsync(Guid userId, CancellationToken cancellationToken);
|
||||
}
|
||||
|
||||
public interface IUserFolderSettingsRepository
|
||||
{
|
||||
Task<UserFolderSettings?> GetByUserIdAsync(Guid userId, CancellationToken cancellationToken);
|
||||
Task UpdateAsync(UserFolderSettings settings, CancellationToken cancellationToken);
|
||||
Task RemoveByUserIdAsync(Guid userId, CancellationToken cancellationToken);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using System.Linq;
|
||||
using Knot.Contracts.Conversations.Domain;
|
||||
|
||||
namespace Knot.Contracts.Conversations.Infrastructure.Persistence;
|
||||
|
||||
public interface IChatsDbContext
|
||||
{
|
||||
IQueryable<Chat> Chats { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Упрощенная проекция чата для запросов (не доменная сущность).
|
||||
/// </summary>
|
||||
public class Chat
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string? Avatar { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<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="..\Messaging\Knot.Contracts.Messaging.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MediatR" Version="12.0.1" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="10.0.4" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,18 @@
|
||||
<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" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MediatR" Version="12.0.1" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="10.0.4" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Knot.Contracts.Klipy.Abstractions;
|
||||
|
||||
public interface IKlipyClient
|
||||
{
|
||||
Task<bool> TestConnectionAsync(CancellationToken cancellationToken = default);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Knot.Contracts.Klipy.Application.Abstractions;
|
||||
|
||||
public interface IKlipyClient
|
||||
{
|
||||
Task<bool> TestConnectionAsync(string apiKey, string appName, CancellationToken cancellationToken = default);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<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" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MediatR" Version="12.0.1" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="10.0.4" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Knot.Contracts.Messaging.Abstractions;
|
||||
|
||||
public interface IMessageQueryService
|
||||
{
|
||||
Task<List<MessageInfo>> GetAllMessagesAsync(CancellationToken cancellationToken);
|
||||
Task DeleteMessagesAsync(List<Guid> messageIds, CancellationToken cancellationToken);
|
||||
}
|
||||
|
||||
public record MessageInfo(Guid Id, Guid ChatId, bool IsDeleted, string? MediaUrl);
|
||||
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Knot.Contracts.Messaging.Abstractions;
|
||||
|
||||
public interface IUserStatsService
|
||||
{
|
||||
Task<Dictionary<Guid, UserStats>> GetStatsForUsersAsync(List<Guid> userIds, CancellationToken cancellationToken = default);
|
||||
}
|
||||
|
||||
public record UserStats(int MessageCount, long StorageSize);
|
||||
@@ -0,0 +1,11 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Knot.Contracts.Messaging.Application.Abstractions;
|
||||
|
||||
public interface IChatAccessProvider
|
||||
{
|
||||
Task<List<Guid>> GetValidChatIdsForUserAsync(Guid userId, CancellationToken ct);
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace Knot.Contracts.Messaging.Application.Abstractions;
|
||||
|
||||
public interface IMessageNotifier
|
||||
{
|
||||
Task NotifyNewMessageAsync(Guid chatId, object messagePayload, CancellationToken cancellationToken);
|
||||
Task NotifyMessageUpdateAsync(Guid chatId, string updateType, object updatePayload, CancellationToken cancellationToken);
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Knot.Contracts.Messaging.Application.Abstractions;
|
||||
|
||||
public interface IMessageQueryService
|
||||
{
|
||||
Task<List<MessageInfo>> GetAllMessagesAsync(CancellationToken cancellationToken);
|
||||
Task<List<MessageInfo>> GetOrphanedMessagesAsync(HashSet<Guid> activeChatIds, CancellationToken cancellationToken);
|
||||
Task DeleteMessagesAsync(List<Guid> messageIds, CancellationToken cancellationToken);
|
||||
}
|
||||
|
||||
public record MessageInfo(Guid Id, Guid ChatId, bool IsDeleted, string? MediaUrl, List<MediaInfo>? Media);
|
||||
|
||||
public record MediaInfo(string Url);
|
||||
@@ -0,0 +1,24 @@
|
||||
using Knot.Contracts.Messaging.Domain;
|
||||
|
||||
namespace Knot.Contracts.Messaging.Application.Abstractions;
|
||||
|
||||
public interface IMessageRepository
|
||||
{
|
||||
void Add(Message message);
|
||||
Task<Message?> GetByIdAsync(Guid id, CancellationToken cancellationToken);
|
||||
Task<List<Message>> GetChatMessagesAsync(Guid chatId, int limit, int offset, CancellationToken cancellationToken);
|
||||
Task<Message?> GetLatestChatMessageAsync(Guid chatId, CancellationToken cancellationToken);
|
||||
Task<List<Message>> GetPinnedMessagesAsync(Guid chatId, CancellationToken cancellationToken);
|
||||
Task<List<Message>> SearchMessagesAsync(string query, Guid? chatId, Guid requestingUserId, CancellationToken cancellationToken);
|
||||
|
||||
Task<List<Message>> GetChatMessagesCursorAsync(Guid chatId, DateTime? cursor, long? sequenceId, int limit, CancellationToken cancellationToken);
|
||||
Task<List<Message>> GetChatMessagesAroundAsync(Guid chatId, long sequenceId, int limit, CancellationToken cancellationToken);
|
||||
Task<Message?> GetLastStoryMessageAsync(Guid chatId, Guid storyId, CancellationToken cancellationToken);
|
||||
|
||||
Task UpdateAsync(Message message, CancellationToken cancellationToken);
|
||||
Task<List<Message>> GetAllMessagesAsync(CancellationToken cancellationToken);
|
||||
Task DeleteChatMessagesAsync(Guid chatId, CancellationToken cancellationToken);
|
||||
Task DeleteUserMessagesAsync(Guid userId, CancellationToken cancellationToken);
|
||||
Task RemoveAsync(Guid id, CancellationToken cancellationToken);
|
||||
Task DeleteAsync(Message message, CancellationToken cancellationToken);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Knot.Contracts.Messaging.Application.Abstractions;
|
||||
|
||||
public interface IUserStatsService
|
||||
{
|
||||
Task<Dictionary<Guid, UserStats>> GetStatsForUsersAsync(List<Guid> userIds, CancellationToken cancellationToken = default);
|
||||
}
|
||||
|
||||
public record UserStats(int MessageCount, long StorageSize);
|
||||
@@ -0,0 +1,33 @@
|
||||
using System;
|
||||
|
||||
namespace Knot.Contracts.Messaging.Domain;
|
||||
|
||||
public class CallMessage : Message
|
||||
{
|
||||
public override string Type => "call";
|
||||
public override string? Content { get; protected set; }
|
||||
public string CallType { get; protected set; }
|
||||
public string CallStatus { get; protected set; }
|
||||
public int? Duration { get; protected set; }
|
||||
|
||||
public CallMessage() : base() { }
|
||||
|
||||
public CallMessage(
|
||||
Guid id,
|
||||
Guid chatId,
|
||||
Guid senderId,
|
||||
string callType,
|
||||
string callStatus,
|
||||
int? duration,
|
||||
Guid? replyToId,
|
||||
Guid? forwardedFromId,
|
||||
DateTime createdAt,
|
||||
bool isImported = false)
|
||||
: base(id, chatId, senderId, replyToId, forwardedFromId, createdAt, isImported)
|
||||
{
|
||||
CallType = callType;
|
||||
CallStatus = callStatus;
|
||||
Duration = duration;
|
||||
Content = $"Call {callStatus}";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
using Knot.Shared.Kernel;
|
||||
|
||||
namespace Knot.Contracts.Messaging.Domain;
|
||||
|
||||
/// <summary>
|
||||
/// Запись о том, что конкретный пользователь удалил у себя сообщение.
|
||||
/// </summary>
|
||||
public sealed class DeletedMessage : Entity<Guid>
|
||||
{
|
||||
public Guid MessageId { get; private set; }
|
||||
public Guid UserId { get; private set; }
|
||||
|
||||
internal DeletedMessage(Guid messageId, Guid userId) : base(Guid.NewGuid())
|
||||
{
|
||||
MessageId = messageId;
|
||||
UserId = userId;
|
||||
}
|
||||
|
||||
private DeletedMessage() : base(Guid.Empty) { }
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace Knot.Contracts.Messaging.Domain;
|
||||
|
||||
public interface IMessageReactionRepository
|
||||
{
|
||||
Task AddAsync(MessageReaction reaction, CancellationToken cancellationToken);
|
||||
Task RemoveAsync(Guid messageId, Guid userId, string emoji, CancellationToken cancellationToken);
|
||||
Task<List<MessageReaction>> GetReactionsForMessageAsync(Guid messageId, CancellationToken cancellationToken);
|
||||
Task<List<MessageReaction>> GetReactionsForMessagesAsync(IEnumerable<Guid> messageIds, CancellationToken cancellationToken);
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
|
||||
namespace Knot.Contracts.Messaging.Domain;
|
||||
|
||||
public class Media
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string Type { get; set; } = string.Empty;
|
||||
public string? Url { get; set; }
|
||||
public string? ThumbnailUrl { get; set; }
|
||||
public long? Size { get; set; }
|
||||
public int Width { get; set; }
|
||||
public int Height { get; set; }
|
||||
public string? FileId { get; set; }
|
||||
public string? Filename { get; set; }
|
||||
public string? Duration { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Knot.Contracts.Messaging.Domain;
|
||||
|
||||
public class MediaMessage : Message
|
||||
{
|
||||
public override string Type => MediaType.ToString().ToLower();
|
||||
public override string? Content { get; protected set; }
|
||||
public string? Caption { get => Content; private set => Content = value; }
|
||||
public MediaType MediaType { get; private set; }
|
||||
|
||||
private List<Media> _media = new();
|
||||
public IReadOnlyCollection<Media> Media => _media.AsReadOnly();
|
||||
|
||||
private MediaMessage() : base() { MediaType = MediaType.File; }
|
||||
|
||||
public MediaMessage(Guid id, Guid chatId, Guid senderId, MediaType mediaType, string? caption, Guid? replyToId, Guid? forwardedFromId, DateTime createdAt, bool isImported)
|
||||
: base(id, chatId, senderId, replyToId, forwardedFromId, createdAt, isImported) { MediaType = mediaType; Caption = caption; }
|
||||
|
||||
public MediaMessage(Guid id, Guid chatId, Guid senderId, string mediaType, string? caption, Guid? replyToId, Guid? forwardedFromId, DateTime createdAt, bool isImported)
|
||||
: this(id, chatId, senderId, Enum.TryParse<MediaType>(mediaType, true, out var mt) ? mt : MediaType.File, caption, replyToId, forwardedFromId, createdAt, isImported) { }
|
||||
|
||||
public void AddMedia(string type, string url, string? filename, long? size, string? duration = null) => _media.Add(new Media { Type = type, Url = url, Filename = filename, FileId = filename, Size = size, Duration = duration });
|
||||
|
||||
public override void Edit(string newCaption) => base.Edit(newCaption);
|
||||
|
||||
public override void Delete() { Caption = null; base.Delete(); }
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace Knot.Contracts.Messaging.Domain;
|
||||
|
||||
public enum MediaType
|
||||
{
|
||||
Image,
|
||||
Video,
|
||||
Voice,
|
||||
File
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Knot.Shared.Kernel;
|
||||
|
||||
namespace Knot.Contracts.Messaging.Domain;
|
||||
|
||||
public abstract class Message : AggregateRoot<Guid>
|
||||
{
|
||||
public Guid ChatId { get; protected set; }
|
||||
public Guid SenderId { get; protected set; }
|
||||
public DateTime CreatedAt { get; protected set; }
|
||||
public long SequenceId { get; protected set; }
|
||||
public void SetSequenceId(long sequenceId) => SequenceId = sequenceId;
|
||||
public Guid? ReplyToId { get; protected set; }
|
||||
public Guid? ForwardedFromId { get; protected set; }
|
||||
public MessageState State { get; protected set; }
|
||||
public abstract string Type { get; }
|
||||
public abstract string? Content { get; protected set; }
|
||||
|
||||
public bool IsEdited => HasState(MessageState.IsEdited);
|
||||
public bool IsDeleted => HasState(MessageState.IsDeleted);
|
||||
|
||||
protected List<DeletedMessage> _deletedFor = new();
|
||||
public IReadOnlyCollection<DeletedMessage> DeletedFor => _deletedFor.AsReadOnly();
|
||||
|
||||
protected Message() : base(Guid.Empty) { }
|
||||
|
||||
protected Message(Guid id, Guid chatId, Guid senderId, Guid? replyToId, Guid? forwardedFromId, DateTime createdAt, bool isImported)
|
||||
: base(id)
|
||||
{
|
||||
ChatId = chatId;
|
||||
SenderId = senderId;
|
||||
ReplyToId = replyToId;
|
||||
ForwardedFromId = forwardedFromId;
|
||||
CreatedAt = createdAt;
|
||||
if (isImported) AddState(MessageState.IsImported);
|
||||
}
|
||||
|
||||
public void AddState(MessageState state) => State |= state;
|
||||
public void RemoveState(MessageState state) => State &= ~state;
|
||||
public bool HasState(MessageState state) => (State & state) == state;
|
||||
public bool IsDeletedForUser(Guid userId) => _deletedFor.Exists(d => d.UserId == userId);
|
||||
|
||||
public virtual void Delete() => AddState(MessageState.IsDeleted);
|
||||
public virtual void Edit(string newContent)
|
||||
{
|
||||
Content = newContent;
|
||||
AddState(MessageState.IsEdited);
|
||||
}
|
||||
|
||||
public void DeleteForUser(Guid userId)
|
||||
{
|
||||
if (!_deletedFor.Exists(x => x.UserId == userId))
|
||||
_deletedFor.Add(new DeletedMessage(Id, userId));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using Knot.Shared.Kernel;
|
||||
|
||||
namespace Knot.Contracts.Messaging.Domain;
|
||||
|
||||
/// <summary>
|
||||
/// Доменное событие: сообщение отправлено.
|
||||
/// </summary>
|
||||
public sealed record MessageSentDomainEvent(Guid MessageId, Guid ChatId, Guid SenderId, string? Content) : IDomainEvent;
|
||||
|
||||
/// <summary>
|
||||
/// Доменное событие: сообщение удалено.
|
||||
/// </summary>
|
||||
public sealed record MessageDeletedDomainEvent(Guid MessageId, Guid ChatId) : IDomainEvent;
|
||||
|
||||
/// <summary>
|
||||
/// Доменное событие: сообщение отредактировано.
|
||||
/// </summary>
|
||||
public sealed record MessageEditedDomainEvent(Guid MessageId, Guid ChatId, string NewContent) : IDomainEvent;
|
||||
|
||||
/// <summary>
|
||||
/// Доменное событие: реакция добавлена.
|
||||
/// </summary>
|
||||
public sealed record MessageReactionAddedDomainEvent(Guid MessageId, Guid ChatId, Guid UserId, string Emoji) : IDomainEvent;
|
||||
|
||||
/// <summary>
|
||||
/// Доменное событие: реакция удалена.
|
||||
/// </summary>
|
||||
public sealed record MessageReactionRemovedDomainEvent(Guid MessageId, Guid ChatId, Guid UserId, string Emoji) : IDomainEvent;
|
||||
@@ -0,0 +1,25 @@
|
||||
using System;
|
||||
using Knot.Shared.Kernel;
|
||||
|
||||
namespace Knot.Contracts.Messaging.Domain;
|
||||
|
||||
public sealed class MessageReaction : AggregateRoot<Guid>
|
||||
{
|
||||
public Guid MessageId { get; private set; }
|
||||
public Guid UserId { get; private set; }
|
||||
public string Emoji { get; private set; }
|
||||
public DateTime CreatedAt { get; private set; }
|
||||
|
||||
private MessageReaction() : base(Guid.Empty)
|
||||
{
|
||||
Emoji = default!;
|
||||
}
|
||||
|
||||
public MessageReaction(Guid messageId, Guid userId, string emoji) : base(Guid.NewGuid())
|
||||
{
|
||||
MessageId = messageId;
|
||||
UserId = userId;
|
||||
Emoji = emoji;
|
||||
CreatedAt = DateTime.UtcNow;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
namespace Knot.Contracts.Messaging.Domain;
|
||||
|
||||
/// <summary>
|
||||
/// Состояние сообщения
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum MessageState
|
||||
{
|
||||
None = 0,
|
||||
IsEdited = 1,
|
||||
IsDeleted = 2,
|
||||
IsImported = 4,
|
||||
IsPinned = 8
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Knot.Contracts.Messaging.Domain;
|
||||
|
||||
public class PollMessage : Message
|
||||
{
|
||||
public override string Type => "poll";
|
||||
public override string? Content { get; protected set; }
|
||||
public List<PollOption> Options { get; set; } = new();
|
||||
public List<PollVote> Votes { get; set; } = new();
|
||||
public bool IsMultipleChoice { get; set; }
|
||||
public bool IsAnonymous { get; set; }
|
||||
public DateTime? ExpiresAt { get; set; }
|
||||
public bool IsClosed { get; set; }
|
||||
|
||||
public PollMessage() : base() { }
|
||||
|
||||
public PollMessage(Guid id, Guid chatId, Guid senderId, string? question, List<PollOption>? options, bool isAnonymous, bool isMultiple, DateTime? expiresAt, Guid? replyToId, Guid? forwardedFromId, DateTime createdAt, bool isImported)
|
||||
: base(id, chatId, senderId, replyToId, forwardedFromId, createdAt, isImported)
|
||||
{
|
||||
Content = question ?? "Poll";
|
||||
Options = options ?? new List<PollOption>();
|
||||
IsAnonymous = isAnonymous;
|
||||
IsMultipleChoice = isMultiple;
|
||||
ExpiresAt = expiresAt;
|
||||
}
|
||||
|
||||
public static PollMessage Create(Guid id, Guid chatId, Guid senderId, string? question, List<string> options, bool isAnonymous, bool isMultiple, DateTime? expiresAt, Guid? replyToId, Guid? forwardedFromId)
|
||||
{
|
||||
var poll = new PollMessage(id, chatId, senderId, question, null, isAnonymous, isMultiple, expiresAt, replyToId, forwardedFromId, DateTime.UtcNow, false);
|
||||
foreach (var opt in options)
|
||||
{
|
||||
poll.Options.Add(new PollOption { Text = opt });
|
||||
}
|
||||
return poll;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace Knot.Contracts.Messaging.Domain;
|
||||
|
||||
public class PollOption
|
||||
{
|
||||
public Guid Id { get; set; } = Guid.NewGuid();
|
||||
public string Text { get; set; } = string.Empty;
|
||||
public int VoteCount { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
using System;
|
||||
|
||||
namespace Knot.Contracts.Messaging.Domain;
|
||||
|
||||
public class PollVote
|
||||
{
|
||||
public Guid OptionId { get; set; }
|
||||
public Guid UserId { get; set; }
|
||||
public DateTime VotedAt { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using Knot.Shared.Kernel;
|
||||
|
||||
namespace Knot.Contracts.Messaging.Domain;
|
||||
|
||||
public sealed class Reaction : Entity<Guid>
|
||||
{
|
||||
public Guid MessageId { get; private set; }
|
||||
public Guid UserId { get; private set; }
|
||||
public string Emoji { get; private set; }
|
||||
|
||||
internal Reaction(Guid messageId, Guid userId, string emoji) : base(Guid.NewGuid())
|
||||
{
|
||||
MessageId = messageId;
|
||||
UserId = userId;
|
||||
Emoji = emoji;
|
||||
}
|
||||
|
||||
private Reaction() : base(Guid.Empty)
|
||||
{
|
||||
Emoji = string.Empty;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using System;
|
||||
|
||||
namespace Knot.Contracts.Messaging.Domain;
|
||||
|
||||
public class StoryMessage : Message
|
||||
{
|
||||
public override string Type => "story";
|
||||
public override string? Content { get; protected set; }
|
||||
public Guid? StoryId { get; private set; }
|
||||
public string? StoryMediaUrl { get; private set; }
|
||||
public string? StoryMediaType { get; private set; }
|
||||
|
||||
public StoryMessage() : base() { }
|
||||
|
||||
public StoryMessage(Guid id, Guid chatId, Guid senderId, Guid storyId, string? storyMediaUrl, string? storyMediaType, DateTime createdAt)
|
||||
: base(id, chatId, senderId, null, null, createdAt, false)
|
||||
{
|
||||
StoryId = storyId;
|
||||
StoryMediaUrl = storyMediaUrl;
|
||||
StoryMediaType = storyMediaType;
|
||||
}
|
||||
|
||||
public StoryMessage(Guid id, Guid chatId, Guid senderId, Guid storyId, string? storyMediaUrl, string? storyMediaType, string? content, Guid? replyToId, Guid? forwardedFromId, DateTime createdAt, bool isImported)
|
||||
: this(id, chatId, senderId, storyId, storyMediaUrl, storyMediaType, createdAt)
|
||||
{
|
||||
Content = content;
|
||||
ReplyToId = replyToId;
|
||||
ForwardedFromId = forwardedFromId;
|
||||
if (isImported) AddState(MessageState.IsImported);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
|
||||
namespace Knot.Contracts.Messaging.Domain;
|
||||
|
||||
public class TextMessage : Message
|
||||
{
|
||||
public override string Type => "text";
|
||||
public override string? Content { get; protected set; }
|
||||
public string? Quote { get; protected set; }
|
||||
|
||||
public TextMessage() : base() { }
|
||||
|
||||
public TextMessage(Guid id, Guid chatId, Guid senderId, string content, Guid? replyToId, Guid? forwardedFromId, DateTime createdAt, bool isImported = false)
|
||||
: base(id, chatId, senderId, replyToId, forwardedFromId, createdAt, isImported) => Content = content;
|
||||
|
||||
public TextMessage(Guid id, Guid chatId, Guid senderId, string content, Guid? replyToId, string? quote, Guid? forwardedFromId, DateTime createdAt, bool isImported = false)
|
||||
: this(id, chatId, senderId, content, replyToId, forwardedFromId, createdAt, isImported) => Quote = quote;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Knot.Contracts.Messaging.Infrastructure.Persistence;
|
||||
|
||||
public interface IMongoMessageCollection
|
||||
{
|
||||
Task<List<Message>> GetAllAsync(CancellationToken cancellationToken);
|
||||
Task<List<Message>> GetOrphanedMessagesAsync(HashSet<Guid> activeChatIds, CancellationToken cancellationToken);
|
||||
Task DeleteManyAsync(List<Guid> messageIds, CancellationToken cancellationToken);
|
||||
}
|
||||
|
||||
public class Message
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public Guid ChatId { get; set; }
|
||||
public bool IsDeleted { get; set; }
|
||||
public string? MediaUrl { get; set; }
|
||||
public List<Media>? Media { get; set; }
|
||||
}
|
||||
|
||||
public class Media
|
||||
{
|
||||
public string Url { get; set; } = string.Empty;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<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" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MediatR" Version="12.0.1" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="10.0.4" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,12 @@
|
||||
using Knot.Shared.Kernel;
|
||||
|
||||
namespace Knot.Contracts.Profiles.Application.DTOs;
|
||||
|
||||
public static class ProfilesErrors
|
||||
{
|
||||
public static Error ProfileNotFound => new("Profiles.NotFound", "Profile not found");
|
||||
public static Error UsernameAlreadyExists => new("Profiles.UsernameExists", "Username already exists");
|
||||
public static Error AvatarNotFound => new("Profiles.AvatarNotFound", "Avatar not found");
|
||||
public static Error InvalidAvatarFormat => new("Profiles.InvalidAvatarFormat", "Invalid avatar format");
|
||||
public static Error AvatarUploadFailed => new("Profiles.AvatarUploadFailed", "Avatar upload failed");
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using MediatR;
|
||||
|
||||
namespace Knot.Contracts.Profiles.Application.DTOs;
|
||||
|
||||
public record SearchProfilesRequest(string Query, int Limit = 20) : IRequest<List<UserProfileDto>>;
|
||||
|
||||
public record UpdateProfileRequest(
|
||||
string? DisplayName,
|
||||
string? About,
|
||||
string? Avatar,
|
||||
bool RemoveAvatar = false
|
||||
) : IRequest<UserProfileDto>;
|
||||
|
||||
public record UpdateSettingsRequest(
|
||||
bool? ShowLastSeen,
|
||||
bool? ShowAvatar,
|
||||
bool? ShowAbout,
|
||||
bool? ShowPhoneNumber,
|
||||
bool? ShowForwardedMessages,
|
||||
bool? ShowAddToGroupPermission
|
||||
) : IRequest<UserProfileDto>;
|
||||
@@ -0,0 +1,16 @@
|
||||
namespace Knot.Contracts.Profiles.Application.DTOs;
|
||||
|
||||
public class UserProfileDto
|
||||
{
|
||||
public Guid UserId { get; set; }
|
||||
public Guid Id { get => UserId; set => UserId = value; }
|
||||
public string? DisplayName { get; set; }
|
||||
public string? Username { get; set; }
|
||||
public string? About { get; set; }
|
||||
public string? Avatar { get; set; }
|
||||
public bool IsBot { get; set; }
|
||||
public DateTime? LastSeen { get; set; }
|
||||
public DateTime? Birthday { get; set; }
|
||||
public bool IsPremium { get; set; }
|
||||
public DateTime CreatedAt { get; set; }
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user