From 6d1c53beeb7347a30a2c6137061331f0fbaf885d Mon Sep 17 00:00:00 2001 From: Artemy <109195690+stalcker2288969@users.noreply.github.com> Date: Thu, 16 Jul 2026 19:27:45 +0700 Subject: [PATCH] Refactor: migrate Core -> Domain and reorganize projects Large refactor that renames/moves core types into a new Govor.Domain surface and reorganizes the Application layer. Models, configurations, migrations and many files moved from Govor.Core/Govor.Data to Govor.Domain; numerous Application services, interfaces and implementations were relocated or added (authentication, friends, messages, medias, push notifications, user sessions, storage, synching, private chats, etc.). Tests updated to use Govor.Domain namespaces and adjusted project references (removed Govor.Data reference from API tests). Also updated API, Hub and mapping code and project files to reflect the new structure and naming. This is primarily a codebase-wide namespace and module reorganization to establish a Domain project and restructure application services. --- .../Controllers/SessionControllerTests.cs | 2 +- Govor.API.Tests/Govor.API.Tests.csproj | 1 - Govor.API.Tests/Hubs/PresenceHubTests.cs | 4 +- .../Controllers/AuthControllerTests.cs | 6 +- .../Controllers/ChatLoadControllerTests.cs | 3 +- .../FriendsRequestQueryControllerTests.cs | 2 +- .../Controllers/FriendshipControllerTests.cs | 2 +- .../Controllers/MediaControllerTests.cs | 2 +- .../OnlinePingingControllerTests.cs | 1 + .../Controllers/ProfileControllerTests.cs | 4 +- .../IntegrationTests/Hubs/FriendsHubTests.cs | 2 +- .../PrivateChatGroupManagerTests.cs | 3 +- Govor.API.Tests/LocalStorageServiceTests.cs | 1 - .../Validators/ChatGroupValidatorTests.cs | 4 +- .../Validators/FriendshipValidatorTests.cs | 4 +- ...orTests.cs => InvitationConstantsTests.cs} | 10 +- .../Validators/MessageValidatorTests.cs | 6 +- .../Validators/PrivateChatValidatorTests.cs | 4 +- ...alidatorTests.cs => UserConstantsTests.cs} | 10 +- .../Common/Extensions/AddOptionExtensions.cs | 2 +- .../ConfigurationProgramExtensions.cs | 94 +- Govor.API/Common/Mapping/MappingProfile.cs | 7 +- ...serProfileToUserProfileDtoMappingAction.cs | 3 +- .../Mapping/UserToUserDtoMappingAction.cs | 6 +- .../AdminStuff/FriendshipsController.cs | 15 +- .../AdminStuff/InviteUserController.cs | 38 +- .../Controllers/AdminStuff/UsersController.cs | 12 +- .../Authentication/AuthController.cs | 134 +-- .../Authentication/RefreshController.cs | 52 +- .../Authentication/SessionKeysController.cs | 7 +- Govor.API/Controllers/ChatLoadController.cs | 30 +- .../Friends/FriendsRequestQueryController.cs | 25 +- .../Friends/FriendshipController.cs | 6 +- Govor.API/Controllers/InviteController.cs | 4 +- Govor.API/Controllers/MediaController.cs | 6 +- .../Controllers/OnlinePingingController.cs | 16 +- .../Controllers/PrivateChatController.cs | 33 +- Govor.API/Controllers/ProfileController.cs | 25 +- Govor.API/Controllers/PushTokensController.cs | 14 +- Govor.API/Controllers/SessionController.cs | 43 +- Govor.API/Filters/HubExceptionFilter.cs | 1 - Govor.API/Govor.API.csproj | 5 +- Govor.API/Hubs/ChatsHub.cs | 26 +- Govor.API/Hubs/FriendsHub.cs | 25 +- .../Infrastructure/ChatNotificationService.cs | 38 +- .../Hubs/Infrastructure/ConnectionManager.cs | 3 + .../Hubs/Infrastructure/ConnectionStore.cs | 2 +- .../Infrastructure/PrivateChatGroupManager.cs | 4 +- Govor.API/Hubs/PresenceHub.cs | 37 +- Govor.API/Hubs/ProfileHub.cs | 11 +- Govor.API/Program.cs | 9 +- Govor.API/Properties/launchSettings.json | 2 +- Govor.API/appsettings.Development.json | 2 +- Govor.API/appsettings.json | 4 +- .../AdminsStuff/InvitationGeneratorTests.cs | 4 +- .../Validators/UsernameValidatorTests.cs | 2 +- .../Authentication/AuthServiceTests.cs | 12 +- .../Authentication/JwtServiceTests.cs | 2 +- .../FriendRequestCommandServiceTests.cs | 7 +- .../Friends/FriendRequestQueryServiceTests.cs | 8 +- .../Friends/FriendshipServiceTests.cs | 8 +- .../AccesserToDownloadMediaServiceTests.cs | 4 +- .../Messages/MessageCommandServiceTests.cs | 13 +- .../Services/Messages/MessagesLoaderTests.cs | 9 +- .../Services/PasswordHasherTests.cs | 2 +- .../Services/PingHandlerServiceTests.cs | 4 +- .../Services/ProfileServiceTests.cs | 5 +- .../PushNotificationServiceTests.cs | 3 +- .../Services/SynchingServiceTests.cs | 2 +- .../Services/UserGroupsGetterServiceTests.cs | 6 +- .../UserNotificationScopeServiceTests.cs | 4 +- .../Services/UserPrivateChatsCreatorTests.cs | 6 +- .../UserSessions/UserSessionOpenerTests.cs | 4 +- .../UserSessions/UserSessionReaderTests.cs | 6 +- .../UserSessions/UserSessionRefresherTests.cs | 8 +- .../UserSessions/UserSessionRevokerTests.cs | 8 +- .../Services/VerifyFriendshipTests.cs | 5 +- .../Authentication/AuthService.cs | 101 +++ .../Exceptions}/InvalidUsernameException.cs | 4 +- .../Exceptions/LoginUserException.cs | 5 + .../Exceptions/UserAlreadyExistException.cs | 5 + .../Exceptions/UserNotRegisteredException.cs | 5 + .../Authentication/IAuthService.cs | 11 + .../Authentication/IInvitesService.cs | 12 + .../IPasswordHasher.cs | 2 +- .../Authentication/InvitesService.cs | 56 ++ .../JWT}/IJwtService.cs | 4 +- .../JWT}/IJwtTokenHasher.cs | 2 +- .../JWT}/JwtAccessOption.cs | 2 +- .../JWT}/JwtRefreshOption.cs | 2 +- .../JWT}/JwtService.cs | 7 +- .../JWT}/JwtTokenHasher.cs | 3 +- .../Authentication/PasswordHasher.cs | 4 +- .../AuthService/LoginUserException.cs | 5 - .../AuthService/UserAlreadyExistException.cs | 5 - .../AuthService/UserNotRegisteredException.cs | 5 - .../RequestAlreadySentException.cs | 2 +- .../FriendsService/SearchUsersException.cs | 2 +- .../SendFriendRequestException.cs | 2 +- .../InviteLinkInvalidException.cs | 2 +- .../VerifyFriendship/FriendshipException.cs | 2 +- .../Friends/FriendRequestCommandService.cs | 126 +++ .../Friends/FriendRequestQueryService.cs | 36 + .../Friends/FriendsBlockService.cs | 4 +- .../Friends/FriendshipService.cs | 62 ++ .../Friends/IFriendRequestCommandService.cs | 11 + .../Friends/IFriendRequestQueryService.cs | 4 +- .../Friends/IFriendsBlockService.cs | 2 +- .../Friends/IFriendshipService.cs | 4 +- .../IVerifyFriendship.cs | 2 +- .../Friends/VerifierFriendship.cs | 59 ++ Govor.Application/Govor.Application.csproj | 14 +- .../{Interfaces => Groups}/IGroupService.cs | 8 +- .../IUserGroupsGetterService.cs | 4 +- .../Groups/UserGroupsGetterService.cs | 25 + .../AdminsStuff/IInvitationGetter.cs | 10 + .../AdminsStuff}/IInvitionGenerator.cs | 2 +- .../AdminsStuff}/IUsersAdministration.cs | 4 +- .../AdminsStuff/InvitationGenerator.cs | 11 +- .../AdminsStuff/InvitationGetter.cs | 41 + .../AdminsStuff/UsersService.cs | 51 +- .../Extensions/CurrentUserService.cs | 2 - .../Extensions/CurrentUserSessionService.cs | 1 - .../Extensions}/IConnectionStore.cs | 2 +- .../Extensions/ICurrentUserService.cs | 2 +- .../Extensions/ICurrentUserSessionService.cs | 2 +- .../Extensions}/IFriendsService.cs | 6 +- .../Validators/IUsernameValidator.cs | 9 + .../Validators/UsernameValidator.cs | 72 +- .../Interfaces/Authentication/IAuthService.cs | 10 - .../Authentication/IInvitesService.cs | 10 - .../Authentication/IUsernameValidator.cs | 8 - .../Friends/IFriendRequestCommandService.cs | 10 - .../Interfaces/IProfileService.cs | 10 - .../IUserPrivateChatsGetterService.cs | 8 - .../Messages/IMessageCommandService.cs | 30 - .../Messages/Parameters/DeleteMessage.cs | 5 - .../Interfaces/Messages/Parameters/Result.cs | 3 - .../Messages/Parameters/SendMedia.cs | 5 - .../IPushNotificationService.cs | 10 - .../UserSession/IUserSessionOpener.cs | 10 - .../UserSession/IUserSessionReader.cs | 6 - .../UserSession/IUserSessionRefresher.cs | 8 - .../UserSession/IUserSessionRevoker.cs | 8 - .../Medias/AccesserToDownloadMediaService.cs | 7 +- .../Medias/IAccesserToDownloadMedia.cs | 2 +- .../{Interfaces => }/Medias/IMediaService.cs | 6 +- .../{Services => }/Medias/MediaService.cs | 9 +- .../Messages/IMessageEditingService.cs | 8 + .../Messages/IMessageRemovingService.cs | 8 + .../Messages/IMessageSendingService.cs | 8 + .../IMessagesLoader.cs | 4 +- .../Messages/MessageEditingService.cs | 57 ++ .../Messages/MessageRemovingService.cs | 24 + .../Messages/MessageSendingService.cs | 77 ++ Govor.Application/Messages/MessagesLoader.cs | 107 +++ .../Messages/Parameters/DeleteMessage.cs | 5 + .../Parameters/DeleteMessageResult.cs | 6 + .../Messages/Parameters/EditMessage.cs | 2 +- .../Messages/Parameters/EditMessageResult.cs | 9 + .../Messages/Parameters/Result.cs | 3 + .../Messages/Parameters/SendMedia.cs | 3 + .../Messages/Parameters/SendMessage.cs | 4 +- .../Messages/Parameters/SendMessageResult.cs | 6 + .../IPingHandlerService.cs | 2 +- .../PingHandlerService.cs | 5 +- .../IPrivateChatGroupManager.cs | 4 +- .../IUserPrivateChatsCreator.cs | 4 +- .../IUserPrivateChatsGetterService.cs | 11 + .../UserPrivateChatsCreator.cs | 34 +- .../UserPrivateChatsGetter.cs | 46 + Govor.Application/Profiles/IProfileService.cs | 10 + Govor.Application/Profiles/ProfileService.cs | 78 ++ .../IPushNotificationService.cs | 12 + .../PushNotifications/IPushTokenService.cs | 14 + .../PushNotifications/Models/PushMessage.cs | 0 .../Models/SendPushResult.cs | 0 .../Providers/FirebasePushProvider.cs | 4 +- .../Providers}/IPushNotificationProvider.cs | 2 +- .../Providers/NullPushProvider.cs | 2 +- .../PushNotificationService.cs | 119 +++ .../PushNotifications/PushTokenService.cs | 168 ++++ .../Services/Authentication/AuthService.cs | 102 --- .../Friends/FriendRequestCommandService.cs | 105 --- .../Friends/FriendRequestQueryService.cs | 44 - .../Services/Friends/FriendshipService.cs | 80 -- Govor.Application/Services/InvitesService.cs | 53 -- .../Messages/MessageCommandService.cs | 229 ----- .../Services/Messages/MessagesLoader.cs | 142 --- Govor.Application/Services/ProfileService.cs | 56 -- .../PushNotificationService.cs | 98 -- .../Services/UserGroupsGetterService.cs | 28 - .../Services/UserPrivateChatsGetter.cs | 28 - .../UserSessions/UserSessionReader.cs | 34 - .../UserSessions/UserSessionRefresher.cs | 77 -- .../UserSessions/UserSessionRevoker.cs | 73 -- .../Services/VerifierFriendship.cs | 72 -- .../IStorageService.cs | 2 +- .../LocalStorageService.cs | 3 +- .../ISynchingService.cs | 2 +- .../{Services => Synching}/SynchingService.cs | 4 +- .../Users/IUserNameExistValidator.cs | 6 + .../Users/UserNameExistValidator.cs | 26 + .../UserOnlineStatus/IOnlineUserStore.cs | 2 +- .../IUserNotificationScopeService.cs | 2 +- .../UserOnlineStatus/IUserPresenceReader.cs | 2 +- .../UserOnlineStatus/OnlineUserStore.cs | 3 +- .../UserNotificationScopeService.cs | 20 +- .../UserOnlineStatus/UserPresenceReader.cs | 4 +- .../Crypto/IOneTimePreKeysRotator.cs | 2 +- .../Crypto/ISessionKeyAttacher.cs | 4 +- .../Crypto/ISessionKeysReader.cs | 4 +- .../Crypto/OneTimePreKeysRotator.cs | 9 +- .../UserSessions/Crypto/SessionKeyAttacher.cs | 9 +- .../UserSessions/Crypto/SessionKeysReader.cs | 8 +- .../Users/UserSessions/IUserSessionOpener.cs | 11 + .../Users/UserSessions/IUserSessionReader.cs | 8 + .../UserSessions/IUserSessionRefresher.cs | 8 + .../Users/UserSessions/IUserSessionRevoker.cs | 10 + .../Users/UserSessions/RefreshResult.cs | 3 + .../UserSessions/UserSessionOpener.cs | 79 +- .../Users/UserSessions/UserSessionReader.cs | 46 + .../UserSessions/UserSessionRefresher.cs | 80 ++ .../Users/UserSessions/UserSessionRevoker.cs | 85 ++ .../Govor.ConsoleClient.csproj | 1 - Govor.Contracts/DTOs/FriendshipDto.cs | 2 +- Govor.Contracts/Govor.Contracts.csproj | 2 +- .../Requests/AvatarUploadRequest.cs | 4 +- Govor.Contracts/Requests/LoginRequest.cs | 8 +- .../Requests/MediaUploadRequest.cs | 4 +- .../Requests/RegistrationRequest.cs | 8 +- .../Requests/SignalR/MediaReference.cs | 2 +- .../Requests/SignalR/MessageRequest.cs | 2 +- Govor.Contracts/Responses/MessageResponse.cs | 2 +- .../Responses/SignalR/MessageEditResponse.cs | 2 +- .../SignalR/MessageRemovedResponse.cs | 2 +- .../Responses/SignalR/UserMessageResponse.cs | 4 +- Govor.Core/Govor.Core.csproj | 13 - .../Validators/AdminValidator.cs | 34 - .../Validators/ChatGroupValidator.cs | 44 - .../Validators/FriendshipValidator.cs | 40 - .../Validators/IObjectValidator.cs | 9 - .../Validators/InvitationValidator.cs | 43 - .../Validators/MediaAttachmentsValidator.cs | 40 - .../Validators/MessageValidator.cs | 44 - .../Validators/PrivateChatValidator.cs | 38 - .../Validators/UserValidator.cs | 46 - .../Repositories/Admins/IAdminsExist.cs | 9 - .../Repositories/Admins/IAdminsReader.cs | 9 - .../Repositories/Admins/IAdminsRepository.cs | 6 - .../Repositories/Admins/IAdminsWriter.cs | 10 - .../Friendships/IFriendshipsExist.cs | 7 - .../Friendships/IFriendshipsReader.cs | 11 - .../Friendships/IFriendshipsRepository.cs | 6 - .../Friendships/IFriendshipsWriter.cs | 10 - .../Groups/IGroupMessagesReader.cs | 8 - .../Repositories/Groups/IGroupsExist.cs | 9 - .../Repositories/Groups/IGroupsReader.cs | 13 - .../Repositories/Groups/IGroupsRepository.cs | 6 - .../Repositories/Groups/IGroupsWriter.cs | 10 - .../Repositories/Invaites/IInvitesExist.cs | 10 - .../Repositories/Invaites/IInvitesReader.cs | 11 - .../Invaites/IInvitesRepository.cs | 6 - .../Repositories/Invaites/IInvitesWriter.cs | 10 - .../IMediaAttachmentsExist.cs | 9 - .../IMediaAttachmentsReader.cs | 10 - .../IMediaAttachmentsRepository.cs | 6 - .../IMediaAttachmentsWriter.cs | 10 - .../Repositories/Messages/IMessagesExist.cs | 9 - .../Repositories/Messages/IMessagesReader.cs | 13 - .../Messages/IMessagesRepository.cs | 6 - .../Repositories/Messages/IMessagesWriter.cs | 10 - .../PrivateChats/IPrivateChatsExist.cs | 7 - .../PrivateChats/IPrivateChatsReader.cs | 11 - .../PrivateChats/IPrivateChatsRepository.cs | 8 - .../PrivateChats/IPrivateChatsWriter.cs | 10 - .../PushTokens/IPushTokenReader.cs | 10 - .../PushTokens/IPushTokenRepository.cs | 6 - .../PushTokens/IPushTokenWriter.cs | 11 - .../IUserSessionsExist.cs | 10 - .../IUserSessionsReader.cs | 14 - .../IUserSessionsRepository.cs | 8 - .../IUserSessionsWriter.cs | 12 - Govor.Core/Repositories/Users/IUsersExist.cs | 10 - Govor.Core/Repositories/Users/IUsersReader.cs | 14 - .../Repositories/Users/IUsersRepository.cs | 6 - Govor.Core/Repositories/Users/IUsersWriter.cs | 11 - Govor.Data.Tests/Govor.Data.Tests.csproj | 4 - .../Repositories/AdminsRepositoryTests.cs | 14 +- .../FriendshipsRepositoryTests.cs | 12 +- .../Repositories/GroupRepositoryTests.cs | 12 +- .../Repositories/InvitesRepositoryTests.cs | 12 +- .../Repositories/MediaAttachmentsTests.cs | 14 +- .../Repositories/MessagesRepositoryTests.cs | 14 +- .../PrivateChatsRepositoryTests.cs | 12 +- .../Repositories/PushTokenRepository.cs | 6 +- .../UserSessionsRepositoryTests.cs | 10 +- .../Repositories/UsersRepositoryTests.cs | 14 +- .../20260301080331_Init.Designer.cs | 848 ------------------ ...260301091506_FixRecipientIndex.Designer.cs | 838 ----------------- .../20260301091506_FixRecipientIndex.cs | 67 -- .../20260301120522_FixPushTokensIndexs.cs | 82 -- Govor.Data/Repositories/AdminsRepository.cs | 108 --- .../Exceptions/AdditionException.cs | 10 - .../Exceptions/NotFoundByKeyException.cs | 14 - .../Exceptions/NotFoundException.cs | 11 - .../Exceptions/RemoveException.cs | 4 - .../Exceptions/UpdateException.cs | 12 - .../Repositories/FriendshipsRepository.cs | 150 ---- Govor.Data/Repositories/GroupRepository.cs | 166 ---- Govor.Data/Repositories/InvitesRepository.cs | 154 ---- .../MediaAttachmentsRepository.cs | 128 --- Govor.Data/Repositories/MessagesRepository.cs | 179 ---- .../Repositories/PrivateChatsRepository.cs | 126 --- .../Repositories/PushTokenRepository.cs | 150 ---- .../Repositories/UserSessionsRepository.cs | 169 ---- Govor.Data/Repositories/UsersRepository.cs | 222 ----- .../Common/Constants/InvitationConstants.cs | 6 + .../Common/Constants/UserConstants.cs | 7 + Govor.Domain/Common/Error.cs | 9 + .../Common}/Extensions/QueryableExtensions.cs | 2 +- Govor.Domain/Common/Result.cs | 49 + .../Configurations/AdminConfiguration.cs | 4 +- .../Configurations/ChatGroupConfigurator.cs | 4 +- .../Configurations/FriendshipConfiguration.cs | 4 +- .../GroupAdminsConfiguration.cs | 4 +- .../GroupInvitationConfiguration.cs | 4 +- .../GroupMembershipConfiguration.cs | 12 +- .../Configurations/InvitationConfiguration.cs | 4 +- .../MediaAttachmentsConfiguration.cs | 4 +- .../Configurations/MediaFileConfiguration.cs | 4 +- .../MessageReactionConfiguration.cs | 4 +- .../MessageViewConfiguration.cs | 4 +- .../Configurations/MessagesConfiguration.cs | 4 +- .../OneTimePreKeyConfiguration.cs | 4 +- .../PrivacyRuleEntityConfiguration.cs | 5 +- .../PrivacyUserSettingsConfiguration.cs | 4 +- .../PrivateChatsConfiguration.cs | 4 +- .../SignedPreKeyConfiguration.cs | 4 +- .../Configurations/UserConfiguration.cs | 4 +- .../UserCryptoSessionConfiguration.cs | 4 +- .../UserPushTokenConfiguration.cs | 4 +- .../UserSessionConfiguration.cs | 18 +- .../Govor.Domain.csproj | 5 - .../GovorCoreException.cs | 2 +- .../GovorDbContext.cs | 12 +- .../20260716110338_InitialCreate.Designer.cs | 150 ++-- .../20260716110338_InitialCreate.cs | 56 +- .../Migrations/GovorDbContextModelSnapshot.cs | 146 +-- .../Models/ChatGroup.cs | 4 +- .../Models/Friendship.cs | 4 +- .../Models/GroupAdmins.cs | 2 +- .../Models/GroupInvitation.cs | 4 +- .../Models/GroupMembership.cs | 3 +- .../Models/Invitation.cs | 4 +- .../Models/MediaFile.cs | 6 +- .../Models/Messages/MediaAttachments.cs | 2 +- .../Models/Messages/Message.cs | 2 +- .../Models/Messages/MessageReaction.cs | 4 +- .../Models/Messages/MessageView.cs | 2 +- .../Models/PrivateChat.cs | 4 +- .../Models/Users/Admin.cs | 2 +- .../Models/Users/Crypto/OneTimePreKey.cs | 2 +- .../Models/Users/Crypto/SignedPreKey.cs | 2 +- .../Models/Users/Crypto/UserCryptoSession.cs | 2 +- .../Models/Users/PrivacyRuleEntity.cs | 2 +- .../Models/Users/PrivacyUserSettings.cs | 2 +- .../Models/Users/User.cs | 2 +- .../Models/Users/UserPushToken.cs | 4 +- .../Models/Users/UserSession.cs | 20 +- Govor.sln | 21 +- 371 files changed, 2729 insertions(+), 6694 deletions(-) rename Govor.API.Tests/UnitTests/Infrastructure/Validators/{InvitationValidatorTests.cs => InvitationConstantsTests.cs} (94%) rename Govor.API.Tests/UnitTests/Infrastructure/Validators/{UserValidatorTests.cs => UserConstantsTests.cs} (96%) create mode 100644 Govor.Application/Authentication/AuthService.cs rename Govor.Application/{Exceptions/AuthService => Authentication/Exceptions}/InvalidUsernameException.cs (55%) create mode 100644 Govor.Application/Authentication/Exceptions/LoginUserException.cs create mode 100644 Govor.Application/Authentication/Exceptions/UserAlreadyExistException.cs create mode 100644 Govor.Application/Authentication/Exceptions/UserNotRegisteredException.cs create mode 100644 Govor.Application/Authentication/IAuthService.cs create mode 100644 Govor.Application/Authentication/IInvitesService.cs rename Govor.Application/{Interfaces => Authentication}/IPasswordHasher.cs (73%) create mode 100644 Govor.Application/Authentication/InvitesService.cs rename Govor.Application/{Interfaces/Authentication => Authentication/JWT}/IJwtService.cs (74%) rename Govor.Application/{Interfaces/Authentication => Authentication/JWT}/IJwtTokenHasher.cs (69%) rename Govor.Application/{Services/Authentication => Authentication/JWT}/JwtAccessOption.cs (66%) rename Govor.Application/{Services/Authentication => Authentication/JWT}/JwtRefreshOption.cs (62%) rename Govor.Application/{Services/Authentication => Authentication/JWT}/JwtService.cs (94%) rename Govor.Application/{Services/Authentication => Authentication/JWT}/JwtTokenHasher.cs (91%) rename Govor.Application/{Services => }/Authentication/PasswordHasher.cs (76%) delete mode 100644 Govor.Application/Exceptions/AuthService/LoginUserException.cs delete mode 100644 Govor.Application/Exceptions/AuthService/UserAlreadyExistException.cs delete mode 100644 Govor.Application/Exceptions/AuthService/UserNotRegisteredException.cs create mode 100644 Govor.Application/Friends/FriendRequestCommandService.cs create mode 100644 Govor.Application/Friends/FriendRequestQueryService.cs rename Govor.Application/{Services => }/Friends/FriendsBlockService.cs (79%) create mode 100644 Govor.Application/Friends/FriendshipService.cs create mode 100644 Govor.Application/Friends/IFriendRequestCommandService.cs rename Govor.Application/{Interfaces => }/Friends/IFriendRequestQueryService.cs (69%) rename Govor.Application/{Interfaces => }/Friends/IFriendsBlockService.cs (81%) rename Govor.Application/{Interfaces => }/Friends/IFriendshipService.cs (73%) rename Govor.Application/{Interfaces => Friends}/IVerifyFriendship.cs (80%) create mode 100644 Govor.Application/Friends/VerifierFriendship.cs rename Govor.Application/{Interfaces => Groups}/IGroupService.cs (79%) rename Govor.Application/{Interfaces => Groups}/IUserGroupsGetterService.cs (61%) create mode 100644 Govor.Application/Groups/UserGroupsGetterService.cs create mode 100644 Govor.Application/Infrastructure/AdminsStuff/IInvitationGetter.cs rename Govor.Application/{Interfaces => Infrastructure/AdminsStuff}/IInvitionGenerator.cs (73%) rename Govor.Application/{Interfaces => Infrastructure/AdminsStuff}/IUsersAdministration.cs (66%) create mode 100644 Govor.Application/Infrastructure/AdminsStuff/InvitationGetter.cs rename Govor.Application/{Interfaces => Infrastructure/Extensions}/IConnectionStore.cs (78%) rename Govor.Application/{Interfaces => }/Infrastructure/Extensions/ICurrentUserService.cs (50%) rename Govor.Application/{Interfaces => }/Infrastructure/Extensions/ICurrentUserSessionService.cs (53%) rename Govor.Application/{Interfaces => Infrastructure/Extensions}/IFriendsService.cs (81%) create mode 100644 Govor.Application/Infrastructure/Validators/IUsernameValidator.cs delete mode 100644 Govor.Application/Interfaces/Authentication/IAuthService.cs delete mode 100644 Govor.Application/Interfaces/Authentication/IInvitesService.cs delete mode 100644 Govor.Application/Interfaces/Authentication/IUsernameValidator.cs delete mode 100644 Govor.Application/Interfaces/Friends/IFriendRequestCommandService.cs delete mode 100644 Govor.Application/Interfaces/IProfileService.cs delete mode 100644 Govor.Application/Interfaces/IUserPrivateChatsGetterService.cs delete mode 100644 Govor.Application/Interfaces/Messages/IMessageCommandService.cs delete mode 100644 Govor.Application/Interfaces/Messages/Parameters/DeleteMessage.cs delete mode 100644 Govor.Application/Interfaces/Messages/Parameters/Result.cs delete mode 100644 Govor.Application/Interfaces/Messages/Parameters/SendMedia.cs delete mode 100644 Govor.Application/Interfaces/PushNotifications/IPushNotificationService.cs delete mode 100644 Govor.Application/Interfaces/UserSession/IUserSessionOpener.cs delete mode 100644 Govor.Application/Interfaces/UserSession/IUserSessionReader.cs delete mode 100644 Govor.Application/Interfaces/UserSession/IUserSessionRefresher.cs delete mode 100644 Govor.Application/Interfaces/UserSession/IUserSessionRevoker.cs rename Govor.Application/{Services => }/Medias/AccesserToDownloadMediaService.cs (91%) rename Govor.Application/{Interfaces => }/Medias/IAccesserToDownloadMedia.cs (69%) rename Govor.Application/{Interfaces => }/Medias/IMediaService.cs (79%) rename Govor.Application/{Services => }/Medias/MediaService.cs (96%) create mode 100644 Govor.Application/Messages/IMessageEditingService.cs create mode 100644 Govor.Application/Messages/IMessageRemovingService.cs create mode 100644 Govor.Application/Messages/IMessageSendingService.cs rename Govor.Application/{Interfaces => Messages}/IMessagesLoader.cs (80%) create mode 100644 Govor.Application/Messages/MessageEditingService.cs create mode 100644 Govor.Application/Messages/MessageRemovingService.cs create mode 100644 Govor.Application/Messages/MessageSendingService.cs create mode 100644 Govor.Application/Messages/MessagesLoader.cs create mode 100644 Govor.Application/Messages/Parameters/DeleteMessage.cs create mode 100644 Govor.Application/Messages/Parameters/DeleteMessageResult.cs rename Govor.Application/{Interfaces => }/Messages/Parameters/EditMessage.cs (52%) create mode 100644 Govor.Application/Messages/Parameters/EditMessageResult.cs create mode 100644 Govor.Application/Messages/Parameters/Result.cs create mode 100644 Govor.Application/Messages/Parameters/SendMedia.cs rename Govor.Application/{Interfaces => }/Messages/Parameters/SendMessage.cs (58%) create mode 100644 Govor.Application/Messages/Parameters/SendMessageResult.cs rename Govor.Application/{Interfaces => PingHandler}/IPingHandlerService.cs (61%) rename Govor.Application/{Services => PingHandler}/PingHandlerService.cs (90%) rename Govor.Application/{Interfaces => PrivateUserChats}/IPrivateChatGroupManager.cs (71%) rename Govor.Application/{Interfaces => PrivateUserChats}/IUserPrivateChatsCreator.cs (59%) create mode 100644 Govor.Application/PrivateUserChats/IUserPrivateChatsGetterService.cs rename Govor.Application/{Services => PrivateUserChats}/UserPrivateChatsCreator.cs (51%) create mode 100644 Govor.Application/PrivateUserChats/UserPrivateChatsGetter.cs create mode 100644 Govor.Application/Profiles/IProfileService.cs create mode 100644 Govor.Application/Profiles/ProfileService.cs create mode 100644 Govor.Application/PushNotifications/IPushNotificationService.cs create mode 100644 Govor.Application/PushNotifications/IPushTokenService.cs rename Govor.Application/{Interfaces => }/PushNotifications/Models/PushMessage.cs (100%) rename Govor.Application/{Interfaces => }/PushNotifications/Models/SendPushResult.cs (100%) rename Govor.Application/{Services => }/PushNotifications/Providers/FirebasePushProvider.cs (97%) rename Govor.Application/{Interfaces/PushNotifications => PushNotifications/Providers}/IPushNotificationProvider.cs (84%) rename Govor.Application/{Services => }/PushNotifications/Providers/NullPushProvider.cs (88%) create mode 100644 Govor.Application/PushNotifications/PushNotificationService.cs create mode 100644 Govor.Application/PushNotifications/PushTokenService.cs delete mode 100644 Govor.Application/Services/Authentication/AuthService.cs delete mode 100644 Govor.Application/Services/Friends/FriendRequestCommandService.cs delete mode 100644 Govor.Application/Services/Friends/FriendRequestQueryService.cs delete mode 100644 Govor.Application/Services/Friends/FriendshipService.cs delete mode 100644 Govor.Application/Services/InvitesService.cs delete mode 100644 Govor.Application/Services/Messages/MessageCommandService.cs delete mode 100644 Govor.Application/Services/Messages/MessagesLoader.cs delete mode 100644 Govor.Application/Services/ProfileService.cs delete mode 100644 Govor.Application/Services/PushNotifications/PushNotificationService.cs delete mode 100644 Govor.Application/Services/UserGroupsGetterService.cs delete mode 100644 Govor.Application/Services/UserPrivateChatsGetter.cs delete mode 100644 Govor.Application/Services/UserSessions/UserSessionReader.cs delete mode 100644 Govor.Application/Services/UserSessions/UserSessionRefresher.cs delete mode 100644 Govor.Application/Services/UserSessions/UserSessionRevoker.cs delete mode 100644 Govor.Application/Services/VerifierFriendship.cs rename Govor.Application/{Interfaces => Storage}/IStorageService.cs (80%) rename Govor.Application/{Services => Storage}/LocalStorageService.cs (97%) rename Govor.Application/{Interfaces => Synching}/ISynchingService.cs (89%) rename Govor.Application/{Services => Synching}/SynchingService.cs (82%) create mode 100644 Govor.Application/Users/IUserNameExistValidator.cs create mode 100644 Govor.Application/Users/UserNameExistValidator.cs rename Govor.Application/{Interfaces => Users}/UserOnlineStatus/IOnlineUserStore.cs (83%) rename Govor.Application/{Interfaces => Users}/UserOnlineStatus/IUserNotificationScopeService.cs (63%) rename Govor.Application/{Interfaces => Users}/UserOnlineStatus/IUserPresenceReader.cs (61%) rename Govor.Application/{Services => Users}/UserOnlineStatus/OnlineUserStore.cs (94%) rename Govor.Application/{Services => Users}/UserOnlineStatus/UserNotificationScopeService.cs (67%) rename Govor.Application/{Services => Users}/UserOnlineStatus/UserPresenceReader.cs (60%) rename Govor.Application/{Interfaces/UserSession => Users/UserSessions}/Crypto/IOneTimePreKeysRotator.cs (78%) rename Govor.Application/{Interfaces/UserSession => Users/UserSessions}/Crypto/ISessionKeyAttacher.cs (70%) rename Govor.Application/{Interfaces/UserSession => Users/UserSessions}/Crypto/ISessionKeysReader.cs (75%) rename Govor.Application/{Services => Users}/UserSessions/Crypto/OneTimePreKeysRotator.cs (90%) rename Govor.Application/{Services => Users}/UserSessions/Crypto/SessionKeyAttacher.cs (90%) rename Govor.Application/{Services => Users}/UserSessions/Crypto/SessionKeysReader.cs (89%) create mode 100644 Govor.Application/Users/UserSessions/IUserSessionOpener.cs create mode 100644 Govor.Application/Users/UserSessions/IUserSessionReader.cs create mode 100644 Govor.Application/Users/UserSessions/IUserSessionRefresher.cs create mode 100644 Govor.Application/Users/UserSessions/IUserSessionRevoker.cs create mode 100644 Govor.Application/Users/UserSessions/RefreshResult.cs rename Govor.Application/{Services => Users}/UserSessions/UserSessionOpener.cs (52%) create mode 100644 Govor.Application/Users/UserSessions/UserSessionReader.cs create mode 100644 Govor.Application/Users/UserSessions/UserSessionRefresher.cs create mode 100644 Govor.Application/Users/UserSessions/UserSessionRevoker.cs delete mode 100644 Govor.Core/Govor.Core.csproj delete mode 100644 Govor.Core/Infrastructure/Validators/AdminValidator.cs delete mode 100644 Govor.Core/Infrastructure/Validators/ChatGroupValidator.cs delete mode 100644 Govor.Core/Infrastructure/Validators/FriendshipValidator.cs delete mode 100644 Govor.Core/Infrastructure/Validators/IObjectValidator.cs delete mode 100644 Govor.Core/Infrastructure/Validators/InvitationValidator.cs delete mode 100644 Govor.Core/Infrastructure/Validators/MediaAttachmentsValidator.cs delete mode 100644 Govor.Core/Infrastructure/Validators/MessageValidator.cs delete mode 100644 Govor.Core/Infrastructure/Validators/PrivateChatValidator.cs delete mode 100644 Govor.Core/Infrastructure/Validators/UserValidator.cs delete mode 100644 Govor.Core/Repositories/Admins/IAdminsExist.cs delete mode 100644 Govor.Core/Repositories/Admins/IAdminsReader.cs delete mode 100644 Govor.Core/Repositories/Admins/IAdminsRepository.cs delete mode 100644 Govor.Core/Repositories/Admins/IAdminsWriter.cs delete mode 100644 Govor.Core/Repositories/Friendships/IFriendshipsExist.cs delete mode 100644 Govor.Core/Repositories/Friendships/IFriendshipsReader.cs delete mode 100644 Govor.Core/Repositories/Friendships/IFriendshipsRepository.cs delete mode 100644 Govor.Core/Repositories/Friendships/IFriendshipsWriter.cs delete mode 100644 Govor.Core/Repositories/Groups/IGroupMessagesReader.cs delete mode 100644 Govor.Core/Repositories/Groups/IGroupsExist.cs delete mode 100644 Govor.Core/Repositories/Groups/IGroupsReader.cs delete mode 100644 Govor.Core/Repositories/Groups/IGroupsRepository.cs delete mode 100644 Govor.Core/Repositories/Groups/IGroupsWriter.cs delete mode 100644 Govor.Core/Repositories/Invaites/IInvitesExist.cs delete mode 100644 Govor.Core/Repositories/Invaites/IInvitesReader.cs delete mode 100644 Govor.Core/Repositories/Invaites/IInvitesRepository.cs delete mode 100644 Govor.Core/Repositories/Invaites/IInvitesWriter.cs delete mode 100644 Govor.Core/Repositories/MediasAttachments/IMediaAttachmentsExist.cs delete mode 100644 Govor.Core/Repositories/MediasAttachments/IMediaAttachmentsReader.cs delete mode 100644 Govor.Core/Repositories/MediasAttachments/IMediaAttachmentsRepository.cs delete mode 100644 Govor.Core/Repositories/MediasAttachments/IMediaAttachmentsWriter.cs delete mode 100644 Govor.Core/Repositories/Messages/IMessagesExist.cs delete mode 100644 Govor.Core/Repositories/Messages/IMessagesReader.cs delete mode 100644 Govor.Core/Repositories/Messages/IMessagesRepository.cs delete mode 100644 Govor.Core/Repositories/Messages/IMessagesWriter.cs delete mode 100644 Govor.Core/Repositories/PrivateChats/IPrivateChatsExist.cs delete mode 100644 Govor.Core/Repositories/PrivateChats/IPrivateChatsReader.cs delete mode 100644 Govor.Core/Repositories/PrivateChats/IPrivateChatsRepository.cs delete mode 100644 Govor.Core/Repositories/PrivateChats/IPrivateChatsWriter.cs delete mode 100644 Govor.Core/Repositories/PushTokens/IPushTokenReader.cs delete mode 100644 Govor.Core/Repositories/PushTokens/IPushTokenRepository.cs delete mode 100644 Govor.Core/Repositories/PushTokens/IPushTokenWriter.cs delete mode 100644 Govor.Core/Repositories/UserSessionsRepository/IUserSessionsExist.cs delete mode 100644 Govor.Core/Repositories/UserSessionsRepository/IUserSessionsReader.cs delete mode 100644 Govor.Core/Repositories/UserSessionsRepository/IUserSessionsRepository.cs delete mode 100644 Govor.Core/Repositories/UserSessionsRepository/IUserSessionsWriter.cs delete mode 100644 Govor.Core/Repositories/Users/IUsersExist.cs delete mode 100644 Govor.Core/Repositories/Users/IUsersReader.cs delete mode 100644 Govor.Core/Repositories/Users/IUsersRepository.cs delete mode 100644 Govor.Core/Repositories/Users/IUsersWriter.cs delete mode 100644 Govor.Data/Migrations/20260301080331_Init.Designer.cs delete mode 100644 Govor.Data/Migrations/20260301091506_FixRecipientIndex.Designer.cs delete mode 100644 Govor.Data/Migrations/20260301091506_FixRecipientIndex.cs delete mode 100644 Govor.Data/Migrations/20260301120522_FixPushTokensIndexs.cs delete mode 100644 Govor.Data/Repositories/AdminsRepository.cs delete mode 100644 Govor.Data/Repositories/Exceptions/AdditionException.cs delete mode 100644 Govor.Data/Repositories/Exceptions/NotFoundByKeyException.cs delete mode 100644 Govor.Data/Repositories/Exceptions/NotFoundException.cs delete mode 100644 Govor.Data/Repositories/Exceptions/RemoveException.cs delete mode 100644 Govor.Data/Repositories/Exceptions/UpdateException.cs delete mode 100644 Govor.Data/Repositories/FriendshipsRepository.cs delete mode 100644 Govor.Data/Repositories/GroupRepository.cs delete mode 100644 Govor.Data/Repositories/InvitesRepository.cs delete mode 100644 Govor.Data/Repositories/MediaAttachmentsRepository.cs delete mode 100644 Govor.Data/Repositories/MessagesRepository.cs delete mode 100644 Govor.Data/Repositories/PrivateChatsRepository.cs delete mode 100644 Govor.Data/Repositories/PushTokenRepository.cs delete mode 100644 Govor.Data/Repositories/UserSessionsRepository.cs delete mode 100644 Govor.Data/Repositories/UsersRepository.cs create mode 100644 Govor.Domain/Common/Constants/InvitationConstants.cs create mode 100644 Govor.Domain/Common/Constants/UserConstants.cs create mode 100644 Govor.Domain/Common/Error.cs rename {Govor.Core/Infrastructure => Govor.Domain/Common}/Extensions/QueryableExtensions.cs (86%) create mode 100644 Govor.Domain/Common/Result.cs rename {Govor.Data => Govor.Domain}/Configurations/AdminConfiguration.cs (83%) rename {Govor.Data => Govor.Domain}/Configurations/ChatGroupConfigurator.cs (92%) rename {Govor.Data => Govor.Domain}/Configurations/FriendshipConfiguration.cs (91%) rename {Govor.Data => Govor.Domain}/Configurations/GroupAdminsConfiguration.cs (85%) rename {Govor.Data => Govor.Domain}/Configurations/GroupInvitationConfiguration.cs (92%) rename {Govor.Data => Govor.Domain}/Configurations/GroupMembershipConfiguration.cs (64%) rename {Govor.Data => Govor.Domain}/Configurations/InvitationConfiguration.cs (87%) rename {Govor.Data => Govor.Domain}/Configurations/MediaAttachmentsConfiguration.cs (89%) rename {Govor.Data => Govor.Domain}/Configurations/MediaFileConfiguration.cs (91%) rename {Govor.Data => Govor.Domain}/Configurations/MessageReactionConfiguration.cs (90%) rename {Govor.Data => Govor.Domain}/Configurations/MessageViewConfiguration.cs (85%) rename {Govor.Data => Govor.Domain}/Configurations/MessagesConfiguration.cs (92%) rename {Govor.Data => Govor.Domain}/Configurations/OneTimePreKeyConfiguration.cs (92%) rename {Govor.Data => Govor.Domain}/Configurations/PrivacyRuleEntityConfiguration.cs (90%) rename {Govor.Data => Govor.Domain}/Configurations/PrivacyUserSettingsConfiguration.cs (92%) rename {Govor.Data => Govor.Domain}/Configurations/PrivateChatsConfiguration.cs (81%) rename {Govor.Data => Govor.Domain}/Configurations/SignedPreKeyConfiguration.cs (90%) rename {Govor.Data => Govor.Domain}/Configurations/UserConfiguration.cs (92%) rename {Govor.Data => Govor.Domain}/Configurations/UserCryptoSessionConfiguration.cs (93%) rename {Govor.Data => Govor.Domain}/Configurations/UserPushTokenConfiguration.cs (91%) rename {Govor.Data => Govor.Domain}/Configurations/UserSessionConfiguration.cs (76%) rename Govor.Data/Govor.Data.csproj => Govor.Domain/Govor.Domain.csproj (83%) rename {Govor.Core => Govor.Domain}/GovorCoreException.cs (93%) rename {Govor.Data => Govor.Domain}/GovorDbContext.cs (93%) rename Govor.Data/Migrations/20260301120522_FixPushTokensIndexs.Designer.cs => Govor.Domain/Migrations/20260716110338_InitialCreate.Designer.cs (81%) rename Govor.Data/Migrations/20260301080331_Init.cs => Govor.Domain/Migrations/20260716110338_InitialCreate.cs (95%) rename {Govor.Data => Govor.Domain}/Migrations/GovorDbContextModelSnapshot.cs (81%) rename {Govor.Core => Govor.Domain}/Models/ChatGroup.cs (93%) rename {Govor.Core => Govor.Domain}/Models/Friendship.cs (85%) rename {Govor.Core => Govor.Domain}/Models/GroupAdmins.cs (80%) rename {Govor.Core => Govor.Domain}/Models/GroupInvitation.cs (87%) rename {Govor.Core => Govor.Domain}/Models/GroupMembership.cs (77%) rename {Govor.Core => Govor.Domain}/Models/Invitation.cs (93%) rename {Govor.Core => Govor.Domain}/Models/MediaFile.cs (80%) rename {Govor.Core => Govor.Domain}/Models/Messages/MediaAttachments.cs (93%) rename {Govor.Core => Govor.Domain}/Models/Messages/Message.cs (96%) rename {Govor.Core => Govor.Domain}/Models/Messages/MessageReaction.cs (83%) rename {Govor.Core => Govor.Domain}/Models/Messages/MessageView.cs (82%) rename {Govor.Core => Govor.Domain}/Models/PrivateChat.cs (86%) rename {Govor.Core => Govor.Domain}/Models/Users/Admin.cs (81%) rename {Govor.Core => Govor.Domain}/Models/Users/Crypto/OneTimePreKey.cs (87%) rename {Govor.Core => Govor.Domain}/Models/Users/Crypto/SignedPreKey.cs (86%) rename {Govor.Core => Govor.Domain}/Models/Users/Crypto/UserCryptoSession.cs (88%) rename {Govor.Core => Govor.Domain}/Models/Users/PrivacyRuleEntity.cs (91%) rename {Govor.Core => Govor.Domain}/Models/Users/PrivacyUserSettings.cs (94%) rename {Govor.Core => Govor.Domain}/Models/Users/User.cs (94%) rename {Govor.Core => Govor.Domain}/Models/Users/UserPushToken.cs (89%) rename {Govor.Core => Govor.Domain}/Models/Users/UserSession.cs (61%) diff --git a/Govor.API.Tests/Controllers/SessionControllerTests.cs b/Govor.API.Tests/Controllers/SessionControllerTests.cs index f3190db..c7d22d5 100644 --- a/Govor.API.Tests/Controllers/SessionControllerTests.cs +++ b/Govor.API.Tests/Controllers/SessionControllerTests.cs @@ -3,7 +3,7 @@ using Govor.API.Controllers; using Govor.Application.Interfaces.Infrastructure.Extensions; using Govor.Application.Interfaces.UserSession; using Govor.Contracts.DTOs; -using Govor.Core.Models.Users; +using Govor.Domain.Models.Users; using Govor.Data.Repositories.Exceptions; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; diff --git a/Govor.API.Tests/Govor.API.Tests.csproj b/Govor.API.Tests/Govor.API.Tests.csproj index 26fdd64..da8779c 100644 --- a/Govor.API.Tests/Govor.API.Tests.csproj +++ b/Govor.API.Tests/Govor.API.Tests.csproj @@ -27,6 +27,5 @@ - diff --git a/Govor.API.Tests/Hubs/PresenceHubTests.cs b/Govor.API.Tests/Hubs/PresenceHubTests.cs index 8318c70..99ddc91 100644 --- a/Govor.API.Tests/Hubs/PresenceHubTests.cs +++ b/Govor.API.Tests/Hubs/PresenceHubTests.cs @@ -2,8 +2,8 @@ using AutoFixture; using Govor.API.Common.SignalR.Helpers; using Govor.API.Hubs; using Govor.Application.Interfaces.UserOnlineStatus; -using Govor.Core.Models.Users; -using Govor.Core.Repositories.Users; +using Govor.Domain.Models.Users; +using Govor.Domain.Repositories.Users; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.SignalR; using Microsoft.Extensions.Logging; diff --git a/Govor.API.Tests/IntegrationTests/Controllers/AuthControllerTests.cs b/Govor.API.Tests/IntegrationTests/Controllers/AuthControllerTests.cs index d216655..54f4953 100644 --- a/Govor.API.Tests/IntegrationTests/Controllers/AuthControllerTests.cs +++ b/Govor.API.Tests/IntegrationTests/Controllers/AuthControllerTests.cs @@ -1,12 +1,12 @@ using AutoFixture; using Govor.API.Controllers.Authentication; -using Govor.Application.Exceptions.AuthService; +using Govor.Application.Authentication.Exceptions; using Govor.Application.Exceptions.InvitesService; using Govor.Application.Interfaces.Authentication; using Govor.Application.Interfaces.UserSession; using Govor.Contracts.Requests; -using Govor.Core.Models; -using Govor.Core.Models.Users; +using Govor.Domain.Models; +using Govor.Domain.Models.Users; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using Moq; diff --git a/Govor.API.Tests/IntegrationTests/Controllers/ChatLoadControllerTests.cs b/Govor.API.Tests/IntegrationTests/Controllers/ChatLoadControllerTests.cs index bc5fb08..cfaf2bd 100644 --- a/Govor.API.Tests/IntegrationTests/Controllers/ChatLoadControllerTests.cs +++ b/Govor.API.Tests/IntegrationTests/Controllers/ChatLoadControllerTests.cs @@ -3,9 +3,10 @@ using AutoMapper; using Govor.API.Controllers; using Govor.Application.Interfaces; using Govor.Application.Interfaces.Infrastructure.Extensions; +using Govor.Application.Messages; using Govor.Contracts.Requests; using Govor.Contracts.Responses; -using Govor.Core.Models.Messages; +using Govor.Domain.Models.Messages; using Govor.Data.Repositories.Exceptions; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; diff --git a/Govor.API.Tests/IntegrationTests/Controllers/FriendsRequestQueryControllerTests.cs b/Govor.API.Tests/IntegrationTests/Controllers/FriendsRequestQueryControllerTests.cs index 1d2b6c1..2f9b8a1 100644 --- a/Govor.API.Tests/IntegrationTests/Controllers/FriendsRequestQueryControllerTests.cs +++ b/Govor.API.Tests/IntegrationTests/Controllers/FriendsRequestQueryControllerTests.cs @@ -4,7 +4,7 @@ using Govor.API.Controllers.Friends; using Govor.Application.Interfaces.Friends; using Govor.Application.Interfaces.Infrastructure.Extensions; using Govor.Contracts.DTOs; -using Govor.Core.Models; +using Govor.Domain.Models; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using Moq; diff --git a/Govor.API.Tests/IntegrationTests/Controllers/FriendshipControllerTests.cs b/Govor.API.Tests/IntegrationTests/Controllers/FriendshipControllerTests.cs index 6d712fb..98eb09e 100644 --- a/Govor.API.Tests/IntegrationTests/Controllers/FriendshipControllerTests.cs +++ b/Govor.API.Tests/IntegrationTests/Controllers/FriendshipControllerTests.cs @@ -5,7 +5,7 @@ using Govor.Application.Exceptions.FriendsService; using Govor.Application.Interfaces.Friends; using Govor.Application.Interfaces.Infrastructure.Extensions; using Govor.Contracts.DTOs; -using Govor.Core.Models.Users; +using Govor.Domain.Models.Users; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using Moq; diff --git a/Govor.API.Tests/IntegrationTests/Controllers/MediaControllerTests.cs b/Govor.API.Tests/IntegrationTests/Controllers/MediaControllerTests.cs index 0cf8f7e..3e74058 100644 --- a/Govor.API.Tests/IntegrationTests/Controllers/MediaControllerTests.cs +++ b/Govor.API.Tests/IntegrationTests/Controllers/MediaControllerTests.cs @@ -4,7 +4,7 @@ using Govor.API.Controllers; using Govor.Application.Interfaces.Infrastructure.Extensions; using Govor.Application.Interfaces.Medias; using Govor.Contracts.Requests; -using Govor.Core.Models.Messages; +using Govor.Domain.Models.Messages; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; diff --git a/Govor.API.Tests/IntegrationTests/Controllers/OnlinePingingControllerTests.cs b/Govor.API.Tests/IntegrationTests/Controllers/OnlinePingingControllerTests.cs index 0133572..d99c066 100644 --- a/Govor.API.Tests/IntegrationTests/Controllers/OnlinePingingControllerTests.cs +++ b/Govor.API.Tests/IntegrationTests/Controllers/OnlinePingingControllerTests.cs @@ -1,6 +1,7 @@ using Govor.API.Controllers; using Govor.Application.Interfaces; using Govor.Application.Interfaces.Infrastructure.Extensions; +using Govor.Application.PingHandler; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using Moq; diff --git a/Govor.API.Tests/IntegrationTests/Controllers/ProfileControllerTests.cs b/Govor.API.Tests/IntegrationTests/Controllers/ProfileControllerTests.cs index 1e73e2d..83653e8 100644 --- a/Govor.API.Tests/IntegrationTests/Controllers/ProfileControllerTests.cs +++ b/Govor.API.Tests/IntegrationTests/Controllers/ProfileControllerTests.cs @@ -8,8 +8,8 @@ using Govor.Application.Interfaces.Medias; using Govor.Application.Profiles; using Govor.Contracts.DTOs; using Govor.Contracts.Requests; -using Govor.Core.Models; -using Govor.Core.Models.Messages; +using Govor.Domain.Models; +using Govor.Domain.Models.Messages; using Govor.Data.Repositories.Exceptions; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; diff --git a/Govor.API.Tests/IntegrationTests/Hubs/FriendsHubTests.cs b/Govor.API.Tests/IntegrationTests/Hubs/FriendsHubTests.cs index e0ee94d..c5a2bd0 100644 --- a/Govor.API.Tests/IntegrationTests/Hubs/FriendsHubTests.cs +++ b/Govor.API.Tests/IntegrationTests/Hubs/FriendsHubTests.cs @@ -7,7 +7,7 @@ using Govor.Application.Interfaces.Friends; using Govor.Application.Interfaces.Infrastructure.Extensions; using Govor.Contracts.DTOs; using Govor.Contracts.Responses.SignalR; -using Govor.Core.Models; +using Govor.Domain.Models; using Microsoft.AspNetCore.SignalR; using Microsoft.Extensions.Logging; using Moq; diff --git a/Govor.API.Tests/IntegrationTests/Hubs/Infrastructure/PrivateChatGroupManagerTests.cs b/Govor.API.Tests/IntegrationTests/Hubs/Infrastructure/PrivateChatGroupManagerTests.cs index bf931f4..57c69cc 100644 --- a/Govor.API.Tests/IntegrationTests/Hubs/Infrastructure/PrivateChatGroupManagerTests.cs +++ b/Govor.API.Tests/IntegrationTests/Hubs/Infrastructure/PrivateChatGroupManagerTests.cs @@ -1,7 +1,8 @@ using Govor.API.Hubs; using Govor.API.Hubs.Infrastructure; +using Govor.Application.Infrastructure.Extensions; using Govor.Application.Interfaces; -using Govor.Core.Models; +using Govor.Domain.Models; using Microsoft.AspNetCore.SignalR; using Moq; diff --git a/Govor.API.Tests/LocalStorageServiceTests.cs b/Govor.API.Tests/LocalStorageServiceTests.cs index aff7ac8..f6be86e 100644 --- a/Govor.API.Tests/LocalStorageServiceTests.cs +++ b/Govor.API.Tests/LocalStorageServiceTests.cs @@ -1,6 +1,5 @@ using AutoFixture; using Govor.Application.Interfaces; -using Govor.Application.Services; using Microsoft.AspNetCore.Hosting; using Moq; diff --git a/Govor.API.Tests/UnitTests/Infrastructure/Validators/ChatGroupValidatorTests.cs b/Govor.API.Tests/UnitTests/Infrastructure/Validators/ChatGroupValidatorTests.cs index 42986c0..57a0afe 100644 --- a/Govor.API.Tests/UnitTests/Infrastructure/Validators/ChatGroupValidatorTests.cs +++ b/Govor.API.Tests/UnitTests/Infrastructure/Validators/ChatGroupValidatorTests.cs @@ -1,6 +1,6 @@ using AutoFixture; -using Govor.Core.Infrastructure.Validators; -using Govor.Core.Models; +using Govor.Domain.Common.Constants; +using Govor.Domain.Models; namespace Govor.API.Tests.UnitTests.Infrastructure.Validators; diff --git a/Govor.API.Tests/UnitTests/Infrastructure/Validators/FriendshipValidatorTests.cs b/Govor.API.Tests/UnitTests/Infrastructure/Validators/FriendshipValidatorTests.cs index 2b49311..5d8bf0a 100644 --- a/Govor.API.Tests/UnitTests/Infrastructure/Validators/FriendshipValidatorTests.cs +++ b/Govor.API.Tests/UnitTests/Infrastructure/Validators/FriendshipValidatorTests.cs @@ -1,6 +1,6 @@ using AutoFixture; -using Govor.Core.Infrastructure.Validators; -using Govor.Core.Models; +using Govor.Domain.Common.Constants; +using Govor.Domain.Models; namespace Govor.API.Tests.UnitTests.Infrastructure.Validators; diff --git a/Govor.API.Tests/UnitTests/Infrastructure/Validators/InvitationValidatorTests.cs b/Govor.API.Tests/UnitTests/Infrastructure/Validators/InvitationConstantsTests.cs similarity index 94% rename from Govor.API.Tests/UnitTests/Infrastructure/Validators/InvitationValidatorTests.cs rename to Govor.API.Tests/UnitTests/Infrastructure/Validators/InvitationConstantsTests.cs index 38a7775..bb787f7 100644 --- a/Govor.API.Tests/UnitTests/Infrastructure/Validators/InvitationValidatorTests.cs +++ b/Govor.API.Tests/UnitTests/Infrastructure/Validators/InvitationConstantsTests.cs @@ -1,18 +1,18 @@ using AutoFixture; -using Govor.Core.Infrastructure.Validators; -using Govor.Core.Models; +using Govor.Domain.Common.Constants; +using Govor.Domain.Models; namespace Govor.API.Tests.UnitTests.Infrastructure.Validators; [TestFixture] -public class InvitationValidatorTests +public class InvitationConstantsTests { private IObjectValidator _messageValidator; private Fixture _fixture; - public InvitationValidatorTests() + public InvitationConstantsTests() { - _messageValidator = new InvitationValidator(); + _messageValidator = new InvitationConstants(); _fixture = new Fixture(); diff --git a/Govor.API.Tests/UnitTests/Infrastructure/Validators/MessageValidatorTests.cs b/Govor.API.Tests/UnitTests/Infrastructure/Validators/MessageValidatorTests.cs index 8472243..aa9fb94 100644 --- a/Govor.API.Tests/UnitTests/Infrastructure/Validators/MessageValidatorTests.cs +++ b/Govor.API.Tests/UnitTests/Infrastructure/Validators/MessageValidatorTests.cs @@ -1,7 +1,7 @@ using AutoFixture; -using Govor.Core.Infrastructure.Validators; -using Govor.Core.Models; -using Govor.Core.Models.Messages; +using Govor.Domain.Common.Constants; +using Govor.Domain.Models; +using Govor.Domain.Models.Messages; namespace Govor.API.Tests.UnitTests.Infrastructure.Validators; diff --git a/Govor.API.Tests/UnitTests/Infrastructure/Validators/PrivateChatValidatorTests.cs b/Govor.API.Tests/UnitTests/Infrastructure/Validators/PrivateChatValidatorTests.cs index 43d54d1..f38c98e 100644 --- a/Govor.API.Tests/UnitTests/Infrastructure/Validators/PrivateChatValidatorTests.cs +++ b/Govor.API.Tests/UnitTests/Infrastructure/Validators/PrivateChatValidatorTests.cs @@ -1,6 +1,6 @@ using AutoFixture; -using Govor.Core.Infrastructure.Validators; -using Govor.Core.Models; +using Govor.Domain.Common.Constants; +using Govor.Domain.Models; namespace Govor.API.Tests.UnitTests.Infrastructure.Validators; diff --git a/Govor.API.Tests/UnitTests/Infrastructure/Validators/UserValidatorTests.cs b/Govor.API.Tests/UnitTests/Infrastructure/Validators/UserConstantsTests.cs similarity index 96% rename from Govor.API.Tests/UnitTests/Infrastructure/Validators/UserValidatorTests.cs rename to Govor.API.Tests/UnitTests/Infrastructure/Validators/UserConstantsTests.cs index c7d9162..487d1ec 100644 --- a/Govor.API.Tests/UnitTests/Infrastructure/Validators/UserValidatorTests.cs +++ b/Govor.API.Tests/UnitTests/Infrastructure/Validators/UserConstantsTests.cs @@ -1,12 +1,12 @@ using AutoFixture; -using Govor.Core.Infrastructure.Validators; -using Govor.Core.Models; -using Govor.Core.Models.Users; +using Govor.Domain.Common.Constants; +using Govor.Domain.Models; +using Govor.Domain.Models.Users; namespace Govor.API.Tests.UnitTests.Infrastructure.Validators; [TestFixture] -public class UserValidatorTests +public class UserConstantsTests { private IObjectValidator _userValidator; private Fixture _fixture; @@ -14,7 +14,7 @@ public class UserValidatorTests [SetUp] public void SetUp() { - _userValidator = new UserValidator(); + _userValidator = new UserConstants(); _fixture = new Fixture(); diff --git a/Govor.API/Common/Extensions/AddOptionExtensions.cs b/Govor.API/Common/Extensions/AddOptionExtensions.cs index 060de2b..b31b5cf 100644 --- a/Govor.API/Common/Extensions/AddOptionExtensions.cs +++ b/Govor.API/Common/Extensions/AddOptionExtensions.cs @@ -1,4 +1,4 @@ -using Govor.Application.Services.Authentication; +using Govor.Application.Authentication.JWT; namespace Govor.API.Common.Extensions; diff --git a/Govor.API/Common/Extensions/ConfigurationProgramExtensions.cs b/Govor.API/Common/Extensions/ConfigurationProgramExtensions.cs index 6de6259..f79650d 100644 --- a/Govor.API/Common/Extensions/ConfigurationProgramExtensions.cs +++ b/Govor.API/Common/Extensions/ConfigurationProgramExtensions.cs @@ -1,46 +1,27 @@ using Govor.API.Common.Mapping; using Govor.API.Common.SignalR.Helpers; using Govor.API.Hubs.Infrastructure; +using Govor.Application.Authentication; +using Govor.Application.Authentication.JWT; +using Govor.Application.Friends; +using Govor.Application.Groups; using Govor.Application.Infrastructure.AdminsStuff; using Govor.Application.Infrastructure.Extensions; using Govor.Application.Infrastructure.Validators; -using Govor.Application.Interfaces; -using Govor.Application.Interfaces.Authentication; -using Govor.Application.Interfaces.Friends; -using Govor.Application.Interfaces.Infrastructure.Extensions; -using Govor.Application.Interfaces.Medias; -using Govor.Application.Interfaces.Messages; -using Govor.Application.Interfaces.PushNotifications; -using Govor.Application.Interfaces.UserOnlineStatus; -using Govor.Application.Interfaces.UserSession; -using Govor.Application.Interfaces.UserSession.Crypto; -using Govor.Application.Services; -using Govor.Application.Services.Authentication; -using Govor.Application.Services.Friends; -using Govor.Application.Services.Medias; -using Govor.Application.Services.Messages; -using Govor.Application.Services.PushNotifications; -using Govor.Application.Services.PushNotifications.Providers; -using Govor.Application.Services.UserOnlineStatus; -using Govor.Application.Services.UserSessions; -using Govor.Application.Services.UserSessions.Crypto; -using Govor.Core.Infrastructure.Extensions; -using Govor.Core.Infrastructure.Validators; -using Govor.Core.Models; -using Govor.Core.Models.Messages; -using Govor.Core.Models.Users; -using Govor.Core.Repositories.Admins; -using Govor.Core.Repositories.Friendships; -using Govor.Core.Repositories.Groups; -using Govor.Core.Repositories.Invaites; -using Govor.Core.Repositories.MediasAttachments; -using Govor.Core.Repositories.Messages; -using Govor.Core.Repositories.PrivateChats; -using Govor.Core.Repositories.PushTokens; -using Govor.Core.Repositories.Users; -using Govor.Core.Repositories.UserSessionsRepository; -using Govor.Data; -using Govor.Data.Repositories; +using Govor.Application.Medias; +using Govor.Application.Messages; +using Govor.Application.PingHandler; +using Govor.Application.PrivateUserChats; +using Govor.Application.Profiles; +using Govor.Application.PushNotifications; +using Govor.Application.PushNotifications.Providers; +using Govor.Application.Storage; +using Govor.Application.Synching; +using Govor.Application.Users; +using Govor.Application.Users.UserOnlineStatus; +using Govor.Application.Users.UserSessions; +using Govor.Application.Users.UserSessions.Crypto; +using Govor.Domain; using Microsoft.EntityFrameworkCore; namespace Govor.API.Common.Extensions; @@ -56,6 +37,7 @@ public static class ConfigurationProgramExtensions services.AddScoped(); services.AddScoped(); services.AddScoped(); + services.AddScoped(); services.AddScoped(); services.AddScoped(); @@ -80,7 +62,10 @@ public static class ConfigurationProgramExtensions services.AddScoped(); - services.AddScoped(); + //services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); @@ -88,6 +73,9 @@ public static class ConfigurationProgramExtensions services.AddScoped(); services.AddScoped(); + // User + services.AddScoped(); + // UserSession services.AddScoped(); services.AddScoped(); @@ -104,6 +92,7 @@ public static class ConfigurationProgramExtensions services.AddSingleton(); // Pushs + services.AddScoped(); services.AddScoped(); services.AddSingleton(); @@ -122,34 +111,7 @@ public static class ConfigurationProgramExtensions services.AddScoped(); } - - public static void AddRepositories(this IServiceCollection services) - { - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - // other - } - - public static void AddValidators(this IServiceCollection services) - { - services.AddScoped, UserValidator>(); - services.AddScoped, MessageValidator>(); - services.AddScoped, MediaAttachmentsValidator>(); - services.AddScoped, AdminValidator>(); - services.AddScoped, InvitationValidator>(); - services.AddScoped, FriendshipValidator>(); - services.AddScoped, PrivateChatValidator>(); - services.AddScoped, ChatGroupValidator>(); - } - + public static void AddGovorDbContext(this IServiceCollection services, IConfiguration configuration) { var useMySql = configuration.GetValue("UseMySql"); diff --git a/Govor.API/Common/Mapping/MappingProfile.cs b/Govor.API/Common/Mapping/MappingProfile.cs index 4ad619d..0921426 100644 --- a/Govor.API/Common/Mapping/MappingProfile.cs +++ b/Govor.API/Common/Mapping/MappingProfile.cs @@ -1,11 +1,10 @@ using AutoMapper; -using Govor.API.Extensions.Mapping; using Govor.Application.Profiles; using Govor.Contracts.DTOs; using Govor.Contracts.Responses; -using Govor.Core.Models; -using Govor.Core.Models.Messages; -using Govor.Core.Models.Users; +using Govor.Domain.Models; +using Govor.Domain.Models.Messages; +using Govor.Domain.Models.Users; namespace Govor.API.Common.Mapping; diff --git a/Govor.API/Common/Mapping/UserProfileToUserProfileDtoMappingAction.cs b/Govor.API/Common/Mapping/UserProfileToUserProfileDtoMappingAction.cs index 2a7be87..01d57e1 100644 --- a/Govor.API/Common/Mapping/UserProfileToUserProfileDtoMappingAction.cs +++ b/Govor.API/Common/Mapping/UserProfileToUserProfileDtoMappingAction.cs @@ -1,8 +1,7 @@ using AutoMapper; -using Govor.Application.Interfaces.UserOnlineStatus; using Govor.Application.Profiles; +using Govor.Application.Users.UserOnlineStatus; using Govor.Contracts.DTOs; -using Govor.Core.Models.Users; namespace Govor.API.Common.Mapping; diff --git a/Govor.API/Common/Mapping/UserToUserDtoMappingAction.cs b/Govor.API/Common/Mapping/UserToUserDtoMappingAction.cs index c915fb3..c90ee9b 100644 --- a/Govor.API/Common/Mapping/UserToUserDtoMappingAction.cs +++ b/Govor.API/Common/Mapping/UserToUserDtoMappingAction.cs @@ -1,9 +1,9 @@ using AutoMapper; -using Govor.Application.Interfaces.UserOnlineStatus; +using Govor.Application.Users.UserOnlineStatus; using Govor.Contracts.DTOs; -using Govor.Core.Models.Users; +using Govor.Domain.Models.Users; -namespace Govor.API.Extensions.Mapping; +namespace Govor.API.Common.Mapping; public class UserToUserDtoMappingAction : IMappingAction { diff --git a/Govor.API/Controllers/AdminStuff/FriendshipsController.cs b/Govor.API/Controllers/AdminStuff/FriendshipsController.cs index 94b5225..2a0e85b 100644 --- a/Govor.API/Controllers/AdminStuff/FriendshipsController.cs +++ b/Govor.API/Controllers/AdminStuff/FriendshipsController.cs @@ -1,8 +1,3 @@ -using Govor.Contracts.DTOs; -using Govor.Core.Models; -using Govor.Core.Models.Users; -using Govor.Core.Repositories.Friendships; -using Govor.Data.Repositories.Exceptions; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; @@ -14,14 +9,8 @@ namespace Govor.API.Controllers.AdminStuff; public class FriendshipsController : Controller { private readonly ILogger _logger; - private readonly IFriendshipsRepository _friendshipsRepository; - public FriendshipsController(ILogger logger, IFriendshipsRepository friendshipsRepository) - { - _logger = logger; - _friendshipsRepository = friendshipsRepository; - } - + /* [HttpGet] public async Task Get() { @@ -88,5 +77,5 @@ public class FriendshipsController : Controller _logger.LogError(ex, ex.Message); return StatusCode(500, new { error = "Internal server error." }); } - } + }*/ } \ No newline at end of file diff --git a/Govor.API/Controllers/AdminStuff/InviteUserController.cs b/Govor.API/Controllers/AdminStuff/InviteUserController.cs index 204ae79..d55043f 100644 --- a/Govor.API/Controllers/AdminStuff/InviteUserController.cs +++ b/Govor.API/Controllers/AdminStuff/InviteUserController.cs @@ -1,8 +1,6 @@ -using Govor.Application.Interfaces; +using Govor.Application.Infrastructure.AdminsStuff; using Govor.Contracts.DTOs; using Govor.Contracts.Requests; -using Govor.Core.Repositories.Invaites; -using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; namespace Govor.API.Controllers.AdminStuff; @@ -12,17 +10,17 @@ namespace Govor.API.Controllers.AdminStuff; //[Authorize(Roles = "Admin")] public class InviteUserController : Controller { - private readonly IInvitesRepository _repository; + private readonly IInvitationGetter _invitationGetter; private readonly IInvitationGenerator _invitationGenerator; private readonly ILogger _logger; public InviteUserController(IInvitationGenerator invitationGenerator, - IInvitesRepository repository, + IInvitationGetter invitationGetter, ILogger logger) { _invitationGenerator = invitationGenerator; _logger = logger; - _repository = repository; + _invitationGetter = invitationGetter; } [HttpPost("[action]")] @@ -51,7 +49,7 @@ public class InviteUserController : Controller { _logger.LogInformation("Getting all active invitations by administrator"); - var read = await _repository.GetAllAsync(); + var read = await _invitationGetter.GetAllAsync(); var result = read.Where(x => x.IsActive).ToList(); List dtos = new List(); @@ -86,7 +84,7 @@ public class InviteUserController : Controller try { _logger.LogInformation("Getting all invitations by administrator"); - var read = await _repository.GetAllAsync(); + var read = await _invitationGetter.GetAllAsync(); List dtos = new List(); @@ -120,18 +118,22 @@ public class InviteUserController : Controller try { _logger.LogInformation("Getting invitations {id} by administrator"); - var read = await _repository.FindByIdAsync(id); + var read = await _invitationGetter.FindByIdAsync(id); + + if(read.IsFailure) + return NotFound(read.Error); + var dto = read.Value; var response = new InvitationResponses(){ - Id = read.Id, - Description = read.Description, - IsAdmin = read.IsAdmin, - MaxParticipants = read.MaxParticipants, - Code = read.Code, - CreatedAt = read.DateCreated, - EndAt = read.EndDate, - IsActive = read.IsActive, - ParticipantCount = read.Users.Count, + Id = dto.Id, + Description = dto.Description, + IsAdmin = dto.IsAdmin, + MaxParticipants = dto.MaxParticipants, + Code = dto.Code, + CreatedAt = dto.DateCreated, + EndAt = dto.EndDate, + IsActive = dto.IsActive, + ParticipantCount = dto.Users.Count, }; return Ok(response); diff --git a/Govor.API/Controllers/AdminStuff/UsersController.cs b/Govor.API/Controllers/AdminStuff/UsersController.cs index 7440264..0a60b3d 100644 --- a/Govor.API/Controllers/AdminStuff/UsersController.cs +++ b/Govor.API/Controllers/AdminStuff/UsersController.cs @@ -1,10 +1,7 @@ -using Govor.Application.Interfaces; +using Govor.Application.Infrastructure.AdminsStuff; using Govor.Contracts.Responses.Admins; -using Govor.Core.Infrastructure.Extensions; -using Govor.Core.Models.Users; -using Govor.Data.Repositories.Exceptions; +using Govor.Domain.Models.Users; using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; namespace Govor.API.Controllers.AdminStuff; @@ -54,11 +51,6 @@ public class UsersController : Controller var read = await _users.GetUserById(id); return Ok(BuildUserDtos([read]).First()); } - catch (NotFoundByKeyException ex) - { - _logger.LogWarning(ex, ex.Message); - return NotFound(ex.Message); - } catch (Exception e) { _logger.LogError(e, e.Message); diff --git a/Govor.API/Controllers/Authentication/AuthController.cs b/Govor.API/Controllers/Authentication/AuthController.cs index 897803f..f1c7fa8 100644 --- a/Govor.API/Controllers/Authentication/AuthController.cs +++ b/Govor.API/Controllers/Authentication/AuthController.cs @@ -1,7 +1,6 @@ -using Govor.Application.Exceptions.AuthService; -using Govor.Application.Exceptions.InvitesService; -using Govor.Application.Interfaces.Authentication; -using Govor.Application.Interfaces.UserSession; +using Govor.Application.Authentication; +using Govor.Application.Authentication.Exceptions; +using Govor.Application.Users.UserSessions; using Govor.Contracts.Requests; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; @@ -29,83 +28,84 @@ public class AuthController : Controller _invitesService = invitesService; _logger = logger; } - - //[RequireHttps] - [HttpPost("register")]// api/auth/register + + [HttpPost("register")] // api/auth/register public async Task Register([FromBody] RegistrationRequest registrationRequest) { - try + + var inviteResult = await _invitesService.ValidateAsync(registrationRequest.InviteLink); + if (!inviteResult.IsSuccess) { - if (!ModelState.IsValid) - return BadRequest(ModelState); + _logger.LogWarning("Invite link invalid: {InviteLink}. Error: {Error}", registrationRequest.InviteLink, + inviteResult.Error); + return BadRequest($"Invite link invalid: {inviteResult.Error.Message}"); + } + + var userResult = await _accountService.RegistrationAsync( + registrationRequest.Name, + registrationRequest.Password, + inviteResult.Value); - var invite = await _invitesService.ValidateAsync(registrationRequest.InviteLink); + if (userResult.IsFailure) + { + _logger.LogWarning("Registration failed for user {Name}. Error: {Error}", registrationRequest.Name, + userResult.Error); + + return userResult.Error.Code switch + { + nameof(UserAlreadyExistException) => BadRequest($"Registration failed: {userResult.Error.Message}"), + nameof(InvalidUsernameException) => BadRequest($"Invalid username: {userResult.Error.Message}"), + _ => BadRequest($"Registration failed: {userResult.Error.Message}") + }; + } - var user = await _accountService.RegistrationAsync(registrationRequest.Name, registrationRequest.Password, - invite); - - _logger.LogInformation($"Register request for {user.Username} with id {user.Id} processed successfully"); + var user = userResult.Value; + _logger.LogInformation("Register request for {Username} with id {Id} processed successfully", user.Username, + user.Id); + + var sessionResult = await _userSession.OpenSessionAsync(user, registrationRequest.DeviceInfo); + if (sessionResult.IsFailure) + { + _logger.LogError("Failed to open session for user {Username}. Error: {Error}", user.Username, + sessionResult.Error.Message); + return StatusCode(500, "An error occurred while creating the session."); + } - var tokens = await _userSession.OpenSessionAsync(user, registrationRequest.DeviceInfo); - - _logger.LogInformation($"Session for user {user.Username} with id {user.Id} has been opened"); - - return Ok(tokens); - } - catch (UserAlreadyExistException ex) - { - _logger.LogWarning(ex, $"Registration failed for user {registrationRequest.Name}"); - return BadRequest("Registration failed: user already exists."); - } - catch (InviteLinkInvalidException ex) - { - _logger.LogWarning(ex, $"Invite link invalid: {registrationRequest.InviteLink}"); - return BadRequest("Invite link invalid."); - } - catch (InvalidUsernameException ex) - { - _logger.LogWarning(ex, $"Invalid username: {registrationRequest.Name}"); - return BadRequest($"Invalid username: {ex.Message}"); - } - catch (Exception ex) - { - _logger.LogError(ex, "Unexpected error during registration for user {Name}", registrationRequest.Name); - return StatusCode(500, "An unexpected error occurred. Please try again later."); - } + _logger.LogInformation("Session for user {Username} with id {Id} has been opened", user.Username, user.Id); + return Ok(sessionResult.Value); } + - //[RequireHttps] - [HttpPost("login")]// api/auth/login + [HttpPost("login")] // api/auth/login public async Task Login([FromBody] LoginRequest loginRequest) { - try + var userResult = await _accountService.LoginAsync(loginRequest.Name, loginRequest.Password); + + if (userResult.IsFailure) { - if (!ModelState.IsValid) - return BadRequest(ModelState); - - var user = await _accountService.LoginAsync(loginRequest.Name, loginRequest.Password); - _logger.LogInformation($"Login request for {user.Username} with id {user.Id} processed successfully"); + _logger.LogWarning("Login failed for user {Name}. Error: {Code}", loginRequest.Name, userResult.Error); - var tokens = await _userSession.OpenSessionAsync(user, loginRequest.DeviceInfo); - - _logger.LogInformation($"Session for user {user.Username} with id {user.Id} has been opened"); - - return Ok(tokens); + return userResult.Error.Code switch + { + nameof(UserNotRegisteredException) => BadRequest("Login failed: user does not exist."), + nameof(InvalidOperationException) => BadRequest("Login failed: username or password is incorrect."), + _ => BadRequest($"Login failed: {userResult.Error.Message}") + }; } - catch (UserNotRegisteredException ex) + + var user = userResult.Value; + _logger.LogInformation("Login request for {Username} with id {Id} processed successfully", user.Username, user.Id); + + var sessionResult = await _userSession.OpenSessionAsync(user, loginRequest.DeviceInfo); + + if (sessionResult.IsFailure) { - _logger.LogWarning(ex, "Login failed for user {Name}", loginRequest.Name); - return BadRequest("Login failed: user does not exist."); - } - catch (LoginUserException ex) - { - _logger.LogWarning(ex, "Login failed for user {Name}", loginRequest.Name); - return BadRequest("Login failed: username or password is incorrect."); - } - catch (Exception ex) - { - _logger.LogError(ex, "Unexpected error during login for user {Name}", loginRequest.Name); - return StatusCode(500, "An unexpected error occurred. Please try again later."); + _logger.LogError("Failed to open session for user {Username}. Error: {Error}", user.Username, sessionResult.Error); + return StatusCode(500, "An error occurred while creating the session."); } + + _logger.LogInformation("Session for user {Username} with id {Id} has been opened", user.Username, user.Id); + + return Ok(sessionResult.Value); } } \ No newline at end of file diff --git a/Govor.API/Controllers/Authentication/RefreshController.cs b/Govor.API/Controllers/Authentication/RefreshController.cs index ebf95c1..68e81fd 100644 --- a/Govor.API/Controllers/Authentication/RefreshController.cs +++ b/Govor.API/Controllers/Authentication/RefreshController.cs @@ -1,4 +1,4 @@ -using Govor.Application.Interfaces.UserSession; +using Govor.Application.Users.UserSessions; using Govor.Contracts.Requests; using Govor.Contracts.Responses; using Microsoft.AspNetCore.Authorization; @@ -13,7 +13,7 @@ public class RefreshController : Controller { private readonly ILogger _logger; private readonly IUserSessionRefresher _userSession; - + public RefreshController( ILogger logger, IUserSessionRefresher userSession) @@ -21,41 +21,35 @@ public class RefreshController : Controller _logger = logger; _userSession = userSession; } - + //[RequireHttps] [HttpPost("refresh")] // api/auth/token/refresh public async Task Refresh([FromBody] RefreshTokenRequest refreshRequest) { - try + if (string.IsNullOrWhiteSpace(refreshRequest.RefreshToken)) { - if (!ModelState.IsValid) - return BadRequest(ModelState); - - if (string.IsNullOrEmpty(refreshRequest.RefreshToken)) - throw new InvalidOperationException("Refresh token cant be empty."); - - var result = await _userSession.RefreshTokenAsync(refreshRequest.RefreshToken); + _logger.LogWarning("Refresh request failed: token is empty."); + return BadRequest("Refresh token can't be empty."); + } + + var result = await _userSession.RefreshTokenAsync(refreshRequest.RefreshToken); - return Ok(new RefreshTokenResponse() - { - AccessToken = result.accessToken, - RefreshToken = result.refreshToken - }); - } - catch (InvalidOperationException ex) + if (result.IsFailure) { - _logger.LogWarning(ex, "Invalid refresh token."); - return BadRequest(ex.Message); + _logger.LogWarning("Refresh token failed. Error Code: {Code}", result.Error.Code); + + return result.Error.Code switch + { + "Auth.EmptyToken" => BadRequest(result.Error.Message), + "Auth.InvalidToken" => Unauthorized(result.Error.Message), + _ => BadRequest($"Refresh failed: {result.Error.Message}") + }; } - catch (UnauthorizedAccessException ex) + + return Ok(new RefreshTokenResponse { - _logger.LogWarning(ex, "Refresh token failed."); - return Unauthorized("Invalid refresh token"); - } - catch (Exception ex) - { - _logger.LogError(ex, ex.Message); - return StatusCode(500, "An unexpected error occurred."); - } + AccessToken = result.Value.accessToken, + RefreshToken = result.Value.refreshToken + }); } } \ No newline at end of file diff --git a/Govor.API/Controllers/Authentication/SessionKeysController.cs b/Govor.API/Controllers/Authentication/SessionKeysController.cs index 77929ec..4f6558e 100644 --- a/Govor.API/Controllers/Authentication/SessionKeysController.cs +++ b/Govor.API/Controllers/Authentication/SessionKeysController.cs @@ -1,7 +1,6 @@ -using Govor.Application.Interfaces.Friends; -using Govor.Application.Interfaces.Infrastructure.Extensions; -using Govor.Application.Interfaces.UserSession; -using Govor.Application.Interfaces.UserSession.Crypto; +using Govor.Application.Friends; +using Govor.Application.Infrastructure.Extensions; +using Govor.Application.Users.UserSessions.Crypto; using Govor.Contracts.Requests; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; diff --git a/Govor.API/Controllers/ChatLoadController.cs b/Govor.API/Controllers/ChatLoadController.cs index e4be8b9..550a8ce 100644 --- a/Govor.API/Controllers/ChatLoadController.cs +++ b/Govor.API/Controllers/ChatLoadController.cs @@ -1,9 +1,8 @@ using AutoMapper; -using Govor.Application.Interfaces; -using Govor.Application.Interfaces.Infrastructure.Extensions; +using Govor.Application.Infrastructure.Extensions; +using Govor.Application.Messages; using Govor.Contracts.Requests; using Govor.Contracts.Responses; -using Govor.Data.Repositories.Exceptions; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; @@ -52,16 +51,6 @@ public class ChatLoadController : Controller return Ok(response); } - catch (UnauthorizedAccessException ex) - { - _logger.LogWarning(ex.Message); - return Forbid(ex.Message); - } - catch (NotFoundException ex) - { - _logger.LogWarning(ex, ex.Message); - return BadRequest(ex.Message); - } catch (ArgumentException ex) { _logger.LogWarning(ex, ex.Message); @@ -95,21 +84,6 @@ public class ChatLoadController : Controller return Ok(response); } - catch (InvalidOperationException ex) - { - _logger.LogWarning(ex, ex.Message); - return BadRequest(ex.Message); - } - catch (UnauthorizedAccessException ex) - { - _logger.LogWarning(ex.Message); - return Forbid(ex.Message); - } - catch (NotFoundException ex) - { - _logger.LogWarning(ex, ex.Message); - return BadRequest(ex.Message); - } catch (ArgumentException ex) { _logger.LogWarning(ex, ex.Message); diff --git a/Govor.API/Controllers/Friends/FriendsRequestQueryController.cs b/Govor.API/Controllers/Friends/FriendsRequestQueryController.cs index 542ee89..2d1d367 100644 --- a/Govor.API/Controllers/Friends/FriendsRequestQueryController.cs +++ b/Govor.API/Controllers/Friends/FriendsRequestQueryController.cs @@ -1,8 +1,7 @@ using AutoMapper; -using Govor.Application.Interfaces.Friends; -using Govor.Application.Interfaces.Infrastructure.Extensions; +using Govor.Application.Friends; +using Govor.Application.Infrastructure.Extensions; using Govor.Contracts.DTOs; -using Govor.Core.Models; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; @@ -41,16 +40,6 @@ public class FriendsRequestQueryController : Controller return Ok(response); } - catch (InvalidOperationException ex) - { - _logger.LogWarning(ex, ex.Message); - return Ok(new List()); - } - catch (UnauthorizedAccessException ex) - { - _logger.LogWarning(ex, ex.Message); - return Forbid(ex.Message); - } catch (Exception ex) { _logger.LogError(ex, ex.Message); @@ -72,16 +61,6 @@ public class FriendsRequestQueryController : Controller return Ok(response); } - catch (InvalidOperationException ex) - { - _logger.LogWarning(ex, ex.Message); - return Ok(new List()); - } - catch (UnauthorizedAccessException ex) - { - _logger.LogWarning(ex, ex.Message); - return Forbid(ex.Message); - } catch (Exception ex) { _logger.LogError(ex, ex.Message); diff --git a/Govor.API/Controllers/Friends/FriendshipController.cs b/Govor.API/Controllers/Friends/FriendshipController.cs index 25c0065..d375717 100644 --- a/Govor.API/Controllers/Friends/FriendshipController.cs +++ b/Govor.API/Controllers/Friends/FriendshipController.cs @@ -1,9 +1,7 @@ using AutoMapper; -using Govor.Application.Exceptions.FriendsService; -using Govor.Application.Interfaces.Friends; -using Govor.Application.Interfaces.Infrastructure.Extensions; +using Govor.Application.Friends; +using Govor.Application.Infrastructure.Extensions; using Govor.Contracts.DTOs; -using Govor.Core.Models.Users; using Microsoft.AspNetCore.Mvc; namespace Govor.API.Controllers.Friends; diff --git a/Govor.API/Controllers/InviteController.cs b/Govor.API/Controllers/InviteController.cs index 26ff900..e7de645 100644 --- a/Govor.API/Controllers/InviteController.cs +++ b/Govor.API/Controllers/InviteController.cs @@ -1,5 +1,5 @@ -using Govor.Application.Interfaces; -using Govor.Application.Interfaces.Infrastructure.Extensions; +using Govor.Application.Groups; +using Govor.Application.Infrastructure.Extensions; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; diff --git a/Govor.API/Controllers/MediaController.cs b/Govor.API/Controllers/MediaController.cs index 6c0a870..d6ab259 100644 --- a/Govor.API/Controllers/MediaController.cs +++ b/Govor.API/Controllers/MediaController.cs @@ -1,7 +1,7 @@ -using Govor.Application.Interfaces.Infrastructure.Extensions; -using Govor.Application.Interfaces.Medias; +using Govor.Application.Infrastructure.Extensions; +using Govor.Application.Medias; using Govor.Contracts.Requests; -using Govor.Core.Models; +using Govor.Domain.Models; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; diff --git a/Govor.API/Controllers/OnlinePingingController.cs b/Govor.API/Controllers/OnlinePingingController.cs index 0a58dfc..001ce34 100644 --- a/Govor.API/Controllers/OnlinePingingController.cs +++ b/Govor.API/Controllers/OnlinePingingController.cs @@ -1,6 +1,6 @@ -using Govor.Application.Interfaces; -using Govor.Application.Interfaces.Infrastructure.Extensions; -using Govor.Application.Interfaces.UserOnlineStatus; +using Govor.Application.Infrastructure.Extensions; +using Govor.Application.PingHandler; +using Govor.Application.Users.UserOnlineStatus; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; @@ -40,16 +40,6 @@ public class OnlinePingingController : Controller _logger.LogInformation($"Ping from user {id} processed successfully"); return Ok(); } - catch (InvalidOperationException e) - { - _logger.LogError(e, e.Message); - return BadRequest("User can't be found in our database."); - } - catch (UnauthorizedAccessException e) - { - _logger.LogError(e, e.Message); - return Forbid(e.Message); - } catch (Exception e) { _logger.LogError(e, e.Message); diff --git a/Govor.API/Controllers/PrivateChatController.cs b/Govor.API/Controllers/PrivateChatController.cs index 7efc26f..da3873f 100644 --- a/Govor.API/Controllers/PrivateChatController.cs +++ b/Govor.API/Controllers/PrivateChatController.cs @@ -1,10 +1,9 @@ -using Govor.Application.Interfaces; -using Govor.Application.Interfaces.Infrastructure.Extensions; +using Govor.Application.Exceptions.VerifyFriendship; +using Govor.Application.Friends; +using Govor.Application.Infrastructure.AdminsStuff; +using Govor.Application.Infrastructure.Extensions; +using Govor.Application.PrivateUserChats; using Govor.Contracts.DTOs; -using Govor.Core.Models; -using Govor.Core.Repositories.PrivateChats; -using Govor.Core.Repositories.Users; -using Govor.Data.Repositories.Exceptions; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; @@ -16,7 +15,6 @@ namespace Govor.API.Controllers; public class PrivateChatController : Controller { private readonly ICurrentUserService _currentUser; - private readonly IUsersRepository _usersRepository; private readonly IVerifyFriendship _verifyFriendship; private readonly IUserPrivateChatsCreator _userPrivateChatsCreator; private readonly IUserPrivateChatsGetterService _privateChatsGetter; @@ -24,15 +22,12 @@ public class PrivateChatController : Controller public PrivateChatController( ICurrentUserService currentUser, - IUsersRepository usersRepository, IVerifyFriendship verifyFriendship, - IPrivateChatsRepository privateChats, IUserPrivateChatsCreator userPrivateChatsCreator, IUserPrivateChatsGetterService userPrivateChatsGetterService, ILogger logger) { _currentUser = currentUser; - _usersRepository = usersRepository; _verifyFriendship = verifyFriendship; _userPrivateChatsCreator = userPrivateChatsCreator; _privateChatsGetter = userPrivateChatsGetterService; @@ -46,14 +41,8 @@ public class PrivateChatController : Controller { var currentId = _currentUser.GetCurrentUserId(); - if (!await _usersRepository.ExistsByIdAsync(friendId)) - { - _logger.LogWarning("User not exist {0}", friendId); - return NotFound("User not exist."); - } - await _verifyFriendship.VerifyAsync(currentId, friendId); - + var chat = await _userPrivateChatsCreator.CreateAsync(currentId, friendId); return Ok(chat.Id); } @@ -62,16 +51,16 @@ public class PrivateChatController : Controller _logger.LogWarning(ex.Message); return Forbid(ex.Message); } - catch (NotFoundException ex) - { - _logger.LogWarning(ex, ex.Message); - return BadRequest(ex.Message); - } catch (ArgumentException ex) { _logger.LogWarning(ex, ex.Message); return BadRequest(ex.Message); } + catch (FriendshipException ex) + { + _logger.LogWarning(ex, ex.Message); + return Forbid(ex.Message); + } catch (Exception ex) { _logger.LogError(ex, ex.Message); diff --git a/Govor.API/Controllers/ProfileController.cs b/Govor.API/Controllers/ProfileController.cs index a58f72e..0f45836 100644 --- a/Govor.API/Controllers/ProfileController.cs +++ b/Govor.API/Controllers/ProfileController.cs @@ -1,12 +1,11 @@ using AutoMapper; using Govor.API.Hubs; -using Govor.Application.Interfaces; -using Govor.Application.Interfaces.Infrastructure.Extensions; -using Govor.Application.Interfaces.Medias; +using Govor.Application.Infrastructure.Extensions; +using Govor.Application.Medias; +using Govor.Application.Profiles; using Govor.Contracts.DTOs; using Govor.Contracts.Requests; -using Govor.Core.Models; -using Govor.Data.Repositories.Exceptions; +using Govor.Domain.Models; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.SignalR; @@ -91,8 +90,12 @@ public class ProfileController : ControllerBase try { var userId = _currentUserService.GetCurrentUserId(); - var user = await _profileService.GetUserProfileAsync(userId); + var result = await _profileService.GetUserProfileAsync(userId); + if(result.IsFailure) + return NotFound(result.Error); + + var user = result.Value; var dto = _mapper.Map(user); return Ok(dto); } @@ -101,11 +104,6 @@ public class ProfileController : ControllerBase _logger.LogWarning(ex.Message); return Forbid(ex.Message); } - catch (NotFoundException ex) - { - _logger.LogWarning(ex, ex.Message); - return NotFound("Profile not found"); - } catch (Exception ex) { _logger.LogError(ex, ex.Message); @@ -128,11 +126,6 @@ public class ProfileController : ControllerBase _logger.LogWarning(ex.Message); return Forbid(ex.Message); } - catch (NotFoundException ex) - { - _logger.LogWarning(ex, ex.Message); - return NotFound("Profile not found"); - } catch (Exception ex) { _logger.LogError(ex, ex.Message); diff --git a/Govor.API/Controllers/PushTokensController.cs b/Govor.API/Controllers/PushTokensController.cs index 9577d29..2b53ae4 100644 --- a/Govor.API/Controllers/PushTokensController.cs +++ b/Govor.API/Controllers/PushTokensController.cs @@ -1,6 +1,6 @@ -using Govor.Application.Interfaces.Infrastructure.Extensions; +using Govor.Application.Infrastructure.Extensions; +using Govor.Application.PushNotifications; using Govor.Contracts.Requests; -using Govor.Core.Repositories.PushTokens; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; @@ -13,15 +13,15 @@ public class PushTokensController : Controller { private readonly ICurrentUserService _currentUser; private readonly ICurrentUserSessionService _currentSession; - private readonly IPushTokenRepository _pushTokenRepo; + private readonly IPushTokenService _pushTokenService; public PushTokensController( + IPushTokenService pushTokenService, ICurrentUserService currentUser, - ICurrentUserSessionService currentSession, - IPushTokenRepository pushTokenRepository) + ICurrentUserSessionService currentSession) { + _pushTokenService = pushTokenService; _currentUser = currentUser; - _pushTokenRepo = pushTokenRepository; _currentSession = currentSession; } @@ -39,7 +39,7 @@ public class PushTokensController : Controller var currentId = _currentUser.GetCurrentUserId(); var currentSessionId = _currentSession.GetUserSessionId(); - await _pushTokenRepo.AddOrUpdateTokenAsync( + await _pushTokenService.AddOrUpdateTokenAsync( userId: currentId, sessionId: currentSessionId, token: req.Token, diff --git a/Govor.API/Controllers/SessionController.cs b/Govor.API/Controllers/SessionController.cs index f68b91b..7aacee4 100644 --- a/Govor.API/Controllers/SessionController.cs +++ b/Govor.API/Controllers/SessionController.cs @@ -1,9 +1,7 @@ using AutoMapper; -using Govor.Application.Interfaces.Infrastructure.Extensions; -using Govor.Application.Interfaces.UserSession; +using Govor.Application.Infrastructure.Extensions; +using Govor.Application.Users.UserSessions; using Govor.Contracts.DTOs; -using Govor.Core.Repositories.PushTokens; -using Govor.Data.Repositories.Exceptions; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; @@ -43,7 +41,11 @@ public class SessionController : Controller try { var sessions = await _userSessionReader.GetAllSessionsAsync(_currentUserService.GetCurrentUserId()); - return Ok(_mapper.Map>(sessions)); + + if(sessions.IsFailure) + return NotFound(sessions.Error); + + return Ok(_mapper.Map>(sessions.Value)); } catch (UnauthorizedAccessException ex) { @@ -65,8 +67,12 @@ public class SessionController : Controller if (sessionId == Guid.Empty) return BadRequest("Invalid sessionId."); - await _userSessionRevoker.CloseSessionByIdAsync(sessionId, + var res = await _userSessionRevoker.CloseSessionByIdAsync(sessionId, _currentUserService.GetCurrentUserId()); + + if (res.IsFailure) + return BadRequest(res.Error); + return Ok(); } catch (InvalidOperationException ex) @@ -79,11 +85,6 @@ public class SessionController : Controller _logger.LogWarning(ex, ex.Message); return Forbid(ex.Message); } - catch (NotFoundException ex) - { - _logger.LogWarning(ex, ex.Message); - return NotFound(ex.Message); - } catch (Exception ex) { _logger.LogError(ex, ex.Message); @@ -96,11 +97,14 @@ public class SessionController : Controller { try { - await _userSessionRevoker.CloseSessionByIdAsync( + var res = await _userSessionRevoker.CloseSessionByIdAsync( _currentUserSessionService.GetUserSessionId(), _currentUserService.GetCurrentUserId()); - - return Ok(); + + if(res.IsFailure) + return NotFound(res.Error); + + return Ok(); } catch (InvalidOperationException ex) { @@ -112,11 +116,6 @@ public class SessionController : Controller _logger.LogWarning(ex, ex.Message); return Forbid(ex.Message); } - catch (NotFoundException ex) - { - _logger.LogWarning(ex, ex.Message); - return NotFound(ex.Message); - } catch (Exception ex) { _logger.LogError(ex, ex.Message); @@ -129,7 +128,11 @@ public class SessionController : Controller { try { - await _userSessionRevoker.CloseAllSessionsAsync(_currentUserService.GetCurrentUserId()); + var res = await _userSessionRevoker.CloseAllSessionsAsync(_currentUserService.GetCurrentUserId()); + + if(res.IsFailure) + return NotFound(res.Error); + return Ok(); } catch (UnauthorizedAccessException ex) diff --git a/Govor.API/Filters/HubExceptionFilter.cs b/Govor.API/Filters/HubExceptionFilter.cs index fa814fb..f11b6ef 100644 --- a/Govor.API/Filters/HubExceptionFilter.cs +++ b/Govor.API/Filters/HubExceptionFilter.cs @@ -70,7 +70,6 @@ public class HubExceptionFilter : IHubFilter } } - // Ничего не возвращаем, если не поддерживается return null; } } \ No newline at end of file diff --git a/Govor.API/Govor.API.csproj b/Govor.API/Govor.API.csproj index 76f5525..c109986 100644 --- a/Govor.API/Govor.API.csproj +++ b/Govor.API/Govor.API.csproj @@ -24,10 +24,7 @@ - - - - + diff --git a/Govor.API/Hubs/ChatsHub.cs b/Govor.API/Hubs/ChatsHub.cs index e9136fa..02bb92c 100644 --- a/Govor.API/Hubs/ChatsHub.cs +++ b/Govor.API/Hubs/ChatsHub.cs @@ -1,11 +1,11 @@ using Govor.API.Common.SignalR.Helpers; using Govor.API.Hubs.Infrastructure; using Govor.Application.Exceptions.VerifyFriendship; -using Govor.Application.Interfaces.Messages; -using Govor.Application.Interfaces.Messages.Parameters; +using Govor.Application.Messages; +using Govor.Application.Messages.Parameters; using Govor.Contracts.Requests.SignalR; using Govor.Contracts.Responses.SignalR; -using Govor.Core.Models.Messages; +using Govor.Domain.Models.Messages; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.SignalR; @@ -15,20 +15,24 @@ namespace Govor.API.Hubs; public class ChatsHub : Hub { private readonly ILogger _logger; - private readonly IMessageCommandService _commandService; + private readonly IMessageSendingService _messageSendingService; + private readonly IMessageEditingService _messageEditingService; + private readonly IMessageRemovingService _messageRemovingService; private readonly IHubUserAccessor _userAccessor; private readonly IChatNotificationService _notifier; private readonly IConnectionManager _connectionManager; - public ChatsHub( - ILogger logger, - IMessageCommandService commandService, + + public ChatsHub(ILogger logger, + IMessageSendingService messageSendingService, + IMessageEditingService messageEditingService, IHubUserAccessor userAccessor, IChatNotificationService notifier, IConnectionManager connectionManager) { _logger = logger; - _commandService = commandService; + _messageSendingService = messageSendingService; + _messageEditingService = messageEditingService; _userAccessor = userAccessor; _notifier = notifier; _connectionManager = connectionManager; @@ -69,7 +73,7 @@ public class ChatsHub : Hub ValidateMessageRequest(request); var sendParams = MapToSendMessage(request, userId); - var result = await _commandService.SendMessageAsync(sendParams); + var result = await _messageSendingService.SendMessageAsync(sendParams); if (!result.IsSuccess) throw new InvalidOperationException(result.Exception.Message ?? "Failed to send message"); @@ -87,7 +91,7 @@ public class ChatsHub : Hub { return await SafeExecute(async (userId) => { - var result = await _commandService.DeleteMessageAsync(new DeleteMessage(userId, request.MessageId)); + var result = await _messageRemovingService.DeleteMessageAsync(new DeleteMessage(userId, request.MessageId)); if (!result.IsSuccess || result.OriginalMessage == null) throw new InvalidOperationException("Message deletion failed"); @@ -112,7 +116,7 @@ public class ChatsHub : Hub return await SafeExecute(async (userId) => { var editParams = new EditMessage(userId, request.MessageId, request.NewEncryptedContent, DateTime.UtcNow); - var result = await _commandService.EditMessageAsync(editParams); + var result = await _messageEditingService.EditMessageAsync(editParams); if (!result.IsSuccess || result.OriginalMessage == null) throw new InvalidOperationException("Edit message error"); diff --git a/Govor.API/Hubs/FriendsHub.cs b/Govor.API/Hubs/FriendsHub.cs index 87b1a36..9871926 100644 --- a/Govor.API/Hubs/FriendsHub.cs +++ b/Govor.API/Hubs/FriendsHub.cs @@ -1,7 +1,7 @@ using AutoMapper; using Govor.API.Common.SignalR.Helpers; using Govor.Application.Exceptions.FriendsService; -using Govor.Application.Interfaces.Friends; +using Govor.Application.Friends; using Govor.Contracts.DTOs; using Govor.Contracts.Responses.SignalR; using Microsoft.AspNetCore.SignalR; @@ -76,7 +76,12 @@ public class FriendsHub : Hub try { var userId = _userAccessor.GetUserId(Context); - var friendship = await _friendRequestService.SendAsync(userId, targetUserId); + var result = await _friendRequestService.SendAsync(userId, targetUserId); + + if(result.IsFailure) + return HubResult.Error(result.Error.ToString()); + + var friendship = result.Value; var dto = _mapper.Map(friendship); await Clients.Group(targetUserId.ToString()) @@ -115,7 +120,13 @@ public class FriendsHub : Hub try { var userId = _userAccessor.GetUserId(Context); - var friendship = await _friendRequestService.AcceptAsync(friendshipId, userId); + var result = await _friendRequestService.AcceptAsync(friendshipId, userId); + + if(result.IsFailure) + return HubResult.BadRequest(result.Error.ToString()); + + var friendship = result.Value; + var dto = _mapper.Map(friendship); await Clients.Group(userId.ToString()) @@ -149,7 +160,13 @@ public class FriendsHub : Hub try { var userId = _userAccessor.GetUserId(Context); - var friendship = await _friendRequestService.RejectAsync(friendshipId, userId); + var result = await _friendRequestService.RejectAsync(friendshipId, userId); + + if(result.IsFailure) + return HubResult.BadRequest(result.Error.ToString()); + + var friendship = result.Value; + var dto = _mapper.Map(friendship); await Clients.Group(userId.ToString()) diff --git a/Govor.API/Hubs/Infrastructure/ChatNotificationService.cs b/Govor.API/Hubs/Infrastructure/ChatNotificationService.cs index fa0cf3e..b9a2428 100644 --- a/Govor.API/Hubs/Infrastructure/ChatNotificationService.cs +++ b/Govor.API/Hubs/Infrastructure/ChatNotificationService.cs @@ -1,9 +1,8 @@ -using Govor.Application.Interfaces; -using Govor.Application.Interfaces.PushNotifications; +using Govor.Application.PrivateUserChats; +using Govor.Application.Profiles; +using Govor.Application.PushNotifications; using Govor.Contracts.Responses.SignalR; -using Govor.Core.Models.Messages; -using Govor.Core.Repositories.PrivateChats; -using Govor.Core.Repositories.PushTokens; +using Govor.Domain.Models.Messages; using Microsoft.AspNetCore.SignalR; namespace Govor.API.Hubs.Infrastructure; @@ -11,19 +10,20 @@ namespace Govor.API.Hubs.Infrastructure; public class ChatNotificationService : IChatNotificationService { private readonly IHubContext _hubContext; - private readonly IPrivateChatsRepository _privateChatsRepository; private readonly IPushNotificationService _notificationService; + private readonly IUserPrivateChatsGetterService _userPrivateChatsGetterService; private readonly IProfileService _profileService; + public ChatNotificationService( - IProfileService profileService, - IHubContext hubContext, + IHubContext hubContext, IPushNotificationService notificationService, - IPrivateChatsRepository privateChatsRepository) + IUserPrivateChatsGetterService userPrivateChatsGetterService, + IProfileService profileService) { _hubContext = hubContext; - _profileService = profileService; _notificationService = notificationService; - _privateChatsRepository = privateChatsRepository; + _userPrivateChatsGetterService = userPrivateChatsGetterService; + _profileService = profileService; } public async Task NotifyMessageSentAsync(UserMessageResponse message) @@ -47,12 +47,22 @@ public class ChatNotificationService : IChatNotificationService private async Task NotifyMessageReceivedInPrivateChatAsync(UserMessageResponse message) { - var privateChat = await _privateChatsRepository.GetByIdAsync(message.RecipientId); - + + var result = await _userPrivateChatsGetterService.GetPrivateChatAsync(message.RecipientId); + + if(result.IsFailure) + return; + var privateChat = result.Value; + var text = message.EncryptedContent.Substring(0, Math.Min(40, message.EncryptedContent.Length)); var userId = message.SenderId == privateChat.UserAId ? privateChat.UserBId : privateChat.UserAId; - var profile = await _profileService.GetUserProfileAsync(message.SenderId); + var resultProf = await _profileService.GetUserProfileAsync(message.SenderId); + + if(resultProf.IsFailure) + return; + var profile = resultProf.Value; + var title = profile.Username; Dictionary data = new Dictionary(); diff --git a/Govor.API/Hubs/Infrastructure/ConnectionManager.cs b/Govor.API/Hubs/Infrastructure/ConnectionManager.cs index e70b353..834a177 100644 --- a/Govor.API/Hubs/Infrastructure/ConnectionManager.cs +++ b/Govor.API/Hubs/Infrastructure/ConnectionManager.cs @@ -1,5 +1,8 @@ using System.Collections.Concurrent; +using Govor.Application.Groups; +using Govor.Application.Infrastructure.Extensions; using Govor.Application.Interfaces; +using Govor.Application.PrivateUserChats; using Microsoft.AspNetCore.SignalR; namespace Govor.API.Hubs.Infrastructure; diff --git a/Govor.API/Hubs/Infrastructure/ConnectionStore.cs b/Govor.API/Hubs/Infrastructure/ConnectionStore.cs index 3e93fa3..d6af509 100644 --- a/Govor.API/Hubs/Infrastructure/ConnectionStore.cs +++ b/Govor.API/Hubs/Infrastructure/ConnectionStore.cs @@ -1,5 +1,5 @@ using System.Collections.Concurrent; -using Govor.Application.Interfaces; +using Govor.Application.Infrastructure.Extensions; namespace Govor.API.Hubs.Infrastructure; diff --git a/Govor.API/Hubs/Infrastructure/PrivateChatGroupManager.cs b/Govor.API/Hubs/Infrastructure/PrivateChatGroupManager.cs index 16714ab..7939c1d 100644 --- a/Govor.API/Hubs/Infrastructure/PrivateChatGroupManager.cs +++ b/Govor.API/Hubs/Infrastructure/PrivateChatGroupManager.cs @@ -1,7 +1,9 @@ using Govor.API.Hubs; using Govor.API.Hubs.Infrastructure; +using Govor.Application.Infrastructure.Extensions; using Govor.Application.Interfaces; -using Govor.Core.Models; +using Govor.Application.PrivateUserChats; +using Govor.Domain.Models; using Microsoft.AspNetCore.SignalR; namespace Govor.API.Hubs.Infrastructure; diff --git a/Govor.API/Hubs/PresenceHub.cs b/Govor.API/Hubs/PresenceHub.cs index 33dadb6..60e825a 100644 --- a/Govor.API/Hubs/PresenceHub.cs +++ b/Govor.API/Hubs/PresenceHub.cs @@ -1,6 +1,5 @@ using Govor.API.Common.SignalR.Helpers; -using Govor.Application.Interfaces.UserOnlineStatus; -using Govor.Core.Repositories.Users; +using Govor.Application.Users.UserOnlineStatus; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.SignalR; @@ -15,17 +14,14 @@ public class PresenceHub : Hub private readonly IUserNotificationScopeService _scopeService; private readonly IOnlineUserStore _onlineUserStore; private readonly IHubUserAccessor _userAccessor; - private readonly IUsersRepository _users; public PresenceHub( ILogger logger, IUserNotificationScopeService scopeService, IOnlineUserStore onlineUserStore, - IHubUserAccessor userAccessor, - IUsersRepository users) + IHubUserAccessor userAccessor) { _logger = logger; - _users = users; _scopeService = scopeService; _onlineUserStore = onlineUserStore; _userAccessor = userAccessor; @@ -79,32 +75,9 @@ public class PresenceHub : Hub if (isLastConnection) { - _ = Task.Run(async () => - { - await Task.Delay(TimeSpan.FromSeconds(5)); - - var currentConnections = _onlineUserStore.GetConnections(userId); - if (currentConnections == null || !currentConnections.Any()) - { - var friends = await _scopeService.GetNotifiedUsers(userId); - await Clients.Groups(friends.Select(f => f.ToString()).ToList()) - .SendAsync("UserOffline", userId); - - try - { - var user = await _users.FindByIdAsync(userId); - if (user != null) - { - user.WasOnline = DateTime.UtcNow; - await _users.UpdateAsync(user); - } - } - catch (Exception ex) - { - _logger.LogError(ex, "Error updating WasOnline for {UserId}", userId); - } - } - }); + var friends = await _scopeService.GetNotifiedUsers(userId); + await Clients.Groups(friends.Select(f => f.ToString()).ToList()) + .SendAsync("UserOffline", userId); } await base.OnDisconnectedAsync(exception); diff --git a/Govor.API/Hubs/ProfileHub.cs b/Govor.API/Hubs/ProfileHub.cs index 27d1918..024f840 100644 --- a/Govor.API/Hubs/ProfileHub.cs +++ b/Govor.API/Hubs/ProfileHub.cs @@ -1,10 +1,10 @@ using Govor.API.Common.SignalR.Helpers; -using Govor.Application.Interfaces; -using Govor.Application.Interfaces.Friends; -using Govor.Application.Interfaces.Medias; +using Govor.Application.Friends; +using Govor.Application.Medias; +using Govor.Application.Profiles; +using Govor.Application.Synching; using Govor.Contracts.DTOs; using Govor.Contracts.Responses.SignalR; -using Govor.Core.Repositories.Groups; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.SignalR; @@ -13,7 +13,6 @@ namespace Govor.API.Hubs; [Authorize] public class ProfileHub : Hub { - private readonly IGroupsRepository _groupsRepository; private readonly IFriendshipService _friendsService; private readonly IProfileService _profileService; private readonly IHubUserAccessor _userAccessor; @@ -22,7 +21,6 @@ public class ProfileHub : Hub private readonly IMediaService _mediaService; public ProfileHub( - IGroupsRepository groupsRepository, IFriendshipService friendsService, IProfileService profileService, IHubUserAccessor userAccessor, @@ -30,7 +28,6 @@ public class ProfileHub : Hub IMediaService mediaService, ILogger logger) { - _groupsRepository = groupsRepository; _friendsService = friendsService; _profileService = profileService; _userAccessor = userAccessor; diff --git a/Govor.API/Program.cs b/Govor.API/Program.cs index 4c8663f..1ee5ad4 100644 --- a/Govor.API/Program.cs +++ b/Govor.API/Program.cs @@ -3,7 +3,7 @@ using FirebaseAdmin; using Google.Apis.Auth.OAuth2; using Govor.API.Common.Extensions; using Govor.API.Hubs; -using Govor.Application.Services.Authentication; +using Govor.Application.Authentication.JWT; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Mvc; using Microsoft.IdentityModel.Tokens; @@ -29,7 +29,6 @@ builder.Configuration.AddJsonFile("appsettings.json", optional: false, reloadOnC FirebaseApp.Create(new AppOptions() { Credential = GoogleCredential.FromFile("secrets/firebase-adminsdk.json") - // или FromStream(File.OpenRead("firebase-adminsdk.json")) }); builder.Services.AddCors(options => @@ -81,9 +80,6 @@ builder.Services.AddControllers(); // Init DI builder.Services.AddServices(); -builder.Services.AddRepositories(); -builder.Services.AddValidators(); - builder.Services.AddOptionsConfiguration(configuration); builder.Services.AddGovorDbContext(configuration); // GovorDbContext init @@ -125,6 +121,7 @@ if (!app.Environment.IsDevelopment()) { //app.MapOpenApi(); builder.WebHost.UseUrls("http://0.0.0.0:8080"); + builder.WebHost.UseUrls("http://10.8.0.5:5000"); //builder.WebHost.UseUrls("http://192.168.1.107:8080"); } @@ -142,7 +139,7 @@ app.UseAuthorization(); app.MapControllers(); -app.Map("/server/ping", +app.MapGet("/server/ping", () => new OkResult()); app.MapHub("/hubs/chats"); diff --git a/Govor.API/Properties/launchSettings.json b/Govor.API/Properties/launchSettings.json index bdcb24a..83eb278 100644 --- a/Govor.API/Properties/launchSettings.json +++ b/Govor.API/Properties/launchSettings.json @@ -5,7 +5,7 @@ "commandName": "Project", "dotnetRunMessages": true, "launchBrowser": false, - "applicationUrl": "http://0.0.0.0:8080;http://localhost:7155", + "applicationUrl": "http://0.0.0.0:8080;http://localhost:7155;http://10.8.0.5:5000", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } diff --git a/Govor.API/appsettings.Development.json b/Govor.API/appsettings.Development.json index c2959b4..61c97cc 100644 --- a/Govor.API/appsettings.Development.json +++ b/Govor.API/appsettings.Development.json @@ -6,7 +6,7 @@ } }, "ConnectionStrings": { - "GovorDbContext": "Host=46.19.68.182;Port=5432;Database=default_db;Username=main;Password=1M^rf!1JKL:y,w;" + "GovorDbContext": "Host=localhost;Port=5432;Database=GovorDb;Username=postgres;Password=stalcker;" }, "UseMySql": false, "AllowedHosts": "*", diff --git a/Govor.API/appsettings.json b/Govor.API/appsettings.json index c2959b4..70d9f3e 100644 --- a/Govor.API/appsettings.json +++ b/Govor.API/appsettings.json @@ -6,7 +6,7 @@ } }, "ConnectionStrings": { - "GovorDbContext": "Host=46.19.68.182;Port=5432;Database=default_db;Username=main;Password=1M^rf!1JKL:y,w;" + "GovorDbContext": "Host=localhost;Port=5432;Database=GovorDb;Username=postgres;Password=stalcker;" }, "UseMySql": false, "AllowedHosts": "*", @@ -18,6 +18,6 @@ "RefreshTokenLifetimeDays": 30 }, "EncryptionOption": { - "Secret": "8B2j9kkw9xP5m7nQwE2zY3A-=Q8zP7C4+TqLZpg" + "Secret": "8B2j9kkw9xP5m7nQwE2zY3A-=Q8zP7C4+TqLZpg" } } diff --git a/Govor.Application.Tests/Infrastructure/AdminsStuff/InvitationGeneratorTests.cs b/Govor.Application.Tests/Infrastructure/AdminsStuff/InvitationGeneratorTests.cs index 698b6ed..e295386 100644 --- a/Govor.Application.Tests/Infrastructure/AdminsStuff/InvitationGeneratorTests.cs +++ b/Govor.Application.Tests/Infrastructure/AdminsStuff/InvitationGeneratorTests.cs @@ -1,8 +1,8 @@ using AutoFixture; using Govor.Application.Infrastructure.AdminsStuff; using Govor.Application.Interfaces; -using Govor.Core.Models; -using Govor.Core.Repositories.Invaites; +using Govor.Domain.Models; +using Govor.Domain.Repositories.Invaites; using Moq; namespace Govor.Application.Tests.Infrastructure.AdminsStuff; diff --git a/Govor.Application.Tests/Infrastructure/Validators/UsernameValidatorTests.cs b/Govor.Application.Tests/Infrastructure/Validators/UsernameValidatorTests.cs index 8d9d865..2a99dd8 100644 --- a/Govor.Application.Tests/Infrastructure/Validators/UsernameValidatorTests.cs +++ b/Govor.Application.Tests/Infrastructure/Validators/UsernameValidatorTests.cs @@ -1,4 +1,4 @@ -using Govor.Application.Exceptions.AuthService; +using Govor.Application.Authentication.Exceptions; using Govor.Application.Infrastructure.Validators; using Microsoft.Extensions.Configuration; diff --git a/Govor.Application.Tests/Services/Authentication/AuthServiceTests.cs b/Govor.Application.Tests/Services/Authentication/AuthServiceTests.cs index ee3964a..71287df 100644 --- a/Govor.Application.Tests/Services/Authentication/AuthServiceTests.cs +++ b/Govor.Application.Tests/Services/Authentication/AuthServiceTests.cs @@ -1,12 +1,12 @@ using AutoFixture; -using Govor.Core.Infrastructure.Extensions; -using Govor.Core.Models; -using Govor.Core.Repositories.Users; -using Govor.Application.Exceptions.AuthService; +using Govor.Domain.Infrastructure.Extensions; +using Govor.Domain.Models; +using Govor.Domain.Repositories.Users; +using Govor.Application.Authentication.Exceptions; using Govor.Application.Interfaces.Authentication; using Govor.Application.Services.Authentication; -using Govor.Core.Models.Users; -using Govor.Core.Repositories.Admins; +using Govor.Domain.Models.Users; +using Govor.Domain.Repositories.Admins; using Moq; namespace Govor.Application.Tests.Services.Authentication; diff --git a/Govor.Application.Tests/Services/Authentication/JwtServiceTests.cs b/Govor.Application.Tests/Services/Authentication/JwtServiceTests.cs index 777e876..d6dd2ff 100644 --- a/Govor.Application.Tests/Services/Authentication/JwtServiceTests.cs +++ b/Govor.Application.Tests/Services/Authentication/JwtServiceTests.cs @@ -4,7 +4,7 @@ using System.Text; using AutoFixture; using Govor.Application.Interfaces.Authentication; using Govor.Application.Services.Authentication; -using Govor.Core.Models.Users; +using Govor.Domain.Models.Users; using Microsoft.Extensions.Options; using Microsoft.IdentityModel.Tokens; using Moq; diff --git a/Govor.Application.Tests/Services/Friends/FriendRequestCommandServiceTests.cs b/Govor.Application.Tests/Services/Friends/FriendRequestCommandServiceTests.cs index 9d7a389..d0fa9d2 100644 --- a/Govor.Application.Tests/Services/Friends/FriendRequestCommandServiceTests.cs +++ b/Govor.Application.Tests/Services/Friends/FriendRequestCommandServiceTests.cs @@ -2,10 +2,11 @@ using AutoFixture; using Govor.Application.Exceptions.FriendsService; using Govor.Application.Interfaces; using Govor.Application.Interfaces.Friends; +using Govor.Application.PrivateUserChats; using Govor.Application.Services.Friends; -using Govor.Core.Models; -using Govor.Core.Repositories.Friendships; -using Govor.Core.Repositories.Users; +using Govor.Domain.Models; +using Govor.Domain.Repositories.Friendships; +using Govor.Domain.Repositories.Users; using Govor.Data.Repositories.Exceptions; using Moq; diff --git a/Govor.Application.Tests/Services/Friends/FriendRequestQueryServiceTests.cs b/Govor.Application.Tests/Services/Friends/FriendRequestQueryServiceTests.cs index 56029ec..aa627aa 100644 --- a/Govor.Application.Tests/Services/Friends/FriendRequestQueryServiceTests.cs +++ b/Govor.Application.Tests/Services/Friends/FriendRequestQueryServiceTests.cs @@ -1,10 +1,10 @@ using AutoFixture; using Govor.Application.Interfaces.Friends; using Govor.Application.Services.Friends; -using Govor.Core.Models; -using Govor.Core.Models.Users; -using Govor.Core.Repositories.Friendships; -using Govor.Core.Repositories.Users; +using Govor.Domain.Models; +using Govor.Domain.Models.Users; +using Govor.Domain.Repositories.Friendships; +using Govor.Domain.Repositories.Users; using Govor.Data.Repositories.Exceptions; using Moq; diff --git a/Govor.Application.Tests/Services/Friends/FriendshipServiceTests.cs b/Govor.Application.Tests/Services/Friends/FriendshipServiceTests.cs index acd7d08..1653ef5 100644 --- a/Govor.Application.Tests/Services/Friends/FriendshipServiceTests.cs +++ b/Govor.Application.Tests/Services/Friends/FriendshipServiceTests.cs @@ -1,10 +1,10 @@ using AutoFixture; using Govor.Application.Interfaces.Friends; using Govor.Application.Services.Friends; -using Govor.Core.Models; -using Govor.Core.Models.Users; -using Govor.Core.Repositories.Friendships; -using Govor.Core.Repositories.Users; +using Govor.Domain.Models; +using Govor.Domain.Models.Users; +using Govor.Domain.Repositories.Friendships; +using Govor.Domain.Repositories.Users; using Govor.Data.Repositories.Exceptions; using Moq; diff --git a/Govor.Application.Tests/Services/Medias/AccesserToDownloadMediaServiceTests.cs b/Govor.Application.Tests/Services/Medias/AccesserToDownloadMediaServiceTests.cs index 8c45613..3a6054a 100644 --- a/Govor.Application.Tests/Services/Medias/AccesserToDownloadMediaServiceTests.cs +++ b/Govor.Application.Tests/Services/Medias/AccesserToDownloadMediaServiceTests.cs @@ -1,6 +1,6 @@ using Govor.Application.Services.Medias; -using Govor.Core.Models; -using Govor.Core.Models.Messages; +using Govor.Domain.Models; +using Govor.Domain.Models.Messages; using Govor.Data; using Microsoft.EntityFrameworkCore; diff --git a/Govor.Application.Tests/Services/Messages/MessageCommandServiceTests.cs b/Govor.Application.Tests/Services/Messages/MessageCommandServiceTests.cs index 40a4327..5cc7e2d 100644 --- a/Govor.Application.Tests/Services/Messages/MessageCommandServiceTests.cs +++ b/Govor.Application.Tests/Services/Messages/MessageCommandServiceTests.cs @@ -2,13 +2,14 @@ using Govor.Application.Interfaces; using Govor.Application.Interfaces.Medias; using Govor.Application.Interfaces.Messages.Parameters; +using Govor.Application.PrivateUserChats; using Govor.Application.Services.Messages; -using Govor.Core.Models; -using Govor.Core.Models.Messages; -using Govor.Core.Repositories.Groups; -using Govor.Core.Repositories.Messages; -using Govor.Core.Repositories.PrivateChats; -using Govor.Core.Repositories.Users; +using Govor.Domain.Models; +using Govor.Domain.Models.Messages; +using Govor.Domain.Repositories.Groups; +using Govor.Domain.Repositories.Messages; +using Govor.Domain.Repositories.PrivateChats; +using Govor.Domain.Repositories.Users; using Govor.Data.Repositories.Exceptions; using Microsoft.Extensions.Logging; using Moq; diff --git a/Govor.Application.Tests/Services/Messages/MessagesLoaderTests.cs b/Govor.Application.Tests/Services/Messages/MessagesLoaderTests.cs index 0cfa9d9..03b4f94 100644 --- a/Govor.Application.Tests/Services/Messages/MessagesLoaderTests.cs +++ b/Govor.Application.Tests/Services/Messages/MessagesLoaderTests.cs @@ -1,9 +1,10 @@ using Govor.Application.Interfaces; +using Govor.Application.Messages; using Govor.Application.Services.Messages; -using Govor.Core.Models; -using Govor.Core.Models.Messages; -using Govor.Core.Repositories.Groups; -using Govor.Core.Repositories.PrivateChats; +using Govor.Domain.Models; +using Govor.Domain.Models.Messages; +using Govor.Domain.Repositories.Groups; +using Govor.Domain.Repositories.PrivateChats; using Govor.Data; using Microsoft.EntityFrameworkCore; using Moq; diff --git a/Govor.Application.Tests/Services/PasswordHasherTests.cs b/Govor.Application.Tests/Services/PasswordHasherTests.cs index a0e4074..cb6b195 100644 --- a/Govor.Application.Tests/Services/PasswordHasherTests.cs +++ b/Govor.Application.Tests/Services/PasswordHasherTests.cs @@ -1,6 +1,6 @@ using AutoFixture; using Govor.Application.Services.Authentication; -using Govor.Core.Infrastructure.Extensions; +using Govor.Domain.Infrastructure.Extensions; namespace Govor.Application.Tests.Services; diff --git a/Govor.Application.Tests/Services/PingHandlerServiceTests.cs b/Govor.Application.Tests/Services/PingHandlerServiceTests.cs index 09762ad..cd68952 100644 --- a/Govor.Application.Tests/Services/PingHandlerServiceTests.cs +++ b/Govor.Application.Tests/Services/PingHandlerServiceTests.cs @@ -1,5 +1,5 @@ -using Govor.Application.Services; -using Govor.Core.Models.Users; +using Govor.Application.PingHandler; +using Govor.Domain.Models.Users; using Govor.Data; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Caching.Memory; diff --git a/Govor.Application.Tests/Services/ProfileServiceTests.cs b/Govor.Application.Tests/Services/ProfileServiceTests.cs index 45e14a6..39ebd90 100644 --- a/Govor.Application.Tests/Services/ProfileServiceTests.cs +++ b/Govor.Application.Tests/Services/ProfileServiceTests.cs @@ -1,6 +1,5 @@ -using Govor.Application.Services; -using Govor.Core.Models.Users; -using Govor.Core.Repositories.Users; +using Govor.Domain.Models.Users; +using Govor.Domain.Repositories.Users; using Govor.Data.Repositories.Exceptions; using Microsoft.Extensions.Logging; using Moq; diff --git a/Govor.Application.Tests/Services/PushNotifications/PushNotificationServiceTests.cs b/Govor.Application.Tests/Services/PushNotifications/PushNotificationServiceTests.cs index dcf2f1a..fd1707f 100644 --- a/Govor.Application.Tests/Services/PushNotifications/PushNotificationServiceTests.cs +++ b/Govor.Application.Tests/Services/PushNotifications/PushNotificationServiceTests.cs @@ -1,7 +1,8 @@ using Govor.Application.Interfaces.PushNotifications; using Govor.Application.Interfaces.PushNotifications.Models; +using Govor.Application.PushNotifications; using Govor.Application.Services.PushNotifications; -using Govor.Core.Repositories.PushTokens; +using Govor.Domain.Repositories.PushTokens; using Microsoft.Extensions.Logging; using Moq; diff --git a/Govor.Application.Tests/Services/SynchingServiceTests.cs b/Govor.Application.Tests/Services/SynchingServiceTests.cs index e18e30e..31f68b5 100644 --- a/Govor.Application.Tests/Services/SynchingServiceTests.cs +++ b/Govor.Application.Tests/Services/SynchingServiceTests.cs @@ -1,4 +1,4 @@ -using Govor.Application.Services; +using Govor.Application.Synching; namespace Govor.Application.Tests.Services; diff --git a/Govor.Application.Tests/Services/UserGroupsGetterServiceTests.cs b/Govor.Application.Tests/Services/UserGroupsGetterServiceTests.cs index 83af882..3b4702b 100644 --- a/Govor.Application.Tests/Services/UserGroupsGetterServiceTests.cs +++ b/Govor.Application.Tests/Services/UserGroupsGetterServiceTests.cs @@ -1,8 +1,8 @@ using AutoFixture; +using Govor.Application.Groups; using Govor.Application.Interfaces; -using Govor.Application.Services; -using Govor.Core.Models; -using Govor.Core.Repositories.Groups; +using Govor.Domain.Models; +using Govor.Domain.Repositories.Groups; using Govor.Data.Repositories.Exceptions; using Moq; diff --git a/Govor.Application.Tests/Services/UserOnlineStatus/UserNotificationScopeServiceTests.cs b/Govor.Application.Tests/Services/UserOnlineStatus/UserNotificationScopeServiceTests.cs index 1eb0eb7..d031e73 100644 --- a/Govor.Application.Tests/Services/UserOnlineStatus/UserNotificationScopeServiceTests.cs +++ b/Govor.Application.Tests/Services/UserOnlineStatus/UserNotificationScopeServiceTests.cs @@ -2,8 +2,8 @@ using AutoFixture; using Govor.Application.Interfaces.Friends; using Govor.Application.Interfaces.UserOnlineStatus; using Govor.Application.Services.UserOnlineStatus; -using Govor.Core.Models; -using Govor.Core.Models.Users; +using Govor.Domain.Models; +using Govor.Domain.Models.Users; using Govor.Data.Repositories.Exceptions; using Microsoft.Extensions.Logging; using Moq; diff --git a/Govor.Application.Tests/Services/UserPrivateChatsCreatorTests.cs b/Govor.Application.Tests/Services/UserPrivateChatsCreatorTests.cs index 147b9ed..ad06d25 100644 --- a/Govor.Application.Tests/Services/UserPrivateChatsCreatorTests.cs +++ b/Govor.Application.Tests/Services/UserPrivateChatsCreatorTests.cs @@ -1,8 +1,8 @@ using AutoFixture; using Govor.Application.Interfaces; -using Govor.Application.Services; -using Govor.Core.Models; -using Govor.Core.Repositories.PrivateChats; +using Govor.Application.PrivateUserChats; +using Govor.Domain.Models; +using Govor.Domain.Repositories.PrivateChats; using Microsoft.Extensions.Logging; using Moq; diff --git a/Govor.Application.Tests/Services/UserSessions/UserSessionOpenerTests.cs b/Govor.Application.Tests/Services/UserSessions/UserSessionOpenerTests.cs index e09c519..396e1a9 100644 --- a/Govor.Application.Tests/Services/UserSessions/UserSessionOpenerTests.cs +++ b/Govor.Application.Tests/Services/UserSessions/UserSessionOpenerTests.cs @@ -1,6 +1,6 @@ using Govor.Application.Services.UserSessions; -using Govor.Core.Models.Users; -using Govor.Core.Repositories.UserSessionsRepository; +using Govor.Domain.Models.Users; +using Govor.Domain.Repositories.UserSessionsRepository; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Moq; diff --git a/Govor.Application.Tests/Services/UserSessions/UserSessionReaderTests.cs b/Govor.Application.Tests/Services/UserSessions/UserSessionReaderTests.cs index cc660fa..159278d 100644 --- a/Govor.Application.Tests/Services/UserSessions/UserSessionReaderTests.cs +++ b/Govor.Application.Tests/Services/UserSessions/UserSessionReaderTests.cs @@ -1,9 +1,9 @@ using AutoFixture; using Govor.Application.Interfaces.UserSession; using Govor.Application.Services.UserSessions; -using Govor.Core.Models; -using Govor.Core.Models.Users; -using Govor.Core.Repositories.UserSessionsRepository; +using Govor.Domain.Models; +using Govor.Domain.Models.Users; +using Govor.Domain.Repositories.UserSessionsRepository; using Govor.Data.Repositories.Exceptions; using Microsoft.Extensions.Logging; using Moq; diff --git a/Govor.Application.Tests/Services/UserSessions/UserSessionRefresherTests.cs b/Govor.Application.Tests/Services/UserSessions/UserSessionRefresherTests.cs index b717f9f..1dfb754 100644 --- a/Govor.Application.Tests/Services/UserSessions/UserSessionRefresherTests.cs +++ b/Govor.Application.Tests/Services/UserSessions/UserSessionRefresherTests.cs @@ -1,10 +1,10 @@ using Govor.Application.Interfaces.Authentication; using Govor.Application.Services.Authentication; using Govor.Application.Services.UserSessions; -using Govor.Core.Models; -using Govor.Core.Models.Users; -using Govor.Core.Repositories.Users; -using Govor.Core.Repositories.UserSessionsRepository; +using Govor.Domain.Models; +using Govor.Domain.Models.Users; +using Govor.Domain.Repositories.Users; +using Govor.Domain.Repositories.UserSessionsRepository; using Govor.Data.Repositories.Exceptions; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; diff --git a/Govor.Application.Tests/Services/UserSessions/UserSessionRevokerTests.cs b/Govor.Application.Tests/Services/UserSessions/UserSessionRevokerTests.cs index 289a82e..240f48d 100644 --- a/Govor.Application.Tests/Services/UserSessions/UserSessionRevokerTests.cs +++ b/Govor.Application.Tests/Services/UserSessions/UserSessionRevokerTests.cs @@ -1,8 +1,8 @@ using Govor.Application.Services.UserSessions; -using Govor.Core.Models; -using Govor.Core.Models.Users; -using Govor.Core.Repositories.PushTokens; -using Govor.Core.Repositories.UserSessionsRepository; +using Govor.Domain.Models; +using Govor.Domain.Models.Users; +using Govor.Domain.Repositories.PushTokens; +using Govor.Domain.Repositories.UserSessionsRepository; using Govor.Data.Repositories.Exceptions; using Microsoft.Extensions.Logging; using Moq; diff --git a/Govor.Application.Tests/Services/VerifyFriendshipTests.cs b/Govor.Application.Tests/Services/VerifyFriendshipTests.cs index a4a396d..cd3628e 100644 --- a/Govor.Application.Tests/Services/VerifyFriendshipTests.cs +++ b/Govor.Application.Tests/Services/VerifyFriendshipTests.cs @@ -1,8 +1,7 @@ using AutoFixture; using Govor.Application.Exceptions.VerifyFriendship; -using Govor.Application.Services; -using Govor.Core.Models; -using Govor.Core.Repositories.Friendships; +using Govor.Domain.Models; +using Govor.Domain.Repositories.Friendships; using Govor.Data.Repositories.Exceptions; using Microsoft.Extensions.Logging; using Moq; diff --git a/Govor.Application/Authentication/AuthService.cs b/Govor.Application/Authentication/AuthService.cs new file mode 100644 index 0000000..2f9df25 --- /dev/null +++ b/Govor.Application/Authentication/AuthService.cs @@ -0,0 +1,101 @@ +using Govor.Application.Authentication.Exceptions; +using Govor.Application.Infrastructure.Validators; +using Govor.Application.Users; +using Govor.Domain; +using Govor.Domain.Common; +using Govor.Domain.Models; +using Govor.Domain.Models.Users; +using Microsoft.EntityFrameworkCore; + +namespace Govor.Application.Authentication; + +public class AuthService : IAccountService +{ + private readonly GovorDbContext _context; + private readonly IPasswordHasher _passwordHasher; + private readonly IUserNameExistValidator _userNameExistValidator; + private readonly IUsernameValidator _usernameValidator; + + public AuthService( + GovorDbContext context, + IUserNameExistValidator existValidator, + IPasswordHasher passwordHasher, + IUsernameValidator usernameValidator) + { + _context = context; + _userNameExistValidator = existValidator; + _passwordHasher = passwordHasher; + _usernameValidator = usernameValidator; + } + + public async Task> RegistrationAsync(string name, string password, Invitation invitation) + { + + var validationResult = _usernameValidator.Validate(name); + if (validationResult.IsFailure) + { + return Result.Failure(validationResult.Error); + } + + if (await _userNameExistValidator.IsUsernameExistsAsync(name)) + { + return Result.Failure(new Error( + nameof(UserAlreadyExistException), + $"User with username '{name}' already exists.")); + } + + var passwordHash = _passwordHasher.Hash(password); + + var user = new User + { + Id = Guid.NewGuid(), + Username = name, + PasswordHash = passwordHash, + Description = string.Empty, + CreatedOn = DateOnly.FromDateTime(DateTime.UtcNow), + IconId = Guid.Empty, + WasOnline = DateTime.UtcNow, + InviteId = invitation.Id + }; + + + await _context.Users.AddAsync(user); + + await SetRoleAsync(user, invitation); + + await _context.SaveChangesAsync(); + + return user; // Success + } + + public async Task> LoginAsync(string name, string password) + { + var user = await _context.Users + .AsNoTracking() + .FirstOrDefaultAsync(u => u.Username == name); + + if (user is null) + { + return Result.Failure(new Error( + nameof(UserNotRegisteredException), + $"User '{name}' is not registered.")); + } + + if (!_passwordHasher.Verify(password, user.PasswordHash)) + { + return Result.Failure(new Error( + nameof(InvalidOperationException), + "The password provided is incorrect.")); + } + + return user; // Success + } + + private async Task SetRoleAsync(User user, Invitation invitation) + { + if (invitation.IsAdmin) + { + await _context.Admins.AddAsync(new Admin { UserId = user.Id }); + } + } +} diff --git a/Govor.Application/Exceptions/AuthService/InvalidUsernameException.cs b/Govor.Application/Authentication/Exceptions/InvalidUsernameException.cs similarity index 55% rename from Govor.Application/Exceptions/AuthService/InvalidUsernameException.cs rename to Govor.Application/Authentication/Exceptions/InvalidUsernameException.cs index 9824b86..435a509 100644 --- a/Govor.Application/Exceptions/AuthService/InvalidUsernameException.cs +++ b/Govor.Application/Authentication/Exceptions/InvalidUsernameException.cs @@ -1,6 +1,6 @@ -using Govor.Core; +using Govor.Domain; -namespace Govor.Application.Exceptions.AuthService; +namespace Govor.Application.Authentication.Exceptions; public class InvalidUsernameException(string message) : GovorCoreException(message) { diff --git a/Govor.Application/Authentication/Exceptions/LoginUserException.cs b/Govor.Application/Authentication/Exceptions/LoginUserException.cs new file mode 100644 index 0000000..1926fcc --- /dev/null +++ b/Govor.Application/Authentication/Exceptions/LoginUserException.cs @@ -0,0 +1,5 @@ +using Govor.Domain; + +namespace Govor.Application.Authentication.Exceptions; + +public class LoginUserException : GovorCoreException { } \ No newline at end of file diff --git a/Govor.Application/Authentication/Exceptions/UserAlreadyExistException.cs b/Govor.Application/Authentication/Exceptions/UserAlreadyExistException.cs new file mode 100644 index 0000000..40701c2 --- /dev/null +++ b/Govor.Application/Authentication/Exceptions/UserAlreadyExistException.cs @@ -0,0 +1,5 @@ +using Govor.Domain; + +namespace Govor.Application.Authentication.Exceptions; + +public class UserAlreadyExistException(string username) : GovorCoreException($"{username} is already exists!") { } \ No newline at end of file diff --git a/Govor.Application/Authentication/Exceptions/UserNotRegisteredException.cs b/Govor.Application/Authentication/Exceptions/UserNotRegisteredException.cs new file mode 100644 index 0000000..a1c82ec --- /dev/null +++ b/Govor.Application/Authentication/Exceptions/UserNotRegisteredException.cs @@ -0,0 +1,5 @@ +using Govor.Domain; + +namespace Govor.Application.Authentication.Exceptions; + +public class UserNotRegisteredException(string username) : GovorCoreException($"{username} is not registered!") { } \ No newline at end of file diff --git a/Govor.Application/Authentication/IAuthService.cs b/Govor.Application/Authentication/IAuthService.cs new file mode 100644 index 0000000..48816d1 --- /dev/null +++ b/Govor.Application/Authentication/IAuthService.cs @@ -0,0 +1,11 @@ +using Govor.Domain.Common; +using Govor.Domain.Models; +using Govor.Domain.Models.Users; + +namespace Govor.Application.Authentication; + +public interface IAccountService +{ + public Task> RegistrationAsync(string name, string password, Invitation invitation); + public Task> LoginAsync(string name, string password); +} \ No newline at end of file diff --git a/Govor.Application/Authentication/IInvitesService.cs b/Govor.Application/Authentication/IInvitesService.cs new file mode 100644 index 0000000..18e030a --- /dev/null +++ b/Govor.Application/Authentication/IInvitesService.cs @@ -0,0 +1,12 @@ +using Govor.Domain.Common; +using Govor.Domain.Models; +using Govor.Domain.Models.Users; + +namespace Govor.Application.Authentication; + +public interface IInvitesService +{ + public Task GetRoleNameAsync(User user); + public Task GetRoleNameAsync(Guid sessionId); + public Task> ValidateAsync(string inviteCode); +} \ No newline at end of file diff --git a/Govor.Application/Interfaces/IPasswordHasher.cs b/Govor.Application/Authentication/IPasswordHasher.cs similarity index 73% rename from Govor.Application/Interfaces/IPasswordHasher.cs rename to Govor.Application/Authentication/IPasswordHasher.cs index c6253c9..a549102 100644 --- a/Govor.Application/Interfaces/IPasswordHasher.cs +++ b/Govor.Application/Authentication/IPasswordHasher.cs @@ -1,4 +1,4 @@ -namespace Govor.Core.Infrastructure.Extensions; +namespace Govor.Application.Authentication; public interface IPasswordHasher { diff --git a/Govor.Application/Authentication/InvitesService.cs b/Govor.Application/Authentication/InvitesService.cs new file mode 100644 index 0000000..1d2a70c --- /dev/null +++ b/Govor.Application/Authentication/InvitesService.cs @@ -0,0 +1,56 @@ +using Govor.Application.Exceptions.InvitesService; +using Govor.Domain; +using Govor.Domain.Common; +using Govor.Domain.Models; +using Govor.Domain.Models.Users; +using Microsoft.EntityFrameworkCore; + +namespace Govor.Application.Authentication; + +public class InvitesService : IInvitesService +{ + private readonly GovorDbContext _context; + + public InvitesService(GovorDbContext context) + { + _context = context; + } + + public async Task GetRoleNameAsync(User user) + { + return await GetRoleNameAsync(user.InviteId); + } + + public async Task GetRoleNameAsync(Guid sessionId) + { + var invitation = await _context.Invitations.FirstOrDefaultAsync(s => s.Id == sessionId); + + if (invitation == null) + return "User"; + + return invitation.IsAdmin ? "Admin" : "User"; + } + + public async Task> ValidateAsync(string inviteCode) + { + var invite = await _context.Invitations + .Include(s => s.Users) + .FirstOrDefaultAsync(s => s.Code == inviteCode); + + if (invite == null) + return Result.Failure(Error.Null); + + if (invite.EndDate < DateTime.Now || invite.MaxParticipants <= invite.Users.Count) + { + invite.IsActive = false; + await _context.SaveChangesAsync(); + + return Result.Failure(new Error( + "Auth.InviteLinkInvalid", $"Invite link invalid: {inviteCode}") + ); + } + + return invite; + } +} + diff --git a/Govor.Application/Interfaces/Authentication/IJwtService.cs b/Govor.Application/Authentication/JWT/IJwtService.cs similarity index 74% rename from Govor.Application/Interfaces/Authentication/IJwtService.cs rename to Govor.Application/Authentication/JWT/IJwtService.cs index d5d54ad..74d581d 100644 --- a/Govor.Application/Interfaces/Authentication/IJwtService.cs +++ b/Govor.Application/Authentication/JWT/IJwtService.cs @@ -1,7 +1,7 @@ using System.Security.Claims; -using Govor.Core.Models.Users; +using Govor.Domain.Models.Users; -namespace Govor.Application.Interfaces.Authentication; +namespace Govor.Application.Authentication.JWT; public interface IJwtService { diff --git a/Govor.Application/Interfaces/Authentication/IJwtTokenHasher.cs b/Govor.Application/Authentication/JWT/IJwtTokenHasher.cs similarity index 69% rename from Govor.Application/Interfaces/Authentication/IJwtTokenHasher.cs rename to Govor.Application/Authentication/JWT/IJwtTokenHasher.cs index 439e87b..7823e04 100644 --- a/Govor.Application/Interfaces/Authentication/IJwtTokenHasher.cs +++ b/Govor.Application/Authentication/JWT/IJwtTokenHasher.cs @@ -1,4 +1,4 @@ -namespace Govor.Application.Interfaces.Authentication; +namespace Govor.Application.Authentication.JWT; public interface IJwtTokenHasher { diff --git a/Govor.Application/Services/Authentication/JwtAccessOption.cs b/Govor.Application/Authentication/JWT/JwtAccessOption.cs similarity index 66% rename from Govor.Application/Services/Authentication/JwtAccessOption.cs rename to Govor.Application/Authentication/JWT/JwtAccessOption.cs index a898c5e..b6dda6f 100644 --- a/Govor.Application/Services/Authentication/JwtAccessOption.cs +++ b/Govor.Application/Authentication/JWT/JwtAccessOption.cs @@ -1,4 +1,4 @@ -namespace Govor.Application.Services.Authentication; +namespace Govor.Application.Authentication.JWT; public class JwtAccessOption { public string SecretKey {get; set;} diff --git a/Govor.Application/Services/Authentication/JwtRefreshOption.cs b/Govor.Application/Authentication/JWT/JwtRefreshOption.cs similarity index 62% rename from Govor.Application/Services/Authentication/JwtRefreshOption.cs rename to Govor.Application/Authentication/JWT/JwtRefreshOption.cs index 51db7ad..482ab96 100644 --- a/Govor.Application/Services/Authentication/JwtRefreshOption.cs +++ b/Govor.Application/Authentication/JWT/JwtRefreshOption.cs @@ -1,4 +1,4 @@ -namespace Govor.Application.Services.Authentication; +namespace Govor.Application.Authentication.JWT; public class JwtRefreshOption { diff --git a/Govor.Application/Services/Authentication/JwtService.cs b/Govor.Application/Authentication/JWT/JwtService.cs similarity index 94% rename from Govor.Application/Services/Authentication/JwtService.cs rename to Govor.Application/Authentication/JWT/JwtService.cs index 764ded3..609eddf 100644 --- a/Govor.Application/Services/Authentication/JwtService.cs +++ b/Govor.Application/Authentication/JWT/JwtService.cs @@ -1,12 +1,11 @@ using System.IdentityModel.Tokens.Jwt; using System.Security.Claims; using System.Text; -using Govor.Application.Interfaces.Authentication; -using Govor.Core.Models.Users; +using Govor.Domain.Models.Users; using Microsoft.Extensions.Options; using Microsoft.IdentityModel.Tokens; -namespace Govor.Application.Services.Authentication; +namespace Govor.Application.Authentication.JWT; public class JwtService : IJwtService { @@ -27,7 +26,7 @@ public class JwtService : IJwtService { new Claim("userId", user.Id.ToString()), new Claim("sid", sessionId.ToString()), - new Claim(ClaimTypes.Role, await _invitesService.GetRoleAsync(user), ClaimValueTypes.String) + new Claim(ClaimTypes.Role, await _invitesService.GetRoleNameAsync(user), ClaimValueTypes.String) }; var singing = new SigningCredentials( diff --git a/Govor.Application/Services/Authentication/JwtTokenHasher.cs b/Govor.Application/Authentication/JWT/JwtTokenHasher.cs similarity index 91% rename from Govor.Application/Services/Authentication/JwtTokenHasher.cs rename to Govor.Application/Authentication/JWT/JwtTokenHasher.cs index 90154d8..d2595d9 100644 --- a/Govor.Application/Services/Authentication/JwtTokenHasher.cs +++ b/Govor.Application/Authentication/JWT/JwtTokenHasher.cs @@ -1,9 +1,8 @@ using System.Security.Cryptography; using System.Text; -using Govor.Application.Interfaces.Authentication; using Microsoft.Extensions.Configuration; -namespace Govor.Application.Services.Authentication; +namespace Govor.Application.Authentication.JWT; public class JwtTokenHasher : IJwtTokenHasher { diff --git a/Govor.Application/Services/Authentication/PasswordHasher.cs b/Govor.Application/Authentication/PasswordHasher.cs similarity index 76% rename from Govor.Application/Services/Authentication/PasswordHasher.cs rename to Govor.Application/Authentication/PasswordHasher.cs index 99003ef..65e2f2d 100644 --- a/Govor.Application/Services/Authentication/PasswordHasher.cs +++ b/Govor.Application/Authentication/PasswordHasher.cs @@ -1,6 +1,6 @@ -using Govor.Core.Infrastructure.Extensions; +using Govor.Domain.Common.Extensions; -namespace Govor.Application.Services.Authentication; +namespace Govor.Application.Authentication; public class PasswordHasher : IPasswordHasher { diff --git a/Govor.Application/Exceptions/AuthService/LoginUserException.cs b/Govor.Application/Exceptions/AuthService/LoginUserException.cs deleted file mode 100644 index 7ad1d60..0000000 --- a/Govor.Application/Exceptions/AuthService/LoginUserException.cs +++ /dev/null @@ -1,5 +0,0 @@ -using Govor.Core; - -namespace Govor.Application.Exceptions.AuthService; - -public class LoginUserException : GovorCoreException { } \ No newline at end of file diff --git a/Govor.Application/Exceptions/AuthService/UserAlreadyExistException.cs b/Govor.Application/Exceptions/AuthService/UserAlreadyExistException.cs deleted file mode 100644 index 14827f5..0000000 --- a/Govor.Application/Exceptions/AuthService/UserAlreadyExistException.cs +++ /dev/null @@ -1,5 +0,0 @@ -using Govor.Core; - -namespace Govor.Application.Exceptions.AuthService; - -public class UserAlreadyExistException(string username) : GovorCoreException($"{username} is already exists!") { } \ No newline at end of file diff --git a/Govor.Application/Exceptions/AuthService/UserNotRegisteredException.cs b/Govor.Application/Exceptions/AuthService/UserNotRegisteredException.cs deleted file mode 100644 index 51f35b3..0000000 --- a/Govor.Application/Exceptions/AuthService/UserNotRegisteredException.cs +++ /dev/null @@ -1,5 +0,0 @@ -using Govor.Core; - -namespace Govor.Application.Exceptions.AuthService; - -public class UserNotRegisteredException(string username) : GovorCoreException($"{username} is not registered!") { } \ No newline at end of file diff --git a/Govor.Application/Exceptions/FriendsService/RequestAlreadySentException.cs b/Govor.Application/Exceptions/FriendsService/RequestAlreadySentException.cs index 97f85d0..7b30c17 100644 --- a/Govor.Application/Exceptions/FriendsService/RequestAlreadySentException.cs +++ b/Govor.Application/Exceptions/FriendsService/RequestAlreadySentException.cs @@ -1,4 +1,4 @@ -using Govor.Core; +using Govor.Domain; namespace Govor.Application.Exceptions.FriendsService; diff --git a/Govor.Application/Exceptions/FriendsService/SearchUsersException.cs b/Govor.Application/Exceptions/FriendsService/SearchUsersException.cs index f51ebce..4a14f83 100644 --- a/Govor.Application/Exceptions/FriendsService/SearchUsersException.cs +++ b/Govor.Application/Exceptions/FriendsService/SearchUsersException.cs @@ -1,4 +1,4 @@ -using Govor.Core; +using Govor.Domain; namespace Govor.Application.Exceptions.FriendsService; diff --git a/Govor.Application/Exceptions/FriendsService/SendFriendRequestException.cs b/Govor.Application/Exceptions/FriendsService/SendFriendRequestException.cs index 0e0b78f..5b1c900 100644 --- a/Govor.Application/Exceptions/FriendsService/SendFriendRequestException.cs +++ b/Govor.Application/Exceptions/FriendsService/SendFriendRequestException.cs @@ -1,4 +1,4 @@ -using Govor.Core; +using Govor.Domain; namespace Govor.Application.Exceptions.FriendsService; diff --git a/Govor.Application/Exceptions/InvitesService/InviteLinkInvalidException.cs b/Govor.Application/Exceptions/InvitesService/InviteLinkInvalidException.cs index 4180c9d..ffe6847 100644 --- a/Govor.Application/Exceptions/InvitesService/InviteLinkInvalidException.cs +++ b/Govor.Application/Exceptions/InvitesService/InviteLinkInvalidException.cs @@ -1,4 +1,4 @@ -using Govor.Core; +using Govor.Domain; namespace Govor.Application.Exceptions.InvitesService; diff --git a/Govor.Application/Exceptions/VerifyFriendship/FriendshipException.cs b/Govor.Application/Exceptions/VerifyFriendship/FriendshipException.cs index ab56926..160e514 100644 --- a/Govor.Application/Exceptions/VerifyFriendship/FriendshipException.cs +++ b/Govor.Application/Exceptions/VerifyFriendship/FriendshipException.cs @@ -1,4 +1,4 @@ -using Govor.Core; +using Govor.Domain; namespace Govor.Application.Exceptions.VerifyFriendship; diff --git a/Govor.Application/Friends/FriendRequestCommandService.cs b/Govor.Application/Friends/FriendRequestCommandService.cs new file mode 100644 index 0000000..6656510 --- /dev/null +++ b/Govor.Application/Friends/FriendRequestCommandService.cs @@ -0,0 +1,126 @@ +using Govor.Application.Exceptions.FriendsService; +using Govor.Application.Interfaces; +using Govor.Application.PrivateUserChats; +using Govor.Domain; +using Govor.Domain.Common; +using Govor.Domain.Models; +using Microsoft.EntityFrameworkCore; + +namespace Govor.Application.Friends; + +public class FriendRequestCommandService : IFriendRequestCommandService +{ + private readonly GovorDbContext _context; + private readonly IUserPrivateChatsCreator _privateChatsCreator; + + public FriendRequestCommandService( + GovorDbContext context, + IUserPrivateChatsCreator privateChatsCreator) + { + _context = context; + _privateChatsCreator = privateChatsCreator; + } + + public async Task> SendAsync(Guid fromUserId, Guid toUserId) + { + if (fromUserId == toUserId) + return Result.Failure(new Error( + "Friendship.Send", + "Cannot send a request to self user") + ); + + var friendship = await _context.Friendships + .FirstOrDefaultAsync(f => (f.RequesterId == fromUserId && f.AddresseeId == toUserId) || + (f.RequesterId == toUserId && f.AddresseeId == fromUserId)); + + if (friendship is null) + { + friendship = new Friendship + { + Id = Guid.NewGuid(), + RequesterId = fromUserId, + AddresseeId = toUserId, + Status = FriendshipStatus.Pending + }; + await _context.Friendships.AddAsync(friendship); + } + else + { + if (friendship.Status == FriendshipStatus.Pending || + friendship.Status == FriendshipStatus.Accepted || + friendship.Status == FriendshipStatus.Blocked) + { + return Result.Failure(new Error( + "Friendship.Send", + $"The request is already {friendship.Status}") + ); + } + + friendship.RequesterId = fromUserId; + friendship.AddresseeId = toUserId; + friendship.Status = FriendshipStatus.Pending; + } + + await _context.SaveChangesAsync(); + return friendship; + } + + public async Task> AcceptAsync(Guid requestId, Guid currentUserId) + { + var friendship = await _context.Friendships.FindAsync(requestId); + + if (friendship is null) + return Result.Failure(new Error( + "Friendship.Accept", + "Friendship not found! You cant accept request!") + ); + + if (friendship.AddresseeId != currentUserId) + return Result.Failure(new Error( + "Friendship.Accept", + "You cannot accept this request!") + ); + + if (friendship.Status != FriendshipStatus.Pending) + return Result.Failure(new Error( + "Friendship.Accept", + "Request is already accepted!") + ); + + friendship.Status = FriendshipStatus.Accepted; + + await _context.SaveChangesAsync(); + + await _privateChatsCreator.CreateAsync(friendship.AddresseeId, friendship.RequesterId); + + return friendship; + } + + public async Task> RejectAsync(Guid requestId, Guid currentUserId) + { + var friendship = await _context.Friendships.FindAsync(requestId); + + if (friendship == null) + return Result.Failure(new Error( + "Friendship.Reject", + "Friendship not found! You cant reject request!") + ); + + if (friendship.AddresseeId != currentUserId) + return Result.Failure(new Error( + "Friendship.Reject", + "You cannot reject this request!") + ); + + if (friendship.Status != FriendshipStatus.Pending && friendship.Status != FriendshipStatus.Rejected) + return Result.Failure(new Error( + "Friendship.Reject", + $"Request is already {friendship.Status}") + ); + + friendship.Status = FriendshipStatus.Rejected; + + await _context.SaveChangesAsync(); + return friendship; + } +} \ No newline at end of file diff --git a/Govor.Application/Friends/FriendRequestQueryService.cs b/Govor.Application/Friends/FriendRequestQueryService.cs new file mode 100644 index 0000000..855c3d7 --- /dev/null +++ b/Govor.Application/Friends/FriendRequestQueryService.cs @@ -0,0 +1,36 @@ +using Microsoft.EntityFrameworkCore; +using Govor.Domain; +using Govor.Domain.Models; + +namespace Govor.Application.Friends; + +public class FriendRequestQueryService : IFriendRequestQueryService +{ + private readonly GovorDbContext _context; + + + public FriendRequestQueryService(GovorDbContext context) + { + _context = context; + } + + public async Task> GetIncomingAsync(Guid userId) + { + return await _context.Friendships + .AsNoTracking() + .Include(f => f.Requester) + .Include(f => f.Addressee) + .Where(f => f.AddresseeId == userId && f.Status == FriendshipStatus.Pending) + .ToListAsync(); + } + + public async Task> GetResponsesAsync(Guid userId) + { + return await _context.Friendships + .AsNoTracking() + .Include(f => f.Requester) + .Include(f => f.Addressee) + .Where(f => f.RequesterId == userId && f.Status != FriendshipStatus.Accepted) + .ToListAsync(); + } +} \ No newline at end of file diff --git a/Govor.Application/Services/Friends/FriendsBlockService.cs b/Govor.Application/Friends/FriendsBlockService.cs similarity index 79% rename from Govor.Application/Services/Friends/FriendsBlockService.cs rename to Govor.Application/Friends/FriendsBlockService.cs index 991f760..57c265c 100644 --- a/Govor.Application/Services/Friends/FriendsBlockService.cs +++ b/Govor.Application/Friends/FriendsBlockService.cs @@ -1,6 +1,4 @@ -using Govor.Application.Interfaces; - -namespace Govor.Application.Services.Friends; +namespace Govor.Application.Friends; public class FriendsBlockService : IFriendsBlockService { diff --git a/Govor.Application/Friends/FriendshipService.cs b/Govor.Application/Friends/FriendshipService.cs new file mode 100644 index 0000000..778c7a5 --- /dev/null +++ b/Govor.Application/Friends/FriendshipService.cs @@ -0,0 +1,62 @@ +using Microsoft.EntityFrameworkCore; +using Govor.Domain; +using Govor.Domain.Models; +using Govor.Domain.Models.Users; + +namespace Govor.Application.Friends; + +public class FriendshipService : IFriendshipService +{ + private readonly GovorDbContext _context; + + public FriendshipService(GovorDbContext context) + { + _context = context; + } + + public async Task> SearchUsersAsync(string query, Guid currentId) + { + if (string.IsNullOrWhiteSpace(query)) + { + return []; + } + + return await _context.Users + .AsNoTracking() + .Where(u => u.Id != currentId && u.Username.Contains(query)) + .Take(5) + .ToListAsync(); + } + + public async Task> GetPotentialFriendsAsync(Guid userId) + { + var pendingFriendships = await _context.Friendships + .AsNoTracking() + .Include(f => f.Requester) + .Include(f => f.Addressee) + .Where(f => (f.RequesterId == userId || f.AddresseeId == userId) + && f.Status == FriendshipStatus.Pending) + .ToListAsync(); + + return pendingFriendships + .Select(f => f.RequesterId == userId ? f.Addressee : f.Requester) + .ToList(); + } + + public async Task> GetFriendsAsync(Guid userId) + { + var acceptedFriendships = await _context.Friendships + .AsNoTracking() + .Include(f => f.Requester) + .Include(f => f.Addressee) + .Where(f => (f.RequesterId == userId || f.AddresseeId == userId) + && f.Status == FriendshipStatus.Accepted) + .ToListAsync(); + + var friends = acceptedFriendships + .Select(f => f.RequesterId == userId ? f.Addressee : f.Requester) + .ToList(); + + return friends; + } +} \ No newline at end of file diff --git a/Govor.Application/Friends/IFriendRequestCommandService.cs b/Govor.Application/Friends/IFriendRequestCommandService.cs new file mode 100644 index 0000000..1ed7d01 --- /dev/null +++ b/Govor.Application/Friends/IFriendRequestCommandService.cs @@ -0,0 +1,11 @@ +using Govor.Domain.Common; +using Govor.Domain.Models; + +namespace Govor.Application.Friends; + +public interface IFriendRequestCommandService +{ + Task> SendAsync(Guid fromUserId, Guid toUserId); + Task> AcceptAsync(Guid requestId, Guid currentUserId); + Task> RejectAsync(Guid requestId, Guid currentUserId); +} diff --git a/Govor.Application/Interfaces/Friends/IFriendRequestQueryService.cs b/Govor.Application/Friends/IFriendRequestQueryService.cs similarity index 69% rename from Govor.Application/Interfaces/Friends/IFriendRequestQueryService.cs rename to Govor.Application/Friends/IFriendRequestQueryService.cs index 93e9525..1c18eb8 100644 --- a/Govor.Application/Interfaces/Friends/IFriendRequestQueryService.cs +++ b/Govor.Application/Friends/IFriendRequestQueryService.cs @@ -1,6 +1,6 @@ -using Govor.Core.Models; +using Govor.Domain.Models; -namespace Govor.Application.Interfaces.Friends; +namespace Govor.Application.Friends; public interface IFriendRequestQueryService diff --git a/Govor.Application/Interfaces/Friends/IFriendsBlockService.cs b/Govor.Application/Friends/IFriendsBlockService.cs similarity index 81% rename from Govor.Application/Interfaces/Friends/IFriendsBlockService.cs rename to Govor.Application/Friends/IFriendsBlockService.cs index 2d69160..2883143 100644 --- a/Govor.Application/Interfaces/Friends/IFriendsBlockService.cs +++ b/Govor.Application/Friends/IFriendsBlockService.cs @@ -1,4 +1,4 @@ -namespace Govor.Application.Interfaces; +namespace Govor.Application.Friends; public interface IFriendsBlockService { diff --git a/Govor.Application/Interfaces/Friends/IFriendshipService.cs b/Govor.Application/Friends/IFriendshipService.cs similarity index 73% rename from Govor.Application/Interfaces/Friends/IFriendshipService.cs rename to Govor.Application/Friends/IFriendshipService.cs index 0351278..ff8e262 100644 --- a/Govor.Application/Interfaces/Friends/IFriendshipService.cs +++ b/Govor.Application/Friends/IFriendshipService.cs @@ -1,6 +1,6 @@ -using Govor.Core.Models.Users; +using Govor.Domain.Models.Users; -namespace Govor.Application.Interfaces.Friends; +namespace Govor.Application.Friends; public interface IFriendshipService { diff --git a/Govor.Application/Interfaces/IVerifyFriendship.cs b/Govor.Application/Friends/IVerifyFriendship.cs similarity index 80% rename from Govor.Application/Interfaces/IVerifyFriendship.cs rename to Govor.Application/Friends/IVerifyFriendship.cs index 27fb6bb..4e9dcf4 100644 --- a/Govor.Application/Interfaces/IVerifyFriendship.cs +++ b/Govor.Application/Friends/IVerifyFriendship.cs @@ -1,4 +1,4 @@ -namespace Govor.Application.Interfaces; +namespace Govor.Application.Friends; public interface IVerifyFriendship { diff --git a/Govor.Application/Friends/VerifierFriendship.cs b/Govor.Application/Friends/VerifierFriendship.cs new file mode 100644 index 0000000..9382fc8 --- /dev/null +++ b/Govor.Application/Friends/VerifierFriendship.cs @@ -0,0 +1,59 @@ +using Microsoft.EntityFrameworkCore; +using Govor.Application.Exceptions.VerifyFriendship; +using Govor.Domain; +using Govor.Domain.Models; +using Microsoft.Extensions.Logging; + +namespace Govor.Application.Friends; + +public class VerifyFriendship : IVerifyFriendship +{ + private readonly GovorDbContext _dbContext; + private readonly ILogger _logger; + private const string FriendshipNotAcceptedError = "Friendship between user {0} and friend {1} does not exist or is not accepted."; + + public VerifyFriendship(GovorDbContext dbContext, ILogger logger) + { + _dbContext = dbContext; + _logger = logger; + } + + public async Task VerifyAsync(Guid targetUserId, Guid friendUserId) + { + if (targetUserId == Guid.Empty || friendUserId == Guid.Empty) + { + _logger.LogWarning("Invalid user IDs provided: targetUserId={TargetUserId}, friendUserId={FriendUserId}", targetUserId, friendUserId); + throw new ArgumentException("User IDs cannot be empty."); + } + + + var isFriendshipAccepted = await _dbContext.Friendships + .AsNoTracking() + .AnyAsync(f => f.Status == FriendshipStatus.Accepted && + ((f.RequesterId == targetUserId && f.AddresseeId == friendUserId) || + (f.RequesterId == friendUserId && f.AddresseeId == targetUserId))); + + if (!isFriendshipAccepted) + { + var errorMessage = string.Format(FriendshipNotAcceptedError, targetUserId, friendUserId); + _logger.LogError(errorMessage); + throw new FriendshipException(errorMessage); + } + + _logger.LogInformation("Friendship verified successfully for targetUserId={TargetUserId}, friendUserId={FriendUserId}", targetUserId, friendUserId); + } + + public async Task TryVerifyAsync(Guid targetUserId, Guid friendUserId) + { + if (targetUserId == Guid.Empty || friendUserId == Guid.Empty) + { + return false; + } + + return await _dbContext.Friendships + .AsNoTracking() + .AnyAsync(f => f.Status == FriendshipStatus.Accepted && + ((f.RequesterId == targetUserId && f.AddresseeId == friendUserId) || + (f.RequesterId == friendUserId && f.AddresseeId == targetUserId))); + } +} diff --git a/Govor.Application/Govor.Application.csproj b/Govor.Application/Govor.Application.csproj index 7b3731b..3fc6ad7 100644 --- a/Govor.Application/Govor.Application.csproj +++ b/Govor.Application/Govor.Application.csproj @@ -6,19 +6,23 @@ enable - - - - - + + + + + + + + + diff --git a/Govor.Application/Interfaces/IGroupService.cs b/Govor.Application/Groups/IGroupService.cs similarity index 79% rename from Govor.Application/Interfaces/IGroupService.cs rename to Govor.Application/Groups/IGroupService.cs index c3a8a40..830b079 100644 --- a/Govor.Application/Interfaces/IGroupService.cs +++ b/Govor.Application/Groups/IGroupService.cs @@ -1,8 +1,8 @@ -using Govor.Application.Interfaces.Messages.Parameters; -using Govor.Core.Models; -using Govor.Core.Models.Users; +using Govor.Domain.Common; +using Govor.Domain.Models; +using Govor.Domain.Models.Users; -namespace Govor.Application.Interfaces; +namespace Govor.Application.Groups; public interface IGroupService { diff --git a/Govor.Application/Interfaces/IUserGroupsGetterService.cs b/Govor.Application/Groups/IUserGroupsGetterService.cs similarity index 61% rename from Govor.Application/Interfaces/IUserGroupsGetterService.cs rename to Govor.Application/Groups/IUserGroupsGetterService.cs index a07ad39..184c924 100644 --- a/Govor.Application/Interfaces/IUserGroupsGetterService.cs +++ b/Govor.Application/Groups/IUserGroupsGetterService.cs @@ -1,6 +1,6 @@ -using Govor.Core.Models; +using Govor.Domain.Models; -namespace Govor.Application.Interfaces; +namespace Govor.Application.Groups; public interface IUserGroupsGetterService { diff --git a/Govor.Application/Groups/UserGroupsGetterService.cs b/Govor.Application/Groups/UserGroupsGetterService.cs new file mode 100644 index 0000000..3f0e283 --- /dev/null +++ b/Govor.Application/Groups/UserGroupsGetterService.cs @@ -0,0 +1,25 @@ +using Govor.Domain; +using Govor.Domain.Models; +using Microsoft.EntityFrameworkCore; + +namespace Govor.Application.Groups; + +public class UserGroupsGetterService : IUserGroupsGetterService +{ + private readonly GovorDbContext _context; + + public UserGroupsGetterService(GovorDbContext context) + { + _context = context; + } + + public async Task> GetUserGroupsAsync(Guid userId) + { + return await _context.GroupMemberships + .AsNoTracking() + .Where(m => m.UserId == userId) + .Select(m => m.ChatGroup) + .ToListAsync(); + } + +} \ No newline at end of file diff --git a/Govor.Application/Infrastructure/AdminsStuff/IInvitationGetter.cs b/Govor.Application/Infrastructure/AdminsStuff/IInvitationGetter.cs new file mode 100644 index 0000000..e34c12d --- /dev/null +++ b/Govor.Application/Infrastructure/AdminsStuff/IInvitationGetter.cs @@ -0,0 +1,10 @@ +using Govor.Domain.Common; +using Govor.Domain.Models; + +namespace Govor.Application.Infrastructure.AdminsStuff; + +public interface IInvitationGetter +{ + Task> GetAllAsync(); + Task> FindByIdAsync(Guid id); +} \ No newline at end of file diff --git a/Govor.Application/Interfaces/IInvitionGenerator.cs b/Govor.Application/Infrastructure/AdminsStuff/IInvitionGenerator.cs similarity index 73% rename from Govor.Application/Interfaces/IInvitionGenerator.cs rename to Govor.Application/Infrastructure/AdminsStuff/IInvitionGenerator.cs index 05d80c2..5009599 100644 --- a/Govor.Application/Interfaces/IInvitionGenerator.cs +++ b/Govor.Application/Infrastructure/AdminsStuff/IInvitionGenerator.cs @@ -1,4 +1,4 @@ -namespace Govor.Application.Interfaces; +namespace Govor.Application.Infrastructure.AdminsStuff; public interface IInvitationGenerator { diff --git a/Govor.Application/Interfaces/IUsersAdministration.cs b/Govor.Application/Infrastructure/AdminsStuff/IUsersAdministration.cs similarity index 66% rename from Govor.Application/Interfaces/IUsersAdministration.cs rename to Govor.Application/Infrastructure/AdminsStuff/IUsersAdministration.cs index da49e27..7168139 100644 --- a/Govor.Application/Interfaces/IUsersAdministration.cs +++ b/Govor.Application/Infrastructure/AdminsStuff/IUsersAdministration.cs @@ -1,6 +1,6 @@ -using Govor.Core.Models.Users; +using Govor.Domain.Models.Users; -namespace Govor.Application.Interfaces; +namespace Govor.Application.Infrastructure.AdminsStuff; public interface IUsersAdministration { diff --git a/Govor.Application/Infrastructure/AdminsStuff/InvitationGenerator.cs b/Govor.Application/Infrastructure/AdminsStuff/InvitationGenerator.cs index f2000b7..4e83563 100644 --- a/Govor.Application/Infrastructure/AdminsStuff/InvitationGenerator.cs +++ b/Govor.Application/Infrastructure/AdminsStuff/InvitationGenerator.cs @@ -1,10 +1,9 @@ -using Govor.Application.Interfaces; -using Govor.Core.Models; -using Govor.Core.Repositories.Invaites; +using Govor.Domain; +using Govor.Domain.Models; namespace Govor.Application.Infrastructure.AdminsStuff; -public class InvitationGenerator(IInvitesRepository repository) : IInvitationGenerator +public class InvitationGenerator(GovorDbContext context) : IInvitationGenerator { public async Task GenerateInvitationCode(DateTime time, int maxUsers, bool isAdmin, string description = "") { @@ -19,7 +18,9 @@ public class InvitationGenerator(IInvitesRepository repository) : IInvitationGen IsAdmin = isAdmin }; - await repository.AddAsync(newInvitation); + await context.Invitations.AddAsync(newInvitation); + + await context.SaveChangesAsync(); return newInvitation.Code; } diff --git a/Govor.Application/Infrastructure/AdminsStuff/InvitationGetter.cs b/Govor.Application/Infrastructure/AdminsStuff/InvitationGetter.cs new file mode 100644 index 0000000..961eaa1 --- /dev/null +++ b/Govor.Application/Infrastructure/AdminsStuff/InvitationGetter.cs @@ -0,0 +1,41 @@ +using Govor.Domain; +using Govor.Domain.Common; +using Govor.Domain.Models; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; + +namespace Govor.Application.Infrastructure.AdminsStuff; + +public class InvitationGetter : IInvitationGetter +{ + private readonly ILogger _logger; + private readonly GovorDbContext _context; + + public InvitationGetter(ILogger logger, GovorDbContext context) + { + _logger = logger; + _context = context; + } + + public async Task> GetAllAsync() + { + return await _context.Invitations + .AsNoTracking() + .Where(iv => iv.IsActive) + .ToListAsync(); + } + + public async Task> FindByIdAsync(Guid id) + { + var res = await _context.Invitations.AsNoTracking() + .FirstOrDefaultAsync(iv => iv.Id == id); + + if (res is null) + return Result.Failure(new Error( + nameof(InvalidOperationException), + "Invitation not found.") + ); + + return res; + } +} \ No newline at end of file diff --git a/Govor.Application/Infrastructure/AdminsStuff/UsersService.cs b/Govor.Application/Infrastructure/AdminsStuff/UsersService.cs index fa8ad21..0f4d982 100644 --- a/Govor.Application/Infrastructure/AdminsStuff/UsersService.cs +++ b/Govor.Application/Infrastructure/AdminsStuff/UsersService.cs @@ -1,54 +1,45 @@ -using Govor.Application.Interfaces; -using Govor.Core.Infrastructure.Extensions; -using Govor.Core.Models.Users; -using Govor.Core.Repositories.Users; -using Govor.Data.Repositories.Exceptions; +using Govor.Application.Authentication; +using Govor.Domain; +using Govor.Domain.Models.Users; +using Microsoft.EntityFrameworkCore; namespace Govor.Application.Infrastructure.AdminsStuff; public class UsersService : IUsersAdministration { - private readonly IUsersRepository _usersRepository; + private readonly GovorDbContext _context; private readonly IPasswordHasher _passwordHasher; - public UsersService(IUsersRepository usersRepository, IPasswordHasher passwordHasher) + public UsersService(GovorDbContext context, IPasswordHasher passwordHasher) { - _usersRepository = usersRepository; + _context = context; _passwordHasher = passwordHasher; } public async Task> GetAllUsersAsync() { - try - { - var results = await _usersRepository.GetAllAsync(); - return results; - } - catch (NotFoundException ex) - { - return new List(); - } + var results = await _context.Users + .AsNoTracking() + .Take(50) + .ToListAsync(); + return results; } public async Task SetPasswordAsync(Guid userId, string password) { - try - { - var user = await _usersRepository.FindByIdAsync(userId); - - user.PasswordHash = _passwordHasher.Hash(password); - - await _usersRepository.UpdateAsync(user); - } - catch (NotFoundException ex) - { - throw new NotFoundException(ex.Message); - } + var user = await GetUserById(userId); + + if (user is null) + return; + + user.PasswordHash = _passwordHasher.Hash(password); + + await _context.SaveChangesAsync(); } public async Task GetUserById(Guid userId) { - var result = await _usersRepository.FindByIdAsync(userId); + var result = await _context.Users.FirstOrDefaultAsync(user => user.Id == userId); return result; } diff --git a/Govor.Application/Infrastructure/Extensions/CurrentUserService.cs b/Govor.Application/Infrastructure/Extensions/CurrentUserService.cs index dfe4732..2a57b30 100644 --- a/Govor.Application/Infrastructure/Extensions/CurrentUserService.cs +++ b/Govor.Application/Infrastructure/Extensions/CurrentUserService.cs @@ -1,5 +1,3 @@ -using System.Security.Claims; -using Govor.Application.Interfaces.Infrastructure.Extensions; using Microsoft.AspNetCore.Http; namespace Govor.Application.Infrastructure.Extensions; diff --git a/Govor.Application/Infrastructure/Extensions/CurrentUserSessionService.cs b/Govor.Application/Infrastructure/Extensions/CurrentUserSessionService.cs index f986ab4..8af58b8 100644 --- a/Govor.Application/Infrastructure/Extensions/CurrentUserSessionService.cs +++ b/Govor.Application/Infrastructure/Extensions/CurrentUserSessionService.cs @@ -1,4 +1,3 @@ -using Govor.Application.Interfaces.Infrastructure.Extensions; using Microsoft.AspNetCore.Http; namespace Govor.Application.Infrastructure.Extensions; diff --git a/Govor.Application/Interfaces/IConnectionStore.cs b/Govor.Application/Infrastructure/Extensions/IConnectionStore.cs similarity index 78% rename from Govor.Application/Interfaces/IConnectionStore.cs rename to Govor.Application/Infrastructure/Extensions/IConnectionStore.cs index 3548722..2ded8fe 100644 --- a/Govor.Application/Interfaces/IConnectionStore.cs +++ b/Govor.Application/Infrastructure/Extensions/IConnectionStore.cs @@ -1,4 +1,4 @@ -namespace Govor.Application.Interfaces; +namespace Govor.Application.Infrastructure.Extensions; public interface IConnectionStore { diff --git a/Govor.Application/Interfaces/Infrastructure/Extensions/ICurrentUserService.cs b/Govor.Application/Infrastructure/Extensions/ICurrentUserService.cs similarity index 50% rename from Govor.Application/Interfaces/Infrastructure/Extensions/ICurrentUserService.cs rename to Govor.Application/Infrastructure/Extensions/ICurrentUserService.cs index 42e1156..b59e0f6 100644 --- a/Govor.Application/Interfaces/Infrastructure/Extensions/ICurrentUserService.cs +++ b/Govor.Application/Infrastructure/Extensions/ICurrentUserService.cs @@ -1,4 +1,4 @@ -namespace Govor.Application.Interfaces.Infrastructure.Extensions; +namespace Govor.Application.Infrastructure.Extensions; public interface ICurrentUserService { diff --git a/Govor.Application/Interfaces/Infrastructure/Extensions/ICurrentUserSessionService.cs b/Govor.Application/Infrastructure/Extensions/ICurrentUserSessionService.cs similarity index 53% rename from Govor.Application/Interfaces/Infrastructure/Extensions/ICurrentUserSessionService.cs rename to Govor.Application/Infrastructure/Extensions/ICurrentUserSessionService.cs index f4000a9..3d313d2 100644 --- a/Govor.Application/Interfaces/Infrastructure/Extensions/ICurrentUserSessionService.cs +++ b/Govor.Application/Infrastructure/Extensions/ICurrentUserSessionService.cs @@ -1,4 +1,4 @@ -namespace Govor.Application.Interfaces.Infrastructure.Extensions; +namespace Govor.Application.Infrastructure.Extensions; public interface ICurrentUserSessionService { diff --git a/Govor.Application/Interfaces/IFriendsService.cs b/Govor.Application/Infrastructure/Extensions/IFriendsService.cs similarity index 81% rename from Govor.Application/Interfaces/IFriendsService.cs rename to Govor.Application/Infrastructure/Extensions/IFriendsService.cs index 4933f6f..21fd1c1 100644 --- a/Govor.Application/Interfaces/IFriendsService.cs +++ b/Govor.Application/Infrastructure/Extensions/IFriendsService.cs @@ -1,7 +1,7 @@ -using Govor.Core.Models; -using Govor.Core.Models.Users; +using Govor.Domain.Models; +using Govor.Domain.Models.Users; -namespace Govor.Application.Interfaces; +namespace Govor.Application.Infrastructure.Extensions; public interface IFriendsService { diff --git a/Govor.Application/Infrastructure/Validators/IUsernameValidator.cs b/Govor.Application/Infrastructure/Validators/IUsernameValidator.cs new file mode 100644 index 0000000..46106c0 --- /dev/null +++ b/Govor.Application/Infrastructure/Validators/IUsernameValidator.cs @@ -0,0 +1,9 @@ +using Govor.Domain.Common; + +namespace Govor.Application.Infrastructure.Validators; + +public interface IUsernameValidator +{ + Result Validate(string username); + bool TryValidate(string username); +} \ No newline at end of file diff --git a/Govor.Application/Infrastructure/Validators/UsernameValidator.cs b/Govor.Application/Infrastructure/Validators/UsernameValidator.cs index c9b4953..4e9c531 100644 --- a/Govor.Application/Infrastructure/Validators/UsernameValidator.cs +++ b/Govor.Application/Infrastructure/Validators/UsernameValidator.cs @@ -1,13 +1,15 @@ using System.Text.RegularExpressions; -using Govor.Application.Exceptions.AuthService; -using Govor.Application.Interfaces.Authentication; -using Govor.Core.Infrastructure.Validators; +using Govor.Application.Authentication.Exceptions; +using Govor.Domain.Common.Constants; +using Govor.Domain.Common; using Microsoft.Extensions.Configuration; namespace Govor.Application.Infrastructure.Validators; public class UsernameValidator : IUsernameValidator { + private const string ErrorCode = nameof(InvalidUsernameException); + private readonly Regex _usernameRegex = new(@"^[А-Яа-яЁё]+[А-Яа-яЁё0-9]*$", RegexOptions.Compiled); private readonly HashSet _blockedExact; @@ -37,43 +39,61 @@ public class UsernameValidator : IUsernameValidator ?? throw new InvalidOperationException("Reserved not set"); } - public void Validate(string username) + public Result Validate(string username) { - if(username.Length < UserValidator.MIN_LENGHT_OF_NAME || username.Length > UserValidator.MAX_LENGHT_OF_NAME) - throw new InvalidUsernameException($"Username must be between {UserValidator.MIN_LENGHT_OF_NAME} and {UserValidator.MAX_LENGHT_OF_NAME} characters."); - - if (!_usernameRegex.IsMatch(username)) - throw new InvalidUsernameException("The username must be in Cyrillic and start with a letter."); + if (username.Length < UserConstants.MIN_LENGHT_OF_NAME || username.Length > UserConstants.MAX_LENGHT_OF_NAME) + { + return new Error( + ErrorCode, + $"Username must be between {UserConstants.MIN_LENGHT_OF_NAME} and {UserConstants.MAX_LENGHT_OF_NAME} characters."); + } + if (!_usernameRegex.IsMatch(username)) + { + return new Error( + ErrorCode, + "The username must be in Cyrillic and start with a letter."); + } + if (Regex.IsMatch(username, @"(.)\1{4,}")) - throw new InvalidUsernameException("Too many repeating characters."); + { + return new Error( + ErrorCode, + "Too many repeating characters."); + } var normalized = Normalize(username); - + if (_reserved.Contains(normalized)) - throw new InvalidUsernameException("This username is reserved."); - + { + return new Error( + ErrorCode, + "This username is reserved."); + } + if (_blockedExact.Contains(normalized)) - throw new InvalidUsernameException("This username is not allowed."); - + { + return new Error( + ErrorCode, + "This username is not allowed."); + } + foreach (var banned in _blockedContains) { if (normalized.Contains(banned)) - throw new InvalidUsernameException("Username contains prohibited content."); + { + return new Error( + ErrorCode, + "Username contains prohibited content."); + } } + + return Result.Success(); } public bool TryValidate(string username) { - try - { - Validate(username); - return true; - } - catch - { - return false; - } + return Validate(username).IsSuccess; } private static string Normalize(string username) @@ -87,4 +107,4 @@ public class UsernameValidator : IUsernameValidator .Replace("6", "б") .Replace("8", "в"); } -} \ No newline at end of file +} diff --git a/Govor.Application/Interfaces/Authentication/IAuthService.cs b/Govor.Application/Interfaces/Authentication/IAuthService.cs deleted file mode 100644 index 010e82c..0000000 --- a/Govor.Application/Interfaces/Authentication/IAuthService.cs +++ /dev/null @@ -1,10 +0,0 @@ -using Govor.Core.Models; -using Govor.Core.Models.Users; - -namespace Govor.Application.Interfaces.Authentication; - -public interface IAccountService -{ - public Task RegistrationAsync(string name, string password, Invitation invitation); - public Task LoginAsync(string name, string password); -} \ No newline at end of file diff --git a/Govor.Application/Interfaces/Authentication/IInvitesService.cs b/Govor.Application/Interfaces/Authentication/IInvitesService.cs deleted file mode 100644 index 86e24f8..0000000 --- a/Govor.Application/Interfaces/Authentication/IInvitesService.cs +++ /dev/null @@ -1,10 +0,0 @@ -using Govor.Core.Models; -using Govor.Core.Models.Users; - -namespace Govor.Application.Interfaces.Authentication; - -public interface IInvitesService -{ - public Task GetRoleAsync(User user); - public Task ValidateAsync(string inviteCode); -} \ No newline at end of file diff --git a/Govor.Application/Interfaces/Authentication/IUsernameValidator.cs b/Govor.Application/Interfaces/Authentication/IUsernameValidator.cs deleted file mode 100644 index 74fd6de..0000000 --- a/Govor.Application/Interfaces/Authentication/IUsernameValidator.cs +++ /dev/null @@ -1,8 +0,0 @@ -using Govor.Core.Infrastructure.Validators; - -namespace Govor.Application.Interfaces.Authentication; - -public interface IUsernameValidator : IObjectValidator -{ - -} \ No newline at end of file diff --git a/Govor.Application/Interfaces/Friends/IFriendRequestCommandService.cs b/Govor.Application/Interfaces/Friends/IFriendRequestCommandService.cs deleted file mode 100644 index 3d3c4e4..0000000 --- a/Govor.Application/Interfaces/Friends/IFriendRequestCommandService.cs +++ /dev/null @@ -1,10 +0,0 @@ -using Govor.Core.Models; - -namespace Govor.Application.Interfaces.Friends; - -public interface IFriendRequestCommandService -{ - Task SendAsync(Guid fromUserId, Guid toUserId); - Task AcceptAsync(Guid requestId, Guid currentUserId); - Task RejectAsync(Guid requestId, Guid currentUserId); -} diff --git a/Govor.Application/Interfaces/IProfileService.cs b/Govor.Application/Interfaces/IProfileService.cs deleted file mode 100644 index 37a717f..0000000 --- a/Govor.Application/Interfaces/IProfileService.cs +++ /dev/null @@ -1,10 +0,0 @@ -using Govor.Application.Profiles; - -namespace Govor.Application.Interfaces; - -public interface IProfileService -{ - public Task GetUserProfileAsync(Guid userId); - public Task SetDescription(string description, Guid userId); - public Task SetNewIcon(Guid userId, Guid iconId); -} diff --git a/Govor.Application/Interfaces/IUserPrivateChatsGetterService.cs b/Govor.Application/Interfaces/IUserPrivateChatsGetterService.cs deleted file mode 100644 index 53dee37..0000000 --- a/Govor.Application/Interfaces/IUserPrivateChatsGetterService.cs +++ /dev/null @@ -1,8 +0,0 @@ -using Govor.Core.Models; - -namespace Govor.Application.Interfaces; - -public interface IUserPrivateChatsGetterService -{ - Task> GetUserChatsAsync(Guid userId); -} \ No newline at end of file diff --git a/Govor.Application/Interfaces/Messages/IMessageCommandService.cs b/Govor.Application/Interfaces/Messages/IMessageCommandService.cs deleted file mode 100644 index b927074..0000000 --- a/Govor.Application/Interfaces/Messages/IMessageCommandService.cs +++ /dev/null @@ -1,30 +0,0 @@ -using Govor.Application.Interfaces.Messages.Parameters; -using Govor.Core.Models.Messages; - -namespace Govor.Application.Interfaces.Messages; - -// Combining IChatService and IGroupService functionalities relevant to messages -public interface IMessageCommandService -{ - Task SendMessageAsync(SendMessage messageParameters); - Task EditMessageAsync(EditMessage messageParameters); - Task DeleteMessageAsync(DeleteMessage messageParameters); - - // Potentially other message-related methods like: - // Task GetMessagesAsync(Guid userId, Guid chatId, RecipientType chatType, int pageNumber, int pageSize); - // Task MarkMessageAsReadAsync(Guid userId, Guid messageId); -} - - - -public record SendMessageResult(bool IsSuccess, Exception? Exception, Message Message) - : Result(IsSuccess, Exception, Message?.Id ?? Guid.Empty); - -public record EditMessageResult(bool IsSuccess, Exception? Exception, Message? OriginalMessage) - : Result(IsSuccess, Exception, OriginalMessage?.Id ?? Guid.Empty) -{ - -} - -public record DeleteMessageResult(bool IsSuccess, Exception? Exception, Message? OriginalMessage) - : Result(IsSuccess, Exception, OriginalMessage?.Id ?? Guid.Empty); diff --git a/Govor.Application/Interfaces/Messages/Parameters/DeleteMessage.cs b/Govor.Application/Interfaces/Messages/Parameters/DeleteMessage.cs deleted file mode 100644 index ceed39d..0000000 --- a/Govor.Application/Interfaces/Messages/Parameters/DeleteMessage.cs +++ /dev/null @@ -1,5 +0,0 @@ -namespace Govor.Application.Interfaces.Messages.Parameters; - -public record DeleteMessage( - Guid DeleterId, - Guid MessageId); \ No newline at end of file diff --git a/Govor.Application/Interfaces/Messages/Parameters/Result.cs b/Govor.Application/Interfaces/Messages/Parameters/Result.cs deleted file mode 100644 index 7151e86..0000000 --- a/Govor.Application/Interfaces/Messages/Parameters/Result.cs +++ /dev/null @@ -1,3 +0,0 @@ -namespace Govor.Application.Interfaces.Messages.Parameters; - -public record Result(bool IsSuccess, Exception Exception, Guid messageId); \ No newline at end of file diff --git a/Govor.Application/Interfaces/Messages/Parameters/SendMedia.cs b/Govor.Application/Interfaces/Messages/Parameters/SendMedia.cs deleted file mode 100644 index e07b452..0000000 --- a/Govor.Application/Interfaces/Messages/Parameters/SendMedia.cs +++ /dev/null @@ -1,5 +0,0 @@ -using Govor.Core.Models; - -namespace Govor.Application.Interfaces.Messages.Parameters; - -public record SendMedia(Guid MediaId, string EncryptedKey); \ No newline at end of file diff --git a/Govor.Application/Interfaces/PushNotifications/IPushNotificationService.cs b/Govor.Application/Interfaces/PushNotifications/IPushNotificationService.cs deleted file mode 100644 index e7872fa..0000000 --- a/Govor.Application/Interfaces/PushNotifications/IPushNotificationService.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Govor.Application.Interfaces.PushNotifications; - -public interface IPushNotificationService -{ - Task SendToUserAsync(Guid userId, string title, string body, string channelId, string tag = "", Dictionary? data = null); - - Task SendToUsersAsync(IEnumerable userIds, string title, string body, string channelId, string tag = "", Dictionary? data = null); - - Task SendToSessionAsync(Guid sessionId, string title, string body, string channelId, string tag = "", Dictionary? data = null); -} \ No newline at end of file diff --git a/Govor.Application/Interfaces/UserSession/IUserSessionOpener.cs b/Govor.Application/Interfaces/UserSession/IUserSessionOpener.cs deleted file mode 100644 index 243688c..0000000 --- a/Govor.Application/Interfaces/UserSession/IUserSessionOpener.cs +++ /dev/null @@ -1,10 +0,0 @@ -using Govor.Core.Models.Users; - -namespace Govor.Application.Interfaces.UserSession; - - -public interface IUserSessionOpener -{ - Task OpenSessionAsync(User user, string deviceInfo); -} - diff --git a/Govor.Application/Interfaces/UserSession/IUserSessionReader.cs b/Govor.Application/Interfaces/UserSession/IUserSessionReader.cs deleted file mode 100644 index 3800917..0000000 --- a/Govor.Application/Interfaces/UserSession/IUserSessionReader.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Govor.Application.Interfaces.UserSession; - -public interface IUserSessionReader -{ - Task> GetAllSessionsAsync(Guid userId); -} diff --git a/Govor.Application/Interfaces/UserSession/IUserSessionRefresher.cs b/Govor.Application/Interfaces/UserSession/IUserSessionRefresher.cs deleted file mode 100644 index 1020f96..0000000 --- a/Govor.Application/Interfaces/UserSession/IUserSessionRefresher.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Govor.Application.Interfaces.UserSession; - -public interface IUserSessionRefresher -{ - Task RefreshTokenAsync(string refreshToken); -} - -public record RefreshResult(string refreshToken, string accessToken); \ No newline at end of file diff --git a/Govor.Application/Interfaces/UserSession/IUserSessionRevoker.cs b/Govor.Application/Interfaces/UserSession/IUserSessionRevoker.cs deleted file mode 100644 index af256fa..0000000 --- a/Govor.Application/Interfaces/UserSession/IUserSessionRevoker.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Govor.Application.Interfaces.UserSession; - - -public interface IUserSessionRevoker -{ - Task CloseSessionByIdAsync(Guid sessionId, Guid userId); - Task CloseAllSessionsAsync(Guid userId); -} diff --git a/Govor.Application/Services/Medias/AccesserToDownloadMediaService.cs b/Govor.Application/Medias/AccesserToDownloadMediaService.cs similarity index 91% rename from Govor.Application/Services/Medias/AccesserToDownloadMediaService.cs rename to Govor.Application/Medias/AccesserToDownloadMediaService.cs index c92c024..6fee042 100644 --- a/Govor.Application/Services/Medias/AccesserToDownloadMediaService.cs +++ b/Govor.Application/Medias/AccesserToDownloadMediaService.cs @@ -1,9 +1,8 @@ -using Govor.Application.Interfaces.Medias; -using Govor.Core.Models; -using Govor.Data; +using Govor.Domain.Models; +using Govor.Domain; using Microsoft.EntityFrameworkCore; -namespace Govor.Application.Services.Medias; +namespace Govor.Application.Medias; public class AccesserToDownloadMediaService : IAccesserToDownloadMedia { diff --git a/Govor.Application/Interfaces/Medias/IAccesserToDownloadMedia.cs b/Govor.Application/Medias/IAccesserToDownloadMedia.cs similarity index 69% rename from Govor.Application/Interfaces/Medias/IAccesserToDownloadMedia.cs rename to Govor.Application/Medias/IAccesserToDownloadMedia.cs index a55669e..600296f 100644 --- a/Govor.Application/Interfaces/Medias/IAccesserToDownloadMedia.cs +++ b/Govor.Application/Medias/IAccesserToDownloadMedia.cs @@ -1,4 +1,4 @@ -namespace Govor.Application.Interfaces.Medias; +namespace Govor.Application.Medias; public interface IAccesserToDownloadMedia { diff --git a/Govor.Application/Interfaces/Medias/IMediaService.cs b/Govor.Application/Medias/IMediaService.cs similarity index 79% rename from Govor.Application/Interfaces/Medias/IMediaService.cs rename to Govor.Application/Medias/IMediaService.cs index 53def6b..8e52df9 100644 --- a/Govor.Application/Interfaces/Medias/IMediaService.cs +++ b/Govor.Application/Medias/IMediaService.cs @@ -1,7 +1,7 @@ -using Govor.Core.Models; -using Govor.Core.Models.Messages; +using Govor.Domain.Models; +using Govor.Domain.Models.Messages; -namespace Govor.Application.Interfaces.Medias; +namespace Govor.Application.Medias; public interface IMediaService { diff --git a/Govor.Application/Services/Medias/MediaService.cs b/Govor.Application/Medias/MediaService.cs similarity index 96% rename from Govor.Application/Services/Medias/MediaService.cs rename to Govor.Application/Medias/MediaService.cs index 828e6e8..b0adbd6 100644 --- a/Govor.Application/Services/Medias/MediaService.cs +++ b/Govor.Application/Medias/MediaService.cs @@ -1,11 +1,10 @@ -using Govor.Application.Interfaces; -using Govor.Application.Interfaces.Medias; -using Govor.Core.Models; -using Govor.Data; +using Govor.Application.Storage; +using Govor.Domain.Models; +using Govor.Domain; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; -namespace Govor.Application.Services.Medias; +namespace Govor.Application.Medias; public class MediaService : IMediaService { diff --git a/Govor.Application/Messages/IMessageEditingService.cs b/Govor.Application/Messages/IMessageEditingService.cs new file mode 100644 index 0000000..f94258d --- /dev/null +++ b/Govor.Application/Messages/IMessageEditingService.cs @@ -0,0 +1,8 @@ +using Govor.Application.Messages.Parameters; + +namespace Govor.Application.Messages; + +public interface IMessageEditingService +{ + Task EditMessageAsync(EditMessage editParams); +} \ No newline at end of file diff --git a/Govor.Application/Messages/IMessageRemovingService.cs b/Govor.Application/Messages/IMessageRemovingService.cs new file mode 100644 index 0000000..041e71f --- /dev/null +++ b/Govor.Application/Messages/IMessageRemovingService.cs @@ -0,0 +1,8 @@ +using Govor.Application.Messages.Parameters; + +namespace Govor.Application.Messages; + +public interface IMessageRemovingService +{ + Task DeleteMessageAsync(DeleteMessage deleteParams); +} \ No newline at end of file diff --git a/Govor.Application/Messages/IMessageSendingService.cs b/Govor.Application/Messages/IMessageSendingService.cs new file mode 100644 index 0000000..13b713f --- /dev/null +++ b/Govor.Application/Messages/IMessageSendingService.cs @@ -0,0 +1,8 @@ +using Govor.Application.Messages.Parameters; + +namespace Govor.Application.Messages; + +public interface IMessageSendingService +{ + Task SendMessageAsync(SendMessage sendParams); +} \ No newline at end of file diff --git a/Govor.Application/Interfaces/IMessagesLoader.cs b/Govor.Application/Messages/IMessagesLoader.cs similarity index 80% rename from Govor.Application/Interfaces/IMessagesLoader.cs rename to Govor.Application/Messages/IMessagesLoader.cs index 67633e1..e6591a5 100644 --- a/Govor.Application/Interfaces/IMessagesLoader.cs +++ b/Govor.Application/Messages/IMessagesLoader.cs @@ -1,6 +1,6 @@ -using Govor.Core.Models.Messages; +using Govor.Domain.Models.Messages; -namespace Govor.Application.Interfaces; +namespace Govor.Application.Messages; public interface IMessagesLoader { diff --git a/Govor.Application/Messages/MessageEditingService.cs b/Govor.Application/Messages/MessageEditingService.cs new file mode 100644 index 0000000..fce9b21 --- /dev/null +++ b/Govor.Application/Messages/MessageEditingService.cs @@ -0,0 +1,57 @@ +using Govor.Application.Messages.Parameters; +using Microsoft.EntityFrameworkCore; +using Govor.Domain; +using Govor.Domain.Models.Messages; +using Microsoft.Extensions.Logging; + +namespace Govor.Application.Messages; + +public class MessageEditingService : IMessageEditingService +{ + private readonly GovorDbContext _dbContext; + private readonly ILogger _logger; + + public MessageEditingService(GovorDbContext dbContext, ILogger logger) + { + _dbContext = dbContext; + _logger = logger; + } + + public async Task EditMessageAsync(EditMessage editParams) + { + var message = await _dbContext.Messages + .Include(m => m.MediaAttachments) + .FirstOrDefaultAsync(m => m.Id == editParams.MessageId); + + if (message == null) + { + return new EditMessageResult(false, new KeyNotFoundException("Message not found."), null); + } + + if (message.SenderId != editParams.EditorId) + { + _logger.LogWarning("User {EditorId} unauthorized to edit message {MessageId}", editParams.EditorId, editParams.MessageId); + return new EditMessageResult(false, new UnauthorizedAccessException("User is not authorized to edit this message."), null); + } + + var originalMessageSnapshot = new Message + { + Id = message.Id, + SenderId = message.SenderId, + RecipientId = message.RecipientId, + RecipientType = message.RecipientType, + SentAt = message.SentAt, + ReplyToMessageId = message.ReplyToMessageId, + MediaAttachments = message.MediaAttachments?.ToList() ?? [] + }; + + message.EncryptedContent = editParams.NewContent; + message.IsEdited = true; + message.EditedAt = editParams.EditedAt; + + await _dbContext.SaveChangesAsync(); + + _logger.LogInformation("Message {MessageId} edited successfully.", editParams.MessageId); + return new EditMessageResult(true, null, originalMessageSnapshot); + } +} diff --git a/Govor.Application/Messages/MessageRemovingService.cs b/Govor.Application/Messages/MessageRemovingService.cs new file mode 100644 index 0000000..51f6f59 --- /dev/null +++ b/Govor.Application/Messages/MessageRemovingService.cs @@ -0,0 +1,24 @@ +using Govor.Application.Messages.Parameters; +using Govor.Domain; +using Microsoft.Extensions.Logging; + +namespace Govor.Application.Messages; + +public class MessageRemovingService : IMessageRemovingService +{ + private readonly GovorDbContext _govorDbContext; + private readonly ILogger _logger; + + public MessageRemovingService + (GovorDbContext govorDbContext, + ILogger logger) + { + _govorDbContext = govorDbContext; + _logger = logger; + } + + public Task DeleteMessageAsync(DeleteMessage deleteParams) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/Govor.Application/Messages/MessageSendingService.cs b/Govor.Application/Messages/MessageSendingService.cs new file mode 100644 index 0000000..b6c318b --- /dev/null +++ b/Govor.Application/Messages/MessageSendingService.cs @@ -0,0 +1,77 @@ +using Govor.Application.Messages.Parameters; +using Microsoft.EntityFrameworkCore; +using Govor.Domain; +using Govor.Domain.Models.Messages; +using Microsoft.Extensions.Logging; + +namespace Govor.Application.Messages; + +public class MessageSendingService : IMessageSendingService +{ + private readonly GovorDbContext _dbContext; + private readonly ILogger _logger; + + public MessageSendingService(GovorDbContext dbContext, ILogger logger) + { + _dbContext = dbContext; + _logger = logger; + } + + public async Task SendMessageAsync(SendMessage sendParams) + { + var validationResult = sendParams.RecipientType switch + { + RecipientType.User => await ValidateUserRecipientAsync(sendParams.RecipientId), + RecipientType.Group => await ValidateGroupRecipientAsync(sendParams.FromUserId, sendParams.RecipientId), + _ => (Success: false, Error: "Invalid recipient type.") + }; + + if (!validationResult.Success) + { + _logger.LogWarning("Message send failed: {Error}", validationResult.Error); + return new SendMessageResult(false, new InvalidOperationException(validationResult.Error), default); + } + + var messageId = Guid.NewGuid(); + var message = new Message + { + Id = messageId, + SenderId = sendParams.FromUserId, + RecipientId = sendParams.RecipientId, + RecipientType = sendParams.RecipientType, + EncryptedContent = sendParams.EncryptContent, + SentAt = sendParams.SendAt, + IsEdited = false, + ReplyToMessageId = sendParams.ReplyToMessageId, + MediaAttachments = sendParams.Media?.Select(m => new MediaAttachments + { + Id = Guid.NewGuid(), + MessageId = messageId, + MediaFileId = m.MediaId + }).ToList() ?? [] + }; + + await _dbContext.Messages.AddAsync(message); + await _dbContext.SaveChangesAsync(); + + _logger.LogInformation("Message {MessageId} sent successfully.", messageId); + return new SendMessageResult(true, null, message); + } + + private async Task<(bool Success, string Error)> ValidateUserRecipientAsync(Guid chatId) + { + var chatExists = await _dbContext.PrivateChats.AnyAsync(c => c.Id == chatId); + return chatExists ? (true, null) : (false, $"Private chat {chatId} not found."); + } + + private async Task<(bool Success, string Error)> ValidateGroupRecipientAsync(Guid userId, Guid groupId) + { + var groupExists = await _dbContext.ChatGroups.AnyAsync(g => g.Id == groupId); + if (!groupExists) return (false, $"Group {groupId} not found."); + + var isMember = await _dbContext.GroupMemberships.AnyAsync(gm => gm.UserId == userId && gm.GroupId == groupId); + if (!isMember) return (false, "Sender is not a member of the group."); + + return (true, null); + } +} diff --git a/Govor.Application/Messages/MessagesLoader.cs b/Govor.Application/Messages/MessagesLoader.cs new file mode 100644 index 0000000..ba11f1e --- /dev/null +++ b/Govor.Application/Messages/MessagesLoader.cs @@ -0,0 +1,107 @@ +using Govor.Application.Interfaces; +using Govor.Domain.Models.Messages; +using Govor.Domain; +using Microsoft.EntityFrameworkCore; + +namespace Govor.Application.Messages; + +public class MessagesLoader : IMessagesLoader +{ + private readonly GovorDbContext _dbContext; + + public MessagesLoader(GovorDbContext dbContext) + { + _dbContext = dbContext; + } + + public async Task> LoadMessagesInUserChat( + Guid privateChatId, + Guid currentUser, + Guid? startMessageId, + int before = 20, + int after = 2) + { + if (privateChatId == Guid.Empty) + throw new ArgumentException("PrivateChatId id cannot be empty", nameof(privateChatId)); + + var chatExists = await _dbContext.PrivateChats.AnyAsync(c => c.Id == privateChatId); + if (!chatExists) + return []; + + var query = _dbContext.Messages + .AsNoTracking() + .Include(m => m.MediaAttachments) + .ThenInclude(m => m.MediaFile) + .Where(m => m.RecipientType == RecipientType.User && m.RecipientId == privateChatId); + + return await FetchPaginatedMessagesAsync(query, startMessageId, before, after); + } + + public async Task> LoadMessagesInChatGroup( + Guid chatId, + Guid currentUser, + Guid? startMessageId, + int before = 20, + int after = 2) + { + if (chatId == Guid.Empty) + throw new ArgumentException("Chat id cannot be empty", nameof(chatId)); + + var isMember = await _dbContext.GroupMemberships + .AnyAsync(gm => gm.UserId == currentUser && gm.GroupId == chatId); + + if (!isMember) + return []; + + var query = _dbContext.Messages + .AsNoTracking() + .Include(m => m.MediaAttachments) + .ThenInclude(m => m.MediaFile) + .AsSplitQuery() + .Where(m => m.RecipientType == RecipientType.Group && m.RecipientId == chatId); + + return await FetchPaginatedMessagesAsync(query, startMessageId, before, after); + } + + private static async Task> FetchPaginatedMessagesAsync( + IQueryable baseQuery, + Guid? startMessageId, + int before, + int after) + { + if (startMessageId is null) + { + return await baseQuery + .OrderByDescending(m => m.SentAt) + .Take(before) + .OrderBy(m => m.SentAt) + .ToListAsync(); + } + + var startMessage = await baseQuery.FirstOrDefaultAsync(m => m.Id == startMessageId.Value); + if (startMessage == null) + return []; + + var beforeMessages = await baseQuery + .Where(m => m.SentAt < startMessage.SentAt) + .OrderByDescending(m => m.SentAt) + .Take(before) + .ToListAsync(); + + var afterMessages = await baseQuery + .Where(m => m.SentAt > startMessage.SentAt) + .OrderBy(m => m.SentAt) + .Take(after) + .ToListAsync(); + + + beforeMessages.Reverse(); + + var result = new List(beforeMessages.Count + 1 + afterMessages.Count); + result.AddRange(beforeMessages); + result.Add(startMessage); + result.AddRange(afterMessages); + + return result; + } +} diff --git a/Govor.Application/Messages/Parameters/DeleteMessage.cs b/Govor.Application/Messages/Parameters/DeleteMessage.cs new file mode 100644 index 0000000..409c848 --- /dev/null +++ b/Govor.Application/Messages/Parameters/DeleteMessage.cs @@ -0,0 +1,5 @@ +namespace Govor.Application.Messages.Parameters; + +public record DeleteMessage( + Guid DeleterId, + Guid MessageId); \ No newline at end of file diff --git a/Govor.Application/Messages/Parameters/DeleteMessageResult.cs b/Govor.Application/Messages/Parameters/DeleteMessageResult.cs new file mode 100644 index 0000000..39e8a89 --- /dev/null +++ b/Govor.Application/Messages/Parameters/DeleteMessageResult.cs @@ -0,0 +1,6 @@ +using Govor.Domain.Models.Messages; + +namespace Govor.Application.Messages.Parameters; + +public record DeleteMessageResult(bool IsSuccess, Exception? Exception, Message? OriginalMessage) + : Result(IsSuccess, Exception, OriginalMessage?.Id ?? Guid.Empty); diff --git a/Govor.Application/Interfaces/Messages/Parameters/EditMessage.cs b/Govor.Application/Messages/Parameters/EditMessage.cs similarity index 52% rename from Govor.Application/Interfaces/Messages/Parameters/EditMessage.cs rename to Govor.Application/Messages/Parameters/EditMessage.cs index 4c0e6af..f167df7 100644 --- a/Govor.Application/Interfaces/Messages/Parameters/EditMessage.cs +++ b/Govor.Application/Messages/Parameters/EditMessage.cs @@ -1,4 +1,4 @@ -namespace Govor.Application.Interfaces.Messages.Parameters; +namespace Govor.Application.Messages.Parameters; public record EditMessage( Guid EditorId, diff --git a/Govor.Application/Messages/Parameters/EditMessageResult.cs b/Govor.Application/Messages/Parameters/EditMessageResult.cs new file mode 100644 index 0000000..759c0c4 --- /dev/null +++ b/Govor.Application/Messages/Parameters/EditMessageResult.cs @@ -0,0 +1,9 @@ +using Govor.Domain.Models.Messages; + +namespace Govor.Application.Messages.Parameters; + +public record EditMessageResult(bool IsSuccess, Exception? Exception, Message? OriginalMessage) + : Result(IsSuccess, Exception, OriginalMessage?.Id ?? Guid.Empty) +{ + +} \ No newline at end of file diff --git a/Govor.Application/Messages/Parameters/Result.cs b/Govor.Application/Messages/Parameters/Result.cs new file mode 100644 index 0000000..b548135 --- /dev/null +++ b/Govor.Application/Messages/Parameters/Result.cs @@ -0,0 +1,3 @@ +namespace Govor.Application.Messages.Parameters; + +public record Result(bool IsSuccess, Exception Exception, Guid messageId); \ No newline at end of file diff --git a/Govor.Application/Messages/Parameters/SendMedia.cs b/Govor.Application/Messages/Parameters/SendMedia.cs new file mode 100644 index 0000000..13333fc --- /dev/null +++ b/Govor.Application/Messages/Parameters/SendMedia.cs @@ -0,0 +1,3 @@ +namespace Govor.Application.Messages.Parameters; + +public record SendMedia(Guid MediaId, string EncryptedKey); \ No newline at end of file diff --git a/Govor.Application/Interfaces/Messages/Parameters/SendMessage.cs b/Govor.Application/Messages/Parameters/SendMessage.cs similarity index 58% rename from Govor.Application/Interfaces/Messages/Parameters/SendMessage.cs rename to Govor.Application/Messages/Parameters/SendMessage.cs index 3f68d10..5bdcf46 100644 --- a/Govor.Application/Interfaces/Messages/Parameters/SendMessage.cs +++ b/Govor.Application/Messages/Parameters/SendMessage.cs @@ -1,6 +1,6 @@ -using Govor.Core.Models.Messages; +using Govor.Domain.Models.Messages; -namespace Govor.Application.Interfaces.Messages.Parameters; +namespace Govor.Application.Messages.Parameters; public record SendMessage( string EncryptContent, diff --git a/Govor.Application/Messages/Parameters/SendMessageResult.cs b/Govor.Application/Messages/Parameters/SendMessageResult.cs new file mode 100644 index 0000000..61ae63f --- /dev/null +++ b/Govor.Application/Messages/Parameters/SendMessageResult.cs @@ -0,0 +1,6 @@ +using Govor.Domain.Models.Messages; + +namespace Govor.Application.Messages.Parameters; + +public record SendMessageResult(bool IsSuccess, Exception? Exception, Message Message) + : Result(IsSuccess, Exception, Message?.Id ?? Guid.Empty); \ No newline at end of file diff --git a/Govor.Application/Interfaces/IPingHandlerService.cs b/Govor.Application/PingHandler/IPingHandlerService.cs similarity index 61% rename from Govor.Application/Interfaces/IPingHandlerService.cs rename to Govor.Application/PingHandler/IPingHandlerService.cs index fe3fa0f..366a5d0 100644 --- a/Govor.Application/Interfaces/IPingHandlerService.cs +++ b/Govor.Application/PingHandler/IPingHandlerService.cs @@ -1,4 +1,4 @@ -namespace Govor.Application.Interfaces; +namespace Govor.Application.PingHandler; public interface IPingHandlerService { diff --git a/Govor.Application/Services/PingHandlerService.cs b/Govor.Application/PingHandler/PingHandlerService.cs similarity index 90% rename from Govor.Application/Services/PingHandlerService.cs rename to Govor.Application/PingHandler/PingHandlerService.cs index 1cc0e37..ac50d75 100644 --- a/Govor.Application/Services/PingHandlerService.cs +++ b/Govor.Application/PingHandler/PingHandlerService.cs @@ -1,9 +1,8 @@ -using Govor.Application.Interfaces; -using Govor.Data; +using Govor.Domain; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Caching.Memory; -namespace Govor.Application.Services; +namespace Govor.Application.PingHandler; public class PingHandlerService : IPingHandlerService { diff --git a/Govor.Application/Interfaces/IPrivateChatGroupManager.cs b/Govor.Application/PrivateUserChats/IPrivateChatGroupManager.cs similarity index 71% rename from Govor.Application/Interfaces/IPrivateChatGroupManager.cs rename to Govor.Application/PrivateUserChats/IPrivateChatGroupManager.cs index 5d09ed7..7031008 100644 --- a/Govor.Application/Interfaces/IPrivateChatGroupManager.cs +++ b/Govor.Application/PrivateUserChats/IPrivateChatGroupManager.cs @@ -1,6 +1,6 @@ -using Govor.Core.Models; +using Govor.Domain.Models; -namespace Govor.Application.Interfaces; +namespace Govor.Application.PrivateUserChats; public interface IPrivateChatGroupManager { diff --git a/Govor.Application/Interfaces/IUserPrivateChatsCreator.cs b/Govor.Application/PrivateUserChats/IUserPrivateChatsCreator.cs similarity index 59% rename from Govor.Application/Interfaces/IUserPrivateChatsCreator.cs rename to Govor.Application/PrivateUserChats/IUserPrivateChatsCreator.cs index 674c705..f4846a6 100644 --- a/Govor.Application/Interfaces/IUserPrivateChatsCreator.cs +++ b/Govor.Application/PrivateUserChats/IUserPrivateChatsCreator.cs @@ -1,6 +1,6 @@ -using Govor.Core.Models; +using Govor.Domain.Models; -namespace Govor.Application.Interfaces; +namespace Govor.Application.PrivateUserChats; public interface IUserPrivateChatsCreator { diff --git a/Govor.Application/PrivateUserChats/IUserPrivateChatsGetterService.cs b/Govor.Application/PrivateUserChats/IUserPrivateChatsGetterService.cs new file mode 100644 index 0000000..412427e --- /dev/null +++ b/Govor.Application/PrivateUserChats/IUserPrivateChatsGetterService.cs @@ -0,0 +1,11 @@ +using Govor.Domain.Common; +using Govor.Domain.Models; + +namespace Govor.Application.PrivateUserChats; + +public interface IUserPrivateChatsGetterService +{ + Task> GetUserChatsAsync(Guid userId); + Task> GetPrivateChatAsync(Guid chatId); + Task ExistChatAsync(Guid userIdA, Guid userIdB); +} \ No newline at end of file diff --git a/Govor.Application/Services/UserPrivateChatsCreator.cs b/Govor.Application/PrivateUserChats/UserPrivateChatsCreator.cs similarity index 51% rename from Govor.Application/Services/UserPrivateChatsCreator.cs rename to Govor.Application/PrivateUserChats/UserPrivateChatsCreator.cs index 2e2d8c9..600047d 100644 --- a/Govor.Application/Services/UserPrivateChatsCreator.cs +++ b/Govor.Application/PrivateUserChats/UserPrivateChatsCreator.cs @@ -1,46 +1,52 @@ -using Govor.Application.Interfaces; -using Govor.Core.Models; -using Govor.Core.Repositories.PrivateChats; +using Govor.Domain; +using Govor.Domain.Models; +using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; -namespace Govor.Application.Services; +namespace Govor.Application.PrivateUserChats; public class UserPrivateChatsCreator : IUserPrivateChatsCreator { - private readonly IPrivateChatsRepository _privateChats; + private readonly GovorDbContext _context; private readonly IPrivateChatGroupManager _privateChatGroupManager; private readonly ILogger _logger; public UserPrivateChatsCreator( - IPrivateChatsRepository privateChats, + GovorDbContext context, IPrivateChatGroupManager privateChatGroupManager, ILogger logger) { - _privateChats = privateChats; + _context = context; _privateChatGroupManager = privateChatGroupManager; _logger = logger; } public async Task CreateAsync(Guid userIdA, Guid userIdB) { - if (!_privateChats.Exist(userIdA, userIdB)) + var existingChat = await _context.PrivateChats + .FirstOrDefaultAsync(c => (c.UserAId == userIdA && c.UserBId == userIdB) || + (c.UserAId == userIdB && c.UserBId == userIdA)); + + if (existingChat is null) { var recipientId = Guid.NewGuid(); - var privateChat = new PrivateChat() + var privateChat = new PrivateChat { Id = recipientId, UserAId = userIdA, UserBId = userIdB }; - await _privateChats.AddAsync(privateChat); - await _privateChatGroupManager.AddUsersToPrivateChatGroupAsync(privateChat); // Notifying + await _context.PrivateChats.AddAsync(privateChat); + await _context.SaveChangesAsync(); - _logger.LogInformation($"User for {userIdA} and {userIdB} was created private chat with Id: {recipientId}"); + await _privateChatGroupManager.AddUsersToPrivateChatGroupAsync(privateChat); + + _logger.LogInformation($"Private chat created with Id: {recipientId} for users {userIdA} and {userIdB}"); return privateChat; } - _logger.LogInformation($"Private chat already exists for {userIdA} and {userIdB}; Returning already created chat..."); - return await _privateChats.GetByMembersAsync(userIdA, userIdB); + _logger.LogInformation($"Private chat already exists for {userIdA} and {userIdB}; Returning existing chat..."); + return existingChat; } } \ No newline at end of file diff --git a/Govor.Application/PrivateUserChats/UserPrivateChatsGetter.cs b/Govor.Application/PrivateUserChats/UserPrivateChatsGetter.cs new file mode 100644 index 0000000..9773a2e --- /dev/null +++ b/Govor.Application/PrivateUserChats/UserPrivateChatsGetter.cs @@ -0,0 +1,46 @@ +using Govor.Domain; +using Govor.Domain.Common; +using Govor.Domain.Models; +using Microsoft.EntityFrameworkCore; + +namespace Govor.Application.PrivateUserChats; + +public class UserPrivateChatsGetter : IUserPrivateChatsGetterService +{ + private readonly GovorDbContext _context; + + public UserPrivateChatsGetter(GovorDbContext context) + { + _context = context; + } + + public async Task> GetUserChatsAsync(Guid userId) + { + return await _context.PrivateChats + .AsNoTracking() + .Where(p => p.UserAId == userId || p.UserBId == userId) + .ToListAsync(); + } + + public async Task> GetPrivateChatAsync(Guid chatId) + { + var res = await _context.PrivateChats.AsNoTracking() + .FirstOrDefaultAsync(p => p.Id == chatId); + + if (res == null) + return Result.Failure(new Error(nameof(InvalidOperationException), + "PrivateChat not found.") + ); + + return res; + } + + public async Task ExistChatAsync(Guid userIdA, Guid userIdB) + { + return await _context.PrivateChats + .AsNoTracking() + .AnyAsync(p => (p.UserAId == userIdA && p.UserBId == userIdB) || + (p.UserBId == userIdA && p.UserAId == userIdB) + ); + } +} \ No newline at end of file diff --git a/Govor.Application/Profiles/IProfileService.cs b/Govor.Application/Profiles/IProfileService.cs new file mode 100644 index 0000000..16f4a45 --- /dev/null +++ b/Govor.Application/Profiles/IProfileService.cs @@ -0,0 +1,10 @@ +using Govor.Domain.Common; + +namespace Govor.Application.Profiles; + +public interface IProfileService +{ + public Task> GetUserProfileAsync(Guid userId); + public Task SetDescription(string description, Guid userId); + public Task SetNewIcon(Guid userId, Guid iconId); +} diff --git a/Govor.Application/Profiles/ProfileService.cs b/Govor.Application/Profiles/ProfileService.cs new file mode 100644 index 0000000..b8f7a02 --- /dev/null +++ b/Govor.Application/Profiles/ProfileService.cs @@ -0,0 +1,78 @@ +using Govor.Domain; +using Govor.Domain.Common; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; + +namespace Govor.Application.Profiles; + +public class ProfileService : IProfileService +{ + private readonly ILogger _logger; + private readonly GovorDbContext _context; + + public ProfileService(GovorDbContext context, ILogger logger) + { + _context = context; + _logger = logger; + } + + public async Task> GetUserProfileAsync(Guid userId) + { + _logger.LogInformation("Getting user {UserId} profile", userId); + + var profile = await _context.Users + .AsNoTracking() + .Where(u => u.Id == userId) + .Select(user => new UserProfile + { + Id = user.Id, + Username = user.Username, + Description = user.Description, + IconId = user.IconId + }) + .FirstOrDefaultAsync(); + + if (profile is null) + { + return Result.Failure(CreateNotFoundError(userId)); + } + + return profile; + } + + public async Task SetDescription(string description, Guid userId) + { + _logger.LogInformation("Updating description for user {UserId}", userId); + + var updatedRows = await _context.Users + .Where(u => u.Id == userId) + .ExecuteUpdateAsync(setters => setters.SetProperty(u => u.Description, description)); + + if (updatedRows == 0) + { + return Result.Failure(CreateNotFoundError(userId)); + } + + return Result.Success(); + } + + public async Task SetNewIcon(Guid userId, Guid iconId) + { + _logger.LogInformation("Updating icon for user {UserId}", userId); + + + var updatedRows = await _context.Users + .Where(u => u.Id == userId) + .ExecuteUpdateAsync(setters => setters.SetProperty(u => u.IconId, iconId)); + + if (updatedRows == 0) + { + return Result.Failure(CreateNotFoundError(userId)); + } + + return Result.Success(); + } + + private static Error CreateNotFoundError(Guid userId) => + new("Profile.UserNotFound", $"User with ID {userId} was not found."); +} diff --git a/Govor.Application/PushNotifications/IPushNotificationService.cs b/Govor.Application/PushNotifications/IPushNotificationService.cs new file mode 100644 index 0000000..39c1a39 --- /dev/null +++ b/Govor.Application/PushNotifications/IPushNotificationService.cs @@ -0,0 +1,12 @@ +using Govor.Domain.Common; + +namespace Govor.Application.PushNotifications; + +public interface IPushNotificationService +{ + Task SendToUserAsync(Guid userId, string title, string body, string channelId, string tag = "", Dictionary? data = null); + + Task SendToUsersAsync(IEnumerable userIds, string title, string body, string channelId, string tag = "", Dictionary? data = null); + + Task SendToSessionAsync(Guid sessionId, string title, string body, string channelId, string tag = "", Dictionary? data = null); +} \ No newline at end of file diff --git a/Govor.Application/PushNotifications/IPushTokenService.cs b/Govor.Application/PushNotifications/IPushTokenService.cs new file mode 100644 index 0000000..57bdca4 --- /dev/null +++ b/Govor.Application/PushNotifications/IPushTokenService.cs @@ -0,0 +1,14 @@ +using Govor.Domain.Common; + +namespace Govor.Application.PushNotifications; + +public interface IPushTokenService +{ + Task DeactivateTokenBySessionAsync(Guid sessionId); + Task DeactivateAllTokensByUserIdAsync(Guid userId); + Task>> GetStringsActiveTokensAsync(Guid userId); + Task>> GetUsersStringsActiveTokensAsync(IEnumerable userIds); + Task> GetActiveTokenBySessionAsync(Guid sessionId); + Task RemoveTokensAsync(IEnumerable tokens); + Task AddOrUpdateTokenAsync(Guid userId, Guid sessionId, string token, string platform); +} \ No newline at end of file diff --git a/Govor.Application/Interfaces/PushNotifications/Models/PushMessage.cs b/Govor.Application/PushNotifications/Models/PushMessage.cs similarity index 100% rename from Govor.Application/Interfaces/PushNotifications/Models/PushMessage.cs rename to Govor.Application/PushNotifications/Models/PushMessage.cs diff --git a/Govor.Application/Interfaces/PushNotifications/Models/SendPushResult.cs b/Govor.Application/PushNotifications/Models/SendPushResult.cs similarity index 100% rename from Govor.Application/Interfaces/PushNotifications/Models/SendPushResult.cs rename to Govor.Application/PushNotifications/Models/SendPushResult.cs diff --git a/Govor.Application/Services/PushNotifications/Providers/FirebasePushProvider.cs b/Govor.Application/PushNotifications/Providers/FirebasePushProvider.cs similarity index 97% rename from Govor.Application/Services/PushNotifications/Providers/FirebasePushProvider.cs rename to Govor.Application/PushNotifications/Providers/FirebasePushProvider.cs index 1964167..7f3be8d 100644 --- a/Govor.Application/Services/PushNotifications/Providers/FirebasePushProvider.cs +++ b/Govor.Application/PushNotifications/Providers/FirebasePushProvider.cs @@ -3,7 +3,7 @@ using Govor.Application.Interfaces.PushNotifications; using Govor.Application.Interfaces.PushNotifications.Models; using Microsoft.Extensions.Logging; -namespace Govor.Application.Services.PushNotifications.Providers; +namespace Govor.Application.PushNotifications.Providers; public class FirebasePushProvider : IPushNotificationProvider { @@ -43,7 +43,7 @@ public class FirebasePushProvider : IPushNotificationProvider var multicastMsg = new MulticastMessage { - Tokens = tokens.ToList(), + Tokens = tokens, Notification = new Notification { Title = message.Title, diff --git a/Govor.Application/Interfaces/PushNotifications/IPushNotificationProvider.cs b/Govor.Application/PushNotifications/Providers/IPushNotificationProvider.cs similarity index 84% rename from Govor.Application/Interfaces/PushNotifications/IPushNotificationProvider.cs rename to Govor.Application/PushNotifications/Providers/IPushNotificationProvider.cs index 96dd7fd..825725c 100644 --- a/Govor.Application/Interfaces/PushNotifications/IPushNotificationProvider.cs +++ b/Govor.Application/PushNotifications/Providers/IPushNotificationProvider.cs @@ -1,6 +1,6 @@ using Govor.Application.Interfaces.PushNotifications.Models; -namespace Govor.Application.Interfaces.PushNotifications; +namespace Govor.Application.PushNotifications.Providers; public interface IPushNotificationProvider { diff --git a/Govor.Application/Services/PushNotifications/Providers/NullPushProvider.cs b/Govor.Application/PushNotifications/Providers/NullPushProvider.cs similarity index 88% rename from Govor.Application/Services/PushNotifications/Providers/NullPushProvider.cs rename to Govor.Application/PushNotifications/Providers/NullPushProvider.cs index a7a059f..41ee252 100644 --- a/Govor.Application/Services/PushNotifications/Providers/NullPushProvider.cs +++ b/Govor.Application/PushNotifications/Providers/NullPushProvider.cs @@ -1,7 +1,7 @@ using Govor.Application.Interfaces.PushNotifications; using Govor.Application.Interfaces.PushNotifications.Models; -namespace Govor.Application.Services.PushNotifications.Providers; +namespace Govor.Application.PushNotifications.Providers; public class NullPushProvider : IPushNotificationProvider { diff --git a/Govor.Application/PushNotifications/PushNotificationService.cs b/Govor.Application/PushNotifications/PushNotificationService.cs new file mode 100644 index 0000000..2d7dd61 --- /dev/null +++ b/Govor.Application/PushNotifications/PushNotificationService.cs @@ -0,0 +1,119 @@ +using Govor.Application.Interfaces.PushNotifications.Models; +using Govor.Application.PushNotifications.Providers; +using Govor.Domain.Common; +using Microsoft.Extensions.Logging; + +namespace Govor.Application.PushNotifications; + +public class PushNotificationService : IPushNotificationService +{ + private readonly IPushNotificationProvider _provider; + private readonly IPushTokenService _tokenService; + private readonly ILogger _logger; + + public PushNotificationService( + IPushNotificationProvider provider, + IPushTokenService tokenService, + ILogger logger) + { + _provider = provider; + _tokenService = tokenService; + _logger = logger; + } + + public async Task SendToUserAsync(Guid userId, string title, string body, string channelId, string tag = "", Dictionary? data = null) + { + var resultTokens = await _tokenService.GetStringsActiveTokensAsync(userId); + if (resultTokens.IsFailure) + return Result.Failure(resultTokens.Error); + + var tokens = resultTokens.Value; + if (tokens.Count == 0) + { + _logger.LogInformation("No active push tokens for user {UserId}", userId); + return Result.Success(); + } + + return await SendMulticastInternalAsync(tokens, title, body, channelId, tag, data, userId.ToString()); + } + + public async Task SendToUsersAsync(IEnumerable userIds, string title, string body, string channelId, string tag = "", Dictionary? data = null) + { + if (userIds == null || !userIds.Any()) + return Result.Failure(new Error("Push.InvalidArgs", "User IDs collection cannot be empty.")); + + var tokensResult = await _tokenService.GetUsersStringsActiveTokensAsync(userIds); + if (tokensResult.IsFailure) + return Result.Failure(tokensResult.Error); + + var tokens = tokensResult.Value; + if (tokens.Count == 0) + return Result.Success(); + + return await SendMulticastInternalAsync(tokens, title, body, channelId, tag, data, "bulk_request"); + } + + public async Task SendToSessionAsync(Guid sessionId, string title, string body, string channelId, string tag = "", Dictionary? data = null) + { + var tokenResult = await _tokenService.GetActiveTokenBySessionAsync(sessionId); + if (tokenResult.IsFailure) + return Result.Failure(tokenResult.Error); + + var token = tokenResult.Value; + if (string.IsNullOrEmpty(token)) + return Result.Success(); + + try + { + var message = CreateMessage(title, body, channelId, tag, data); + var result = await _provider.SendToTokenAsync(token, message); + + if (result.FailureCount > 0) + { + await _tokenService.RemoveTokensAsync(result.FailedTokens); + _logger.LogWarning("Removed {Count} invalid FCM tokens for session {SessionId}", result.FailureCount, sessionId); + } + + return Result.Success(); + } + catch (Exception ex) + { + _logger.LogError(ex, "Failed to send single push notification to session {SessionId}", sessionId); + return Result.Failure(ex); + } + } + + private async Task SendMulticastInternalAsync(List tokens, string title, string body, string channelId, string tag, Dictionary? data, string targetInfo) + { + try + { + var message = CreateMessage(title, body, channelId, tag, data); + var result = await _provider.SendMulticastAsync(tokens, message); + + if (result.FailureCount > 0) + { + await _tokenService.RemoveTokensAsync(result.FailedTokens); + _logger.LogWarning("Removed {Count} invalid FCM tokens for target: {Target}", result.FailureCount, targetInfo); + } + + return Result.Success(); + } + catch (Exception ex) + { + _logger.LogError(ex, "Error occurred during push notification multicast sending to {Target}", targetInfo); + return Result.Failure(ex); + } + } + + private static PushMessage CreateMessage(string title, string body, string channelId, string tag, Dictionary? data) + { + return new PushMessage + { + Title = title, + Body = body, + Data = data ?? new(), + Tag = tag, + ChannelId = channelId + }; + } +} \ No newline at end of file diff --git a/Govor.Application/PushNotifications/PushTokenService.cs b/Govor.Application/PushNotifications/PushTokenService.cs new file mode 100644 index 0000000..76f1ad2 --- /dev/null +++ b/Govor.Application/PushNotifications/PushTokenService.cs @@ -0,0 +1,168 @@ +using Govor.Domain; +using Govor.Domain.Common; +using Govor.Domain.Models.Users; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; + +namespace Govor.Application.PushNotifications; + +public class PushTokenService : IPushTokenService +{ + private readonly GovorDbContext _context; + private readonly ILogger _logger; + + public PushTokenService(GovorDbContext context, ILogger logger) + { + _context = context; + _logger = logger; + } + + public async Task DeactivateTokenBySessionAsync(Guid sessionId) + { + try + { + await _context.UserPushTokens + .Where(t => t.UserSessionId == sessionId && t.IsActive) + .ExecuteUpdateAsync(s => s.SetProperty(t => t.IsActive, false)); + + return Result.Success(); + } + catch (Exception ex) + { + _logger.LogError(ex, "Failed to deactivate push token for session {SessionId}", sessionId); + return Result.Failure(ex); + } + } + + public async Task DeactivateAllTokensByUserIdAsync(Guid userId) + { + try + { + await _context.UserPushTokens + .Where(t => t.UserId == userId && t.IsActive) + .ExecuteUpdateAsync(s => s.SetProperty(t => t.IsActive, false)); + + return Result.Success(); + } + catch (Exception ex) + { + _logger.LogError(ex, "Failed to deactivate all push tokens for user {UserId}", userId); + return Result.Failure(ex); + } + } + + public async Task>> GetStringsActiveTokensAsync(Guid userId) + { + try + { + var tokens = await _context.UserPushTokens + .AsNoTracking() + .Where(t => t.UserId == userId && t.IsActive) + .Select(t => t.Token) + .ToListAsync(); + + return tokens; + } + catch (Exception ex) + { + _logger.LogError(ex, "Failed to fetch active push tokens for user {UserId}", userId); + return Result>.Failure(ex); + } + } + + public async Task>> GetUsersStringsActiveTokensAsync(IEnumerable userIds) + { + try + { + var tokens = await _context.UserPushTokens + .AsNoTracking() + .Where(t => userIds.Contains(t.UserId) && t.IsActive) + .Select(t => t.Token) + .ToListAsync(); + + return tokens; + } + catch (Exception ex) + { + _logger.LogError(ex, "Failed to fetch active push tokens for bulk users"); + return Result>.Failure(ex); + } + } + + public async Task> GetActiveTokenBySessionAsync(Guid sessionId) + { + try + { + var token = await _context.UserPushTokens + .AsNoTracking() + .Where(t => t.UserSessionId == sessionId && t.IsActive) + .Select(t => t.Token) + .FirstOrDefaultAsync(); + + return token; + } + catch (Exception ex) + { + _logger.LogError(ex, "Failed to fetch active push token for session {SessionId}", sessionId); + return Result.Failure(ex); + } + } + + public async Task RemoveTokensAsync(IEnumerable tokens) + { + if (tokens is null || !tokens.Any()) + return Result.Success(); + + try + { + await _context.UserPushTokens + .Where(t => tokens.Contains(t.Token)) + .ExecuteDeleteAsync(); + + return Result.Success(); + } + catch (Exception ex) + { + _logger.LogError(ex, "Failed to bulk remove invalid push tokens"); + return Result.Failure(ex); + } + } + + public async Task AddOrUpdateTokenAsync(Guid userId, Guid sessionId, string token, string platform) + { + if (string.IsNullOrWhiteSpace(token)) + { + return new Error("PushToken.Empty", "Push token cannot be empty."); + } + + var existingToken = await _context.UserPushTokens + .FirstOrDefaultAsync(t => t.Token == token); + + if (existingToken is null) + { + var newToken = new UserPushToken + { + Id = Guid.NewGuid(), + UserId = userId, + UserSessionId = sessionId, + Token = token, + Platform = platform, + CreatedAt = DateTime.UtcNow + }; + + await _context.UserPushTokens.AddAsync(newToken); + } + else + { + + existingToken.UserId = userId; + existingToken.UserSessionId = sessionId; + existingToken.Platform = platform; + existingToken.UpdatedAt = DateTime.UtcNow; + } + + await _context.SaveChangesAsync(); + + return Result.Success(); + } +} diff --git a/Govor.Application/Services/Authentication/AuthService.cs b/Govor.Application/Services/Authentication/AuthService.cs deleted file mode 100644 index 0b46164..0000000 --- a/Govor.Application/Services/Authentication/AuthService.cs +++ /dev/null @@ -1,102 +0,0 @@ -using Govor.Application.Exceptions.AuthService; -using Govor.Core.Infrastructure.Extensions; -using Govor.Core.Models; -using Govor.Core.Repositories.Users; -using Govor.Application.Interfaces.Authentication; -using Govor.Core.Models.Users; -using Govor.Core.Repositories.Admins; - -namespace Govor.Application.Services.Authentication; - -public class AuthService : IAccountService -{ - private readonly IPasswordHasher _passwordHasher; - private readonly IUsersRepository _usersRepository; - private readonly IAdminsRepository _adminsRepository; - private readonly IUsernameValidator _usernameValidator; - - public AuthService(IUsersRepository usersRepository, - IPasswordHasher passwordHasher, - IAdminsRepository adminsRepository, - IUsernameValidator usernameValidator - ) - { - _usersRepository = usersRepository; - _passwordHasher = passwordHasher; - _adminsRepository = adminsRepository; - _usernameValidator = usernameValidator; - } - - public async Task RegistrationAsync(string name, string password, Invitation invitation) - { - _usernameValidator.Validate(name); - - if (await _usersRepository.ExistsUsernameAsync(name)) - throw new UserAlreadyExistException(name); - - var passwordHash = _passwordHasher.Hash(password); - - var user = new User - { - Id = Guid.NewGuid(), - Username = name, - PasswordHash = passwordHash, - Description = string.Empty, - CreatedOn = DateOnly.FromDateTime(DateTime.UtcNow), - IconId = Guid.Empty, - WasOnline = DateTime.UtcNow, - InviteId = invitation.Id - }; - - await _usersRepository.AddAsync(user); - - await SetRole(user, invitation); - - return user; - } - - - public async Task LoginAsync(string name, string password) - { - if (await _usersRepository.ExistsUsernameAsync(name) == false) - throw new UserNotRegisteredException(name); - - var user = await _usersRepository.FindByUsernameAsync(name); - - if (_passwordHasher.Verify(password, user.PasswordHash) == false) - throw new LoginUserException(); - - return user; - } - - /* - public async Task RefreshTokenAsync(string refreshToken) - { - try - { - var principal = _jwtService.GetPrincipalFromExpiredToken(refreshToken); - - var userId = Guid.Parse(principal?.FindFirst("userId")?.Value ?? string.Empty); - - var storedTokens = await _userSessionsRepository.GetUserTokensAsync(userId); - - if (!storedTokens.Contains(refreshToken)) - throw new UnauthorizedAccessException("Invalid refresh token"); - - var user = await _usersRepository.FindByIdAsync(userId); - var newAccessToken = await _jwtService.GenerateAccessTokenAsync(user); - return newAccessToken; - } - catch (SecurityTokenException ex) - { - throw new InvalidOperationException("Invalid refresh token", ex); - } - } - */ - - private async Task SetRole(User user, Invitation invitation) - { - if(invitation.IsAdmin) - await _adminsRepository.AddAsync(new Admin() { UserId = user.Id }); - } -} \ No newline at end of file diff --git a/Govor.Application/Services/Friends/FriendRequestCommandService.cs b/Govor.Application/Services/Friends/FriendRequestCommandService.cs deleted file mode 100644 index a6b16f0..0000000 --- a/Govor.Application/Services/Friends/FriendRequestCommandService.cs +++ /dev/null @@ -1,105 +0,0 @@ -using Govor.Application.Exceptions.FriendsService; -using Govor.Application.Interfaces; -using Govor.Application.Interfaces.Friends; -using Govor.Core.Models; -using Govor.Core.Repositories.Friendships; -using Govor.Data.Repositories.Exceptions; - -namespace Govor.Application.Services.Friends; - -public class FriendRequestCommandService : IFriendRequestCommandService -{ - private readonly IFriendshipsRepository _friendshipsRepository; - private readonly IUserPrivateChatsCreator _privateChatsCreator; - public FriendRequestCommandService( - IFriendshipsRepository friendshipsRepository, - IUserPrivateChatsCreator privateChatsCreator) - { - _friendshipsRepository = friendshipsRepository; - _privateChatsCreator = privateChatsCreator; - } - - public async Task SendAsync(Guid fromUserId, Guid toUserId) - { - if (fromUserId == toUserId) - throw new InvalidOperationException("Cannot send a request to self user"); - - var friendship = await _friendshipsRepository.GetFriendshipAsync(fromUserId, toUserId); - - if (friendship is null) - { - friendship = new Friendship - { - Id = Guid.NewGuid(), - RequesterId = fromUserId, - AddresseeId = toUserId, - Status = FriendshipStatus.Pending - }; - await _friendshipsRepository.AddAsync(friendship); - } - else - { - if (friendship.Status == FriendshipStatus.Pending || friendship.Status == FriendshipStatus.Accepted - || friendship.Status == FriendshipStatus.Blocked) - { - throw new RequestAlreadySentException(fromUserId, toUserId); - } - - friendship.RequesterId = fromUserId; - friendship.AddresseeId = toUserId; - friendship.Status = FriendshipStatus.Pending; - - await _friendshipsRepository.UpdateAsync(friendship); - } - - return friendship; - } - - public async Task AcceptAsync(Guid requestId, Guid currentUserId) - { - try - { - var friendship = await _friendshipsRepository.GetByIdAsync(requestId); - - - if (friendship.AddresseeId != currentUserId) - throw new UnauthorizedAccessException("You cannot accept this request"); - - if (friendship.Status != FriendshipStatus.Pending) - throw new InvalidOperationException("Request is already accepted"); - - friendship.Status = FriendshipStatus.Accepted; - await _friendshipsRepository.UpdateAsync(friendship); - - await _privateChatsCreator.CreateAsync(friendship.AddresseeId, friendship.RequesterId); - - return friendship; - } - catch (NotFoundByKeyException ex) - { - throw new InvalidOperationException("Friendship not found! You cant accept request!", ex); - } - } - - public async Task RejectAsync(Guid requestId, Guid currentUserId) - { - try - { - var friendship = await _friendshipsRepository.GetByIdAsync(requestId); - - if (friendship.AddresseeId != currentUserId) - throw new UnauthorizedAccessException("You cannot accept this request"); - - if (friendship.Status != FriendshipStatus.Pending && friendship.Status != FriendshipStatus.Rejected) - throw new InvalidOperationException($"Request is already {friendship.Status}"); - - friendship.Status = FriendshipStatus.Rejected; - await _friendshipsRepository.UpdateAsync(friendship); - return friendship; - } - catch (NotFoundByKeyException ex) - { - throw new InvalidOperationException("Friendship not found! You cant reject request!", ex); - } - } -} \ No newline at end of file diff --git a/Govor.Application/Services/Friends/FriendRequestQueryService.cs b/Govor.Application/Services/Friends/FriendRequestQueryService.cs deleted file mode 100644 index de66537..0000000 --- a/Govor.Application/Services/Friends/FriendRequestQueryService.cs +++ /dev/null @@ -1,44 +0,0 @@ -using Govor.Application.Interfaces.Friends; -using Govor.Core.Models; -using Govor.Core.Repositories.Friendships; -using Govor.Data.Repositories.Exceptions; - -namespace Govor.Application.Services.Friends; - -public class FriendRequestQueryService : IFriendRequestQueryService -{ - private readonly IFriendshipsRepository _friendshipsRepository; - - public FriendRequestQueryService(IFriendshipsRepository friendshipsRepository) - { - _friendshipsRepository = friendshipsRepository; - } - - public async Task> GetIncomingAsync(Guid userId) - { - try - { - var friendships = await _friendshipsRepository.FindByUserIdAsync(userId); - return friendships.Where(f => f.AddresseeId == userId && f.Status == FriendshipStatus.Pending).ToList() - ?? new List(); - } - catch (NotFoundByKeyException ex) - { - throw new InvalidOperationException("User not exist", ex); - } - } - - public async Task> GetResponsesAsync(Guid userId) - { - try - { - var friendships = await _friendshipsRepository.FindByUserIdAsync(userId); - return friendships.Where(f => f.RequesterId == userId && f.Status != FriendshipStatus.Accepted).ToList() - ?? new List(); - } - catch (NotFoundByKeyException ex) - { - throw new InvalidOperationException("User not exist", ex); - } - } -} \ No newline at end of file diff --git a/Govor.Application/Services/Friends/FriendshipService.cs b/Govor.Application/Services/Friends/FriendshipService.cs deleted file mode 100644 index fce9a29..0000000 --- a/Govor.Application/Services/Friends/FriendshipService.cs +++ /dev/null @@ -1,80 +0,0 @@ -using Govor.Application.Exceptions.FriendsService; -using Govor.Application.Interfaces.Friends; -using Govor.Core.Models; -using Govor.Core.Models.Users; -using Govor.Core.Repositories.Friendships; -using Govor.Core.Repositories.Users; -using Govor.Data.Repositories.Exceptions; - -namespace Govor.Application.Services.Friends; - -public class FriendshipService : IFriendshipService -{ - private readonly IUsersRepository _usersRepository; - private readonly IFriendshipsRepository _friendshipsRepository; - - public FriendshipService(IUsersRepository usersRepository, IFriendshipsRepository friendshipsRepository) - { - _usersRepository = usersRepository; - _friendshipsRepository = friendshipsRepository; - } - - - public async Task> SearchUsersAsync(string query, Guid currentId) - { - List all = new List(); - - try - { - all = await _usersRepository.SearchPotentialFriendsAsync(currentId, query); - - return all; - } - catch (NotFoundByKeyException<(string, Guid)> ex) - { - return []; - } - catch (NotFoundByKeyException ex) - { - return []; - } - catch (Exception ex) - { - throw new UnauthorizedAccessException($"When we try find friends by pattern {query} something wrong", ex); - } - } - - public async Task> GetPotentialFriendsAsync(Guid userId) - { - try - { - var friendships = await _friendshipsRepository.FindByUserIdAsync(userId); - - return friendships - .Where(f => f.Status == FriendshipStatus.Pending) - .Select(f => f.RequesterId == userId ? f.Addressee : f.Requester) - .ToList(); - } - catch (NotFoundByKeyException ex) - { - throw new InvalidOperationException("Nothing was found for the specified id.", ex); - } - } - - public async Task> GetFriendsAsync(Guid userId) - { - try - { - var friendships = await _friendshipsRepository.FindByUserIdAsync(userId); - - return friendships - .Where(f => f.Status == FriendshipStatus.Accepted) - .Select(f => f.RequesterId == userId ? f.Addressee : f.Requester) - .ToList(); - } - catch (NotFoundByKeyException ex) - { - throw new InvalidOperationException("Nothing was found for the specified id.", ex); - } - } -} \ No newline at end of file diff --git a/Govor.Application/Services/InvitesService.cs b/Govor.Application/Services/InvitesService.cs deleted file mode 100644 index f281025..0000000 --- a/Govor.Application/Services/InvitesService.cs +++ /dev/null @@ -1,53 +0,0 @@ -using Govor.Application.Exceptions.InvitesService; -using Govor.Application.Interfaces.Authentication; -using Govor.Core.Models; -using Govor.Core.Models.Users; -using Govor.Core.Repositories.Invaites; -using Govor.Data.Repositories.Exceptions; - -namespace Govor.Application.Services; - -public class InvitesService : IInvitesService -{ - private readonly IInvitesRepository _invitesRepository; - - public InvitesService(IInvitesRepository invitesRepository) - { - _invitesRepository = invitesRepository; - } - - public async Task GetRoleAsync(User user) - { - try - { - var invitation = await _invitesRepository.FindByIdAsync(user.InviteId); - return invitation.IsAdmin ? "Admin" : "User"; - } - catch (NotFoundByKeyException) - { - return "User"; - } - } - - public async Task ValidateAsync(string inviteCode) - { - try - { - var invite = await _invitesRepository.FindByCodeAsync(inviteCode); - - if (invite.EndDate < DateTime.Now || invite.MaxParticipants <= invite.Users.Count) - { - invite.IsActive = false; - await _invitesRepository.UpdateAsync(invite); - throw new InviteLinkInvalidException(inviteCode); - } - - return invite; - } - catch (NotFoundByKeyException) - { - throw new InviteLinkInvalidException(inviteCode); - } - } -} - diff --git a/Govor.Application/Services/Messages/MessageCommandService.cs b/Govor.Application/Services/Messages/MessageCommandService.cs deleted file mode 100644 index 884c03e..0000000 --- a/Govor.Application/Services/Messages/MessageCommandService.cs +++ /dev/null @@ -1,229 +0,0 @@ -using Govor.Application.Interfaces; -using Govor.Application.Interfaces.Medias; -using Govor.Application.Interfaces.Messages; -using Govor.Application.Interfaces.Messages.Parameters; -using Govor.Core.Models; -using Govor.Core.Models.Messages; -using Govor.Core.Repositories.Groups; -using Govor.Core.Repositories.Messages; -using Govor.Core.Repositories.PrivateChats; -using Govor.Core.Repositories.Users; -using Govor.Data.Repositories.Exceptions; -using Microsoft.Extensions.Logging; - -namespace Govor.Application.Services.Messages; - -public class MessageCommandService : IMessageCommandService -{ - private readonly IMessagesRepository _messagesRepository; - private readonly IPrivateChatsRepository _privateChatsRepository; - private readonly IUsersRepository _usersRepository; - private readonly IGroupsRepository _groupsRepository; - private readonly IUserPrivateChatsCreator _privateChatsCreator; - private readonly IVerifyFriendship _verifyFriendship; - private readonly IMediaService _mediaService; - private readonly ILogger _logger; - - public MessageCommandService( - IMessagesRepository messagesRepository, - IUsersRepository usersRepository, - IGroupsRepository groupsRepository, - IPrivateChatsRepository privateChatsRepository, - IUserPrivateChatsCreator privateChatsCreator, - IVerifyFriendship verifyFriendship, - IMediaService mediaService, - ILogger logger) - { - _messagesRepository = messagesRepository; - _usersRepository = usersRepository; - _groupsRepository = groupsRepository; - _privateChatsRepository = privateChatsRepository; - _privateChatsCreator = privateChatsCreator; - _verifyFriendship = verifyFriendship; - _mediaService = mediaService; - _logger = logger; - } - - public async Task SendMessageAsync(SendMessage sendParams) - { - try - { - var recipientId = sendParams.RecipientType switch - { - RecipientType.User => await HandleUserRecipientAsync(sendParams), - RecipientType.Group => await HandleGroupRecipientAsync(sendParams), - _ => throw new ArgumentException("Invalid recipient type.") - }; - - var messageId = Guid.NewGuid(); - var message = new Message - { - Id = messageId, - SenderId = sendParams.FromUserId, - RecipientId = recipientId, - RecipientType = sendParams.RecipientType, - EncryptedContent = sendParams.EncryptContent, - SentAt = sendParams.SendAt, - IsEdited = false, - ReplyToMessageId = sendParams.ReplyToMessageId, - MediaAttachments = sendParams.Media?.Select(m => new MediaAttachments - { - Id = Guid.NewGuid(), - MessageId = messageId, - MediaFileId = m.MediaId - }).ToList() ?? new List() - }; - - // Attach media - if (sendParams.Media?.Any() == true) - foreach (var media in sendParams.Media) - await _mediaService.AttachToMessageAsync(media.MediaId, messageId); - - await _messagesRepository.AddAsync(message); - _logger.LogInformation( - "Message {MessageId} from {SenderId} to {RecipientId} ({RecipientType}) saved successfully.", - messageId, sendParams.FromUserId, sendParams.RecipientId, sendParams.RecipientType); - - return new SendMessageResult(true, null, message); - } - catch (Exception ex) - { - _logger.LogError( - ex, - "Error sending message from {SenderId} to {RecipientId} ({RecipientType})", - sendParams.FromUserId, sendParams.RecipientId, sendParams.RecipientType); - return new SendMessageResult(false, ex, default); - } - } - - private async Task HandleUserRecipientAsync(SendMessage sendParams) - { - var privateChat = await _privateChatsRepository.GetByIdAsync(sendParams.RecipientId); - - if (privateChat == null) - { - _logger.LogWarning("Private chat {ChatId} not found", sendParams.RecipientId); - throw new KeyNotFoundException($"Private chat {sendParams.RecipientId} not found."); - } - - return privateChat.Id; - } - - private async Task HandleGroupRecipientAsync(SendMessage sendParams) - { - if (!_groupsRepository.Exist(sendParams.RecipientId)) - { - _logger.LogWarning("Attempt to send message to non-existent group {GroupId}", sendParams.RecipientId); - throw new KeyNotFoundException($"Recipient group {sendParams.RecipientId} not found."); - } - - var isMember = await _groupsRepository.IsUserMemberOfGroupAsync(sendParams.FromUserId, sendParams.RecipientId); - if (!isMember) - { - _logger.LogWarning("User {UserId} attempted to send message to group {GroupId} but is not a member", - sendParams.FromUserId, sendParams.RecipientId); - throw new UnauthorizedAccessException("Sender is not a member of the group."); - } - - return sendParams.RecipientId; - } - - //TODO: Full Cleanup all them: - public async Task EditMessageAsync(EditMessage editParams) - { - try - { - var message = await _messagesRepository.FindByIdAsync(editParams.MessageId); - - if (message.SenderId != editParams.EditorId) - { - _logger.LogWarning( - "User {EditorId} attempted to edit message {MessageId} not sent by them (sender was {SenderId})", - editParams.EditorId, editParams.MessageId, message.SenderId); - return new EditMessageResult(false, - new UnauthorizedAccessException("User is not authorized to edit this message."), null); - } - - /*if (message.SentAt < DateTime.UtcNow.AddMinutes(-15)) - throw new Exception("Edit time limit exceeded");*/ - - var originalMessageForNotification = new Message - { - Id = message.Id, - SenderId = message.SenderId, - RecipientId = message.RecipientId, - RecipientType = message.RecipientType, - SentAt = message.SentAt, - ReplyToMessageId = message.ReplyToMessageId, - Reactions = message.Reactions, - MediaAttachments = message.MediaAttachments, - MessageViews = message.MessageViews - }; - - message.EncryptedContent = editParams.NewContent; - message.IsEdited = true; - message.EditedAt = editParams.EditedAt; - - await _messagesRepository.UpdateAsync(message); - _logger.LogInformation("Message {MessageId} edited successfully by user {EditorId}", editParams.MessageId, - editParams.EditorId); - return new EditMessageResult(true, default, originalMessageForNotification); - } - catch (Exception ex) - { - _logger.LogError(ex, "Error editing message {MessageId} by user {EditorId}", editParams.MessageId, - editParams.EditorId); - return new EditMessageResult(false, ex, default); - } - } - - public async Task DeleteMessageAsync(DeleteMessage deleteParams) - { - try - { - var message = await _messagesRepository.FindByIdAsync(deleteParams.MessageId); - - if (message.SenderId != deleteParams.DeleterId) - { - // TODO: Allow group admins to delete messages in their groups? - // if (message.RecipientType == RecipientType.Group) { - // bool isAdmin = await _groupsRepository.IsUserAdminOfGroupAsync(deleteParams.DeleterId, message.RecipientId); - // if (!isAdmin) { - // _logger.LogWarning("User {DeleterId} (not sender or admin) attempted to delete group message {MessageId}", deleteParams.DeleterId, deleteParams.MessageId); - // return new DeleteMessageResult(false, new UnauthorizedAccessException("User is not authorized to delete this message."), null); - // } - // } else { - _logger.LogWarning( - "User {DeleterId} attempted to delete message {MessageId} not sent by them (sender was {SenderId})", - deleteParams.DeleterId, deleteParams.MessageId, message.SenderId); - return new DeleteMessageResult(false, - new UnauthorizedAccessException("User is not authorized to delete this message."), default); - // } - } - - var originalMessageForNotification = new Message - { - Id = message.Id, - SenderId = message.SenderId, - RecipientId = message.RecipientId, - RecipientType = message.RecipientType - }; - - await _messagesRepository.RemoveAsync(deleteParams.MessageId); - - _logger.LogInformation("Message {MessageId} deleted successfully by user {DeleterId}", - deleteParams.MessageId, deleteParams.DeleterId); - return new DeleteMessageResult(true, default, originalMessageForNotification); - } - catch (NotFoundByKeyException ex) - { - return new DeleteMessageResult(false, new KeyNotFoundException("Message not found", ex), default); - } - catch (Exception ex) - { - _logger.LogError(ex, "Error deleting message {MessageId} by user {DeleterId}", deleteParams.MessageId, - deleteParams.DeleterId); - return new DeleteMessageResult(false, ex, default); - } - } -} \ No newline at end of file diff --git a/Govor.Application/Services/Messages/MessagesLoader.cs b/Govor.Application/Services/Messages/MessagesLoader.cs deleted file mode 100644 index ff27317..0000000 --- a/Govor.Application/Services/Messages/MessagesLoader.cs +++ /dev/null @@ -1,142 +0,0 @@ -using Govor.Application.Interfaces; -using Govor.Core.Models.Messages; -using Govor.Core.Repositories.Groups; -using Govor.Core.Repositories.PrivateChats; -using Govor.Data; -using Govor.Data.Repositories.Exceptions; -using Microsoft.EntityFrameworkCore; - -namespace Govor.Application.Services.Messages; - -public class MessagesLoader : IMessagesLoader -{ - private IGroupsRepository _groupsRepository; - private IPrivateChatsRepository _privateChatsRepository; - private GovorDbContext _dbContext; - - public MessagesLoader( - IGroupsRepository groupsRepository, - IPrivateChatsRepository privateChatsRepository, - GovorDbContext dbContext) - { - _groupsRepository = groupsRepository; - _privateChatsRepository = privateChatsRepository; - _dbContext = dbContext; - } - - public async Task> LoadMessagesInUserChat( - Guid privateChatId, - Guid currentUser, - Guid? startMessageId, - int before = 20, - int after = 2) - { - if (privateChatId == Guid.Empty) - throw new ArgumentException("PrivateChatId id cannot be empty"); - - if (!_privateChatsRepository.Exist(privateChatId)) - throw new InvalidOperationException("Private chat not found"); - - var query = _dbContext.Messages - .AsNoTracking() - .Include(m => m.MediaAttachments) - .ThenInclude(m => m.MediaFile) - .Where(m => m.RecipientType == RecipientType.User && - m.RecipientId == privateChatId); - - if (startMessageId is null) - { - return await query - .OrderByDescending(m => m.SentAt) - .Take(before) - .ToListAsync(); - } - - var startMessage = await _dbContext.Messages.FindAsync(startMessageId.Value); - if (startMessage == null) - throw new NotFoundException("Start message not found"); - - var beforeMessages = await query - .Where(m => m.SentAt < startMessage.SentAt) - .OrderByDescending(m => m.SentAt) - .Take(before) - .ToListAsync(); - - var afterMessages = await query - .Where(m => m.SentAt > startMessage.SentAt) - .OrderBy(m => m.SentAt) - .Take(after) - .ToListAsync(); - - // older -> start -> newer - var result = beforeMessages - .OrderBy(m => m.SentAt) - .Concat(new[] { startMessage }) - .Concat(afterMessages) - .ToList(); - - return result; - } - - - public async Task> LoadMessagesInChatGroup( - Guid chatId, - Guid currentUser, - Guid? startMessageId, - int before = 20, - int after = 2) - { - if (chatId == Guid.Empty) - throw new ArgumentException("Chat id cannot be empty"); - - var isMember = await _groupsRepository.IsUserMemberOfGroupAsync(currentUser, chatId); - if (!isMember) - throw new UnauthorizedAccessException("You are not a member of this group."); - - var baseQuery = _dbContext.Messages - .AsNoTracking() - .Include(m => m.MediaAttachments) - .ThenInclude(m => m.MediaFile) - .AsSplitQuery() - .Where(m => m.RecipientType == RecipientType.Group && m.RecipientId == chatId); - - if (startMessageId is null) - { - return await baseQuery - .OrderByDescending(m => m.SentAt) - .Take(before) - .OrderBy(m => m.SentAt) - .ToListAsync(); - } - - var startMessage = await _dbContext.Messages - .AsNoTracking() - .FirstOrDefaultAsync(m => m.Id == startMessageId.Value && - m.RecipientType == RecipientType.Group && - m.RecipientId == chatId); - - if (startMessage == null) - throw new NotFoundException("Start message not found in this group."); - - var beforeMessages = await baseQuery - .Where(m => m.SentAt < startMessage.SentAt) - .OrderByDescending(m => m.SentAt) - .Take(before) - .ToListAsync(); - - var afterMessages = await baseQuery - .Where(m => m.SentAt > startMessage.SentAt) - .OrderBy(m => m.SentAt) - .Take(after) - .ToListAsync(); - - var result = beforeMessages - .OrderBy(m => m.SentAt) - .Concat(new[] { startMessage }) - .Concat(afterMessages) - .ToList(); - - return result; - } - -} \ No newline at end of file diff --git a/Govor.Application/Services/ProfileService.cs b/Govor.Application/Services/ProfileService.cs deleted file mode 100644 index ab07ce8..0000000 --- a/Govor.Application/Services/ProfileService.cs +++ /dev/null @@ -1,56 +0,0 @@ -using Govor.Application.Interfaces; -using Govor.Application.Profiles; -using Govor.Core.Repositories.Users; -using Govor.Data.Repositories.Exceptions; -using Microsoft.Extensions.Logging; - -namespace Govor.Application.Services; - -public class ProfileService : IProfileService -{ - private readonly ILogger _logger; - private readonly IUsersRepository _userRepository; - - public ProfileService(IUsersRepository userRepository, ILogger logger) - { - _userRepository = userRepository; - _logger = logger; - } - - public async Task GetUserProfileAsync(Guid userId) - { - _logger.LogInformation("Gettings user {userId} profile", userId); - try - { - var user = await _userRepository.FindByIdAsync(userId); - - return new UserProfile - { - Id = user.Id, - Username = user.Username, - Description = user.Description, - IconId = user.IconId - }; - } - catch (NotFoundByKeyException ex) - { - throw new NotFoundException("User's profile cant be found with given id", ex); - } - } - - public async Task SetDescription(string description, Guid userId) - { - var user = await _userRepository.FindByIdAsync(userId); - - user.Description = description; - await _userRepository.UpdateAsync(user); - } - - public async Task SetNewIcon(Guid userId, Guid iconId) - { - var user = await _userRepository.FindByIdAsync(userId); - - user.IconId = iconId; - await _userRepository.UpdateAsync(user); - } -} diff --git a/Govor.Application/Services/PushNotifications/PushNotificationService.cs b/Govor.Application/Services/PushNotifications/PushNotificationService.cs deleted file mode 100644 index 4fa824f..0000000 --- a/Govor.Application/Services/PushNotifications/PushNotificationService.cs +++ /dev/null @@ -1,98 +0,0 @@ -using FirebaseAdmin.Messaging; -using Govor.Application.Interfaces.PushNotifications; -using Govor.Application.Interfaces.PushNotifications.Models; -using Govor.Core.Repositories.PushTokens; -using Microsoft.Extensions.Logging; - -namespace Govor.Application.Services.PushNotifications; - -public class PushNotificationService : IPushNotificationService -{ - private readonly IPushNotificationProvider _provider; - private readonly IPushTokenRepository _tokenRepo; - private readonly ILogger _logger; - - public PushNotificationService( - IPushNotificationProvider provider, - IPushTokenRepository tokenRepo, - ILogger logger) - { - _provider = provider; - _tokenRepo = tokenRepo; - _logger = logger; - } - - public async Task SendToUserAsync(Guid userId, string title, string body, string channelId, string tag = "", Dictionary? data = null) - { - var tokens = await _tokenRepo.GetActiveTokensAsync(userId); - if (tokens.Count == 0) - { - _logger.LogInformation("No active push tokens for user {UserId}", userId); - return; - } - - var message = new PushMessage - { - Title = title, - Body = body, - Data = data ?? new(), - Tag = tag, - ChannelId = channelId - }; - - var result = await _provider.SendMulticastAsync(tokens, message); - - if (result.FailureCount > 0) - { - await _tokenRepo.RemoveTokensAsync(result.FailedTokens); - _logger.LogWarning("Removed {Count} invalid FCM tokens for user {UserId}", result.FailureCount, userId); - } - } - - public async Task SendToUsersAsync(IEnumerable userIds, string title, string body, string channelId, string tag = "", Dictionary? data = null) - { - if (userIds is null) - throw new ArgumentNullException(nameof(userIds)); - - var tokens = (await _tokenRepo.GetActiveTokensUsersAsync(userIds)).AsReadOnly(); - if (tokens.Count == 0) - return; - - var result = await _provider.SendMulticastAsync(tokens, new PushMessage() - { - Title = title, - Body = body, - Data = data ?? new(), - Tag = tag, - ChannelId = channelId - }); - - if (result.FailureCount > 0) - { - await _tokenRepo.RemoveTokensAsync(result.FailedTokens); - _logger.LogWarning("Removed {Count} invalid FCM tokens for users {Users}...", result.FailureCount, userIds); - } - } - - public async Task SendToSessionAsync(Guid sessionId, string title, string body, string channelId, string tag = "", Dictionary? data = null) - { - var token = await _tokenRepo.GetActiveTokenBySessionAsync(sessionId); - if(string.IsNullOrEmpty(token)) - return; - - var result = await _provider.SendToTokenAsync(token, new PushMessage() - { - Title = title, - Body = body, - Data = data ?? new(), - Tag = tag, - ChannelId = channelId - }); - - if (result.FailureCount > 0) - { - await _tokenRepo.RemoveTokensAsync(result.FailedTokens); - _logger.LogWarning("Removed {Count} invalid FCM tokens for session {Session}...", result.FailureCount, sessionId); - } - } -} \ No newline at end of file diff --git a/Govor.Application/Services/UserGroupsGetterService.cs b/Govor.Application/Services/UserGroupsGetterService.cs deleted file mode 100644 index a665667..0000000 --- a/Govor.Application/Services/UserGroupsGetterService.cs +++ /dev/null @@ -1,28 +0,0 @@ -using Govor.Application.Interfaces; -using Govor.Core.Models; -using Govor.Core.Repositories.Groups; -using Govor.Data.Repositories.Exceptions; - -namespace Govor.Application.Services; - -public class UserGroupsGetterService : IUserGroupsGetterService -{ - private readonly IGroupsRepository _groupRep; - - public UserGroupsGetterService(IGroupsRepository groupsRepository) - { - _groupRep = groupsRepository; - } - - public async Task> GetUserGroupsAsync(Guid userId) - { - try - { - return await _groupRep.GetByUserIdAsync(userId); - } - catch (NotFoundByKeyException ex) - { - return new List(); - } - } -} \ No newline at end of file diff --git a/Govor.Application/Services/UserPrivateChatsGetter.cs b/Govor.Application/Services/UserPrivateChatsGetter.cs deleted file mode 100644 index 96e1644..0000000 --- a/Govor.Application/Services/UserPrivateChatsGetter.cs +++ /dev/null @@ -1,28 +0,0 @@ -using Govor.Application.Interfaces; -using Govor.Core.Models; -using Govor.Core.Repositories.PrivateChats; -using Govor.Data.Repositories.Exceptions; - -namespace Govor.Application.Services; - -public class UserPrivateChatsGetter : IUserPrivateChatsGetterService -{ - private readonly IPrivateChatsRepository _groupRep; - - public UserPrivateChatsGetter(IPrivateChatsRepository groupsRepository) - { - _groupRep = groupsRepository; - } - - public async Task> GetUserChatsAsync(Guid userId) - { - try - { - return await _groupRep.GetAllOfUser(userId); - } - catch (NotFoundByKeyException ex) - { - return []; - } - } -} \ No newline at end of file diff --git a/Govor.Application/Services/UserSessions/UserSessionReader.cs b/Govor.Application/Services/UserSessions/UserSessionReader.cs deleted file mode 100644 index f9ba04c..0000000 --- a/Govor.Application/Services/UserSessions/UserSessionReader.cs +++ /dev/null @@ -1,34 +0,0 @@ -using Govor.Application.Interfaces.UserSession; -using Govor.Core.Repositories.UserSessionsRepository; -using Govor.Data.Repositories.Exceptions; -using Microsoft.Extensions.Logging; - -namespace Govor.Application.Services.UserSessions; - -public class UserSessionReader : IUserSessionReader -{ - private readonly IUserSessionsRepository _repository; - private readonly ILogger _logger; - - public UserSessionReader(IUserSessionsRepository repository, ILogger logger) - { - _repository = repository; - _logger = logger; - } - - public async Task> GetAllSessionsAsync(Guid userId) - { - try - { - _logger.LogInformation($"Getting all sessions for user {userId}"); - var sessions = await _repository.GetByUserIdAsync(userId); - - return sessions.Where(f => !f.IsRevoked).ToList() ?? []; - } - catch (NotFoundByKeyException ex) - { - _logger.LogWarning("The user has no sessions."); - return []; - } - } -} \ No newline at end of file diff --git a/Govor.Application/Services/UserSessions/UserSessionRefresher.cs b/Govor.Application/Services/UserSessions/UserSessionRefresher.cs deleted file mode 100644 index 36823a2..0000000 --- a/Govor.Application/Services/UserSessions/UserSessionRefresher.cs +++ /dev/null @@ -1,77 +0,0 @@ -using Govor.Application.Interfaces.Authentication; -using Govor.Application.Interfaces.UserSession; -using Govor.Application.Services.Authentication; -using Govor.Core.Models.Users; -using Govor.Core.Repositories.Users; -using Govor.Core.Repositories.UserSessionsRepository; -using Govor.Data.Repositories.Exceptions; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; - -namespace Govor.Application.Services.UserSessions; - -public class UserSessionRefresher : IUserSessionRefresher -{ - private readonly IUserSessionsRepository _sessionsRepository; - private readonly ILogger _logger; - private readonly IUsersRepository _usersRepository; - private readonly JwtRefreshOption _options; - private readonly IJwtTokenHasher _jwtTokenHasher; - private readonly IJwtService _jwtService; - - public UserSessionRefresher( - IUserSessionsRepository sessionsRepository, - ILogger logger, - IUsersRepository usersRepository, - IOptions options, - IJwtTokenHasher jwtTokenHasher, - IJwtService jwtService) - { - _sessionsRepository = sessionsRepository; - _logger = logger; - _usersRepository = usersRepository; - _options = options.Value; - _jwtTokenHasher = jwtTokenHasher; - _jwtService = jwtService; - } - - public async Task RefreshTokenAsync(string refreshToken) - { - try - { - var session = await _sessionsRepository.GetByHashedRefreshTokenAsync(_jwtTokenHasher.HashToken(refreshToken)); - - if (session.IsRevoked || session.ExpiresAt <= DateTime.UtcNow) - throw new UnauthorizedAccessException("Refresh token is invalid or expired"); - - // Find user - var user = await _usersRepository.FindByIdAsync(session.UserId); - - // New tokens - var newAccessToken = await _jwtService.GenerateAccessTokenAsync(user, session.Id); - var newRefreshToken = await _jwtService.GenerateRefreshTokenAsync(user); - - var newRefreshTokenHash = _jwtTokenHasher.HashToken(newRefreshToken); - - // Opening new session - var newSession = new UserSession - { - Id = session.Id, - UserId = user.Id, - RefreshTokenHash = newRefreshTokenHash, - DeviceInfo = session.DeviceInfo, - CreatedAt = DateTime.UtcNow, - ExpiresAt = DateTime.UtcNow.AddDays(_options.RefreshTokenLifetimeDays) - }; - - await _sessionsRepository.UpdateAsync(newSession); - - return new RefreshResult(newRefreshToken, newAccessToken); - } - catch (NotFoundByKeyException ex) - { - _logger.LogWarning(ex, ex.Message); - throw new UnauthorizedAccessException("Invalid refresh token", ex); - } - } -} \ No newline at end of file diff --git a/Govor.Application/Services/UserSessions/UserSessionRevoker.cs b/Govor.Application/Services/UserSessions/UserSessionRevoker.cs deleted file mode 100644 index a889379..0000000 --- a/Govor.Application/Services/UserSessions/UserSessionRevoker.cs +++ /dev/null @@ -1,73 +0,0 @@ -using Govor.Application.Interfaces.UserSession; -using Govor.Core.Repositories.PushTokens; -using Govor.Core.Repositories.UserSessionsRepository; -using Govor.Data.Repositories.Exceptions; -using Microsoft.Extensions.Logging; - -namespace Govor.Application.Services.UserSessions; - -public class UserSessionRevoker : IUserSessionRevoker -{ - private readonly IUserSessionsRepository _sessionsRepository; - private readonly IPushTokenRepository _pushTokenRepository; - private readonly ILogger _logger; - - public UserSessionRevoker( - IUserSessionsRepository sessionsRepository, - IPushTokenRepository pushTokenRepository, - ILogger logger) - { - _sessionsRepository = sessionsRepository; - _pushTokenRepository = pushTokenRepository; - _logger = logger; - } - - public async Task CloseSessionByIdAsync(Guid sessionId, Guid userId) - { - try - { - var session = await _sessionsRepository.GetByIdAsync(sessionId); - - if (session.UserId != userId) - { - _logger.LogWarning("User {userId} does not belong to this session {sessionId}", userId, sessionId); - throw new UnauthorizedAccessException($"User {userId} does not belong to this session {sessionId}"); - } - - if(session.IsRevoked) return; - - session.IsRevoked = true; - await _sessionsRepository.UpdateAsync(session); - - await _pushTokenRepository.DeactivateTokenBySessionAsync(sessionId); // pushes deactivate - } - catch (NotFoundByKeyException ex) - { - _logger.LogWarning("User {userId} tried close unreal session!", userId); - throw new NotFoundException("Session not found", ex); - } - } - - public async Task CloseAllSessionsAsync(Guid userId) - { - try - { - var sessions = await _sessionsRepository.GetByUserIdAsync(userId); - - foreach (var session in sessions) - { - if(session.IsRevoked) continue; - - session.IsRevoked = true; - await _sessionsRepository.UpdateAsync(session); - - await _pushTokenRepository.DeactivateTokenBySessionAsync(session.Id); // pushes deactivate - } - } - catch (NotFoundByKeyException ex) - { - _logger.LogWarning("User {userId} has not sessions", userId); - throw new NotFoundException("Session not found", ex); - } - } -} \ No newline at end of file diff --git a/Govor.Application/Services/VerifierFriendship.cs b/Govor.Application/Services/VerifierFriendship.cs deleted file mode 100644 index 1a57659..0000000 --- a/Govor.Application/Services/VerifierFriendship.cs +++ /dev/null @@ -1,72 +0,0 @@ -using Govor.Application.Exceptions.VerifyFriendship; -using Govor.Application.Interfaces; -using Govor.Core.Models; -using Govor.Core.Repositories.Friendships; -using Govor.Data.Repositories.Exceptions; -using Microsoft.Extensions.Logging; - -namespace Govor.Application.Services; - -public class VerifyFriendship : IVerifyFriendship -{ - private readonly IFriendshipsRepository _friendshipsRepository; - private readonly ILogger _logger; - private const string FriendshipNotAcceptedError = "Friendship between user {0} and friend {1} does not exist or is not accepted."; - - public VerifyFriendship(IFriendshipsRepository friendshipsRepository, ILogger logger) - { - _friendshipsRepository = friendshipsRepository ?? throw new ArgumentNullException(nameof(friendshipsRepository)); - _logger = logger; - } - - public async Task VerifyAsync(Guid targetUserId, Guid friendUserId) - { - try - { - if (targetUserId == Guid.Empty || friendUserId == Guid.Empty) - { - _logger?.LogWarning( - "Invalid user IDs provided: targetUserId={TargetUserId}, friendUserId={FriendUserId}", targetUserId, - friendUserId); - throw new ArgumentException("User IDs cannot be empty.", nameof(targetUserId)); - } - - var friendships = await _friendshipsRepository.FindByUserIdAsync(targetUserId); - var friendship = friendships.Where(f => f.AddresseeId == friendUserId || f.RequesterId == friendUserId) - ?.FirstOrDefault(); - - if (friendship == null || friendship.Status != FriendshipStatus.Accepted) - { - var errorMessage = string.Format(FriendshipNotAcceptedError, targetUserId, friendUserId); - _logger?.LogError(errorMessage); - throw new FriendshipException(errorMessage); - } - - _logger.LogInformation("hello"); - - _logger.LogInformation( - "Friendship verified successfully for targetUserId={TargetUserId}, friendUserId={FriendUserId}", - targetUserId, friendUserId); - } - catch (NotFoundByKeyException ex) - { - var errorMessage = string.Format(FriendshipNotAcceptedError, targetUserId, friendUserId); - _logger.LogError(errorMessage); - - throw new FriendshipException(errorMessage); - } - } - - public async Task TryVerifyAsync(Guid targetUserId, Guid friendUserId) - { - try - { - await VerifyAsync(targetUserId, friendUserId); - return true; - } - catch (Exception ex) - { - return false; - } - } -} \ No newline at end of file diff --git a/Govor.Application/Interfaces/IStorageService.cs b/Govor.Application/Storage/IStorageService.cs similarity index 80% rename from Govor.Application/Interfaces/IStorageService.cs rename to Govor.Application/Storage/IStorageService.cs index f648964..1558caf 100644 --- a/Govor.Application/Interfaces/IStorageService.cs +++ b/Govor.Application/Storage/IStorageService.cs @@ -1,4 +1,4 @@ -namespace Govor.Application.Interfaces; +namespace Govor.Application.Storage; public interface IStorageService { diff --git a/Govor.Application/Services/LocalStorageService.cs b/Govor.Application/Storage/LocalStorageService.cs similarity index 97% rename from Govor.Application/Services/LocalStorageService.cs rename to Govor.Application/Storage/LocalStorageService.cs index 80a2791..9a673d2 100644 --- a/Govor.Application/Services/LocalStorageService.cs +++ b/Govor.Application/Storage/LocalStorageService.cs @@ -1,5 +1,4 @@ -using Govor.Application.Interfaces; -namespace Govor.Application.Services; +namespace Govor.Application.Storage; public class LocalStorageService : IStorageService { diff --git a/Govor.Application/Interfaces/ISynchingService.cs b/Govor.Application/Synching/ISynchingService.cs similarity index 89% rename from Govor.Application/Interfaces/ISynchingService.cs rename to Govor.Application/Synching/ISynchingService.cs index ece6de5..44f25cc 100644 --- a/Govor.Application/Interfaces/ISynchingService.cs +++ b/Govor.Application/Synching/ISynchingService.cs @@ -1,4 +1,4 @@ -namespace Govor.Application.Interfaces; +namespace Govor.Application.Synching; public interface ISynchingService { diff --git a/Govor.Application/Services/SynchingService.cs b/Govor.Application/Synching/SynchingService.cs similarity index 82% rename from Govor.Application/Services/SynchingService.cs rename to Govor.Application/Synching/SynchingService.cs index 63f00da..c07f4a0 100644 --- a/Govor.Application/Services/SynchingService.cs +++ b/Govor.Application/Synching/SynchingService.cs @@ -1,6 +1,4 @@ -using Govor.Application.Interfaces; - -namespace Govor.Application.Services; +namespace Govor.Application.Synching; public class SynchingService : ISynchingService { diff --git a/Govor.Application/Users/IUserNameExistValidator.cs b/Govor.Application/Users/IUserNameExistValidator.cs new file mode 100644 index 0000000..95a4b74 --- /dev/null +++ b/Govor.Application/Users/IUserNameExistValidator.cs @@ -0,0 +1,6 @@ +namespace Govor.Application.Users; + +public interface IUserNameExistValidator +{ + Task IsUsernameExistsAsync(string userName); +} \ No newline at end of file diff --git a/Govor.Application/Users/UserNameExistValidator.cs b/Govor.Application/Users/UserNameExistValidator.cs new file mode 100644 index 0000000..f6e40d3 --- /dev/null +++ b/Govor.Application/Users/UserNameExistValidator.cs @@ -0,0 +1,26 @@ +using Govor.Domain; +using Microsoft.EntityFrameworkCore; + +namespace Govor.Application.Users; + +public class UserNameExistValidator : IUserNameExistValidator +{ + private readonly GovorDbContext _context; + + public UserNameExistValidator(GovorDbContext context) + { + _context = context; + } + + public async Task IsUsernameExistsAsync(string userName) + { + if (string.IsNullOrWhiteSpace(userName)) + { + return false; + } + + return await _context.Users + .AsNoTracking() + .AnyAsync(u => u.Username == userName); + } +} \ No newline at end of file diff --git a/Govor.Application/Interfaces/UserOnlineStatus/IOnlineUserStore.cs b/Govor.Application/Users/UserOnlineStatus/IOnlineUserStore.cs similarity index 83% rename from Govor.Application/Interfaces/UserOnlineStatus/IOnlineUserStore.cs rename to Govor.Application/Users/UserOnlineStatus/IOnlineUserStore.cs index 80512ee..12d9952 100644 --- a/Govor.Application/Interfaces/UserOnlineStatus/IOnlineUserStore.cs +++ b/Govor.Application/Users/UserOnlineStatus/IOnlineUserStore.cs @@ -1,4 +1,4 @@ -namespace Govor.Application.Interfaces.UserOnlineStatus; +namespace Govor.Application.Users.UserOnlineStatus; public interface IOnlineUserStore { diff --git a/Govor.Application/Interfaces/UserOnlineStatus/IUserNotificationScopeService.cs b/Govor.Application/Users/UserOnlineStatus/IUserNotificationScopeService.cs similarity index 63% rename from Govor.Application/Interfaces/UserOnlineStatus/IUserNotificationScopeService.cs rename to Govor.Application/Users/UserOnlineStatus/IUserNotificationScopeService.cs index 0ac93a0..29685d8 100644 --- a/Govor.Application/Interfaces/UserOnlineStatus/IUserNotificationScopeService.cs +++ b/Govor.Application/Users/UserOnlineStatus/IUserNotificationScopeService.cs @@ -1,4 +1,4 @@ -namespace Govor.Application.Interfaces.UserOnlineStatus; +namespace Govor.Application.Users.UserOnlineStatus; public interface IUserNotificationScopeService { diff --git a/Govor.Application/Interfaces/UserOnlineStatus/IUserPresenceReader.cs b/Govor.Application/Users/UserOnlineStatus/IUserPresenceReader.cs similarity index 61% rename from Govor.Application/Interfaces/UserOnlineStatus/IUserPresenceReader.cs rename to Govor.Application/Users/UserOnlineStatus/IUserPresenceReader.cs index 5291ccb..fb6a53d 100644 --- a/Govor.Application/Interfaces/UserOnlineStatus/IUserPresenceReader.cs +++ b/Govor.Application/Users/UserOnlineStatus/IUserPresenceReader.cs @@ -1,4 +1,4 @@ -namespace Govor.Application.Interfaces.UserOnlineStatus; +namespace Govor.Application.Users.UserOnlineStatus; public interface IUserPresenceReader { diff --git a/Govor.Application/Services/UserOnlineStatus/OnlineUserStore.cs b/Govor.Application/Users/UserOnlineStatus/OnlineUserStore.cs similarity index 94% rename from Govor.Application/Services/UserOnlineStatus/OnlineUserStore.cs rename to Govor.Application/Users/UserOnlineStatus/OnlineUserStore.cs index b772486..a859537 100644 --- a/Govor.Application/Services/UserOnlineStatus/OnlineUserStore.cs +++ b/Govor.Application/Users/UserOnlineStatus/OnlineUserStore.cs @@ -1,7 +1,6 @@ using System.Collections.Concurrent; -using Govor.Application.Interfaces.UserOnlineStatus; -namespace Govor.Application.Services.UserOnlineStatus; +namespace Govor.Application.Users.UserOnlineStatus; public class OnlineUserStore : IOnlineUserStore { diff --git a/Govor.Application/Services/UserOnlineStatus/UserNotificationScopeService.cs b/Govor.Application/Users/UserOnlineStatus/UserNotificationScopeService.cs similarity index 67% rename from Govor.Application/Services/UserOnlineStatus/UserNotificationScopeService.cs rename to Govor.Application/Users/UserOnlineStatus/UserNotificationScopeService.cs index 82c5cae..8da99c8 100644 --- a/Govor.Application/Services/UserOnlineStatus/UserNotificationScopeService.cs +++ b/Govor.Application/Users/UserOnlineStatus/UserNotificationScopeService.cs @@ -1,9 +1,7 @@ -using Govor.Application.Interfaces.Friends; -using Govor.Application.Interfaces.UserOnlineStatus; -using Govor.Data.Repositories.Exceptions; +using Govor.Application.Friends; using Microsoft.Extensions.Logging; -namespace Govor.Application.Services.UserOnlineStatus; +namespace Govor.Application.Users.UserOnlineStatus; public class UserNotificationScopeService : IUserNotificationScopeService { @@ -18,17 +16,9 @@ public class UserNotificationScopeService : IUserNotificationScopeService public async Task> GetNotifiedUsers(Guid userId) { - try - { - _logger.LogInformation($"Getting notified users of online/offline action user {userId}"); - var users = await _friendships.GetFriendsAsync(userId); - return users.Select(u => u.Id).ToList(); - } - catch (NotFoundByKeyException ex) - { - _logger.LogWarning(ex, ex.Message); - throw new InvalidOperationException("User not found"); - } + _logger.LogInformation($"Getting notified users of online/offline action user {userId}"); + var users = await _friendships.GetFriendsAsync(userId); + return users.Select(u => u.Id).ToList(); } /*public async Task SetWasOnlineAsync(Guid userId, DateTime when) diff --git a/Govor.Application/Services/UserOnlineStatus/UserPresenceReader.cs b/Govor.Application/Users/UserOnlineStatus/UserPresenceReader.cs similarity index 60% rename from Govor.Application/Services/UserOnlineStatus/UserPresenceReader.cs rename to Govor.Application/Users/UserOnlineStatus/UserPresenceReader.cs index aeab7ab..de7f951 100644 --- a/Govor.Application/Services/UserOnlineStatus/UserPresenceReader.cs +++ b/Govor.Application/Users/UserOnlineStatus/UserPresenceReader.cs @@ -1,6 +1,4 @@ -using Govor.Application.Interfaces.UserOnlineStatus; - -namespace Govor.Application.Services.UserOnlineStatus; +namespace Govor.Application.Users.UserOnlineStatus; public class UserPresenceReader : IUserPresenceReader { diff --git a/Govor.Application/Interfaces/UserSession/Crypto/IOneTimePreKeysRotator.cs b/Govor.Application/Users/UserSessions/Crypto/IOneTimePreKeysRotator.cs similarity index 78% rename from Govor.Application/Interfaces/UserSession/Crypto/IOneTimePreKeysRotator.cs rename to Govor.Application/Users/UserSessions/Crypto/IOneTimePreKeysRotator.cs index 9bf0865..6c3a7dc 100644 --- a/Govor.Application/Interfaces/UserSession/Crypto/IOneTimePreKeysRotator.cs +++ b/Govor.Application/Users/UserSessions/Crypto/IOneTimePreKeysRotator.cs @@ -1,4 +1,4 @@ -namespace Govor.Application.Interfaces.UserSession.Crypto; +namespace Govor.Application.Users.UserSessions.Crypto; public interface IOneTimePreKeysRotator { diff --git a/Govor.Application/Interfaces/UserSession/Crypto/ISessionKeyAttacher.cs b/Govor.Application/Users/UserSessions/Crypto/ISessionKeyAttacher.cs similarity index 70% rename from Govor.Application/Interfaces/UserSession/Crypto/ISessionKeyAttacher.cs rename to Govor.Application/Users/UserSessions/Crypto/ISessionKeyAttacher.cs index d08db89..214aef6 100644 --- a/Govor.Application/Interfaces/UserSession/Crypto/ISessionKeyAttacher.cs +++ b/Govor.Application/Users/UserSessions/Crypto/ISessionKeyAttacher.cs @@ -1,6 +1,6 @@ -using Govor.Core.Models.Users.Crypto; +using Govor.Domain.Models.Users.Crypto; -namespace Govor.Application.Interfaces.UserSession.Crypto; +namespace Govor.Application.Users.UserSessions.Crypto; public interface ISessionKeyAttacher { diff --git a/Govor.Application/Interfaces/UserSession/Crypto/ISessionKeysReader.cs b/Govor.Application/Users/UserSessions/Crypto/ISessionKeysReader.cs similarity index 75% rename from Govor.Application/Interfaces/UserSession/Crypto/ISessionKeysReader.cs rename to Govor.Application/Users/UserSessions/Crypto/ISessionKeysReader.cs index 5a0a23f..eb5a1a4 100644 --- a/Govor.Application/Interfaces/UserSession/Crypto/ISessionKeysReader.cs +++ b/Govor.Application/Users/UserSessions/Crypto/ISessionKeysReader.cs @@ -1,6 +1,6 @@ -using Govor.Core.Models.Users.Crypto; +using Govor.Domain.Models.Users.Crypto; -namespace Govor.Application.Interfaces.UserSession.Crypto; +namespace Govor.Application.Users.UserSessions.Crypto; public interface ISessionKeysReader { diff --git a/Govor.Application/Services/UserSessions/Crypto/OneTimePreKeysRotator.cs b/Govor.Application/Users/UserSessions/Crypto/OneTimePreKeysRotator.cs similarity index 90% rename from Govor.Application/Services/UserSessions/Crypto/OneTimePreKeysRotator.cs rename to Govor.Application/Users/UserSessions/Crypto/OneTimePreKeysRotator.cs index 0e5856c..e652413 100644 --- a/Govor.Application/Services/UserSessions/Crypto/OneTimePreKeysRotator.cs +++ b/Govor.Application/Users/UserSessions/Crypto/OneTimePreKeysRotator.cs @@ -1,11 +1,10 @@ -using Govor.Application.Interfaces.Infrastructure.Extensions; -using Govor.Application.Interfaces.UserSession.Crypto; -using Govor.Core.Models.Users.Crypto; -using Govor.Data; +using Govor.Application.Infrastructure.Extensions; +using Govor.Domain.Models.Users.Crypto; +using Govor.Domain; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; -namespace Govor.Application.Services.UserSessions.Crypto; +namespace Govor.Application.Users.UserSessions.Crypto; public class OneTimePreKeysRotator : IOneTimePreKeysRotator { diff --git a/Govor.Application/Services/UserSessions/Crypto/SessionKeyAttacher.cs b/Govor.Application/Users/UserSessions/Crypto/SessionKeyAttacher.cs similarity index 90% rename from Govor.Application/Services/UserSessions/Crypto/SessionKeyAttacher.cs rename to Govor.Application/Users/UserSessions/Crypto/SessionKeyAttacher.cs index 1a42da3..c4860fb 100644 --- a/Govor.Application/Services/UserSessions/Crypto/SessionKeyAttacher.cs +++ b/Govor.Application/Users/UserSessions/Crypto/SessionKeyAttacher.cs @@ -1,11 +1,10 @@ -using Govor.Application.Interfaces.Infrastructure.Extensions; -using Govor.Application.Interfaces.UserSession.Crypto; -using Govor.Core.Models.Users.Crypto; -using Govor.Data; +using Govor.Application.Infrastructure.Extensions; +using Govor.Domain.Models.Users.Crypto; +using Govor.Domain; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; -namespace Govor.Application.Services.UserSessions.Crypto; +namespace Govor.Application.Users.UserSessions.Crypto; public class SessionKeyAttacher : ISessionKeyAttacher { diff --git a/Govor.Application/Services/UserSessions/Crypto/SessionKeysReader.cs b/Govor.Application/Users/UserSessions/Crypto/SessionKeysReader.cs similarity index 89% rename from Govor.Application/Services/UserSessions/Crypto/SessionKeysReader.cs rename to Govor.Application/Users/UserSessions/Crypto/SessionKeysReader.cs index 8a9e81a..f8c474f 100644 --- a/Govor.Application/Services/UserSessions/Crypto/SessionKeysReader.cs +++ b/Govor.Application/Users/UserSessions/Crypto/SessionKeysReader.cs @@ -1,11 +1,9 @@ -using Govor.Application.Interfaces.Infrastructure.Extensions; -using Govor.Application.Interfaces.UserSession.Crypto; -using Govor.Core.Models.Users.Crypto; -using Govor.Data; +using Govor.Domain.Models.Users.Crypto; +using Govor.Domain; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; -namespace Govor.Application.Services.UserSessions.Crypto; +namespace Govor.Application.Users.UserSessions.Crypto; public class SessionKeysReader : ISessionKeysReader { diff --git a/Govor.Application/Users/UserSessions/IUserSessionOpener.cs b/Govor.Application/Users/UserSessions/IUserSessionOpener.cs new file mode 100644 index 0000000..4f95a7a --- /dev/null +++ b/Govor.Application/Users/UserSessions/IUserSessionOpener.cs @@ -0,0 +1,11 @@ +using Govor.Domain.Common; +using Govor.Domain.Models.Users; + +namespace Govor.Application.Users.UserSessions; + + +public interface IUserSessionOpener +{ + Task> OpenSessionAsync(User user, string deviceInfo); +} + diff --git a/Govor.Application/Users/UserSessions/IUserSessionReader.cs b/Govor.Application/Users/UserSessions/IUserSessionReader.cs new file mode 100644 index 0000000..49432c5 --- /dev/null +++ b/Govor.Application/Users/UserSessions/IUserSessionReader.cs @@ -0,0 +1,8 @@ +using Govor.Domain.Common; + +namespace Govor.Application.Users.UserSessions; + +public interface IUserSessionReader +{ + Task>> GetAllSessionsAsync(Guid userId); +} \ No newline at end of file diff --git a/Govor.Application/Users/UserSessions/IUserSessionRefresher.cs b/Govor.Application/Users/UserSessions/IUserSessionRefresher.cs new file mode 100644 index 0000000..602e79e --- /dev/null +++ b/Govor.Application/Users/UserSessions/IUserSessionRefresher.cs @@ -0,0 +1,8 @@ +using Govor.Domain.Common; + +namespace Govor.Application.Users.UserSessions; + +public interface IUserSessionRefresher +{ + Task> RefreshTokenAsync(string refreshToken); +} \ No newline at end of file diff --git a/Govor.Application/Users/UserSessions/IUserSessionRevoker.cs b/Govor.Application/Users/UserSessions/IUserSessionRevoker.cs new file mode 100644 index 0000000..0369cef --- /dev/null +++ b/Govor.Application/Users/UserSessions/IUserSessionRevoker.cs @@ -0,0 +1,10 @@ +using Govor.Domain.Common; + +namespace Govor.Application.Users.UserSessions; + + +public interface IUserSessionRevoker +{ + Task CloseSessionByIdAsync(Guid sessionId, Guid userId); + Task CloseAllSessionsAsync(Guid userId); +} diff --git a/Govor.Application/Users/UserSessions/RefreshResult.cs b/Govor.Application/Users/UserSessions/RefreshResult.cs new file mode 100644 index 0000000..0e907d7 --- /dev/null +++ b/Govor.Application/Users/UserSessions/RefreshResult.cs @@ -0,0 +1,3 @@ +namespace Govor.Application.Users.UserSessions; + +public record RefreshResult(string refreshToken, string accessToken); \ No newline at end of file diff --git a/Govor.Application/Services/UserSessions/UserSessionOpener.cs b/Govor.Application/Users/UserSessions/UserSessionOpener.cs similarity index 52% rename from Govor.Application/Services/UserSessions/UserSessionOpener.cs rename to Govor.Application/Users/UserSessions/UserSessionOpener.cs index bf4a382..4788505 100644 --- a/Govor.Application/Services/UserSessions/UserSessionOpener.cs +++ b/Govor.Application/Users/UserSessions/UserSessionOpener.cs @@ -1,54 +1,74 @@ -using Govor.Application.Interfaces.Authentication; -using Govor.Application.Interfaces.UserSession; -using Govor.Application.Services.Authentication; -using Govor.Core.Models.Users; -using Govor.Core.Repositories.UserSessionsRepository; -using Govor.Data.Repositories.Exceptions; +using Govor.Application.Authentication.JWT; +using Govor.Domain; +using Govor.Domain.Common; // Путь к вашему Result и Error +using Govor.Domain.Models.Users; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; -namespace Govor.Application.Services.UserSessions; +namespace Govor.Application.Users.UserSessions; public class UserSessionOpener : IUserSessionOpener { - private readonly IUserSessionsRepository _repository; private readonly ILogger _logger; + private readonly IUserSessionReader _userSessionReader; + private readonly GovorDbContext _context; private readonly IJwtTokenHasher _jwtTokenHasher; private readonly JwtRefreshOption _options; private readonly IJwtService _jwtService; public UserSessionOpener( - IUserSessionsRepository repository, - IJwtService jwtService, + ILogger logger, + IUserSessionReader userSessionReader, + GovorDbContext context, IJwtTokenHasher jwtTokenHasher, IOptions options, - ILogger logger) + IJwtService jwtService) { - _jwtService = jwtService; - _repository = repository; - _jwtTokenHasher = jwtTokenHasher; _logger = logger; + _userSessionReader = userSessionReader; + _context = context; + _jwtTokenHasher = jwtTokenHasher; _options = options.Value; + _jwtService = jwtService; } - public async Task OpenSessionAsync(User user, string deviceInfo) + public async Task> OpenSessionAsync(User user, string deviceInfo) { - _logger.LogInformation($"Opening session for user {user.Id} on device '{deviceInfo}'"); + _logger.LogInformation("Opening session for user {UserId} on device '{DeviceInfo}'", user.Id, deviceInfo); + + var result = await _userSessionReader.GetAllSessionsAsync(user.Id); + + if (result.IsFailure) + { + _logger.LogError("Failed to fetch sessions for user {UserId}: {Error}", user.Id, result.Error.Message); + return Result.Failure(result.Error); + } + + var sessions = result.Value; + var existingSession = sessions.FirstOrDefault(s => s.DeviceInfo == deviceInfo); try { - var sessions = await _repository.GetByUserIdAsync(user.Id); - var existingSession = sessions.FirstOrDefault(s => s.DeviceInfo == deviceInfo ); + RefreshResult refreshResult; if (existingSession is not null) - return await UpdateExistingSessionAsync(user, deviceInfo, existingSession); + { + refreshResult = await UpdateExistingSessionAsync(user, deviceInfo, existingSession); + } + else + { + refreshResult = await CreateNewSessionAsync(user, deviceInfo); + } + + await _context.SaveChangesAsync(); + + return refreshResult; } - catch (NotFoundByKeyException ex) + catch (Exception ex) { - _logger.LogError(ex, "Could not find session for user {userId}", user.Id); + _logger.LogError(ex, "Database error while opening session for user {UserId}", user.Id); + return Result.Failure(ex); } - - return await CreateNewSessionAsync(user, deviceInfo); } private async Task UpdateExistingSessionAsync(User user, string deviceInfo, UserSession session) @@ -57,14 +77,13 @@ public class UserSessionOpener : IUserSessionOpener var newTokenHash = _jwtTokenHasher.HashToken(refreshToken); var newExpiresAt = DateTime.UtcNow.AddDays(_options.RefreshTokenLifetimeDays); - + session.RefreshTokenHash = newTokenHash; session.ExpiresAt = newExpiresAt; session.CreatedAt = DateTime.UtcNow; session.IsRevoked = false; - - await _repository.UpdateAsync(session); - _logger.LogInformation($"Updated session for user {user.Id} on device '{deviceInfo}'"); + + _logger.LogInformation("Updated session for user {UserId} on device '{DeviceInfo}'", user.Id, deviceInfo); return new RefreshResult(refreshToken, accessToken); } @@ -86,10 +105,10 @@ public class UserSessionOpener : IUserSessionOpener ExpiresAt = DateTime.UtcNow.AddDays(_options.RefreshTokenLifetimeDays), IsRevoked = false }; + + await _context.UserSessions.AddAsync(newSession); - await _repository.AddAsync(newSession); - - _logger.LogInformation($"Created new session {sessionId} for user {user.Id} on device '{deviceInfo}'"); + _logger.LogInformation("Created new session {SessionId} for user {UserId} on device '{DeviceInfo}'", sessionId, user.Id, deviceInfo); return new RefreshResult(refreshToken, accessToken); } diff --git a/Govor.Application/Users/UserSessions/UserSessionReader.cs b/Govor.Application/Users/UserSessions/UserSessionReader.cs new file mode 100644 index 0000000..fdbcb68 --- /dev/null +++ b/Govor.Application/Users/UserSessions/UserSessionReader.cs @@ -0,0 +1,46 @@ +using Govor.Domain; +using Govor.Domain.Common; +using Govor.Domain.Models.Users; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; + +namespace Govor.Application.Users.UserSessions; + +public class UserSessionReader : IUserSessionReader +{ + private readonly GovorDbContext _context; + private readonly ILogger _logger; + + public UserSessionReader(GovorDbContext context, ILogger logger) + { + _context = context; + _logger = logger; + } + + public async Task>> GetAllSessionsAsync(Guid userId) + { + if (userId == Guid.Empty) + { + return Result>.Failure(new Error( + "UserSession.InvalidUserId", + "Provided User ID cannot be empty.")); + } + + _logger.LogInformation("Getting all active sessions for user {UserId}", userId); + + try + { + var sessions = await _context.UserSessions + .AsNoTracking() + .Where(s => s.UserId == userId && !s.IsRevoked) + .ToListAsync(); + + return sessions; + } + catch (Exception ex) + { + _logger.LogError(ex, "Failed to fetch user sessions for user {UserId}", userId); + return Result>.Failure(ex); + } + } +} \ No newline at end of file diff --git a/Govor.Application/Users/UserSessions/UserSessionRefresher.cs b/Govor.Application/Users/UserSessions/UserSessionRefresher.cs new file mode 100644 index 0000000..1486d16 --- /dev/null +++ b/Govor.Application/Users/UserSessions/UserSessionRefresher.cs @@ -0,0 +1,80 @@ +using Govor.Application.Authentication.JWT; +using Govor.Domain; +using Govor.Domain.Common; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; + +namespace Govor.Application.Users.UserSessions; + +public class UserSessionRefresher : IUserSessionRefresher +{ + private readonly ILogger _logger; + private readonly JwtRefreshOption _options; + private readonly IJwtTokenHasher _jwtTokenHasher; + private readonly IJwtService _jwtService; + private readonly GovorDbContext _context; + + public UserSessionRefresher( + ILogger logger, + IOptions options, + IJwtTokenHasher jwtTokenHasher, + IJwtService jwtService, + GovorDbContext context) + { + _logger = logger; + _options = options.Value; + _jwtTokenHasher = jwtTokenHasher; + _jwtService = jwtService; + _context = context; + } + + public async Task> RefreshTokenAsync(string refreshToken) + { + if (string.IsNullOrWhiteSpace(refreshToken)) + { + return Result.Failure(new Error("Auth.EmptyToken", "Refresh token cannot be empty.")); + } + + var hashedToken = _jwtTokenHasher.HashToken(refreshToken); + + try + { + var session = await _context.UserSessions + .AsNoTracking() + .Include(userSession => userSession.User) + .FirstOrDefaultAsync(s => s.RefreshTokenHash == hashedToken); + + if (session is null) + { + _logger.LogWarning("Refresh token session not found for hashed token"); + return Result.Failure(new Error("Auth.InvalidToken", "Invalid refresh token.")); + } + + if (session.IsRevoked || session.ExpiresAt <= DateTime.UtcNow) + { + _logger.LogWarning("Attempted to refresh an expired or revoked session: {SessionId}", session.Id); + return Result.Failure(new Error("Auth.InvalidToken", "Refresh token is invalid or expired.")); + } + + var newAccessToken = await _jwtService.GenerateAccessTokenAsync(session.User, session.Id); + var newRefreshToken = await _jwtService.GenerateRefreshTokenAsync(session.User); + var newRefreshTokenHash = _jwtTokenHasher.HashToken(newRefreshToken); + + session.RefreshTokenHash = newRefreshTokenHash; + session.CreatedAt = DateTime.UtcNow; + session.ExpiresAt = DateTime.UtcNow.AddDays(_options.RefreshTokenLifetimeDays); + + await _context.SaveChangesAsync(); + + _logger.LogInformation("Successfully refreshed session {SessionId} for user {UserId}", session.Id, session.UserId); + + return new RefreshResult(newRefreshToken, newAccessToken); + } + catch (Exception ex) + { + _logger.LogError(ex, "Database error occurred during token refresh execution"); + return Result.Failure(ex); + } + } +} diff --git a/Govor.Application/Users/UserSessions/UserSessionRevoker.cs b/Govor.Application/Users/UserSessions/UserSessionRevoker.cs new file mode 100644 index 0000000..4135449 --- /dev/null +++ b/Govor.Application/Users/UserSessions/UserSessionRevoker.cs @@ -0,0 +1,85 @@ +using Govor.Application.PushNotifications; +using Govor.Domain; +using Govor.Domain.Common; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; + +namespace Govor.Application.Users.UserSessions; + +public class UserSessionRevoker : IUserSessionRevoker +{ + private readonly GovorDbContext _context; + private readonly IPushTokenService _tokenService; + private readonly ILogger _logger; + + public UserSessionRevoker( + GovorDbContext context, + IPushTokenService tokenService, + ILogger logger) + { + _tokenService = tokenService; + _context = context; + _logger = logger; + } + + public async Task CloseSessionByIdAsync(Guid sessionId, Guid userId) + { + _logger.LogInformation("Attempting to close session {SessionId} for user {UserId}", sessionId, userId); + + try + { + var session = await _context.UserSessions + .FirstOrDefaultAsync(s => s.Id == sessionId && s.UserId == userId && !s.IsRevoked); + + if (session is null) + { + _logger.LogWarning("Active session {SessionId} not found or doesn't belong to user {UserId}", sessionId, userId); + return Result.Failure(new Error( + "UserSession.NotFoundOrUnauthorized", + $"Active session {sessionId} for user {userId} was not found.")); + } + + session.IsRevoked = true; + + await _context.SaveChangesAsync(); + + await _tokenService.DeactivateTokenBySessionAsync(sessionId); + + _logger.LogInformation("Successfully revoked session {SessionId}", sessionId); + return Result.Success(); + } + catch (Exception ex) + { + _logger.LogError(ex, "Error occurred while closing session {SessionId}", sessionId); + return Result.Failure(ex); + } + } + + public async Task CloseAllSessionsAsync(Guid userId) + { + _logger.LogInformation("Attempting to close all active sessions for user {UserId}", userId); + + try + { + var updatedRowsCount = await _context.UserSessions + .Where(s => s.UserId == userId && !s.IsRevoked) + .ExecuteUpdateAsync(setters => setters.SetProperty(s => s.IsRevoked, true)); + + if (updatedRowsCount == 0) + { + _logger.LogInformation("User {UserId} had no active sessions to close", userId); + return Result.Success(); + } + + await _tokenService.DeactivateAllTokensByUserIdAsync(userId); + + _logger.LogInformation("Successfully revoked all {Count} active sessions for user {UserId}", updatedRowsCount, userId); + return Result.Success(); + } + catch (Exception ex) + { + _logger.LogError(ex, "Error occurred while closing all sessions for user {UserId}", userId); + return Result.Failure(ex); + } + } +} \ No newline at end of file diff --git a/Govor.ConsoleClient/Govor.ConsoleClient.csproj b/Govor.ConsoleClient/Govor.ConsoleClient.csproj index e3de400..1686633 100644 --- a/Govor.ConsoleClient/Govor.ConsoleClient.csproj +++ b/Govor.ConsoleClient/Govor.ConsoleClient.csproj @@ -16,7 +16,6 @@ - diff --git a/Govor.Contracts/DTOs/FriendshipDto.cs b/Govor.Contracts/DTOs/FriendshipDto.cs index 85065e1..fa09625 100644 --- a/Govor.Contracts/DTOs/FriendshipDto.cs +++ b/Govor.Contracts/DTOs/FriendshipDto.cs @@ -1,4 +1,4 @@ -using Govor.Core.Models; +using Govor.Domain.Models; namespace Govor.Contracts.DTOs; diff --git a/Govor.Contracts/Govor.Contracts.csproj b/Govor.Contracts/Govor.Contracts.csproj index 6427a81..ed3cb48 100644 --- a/Govor.Contracts/Govor.Contracts.csproj +++ b/Govor.Contracts/Govor.Contracts.csproj @@ -7,7 +7,7 @@ - + diff --git a/Govor.Contracts/Requests/AvatarUploadRequest.cs b/Govor.Contracts/Requests/AvatarUploadRequest.cs index 3ae6553..4458dec 100644 --- a/Govor.Contracts/Requests/AvatarUploadRequest.cs +++ b/Govor.Contracts/Requests/AvatarUploadRequest.cs @@ -1,6 +1,6 @@ using System.ComponentModel.DataAnnotations; -using Govor.Core.Models; -using Govor.Core.Models.Messages; +using Govor.Domain.Models; +using Govor.Domain.Models.Messages; using Microsoft.AspNetCore.Http; namespace Govor.Contracts.Requests; diff --git a/Govor.Contracts/Requests/LoginRequest.cs b/Govor.Contracts/Requests/LoginRequest.cs index f7a0b11..25f6d20 100644 --- a/Govor.Contracts/Requests/LoginRequest.cs +++ b/Govor.Contracts/Requests/LoginRequest.cs @@ -1,14 +1,14 @@ using System.ComponentModel.DataAnnotations; -using Govor.Core.Infrastructure.Validators; +using Govor.Domain.Common.Constants; namespace Govor.Contracts.Requests; public class LoginRequest { [Required] - [StringLength(UserValidator.MAX_LENGHT_OF_NAME, - MinimumLength = UserValidator.MIN_LENGHT_OF_NAME, - ErrorMessage = "Username must be between 4 and 50 characters.")] + [StringLength(UserConstants.MAX_LENGHT_OF_NAME, + MinimumLength = UserConstants.MIN_LENGHT_OF_NAME, + ErrorMessage = "Username must be between 4 and 44 characters.")] public string Name { get; init; } [Required] [MinLength(8)] diff --git a/Govor.Contracts/Requests/MediaUploadRequest.cs b/Govor.Contracts/Requests/MediaUploadRequest.cs index ec62161..4baa48f 100644 --- a/Govor.Contracts/Requests/MediaUploadRequest.cs +++ b/Govor.Contracts/Requests/MediaUploadRequest.cs @@ -1,5 +1,5 @@ -using Govor.Core.Models; -using Govor.Core.Models.Messages; +using Govor.Domain.Models; +using Govor.Domain.Models.Messages; using Microsoft.AspNetCore.Http; using System.ComponentModel.DataAnnotations; diff --git a/Govor.Contracts/Requests/RegistrationRequest.cs b/Govor.Contracts/Requests/RegistrationRequest.cs index eb130c8..afe6048 100644 --- a/Govor.Contracts/Requests/RegistrationRequest.cs +++ b/Govor.Contracts/Requests/RegistrationRequest.cs @@ -1,19 +1,19 @@ using System.ComponentModel.DataAnnotations; -using Govor.Core.Infrastructure.Validators; +using Govor.Domain.Common.Constants; namespace Govor.Contracts.Requests; public record RegistrationRequest { [Required] - [StringLength(UserValidator.MAX_LENGHT_OF_NAME, - MinimumLength = UserValidator.MIN_LENGHT_OF_NAME, + [StringLength(UserConstants.MAX_LENGHT_OF_NAME, + MinimumLength = UserConstants.MIN_LENGHT_OF_NAME, ErrorMessage = "Username must be between 4 and 44 characters.")] public string Name { get; init; } [Required] [MinLength(8)] public string Password { get; init; } - [MinLength(InvitationValidator.MIN_INVITATION_LENGTH)] + [MinLength(InvitationConstants.MIN_INVITATION_LENGTH)] public string InviteLink { get; init; } public string DeviceInfo { get; init; } } diff --git a/Govor.Contracts/Requests/SignalR/MediaReference.cs b/Govor.Contracts/Requests/SignalR/MediaReference.cs index d2b9a1b..21f8d3a 100644 --- a/Govor.Contracts/Requests/SignalR/MediaReference.cs +++ b/Govor.Contracts/Requests/SignalR/MediaReference.cs @@ -1,4 +1,4 @@ -using Govor.Core.Models; +using Govor.Domain.Models; namespace Govor.Contracts.Requests.SignalR; diff --git a/Govor.Contracts/Requests/SignalR/MessageRequest.cs b/Govor.Contracts/Requests/SignalR/MessageRequest.cs index d2dabaf..61f5802 100644 --- a/Govor.Contracts/Requests/SignalR/MessageRequest.cs +++ b/Govor.Contracts/Requests/SignalR/MessageRequest.cs @@ -1,4 +1,4 @@ -using Govor.Core.Models.Messages; +using Govor.Domain.Models.Messages; using System.ComponentModel.DataAnnotations; namespace Govor.Contracts.Requests.SignalR; diff --git a/Govor.Contracts/Responses/MessageResponse.cs b/Govor.Contracts/Responses/MessageResponse.cs index 60ea4ba..6d013f0 100644 --- a/Govor.Contracts/Responses/MessageResponse.cs +++ b/Govor.Contracts/Responses/MessageResponse.cs @@ -1,4 +1,4 @@ -using Govor.Core.Models.Messages; +using Govor.Domain.Models.Messages; namespace Govor.Contracts.Responses; diff --git a/Govor.Contracts/Responses/SignalR/MessageEditResponse.cs b/Govor.Contracts/Responses/SignalR/MessageEditResponse.cs index f03c638..dcb51d6 100644 --- a/Govor.Contracts/Responses/SignalR/MessageEditResponse.cs +++ b/Govor.Contracts/Responses/SignalR/MessageEditResponse.cs @@ -1,4 +1,4 @@ -using Govor.Core.Models.Messages; +using Govor.Domain.Models.Messages; namespace Govor.Contracts.Responses.SignalR; diff --git a/Govor.Contracts/Responses/SignalR/MessageRemovedResponse.cs b/Govor.Contracts/Responses/SignalR/MessageRemovedResponse.cs index 89471b4..07a72d4 100644 --- a/Govor.Contracts/Responses/SignalR/MessageRemovedResponse.cs +++ b/Govor.Contracts/Responses/SignalR/MessageRemovedResponse.cs @@ -1,4 +1,4 @@ -using Govor.Core.Models.Messages; +using Govor.Domain.Models.Messages; namespace Govor.Contracts.Responses.SignalR; diff --git a/Govor.Contracts/Responses/SignalR/UserMessageResponse.cs b/Govor.Contracts/Responses/SignalR/UserMessageResponse.cs index 0106c6e..9d664c9 100644 --- a/Govor.Contracts/Responses/SignalR/UserMessageResponse.cs +++ b/Govor.Contracts/Responses/SignalR/UserMessageResponse.cs @@ -1,5 +1,5 @@ -using Govor.Core.Models; -using Govor.Core.Models.Messages; +using Govor.Domain.Models; +using Govor.Domain.Models.Messages; namespace Govor.Contracts.Responses.SignalR; diff --git a/Govor.Core/Govor.Core.csproj b/Govor.Core/Govor.Core.csproj deleted file mode 100644 index eaa57c8..0000000 --- a/Govor.Core/Govor.Core.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - - net8.0 - enable - enable - - - - - - - diff --git a/Govor.Core/Infrastructure/Validators/AdminValidator.cs b/Govor.Core/Infrastructure/Validators/AdminValidator.cs deleted file mode 100644 index 2aebfb6..0000000 --- a/Govor.Core/Infrastructure/Validators/AdminValidator.cs +++ /dev/null @@ -1,34 +0,0 @@ -using Govor.Core.Models.Users; - -namespace Govor.Core.Infrastructure.Validators; - -public class AdminValidator : IObjectValidator -{ - public void Validate(Admin admin) - { - try - { - if(admin is null) - throw new ArgumentNullException(nameof(admin)); - if(admin.UserId == Guid.Empty) - throw new ArgumentException("User ID cannot be empty", nameof(admin.UserId)); - } - catch (Exception e) - { - throw new InvalidObjectException(e); - } - } - - public bool TryValidate(Admin admin) - { - try - { - Validate(admin); - return true; - } - catch (Exception e) - { - return false; - } - } -} \ No newline at end of file diff --git a/Govor.Core/Infrastructure/Validators/ChatGroupValidator.cs b/Govor.Core/Infrastructure/Validators/ChatGroupValidator.cs deleted file mode 100644 index c8e70ff..0000000 --- a/Govor.Core/Infrastructure/Validators/ChatGroupValidator.cs +++ /dev/null @@ -1,44 +0,0 @@ -using Govor.Core.Models; - -namespace Govor.Core.Infrastructure.Validators; - -public class ChatGroupValidator : IObjectValidator -{ - public void Validate(ChatGroup chat) - { - try - { - if(chat is null) - throw new ArgumentNullException(nameof(chat)); - if(chat.Id == Guid.Empty) - throw new ArgumentException("Id of chat group can't be empty",nameof(chat.Id)); - if(string.IsNullOrEmpty(chat.Name)) - throw new ArgumentException("Name of chat group can't be empty",nameof(chat.Name)); - if(chat.Description is null) - throw new ArgumentException("Description of chat group can't be null",nameof(chat.Description)); - if(chat.ImageId == Guid.Empty) - throw new ArgumentException("ImageId of chat group can't be empty",nameof(chat.ImageId)); - if(chat.IsPrivate && chat.InviteCodes.Count <= 0) - throw new ArgumentException("Private group must have invitation links",nameof(chat.InviteCodes)); - if(chat.Admins.Count <= 0) - throw new ArgumentException("Chat must have owner",nameof(chat.Admins)); - } - catch (Exception ex) - { - throw new InvalidObjectException(ex); - } - } - - public bool TryValidate(ChatGroup chat) - { - try - { - Validate(chat); - return true; - } - catch (Exception) - { - return false; - } - } -} \ No newline at end of file diff --git a/Govor.Core/Infrastructure/Validators/FriendshipValidator.cs b/Govor.Core/Infrastructure/Validators/FriendshipValidator.cs deleted file mode 100644 index 96c0c40..0000000 --- a/Govor.Core/Infrastructure/Validators/FriendshipValidator.cs +++ /dev/null @@ -1,40 +0,0 @@ -using Govor.Core.Models; - -namespace Govor.Core.Infrastructure.Validators; - -public class FriendshipValidator : IObjectValidator -{ - public void Validate(Friendship friendship) - { - try - { - if(friendship is null) - throw new ArgumentNullException(nameof(friendship)); - if(friendship.Id == Guid.Empty) - throw new ArgumentException("Id cannot be empty", nameof(friendship.Id)); - if(friendship.AddresseeId == Guid.Empty) - throw new ArgumentException("Addresses cannot be empty", nameof(friendship.AddresseeId)); - if(friendship.RequesterId == Guid.Empty) - throw new ArgumentException("Requester cannot be empty", nameof(friendship.RequesterId)); - if(friendship.AddresseeId == friendship.RequesterId) - throw new ArgumentException("Addresses cannot be same", nameof(friendship.AddresseeId)); - } - catch (Exception e) - { - throw new InvalidObjectException(e); - } - } - - public bool TryValidate(Friendship friendship) - { - try - { - Validate(friendship); - return true; - } - catch - { - return false; - } - } -} \ No newline at end of file diff --git a/Govor.Core/Infrastructure/Validators/IObjectValidator.cs b/Govor.Core/Infrastructure/Validators/IObjectValidator.cs deleted file mode 100644 index f33f949..0000000 --- a/Govor.Core/Infrastructure/Validators/IObjectValidator.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Govor.Core.Infrastructure.Validators; - -public interface IObjectValidator -{ - void Validate(T objectToValidate); - bool TryValidate(T objectToValidate); -} - -public class InvalidObjectException(Exception ex) : GovorCoreException($"The object {typeof(T).FullName} is invalid.", ex); \ No newline at end of file diff --git a/Govor.Core/Infrastructure/Validators/InvitationValidator.cs b/Govor.Core/Infrastructure/Validators/InvitationValidator.cs deleted file mode 100644 index ec8e36a..0000000 --- a/Govor.Core/Infrastructure/Validators/InvitationValidator.cs +++ /dev/null @@ -1,43 +0,0 @@ -using Govor.Core.Models; - -namespace Govor.Core.Infrastructure.Validators; - -public class InvitationValidator : IObjectValidator -{ - public const int MIN_INVITATION_LENGTH = 10; - public void Validate(Invitation inv) - { - try - { - if(inv is null) - throw new ArgumentNullException(nameof(inv)); - if(inv.Id == Guid.Empty) - throw new ArgumentException("Id cannot be empty", nameof(inv.Id)); - if(inv.DateCreated == DateTime.MinValue) - throw new ArgumentException("DateCreated cannot be empty", nameof(inv.DateCreated)); - if(inv.EndDate < inv.DateCreated && inv.IsActive) - throw new ArgumentException("EndDate cannot be less than StartDate when is active", nameof(inv.EndDate)); - if((inv.MaxParticipants <= 0 || inv.MaxParticipants <= inv.Users.Count) && inv.IsActive) - throw new ArgumentException("MaxParticipants cannot be less than 0 or users cannot be more then MaxParticipants when is active", nameof(inv.MaxParticipants)); - if(inv.Code == string.Empty || inv.Code.Length < MIN_INVITATION_LENGTH) - throw new ArgumentException($"Code cannot be empty or less then {MIN_INVITATION_LENGTH}", nameof(inv.Code)); - } - catch (Exception ex) - { - throw new InvalidObjectException(ex); - } - } - - public bool TryValidate(Invitation inv) - { - try - { - Validate(inv); - return true; - } - catch (Exception e) - { - return false; - } - } -} \ No newline at end of file diff --git a/Govor.Core/Infrastructure/Validators/MediaAttachmentsValidator.cs b/Govor.Core/Infrastructure/Validators/MediaAttachmentsValidator.cs deleted file mode 100644 index 6a2bd1c..0000000 --- a/Govor.Core/Infrastructure/Validators/MediaAttachmentsValidator.cs +++ /dev/null @@ -1,40 +0,0 @@ -using Govor.Core.Models.Messages; -using Exception = System.Exception; - -namespace Govor.Core.Infrastructure.Validators; - -public class MediaAttachmentsValidator : IObjectValidator -{ - public void Validate(MediaAttachments attachments) - { - try - { - if (attachments is null) - throw new ArgumentNullException(nameof(attachments)); - if(attachments.Id == Guid.Empty) - throw new ArgumentException("Id cannot be empty", nameof(attachments)); - if(attachments.MessageId == Guid.Empty) - throw new ArgumentException("MessageId cannot be empty", nameof(attachments)); - if(string.IsNullOrWhiteSpace(attachments.MediaFile.Url)) - throw new ArgumentException("File path cannot be empty", nameof(attachments)); - } - catch (Exception ex) - { - throw new InvalidObjectException(ex); - } - - } - - public bool TryValidate(MediaAttachments attachments) - { - try - { - Validate(attachments); - return true; - } - catch (Exception) - { - return false; - } - } -} \ No newline at end of file diff --git a/Govor.Core/Infrastructure/Validators/MessageValidator.cs b/Govor.Core/Infrastructure/Validators/MessageValidator.cs deleted file mode 100644 index 149ac1d..0000000 --- a/Govor.Core/Infrastructure/Validators/MessageValidator.cs +++ /dev/null @@ -1,44 +0,0 @@ -using Govor.Core.Models.Messages; - -namespace Govor.Core.Infrastructure.Validators; - -public class MessageValidator : IObjectValidator -{ - public void Validate(Message message) - { - try - { - if (message is null) - throw new ArgumentNullException(nameof(message)); - if (message.Id == Guid.Empty) - throw new ArgumentException("Message ID cannot be empty", nameof(message.Id)); - if (message.SenderId == Guid.Empty) - throw new ArgumentException("Sender ID cannot be empty", nameof(message.SenderId)); - if (message.RecipientId == Guid.Empty) - throw new ArgumentException("Recipient ID cannot be empty", nameof(message.RecipientId)); - if(string.IsNullOrWhiteSpace(message.EncryptedContent) && (message.MediaAttachments is null || message.MediaAttachments.Count == 0)) - throw new ArgumentException("Encrypted content cannot be empty when media attachments are empty", nameof(message.EncryptedContent)); - if(message.IsEdited && message.EditedAt == DateTime.MinValue) - throw new ArgumentException("Edited at time cannot be empty", nameof(message.EditedAt)); - if (message.SentAt == DateTime.MinValue) - throw new ArgumentException("Sent at time cannot be empty", nameof(message.EditedAt)); - } - catch (Exception ex) - { - throw new InvalidObjectException(ex); - } - } - - public bool TryValidate(Message message) - { - try - { - Validate(message); - return true; - } - catch (Exception ex) - { - return false; - } - } -} \ No newline at end of file diff --git a/Govor.Core/Infrastructure/Validators/PrivateChatValidator.cs b/Govor.Core/Infrastructure/Validators/PrivateChatValidator.cs deleted file mode 100644 index 184d442..0000000 --- a/Govor.Core/Infrastructure/Validators/PrivateChatValidator.cs +++ /dev/null @@ -1,38 +0,0 @@ -using Govor.Core.Models; - -namespace Govor.Core.Infrastructure.Validators; - -public class PrivateChatValidator : IObjectValidator -{ - public void Validate(PrivateChat chat) - { - try - { - if(chat is null) - throw new ArgumentNullException(nameof(chat)); - if(chat.Id == Guid.Empty) - throw new ArgumentException("Id cannot be empty", nameof(chat)); - if(chat.UserAId == Guid.Empty) - throw new ArgumentException("UserAId cannot be empty", nameof(chat.UserAId)); - if(chat.UserBId == Guid.Empty) - throw new ArgumentException("UserBId cannot be empty", nameof(chat.UserBId)); - } - catch (Exception ex) - { - throw new InvalidObjectException(ex); - } - } - - public bool TryValidate(PrivateChat chat) - { - try - { - Validate(chat); - return true; - } - catch (Exception ex) - { - return false; - } - } -} \ No newline at end of file diff --git a/Govor.Core/Infrastructure/Validators/UserValidator.cs b/Govor.Core/Infrastructure/Validators/UserValidator.cs deleted file mode 100644 index b849aca..0000000 --- a/Govor.Core/Infrastructure/Validators/UserValidator.cs +++ /dev/null @@ -1,46 +0,0 @@ -using Govor.Core.Models.Users; -using ArgumentNullException = System.ArgumentNullException; - -namespace Govor.Core.Infrastructure.Validators; - -public class UserValidator : IObjectValidator -{ - public const int MIN_LENGHT_OF_NAME = 4; - public const int MAX_LENGHT_OF_NAME = 44; - - public void Validate(User user) - { - try - { - if (user is null) - throw new ArgumentNullException(nameof(user)); - if(user.Id == Guid.Empty) - throw new ArgumentException("User ID cannot be empty", nameof(user.Id)); - if(user.Username is null - || user.Username.Length < MIN_LENGHT_OF_NAME - || user.Username.Length > MAX_LENGHT_OF_NAME) - throw new ArgumentException($"Username cannot be empty or less then {MIN_LENGHT_OF_NAME} chars or more then {MAX_LENGHT_OF_NAME}", nameof(user.Username)); - if(user.PasswordHash is null || user.PasswordHash == string.Empty) - throw new ArgumentException("Password cannot be empty", nameof(user.PasswordHash)); - if(user.CreatedOn == DateOnly.MinValue) - throw new ArgumentException("Time of creation account cannot be empty", nameof(user.CreatedOn)); - } - catch(Exception ex) - { - throw new InvalidObjectException(ex); - } - } - - public bool TryValidate(User objectToValidate) - { - try - { - Validate(objectToValidate); - return true; - } - catch (InvalidObjectException ex) - { - return false; - } - } -} \ No newline at end of file diff --git a/Govor.Core/Repositories/Admins/IAdminsExist.cs b/Govor.Core/Repositories/Admins/IAdminsExist.cs deleted file mode 100644 index c04e928..0000000 --- a/Govor.Core/Repositories/Admins/IAdminsExist.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Govor.Core.Models.Users; - -namespace Govor.Core.Repositories.Admins; - -public interface IAdminsExist -{ - bool Exist(Guid guid); - bool Exist(Admin admin); -} \ No newline at end of file diff --git a/Govor.Core/Repositories/Admins/IAdminsReader.cs b/Govor.Core/Repositories/Admins/IAdminsReader.cs deleted file mode 100644 index ca550a8..0000000 --- a/Govor.Core/Repositories/Admins/IAdminsReader.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Govor.Core.Models.Users; - -namespace Govor.Core.Repositories.Admins; - -public interface IAdminsReader -{ - Task> GetAllAsync(); - Task GetByIdAsync(Guid id); -} \ No newline at end of file diff --git a/Govor.Core/Repositories/Admins/IAdminsRepository.cs b/Govor.Core/Repositories/Admins/IAdminsRepository.cs deleted file mode 100644 index 09e9962..0000000 --- a/Govor.Core/Repositories/Admins/IAdminsRepository.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Govor.Core.Repositories.Admins; - -public interface IAdminsRepository : IAdminsReader, IAdminsWriter, IAdminsExist -{ - -} \ No newline at end of file diff --git a/Govor.Core/Repositories/Admins/IAdminsWriter.cs b/Govor.Core/Repositories/Admins/IAdminsWriter.cs deleted file mode 100644 index 60cbe2a..0000000 --- a/Govor.Core/Repositories/Admins/IAdminsWriter.cs +++ /dev/null @@ -1,10 +0,0 @@ -using Govor.Core.Models.Users; - -namespace Govor.Core.Repositories.Admins; - -public interface IAdminsWriter -{ - Task AddAsync(Admin admin); - Task UpdateAsync(Admin admin); - Task RemoveAsync(Guid admin); -} \ No newline at end of file diff --git a/Govor.Core/Repositories/Friendships/IFriendshipsExist.cs b/Govor.Core/Repositories/Friendships/IFriendshipsExist.cs deleted file mode 100644 index 5475414..0000000 --- a/Govor.Core/Repositories/Friendships/IFriendshipsExist.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Govor.Core.Repositories.Friendships; - -public interface IFriendshipsExist -{ - bool Exist(Guid requesterId, Guid addresseeId); - bool IsPossibilityOfCreatingFriendship(Guid requesterId, Guid addresseeId); -} \ No newline at end of file diff --git a/Govor.Core/Repositories/Friendships/IFriendshipsReader.cs b/Govor.Core/Repositories/Friendships/IFriendshipsReader.cs deleted file mode 100644 index cee9027..0000000 --- a/Govor.Core/Repositories/Friendships/IFriendshipsReader.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Govor.Core.Models; - -namespace Govor.Core.Repositories.Friendships; - -public interface IFriendshipsReader -{ - Task> GetAllAsync(); - Task GetByIdAsync(Guid id); - Task GetFriendshipAsync(Guid fromUserId, Guid toUserId); - Task> FindByUserIdAsync(Guid userId); -} \ No newline at end of file diff --git a/Govor.Core/Repositories/Friendships/IFriendshipsRepository.cs b/Govor.Core/Repositories/Friendships/IFriendshipsRepository.cs deleted file mode 100644 index b88e805..0000000 --- a/Govor.Core/Repositories/Friendships/IFriendshipsRepository.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Govor.Core.Repositories.Friendships; - -public interface IFriendshipsRepository : IFriendshipsReader, IFriendshipsWriter, IFriendshipsExist -{ - -} \ No newline at end of file diff --git a/Govor.Core/Repositories/Friendships/IFriendshipsWriter.cs b/Govor.Core/Repositories/Friendships/IFriendshipsWriter.cs deleted file mode 100644 index 2b1cfa4..0000000 --- a/Govor.Core/Repositories/Friendships/IFriendshipsWriter.cs +++ /dev/null @@ -1,10 +0,0 @@ -using Govor.Core.Models; - -namespace Govor.Core.Repositories.Friendships; - -public interface IFriendshipsWriter -{ - Task AddAsync(Friendship friendship); - Task UpdateAsync(Friendship friendship); - Task RemoveAsync(Friendship friendship); -} \ No newline at end of file diff --git a/Govor.Core/Repositories/Groups/IGroupMessagesReader.cs b/Govor.Core/Repositories/Groups/IGroupMessagesReader.cs deleted file mode 100644 index d53b8ce..0000000 --- a/Govor.Core/Repositories/Groups/IGroupMessagesReader.cs +++ /dev/null @@ -1,8 +0,0 @@ -using Govor.Core.Models.Messages; - -namespace Govor.Core.Repositories.Groups; - -public interface IGroupMessagesReader -{ - public Task> GetMessages(Guid chatId, Guid? startMessageId, int pageSize = 20, RecipientType type = RecipientType.User); -} \ No newline at end of file diff --git a/Govor.Core/Repositories/Groups/IGroupsExist.cs b/Govor.Core/Repositories/Groups/IGroupsExist.cs deleted file mode 100644 index f6b763f..0000000 --- a/Govor.Core/Repositories/Groups/IGroupsExist.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Govor.Core.Models; - -namespace Govor.Core.Repositories.Groups; - -public interface IGroupsExist -{ - public bool Exist(Guid groupId); - public bool Exist(ChatGroup chatGroup); -} \ No newline at end of file diff --git a/Govor.Core/Repositories/Groups/IGroupsReader.cs b/Govor.Core/Repositories/Groups/IGroupsReader.cs deleted file mode 100644 index 26829d0..0000000 --- a/Govor.Core/Repositories/Groups/IGroupsReader.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Govor.Core.Models; - -namespace Govor.Core.Repositories.Groups; - -public interface IGroupsReader -{ - public Task> GetAllAsync(); - public Task GetByIdAsync(Guid id); - public Task> SearchByNameAsync(string name); - public Task> GetByAdminIdAsync(Guid userId); - public Task> GetByUserIdAsync(Guid userId); - public Task IsUserMemberOfGroupAsync(Guid userId, Guid groupId); -} \ No newline at end of file diff --git a/Govor.Core/Repositories/Groups/IGroupsRepository.cs b/Govor.Core/Repositories/Groups/IGroupsRepository.cs deleted file mode 100644 index 9b2faa7..0000000 --- a/Govor.Core/Repositories/Groups/IGroupsRepository.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Govor.Core.Repositories.Groups; - -public interface IGroupsRepository : IGroupsReader, IGroupsWriter, IGroupsExist -{ - -} \ No newline at end of file diff --git a/Govor.Core/Repositories/Groups/IGroupsWriter.cs b/Govor.Core/Repositories/Groups/IGroupsWriter.cs deleted file mode 100644 index 4cc38f4..0000000 --- a/Govor.Core/Repositories/Groups/IGroupsWriter.cs +++ /dev/null @@ -1,10 +0,0 @@ -using Govor.Core.Models; - -namespace Govor.Core.Repositories.Groups; - -public interface IGroupsWriter -{ - Task AddAsync(ChatGroup group); - Task UpdateAsync(ChatGroup group); - Task RemoveAsync(Guid groupId); -} \ No newline at end of file diff --git a/Govor.Core/Repositories/Invaites/IInvitesExist.cs b/Govor.Core/Repositories/Invaites/IInvitesExist.cs deleted file mode 100644 index e763d28..0000000 --- a/Govor.Core/Repositories/Invaites/IInvitesExist.cs +++ /dev/null @@ -1,10 +0,0 @@ -using Govor.Core.Models; - -namespace Govor.Core.Repositories.Invaites; - -public interface IInvitesExist -{ - bool Exist(Invitation invitation); - bool Exist(string code); - bool Exist(Guid guid); -} \ No newline at end of file diff --git a/Govor.Core/Repositories/Invaites/IInvitesReader.cs b/Govor.Core/Repositories/Invaites/IInvitesReader.cs deleted file mode 100644 index 85cb34d..0000000 --- a/Govor.Core/Repositories/Invaites/IInvitesReader.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Govor.Core.Models; - -namespace Govor.Core.Repositories.Invaites; - -public interface IInvitesReader -{ - Task> GetAllAsync(); - Task FindByIdAsync(Guid id); - Task FindByCodeAsync(string code); - Task> FindAdminsInvitesAsync(); -} \ No newline at end of file diff --git a/Govor.Core/Repositories/Invaites/IInvitesRepository.cs b/Govor.Core/Repositories/Invaites/IInvitesRepository.cs deleted file mode 100644 index 832517c..0000000 --- a/Govor.Core/Repositories/Invaites/IInvitesRepository.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Govor.Core.Repositories.Invaites; - -public interface IInvitesRepository : IInvitesReader, IInvitesWriter, IInvitesExist -{ - -} \ No newline at end of file diff --git a/Govor.Core/Repositories/Invaites/IInvitesWriter.cs b/Govor.Core/Repositories/Invaites/IInvitesWriter.cs deleted file mode 100644 index b8f7487..0000000 --- a/Govor.Core/Repositories/Invaites/IInvitesWriter.cs +++ /dev/null @@ -1,10 +0,0 @@ -using Govor.Core.Models; - -namespace Govor.Core.Repositories.Invaites; - -public interface IInvitesWriter -{ - Task AddAsync(Invitation invitation); - Task UpdateAsync(Invitation invitation); - Task RemoveAsync(Invitation invitation); -} \ No newline at end of file diff --git a/Govor.Core/Repositories/MediasAttachments/IMediaAttachmentsExist.cs b/Govor.Core/Repositories/MediasAttachments/IMediaAttachmentsExist.cs deleted file mode 100644 index 89ab2d7..0000000 --- a/Govor.Core/Repositories/MediasAttachments/IMediaAttachmentsExist.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Govor.Core.Models.Messages; - -namespace Govor.Core.Repositories.MediasAttachments; - -public interface IMediaAttachmentsExist -{ - bool Exist(Guid id); - bool Exist(MediaAttachments attachments); -} \ No newline at end of file diff --git a/Govor.Core/Repositories/MediasAttachments/IMediaAttachmentsReader.cs b/Govor.Core/Repositories/MediasAttachments/IMediaAttachmentsReader.cs deleted file mode 100644 index cb54728..0000000 --- a/Govor.Core/Repositories/MediasAttachments/IMediaAttachmentsReader.cs +++ /dev/null @@ -1,10 +0,0 @@ -using Govor.Core.Models.Messages; - -namespace Govor.Core.Repositories.MediasAttachments; - -public interface IMediaAttachmentsReader -{ - Task> GetAllAsync(); - Task FindByIdAsync(Guid id); - Task> GetAllByMessageId(Guid messageId); -} \ No newline at end of file diff --git a/Govor.Core/Repositories/MediasAttachments/IMediaAttachmentsRepository.cs b/Govor.Core/Repositories/MediasAttachments/IMediaAttachmentsRepository.cs deleted file mode 100644 index 457e84d..0000000 --- a/Govor.Core/Repositories/MediasAttachments/IMediaAttachmentsRepository.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Govor.Core.Repositories.MediasAttachments; - -public interface IMediaAttachmentsRepository : IMediaAttachmentsReader, IMediaAttachmentsWriter, IMediaAttachmentsExist -{ - -} \ No newline at end of file diff --git a/Govor.Core/Repositories/MediasAttachments/IMediaAttachmentsWriter.cs b/Govor.Core/Repositories/MediasAttachments/IMediaAttachmentsWriter.cs deleted file mode 100644 index 5754a3f..0000000 --- a/Govor.Core/Repositories/MediasAttachments/IMediaAttachmentsWriter.cs +++ /dev/null @@ -1,10 +0,0 @@ -using Govor.Core.Models.Messages; - -namespace Govor.Core.Repositories.MediasAttachments; - -public interface IMediaAttachmentsWriter -{ - Task AddAsync(MediaAttachments mediaAttachments); - Task UpdateAsync(MediaAttachments attachments); - Task RemoveAsync(Guid Id); -} \ No newline at end of file diff --git a/Govor.Core/Repositories/Messages/IMessagesExist.cs b/Govor.Core/Repositories/Messages/IMessagesExist.cs deleted file mode 100644 index 6d6deb6..0000000 --- a/Govor.Core/Repositories/Messages/IMessagesExist.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Govor.Core.Models.Messages; - -namespace Govor.Core.Repositories.Messages; - -public interface IMessagesExist -{ - bool Exist(Guid messageId); - bool Exist(Message message); -} \ No newline at end of file diff --git a/Govor.Core/Repositories/Messages/IMessagesReader.cs b/Govor.Core/Repositories/Messages/IMessagesReader.cs deleted file mode 100644 index 5ca6afc..0000000 --- a/Govor.Core/Repositories/Messages/IMessagesReader.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Govor.Core.Models.Messages; - -namespace Govor.Core.Repositories.Messages; - -public interface IMessagesReader -{ - Task> GetAllAsync(); - Task FindByIdAsync(Guid messageId); - Task> FindBySenderIdAsync(Guid senderId); - Task> FindByReceiverIdAsync(Guid receiverId); - Task> FindBySenderAndReceiverIdAsync(Guid senderId, Guid receiverId, RecipientType recipientType = RecipientType.User); - Task> FindBySentAtAsync(DateTime date); -} \ No newline at end of file diff --git a/Govor.Core/Repositories/Messages/IMessagesRepository.cs b/Govor.Core/Repositories/Messages/IMessagesRepository.cs deleted file mode 100644 index 86867e9..0000000 --- a/Govor.Core/Repositories/Messages/IMessagesRepository.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Govor.Core.Repositories.Messages; - -public interface IMessagesRepository : IMessagesReader, IMessagesWriter, IMessagesExist -{ - -} \ No newline at end of file diff --git a/Govor.Core/Repositories/Messages/IMessagesWriter.cs b/Govor.Core/Repositories/Messages/IMessagesWriter.cs deleted file mode 100644 index f9f7b81..0000000 --- a/Govor.Core/Repositories/Messages/IMessagesWriter.cs +++ /dev/null @@ -1,10 +0,0 @@ -using Govor.Core.Models.Messages; - -namespace Govor.Core.Repositories.Messages; - -public interface IMessagesWriter -{ - Task AddAsync(Message message); - Task UpdateAsync(Message message); - Task RemoveAsync(Guid messageId); -} \ No newline at end of file diff --git a/Govor.Core/Repositories/PrivateChats/IPrivateChatsExist.cs b/Govor.Core/Repositories/PrivateChats/IPrivateChatsExist.cs deleted file mode 100644 index af72f01..0000000 --- a/Govor.Core/Repositories/PrivateChats/IPrivateChatsExist.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Govor.Core.Repositories.PrivateChats; - -public interface IPrivateChatsExist -{ - bool Exist(Guid chatId); - bool Exist(Guid userAId, Guid userBId); -} \ No newline at end of file diff --git a/Govor.Core/Repositories/PrivateChats/IPrivateChatsReader.cs b/Govor.Core/Repositories/PrivateChats/IPrivateChatsReader.cs deleted file mode 100644 index 0327dad..0000000 --- a/Govor.Core/Repositories/PrivateChats/IPrivateChatsReader.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Govor.Core.Models; - -namespace Govor.Core.Repositories.PrivateChats; - -public interface IPrivateChatsReader -{ - Task> GetAllAsync(); - Task GetByIdAsync(Guid id); - Task GetByMembersAsync(Guid memberAId, Guid memberBId); - Task> GetAllOfUser(Guid userId); -} \ No newline at end of file diff --git a/Govor.Core/Repositories/PrivateChats/IPrivateChatsRepository.cs b/Govor.Core/Repositories/PrivateChats/IPrivateChatsRepository.cs deleted file mode 100644 index 7a9829c..0000000 --- a/Govor.Core/Repositories/PrivateChats/IPrivateChatsRepository.cs +++ /dev/null @@ -1,8 +0,0 @@ -using Govor.Core.Repositories.Groups; - -namespace Govor.Core.Repositories.PrivateChats; - -public interface IPrivateChatsRepository : IPrivateChatsReader, IPrivateChatsWriter, IPrivateChatsExist -{ - -} \ No newline at end of file diff --git a/Govor.Core/Repositories/PrivateChats/IPrivateChatsWriter.cs b/Govor.Core/Repositories/PrivateChats/IPrivateChatsWriter.cs deleted file mode 100644 index d2afa33..0000000 --- a/Govor.Core/Repositories/PrivateChats/IPrivateChatsWriter.cs +++ /dev/null @@ -1,10 +0,0 @@ -using Govor.Core.Models; - -namespace Govor.Core.Repositories.PrivateChats; - -public interface IPrivateChatsWriter -{ - Task AddAsync(PrivateChat chat); - Task UpdateAsync(PrivateChat chat); - Task RemoveAsync(Guid chatId); -} \ No newline at end of file diff --git a/Govor.Core/Repositories/PushTokens/IPushTokenReader.cs b/Govor.Core/Repositories/PushTokens/IPushTokenReader.cs deleted file mode 100644 index 17ee1f2..0000000 --- a/Govor.Core/Repositories/PushTokens/IPushTokenReader.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Govor.Core.Repositories.PushTokens; - -public interface IPushTokenReader -{ - Task> GetActiveTokensAsync(Guid userId); - - Task> GetActiveTokensUsersAsync(IEnumerable userIds); - - Task GetActiveTokenBySessionAsync(Guid sessionId); -} \ No newline at end of file diff --git a/Govor.Core/Repositories/PushTokens/IPushTokenRepository.cs b/Govor.Core/Repositories/PushTokens/IPushTokenRepository.cs deleted file mode 100644 index 9f2a841..0000000 --- a/Govor.Core/Repositories/PushTokens/IPushTokenRepository.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Govor.Core.Repositories.PushTokens; - -public interface IPushTokenRepository : IPushTokenReader, IPushTokenWriter -{ - -} \ No newline at end of file diff --git a/Govor.Core/Repositories/PushTokens/IPushTokenWriter.cs b/Govor.Core/Repositories/PushTokens/IPushTokenWriter.cs deleted file mode 100644 index 6847af9..0000000 --- a/Govor.Core/Repositories/PushTokens/IPushTokenWriter.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace Govor.Core.Repositories.PushTokens; - -public interface IPushTokenWriter -{ - Task AddOrUpdateTokenAsync(Guid userId, Guid? sessionId, string token, - string platform, string provider = "FCM"); - - Task RemoveTokensAsync(IEnumerable tokens); - - Task DeactivateTokenBySessionAsync(Guid sessionId); // logout -} \ No newline at end of file diff --git a/Govor.Core/Repositories/UserSessionsRepository/IUserSessionsExist.cs b/Govor.Core/Repositories/UserSessionsRepository/IUserSessionsExist.cs deleted file mode 100644 index 1655ee5..0000000 --- a/Govor.Core/Repositories/UserSessionsRepository/IUserSessionsExist.cs +++ /dev/null @@ -1,10 +0,0 @@ -using Govor.Core.Models.Users; - -namespace Govor.Core.Repositories.UserSessionsRepository; - -public interface IUserSessionsExist -{ - public bool Exist(Guid sessionId); - public bool Exist(string hashedToken); - public bool Exist(UserSession userSession); -} \ No newline at end of file diff --git a/Govor.Core/Repositories/UserSessionsRepository/IUserSessionsReader.cs b/Govor.Core/Repositories/UserSessionsRepository/IUserSessionsReader.cs deleted file mode 100644 index 851569c..0000000 --- a/Govor.Core/Repositories/UserSessionsRepository/IUserSessionsReader.cs +++ /dev/null @@ -1,14 +0,0 @@ -using Govor.Core.Models.Users; - -namespace Govor.Core.Repositories.UserSessionsRepository; - -public interface IUserSessionsReader -{ - public Task> GetAllAsync(); - public Task GetByIdAsync(Guid sessionId); - public Task> GetByUserIdAsync(Guid userId); - public Task> GetByCreatedAtAsync(DateTime createdAt); - public Task> GetByExpiresAtAsync(DateTime createdAt); - public Task> GetByRevokedAsync(bool isRevoked); - public Task GetByHashedRefreshTokenAsync(string hash); -} \ No newline at end of file diff --git a/Govor.Core/Repositories/UserSessionsRepository/IUserSessionsRepository.cs b/Govor.Core/Repositories/UserSessionsRepository/IUserSessionsRepository.cs deleted file mode 100644 index 35061b7..0000000 --- a/Govor.Core/Repositories/UserSessionsRepository/IUserSessionsRepository.cs +++ /dev/null @@ -1,8 +0,0 @@ -using Govor.Core.Models; - -namespace Govor.Core.Repositories.UserSessionsRepository; - -public interface IUserSessionsRepository : IUserSessionsReader, IUserSessionsWriter, IUserSessionsExist -{ - -} \ No newline at end of file diff --git a/Govor.Core/Repositories/UserSessionsRepository/IUserSessionsWriter.cs b/Govor.Core/Repositories/UserSessionsRepository/IUserSessionsWriter.cs deleted file mode 100644 index 4f7eeac..0000000 --- a/Govor.Core/Repositories/UserSessionsRepository/IUserSessionsWriter.cs +++ /dev/null @@ -1,12 +0,0 @@ -using Govor.Core.Models; -using Govor.Core.Models.Users; - -namespace Govor.Core.Repositories.UserSessionsRepository; - -public interface IUserSessionsWriter -{ - Task AddAsync(UserSession userSession); - Task UpdateAsync(UserSession userSession); - Task RemoveAsync(Guid sessionId); - Task RemoveByUserIdAsync(Guid userId); -} \ No newline at end of file diff --git a/Govor.Core/Repositories/Users/IUsersExist.cs b/Govor.Core/Repositories/Users/IUsersExist.cs deleted file mode 100644 index a06a180..0000000 --- a/Govor.Core/Repositories/Users/IUsersExist.cs +++ /dev/null @@ -1,10 +0,0 @@ -using Govor.Core.Models.Users; - -namespace Govor.Core.Repositories.Users; - -public interface IUsersExist -{ - public Task ExistsAsync(User user); - public Task ExistsByIdAsync(Guid id); - public Task ExistsUsernameAsync(string username); -} \ No newline at end of file diff --git a/Govor.Core/Repositories/Users/IUsersReader.cs b/Govor.Core/Repositories/Users/IUsersReader.cs deleted file mode 100644 index 53c4a32..0000000 --- a/Govor.Core/Repositories/Users/IUsersReader.cs +++ /dev/null @@ -1,14 +0,0 @@ -using Govor.Core.Models.Users; - -namespace Govor.Core.Repositories.Users; - -public interface IUsersReader -{ - public Task> GetAllAsync(); - public Task FindByIdAsync(Guid id); - public Task> FindByRangeIdAsync(IEnumerable ids); - public Task FindByUsernameAsync(string username); - public Task> FindByRangeUsernamesAsync(IEnumerable usernames); - public Task> SearchPotentialFriendsAsync(Guid currentUserId, string query); - public Task> FindUsersByCreatedDateAsync(DateOnly createdDate); -} \ No newline at end of file diff --git a/Govor.Core/Repositories/Users/IUsersRepository.cs b/Govor.Core/Repositories/Users/IUsersRepository.cs deleted file mode 100644 index 8609807..0000000 --- a/Govor.Core/Repositories/Users/IUsersRepository.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Govor.Core.Repositories.Users; - -public interface IUsersRepository : IUsersReader, IUsersWriter, IUsersExist -{ - -} \ No newline at end of file diff --git a/Govor.Core/Repositories/Users/IUsersWriter.cs b/Govor.Core/Repositories/Users/IUsersWriter.cs deleted file mode 100644 index d05c8cf..0000000 --- a/Govor.Core/Repositories/Users/IUsersWriter.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Govor.Core.Models.Users; - -namespace Govor.Core.Repositories.Users; - -public interface IUsersWriter -{ - public Task AddAsync(User user); - public Task UpdateAsync(User user); - public Task RemoveAsync(User user); - public Task RemoveAsync(Guid userId); -} \ No newline at end of file diff --git a/Govor.Data.Tests/Govor.Data.Tests.csproj b/Govor.Data.Tests/Govor.Data.Tests.csproj index 8ad7ddc..c7e42eb 100644 --- a/Govor.Data.Tests/Govor.Data.Tests.csproj +++ b/Govor.Data.Tests/Govor.Data.Tests.csproj @@ -23,8 +23,4 @@ - - - - diff --git a/Govor.Data.Tests/Repositories/AdminsRepositoryTests.cs b/Govor.Data.Tests/Repositories/AdminsRepositoryTests.cs index 5e95ea6..1730862 100644 --- a/Govor.Data.Tests/Repositories/AdminsRepositoryTests.cs +++ b/Govor.Data.Tests/Repositories/AdminsRepositoryTests.cs @@ -1,13 +1,13 @@ using AutoFixture; -using Govor.Core.Infrastructure.Validators; -using Govor.Core.Models; -using Govor.Core.Models.Users; -using Govor.Data; -using Govor.Data.Repositories; -using Govor.Data.Repositories.Exceptions; +using Govor.Domain.Infrastructure.Validators; +using Govor.Domain.Models; +using Govor.Domain.Models.Users; +using Govor.Domain; +using Govor.Domain.Repositories; +using Govor.Domain.Repositories.Exceptions; using Microsoft.EntityFrameworkCore; -namespace Govor.Data.Tests.Repositories; +namespace Govor.Domain.Tests.Repositories; [TestFixture] public class AdminsRepositoryTests diff --git a/Govor.Data.Tests/Repositories/FriendshipsRepositoryTests.cs b/Govor.Data.Tests/Repositories/FriendshipsRepositoryTests.cs index 8b0a905..d7d00f8 100644 --- a/Govor.Data.Tests/Repositories/FriendshipsRepositoryTests.cs +++ b/Govor.Data.Tests/Repositories/FriendshipsRepositoryTests.cs @@ -1,12 +1,12 @@ using AutoFixture; -using Govor.Core.Infrastructure.Validators; -using Govor.Core.Models; -using Govor.Data; -using Govor.Data.Repositories; -using Govor.Data.Repositories.Exceptions; +using Govor.Domain.Infrastructure.Validators; +using Govor.Domain.Models; +using Govor.Domain; +using Govor.Domain.Repositories; +using Govor.Domain.Repositories.Exceptions; using Microsoft.EntityFrameworkCore; -namespace Govor.Data.Tests.Repositories; +namespace Govor.Domain.Tests.Repositories; [TestFixture] public class FriendshipsRepositoryTests diff --git a/Govor.Data.Tests/Repositories/GroupRepositoryTests.cs b/Govor.Data.Tests/Repositories/GroupRepositoryTests.cs index 35fb5d3..46def33 100644 --- a/Govor.Data.Tests/Repositories/GroupRepositoryTests.cs +++ b/Govor.Data.Tests/Repositories/GroupRepositoryTests.cs @@ -1,12 +1,12 @@ using AutoFixture; -using Govor.Core.Infrastructure.Validators; -using Govor.Core.Models; -using Govor.Data; -using Govor.Data.Repositories; -using Govor.Data.Repositories.Exceptions; +using Govor.Domain.Infrastructure.Validators; +using Govor.Domain.Models; +using Govor.Domain; +using Govor.Domain.Repositories; +using Govor.Domain.Repositories.Exceptions; using Microsoft.EntityFrameworkCore; -namespace Govor.Data.Tests.Repositories; +namespace Govor.Domain.Tests.Repositories; [TestFixture] public class GroupRepositoryTests diff --git a/Govor.Data.Tests/Repositories/InvitesRepositoryTests.cs b/Govor.Data.Tests/Repositories/InvitesRepositoryTests.cs index 413d23f..9ef01af 100644 --- a/Govor.Data.Tests/Repositories/InvitesRepositoryTests.cs +++ b/Govor.Data.Tests/Repositories/InvitesRepositoryTests.cs @@ -1,12 +1,12 @@ using AutoFixture; -using Govor.Core.Infrastructure.Validators; -using Govor.Core.Models; -using Govor.Data; -using Govor.Data.Repositories; -using Govor.Data.Repositories.Exceptions; +using Govor.Domain.Infrastructure.Validators; +using Govor.Domain.Models; +using Govor.Domain; +using Govor.Domain.Repositories; +using Govor.Domain.Repositories.Exceptions; using Microsoft.EntityFrameworkCore; -namespace Govor.Data.Tests.Repositories; +namespace Govor.Domain.Tests.Repositories; [TestFixture] public class InvitesRepositoryTests diff --git a/Govor.Data.Tests/Repositories/MediaAttachmentsTests.cs b/Govor.Data.Tests/Repositories/MediaAttachmentsTests.cs index 232b62c..c99629e 100644 --- a/Govor.Data.Tests/Repositories/MediaAttachmentsTests.cs +++ b/Govor.Data.Tests/Repositories/MediaAttachmentsTests.cs @@ -1,13 +1,13 @@ using AutoFixture; -using Govor.Core.Infrastructure.Validators; -using Govor.Core.Models; -using Govor.Core.Models.Messages; -using Govor.Data; -using Govor.Data.Repositories; -using Govor.Data.Repositories.Exceptions; +using Govor.Domain.Infrastructure.Validators; +using Govor.Domain.Models; +using Govor.Domain.Models.Messages; +using Govor.Domain; +using Govor.Domain.Repositories; +using Govor.Domain.Repositories.Exceptions; using Microsoft.EntityFrameworkCore; -namespace Govor.Data.Tests.Repositories; +namespace Govor.Domain.Tests.Repositories; [TestFixture] public class MediaAttachmentsTests diff --git a/Govor.Data.Tests/Repositories/MessagesRepositoryTests.cs b/Govor.Data.Tests/Repositories/MessagesRepositoryTests.cs index 7c4a144..8b0c0fe 100644 --- a/Govor.Data.Tests/Repositories/MessagesRepositoryTests.cs +++ b/Govor.Data.Tests/Repositories/MessagesRepositoryTests.cs @@ -1,13 +1,13 @@ using AutoFixture; -using Govor.Core.Infrastructure.Validators; -using Govor.Core.Models; -using Govor.Core.Models.Messages; -using Govor.Data; -using Govor.Data.Repositories; -using Govor.Data.Repositories.Exceptions; +using Govor.Domain.Infrastructure.Validators; +using Govor.Domain.Models; +using Govor.Domain.Models.Messages; +using Govor.Domain; +using Govor.Domain.Repositories; +using Govor.Domain.Repositories.Exceptions; using Microsoft.EntityFrameworkCore; -namespace Govor.Data.Tests.Repositories; +namespace Govor.Domain.Tests.Repositories; [TestFixture] public class MessagesRepositoryTests diff --git a/Govor.Data.Tests/Repositories/PrivateChatsRepositoryTests.cs b/Govor.Data.Tests/Repositories/PrivateChatsRepositoryTests.cs index 15d6b07..657232d 100644 --- a/Govor.Data.Tests/Repositories/PrivateChatsRepositoryTests.cs +++ b/Govor.Data.Tests/Repositories/PrivateChatsRepositoryTests.cs @@ -1,12 +1,12 @@ using AutoFixture; -using Govor.Core.Infrastructure.Validators; -using Govor.Core.Models; -using Govor.Data; -using Govor.Data.Repositories; -using Govor.Data.Repositories.Exceptions; +using Govor.Domain.Infrastructure.Validators; +using Govor.Domain.Models; +using Govor.Domain; +using Govor.Domain.Repositories; +using Govor.Domain.Repositories.Exceptions; using Microsoft.EntityFrameworkCore; -namespace Govor.Data.Tests.Repositories; +namespace Govor.Domain.Tests.Repositories; [TestFixture] public class PrivateChatsRepositoryTests diff --git a/Govor.Data.Tests/Repositories/PushTokenRepository.cs b/Govor.Data.Tests/Repositories/PushTokenRepository.cs index 258f092..e590b7b 100644 --- a/Govor.Data.Tests/Repositories/PushTokenRepository.cs +++ b/Govor.Data.Tests/Repositories/PushTokenRepository.cs @@ -1,8 +1,8 @@ -using Govor.Core.Models.Users; -using Govor.Data.Repositories; +using Govor.Domain.Models.Users; +using Govor.Domain.Repositories; using Microsoft.EntityFrameworkCore; -namespace Govor.Data.Tests.Repositories; +namespace Govor.Domain.Tests.Repositories; [TestFixture] public class PushTokenRepositoryTests diff --git a/Govor.Data.Tests/Repositories/UserSessionsRepositoryTests.cs b/Govor.Data.Tests/Repositories/UserSessionsRepositoryTests.cs index 234e21b..4006783 100644 --- a/Govor.Data.Tests/Repositories/UserSessionsRepositoryTests.cs +++ b/Govor.Data.Tests/Repositories/UserSessionsRepositoryTests.cs @@ -1,11 +1,11 @@ using AutoFixture; -using Govor.Core.Models; -using Govor.Core.Models.Users; -using Govor.Data.Repositories; -using Govor.Data.Repositories.Exceptions; +using Govor.Domain.Models; +using Govor.Domain.Models.Users; +using Govor.Domain.Repositories; +using Govor.Domain.Repositories.Exceptions; using Microsoft.EntityFrameworkCore; -namespace Govor.Data.Tests.Repositories; +namespace Govor.Domain.Tests.Repositories; [TestFixture] public class UserSessionsRepositoryTests diff --git a/Govor.Data.Tests/Repositories/UsersRepositoryTests.cs b/Govor.Data.Tests/Repositories/UsersRepositoryTests.cs index 8a37d46..65d0910 100644 --- a/Govor.Data.Tests/Repositories/UsersRepositoryTests.cs +++ b/Govor.Data.Tests/Repositories/UsersRepositoryTests.cs @@ -1,13 +1,13 @@ using AutoFixture; -using Govor.Core.Infrastructure.Validators; -using Govor.Core.Models; -using Govor.Core.Models.Users; -using Govor.Data; -using Govor.Data.Repositories; -using Govor.Data.Repositories.Exceptions; +using Govor.Domain.Infrastructure.Validators; +using Govor.Domain.Models; +using Govor.Domain.Models.Users; +using Govor.Domain; +using Govor.Domain.Repositories; +using Govor.Domain.Repositories.Exceptions; using Microsoft.EntityFrameworkCore; -namespace Govor.Data.Tests.Repositories; +namespace Govor.Domain.Tests.Repositories; [TestFixture] public class UsersRepositoryTests diff --git a/Govor.Data/Migrations/20260301080331_Init.Designer.cs b/Govor.Data/Migrations/20260301080331_Init.Designer.cs deleted file mode 100644 index ec91fae..0000000 --- a/Govor.Data/Migrations/20260301080331_Init.Designer.cs +++ /dev/null @@ -1,848 +0,0 @@ -// -using System; -using Govor.Data; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; - -#nullable disable - -namespace Govor.Data.Migrations -{ - [DbContext(typeof(GovorDbContext))] - [Migration("20260301080331_Init")] - partial class Init - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "8.0.6") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("Govor.Core.Models.ChatGroup", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("Description") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("character varying(500)"); - - b.Property("ImageId") - .HasColumnType("uuid"); - - b.Property("IsChannel") - .HasColumnType("boolean"); - - b.Property("IsPrivate") - .HasColumnType("boolean"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)"); - - b.HasKey("Id"); - - b.ToTable("ChatGroups"); - }); - - modelBuilder.Entity("Govor.Core.Models.Friendship", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("AddresseeId") - .HasColumnType("uuid"); - - b.Property("RequesterId") - .HasColumnType("uuid"); - - b.Property("Status") - .HasColumnType("integer"); - - b.HasKey("Id"); - - b.HasIndex("AddresseeId"); - - b.HasIndex("Id") - .IsUnique(); - - b.HasIndex("RequesterId"); - - b.ToTable("Friendships"); - }); - - modelBuilder.Entity("Govor.Core.Models.GroupAdmins", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("GroupId") - .HasColumnType("uuid"); - - b.Property("UserId") - .HasColumnType("uuid"); - - b.HasKey("Id"); - - b.HasIndex("GroupId"); - - b.ToTable("GroupAdmins"); - }); - - modelBuilder.Entity("Govor.Core.Models.GroupInvitation", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("Description") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("character varying(500)"); - - b.Property("EndDate") - .HasColumnType("timestamp with time zone"); - - b.Property("GroupId") - .HasColumnType("uuid"); - - b.Property("InvitationCode") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("character varying(200)"); - - b.Property("MaxParticipants") - .HasColumnType("integer"); - - b.Property("UserMakerId") - .HasColumnType("uuid"); - - b.HasKey("Id"); - - b.HasIndex("GroupId"); - - b.HasIndex("UserMakerId"); - - b.ToTable("GroupInvitations"); - }); - - modelBuilder.Entity("Govor.Core.Models.GroupMembership", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("GroupId") - .HasColumnType("uuid"); - - b.Property("InvitationId") - .HasColumnType("uuid"); - - b.Property("IsBanned") - .HasColumnType("boolean"); - - b.Property("MemberSince") - .HasColumnType("timestamp with time zone"); - - b.Property("UserId") - .HasColumnType("uuid"); - - b.HasKey("Id"); - - b.HasIndex("GroupId"); - - b.HasIndex("InvitationId"); - - b.ToTable("GroupMemberships"); - }); - - modelBuilder.Entity("Govor.Core.Models.Invitation", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("Code") - .IsRequired() - .HasColumnType("text"); - - b.Property("DateCreated") - .HasColumnType("timestamp with time zone"); - - b.Property("Description") - .IsRequired() - .HasColumnType("text"); - - b.Property("EndDate") - .HasColumnType("timestamp with time zone"); - - b.Property("IsActive") - .HasColumnType("boolean"); - - b.Property("IsAdmin") - .HasColumnType("boolean"); - - b.Property("MaxParticipants") - .HasColumnType("integer"); - - b.HasKey("Id"); - - b.ToTable("Invitations"); - }); - - modelBuilder.Entity("Govor.Core.Models.MediaFile", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("DateCreated") - .HasColumnType("timestamp with time zone"); - - b.Property("MediaType") - .IsRequired() - .HasColumnType("text"); - - b.Property("MineType") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)"); - - b.Property("OwnerId") - .HasColumnType("uuid"); - - b.Property("OwnerType") - .HasColumnType("integer"); - - b.Property("UploaderId") - .HasColumnType("uuid"); - - b.Property("Url") - .IsRequired() - .HasColumnType("text"); - - b.HasKey("Id"); - - b.ToTable("MediaFiles"); - }); - - modelBuilder.Entity("Govor.Core.Models.Messages.MediaAttachments", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("MediaFileId") - .HasColumnType("uuid"); - - b.Property("MessageId") - .HasColumnType("uuid"); - - b.HasKey("Id"); - - b.HasIndex("MediaFileId"); - - b.HasIndex("MessageId"); - - b.ToTable("MediaAttachments"); - }); - - modelBuilder.Entity("Govor.Core.Models.Messages.Message", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("ChatGroupId") - .HasColumnType("uuid"); - - b.Property("EditedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("EncryptedContent") - .IsRequired() - .HasColumnType("text"); - - b.Property("IsEdited") - .HasColumnType("boolean"); - - b.Property("PrivateChatId") - .HasColumnType("uuid"); - - b.Property("RecipientId") - .HasColumnType("uuid"); - - b.Property("RecipientType") - .HasColumnType("integer"); - - b.Property("ReplyToMessageId") - .HasColumnType("uuid"); - - b.Property("SenderId") - .HasColumnType("uuid"); - - b.Property("SentAt") - .HasColumnType("timestamp with time zone"); - - b.HasKey("Id"); - - b.HasIndex("ChatGroupId"); - - b.HasIndex("Id") - .IsUnique(); - - b.HasIndex("PrivateChatId"); - - b.HasIndex("RecipientId") - .IsUnique(); - - b.ToTable("Messages"); - }); - - modelBuilder.Entity("Govor.Core.Models.Messages.MessageReaction", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("MessageId") - .HasColumnType("uuid"); - - b.Property("ReactedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("ReactionCode") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)"); - - b.Property("UserId") - .HasColumnType("uuid"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.HasIndex("MessageId", "UserId") - .IsUnique(); - - b.ToTable("MessageReactions"); - }); - - modelBuilder.Entity("Govor.Core.Models.Messages.MessageView", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("MessageId") - .HasColumnType("uuid"); - - b.Property("UserId") - .HasColumnType("uuid"); - - b.Property("ViewedAt") - .HasColumnType("timestamp with time zone"); - - b.HasKey("Id"); - - b.HasIndex("MessageId", "UserId") - .IsUnique(); - - b.ToTable("MessageViews"); - }); - - modelBuilder.Entity("Govor.Core.Models.PrivateChat", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("UserAId") - .HasColumnType("uuid"); - - b.Property("UserBId") - .HasColumnType("uuid"); - - b.HasKey("Id"); - - b.HasIndex("Id") - .IsUnique(); - - b.ToTable("PrivateChats"); - }); - - modelBuilder.Entity("Govor.Core.Models.Users.Admin", b => - { - b.Property("UserId") - .HasColumnType("uuid"); - - b.HasKey("UserId"); - - b.ToTable("Admins"); - }); - - modelBuilder.Entity("Govor.Core.Models.Users.Crypto.OneTimePreKey", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("IsUsed") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(false); - - b.Property("PublicKey") - .IsRequired() - .HasColumnType("bytea"); - - b.Property("UploadedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("UserCryptoSessionId") - .HasColumnType("uuid"); - - b.HasKey("Id"); - - b.HasIndex("UploadedAt"); - - b.HasIndex("UserCryptoSessionId", "IsUsed"); - - b.ToTable("OneTimePreKeys"); - }); - - modelBuilder.Entity("Govor.Core.Models.Users.Crypto.SignedPreKey", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("PublicSignedPreKey") - .IsRequired() - .HasColumnType("bytea"); - - b.Property("SignedPreKeySignature") - .IsRequired() - .HasColumnType("bytea"); - - b.Property("UserCryptoSessionId") - .HasColumnType("uuid"); - - b.HasKey("Id"); - - b.HasIndex("UserCryptoSessionId") - .IsUnique(); - - b.ToTable("SignedPreKeys"); - }); - - modelBuilder.Entity("Govor.Core.Models.Users.Crypto.UserCryptoSession", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("PublicIdentityKey") - .IsRequired() - .HasColumnType("bytea"); - - b.Property("UserSessionId") - .HasColumnType("uuid"); - - b.HasKey("Id"); - - b.HasIndex("UserSessionId") - .IsUnique(); - - b.ToTable("UserCryptoSessions"); - }); - - modelBuilder.Entity("Govor.Core.Models.Users.User", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("CreatedOn") - .HasColumnType("date"); - - b.Property("Description") - .HasMaxLength(500) - .HasColumnType("character varying(500)"); - - b.Property("IconId") - .HasColumnType("uuid"); - - b.Property("InviteId") - .HasColumnType("uuid"); - - b.Property("PasswordHash") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("character varying(50)"); - - b.Property("WasOnline") - .HasColumnType("timestamp with time zone"); - - b.HasKey("Id"); - - b.HasIndex("CreatedOn"); - - b.HasIndex("InviteId"); - - b.HasIndex("Username") - .IsUnique(); - - b.HasIndex("WasOnline"); - - b.ToTable("Users"); - }); - - modelBuilder.Entity("Govor.Core.Models.Users.UserPushToken", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("IsActive") - .HasColumnType("boolean"); - - b.Property("LastUsedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("Platform") - .IsRequired() - .HasColumnType("text"); - - b.Property("Provider") - .IsRequired() - .HasColumnType("text"); - - b.Property("Token") - .IsRequired() - .HasColumnType("text"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("UserId") - .HasColumnType("uuid"); - - b.Property("UserSessionId") - .HasColumnType("uuid"); - - b.HasKey("Id"); - - b.HasIndex("Token") - .IsUnique(); - - b.HasIndex("UserId") - .IsUnique(); - - b.HasIndex("UserSessionId") - .IsUnique(); - - b.HasIndex("UserId", "IsActive"); - - b.ToTable("UserPushTokens"); - }); - - modelBuilder.Entity("Govor.Core.Models.Users.UserSession", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("DeviceInfo") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)"); - - b.Property("ExpiresAt") - .HasColumnType("timestamp with time zone"); - - b.Property("IsRevoked") - .HasColumnType("boolean"); - - b.Property("RefreshTokenHash") - .IsRequired() - .HasColumnType("text"); - - b.Property("UserId") - .HasColumnType("uuid"); - - b.HasKey("Id"); - - b.HasIndex("Id") - .IsUnique(); - - b.HasIndex("RefreshTokenHash") - .IsUnique(); - - b.HasIndex("UserId"); - - b.ToTable("UserSessions"); - }); - - modelBuilder.Entity("Govor.Core.Models.Friendship", b => - { - b.HasOne("Govor.Core.Models.Users.User", "Addressee") - .WithMany("ReceivedFriendRequests") - .HasForeignKey("AddresseeId") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - - b.HasOne("Govor.Core.Models.Users.User", "Requester") - .WithMany("SentFriendRequests") - .HasForeignKey("RequesterId") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - - b.Navigation("Addressee"); - - b.Navigation("Requester"); - }); - - modelBuilder.Entity("Govor.Core.Models.GroupAdmins", b => - { - b.HasOne("Govor.Core.Models.ChatGroup", null) - .WithMany("Admins") - .HasForeignKey("GroupId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Govor.Core.Models.GroupInvitation", b => - { - b.HasOne("Govor.Core.Models.ChatGroup", null) - .WithMany("InviteCodes") - .HasForeignKey("GroupId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Govor.Core.Models.Users.User", "UserMaker") - .WithMany() - .HasForeignKey("UserMakerId") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - - b.Navigation("UserMaker"); - }); - - modelBuilder.Entity("Govor.Core.Models.GroupMembership", b => - { - b.HasOne("Govor.Core.Models.ChatGroup", null) - .WithMany("Members") - .HasForeignKey("GroupId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Govor.Core.Models.GroupInvitation", null) - .WithMany() - .HasForeignKey("InvitationId") - .OnDelete(DeleteBehavior.SetNull); - }); - - modelBuilder.Entity("Govor.Core.Models.Messages.MediaAttachments", b => - { - b.HasOne("Govor.Core.Models.MediaFile", "MediaFile") - .WithMany() - .HasForeignKey("MediaFileId") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - - b.HasOne("Govor.Core.Models.Messages.Message", "Message") - .WithMany("MediaAttachments") - .HasForeignKey("MessageId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("MediaFile"); - - b.Navigation("Message"); - }); - - modelBuilder.Entity("Govor.Core.Models.Messages.Message", b => - { - b.HasOne("Govor.Core.Models.ChatGroup", null) - .WithMany("Messages") - .HasForeignKey("ChatGroupId"); - - b.HasOne("Govor.Core.Models.PrivateChat", null) - .WithMany("Messages") - .HasForeignKey("PrivateChatId"); - }); - - modelBuilder.Entity("Govor.Core.Models.Messages.MessageReaction", b => - { - b.HasOne("Govor.Core.Models.Messages.Message", "Message") - .WithMany("Reactions") - .HasForeignKey("MessageId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Govor.Core.Models.Users.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Message"); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Govor.Core.Models.Messages.MessageView", b => - { - b.HasOne("Govor.Core.Models.Messages.Message", null) - .WithMany("MessageViews") - .HasForeignKey("MessageId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Govor.Core.Models.Users.Admin", b => - { - b.HasOne("Govor.Core.Models.Users.User", "User") - .WithOne() - .HasForeignKey("Govor.Core.Models.Users.Admin", "UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Govor.Core.Models.Users.Crypto.OneTimePreKey", b => - { - b.HasOne("Govor.Core.Models.Users.Crypto.UserCryptoSession", "UserCryptoSession") - .WithMany("OneTimePreKeys") - .HasForeignKey("UserCryptoSessionId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("UserCryptoSession"); - }); - - modelBuilder.Entity("Govor.Core.Models.Users.Crypto.SignedPreKey", b => - { - b.HasOne("Govor.Core.Models.Users.Crypto.UserCryptoSession", "UserCryptoSession") - .WithOne("SignedPreKey") - .HasForeignKey("Govor.Core.Models.Users.Crypto.SignedPreKey", "UserCryptoSessionId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("UserCryptoSession"); - }); - - modelBuilder.Entity("Govor.Core.Models.Users.Crypto.UserCryptoSession", b => - { - b.HasOne("Govor.Core.Models.Users.UserSession", "UserSession") - .WithOne("CryptoSession") - .HasForeignKey("Govor.Core.Models.Users.Crypto.UserCryptoSession", "UserSessionId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("UserSession"); - }); - - modelBuilder.Entity("Govor.Core.Models.Users.User", b => - { - b.HasOne("Govor.Core.Models.Invitation", "Invite") - .WithMany("Users") - .HasForeignKey("InviteId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Invite"); - }); - - modelBuilder.Entity("Govor.Core.Models.Users.UserSession", b => - { - b.HasOne("Govor.Core.Models.Users.User", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Govor.Core.Models.ChatGroup", b => - { - b.Navigation("Admins"); - - b.Navigation("InviteCodes"); - - b.Navigation("Members"); - - b.Navigation("Messages"); - }); - - modelBuilder.Entity("Govor.Core.Models.Invitation", b => - { - b.Navigation("Users"); - }); - - modelBuilder.Entity("Govor.Core.Models.Messages.Message", b => - { - b.Navigation("MediaAttachments"); - - b.Navigation("MessageViews"); - - b.Navigation("Reactions"); - }); - - modelBuilder.Entity("Govor.Core.Models.PrivateChat", b => - { - b.Navigation("Messages"); - }); - - modelBuilder.Entity("Govor.Core.Models.Users.Crypto.UserCryptoSession", b => - { - b.Navigation("OneTimePreKeys"); - - b.Navigation("SignedPreKey") - .IsRequired(); - }); - - modelBuilder.Entity("Govor.Core.Models.Users.User", b => - { - b.Navigation("ReceivedFriendRequests"); - - b.Navigation("SentFriendRequests"); - }); - - modelBuilder.Entity("Govor.Core.Models.Users.UserSession", b => - { - b.Navigation("CryptoSession") - .IsRequired(); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/Govor.Data/Migrations/20260301091506_FixRecipientIndex.Designer.cs b/Govor.Data/Migrations/20260301091506_FixRecipientIndex.Designer.cs deleted file mode 100644 index 9327098..0000000 --- a/Govor.Data/Migrations/20260301091506_FixRecipientIndex.Designer.cs +++ /dev/null @@ -1,838 +0,0 @@ -// -using System; -using Govor.Data; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; - -#nullable disable - -namespace Govor.Data.Migrations -{ - [DbContext(typeof(GovorDbContext))] - [Migration("20260301091506_FixRecipientIndex")] - partial class FixRecipientIndex - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "8.0.6") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("Govor.Core.Models.ChatGroup", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("Description") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("character varying(500)"); - - b.Property("ImageId") - .HasColumnType("uuid"); - - b.Property("IsChannel") - .HasColumnType("boolean"); - - b.Property("IsPrivate") - .HasColumnType("boolean"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)"); - - b.HasKey("Id"); - - b.ToTable("ChatGroups"); - }); - - modelBuilder.Entity("Govor.Core.Models.Friendship", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("AddresseeId") - .HasColumnType("uuid"); - - b.Property("RequesterId") - .HasColumnType("uuid"); - - b.Property("Status") - .HasColumnType("integer"); - - b.HasKey("Id"); - - b.HasIndex("AddresseeId"); - - b.HasIndex("RequesterId"); - - b.ToTable("Friendships"); - }); - - modelBuilder.Entity("Govor.Core.Models.GroupAdmins", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("GroupId") - .HasColumnType("uuid"); - - b.Property("UserId") - .HasColumnType("uuid"); - - b.HasKey("Id"); - - b.HasIndex("GroupId"); - - b.ToTable("GroupAdmins"); - }); - - modelBuilder.Entity("Govor.Core.Models.GroupInvitation", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("Description") - .IsRequired() - .HasMaxLength(500) - .HasColumnType("character varying(500)"); - - b.Property("EndDate") - .HasColumnType("timestamp with time zone"); - - b.Property("GroupId") - .HasColumnType("uuid"); - - b.Property("InvitationCode") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("character varying(200)"); - - b.Property("MaxParticipants") - .HasColumnType("integer"); - - b.Property("UserMakerId") - .HasColumnType("uuid"); - - b.HasKey("Id"); - - b.HasIndex("GroupId"); - - b.HasIndex("UserMakerId"); - - b.ToTable("GroupInvitations"); - }); - - modelBuilder.Entity("Govor.Core.Models.GroupMembership", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("GroupId") - .HasColumnType("uuid"); - - b.Property("InvitationId") - .HasColumnType("uuid"); - - b.Property("IsBanned") - .HasColumnType("boolean"); - - b.Property("MemberSince") - .HasColumnType("timestamp with time zone"); - - b.Property("UserId") - .HasColumnType("uuid"); - - b.HasKey("Id"); - - b.HasIndex("GroupId"); - - b.HasIndex("InvitationId"); - - b.ToTable("GroupMemberships"); - }); - - modelBuilder.Entity("Govor.Core.Models.Invitation", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("Code") - .IsRequired() - .HasColumnType("text"); - - b.Property("DateCreated") - .HasColumnType("timestamp with time zone"); - - b.Property("Description") - .IsRequired() - .HasColumnType("text"); - - b.Property("EndDate") - .HasColumnType("timestamp with time zone"); - - b.Property("IsActive") - .HasColumnType("boolean"); - - b.Property("IsAdmin") - .HasColumnType("boolean"); - - b.Property("MaxParticipants") - .HasColumnType("integer"); - - b.HasKey("Id"); - - b.ToTable("Invitations"); - }); - - modelBuilder.Entity("Govor.Core.Models.MediaFile", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("DateCreated") - .HasColumnType("timestamp with time zone"); - - b.Property("MediaType") - .IsRequired() - .HasColumnType("text"); - - b.Property("MineType") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)"); - - b.Property("OwnerId") - .HasColumnType("uuid"); - - b.Property("OwnerType") - .HasColumnType("integer"); - - b.Property("UploaderId") - .HasColumnType("uuid"); - - b.Property("Url") - .IsRequired() - .HasColumnType("text"); - - b.HasKey("Id"); - - b.ToTable("MediaFiles"); - }); - - modelBuilder.Entity("Govor.Core.Models.Messages.MediaAttachments", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("MediaFileId") - .HasColumnType("uuid"); - - b.Property("MessageId") - .HasColumnType("uuid"); - - b.HasKey("Id"); - - b.HasIndex("MediaFileId"); - - b.HasIndex("MessageId"); - - b.ToTable("MediaAttachments"); - }); - - modelBuilder.Entity("Govor.Core.Models.Messages.Message", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("ChatGroupId") - .HasColumnType("uuid"); - - b.Property("EditedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("EncryptedContent") - .IsRequired() - .HasColumnType("text"); - - b.Property("IsEdited") - .HasColumnType("boolean"); - - b.Property("PrivateChatId") - .HasColumnType("uuid"); - - b.Property("RecipientId") - .HasColumnType("uuid"); - - b.Property("RecipientType") - .HasColumnType("integer"); - - b.Property("ReplyToMessageId") - .HasColumnType("uuid"); - - b.Property("SenderId") - .HasColumnType("uuid"); - - b.Property("SentAt") - .HasColumnType("timestamp with time zone"); - - b.HasKey("Id"); - - b.HasIndex("ChatGroupId"); - - b.HasIndex("PrivateChatId"); - - b.HasIndex("RecipientId"); - - b.ToTable("Messages"); - }); - - modelBuilder.Entity("Govor.Core.Models.Messages.MessageReaction", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("MessageId") - .HasColumnType("uuid"); - - b.Property("ReactedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("ReactionCode") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("character varying(64)"); - - b.Property("UserId") - .HasColumnType("uuid"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.HasIndex("MessageId", "UserId") - .IsUnique(); - - b.ToTable("MessageReactions"); - }); - - modelBuilder.Entity("Govor.Core.Models.Messages.MessageView", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("MessageId") - .HasColumnType("uuid"); - - b.Property("UserId") - .HasColumnType("uuid"); - - b.Property("ViewedAt") - .HasColumnType("timestamp with time zone"); - - b.HasKey("Id"); - - b.HasIndex("MessageId", "UserId") - .IsUnique(); - - b.ToTable("MessageViews"); - }); - - modelBuilder.Entity("Govor.Core.Models.PrivateChat", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("UserAId") - .HasColumnType("uuid"); - - b.Property("UserBId") - .HasColumnType("uuid"); - - b.HasKey("Id"); - - b.ToTable("PrivateChats"); - }); - - modelBuilder.Entity("Govor.Core.Models.Users.Admin", b => - { - b.Property("UserId") - .HasColumnType("uuid"); - - b.HasKey("UserId"); - - b.ToTable("Admins"); - }); - - modelBuilder.Entity("Govor.Core.Models.Users.Crypto.OneTimePreKey", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("IsUsed") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(false); - - b.Property("PublicKey") - .IsRequired() - .HasColumnType("bytea"); - - b.Property("UploadedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("UserCryptoSessionId") - .HasColumnType("uuid"); - - b.HasKey("Id"); - - b.HasIndex("UploadedAt"); - - b.HasIndex("UserCryptoSessionId", "IsUsed"); - - b.ToTable("OneTimePreKeys"); - }); - - modelBuilder.Entity("Govor.Core.Models.Users.Crypto.SignedPreKey", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("PublicSignedPreKey") - .IsRequired() - .HasColumnType("bytea"); - - b.Property("SignedPreKeySignature") - .IsRequired() - .HasColumnType("bytea"); - - b.Property("UserCryptoSessionId") - .HasColumnType("uuid"); - - b.HasKey("Id"); - - b.HasIndex("UserCryptoSessionId") - .IsUnique(); - - b.ToTable("SignedPreKeys"); - }); - - modelBuilder.Entity("Govor.Core.Models.Users.Crypto.UserCryptoSession", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("PublicIdentityKey") - .IsRequired() - .HasColumnType("bytea"); - - b.Property("UserSessionId") - .HasColumnType("uuid"); - - b.HasKey("Id"); - - b.HasIndex("UserSessionId") - .IsUnique(); - - b.ToTable("UserCryptoSessions"); - }); - - modelBuilder.Entity("Govor.Core.Models.Users.User", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("CreatedOn") - .HasColumnType("date"); - - b.Property("Description") - .HasMaxLength(500) - .HasColumnType("character varying(500)"); - - b.Property("IconId") - .HasColumnType("uuid"); - - b.Property("InviteId") - .HasColumnType("uuid"); - - b.Property("PasswordHash") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("character varying(128)"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("character varying(50)"); - - b.Property("WasOnline") - .HasColumnType("timestamp with time zone"); - - b.HasKey("Id"); - - b.HasIndex("CreatedOn"); - - b.HasIndex("InviteId"); - - b.HasIndex("Username") - .IsUnique(); - - b.HasIndex("WasOnline"); - - b.ToTable("Users"); - }); - - modelBuilder.Entity("Govor.Core.Models.Users.UserPushToken", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("IsActive") - .HasColumnType("boolean"); - - b.Property("LastUsedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("Platform") - .IsRequired() - .HasColumnType("text"); - - b.Property("Provider") - .IsRequired() - .HasColumnType("text"); - - b.Property("Token") - .IsRequired() - .HasColumnType("text"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("UserId") - .HasColumnType("uuid"); - - b.Property("UserSessionId") - .HasColumnType("uuid"); - - b.HasKey("Id"); - - b.HasIndex("Token") - .IsUnique(); - - b.HasIndex("UserId") - .IsUnique(); - - b.HasIndex("UserSessionId") - .IsUnique(); - - b.HasIndex("UserId", "IsActive"); - - b.ToTable("UserPushTokens"); - }); - - modelBuilder.Entity("Govor.Core.Models.Users.UserSession", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("DeviceInfo") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("character varying(256)"); - - b.Property("ExpiresAt") - .HasColumnType("timestamp with time zone"); - - b.Property("IsRevoked") - .HasColumnType("boolean"); - - b.Property("RefreshTokenHash") - .IsRequired() - .HasColumnType("text"); - - b.Property("UserId") - .HasColumnType("uuid"); - - b.HasKey("Id"); - - b.HasIndex("Id") - .IsUnique(); - - b.HasIndex("RefreshTokenHash") - .IsUnique(); - - b.HasIndex("UserId"); - - b.ToTable("UserSessions"); - }); - - modelBuilder.Entity("Govor.Core.Models.Friendship", b => - { - b.HasOne("Govor.Core.Models.Users.User", "Addressee") - .WithMany("ReceivedFriendRequests") - .HasForeignKey("AddresseeId") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - - b.HasOne("Govor.Core.Models.Users.User", "Requester") - .WithMany("SentFriendRequests") - .HasForeignKey("RequesterId") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - - b.Navigation("Addressee"); - - b.Navigation("Requester"); - }); - - modelBuilder.Entity("Govor.Core.Models.GroupAdmins", b => - { - b.HasOne("Govor.Core.Models.ChatGroup", null) - .WithMany("Admins") - .HasForeignKey("GroupId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Govor.Core.Models.GroupInvitation", b => - { - b.HasOne("Govor.Core.Models.ChatGroup", null) - .WithMany("InviteCodes") - .HasForeignKey("GroupId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Govor.Core.Models.Users.User", "UserMaker") - .WithMany() - .HasForeignKey("UserMakerId") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - - b.Navigation("UserMaker"); - }); - - modelBuilder.Entity("Govor.Core.Models.GroupMembership", b => - { - b.HasOne("Govor.Core.Models.ChatGroup", null) - .WithMany("Members") - .HasForeignKey("GroupId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Govor.Core.Models.GroupInvitation", null) - .WithMany() - .HasForeignKey("InvitationId") - .OnDelete(DeleteBehavior.SetNull); - }); - - modelBuilder.Entity("Govor.Core.Models.Messages.MediaAttachments", b => - { - b.HasOne("Govor.Core.Models.MediaFile", "MediaFile") - .WithMany() - .HasForeignKey("MediaFileId") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - - b.HasOne("Govor.Core.Models.Messages.Message", "Message") - .WithMany("MediaAttachments") - .HasForeignKey("MessageId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("MediaFile"); - - b.Navigation("Message"); - }); - - modelBuilder.Entity("Govor.Core.Models.Messages.Message", b => - { - b.HasOne("Govor.Core.Models.ChatGroup", null) - .WithMany("Messages") - .HasForeignKey("ChatGroupId"); - - b.HasOne("Govor.Core.Models.PrivateChat", null) - .WithMany("Messages") - .HasForeignKey("PrivateChatId"); - }); - - modelBuilder.Entity("Govor.Core.Models.Messages.MessageReaction", b => - { - b.HasOne("Govor.Core.Models.Messages.Message", "Message") - .WithMany("Reactions") - .HasForeignKey("MessageId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Govor.Core.Models.Users.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Message"); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Govor.Core.Models.Messages.MessageView", b => - { - b.HasOne("Govor.Core.Models.Messages.Message", null) - .WithMany("MessageViews") - .HasForeignKey("MessageId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Govor.Core.Models.Users.Admin", b => - { - b.HasOne("Govor.Core.Models.Users.User", "User") - .WithOne() - .HasForeignKey("Govor.Core.Models.Users.Admin", "UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Govor.Core.Models.Users.Crypto.OneTimePreKey", b => - { - b.HasOne("Govor.Core.Models.Users.Crypto.UserCryptoSession", "UserCryptoSession") - .WithMany("OneTimePreKeys") - .HasForeignKey("UserCryptoSessionId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("UserCryptoSession"); - }); - - modelBuilder.Entity("Govor.Core.Models.Users.Crypto.SignedPreKey", b => - { - b.HasOne("Govor.Core.Models.Users.Crypto.UserCryptoSession", "UserCryptoSession") - .WithOne("SignedPreKey") - .HasForeignKey("Govor.Core.Models.Users.Crypto.SignedPreKey", "UserCryptoSessionId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("UserCryptoSession"); - }); - - modelBuilder.Entity("Govor.Core.Models.Users.Crypto.UserCryptoSession", b => - { - b.HasOne("Govor.Core.Models.Users.UserSession", "UserSession") - .WithOne("CryptoSession") - .HasForeignKey("Govor.Core.Models.Users.Crypto.UserCryptoSession", "UserSessionId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("UserSession"); - }); - - modelBuilder.Entity("Govor.Core.Models.Users.User", b => - { - b.HasOne("Govor.Core.Models.Invitation", "Invite") - .WithMany("Users") - .HasForeignKey("InviteId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Invite"); - }); - - modelBuilder.Entity("Govor.Core.Models.Users.UserSession", b => - { - b.HasOne("Govor.Core.Models.Users.User", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Govor.Core.Models.ChatGroup", b => - { - b.Navigation("Admins"); - - b.Navigation("InviteCodes"); - - b.Navigation("Members"); - - b.Navigation("Messages"); - }); - - modelBuilder.Entity("Govor.Core.Models.Invitation", b => - { - b.Navigation("Users"); - }); - - modelBuilder.Entity("Govor.Core.Models.Messages.Message", b => - { - b.Navigation("MediaAttachments"); - - b.Navigation("MessageViews"); - - b.Navigation("Reactions"); - }); - - modelBuilder.Entity("Govor.Core.Models.PrivateChat", b => - { - b.Navigation("Messages"); - }); - - modelBuilder.Entity("Govor.Core.Models.Users.Crypto.UserCryptoSession", b => - { - b.Navigation("OneTimePreKeys"); - - b.Navigation("SignedPreKey") - .IsRequired(); - }); - - modelBuilder.Entity("Govor.Core.Models.Users.User", b => - { - b.Navigation("ReceivedFriendRequests"); - - b.Navigation("SentFriendRequests"); - }); - - modelBuilder.Entity("Govor.Core.Models.Users.UserSession", b => - { - b.Navigation("CryptoSession") - .IsRequired(); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/Govor.Data/Migrations/20260301091506_FixRecipientIndex.cs b/Govor.Data/Migrations/20260301091506_FixRecipientIndex.cs deleted file mode 100644 index 5e43c86..0000000 --- a/Govor.Data/Migrations/20260301091506_FixRecipientIndex.cs +++ /dev/null @@ -1,67 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Govor.Data.Migrations -{ - /// - public partial class FixRecipientIndex : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropIndex( - name: "IX_PrivateChats_Id", - table: "PrivateChats"); - - migrationBuilder.DropIndex( - name: "IX_Messages_Id", - table: "Messages"); - - migrationBuilder.DropIndex( - name: "IX_Messages_RecipientId", - table: "Messages"); - - migrationBuilder.DropIndex( - name: "IX_Friendships_Id", - table: "Friendships"); - - migrationBuilder.CreateIndex( - name: "IX_Messages_RecipientId", - table: "Messages", - column: "RecipientId"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropIndex( - name: "IX_Messages_RecipientId", - table: "Messages"); - - migrationBuilder.CreateIndex( - name: "IX_PrivateChats_Id", - table: "PrivateChats", - column: "Id", - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_Messages_Id", - table: "Messages", - column: "Id", - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_Messages_RecipientId", - table: "Messages", - column: "RecipientId", - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_Friendships_Id", - table: "Friendships", - column: "Id", - unique: true); - } - } -} diff --git a/Govor.Data/Migrations/20260301120522_FixPushTokensIndexs.cs b/Govor.Data/Migrations/20260301120522_FixPushTokensIndexs.cs deleted file mode 100644 index d57185e..0000000 --- a/Govor.Data/Migrations/20260301120522_FixPushTokensIndexs.cs +++ /dev/null @@ -1,82 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Govor.Data.Migrations -{ - /// - public partial class FixPushTokensIndexs : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropIndex( - name: "IX_UserPushTokens_UserId", - table: "UserPushTokens"); - - migrationBuilder.AlterColumn( - name: "Token", - table: "UserPushTokens", - type: "character varying(512)", - maxLength: 512, - nullable: false, - oldClrType: typeof(string), - oldType: "text"); - - migrationBuilder.AlterColumn( - name: "Provider", - table: "UserPushTokens", - type: "character varying(50)", - maxLength: 50, - nullable: false, - oldClrType: typeof(string), - oldType: "text"); - - migrationBuilder.AlterColumn( - name: "Platform", - table: "UserPushTokens", - type: "character varying(50)", - maxLength: 50, - nullable: false, - oldClrType: typeof(string), - oldType: "text"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.AlterColumn( - name: "Token", - table: "UserPushTokens", - type: "text", - nullable: false, - oldClrType: typeof(string), - oldType: "character varying(512)", - oldMaxLength: 512); - - migrationBuilder.AlterColumn( - name: "Provider", - table: "UserPushTokens", - type: "text", - nullable: false, - oldClrType: typeof(string), - oldType: "character varying(50)", - oldMaxLength: 50); - - migrationBuilder.AlterColumn( - name: "Platform", - table: "UserPushTokens", - type: "text", - nullable: false, - oldClrType: typeof(string), - oldType: "character varying(50)", - oldMaxLength: 50); - - migrationBuilder.CreateIndex( - name: "IX_UserPushTokens_UserId", - table: "UserPushTokens", - column: "UserId", - unique: true); - } - } -} diff --git a/Govor.Data/Repositories/AdminsRepository.cs b/Govor.Data/Repositories/AdminsRepository.cs deleted file mode 100644 index 8e569bc..0000000 --- a/Govor.Data/Repositories/AdminsRepository.cs +++ /dev/null @@ -1,108 +0,0 @@ -using Govor.Core.Infrastructure.Extensions; -using Govor.Core.Infrastructure.Validators; -using Govor.Core.Models; -using Govor.Core.Models.Users; -using Govor.Core.Repositories.Admins; -using Govor.Data.Repositories.Exceptions; -using Microsoft.EntityFrameworkCore; - -namespace Govor.Data.Repositories; - -public class AdminsRepository(GovorDbContext context, IObjectValidator validator) : IAdminsRepository -{ - private GovorDbContext _context = context; - private IObjectValidator _validator = validator; - public async Task> GetAllAsync() - { - return await _context.Admins - .AsNoTracking() - .Include(a => a.User) - .AsSplitQuery() - .ToListOrThrowIfEmpty(new NotFoundException("Database is empty")); - } - - public async Task GetByIdAsync(Guid id) - { - return await _context.Admins - .AsNoTracking() - .Include(a => a.User) - .AsSplitQuery() - .FirstOrDefaultAsync(u => u.UserId == id) - ?? throw new NotFoundByKeyException(id, "User with given id does not exist"); - } - - public async Task AddAsync(Admin admin) - { - try - { - _validator.Validate(admin); - - _context.Admins.Add(admin); - await _context.SaveChangesAsync(); - } - catch (InvalidObjectException ex) - { - throw new AdditionException("Admin with given data invalid", ex); - } - catch (Exception ex) - { - throw new AdditionException("Cannot add admin", ex); - } - } - - public async Task UpdateAsync(Admin admin) - { - try - { - _validator.Validate(admin); - - var rowsAffected = await _context.Admins - .Where(a => a.UserId == admin.UserId) - .ExecuteUpdateAsync(u => u - .SetProperty(a => a.UserId, admin.UserId) - ); - - if (rowsAffected == 0) - throw new UpdateException($"Not found admin by given id {admin.UserId}"); - - await _context.SaveChangesAsync(); - } - catch (Exception ex) - { - throw new UpdateException($"Error when updating the admin {admin.UserId}", ex); - } - } - - public async Task RemoveAsync(Guid admin) - { - try - { - var result = await GetByIdAsync(admin); - - _context.Admins.Remove(result); - await _context.SaveChangesAsync(); - } - catch (NotFoundByKeyException ex) - { - throw new RemoveException($"Not found admin by given id {admin}", ex); - } - catch (Exception ex) - { - throw new RemoveException("Error when removing the admin", ex); - } - } - - public bool Exist(Guid id) - { - return _context.Users.Any(u => u.Id == id); - } - - public bool Exist(Admin admin) - { - _validator.Validate(admin); - - return _context.Admins.Any(u => - u.UserId == admin.UserId - ); - } -} \ No newline at end of file diff --git a/Govor.Data/Repositories/Exceptions/AdditionException.cs b/Govor.Data/Repositories/Exceptions/AdditionException.cs deleted file mode 100644 index 46fa961..0000000 --- a/Govor.Data/Repositories/Exceptions/AdditionException.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Govor.Data.Repositories.Exceptions; - -public class AdditionException : Exception -{ - public AdditionException(string s, Exception ex) : base(s, ex) - { - } - - public AdditionException(string s) : base(s) { } -} \ No newline at end of file diff --git a/Govor.Data/Repositories/Exceptions/NotFoundByKeyException.cs b/Govor.Data/Repositories/Exceptions/NotFoundByKeyException.cs deleted file mode 100644 index 08f6c8b..0000000 --- a/Govor.Data/Repositories/Exceptions/NotFoundByKeyException.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace Govor.Data.Repositories.Exceptions; - -public class NotFoundByKeyException : NotFoundException -{ - public NotFoundByKeyException(T key) - : base($"Not found object by {key}"){} - - public NotFoundByKeyException(T id, string message) - : base($"Not found object by {id}. Message: " + message) {} - - public NotFoundByKeyException(string message, Exception innerException) : base(message, innerException) - { - } -} \ No newline at end of file diff --git a/Govor.Data/Repositories/Exceptions/NotFoundException.cs b/Govor.Data/Repositories/Exceptions/NotFoundException.cs deleted file mode 100644 index dc60ca5..0000000 --- a/Govor.Data/Repositories/Exceptions/NotFoundException.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Govor.Core; - -namespace Govor.Data.Repositories.Exceptions; - -public class NotFoundException : GovorCoreException -{ - public NotFoundException(string message) - : base(message) {} - public NotFoundException(string message, Exception innerException) - : base(message, innerException){} -} \ No newline at end of file diff --git a/Govor.Data/Repositories/Exceptions/RemoveException.cs b/Govor.Data/Repositories/Exceptions/RemoveException.cs deleted file mode 100644 index 7fbb765..0000000 --- a/Govor.Data/Repositories/Exceptions/RemoveException.cs +++ /dev/null @@ -1,4 +0,0 @@ -namespace Govor.Data.Repositories.Exceptions; - -public class RemoveException(string s, Exception exception) - : Exception(s, exception); \ No newline at end of file diff --git a/Govor.Data/Repositories/Exceptions/UpdateException.cs b/Govor.Data/Repositories/Exceptions/UpdateException.cs deleted file mode 100644 index a44e54c..0000000 --- a/Govor.Data/Repositories/Exceptions/UpdateException.cs +++ /dev/null @@ -1,12 +0,0 @@ -using Govor.Core; - -namespace Govor.Data.Repositories.Exceptions; - -public class UpdateException : GovorCoreException -{ - public UpdateException(string s) - : base(s) { } - - public UpdateException(string s, Exception ex) - : base(s, ex) { } -} \ No newline at end of file diff --git a/Govor.Data/Repositories/FriendshipsRepository.cs b/Govor.Data/Repositories/FriendshipsRepository.cs deleted file mode 100644 index 128ed14..0000000 --- a/Govor.Data/Repositories/FriendshipsRepository.cs +++ /dev/null @@ -1,150 +0,0 @@ -using Govor.Core.Infrastructure.Extensions; -using Govor.Core.Infrastructure.Validators; -using Govor.Core.Models; -using Govor.Core.Models.Users; -using Govor.Core.Repositories.Friendships; -using Govor.Data.Repositories.Exceptions; -using Microsoft.EntityFrameworkCore; - -namespace Govor.Data.Repositories; - -public class FriendshipsRepository : IFriendshipsRepository -{ - private GovorDbContext _context; - private IObjectValidator _validator; - - public FriendshipsRepository(GovorDbContext context, IObjectValidator validator) - { - _context = context; - _validator = validator; - } - - public async Task> GetAllAsync() - { - return await _context.Friendships - .AsNoTracking() - .Include(x => x.Requester) - .Include(x => x.Addressee) - .AsSplitQuery() - .ToListOrThrowIfEmpty(new NotFoundException("Database is empty")); - } - - public async Task GetByIdAsync(Guid id) - { - return await _context.Friendships - .AsNoTracking() - .Include(x => x.Requester) - .Include(x => x.Addressee) - .AsSplitQuery() - .FirstOrDefaultAsync(x => x.Id == id) - ?? throw new NotFoundByKeyException(id, "Friendship with given id was not found"); - } - - public async Task GetFriendshipAsync(Guid fromUserId, Guid toUserId) - { - return await _context.Friendships - .FirstOrDefaultAsync(x => - (x.RequesterId == fromUserId && x.AddresseeId == toUserId) || - (x.RequesterId == toUserId && x.AddresseeId == fromUserId)); - } - - public async Task> FindByUserIdAsync(Guid userId) - { - return await _context.Friendships - .AsNoTracking() - .Include(x => x.Requester) - .Include(x => x.Addressee) - .AsSplitQuery() - .Where(f => - (f.RequesterId == userId || f.AddresseeId == userId)) - .ToListOrThrowIfEmpty(new NotFoundByKeyException(userId, "Friendship with given user id was not found")); - } - - public async Task AddAsync(Friendship friendship) - { - try - { - _validator.Validate(friendship); - - _context.Friendships.Add(friendship); - await _context.SaveChangesAsync(); - } - catch (InvalidObjectException ex) - { - throw new AdditionException("Admin with given data invalid", ex); - } - catch (Exception ex) - { - throw new AdditionException("Cannot add admin", ex); - } - } - - public async Task UpdateAsync(Friendship friendship) - { - try - { - _validator.Validate(friendship); - - var rowsAffected = await _context.Friendships - .Where(a => a.Id == friendship.Id) - .ExecuteUpdateAsync(u => u - .SetProperty(a => a.RequesterId, friendship.RequesterId) - .SetProperty(a => a.AddresseeId, friendship.AddresseeId) - .SetProperty(a => a.Status, friendship.Status) - ); - - if (rowsAffected == 0) - throw new UpdateException($"Not found friendship by given id {friendship.Id}"); - - await _context.SaveChangesAsync(); - } - catch (Exception ex) - { - throw new UpdateException($"Error when updating the friendship {friendship.Id}", ex); - } - } - - public async Task RemoveAsync(Friendship friendship) - { - try - { - var result = await GetByIdAsync(friendship.Id); - - _context.Friendships.Remove(result); - await _context.SaveChangesAsync(); - } - catch (NotFoundByKeyException ex) - { - throw new RemoveException($"Not found friendship by given id {friendship.Id}", ex); - } - catch (Exception ex) - { - throw new RemoveException("Error when removing the friendship", ex); - } - } - - public bool Exist(Guid requesterId, Guid addresseeId) - { - return _context.Friendships.AsNoTracking().Any(x => (x.RequesterId == requesterId && x.AddresseeId == addresseeId) || - x.RequesterId == addresseeId && x.AddresseeId == requesterId); - } - - public bool IsPossibilityOfCreatingFriendship(Guid requesterId, Guid addresseeId) - { - // Ищем любую существующую связь между пользователями - var existingFriendship = _context.Friendships - .AsNoTracking() - .FirstOrDefault(x => - (x.RequesterId == requesterId && x.AddresseeId == addresseeId) || - (x.RequesterId == addresseeId && x.AddresseeId == requesterId)); - - // Если записи нет — создавать можно - if (existingFriendship == null) return true; - - // Если запись есть, создавать новую НЕЛЬЗЯ (нужно обновлять старую), - // за исключением случаев, когда статус "Rejected" или "Blocked" (смотря какая логика) - // Но обычно метод "IsPossibility" подразумевает именно "можно ли инициировать процесс" - - return existingFriendship.Status == FriendshipStatus.Rejected; - } -} \ No newline at end of file diff --git a/Govor.Data/Repositories/GroupRepository.cs b/Govor.Data/Repositories/GroupRepository.cs deleted file mode 100644 index f3a9b3d..0000000 --- a/Govor.Data/Repositories/GroupRepository.cs +++ /dev/null @@ -1,166 +0,0 @@ -using Govor.Core.Infrastructure.Extensions; -using Govor.Core.Infrastructure.Validators; -using Govor.Core.Models; -using Govor.Core.Models.Users; -using Govor.Core.Repositories.Groups; -using Govor.Data.Repositories.Exceptions; -using Microsoft.EntityFrameworkCore; - -namespace Govor.Data.Repositories; - -public class GroupRepository : IGroupsRepository -{ - private GovorDbContext _context; - private IObjectValidator _validator; - - public GroupRepository(GovorDbContext context, IObjectValidator validator) - { - _context = context; - _validator = validator; - } - - public async Task> GetAllAsync() - { - return await _context.ChatGroups - .AsNoTracking() - .Include(g => g.Admins) - .Include(g => g.Members) - .Include(g => g.InviteCodes) - .AsSplitQuery() - .ToListOrThrowIfEmpty(new NotFoundException("Database is empty")); - } - - public async Task GetByIdAsync(Guid id) - { - return await _context.ChatGroups - .AsNoTracking() - .Include(g => g.Admins) - .Include(g => g.Members) - .Include(g => g.InviteCodes) - .AsSplitQuery() - .FirstOrDefaultAsync(g => g.Id == id) - ?? throw new NotFoundByKeyException(id, "Group with given id doesn't exist"); - } - - public async Task> SearchByNameAsync(string name) - { - return await _context.ChatGroups - .AsNoTracking() - .Include(g => g.Admins) - .Include(g => g.Members) - .Include(g => g.InviteCodes) - .AsSplitQuery() - .Where(g => g.Name.ToLower().Contains(name.ToLower())) - .Take(20) - .ToListOrThrowIfEmpty(new NotFoundByKeyException(name, "Group with name doesn't exist")); - } - - public async Task> GetByAdminIdAsync(Guid userId) - { - return await _context.ChatGroups - .AsNoTracking() - .Include(g => g.Admins) - .Include(g => g.Members) - .Include(g => g.InviteCodes) - .AsSplitQuery() - .Where(g => g.Admins.Any(a => a.UserId == userId)) - .ToListOrThrowIfEmpty(new NotFoundByKeyException(userId, "Admin with given id doesn't exist")); - } - - public async Task> GetByUserIdAsync(Guid userId) - { - return await _context.ChatGroups - .AsNoTracking() - .Include(g => g.Admins) - .Include(g => g.Members) - .Include(g => g.InviteCodes) - .AsSplitQuery() - .Where(g => g.Members.Any(a => a.UserId == userId)) - .ToListOrThrowIfEmpty(new NotFoundByKeyException(userId, "Member with given id doesn't exist")); - } - - public async Task AddAsync(ChatGroup group) - { - try - { - _validator.Validate(group); - - _context.ChatGroups.Add(group); - await _context.SaveChangesAsync(); - } - catch (InvalidObjectException ex) - { - throw new AdditionException("Group with given data invalid", ex); - } - catch (Exception ex) - { - throw new AdditionException("Cannot add group", ex); - } - } - - public async Task UpdateAsync(ChatGroup group) - { - try - { - _validator.Validate(group); - - var rowsAffected = await _context.ChatGroups - .Where(u => u.Id == group.Id) - .ExecuteUpdateAsync(g => g - .SetProperty(g => g.Name, group.Name) - .SetProperty(g => g.Description, group.Description) - .SetProperty(g => g.ImageId, group.ImageId) - .SetProperty(g => g.IsChannel, group.IsChannel) - .SetProperty(g => g.IsPrivate, group.IsPrivate) - .SetProperty(g => g.InviteCodes, group.InviteCodes) - ); - - if (rowsAffected == 0) - throw new UpdateException($"Not found group by given id {group.Id}"); - - await _context.SaveChangesAsync(); - } - catch (Exception ex) - { - throw new UpdateException($"Error when updating the group {group.Id}", ex); - } - } - - public async Task RemoveAsync(Guid groupId) - { - try - { - var result = await GetByIdAsync(groupId); - - _context.ChatGroups.Remove(result); - await _context.SaveChangesAsync(); - } - catch (InvalidObjectException ex) - { - throw new RemoveException("User with given data invalid", ex); - } - } - - public bool Exist(Guid groupId) - { - return _context.ChatGroups.Any(g => g.Id == groupId); - } - - public bool Exist(ChatGroup chatGroup) - { - return _context.ChatGroups.Any(g => g.Id == chatGroup.Id && - g.IsChannel == chatGroup.IsChannel && - g.Description == chatGroup.Description && - g.IsPrivate == chatGroup.IsPrivate && - g.Name == chatGroup.Name && - g.ImageId == chatGroup.ImageId); - } - - public async Task IsUserMemberOfGroupAsync(Guid userId, Guid groupId) - { - return await _context.ChatGroups - .AsNoTracking() - .Include(g => g.Members) - .AnyAsync(g => g.Members.Any(a => a.UserId == userId && a.GroupId == groupId)); - } -} diff --git a/Govor.Data/Repositories/InvitesRepository.cs b/Govor.Data/Repositories/InvitesRepository.cs deleted file mode 100644 index ba9050d..0000000 --- a/Govor.Data/Repositories/InvitesRepository.cs +++ /dev/null @@ -1,154 +0,0 @@ -using Govor.Core.Infrastructure.Extensions; -using Govor.Core.Infrastructure.Validators; -using Govor.Core.Models; -using Govor.Core.Models.Users; -using Govor.Core.Repositories.Invaites; -using Govor.Data.Repositories.Exceptions; -using Microsoft.EntityFrameworkCore; - -namespace Govor.Data.Repositories; - -public class InvitesRepository : IInvitesRepository -{ - private GovorDbContext _context; - private IObjectValidator _validator; - - public InvitesRepository(GovorDbContext context, IObjectValidator validator) - { - _context = context; - _validator = validator; - } - - public async Task> GetAllAsync() - { - return await _context.Invitations - .AsNoTracking() - .Include(i => i.Users) - .AsSplitQuery() - .ToListOrThrowIfEmpty(new NotFoundException("Database is empty")); - } - - public async Task FindByIdAsync(Guid id) - { - return await _context.Invitations - .AsNoTracking() - .Include(i => i.Users) - .AsSplitQuery() - .FirstOrDefaultAsync(i => i.Id == id) - ?? throw new NotFoundByKeyException(id, "Invitation with given id does not exist"); - } - - public async Task FindByCodeAsync(string code) - { - return await _context.Invitations - .AsNoTracking() - .Include(i => i.Users) - .AsSplitQuery() - .FirstOrDefaultAsync(i => i.Code == code) - ?? throw new NotFoundByKeyException(code, "Invitation with given code does not exist"); - } - - public async Task> FindAdminsInvitesAsync() - { - return await _context.Invitations - .AsNoTracking() - .Include(i => i.Users) - .AsSplitQuery() - .Where(i => i.IsAdmin) - .ToListOrThrowIfEmpty(new NotFoundByKeyException(true, "Admins invites do not exist")); - } - - public async Task AddAsync(Invitation invitation) - { - try - { - _validator.Validate(invitation); - - if(Exist(invitation.Code)) - throw new AdditionException("Invitation with given code already exists"); - - _context.Invitations.Add(invitation); - await _context.SaveChangesAsync(); - } - catch (InvalidObjectException ex) - { - throw new AdditionException("Invitation with given data invalid", ex); - } - catch (Exception ex) - { - throw new AdditionException("Cannot add invitation", ex); - }; - } - - public async Task UpdateAsync(Invitation invitation) - { - try - { - _validator.Validate(invitation); - - var rowsAffected = await _context.Invitations - .Where(a => a.Id == invitation.Id) - .ExecuteUpdateAsync(u => u - .SetProperty(i => i.IsAdmin, invitation.IsAdmin) - .SetProperty(i => i.Code, invitation.Code) - .SetProperty(i => i.Description, invitation.Description) - .SetProperty(i => i.DateCreated, invitation.DateCreated) - .SetProperty(i => i.EndDate, invitation.EndDate) - .SetProperty(i => i.MaxParticipants, invitation.MaxParticipants) - .SetProperty(i => i.Users, invitation.Users) - ); - - if (rowsAffected == 0) - throw new UpdateException($"Not found invitation by given id {invitation.Id}"); - - await _context.SaveChangesAsync(); - } - catch (Exception ex) - { - throw new UpdateException($"Error when updating the invitation {invitation.Id}", ex); - } - } - - public async Task RemoveAsync(Invitation invitation) - { - try - { - var result = await FindByIdAsync(invitation.Id); - - _context.Invitations.Remove(result); - await _context.SaveChangesAsync(); - } - catch (NotFoundByKeyException ex) - { - throw new RemoveException($"Not found invitation by given id {invitation.Id}", ex); - } - catch (Exception ex) - { - throw new RemoveException("Error when removing the invitation", ex); - } - } - - public bool Exist(Invitation invitation) - { - _validator.Validate(invitation); - return _context.Invitations.Any(i => i.Id == invitation.Id && - i.Code == invitation.Code && - i.IsAdmin == invitation.IsAdmin && - i.DateCreated == invitation.DateCreated && - i.EndDate == invitation.EndDate && - i.Description == invitation.Description && - i.MaxParticipants == invitation.MaxParticipants - - ); - } - - public bool Exist(string code) - { - return _context.Invitations.Any(i => i.Code == code); - } - - public bool Exist(Guid guid) - { - return _context.Invitations.Any(i => i.Id == guid); - } -} \ No newline at end of file diff --git a/Govor.Data/Repositories/MediaAttachmentsRepository.cs b/Govor.Data/Repositories/MediaAttachmentsRepository.cs deleted file mode 100644 index bb7588d..0000000 --- a/Govor.Data/Repositories/MediaAttachmentsRepository.cs +++ /dev/null @@ -1,128 +0,0 @@ -using Govor.Core.Infrastructure.Extensions; -using Govor.Core.Infrastructure.Validators; -using Govor.Core.Models.Messages; -using Govor.Core.Repositories.MediasAttachments; -using Govor.Data.Repositories.Exceptions; -using Microsoft.EntityFrameworkCore; - -namespace Govor.Data.Repositories; - -public class MediaAttachmentsRepository : IMediaAttachmentsRepository -{ - public IObjectValidator _validator; - public GovorDbContext _context; - - public MediaAttachmentsRepository(GovorDbContext context, IObjectValidator validator) - { - _context = context; - _validator = validator; - } - - public async Task> GetAllAsync() - { - return await _context.MediaAttachments - .AsNoTracking() - .Include(ma => ma.Message) - .AsSplitQuery() - .ToListOrThrowIfEmpty(new NotFoundException("No media attachments found.")); - } - - public async Task> GetAllByMessageId(Guid messageId) - { - return await _context.MediaAttachments - .AsNoTracking() - .Include(ma => ma.Message) - .AsSplitQuery() - .Where(m => m.MessageId == messageId) - .ToListOrThrowIfEmpty(new NotFoundByKeyException(messageId, "No media attachments found by given message Id")); - } - - public async Task FindByIdAsync(Guid id) - { - return await _context.MediaAttachments - .AsNoTracking() - .Include(ma => ma.Message) - .AsSplitQuery() - .FirstOrDefaultAsync(m => m.Id == id) - ?? throw new NotFoundByKeyException(id, "No media attachments found by given Id"); - } - - public async Task AddAsync(MediaAttachments mediaAttachments) - { - try - { - _validator.Validate(mediaAttachments); - - _context.MediaAttachments.Add(mediaAttachments); - await _context.SaveChangesAsync(); - } - catch (InvalidObjectException ex) - { - throw new AdditionException("Attachments with given data invalid", ex); - } - catch (Exception ex) - { - throw new AdditionException("Cannot add Attachments", ex); - } - } - - public async Task UpdateAsync(MediaAttachments attachments) - { - try - { - _validator.Validate(attachments); - - var rowsAffected = await _context.MediaAttachments - .Where(m => m.Id == attachments.Id) - .ExecuteUpdateAsync(u => u - .SetProperty(m => m.MessageId, attachments.MessageId) - .SetProperty(m => m.Message, attachments.Message) - .SetProperty(m => m.MediaFileId, attachments.MediaFileId) - ); - - if (rowsAffected == 0) - throw new UpdateException($"Not found attachments by given id {attachments.Id}"); - - await _context.SaveChangesAsync(); - } - catch (Exception ex) - { - throw new UpdateException($"Error when updating the attachments {attachments.Id}", ex); - } - } - - public async Task RemoveAsync(Guid Id) - { - try - { - var result = await FindByIdAsync(Id); - - _context.MediaAttachments.Remove(result); - await _context.SaveChangesAsync(); - } - catch (NotFoundByKeyException ex) - { - throw new RemoveException($"Not found attachments by given id {Id}", ex); - } - catch (Exception ex) - { - throw new RemoveException("Error when removing the attachments", ex); - } - } - - public bool Exist(Guid id) - { - return _context.MediaAttachments.Any(e => e.Id == id); - } - - public bool Exist(MediaAttachments attachments) - { - _validator.Validate(attachments); - - return _context.MediaAttachments.Any( - e => e.Id == attachments.Id && - e.MessageId == attachments.MessageId && - e.MediaFileId == attachments.MediaFileId - ); - } -} \ No newline at end of file diff --git a/Govor.Data/Repositories/MessagesRepository.cs b/Govor.Data/Repositories/MessagesRepository.cs deleted file mode 100644 index 4932297..0000000 --- a/Govor.Data/Repositories/MessagesRepository.cs +++ /dev/null @@ -1,179 +0,0 @@ -using Govor.Core.Infrastructure.Extensions; -using Govor.Core.Infrastructure.Validators; -using Govor.Core.Models; -using Govor.Core.Models.Messages; -using Govor.Core.Repositories.Messages; -using Govor.Data.Repositories.Exceptions; -using Microsoft.EntityFrameworkCore; - -namespace Govor.Data.Repositories; - -public class MessagesRepository : IMessagesRepository -{ - private GovorDbContext _context; - private IObjectValidator _validator; - public MessagesRepository(GovorDbContext context, IObjectValidator validator) - { - _context = context; - _validator = validator; - } - - public async Task> GetAllAsync() - { - return await _context.Messages - .AsNoTracking() - .Include(m => m.MediaAttachments) - .ThenInclude(m => m.MediaFile) - .AsSplitQuery() - .ToListOrThrowIfEmpty(new NotFoundException("No messages found in the database")); - } - - public async Task FindByIdAsync(Guid messageId) - { - return await _context.Messages - .AsNoTracking() - .AsSplitQuery() - .FirstOrDefaultAsync(m => m.Id == messageId) - ?? throw new NotFoundByKeyException(messageId, "Message with given id does not exist"); - } - - public async Task> FindBySenderIdAsync(Guid senderId) - { - return await _context.Messages - .AsNoTracking() - .Include(m => m.MediaAttachments) - .ThenInclude(m => m.MediaFile) - .AsSplitQuery() - .Where(m => m.SenderId == senderId) - .ToListOrThrowIfEmpty(new NotFoundByKeyException(senderId, "Messages with given sender id do not exist")); - } - - public async Task> FindByReceiverIdAsync(Guid receiverId) - { - return await _context.Messages - .AsNoTracking() - .Include(m => m.MediaAttachments) - .ThenInclude(m => m.MediaFile) - .AsSplitQuery() - .Where(m => m.RecipientId == receiverId) - .ToListOrThrowIfEmpty(new NotFoundByKeyException(receiverId, "Messages with given recipient id do not exist")); - } - - public async Task> FindBySenderAndReceiverIdAsync(Guid senderId, Guid receiverId, RecipientType recipientType = RecipientType.User) - { - return await _context.Messages - .AsNoTracking() - .Include(m => m.MediaAttachments) - .ThenInclude(m => m.MediaFile) - .AsSplitQuery() - .Where(m => m.SenderId == senderId - && m.RecipientId == receiverId - && m.RecipientType == recipientType) - .ToListOrThrowIfEmpty(new NotFoundException("No messages found in the database")); - } - - public async Task> FindBySentAtAsync(DateTime date) - { - return await _context.Messages - .AsNoTracking() - .Include(m => m.MediaAttachments) - .ThenInclude(m => m.MediaFile) - .AsSplitQuery() - .Where(m => m.SentAt == date) - .ToListOrThrowIfEmpty(new NotFoundByKeyException(date, "Messages sent at date do not exist")); - } - - public async Task AddAsync(Message message) - { - try - { - _validator.Validate(message); - - _context.Messages.Add(message); - await _context.SaveChangesAsync(); - } - catch (InvalidObjectException ex) - { - throw new AdditionException("Message with given data invalid", ex); - } - catch (Exception ex) - { - throw new AdditionException("Cannot add message", ex); - } - } - - // TODO: Test this block - public async Task UpdateAsync(Message message) - { - try - { - _validator.Validate(message); - - var rowsAffected = await _context.Messages - .Where(m => m.Id == message.Id) - .ExecuteUpdateAsync(u => u - .SetProperty(m => m.SenderId, message.SenderId) - .SetProperty(m => m.RecipientId, message.RecipientId) - .SetProperty(m => m.SentAt, message.SentAt) - .SetProperty(m => m.RecipientType, message.RecipientType) - .SetProperty(m => m.EncryptedContent, message.EncryptedContent) - .SetProperty(m => m.EditedAt, message.EditedAt) - .SetProperty(m => m.IsEdited, message.IsEdited) - .SetProperty(m => m.Reactions, message.Reactions) - .SetProperty(m => m.ReplyToMessageId, message.ReplyToMessageId) - .SetProperty(m => m.MessageViews, message.MessageViews) - .SetProperty(m => m.MediaAttachments, message.MediaAttachments) - - ); - - if (rowsAffected == 0) - throw new UpdateException($"Not found message by given id {message.Id}"); - - await _context.SaveChangesAsync(); - } - catch (Exception ex) - { - throw new UpdateException($"Error when updating the message {message.Id}", ex); - } - } - - public async Task RemoveAsync(Guid messageId) - { - try - { - var result = await FindByIdAsync(messageId); - - _context.Messages.Remove(result); - await _context.SaveChangesAsync(); - } - catch (NotFoundByKeyException ex) - { - throw new RemoveException($"Not found message by given id {messageId}", ex); - } - catch (Exception ex) - { - throw new RemoveException("Error when removing the message", ex); - } - } - - public bool Exist(Message message) - { - _validator.Validate(message); - - return _context.Messages.Any( - m => m.Id == message.Id && - m.SenderId == message.SenderId && - m.RecipientId == message.RecipientId && - m.EncryptedContent == message.EncryptedContent && - m.EditedAt == message.EditedAt && - m.IsEdited == message.IsEdited && - m.SentAt == message.SentAt && - m.ReplyToMessageId == message.ReplyToMessageId - ); - } - - public bool Exist(Guid messageId) - { - return _context.Messages.Any(m => m.Id == messageId); - } -} diff --git a/Govor.Data/Repositories/PrivateChatsRepository.cs b/Govor.Data/Repositories/PrivateChatsRepository.cs deleted file mode 100644 index e72de8a..0000000 --- a/Govor.Data/Repositories/PrivateChatsRepository.cs +++ /dev/null @@ -1,126 +0,0 @@ -using Govor.Core.Infrastructure.Extensions; -using Govor.Core.Infrastructure.Validators; -using Govor.Core.Models; -using Govor.Core.Models.Messages; -using Govor.Core.Repositories.PrivateChats; -using Govor.Data.Repositories.Exceptions; -using Microsoft.EntityFrameworkCore; - -namespace Govor.Data.Repositories; - -public class PrivateChatsRepository : IPrivateChatsRepository -{ - private GovorDbContext _context; - private IObjectValidator _validator; - - public PrivateChatsRepository(GovorDbContext context, IObjectValidator validator) - { - _context = context; - _validator = validator; - } - - public async Task> GetAllAsync() - { - return await _context.PrivateChats - .AsNoTracking() - .ToListOrThrowIfEmpty(new NotFoundException("Database is empty")); - } - - public async Task GetByIdAsync(Guid id) - { - return await _context.PrivateChats - .AsNoTracking() - .FirstOrDefaultAsync(p => p.Id == id) - ?? throw new NotFoundByKeyException(id, "Private Chat with given Id does not exist"); - } - - public async Task GetByMembersAsync(Guid memberAId, Guid memberBId) - { - return await _context.PrivateChats - .AsNoTracking() - .FirstOrDefaultAsync(f => (f.UserAId == memberAId && f.UserBId == memberBId) || (f.UserAId == memberBId && f.UserBId == memberAId)) - ?? throw new NotFoundByKeyException<(Guid, Guid)>((memberAId, memberBId), "Private Chat with given members Id's does not exist"); - } - - public async Task> GetAllOfUser(Guid userId) - { - return await _context.PrivateChats - .AsNoTracking() - .Where(f => f.UserAId == userId || f.UserBId == userId) - .ToListOrThrowIfEmpty(new NotFoundByKeyException(userId, "Private Chat with given member Id's does not exist")); - } - - public async Task AddAsync(PrivateChat chat) - { - try - { - _validator.Validate(chat); - - _context.PrivateChats.Add(chat); - await _context.SaveChangesAsync(); - } - catch (InvalidObjectException ex) - { - throw new AdditionException("Private chat with given data invalid", ex); - } - catch (Exception ex) - { - throw new AdditionException("Cannot add private chat", ex); - } - } - - public async Task UpdateAsync(PrivateChat chat) - { - try - { - _validator.Validate(chat); - - var rowsAffected = await _context.PrivateChats - .Where(m => m.Id == chat.Id) - .ExecuteUpdateAsync(c => c - .SetProperty(c => c.UserAId, chat.UserAId) - .SetProperty(c => c.UserBId, chat.UserBId) - .SetProperty(c => c.Messages, chat.Messages) - ); - - if (rowsAffected == 0) - throw new UpdateException($"Not found private chat by given id {chat.Id}"); - - await _context.SaveChangesAsync(); - } - catch (Exception ex) - { - throw new UpdateException($"Error when updating the private chat {chat.Id}", ex); - } - } - - public async Task RemoveAsync(Guid chatId) - { - try - { - var result = await GetByIdAsync(chatId); - - _context.PrivateChats.Remove(result); - await _context.SaveChangesAsync(); - } - catch (NotFoundByKeyException ex) - { - throw new RemoveException($"Not found private chat by given id {chatId}", ex); - } - catch (Exception ex) - { - throw new RemoveException("Error when removing the private chat", ex); - } - } - - public bool Exist(Guid chatId) - { - return _context.PrivateChats.Any(c => c.Id == chatId); - } - - public bool Exist(Guid userAId, Guid userBId) - { - return _context.PrivateChats.Any(f => (f.UserAId == userAId && f.UserBId == userBId) - || (f.UserAId == userBId && f.UserBId == userAId)); - } -} \ No newline at end of file diff --git a/Govor.Data/Repositories/PushTokenRepository.cs b/Govor.Data/Repositories/PushTokenRepository.cs deleted file mode 100644 index 39eeaf4..0000000 --- a/Govor.Data/Repositories/PushTokenRepository.cs +++ /dev/null @@ -1,150 +0,0 @@ -using System.Security; -using Govor.Core.Infrastructure.Extensions; -using Govor.Core.Models.Users; -using Govor.Core.Repositories.PushTokens; -using Govor.Data.Repositories.Exceptions; -using Microsoft.EntityFrameworkCore; - -namespace Govor.Data.Repositories; - -public class PushTokenRepository : IPushTokenRepository -{ - private GovorDbContext _context; - - public PushTokenRepository(GovorDbContext context) - { - _context = context; - } - - public async Task> GetActiveTokensAsync(Guid userId) - { - return await _context.UserPushTokens - .AsNoTracking() - .Where(t => t.UserId == userId && t.IsActive) - .Select(t => t.Token) - .ToListAsync(); - } - - public async Task> GetActiveTokensUsersAsync(IEnumerable userIds) - { - if (userIds is null || !userIds.Any()) - return []; - - var distinctIds = userIds.Distinct().ToList(); - - return await _context.UserPushTokens - .AsNoTracking() - .Where(t => distinctIds.Contains(t.UserId) && t.IsActive) - .Select(t => t.Token) - .ToListAsync(); - } - - public async Task GetActiveTokenBySessionAsync(Guid sessionId) - { - if (sessionId == Guid.Empty) - return ""; - - return await _context.UserPushTokens - .AsNoTracking() - .Where(t => t.UserSessionId == sessionId && t.IsActive) - .Select(t => t.Token) - .FirstOrDefaultAsync() ?? ""; - } - - public async Task AddOrUpdateTokenAsync(Guid userId, Guid? sessionId, string token, string platform, string provider = "FCM") - { - if (userId == Guid.Empty) - throw new ArgumentException("UserId cannot be empty", nameof(userId)); - - if (string.IsNullOrWhiteSpace(token)) - throw new ArgumentException("Token cannot be empty", nameof(token)); - - if (string.IsNullOrWhiteSpace(platform)) - throw new ArgumentException("Platform cannot be empty", nameof(platform)); - - var existing = await _context.UserPushTokens - .FirstOrDefaultAsync(t => t.UserSessionId == sessionId && t.Platform == platform); - - if (existing != null) - { - if(existing.UserId != userId) - throw new SecurityException("Token already belongs to another user"); - - // Updates - existing.UserId = userId; - existing.UserSessionId = sessionId; - existing.Platform = platform; - existing.Provider = provider; - existing.UpdatedAt = DateTime.UtcNow; - existing.LastUsedAt = DateTime.UtcNow; - existing.Token = token; - existing.IsActive = true; - - _context.UserPushTokens.Update(existing); - } - else - { - // Add new - var newToken = new UserPushToken - { - UserId = userId, - UserSessionId = sessionId, - Token = token, - Platform = platform, - Provider = provider, - CreatedAt = DateTime.UtcNow, - UpdatedAt = DateTime.UtcNow, - LastUsedAt = DateTime.UtcNow, - IsActive = true, - }; - - _context.UserPushTokens.Add(newToken); - } - - await _context.SaveChangesAsync(); - } - - public async Task RemoveTokensAsync(IEnumerable tokens) - { - if (tokens is null || !tokens.Any()) - return; - - var tokenList = tokens.Distinct().ToList(); - - var toRemove = await _context.UserPushTokens - .Where(t => tokenList.Contains(t.Token)) - .ToListAsync(); - - if (toRemove.Any()) - { - foreach (var token in toRemove) - { - token.IsActive = false; - _context.UserPushTokens.Update(token); - } - - await _context.SaveChangesAsync(); - } - } - - public async Task DeactivateTokenBySessionAsync(Guid sessionId) - { - if (sessionId == Guid.Empty) - return; - - var tokens = await _context.UserPushTokens - .Where(t => t.UserSessionId == sessionId && t.IsActive) - .ToListAsync(); - - if (tokens.Any()) - { - foreach (var token in tokens) - { - token.IsActive = false; - token.UpdatedAt = DateTime.UtcNow; - } - - await _context.SaveChangesAsync(); - } - } -} \ No newline at end of file diff --git a/Govor.Data/Repositories/UserSessionsRepository.cs b/Govor.Data/Repositories/UserSessionsRepository.cs deleted file mode 100644 index 92b68a5..0000000 --- a/Govor.Data/Repositories/UserSessionsRepository.cs +++ /dev/null @@ -1,169 +0,0 @@ -using Govor.Core.Infrastructure.Extensions; -using Govor.Core.Models.Users; -using Govor.Core.Repositories.UserSessionsRepository; -using Govor.Data.Repositories.Exceptions; -using Microsoft.EntityFrameworkCore; - -namespace Govor.Data.Repositories; - -public class UserSessionsRepository : IUserSessionsRepository -{ - private GovorDbContext _context; - - public UserSessionsRepository(GovorDbContext context) - { - _context = context; - } - - public async Task> GetAllAsync() - { - return await _context.UserSessions - .AsNoTracking() - .ToListOrThrowIfEmpty(new NotFoundException("Database is empty")); - } - - public async Task GetByIdAsync(Guid sessionId) - { - return await _context.UserSessions - .AsNoTracking() - .FirstOrDefaultAsync(session => session.Id == sessionId) - ?? throw new NotFoundByKeyException(sessionId, "Session with given id does not exist"); - } - - public async Task> GetByUserIdAsync(Guid userId) - { - return await _context.UserSessions - .AsNoTracking() - .Where(session => session.UserId == userId) - .ToListOrThrowIfEmpty(new NotFoundByKeyException(userId, "Sessions with given user id does not exist")); - } - - public async Task> GetByCreatedAtAsync(DateTime createdAt) - { - return await _context.UserSessions - .AsNoTracking() - .Where(session => session.CreatedAt == createdAt) - .ToListOrThrowIfEmpty(new NotFoundByKeyException(createdAt, "Sessions with given created at does not exist")); - } - - public async Task> GetByExpiresAtAsync(DateTime expiresAt) - { - return await _context.UserSessions - .AsNoTracking() - .Where(session => session.ExpiresAt == expiresAt) - .ToListOrThrowIfEmpty(new NotFoundByKeyException(expiresAt, "Sessions with given expires at does not exist")); - } - - public async Task> GetByRevokedAsync(bool isRevoked) - { - return await _context.UserSessions - .AsNoTracking() - .Where(session => session.IsRevoked == isRevoked) - .ToListOrThrowIfEmpty(new NotFoundByKeyException(isRevoked, "Sessions is revoked does not exist")); - } - - public async Task GetByHashedRefreshTokenAsync(string hash) - { - return await _context.UserSessions - .AsNoTracking() - .FirstOrDefaultAsync(session => session.RefreshTokenHash == hash) - ?? throw new NotFoundByKeyException(hash, "Session with given refresh token does not exist"); - } - - public async Task AddAsync(UserSession userSession) - { - try - { - _context.UserSessions.Add(userSession); - await _context.SaveChangesAsync(); - } - catch (Exception ex) - { - throw new AdditionException("Failed to add user session", ex); - } - } - - public async Task UpdateAsync(UserSession userSession) - { - try - { - //_validator.Validate(user); - - var rowsAffected = await _context.UserSessions - .Where(u => u.Id == userSession.Id) - .ExecuteUpdateAsync(u => u - .SetProperty(a => a.UserId, userSession.UserId) - .SetProperty(u => u.RefreshTokenHash, userSession.RefreshTokenHash) - .SetProperty(u => u.DeviceInfo, userSession.DeviceInfo) - .SetProperty(u => u.ExpiresAt, userSession.ExpiresAt) - .SetProperty(u => u.IsRevoked, userSession.IsRevoked) - ); - - if (rowsAffected == 0) - throw new UpdateException($"Not found user session by given id {userSession.Id}"); - } - catch (Exception ex) - { - throw new UpdateException($"Error when updating the user session {userSession.Id}", ex); - } - } - - public async Task RemoveAsync(Guid sessionId) - { - try - { - var result = await GetByIdAsync(sessionId); - - _context.UserSessions.Remove(result); - await _context.SaveChangesAsync(); - } - catch (NotFoundByKeyException ex) - { - throw new RemoveException($"Not found session by given id {sessionId}", ex); - } - catch (Exception ex) - { - throw new RemoveException("Error when removing the session", ex); - } - } - - public async Task RemoveByUserIdAsync(Guid userId) - { - try - { - var result = await GetByUserIdAsync(userId); - - _context.UserSessions.RemoveRange(result); - await _context.SaveChangesAsync(); - } - catch (NotFoundByKeyException ex) - { - throw new RemoveException($"Not found user sessions by given user id {userId}", ex); - } - catch (Exception ex) - { - throw new RemoveException("Error when removing the user sessions", ex); - } - } - - public bool Exist(Guid sessionId) - { - return _context.UserSessions.Any(session => session.Id == sessionId); - } - - public bool Exist(string hashedToken) - { - return _context.UserSessions.Any(session => session.RefreshTokenHash == hashedToken); - } - - public bool Exist(UserSession userSession) - { - return _context.UserSessions.Any(session => session.Id == userSession.Id && - session.RefreshTokenHash == userSession.RefreshTokenHash && - session.IsRevoked == userSession.IsRevoked && - session.CreatedAt == userSession.CreatedAt && - session.ExpiresAt == userSession.ExpiresAt && - session.DeviceInfo == userSession.DeviceInfo && - session.UserId == userSession.UserId); - } -} \ No newline at end of file diff --git a/Govor.Data/Repositories/UsersRepository.cs b/Govor.Data/Repositories/UsersRepository.cs deleted file mode 100644 index 6cab480..0000000 --- a/Govor.Data/Repositories/UsersRepository.cs +++ /dev/null @@ -1,222 +0,0 @@ -using Govor.Core.Infrastructure.Extensions; -using Govor.Core.Infrastructure.Validators; -using Govor.Core.Models; -using Govor.Core.Models.Users; -using Govor.Core.Repositories.Users; -using Govor.Data.Repositories.Exceptions; -using Microsoft.EntityFrameworkCore; - -namespace Govor.Data.Repositories; - -public class UsersRepository : IUsersRepository -{ - private GovorDbContext _context; - private IObjectValidator _validator; - public UsersRepository(GovorDbContext context, IObjectValidator validator) - { - _context = context; - _validator = validator; - } - - public async Task> GetAllAsync() - { - return await _context.Users - .AsNoTracking() - .Include(u => u.Invite) - .Include(u => u.ReceivedFriendRequests) - .Include(u => u.SentFriendRequests) - .AsSplitQuery() - .ToListOrThrowIfEmpty(new NotFoundException("Users in Database not exists")); - } - - public async Task FindByIdAsync(Guid id) - { - if(id == Guid.Empty) - throw new ArgumentException("Id must not be empty", nameof(id)); - - return await _context.Users - .AsNoTracking() - .Include(u => u.Invite) - .Include(u => u.ReceivedFriendRequests) - .Include(u => u.SentFriendRequests) - .AsSplitQuery() - .FirstOrDefaultAsync(x => x.Id == id) - ?? throw new NotFoundByKeyException(id, "User with given id does not exist"); - } - - public async Task> FindByRangeIdAsync(IEnumerable ids) - { - if (ids is null || !ids.Any()) - throw new ArgumentException("Ids must not be empty", nameof(ids)); - - return await _context.Users - .AsNoTracking() - .Where(x => ids.Contains(x.Id)) - .Include(u => u.Invite) - .Include(u => u.ReceivedFriendRequests) - .Include(u => u.SentFriendRequests) - .AsSplitQuery() - .ToListOrThrowIfEmpty(new NotFoundByKeyException>(ids,"Users with given ids not found")); - } - - public async Task FindByUsernameAsync(string username) - { - if(username is null || username == string.Empty) - throw new ArgumentNullException(username, "Username cannot be empty"); - - return await _context.Users - .AsNoTracking() - .Include(u => u.Invite) - .Include(u => u.ReceivedFriendRequests) - .Include(u => u.SentFriendRequests) - .AsSplitQuery() - .FirstOrDefaultAsync(x => x.Username == username) - ?? throw new NotFoundByKeyException(username, "User with given username does not exist"); - } - - public async Task> SearchPotentialFriendsAsync(Guid currentUserId, string query) - { - return await _context.Users - .AsNoTracking() - .AsSplitQuery() - .Where(u => u.Id != currentUserId && - u.Username.ToLower().Contains(query.ToLower()) && - !_context.Friendships.Any(f => - ((f.RequesterId == currentUserId && f.AddresseeId == u.Id) || - (f.RequesterId == u.Id && f.AddresseeId == currentUserId)) && f.Status != FriendshipStatus.Rejected)) - .Take(7) - .OrderBy(u => u.Username) - .ToListOrThrowIfEmpty(new NotFoundByKeyException<(string, Guid)>((query, currentUserId), $"Users with given query for user {currentUserId} not found")); - } - - - public async Task> FindByRangeUsernamesAsync(IEnumerable usernames) - { - if (usernames is null || !usernames.Any()) - throw new ArgumentException("Usernames must not be empty", nameof(usernames)); - - return await _context.Users - .AsNoTracking() - .Where(x => usernames.Contains(x.Username)) - .Include(u => u.Invite) - .Include(u => u.ReceivedFriendRequests) - .Include(u => u.SentFriendRequests) - .AsSplitQuery() - .ToListOrThrowIfEmpty(new NotFoundByKeyException>(usernames, "Users with given usernames not found")); - } - - public async Task> FindUsersByCreatedDateAsync(DateOnly createdDate) - { - if(createdDate == DateOnly.MinValue) - throw new ArgumentException("Created date cannot be earlier than MinValue", nameof(createdDate)); - - return await _context.Users - .AsNoTracking() - .Where(u => createdDate == u.CreatedOn) - .Include(u => u.Invite) - .Include(u => u.ReceivedFriendRequests) - .Include(u => u.SentFriendRequests) - .AsSplitQuery() - .ToListOrThrowIfEmpty(new NotFoundByKeyException(createdDate, "Users with given created date do not exist")); - } - - public async Task AddAsync(User user) - { - try - { - _validator.Validate(user); - - _context.Users.Add(user); - await _context.SaveChangesAsync(); - } - catch (InvalidObjectException ex) - { - throw new AdditionException("User with given data invalid", ex); - } - catch (Exception ex) - { - throw new AdditionException("Cannot add user", ex); - } - } - - // TODO: Test this block - public async Task UpdateAsync(User user) - { - try - { - _validator.Validate(user); - - var rowsAffected = await _context.Users - .Where(u => u.Id == user.Id) - .ExecuteUpdateAsync(u => u - .SetProperty(a => a.Username, user.Username) - .SetProperty(u => u.IconId, user.IconId) - .SetProperty(u => u.Description, user.Description) - .SetProperty(u => u.CreatedOn, user.CreatedOn) - .SetProperty(u => u.PasswordHash, user.PasswordHash) - .SetProperty(u => u.WasOnline, user.WasOnline) - .SetProperty(u => u.InviteId, user.InviteId) - ); - - if (rowsAffected == 0) - throw new UpdateException($"Not found user by given id {user.Id}"); - } - catch (Exception ex) - { - throw new UpdateException($"Error when updating the user {user.Id}", ex); - } - } - - public async Task RemoveAsync(User user) - { - try - { - _validator.Validate(user); - await RemoveAsync(user.Id); - } - catch (InvalidObjectException ex) - { - throw new RemoveException("User with given data invalid", ex); - } - } - - public async Task RemoveAsync(Guid userId) - { - try - { - var result = await FindByIdAsync(userId); - - _context.Users.Remove(result); - await _context.SaveChangesAsync(); - } - catch (NotFoundByKeyException ex) - { - throw new RemoveException($"Not found user by given id {userId}", ex); - } - catch (Exception ex) - { - throw new RemoveException("Error when removing the user", ex); - } - } - - public Task ExistsAsync(User user) - { - _validator.Validate(user); - - return _context.Users.AnyAsync(u => - u.Id == user.Id && - u.Username == user.Username && - u.PasswordHash == user.PasswordHash - ); - } - - public Task ExistsByIdAsync(Guid id) - { - return _context.Users.AnyAsync(u => u.Id == id); - } - - public Task ExistsUsernameAsync(string username) - { - return _context.Users.AnyAsync(u => u.Username == username); - } -} \ No newline at end of file diff --git a/Govor.Domain/Common/Constants/InvitationConstants.cs b/Govor.Domain/Common/Constants/InvitationConstants.cs new file mode 100644 index 0000000..2fe4161 --- /dev/null +++ b/Govor.Domain/Common/Constants/InvitationConstants.cs @@ -0,0 +1,6 @@ +namespace Govor.Domain.Common.Constants; + +public class InvitationConstants +{ + public const int MIN_INVITATION_LENGTH = 5; +} \ No newline at end of file diff --git a/Govor.Domain/Common/Constants/UserConstants.cs b/Govor.Domain/Common/Constants/UserConstants.cs new file mode 100644 index 0000000..cc8ebde --- /dev/null +++ b/Govor.Domain/Common/Constants/UserConstants.cs @@ -0,0 +1,7 @@ +namespace Govor.Domain.Common.Constants; + +public class UserConstants +{ + public const int MAX_LENGHT_OF_NAME = 44; + public const int MIN_LENGHT_OF_NAME = 4; +} \ No newline at end of file diff --git a/Govor.Domain/Common/Error.cs b/Govor.Domain/Common/Error.cs new file mode 100644 index 0000000..e49d9f4 --- /dev/null +++ b/Govor.Domain/Common/Error.cs @@ -0,0 +1,9 @@ +namespace Govor.Domain.Common; + + +public record Error(string Code, string Message) +{ + public static readonly Error None = new(string.Empty, string.Empty); + public static readonly Error Null = new("NULL", "Value cannot be null."); + public override string ToString() => $"{Code}: {Message}"; +} \ No newline at end of file diff --git a/Govor.Core/Infrastructure/Extensions/QueryableExtensions.cs b/Govor.Domain/Common/Extensions/QueryableExtensions.cs similarity index 86% rename from Govor.Core/Infrastructure/Extensions/QueryableExtensions.cs rename to Govor.Domain/Common/Extensions/QueryableExtensions.cs index e380f41..a87e92c 100644 --- a/Govor.Core/Infrastructure/Extensions/QueryableExtensions.cs +++ b/Govor.Domain/Common/Extensions/QueryableExtensions.cs @@ -1,6 +1,6 @@ using Microsoft.EntityFrameworkCore; -namespace Govor.Core.Infrastructure.Extensions; +namespace Govor.Domain.Common.Extensions; public static class QueryableExtensions { diff --git a/Govor.Domain/Common/Result.cs b/Govor.Domain/Common/Result.cs new file mode 100644 index 0000000..cfcf3a1 --- /dev/null +++ b/Govor.Domain/Common/Result.cs @@ -0,0 +1,49 @@ +namespace Govor.Domain.Common; + +public class Result +{ + protected Result(bool isSuccess, Error error) + { + if (isSuccess && error != Error.None || !isSuccess && error == Error.None) + { + throw new ArgumentException("Invalid error state", nameof(error)); + } + + IsSuccess = isSuccess; + Error = error; + } + + public bool IsSuccess { get; } + public bool IsFailure => !IsSuccess; + public Error Error { get; } + + public static Result Success() => new(true, Error.None); + public static Result Failure(Error error) => new(false, error); + + public static Result Failure(Exception ex) => new(false, new Error(ex.GetType().Name, ex.Message)); + + public static implicit operator Result(Error error) => Failure(error); +} + +public class Result : Result +{ + private readonly T? _value; + + private Result(T? value, bool isSuccess, Error error) : base(isSuccess, error) + { + _value = value; + } + + public T Value => IsSuccess + ? _value! + : throw new InvalidOperationException("The value of a failure result cannot be accessed."); + + public static Result Success(T value) => new(value, true, Error.None); + public static new Result Failure(Error error) => new(default, false, error); + public static new Result Failure(Exception ex) => new(default, false, new Error(ex.GetType().Name, ex.Message)); + + public static implicit operator Result(T value) => Success(value); + + public static implicit operator Result(Error error) => Failure(error); + public static implicit operator T(Result result) => result.Value; +} \ No newline at end of file diff --git a/Govor.Data/Configurations/AdminConfiguration.cs b/Govor.Domain/Configurations/AdminConfiguration.cs similarity index 83% rename from Govor.Data/Configurations/AdminConfiguration.cs rename to Govor.Domain/Configurations/AdminConfiguration.cs index 7f0dfad..603b401 100644 --- a/Govor.Data/Configurations/AdminConfiguration.cs +++ b/Govor.Domain/Configurations/AdminConfiguration.cs @@ -1,8 +1,8 @@ -using Govor.Core.Models.Users; +using Govor.Domain.Models.Users; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; -namespace Govor.Data.Configurations; +namespace Govor.Domain.Configurations; public class AdminConfiguration : IEntityTypeConfiguration { diff --git a/Govor.Data/Configurations/ChatGroupConfigurator.cs b/Govor.Domain/Configurations/ChatGroupConfigurator.cs similarity index 92% rename from Govor.Data/Configurations/ChatGroupConfigurator.cs rename to Govor.Domain/Configurations/ChatGroupConfigurator.cs index f2f5c90..a628bac 100644 --- a/Govor.Data/Configurations/ChatGroupConfigurator.cs +++ b/Govor.Domain/Configurations/ChatGroupConfigurator.cs @@ -1,8 +1,8 @@ -using Govor.Core.Models; +using Govor.Domain.Models; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; -namespace Govor.Data.Configurations; +namespace Govor.Domain.Configurations; public class ChatGroupConfigurator : IEntityTypeConfiguration { diff --git a/Govor.Data/Configurations/FriendshipConfiguration.cs b/Govor.Domain/Configurations/FriendshipConfiguration.cs similarity index 91% rename from Govor.Data/Configurations/FriendshipConfiguration.cs rename to Govor.Domain/Configurations/FriendshipConfiguration.cs index bd2c17b..20cfb2e 100644 --- a/Govor.Data/Configurations/FriendshipConfiguration.cs +++ b/Govor.Domain/Configurations/FriendshipConfiguration.cs @@ -1,8 +1,8 @@ -using Govor.Core.Models; +using Govor.Domain.Models; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; -namespace Govor.Data.Configurations; +namespace Govor.Domain.Configurations; public class FriendshipConfiguration : IEntityTypeConfiguration { diff --git a/Govor.Data/Configurations/GroupAdminsConfiguration.cs b/Govor.Domain/Configurations/GroupAdminsConfiguration.cs similarity index 85% rename from Govor.Data/Configurations/GroupAdminsConfiguration.cs rename to Govor.Domain/Configurations/GroupAdminsConfiguration.cs index 92866ff..c5a1760 100644 --- a/Govor.Data/Configurations/GroupAdminsConfiguration.cs +++ b/Govor.Domain/Configurations/GroupAdminsConfiguration.cs @@ -1,8 +1,8 @@ -using Govor.Core.Models; +using Govor.Domain.Models; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; -namespace Govor.Data.Configurations; +namespace Govor.Domain.Configurations; public class GroupAdminsConfiguration : IEntityTypeConfiguration { diff --git a/Govor.Data/Configurations/GroupInvitationConfiguration.cs b/Govor.Domain/Configurations/GroupInvitationConfiguration.cs similarity index 92% rename from Govor.Data/Configurations/GroupInvitationConfiguration.cs rename to Govor.Domain/Configurations/GroupInvitationConfiguration.cs index 4d92246..9fa15fa 100644 --- a/Govor.Data/Configurations/GroupInvitationConfiguration.cs +++ b/Govor.Domain/Configurations/GroupInvitationConfiguration.cs @@ -1,8 +1,8 @@ -using Govor.Core.Models; +using Govor.Domain.Models; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; -namespace Govor.Data.Configurations; +namespace Govor.Domain.Configurations; public class GroupInvitationConfiguration : IEntityTypeConfiguration { diff --git a/Govor.Data/Configurations/GroupMembershipConfiguration.cs b/Govor.Domain/Configurations/GroupMembershipConfiguration.cs similarity index 64% rename from Govor.Data/Configurations/GroupMembershipConfiguration.cs rename to Govor.Domain/Configurations/GroupMembershipConfiguration.cs index fb16926..0edf803 100644 --- a/Govor.Data/Configurations/GroupMembershipConfiguration.cs +++ b/Govor.Domain/Configurations/GroupMembershipConfiguration.cs @@ -1,8 +1,8 @@ -using Govor.Core.Models; +using Govor.Domain.Models; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; -namespace Govor.Data.Configurations; +namespace Govor.Domain.Configurations; public class GroupMembershipConfiguration : IEntityTypeConfiguration { @@ -14,10 +14,16 @@ public class GroupMembershipConfiguration : IEntityTypeConfiguration e.GroupId).IsRequired(); builder.Property(e => e.InvitationId).IsRequired(false); - // Optional: можно добавить навигацию к GroupInvitation + builder.HasOne(e => e.ChatGroup) + .WithMany() + .HasForeignKey(e => e.GroupId) + .OnDelete(DeleteBehavior.Cascade); + + // Optional: настройка связи с GroupInvitation builder.HasOne() .WithMany() .HasForeignKey(e => e.InvitationId) .OnDelete(DeleteBehavior.SetNull); + } } \ No newline at end of file diff --git a/Govor.Data/Configurations/InvitationConfiguration.cs b/Govor.Domain/Configurations/InvitationConfiguration.cs similarity index 87% rename from Govor.Data/Configurations/InvitationConfiguration.cs rename to Govor.Domain/Configurations/InvitationConfiguration.cs index 540032a..2615523 100644 --- a/Govor.Data/Configurations/InvitationConfiguration.cs +++ b/Govor.Domain/Configurations/InvitationConfiguration.cs @@ -1,8 +1,8 @@ -using Govor.Core.Models; +using Govor.Domain.Models; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; -namespace Govor.Data.Configurations; +namespace Govor.Domain.Configurations; public class InvitationConfiguration : IEntityTypeConfiguration { diff --git a/Govor.Data/Configurations/MediaAttachmentsConfiguration.cs b/Govor.Domain/Configurations/MediaAttachmentsConfiguration.cs similarity index 89% rename from Govor.Data/Configurations/MediaAttachmentsConfiguration.cs rename to Govor.Domain/Configurations/MediaAttachmentsConfiguration.cs index 26fcca3..07c9f68 100644 --- a/Govor.Data/Configurations/MediaAttachmentsConfiguration.cs +++ b/Govor.Domain/Configurations/MediaAttachmentsConfiguration.cs @@ -1,8 +1,8 @@ -using Govor.Core.Models.Messages; +using Govor.Domain.Models.Messages; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; -namespace Govor.Data.Configurations; +namespace Govor.Domain.Configurations; public class MediaAttachmentsConfiguration : IEntityTypeConfiguration { diff --git a/Govor.Data/Configurations/MediaFileConfiguration.cs b/Govor.Domain/Configurations/MediaFileConfiguration.cs similarity index 91% rename from Govor.Data/Configurations/MediaFileConfiguration.cs rename to Govor.Domain/Configurations/MediaFileConfiguration.cs index 452587f..5ff97aa 100644 --- a/Govor.Data/Configurations/MediaFileConfiguration.cs +++ b/Govor.Domain/Configurations/MediaFileConfiguration.cs @@ -1,8 +1,8 @@ -using Govor.Core.Models; +using Govor.Domain.Models; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; -namespace Govor.Data.Configurations; +namespace Govor.Domain.Configurations; public class MediaFileConfiguration : IEntityTypeConfiguration { diff --git a/Govor.Data/Configurations/MessageReactionConfiguration.cs b/Govor.Domain/Configurations/MessageReactionConfiguration.cs similarity index 90% rename from Govor.Data/Configurations/MessageReactionConfiguration.cs rename to Govor.Domain/Configurations/MessageReactionConfiguration.cs index 77ca4f2..d606070 100644 --- a/Govor.Data/Configurations/MessageReactionConfiguration.cs +++ b/Govor.Domain/Configurations/MessageReactionConfiguration.cs @@ -1,8 +1,8 @@ -using Govor.Core.Models.Messages; +using Govor.Domain.Models.Messages; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; -namespace Govor.Data.Configurations; +namespace Govor.Domain.Configurations; public class MessageReactionConfiguration : IEntityTypeConfiguration { diff --git a/Govor.Data/Configurations/MessageViewConfiguration.cs b/Govor.Domain/Configurations/MessageViewConfiguration.cs similarity index 85% rename from Govor.Data/Configurations/MessageViewConfiguration.cs rename to Govor.Domain/Configurations/MessageViewConfiguration.cs index 04d5774..530bb7e 100644 --- a/Govor.Data/Configurations/MessageViewConfiguration.cs +++ b/Govor.Domain/Configurations/MessageViewConfiguration.cs @@ -1,8 +1,8 @@ -using Govor.Core.Models.Messages; +using Govor.Domain.Models.Messages; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; -namespace Govor.Data.Configurations; +namespace Govor.Domain.Configurations; public class MessageViewConfiguration : IEntityTypeConfiguration { diff --git a/Govor.Data/Configurations/MessagesConfiguration.cs b/Govor.Domain/Configurations/MessagesConfiguration.cs similarity index 92% rename from Govor.Data/Configurations/MessagesConfiguration.cs rename to Govor.Domain/Configurations/MessagesConfiguration.cs index 5693296..69d3cf8 100644 --- a/Govor.Data/Configurations/MessagesConfiguration.cs +++ b/Govor.Domain/Configurations/MessagesConfiguration.cs @@ -1,8 +1,8 @@ -using Govor.Core.Models.Messages; +using Govor.Domain.Models.Messages; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; -namespace Govor.Data.Configurations; +namespace Govor.Domain.Configurations; public class MessagesConfiguration : IEntityTypeConfiguration { diff --git a/Govor.Data/Configurations/OneTimePreKeyConfiguration.cs b/Govor.Domain/Configurations/OneTimePreKeyConfiguration.cs similarity index 92% rename from Govor.Data/Configurations/OneTimePreKeyConfiguration.cs rename to Govor.Domain/Configurations/OneTimePreKeyConfiguration.cs index 0b3c347..a1a91c0 100644 --- a/Govor.Data/Configurations/OneTimePreKeyConfiguration.cs +++ b/Govor.Domain/Configurations/OneTimePreKeyConfiguration.cs @@ -1,8 +1,8 @@ -using Govor.Core.Models.Users.Crypto; +using Govor.Domain.Models.Users.Crypto; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; -namespace Govor.Data.Configurations; +namespace Govor.Domain.Configurations; public class OneTimePreKeyConfiguration : IEntityTypeConfiguration { diff --git a/Govor.Data/Configurations/PrivacyRuleEntityConfiguration.cs b/Govor.Domain/Configurations/PrivacyRuleEntityConfiguration.cs similarity index 90% rename from Govor.Data/Configurations/PrivacyRuleEntityConfiguration.cs rename to Govor.Domain/Configurations/PrivacyRuleEntityConfiguration.cs index 226fb6f..443faf3 100644 --- a/Govor.Data/Configurations/PrivacyRuleEntityConfiguration.cs +++ b/Govor.Domain/Configurations/PrivacyRuleEntityConfiguration.cs @@ -1,9 +1,8 @@ -using Govor.Core.Models.Users; +using Govor.Domain.Models.Users; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; -namespace Govor.Data.Configurations; - +namespace Govor.Domain.Configurations; public class PrivacyRuleEntityConfiguration : IEntityTypeConfiguration { diff --git a/Govor.Data/Configurations/PrivacyUserSettingsConfiguration.cs b/Govor.Domain/Configurations/PrivacyUserSettingsConfiguration.cs similarity index 92% rename from Govor.Data/Configurations/PrivacyUserSettingsConfiguration.cs rename to Govor.Domain/Configurations/PrivacyUserSettingsConfiguration.cs index 7582db7..48fecf7 100644 --- a/Govor.Data/Configurations/PrivacyUserSettingsConfiguration.cs +++ b/Govor.Domain/Configurations/PrivacyUserSettingsConfiguration.cs @@ -1,8 +1,8 @@ -using Govor.Core.Models.Users; +using Govor.Domain.Models.Users; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; -namespace Govor.Data.Configurations; +namespace Govor.Domain.Configurations; public class PrivacyUserSettingsConfiguration : IEntityTypeConfiguration { diff --git a/Govor.Data/Configurations/PrivateChatsConfiguration.cs b/Govor.Domain/Configurations/PrivateChatsConfiguration.cs similarity index 81% rename from Govor.Data/Configurations/PrivateChatsConfiguration.cs rename to Govor.Domain/Configurations/PrivateChatsConfiguration.cs index 7c42412..ba48a30 100644 --- a/Govor.Data/Configurations/PrivateChatsConfiguration.cs +++ b/Govor.Domain/Configurations/PrivateChatsConfiguration.cs @@ -1,8 +1,8 @@ -using Govor.Core.Models; +using Govor.Domain.Models; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; -namespace Govor.Data.Configurations; +namespace Govor.Domain.Configurations; public class PrivateChatsConfiguration : IEntityTypeConfiguration { diff --git a/Govor.Data/Configurations/SignedPreKeyConfiguration.cs b/Govor.Domain/Configurations/SignedPreKeyConfiguration.cs similarity index 90% rename from Govor.Data/Configurations/SignedPreKeyConfiguration.cs rename to Govor.Domain/Configurations/SignedPreKeyConfiguration.cs index f28e1c4..383b86a 100644 --- a/Govor.Data/Configurations/SignedPreKeyConfiguration.cs +++ b/Govor.Domain/Configurations/SignedPreKeyConfiguration.cs @@ -1,8 +1,8 @@ -using Govor.Core.Models.Users.Crypto; +using Govor.Domain.Models.Users.Crypto; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; -namespace Govor.Data.Configurations; +namespace Govor.Domain.Configurations; public class SignedPreKeyConfiguration : IEntityTypeConfiguration { diff --git a/Govor.Data/Configurations/UserConfiguration.cs b/Govor.Domain/Configurations/UserConfiguration.cs similarity index 92% rename from Govor.Data/Configurations/UserConfiguration.cs rename to Govor.Domain/Configurations/UserConfiguration.cs index 98e4dd6..1a34014 100644 --- a/Govor.Data/Configurations/UserConfiguration.cs +++ b/Govor.Domain/Configurations/UserConfiguration.cs @@ -1,8 +1,8 @@ -using Govor.Core.Models.Users; +using Govor.Domain.Models.Users; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; -namespace Govor.Data.Configurations; +namespace Govor.Domain.Configurations; public class UserConfiguration : IEntityTypeConfiguration { diff --git a/Govor.Data/Configurations/UserCryptoSessionConfiguration.cs b/Govor.Domain/Configurations/UserCryptoSessionConfiguration.cs similarity index 93% rename from Govor.Data/Configurations/UserCryptoSessionConfiguration.cs rename to Govor.Domain/Configurations/UserCryptoSessionConfiguration.cs index 73a8d73..a326bcd 100644 --- a/Govor.Data/Configurations/UserCryptoSessionConfiguration.cs +++ b/Govor.Domain/Configurations/UserCryptoSessionConfiguration.cs @@ -1,8 +1,8 @@ -using Govor.Core.Models.Users.Crypto; +using Govor.Domain.Models.Users.Crypto; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; -namespace Govor.Data.Configurations; +namespace Govor.Domain.Configurations; public class UserCryptoSessionConfiguration : IEntityTypeConfiguration { diff --git a/Govor.Data/Configurations/UserPushTokenConfiguration.cs b/Govor.Domain/Configurations/UserPushTokenConfiguration.cs similarity index 91% rename from Govor.Data/Configurations/UserPushTokenConfiguration.cs rename to Govor.Domain/Configurations/UserPushTokenConfiguration.cs index 203408a..51657ff 100644 --- a/Govor.Data/Configurations/UserPushTokenConfiguration.cs +++ b/Govor.Domain/Configurations/UserPushTokenConfiguration.cs @@ -1,8 +1,8 @@ -using Govor.Core.Models.Users; +using Govor.Domain.Models.Users; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; -namespace Govor.Data.Configurations; +namespace Govor.Domain.Configurations; public class UserPushTokenConfiguration : IEntityTypeConfiguration { diff --git a/Govor.Data/Configurations/UserSessionConfiguration.cs b/Govor.Domain/Configurations/UserSessionConfiguration.cs similarity index 76% rename from Govor.Data/Configurations/UserSessionConfiguration.cs rename to Govor.Domain/Configurations/UserSessionConfiguration.cs index 2dd82d2..67a52c4 100644 --- a/Govor.Data/Configurations/UserSessionConfiguration.cs +++ b/Govor.Domain/Configurations/UserSessionConfiguration.cs @@ -1,19 +1,15 @@ -using Govor.Core.Models; -using Govor.Core.Models.Users; -using Govor.Core.Models.Users.Crypto; +using Govor.Domain.Models.Users; +using Govor.Domain.Models.Users.Crypto; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; -namespace Govor.Data.Configurations; +namespace Govor.Domain.Configurations; public class UserSessionConfiguration : IEntityTypeConfiguration { public void Configure(EntityTypeBuilder builder) { builder.HasKey(us => us.Id); - - builder.HasIndex(us => us.Id) - .IsUnique(); builder.HasIndex(us => us.UserId); @@ -25,15 +21,17 @@ public class UserSessionConfiguration : IEntityTypeConfiguration builder.Property(us => us.DeviceInfo) .HasMaxLength(256); - - builder.HasOne() + + builder.HasOne(us => us.User) .WithMany() .HasForeignKey(us => us.UserId) - .OnDelete(DeleteBehavior.Cascade); + .IsRequired() + .OnDelete(DeleteBehavior.Cascade); builder.HasOne(e => e.CryptoSession) .WithOne(e => e.UserSession) .HasForeignKey(e => e.UserSessionId) + .IsRequired() .OnDelete(DeleteBehavior.Cascade); } } \ No newline at end of file diff --git a/Govor.Data/Govor.Data.csproj b/Govor.Domain/Govor.Domain.csproj similarity index 83% rename from Govor.Data/Govor.Data.csproj rename to Govor.Domain/Govor.Domain.csproj index 036ffa3..0c11df6 100644 --- a/Govor.Data/Govor.Data.csproj +++ b/Govor.Domain/Govor.Domain.csproj @@ -11,9 +11,4 @@ - - - - - diff --git a/Govor.Core/GovorCoreException.cs b/Govor.Domain/GovorCoreException.cs similarity index 93% rename from Govor.Core/GovorCoreException.cs rename to Govor.Domain/GovorCoreException.cs index e109d3d..a37e157 100644 --- a/Govor.Core/GovorCoreException.cs +++ b/Govor.Domain/GovorCoreException.cs @@ -1,4 +1,4 @@ -namespace Govor.Core; +namespace Govor.Domain; /// /// Base exception class for Govor solutions diff --git a/Govor.Data/GovorDbContext.cs b/Govor.Domain/GovorDbContext.cs similarity index 93% rename from Govor.Data/GovorDbContext.cs rename to Govor.Domain/GovorDbContext.cs index d811a88..ecc436a 100644 --- a/Govor.Data/GovorDbContext.cs +++ b/Govor.Domain/GovorDbContext.cs @@ -1,11 +1,11 @@ -using Govor.Core.Models; -using Govor.Core.Models.Messages; -using Govor.Core.Models.Users; -using Govor.Core.Models.Users.Crypto; -using Govor.Data.Configurations; +using Govor.Domain.Models; +using Govor.Domain.Models.Messages; +using Govor.Domain.Models.Users; +using Govor.Domain.Models.Users.Crypto; +using Govor.Domain.Configurations; using Microsoft.EntityFrameworkCore; -namespace Govor.Data; +namespace Govor.Domain; public class GovorDbContext(DbContextOptions options) : DbContext(options) { diff --git a/Govor.Data/Migrations/20260301120522_FixPushTokensIndexs.Designer.cs b/Govor.Domain/Migrations/20260716110338_InitialCreate.Designer.cs similarity index 81% rename from Govor.Data/Migrations/20260301120522_FixPushTokensIndexs.Designer.cs rename to Govor.Domain/Migrations/20260716110338_InitialCreate.Designer.cs index c7439d1..6cfef7d 100644 --- a/Govor.Data/Migrations/20260301120522_FixPushTokensIndexs.Designer.cs +++ b/Govor.Domain/Migrations/20260716110338_InitialCreate.Designer.cs @@ -1,6 +1,6 @@ // using System; -using Govor.Data; +using Govor.Domain; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; @@ -9,11 +9,11 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; #nullable disable -namespace Govor.Data.Migrations +namespace Govor.Domain.Migrations { [DbContext(typeof(GovorDbContext))] - [Migration("20260301120522_FixPushTokensIndexs")] - partial class FixPushTokensIndexs + [Migration("20260716110338_InitialCreate")] + partial class InitialCreate { /// protected override void BuildTargetModel(ModelBuilder modelBuilder) @@ -25,7 +25,7 @@ namespace Govor.Data.Migrations NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - modelBuilder.Entity("Govor.Core.Models.ChatGroup", b => + modelBuilder.Entity("Govor.Domain.Models.ChatGroup", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -55,7 +55,7 @@ namespace Govor.Data.Migrations b.ToTable("ChatGroups"); }); - modelBuilder.Entity("Govor.Core.Models.Friendship", b => + modelBuilder.Entity("Govor.Domain.Models.Friendship", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -79,7 +79,7 @@ namespace Govor.Data.Migrations b.ToTable("Friendships"); }); - modelBuilder.Entity("Govor.Core.Models.GroupAdmins", b => + modelBuilder.Entity("Govor.Domain.Models.GroupAdmins", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -98,7 +98,7 @@ namespace Govor.Data.Migrations b.ToTable("GroupAdmins"); }); - modelBuilder.Entity("Govor.Core.Models.GroupInvitation", b => + modelBuilder.Entity("Govor.Domain.Models.GroupInvitation", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -138,12 +138,15 @@ namespace Govor.Data.Migrations b.ToTable("GroupInvitations"); }); - modelBuilder.Entity("Govor.Core.Models.GroupMembership", b => + modelBuilder.Entity("Govor.Domain.Models.GroupMembership", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("uuid"); + b.Property("ChatGroupId") + .HasColumnType("uuid"); + b.Property("GroupId") .HasColumnType("uuid"); @@ -161,6 +164,8 @@ namespace Govor.Data.Migrations b.HasKey("Id"); + b.HasIndex("ChatGroupId"); + b.HasIndex("GroupId"); b.HasIndex("InvitationId"); @@ -168,7 +173,7 @@ namespace Govor.Data.Migrations b.ToTable("GroupMemberships"); }); - modelBuilder.Entity("Govor.Core.Models.Invitation", b => + modelBuilder.Entity("Govor.Domain.Models.Invitation", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -202,7 +207,7 @@ namespace Govor.Data.Migrations b.ToTable("Invitations"); }); - modelBuilder.Entity("Govor.Core.Models.MediaFile", b => + modelBuilder.Entity("Govor.Domain.Models.MediaFile", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -238,7 +243,7 @@ namespace Govor.Data.Migrations b.ToTable("MediaFiles"); }); - modelBuilder.Entity("Govor.Core.Models.Messages.MediaAttachments", b => + modelBuilder.Entity("Govor.Domain.Models.Messages.MediaAttachments", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -259,7 +264,7 @@ namespace Govor.Data.Migrations b.ToTable("MediaAttachments"); }); - modelBuilder.Entity("Govor.Core.Models.Messages.Message", b => + modelBuilder.Entity("Govor.Domain.Models.Messages.Message", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -307,7 +312,7 @@ namespace Govor.Data.Migrations b.ToTable("Messages"); }); - modelBuilder.Entity("Govor.Core.Models.Messages.MessageReaction", b => + modelBuilder.Entity("Govor.Domain.Models.Messages.MessageReaction", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -337,7 +342,7 @@ namespace Govor.Data.Migrations b.ToTable("MessageReactions"); }); - modelBuilder.Entity("Govor.Core.Models.Messages.MessageView", b => + modelBuilder.Entity("Govor.Domain.Models.Messages.MessageView", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -360,7 +365,7 @@ namespace Govor.Data.Migrations b.ToTable("MessageViews"); }); - modelBuilder.Entity("Govor.Core.Models.PrivateChat", b => + modelBuilder.Entity("Govor.Domain.Models.PrivateChat", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -377,7 +382,7 @@ namespace Govor.Data.Migrations b.ToTable("PrivateChats"); }); - modelBuilder.Entity("Govor.Core.Models.Users.Admin", b => + modelBuilder.Entity("Govor.Domain.Models.Users.Admin", b => { b.Property("UserId") .HasColumnType("uuid"); @@ -387,7 +392,7 @@ namespace Govor.Data.Migrations b.ToTable("Admins"); }); - modelBuilder.Entity("Govor.Core.Models.Users.Crypto.OneTimePreKey", b => + modelBuilder.Entity("Govor.Domain.Models.Users.Crypto.OneTimePreKey", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -417,7 +422,7 @@ namespace Govor.Data.Migrations b.ToTable("OneTimePreKeys"); }); - modelBuilder.Entity("Govor.Core.Models.Users.Crypto.SignedPreKey", b => + modelBuilder.Entity("Govor.Domain.Models.Users.Crypto.SignedPreKey", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -442,7 +447,7 @@ namespace Govor.Data.Migrations b.ToTable("SignedPreKeys"); }); - modelBuilder.Entity("Govor.Core.Models.Users.Crypto.UserCryptoSession", b => + modelBuilder.Entity("Govor.Domain.Models.Users.Crypto.UserCryptoSession", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -463,7 +468,7 @@ namespace Govor.Data.Migrations b.ToTable("UserCryptoSessions"); }); - modelBuilder.Entity("Govor.Core.Models.Users.User", b => + modelBuilder.Entity("Govor.Domain.Models.Users.User", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -509,7 +514,7 @@ namespace Govor.Data.Migrations b.ToTable("Users"); }); - modelBuilder.Entity("Govor.Core.Models.Users.UserPushToken", b => + modelBuilder.Entity("Govor.Domain.Models.Users.UserPushToken", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -561,7 +566,7 @@ namespace Govor.Data.Migrations b.ToTable("UserPushTokens"); }); - modelBuilder.Entity("Govor.Core.Models.Users.UserSession", b => + modelBuilder.Entity("Govor.Domain.Models.Users.UserSession", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -590,9 +595,6 @@ namespace Govor.Data.Migrations b.HasKey("Id"); - b.HasIndex("Id") - .IsUnique(); - b.HasIndex("RefreshTokenHash") .IsUnique(); @@ -601,15 +603,15 @@ namespace Govor.Data.Migrations b.ToTable("UserSessions"); }); - modelBuilder.Entity("Govor.Core.Models.Friendship", b => + modelBuilder.Entity("Govor.Domain.Models.Friendship", b => { - b.HasOne("Govor.Core.Models.Users.User", "Addressee") + b.HasOne("Govor.Domain.Models.Users.User", "Addressee") .WithMany("ReceivedFriendRequests") .HasForeignKey("AddresseeId") .OnDelete(DeleteBehavior.Restrict) .IsRequired(); - b.HasOne("Govor.Core.Models.Users.User", "Requester") + b.HasOne("Govor.Domain.Models.Users.User", "Requester") .WithMany("SentFriendRequests") .HasForeignKey("RequesterId") .OnDelete(DeleteBehavior.Restrict) @@ -620,24 +622,24 @@ namespace Govor.Data.Migrations b.Navigation("Requester"); }); - modelBuilder.Entity("Govor.Core.Models.GroupAdmins", b => + modelBuilder.Entity("Govor.Domain.Models.GroupAdmins", b => { - b.HasOne("Govor.Core.Models.ChatGroup", null) + b.HasOne("Govor.Domain.Models.ChatGroup", null) .WithMany("Admins") .HasForeignKey("GroupId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); }); - modelBuilder.Entity("Govor.Core.Models.GroupInvitation", b => + modelBuilder.Entity("Govor.Domain.Models.GroupInvitation", b => { - b.HasOne("Govor.Core.Models.ChatGroup", null) + b.HasOne("Govor.Domain.Models.ChatGroup", null) .WithMany("InviteCodes") .HasForeignKey("GroupId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.HasOne("Govor.Core.Models.Users.User", "UserMaker") + b.HasOne("Govor.Domain.Models.Users.User", "UserMaker") .WithMany() .HasForeignKey("UserMakerId") .OnDelete(DeleteBehavior.Restrict) @@ -646,29 +648,35 @@ namespace Govor.Data.Migrations b.Navigation("UserMaker"); }); - modelBuilder.Entity("Govor.Core.Models.GroupMembership", b => + modelBuilder.Entity("Govor.Domain.Models.GroupMembership", b => { - b.HasOne("Govor.Core.Models.ChatGroup", null) + b.HasOne("Govor.Domain.Models.ChatGroup", null) .WithMany("Members") + .HasForeignKey("ChatGroupId"); + + b.HasOne("Govor.Domain.Models.ChatGroup", "ChatGroup") + .WithMany() .HasForeignKey("GroupId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.HasOne("Govor.Core.Models.GroupInvitation", null) + b.HasOne("Govor.Domain.Models.GroupInvitation", null) .WithMany() .HasForeignKey("InvitationId") .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("ChatGroup"); }); - modelBuilder.Entity("Govor.Core.Models.Messages.MediaAttachments", b => + modelBuilder.Entity("Govor.Domain.Models.Messages.MediaAttachments", b => { - b.HasOne("Govor.Core.Models.MediaFile", "MediaFile") + b.HasOne("Govor.Domain.Models.MediaFile", "MediaFile") .WithMany() .HasForeignKey("MediaFileId") .OnDelete(DeleteBehavior.Restrict) .IsRequired(); - b.HasOne("Govor.Core.Models.Messages.Message", "Message") + b.HasOne("Govor.Domain.Models.Messages.Message", "Message") .WithMany("MediaAttachments") .HasForeignKey("MessageId") .OnDelete(DeleteBehavior.Cascade) @@ -679,26 +687,26 @@ namespace Govor.Data.Migrations b.Navigation("Message"); }); - modelBuilder.Entity("Govor.Core.Models.Messages.Message", b => + modelBuilder.Entity("Govor.Domain.Models.Messages.Message", b => { - b.HasOne("Govor.Core.Models.ChatGroup", null) + b.HasOne("Govor.Domain.Models.ChatGroup", null) .WithMany("Messages") .HasForeignKey("ChatGroupId"); - b.HasOne("Govor.Core.Models.PrivateChat", null) + b.HasOne("Govor.Domain.Models.PrivateChat", null) .WithMany("Messages") .HasForeignKey("PrivateChatId"); }); - modelBuilder.Entity("Govor.Core.Models.Messages.MessageReaction", b => + modelBuilder.Entity("Govor.Domain.Models.Messages.MessageReaction", b => { - b.HasOne("Govor.Core.Models.Messages.Message", "Message") + b.HasOne("Govor.Domain.Models.Messages.Message", "Message") .WithMany("Reactions") .HasForeignKey("MessageId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.HasOne("Govor.Core.Models.Users.User", "User") + b.HasOne("Govor.Domain.Models.Users.User", "User") .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) @@ -709,29 +717,29 @@ namespace Govor.Data.Migrations b.Navigation("User"); }); - modelBuilder.Entity("Govor.Core.Models.Messages.MessageView", b => + modelBuilder.Entity("Govor.Domain.Models.Messages.MessageView", b => { - b.HasOne("Govor.Core.Models.Messages.Message", null) + b.HasOne("Govor.Domain.Models.Messages.Message", null) .WithMany("MessageViews") .HasForeignKey("MessageId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); }); - modelBuilder.Entity("Govor.Core.Models.Users.Admin", b => + modelBuilder.Entity("Govor.Domain.Models.Users.Admin", b => { - b.HasOne("Govor.Core.Models.Users.User", "User") + b.HasOne("Govor.Domain.Models.Users.User", "User") .WithOne() - .HasForeignKey("Govor.Core.Models.Users.Admin", "UserId") + .HasForeignKey("Govor.Domain.Models.Users.Admin", "UserId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); b.Navigation("User"); }); - modelBuilder.Entity("Govor.Core.Models.Users.Crypto.OneTimePreKey", b => + modelBuilder.Entity("Govor.Domain.Models.Users.Crypto.OneTimePreKey", b => { - b.HasOne("Govor.Core.Models.Users.Crypto.UserCryptoSession", "UserCryptoSession") + b.HasOne("Govor.Domain.Models.Users.Crypto.UserCryptoSession", "UserCryptoSession") .WithMany("OneTimePreKeys") .HasForeignKey("UserCryptoSessionId") .OnDelete(DeleteBehavior.Cascade) @@ -740,31 +748,31 @@ namespace Govor.Data.Migrations b.Navigation("UserCryptoSession"); }); - modelBuilder.Entity("Govor.Core.Models.Users.Crypto.SignedPreKey", b => + modelBuilder.Entity("Govor.Domain.Models.Users.Crypto.SignedPreKey", b => { - b.HasOne("Govor.Core.Models.Users.Crypto.UserCryptoSession", "UserCryptoSession") + b.HasOne("Govor.Domain.Models.Users.Crypto.UserCryptoSession", "UserCryptoSession") .WithOne("SignedPreKey") - .HasForeignKey("Govor.Core.Models.Users.Crypto.SignedPreKey", "UserCryptoSessionId") + .HasForeignKey("Govor.Domain.Models.Users.Crypto.SignedPreKey", "UserCryptoSessionId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); b.Navigation("UserCryptoSession"); }); - modelBuilder.Entity("Govor.Core.Models.Users.Crypto.UserCryptoSession", b => + modelBuilder.Entity("Govor.Domain.Models.Users.Crypto.UserCryptoSession", b => { - b.HasOne("Govor.Core.Models.Users.UserSession", "UserSession") + b.HasOne("Govor.Domain.Models.Users.UserSession", "UserSession") .WithOne("CryptoSession") - .HasForeignKey("Govor.Core.Models.Users.Crypto.UserCryptoSession", "UserSessionId") + .HasForeignKey("Govor.Domain.Models.Users.Crypto.UserCryptoSession", "UserSessionId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); b.Navigation("UserSession"); }); - modelBuilder.Entity("Govor.Core.Models.Users.User", b => + modelBuilder.Entity("Govor.Domain.Models.Users.User", b => { - b.HasOne("Govor.Core.Models.Invitation", "Invite") + b.HasOne("Govor.Domain.Models.Invitation", "Invite") .WithMany("Users") .HasForeignKey("InviteId") .OnDelete(DeleteBehavior.Cascade) @@ -773,16 +781,18 @@ namespace Govor.Data.Migrations b.Navigation("Invite"); }); - modelBuilder.Entity("Govor.Core.Models.Users.UserSession", b => + modelBuilder.Entity("Govor.Domain.Models.Users.UserSession", b => { - b.HasOne("Govor.Core.Models.Users.User", null) + b.HasOne("Govor.Domain.Models.Users.User", "User") .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); + + b.Navigation("User"); }); - modelBuilder.Entity("Govor.Core.Models.ChatGroup", b => + modelBuilder.Entity("Govor.Domain.Models.ChatGroup", b => { b.Navigation("Admins"); @@ -793,12 +803,12 @@ namespace Govor.Data.Migrations b.Navigation("Messages"); }); - modelBuilder.Entity("Govor.Core.Models.Invitation", b => + modelBuilder.Entity("Govor.Domain.Models.Invitation", b => { b.Navigation("Users"); }); - modelBuilder.Entity("Govor.Core.Models.Messages.Message", b => + modelBuilder.Entity("Govor.Domain.Models.Messages.Message", b => { b.Navigation("MediaAttachments"); @@ -807,12 +817,12 @@ namespace Govor.Data.Migrations b.Navigation("Reactions"); }); - modelBuilder.Entity("Govor.Core.Models.PrivateChat", b => + modelBuilder.Entity("Govor.Domain.Models.PrivateChat", b => { b.Navigation("Messages"); }); - modelBuilder.Entity("Govor.Core.Models.Users.Crypto.UserCryptoSession", b => + modelBuilder.Entity("Govor.Domain.Models.Users.Crypto.UserCryptoSession", b => { b.Navigation("OneTimePreKeys"); @@ -820,14 +830,14 @@ namespace Govor.Data.Migrations .IsRequired(); }); - modelBuilder.Entity("Govor.Core.Models.Users.User", b => + modelBuilder.Entity("Govor.Domain.Models.Users.User", b => { b.Navigation("ReceivedFriendRequests"); b.Navigation("SentFriendRequests"); }); - modelBuilder.Entity("Govor.Core.Models.Users.UserSession", b => + modelBuilder.Entity("Govor.Domain.Models.Users.UserSession", b => { b.Navigation("CryptoSession") .IsRequired(); diff --git a/Govor.Data/Migrations/20260301080331_Init.cs b/Govor.Domain/Migrations/20260716110338_InitialCreate.cs similarity index 95% rename from Govor.Data/Migrations/20260301080331_Init.cs rename to Govor.Domain/Migrations/20260716110338_InitialCreate.cs index da67b0a..ead7690 100644 --- a/Govor.Data/Migrations/20260301080331_Init.cs +++ b/Govor.Domain/Migrations/20260716110338_InitialCreate.cs @@ -3,10 +3,10 @@ using Microsoft.EntityFrameworkCore.Migrations; #nullable disable -namespace Govor.Data.Migrations +namespace Govor.Domain.Migrations { /// - public partial class Init : Migration + public partial class InitialCreate : Migration { /// protected override void Up(MigrationBuilder migrationBuilder) @@ -83,9 +83,9 @@ namespace Govor.Data.Migrations Id = table.Column(type: "uuid", nullable: false), UserId = table.Column(type: "uuid", nullable: false), UserSessionId = table.Column(type: "uuid", nullable: true), - Token = table.Column(type: "text", nullable: false), - Provider = table.Column(type: "text", nullable: false), - Platform = table.Column(type: "text", nullable: false), + Token = table.Column(type: "character varying(512)", maxLength: 512, nullable: false), + Provider = table.Column(type: "character varying(50)", maxLength: 50, nullable: false), + Platform = table.Column(type: "character varying(50)", maxLength: 50, nullable: false), CreatedAt = table.Column(type: "timestamp with time zone", nullable: false), UpdatedAt = table.Column(type: "timestamp with time zone", nullable: false), LastUsedAt = table.Column(type: "timestamp with time zone", nullable: true), @@ -347,11 +347,17 @@ namespace Govor.Data.Migrations UserId = table.Column(type: "uuid", nullable: false), InvitationId = table.Column(type: "uuid", nullable: true), IsBanned = table.Column(type: "boolean", nullable: false), - MemberSince = table.Column(type: "timestamp with time zone", nullable: false) + MemberSince = table.Column(type: "timestamp with time zone", nullable: false), + ChatGroupId = table.Column(type: "uuid", nullable: true) }, constraints: table => { table.PrimaryKey("PK_GroupMemberships", x => x.Id); + table.ForeignKey( + name: "FK_GroupMemberships_ChatGroups_ChatGroupId", + column: x => x.ChatGroupId, + principalTable: "ChatGroups", + principalColumn: "Id"); table.ForeignKey( name: "FK_GroupMemberships_ChatGroups_GroupId", column: x => x.GroupId, @@ -431,12 +437,6 @@ namespace Govor.Data.Migrations table: "Friendships", column: "AddresseeId"); - migrationBuilder.CreateIndex( - name: "IX_Friendships_Id", - table: "Friendships", - column: "Id", - unique: true); - migrationBuilder.CreateIndex( name: "IX_Friendships_RequesterId", table: "Friendships", @@ -457,6 +457,11 @@ namespace Govor.Data.Migrations table: "GroupInvitations", column: "UserMakerId"); + migrationBuilder.CreateIndex( + name: "IX_GroupMemberships_ChatGroupId", + table: "GroupMemberships", + column: "ChatGroupId"); + migrationBuilder.CreateIndex( name: "IX_GroupMemberships_GroupId", table: "GroupMemberships", @@ -493,12 +498,6 @@ namespace Govor.Data.Migrations table: "Messages", column: "ChatGroupId"); - migrationBuilder.CreateIndex( - name: "IX_Messages_Id", - table: "Messages", - column: "Id", - unique: true); - migrationBuilder.CreateIndex( name: "IX_Messages_PrivateChatId", table: "Messages", @@ -507,8 +506,7 @@ namespace Govor.Data.Migrations migrationBuilder.CreateIndex( name: "IX_Messages_RecipientId", table: "Messages", - column: "RecipientId", - unique: true); + column: "RecipientId"); migrationBuilder.CreateIndex( name: "IX_MessageViews_MessageId_UserId", @@ -526,12 +524,6 @@ namespace Govor.Data.Migrations table: "OneTimePreKeys", columns: new[] { "UserCryptoSessionId", "IsUsed" }); - migrationBuilder.CreateIndex( - name: "IX_PrivateChats_Id", - table: "PrivateChats", - column: "Id", - unique: true); - migrationBuilder.CreateIndex( name: "IX_SignedPreKeys_UserCryptoSessionId", table: "SignedPreKeys", @@ -550,12 +542,6 @@ namespace Govor.Data.Migrations column: "Token", unique: true); - migrationBuilder.CreateIndex( - name: "IX_UserPushTokens_UserId", - table: "UserPushTokens", - column: "UserId", - unique: true); - migrationBuilder.CreateIndex( name: "IX_UserPushTokens_UserId_IsActive", table: "UserPushTokens", @@ -588,12 +574,6 @@ namespace Govor.Data.Migrations table: "Users", column: "WasOnline"); - migrationBuilder.CreateIndex( - name: "IX_UserSessions_Id", - table: "UserSessions", - column: "Id", - unique: true); - migrationBuilder.CreateIndex( name: "IX_UserSessions_RefreshTokenHash", table: "UserSessions", diff --git a/Govor.Data/Migrations/GovorDbContextModelSnapshot.cs b/Govor.Domain/Migrations/GovorDbContextModelSnapshot.cs similarity index 81% rename from Govor.Data/Migrations/GovorDbContextModelSnapshot.cs rename to Govor.Domain/Migrations/GovorDbContextModelSnapshot.cs index 7eee105..713c4e5 100644 --- a/Govor.Data/Migrations/GovorDbContextModelSnapshot.cs +++ b/Govor.Domain/Migrations/GovorDbContextModelSnapshot.cs @@ -1,6 +1,6 @@ // using System; -using Govor.Data; +using Govor.Domain; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; @@ -8,7 +8,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; #nullable disable -namespace Govor.Data.Migrations +namespace Govor.Domain.Migrations { [DbContext(typeof(GovorDbContext))] partial class GovorDbContextModelSnapshot : ModelSnapshot @@ -22,7 +22,7 @@ namespace Govor.Data.Migrations NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - modelBuilder.Entity("Govor.Core.Models.ChatGroup", b => + modelBuilder.Entity("Govor.Domain.Models.ChatGroup", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -52,7 +52,7 @@ namespace Govor.Data.Migrations b.ToTable("ChatGroups"); }); - modelBuilder.Entity("Govor.Core.Models.Friendship", b => + modelBuilder.Entity("Govor.Domain.Models.Friendship", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -76,7 +76,7 @@ namespace Govor.Data.Migrations b.ToTable("Friendships"); }); - modelBuilder.Entity("Govor.Core.Models.GroupAdmins", b => + modelBuilder.Entity("Govor.Domain.Models.GroupAdmins", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -95,7 +95,7 @@ namespace Govor.Data.Migrations b.ToTable("GroupAdmins"); }); - modelBuilder.Entity("Govor.Core.Models.GroupInvitation", b => + modelBuilder.Entity("Govor.Domain.Models.GroupInvitation", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -135,12 +135,15 @@ namespace Govor.Data.Migrations b.ToTable("GroupInvitations"); }); - modelBuilder.Entity("Govor.Core.Models.GroupMembership", b => + modelBuilder.Entity("Govor.Domain.Models.GroupMembership", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("uuid"); + b.Property("ChatGroupId") + .HasColumnType("uuid"); + b.Property("GroupId") .HasColumnType("uuid"); @@ -158,6 +161,8 @@ namespace Govor.Data.Migrations b.HasKey("Id"); + b.HasIndex("ChatGroupId"); + b.HasIndex("GroupId"); b.HasIndex("InvitationId"); @@ -165,7 +170,7 @@ namespace Govor.Data.Migrations b.ToTable("GroupMemberships"); }); - modelBuilder.Entity("Govor.Core.Models.Invitation", b => + modelBuilder.Entity("Govor.Domain.Models.Invitation", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -199,7 +204,7 @@ namespace Govor.Data.Migrations b.ToTable("Invitations"); }); - modelBuilder.Entity("Govor.Core.Models.MediaFile", b => + modelBuilder.Entity("Govor.Domain.Models.MediaFile", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -235,7 +240,7 @@ namespace Govor.Data.Migrations b.ToTable("MediaFiles"); }); - modelBuilder.Entity("Govor.Core.Models.Messages.MediaAttachments", b => + modelBuilder.Entity("Govor.Domain.Models.Messages.MediaAttachments", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -256,7 +261,7 @@ namespace Govor.Data.Migrations b.ToTable("MediaAttachments"); }); - modelBuilder.Entity("Govor.Core.Models.Messages.Message", b => + modelBuilder.Entity("Govor.Domain.Models.Messages.Message", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -304,7 +309,7 @@ namespace Govor.Data.Migrations b.ToTable("Messages"); }); - modelBuilder.Entity("Govor.Core.Models.Messages.MessageReaction", b => + modelBuilder.Entity("Govor.Domain.Models.Messages.MessageReaction", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -334,7 +339,7 @@ namespace Govor.Data.Migrations b.ToTable("MessageReactions"); }); - modelBuilder.Entity("Govor.Core.Models.Messages.MessageView", b => + modelBuilder.Entity("Govor.Domain.Models.Messages.MessageView", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -357,7 +362,7 @@ namespace Govor.Data.Migrations b.ToTable("MessageViews"); }); - modelBuilder.Entity("Govor.Core.Models.PrivateChat", b => + modelBuilder.Entity("Govor.Domain.Models.PrivateChat", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -374,7 +379,7 @@ namespace Govor.Data.Migrations b.ToTable("PrivateChats"); }); - modelBuilder.Entity("Govor.Core.Models.Users.Admin", b => + modelBuilder.Entity("Govor.Domain.Models.Users.Admin", b => { b.Property("UserId") .HasColumnType("uuid"); @@ -384,7 +389,7 @@ namespace Govor.Data.Migrations b.ToTable("Admins"); }); - modelBuilder.Entity("Govor.Core.Models.Users.Crypto.OneTimePreKey", b => + modelBuilder.Entity("Govor.Domain.Models.Users.Crypto.OneTimePreKey", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -414,7 +419,7 @@ namespace Govor.Data.Migrations b.ToTable("OneTimePreKeys"); }); - modelBuilder.Entity("Govor.Core.Models.Users.Crypto.SignedPreKey", b => + modelBuilder.Entity("Govor.Domain.Models.Users.Crypto.SignedPreKey", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -439,7 +444,7 @@ namespace Govor.Data.Migrations b.ToTable("SignedPreKeys"); }); - modelBuilder.Entity("Govor.Core.Models.Users.Crypto.UserCryptoSession", b => + modelBuilder.Entity("Govor.Domain.Models.Users.Crypto.UserCryptoSession", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -460,7 +465,7 @@ namespace Govor.Data.Migrations b.ToTable("UserCryptoSessions"); }); - modelBuilder.Entity("Govor.Core.Models.Users.User", b => + modelBuilder.Entity("Govor.Domain.Models.Users.User", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -506,7 +511,7 @@ namespace Govor.Data.Migrations b.ToTable("Users"); }); - modelBuilder.Entity("Govor.Core.Models.Users.UserPushToken", b => + modelBuilder.Entity("Govor.Domain.Models.Users.UserPushToken", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -558,7 +563,7 @@ namespace Govor.Data.Migrations b.ToTable("UserPushTokens"); }); - modelBuilder.Entity("Govor.Core.Models.Users.UserSession", b => + modelBuilder.Entity("Govor.Domain.Models.Users.UserSession", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -587,9 +592,6 @@ namespace Govor.Data.Migrations b.HasKey("Id"); - b.HasIndex("Id") - .IsUnique(); - b.HasIndex("RefreshTokenHash") .IsUnique(); @@ -598,15 +600,15 @@ namespace Govor.Data.Migrations b.ToTable("UserSessions"); }); - modelBuilder.Entity("Govor.Core.Models.Friendship", b => + modelBuilder.Entity("Govor.Domain.Models.Friendship", b => { - b.HasOne("Govor.Core.Models.Users.User", "Addressee") + b.HasOne("Govor.Domain.Models.Users.User", "Addressee") .WithMany("ReceivedFriendRequests") .HasForeignKey("AddresseeId") .OnDelete(DeleteBehavior.Restrict) .IsRequired(); - b.HasOne("Govor.Core.Models.Users.User", "Requester") + b.HasOne("Govor.Domain.Models.Users.User", "Requester") .WithMany("SentFriendRequests") .HasForeignKey("RequesterId") .OnDelete(DeleteBehavior.Restrict) @@ -617,24 +619,24 @@ namespace Govor.Data.Migrations b.Navigation("Requester"); }); - modelBuilder.Entity("Govor.Core.Models.GroupAdmins", b => + modelBuilder.Entity("Govor.Domain.Models.GroupAdmins", b => { - b.HasOne("Govor.Core.Models.ChatGroup", null) + b.HasOne("Govor.Domain.Models.ChatGroup", null) .WithMany("Admins") .HasForeignKey("GroupId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); }); - modelBuilder.Entity("Govor.Core.Models.GroupInvitation", b => + modelBuilder.Entity("Govor.Domain.Models.GroupInvitation", b => { - b.HasOne("Govor.Core.Models.ChatGroup", null) + b.HasOne("Govor.Domain.Models.ChatGroup", null) .WithMany("InviteCodes") .HasForeignKey("GroupId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.HasOne("Govor.Core.Models.Users.User", "UserMaker") + b.HasOne("Govor.Domain.Models.Users.User", "UserMaker") .WithMany() .HasForeignKey("UserMakerId") .OnDelete(DeleteBehavior.Restrict) @@ -643,29 +645,35 @@ namespace Govor.Data.Migrations b.Navigation("UserMaker"); }); - modelBuilder.Entity("Govor.Core.Models.GroupMembership", b => + modelBuilder.Entity("Govor.Domain.Models.GroupMembership", b => { - b.HasOne("Govor.Core.Models.ChatGroup", null) + b.HasOne("Govor.Domain.Models.ChatGroup", null) .WithMany("Members") + .HasForeignKey("ChatGroupId"); + + b.HasOne("Govor.Domain.Models.ChatGroup", "ChatGroup") + .WithMany() .HasForeignKey("GroupId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.HasOne("Govor.Core.Models.GroupInvitation", null) + b.HasOne("Govor.Domain.Models.GroupInvitation", null) .WithMany() .HasForeignKey("InvitationId") .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("ChatGroup"); }); - modelBuilder.Entity("Govor.Core.Models.Messages.MediaAttachments", b => + modelBuilder.Entity("Govor.Domain.Models.Messages.MediaAttachments", b => { - b.HasOne("Govor.Core.Models.MediaFile", "MediaFile") + b.HasOne("Govor.Domain.Models.MediaFile", "MediaFile") .WithMany() .HasForeignKey("MediaFileId") .OnDelete(DeleteBehavior.Restrict) .IsRequired(); - b.HasOne("Govor.Core.Models.Messages.Message", "Message") + b.HasOne("Govor.Domain.Models.Messages.Message", "Message") .WithMany("MediaAttachments") .HasForeignKey("MessageId") .OnDelete(DeleteBehavior.Cascade) @@ -676,26 +684,26 @@ namespace Govor.Data.Migrations b.Navigation("Message"); }); - modelBuilder.Entity("Govor.Core.Models.Messages.Message", b => + modelBuilder.Entity("Govor.Domain.Models.Messages.Message", b => { - b.HasOne("Govor.Core.Models.ChatGroup", null) + b.HasOne("Govor.Domain.Models.ChatGroup", null) .WithMany("Messages") .HasForeignKey("ChatGroupId"); - b.HasOne("Govor.Core.Models.PrivateChat", null) + b.HasOne("Govor.Domain.Models.PrivateChat", null) .WithMany("Messages") .HasForeignKey("PrivateChatId"); }); - modelBuilder.Entity("Govor.Core.Models.Messages.MessageReaction", b => + modelBuilder.Entity("Govor.Domain.Models.Messages.MessageReaction", b => { - b.HasOne("Govor.Core.Models.Messages.Message", "Message") + b.HasOne("Govor.Domain.Models.Messages.Message", "Message") .WithMany("Reactions") .HasForeignKey("MessageId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.HasOne("Govor.Core.Models.Users.User", "User") + b.HasOne("Govor.Domain.Models.Users.User", "User") .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) @@ -706,29 +714,29 @@ namespace Govor.Data.Migrations b.Navigation("User"); }); - modelBuilder.Entity("Govor.Core.Models.Messages.MessageView", b => + modelBuilder.Entity("Govor.Domain.Models.Messages.MessageView", b => { - b.HasOne("Govor.Core.Models.Messages.Message", null) + b.HasOne("Govor.Domain.Models.Messages.Message", null) .WithMany("MessageViews") .HasForeignKey("MessageId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); }); - modelBuilder.Entity("Govor.Core.Models.Users.Admin", b => + modelBuilder.Entity("Govor.Domain.Models.Users.Admin", b => { - b.HasOne("Govor.Core.Models.Users.User", "User") + b.HasOne("Govor.Domain.Models.Users.User", "User") .WithOne() - .HasForeignKey("Govor.Core.Models.Users.Admin", "UserId") + .HasForeignKey("Govor.Domain.Models.Users.Admin", "UserId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); b.Navigation("User"); }); - modelBuilder.Entity("Govor.Core.Models.Users.Crypto.OneTimePreKey", b => + modelBuilder.Entity("Govor.Domain.Models.Users.Crypto.OneTimePreKey", b => { - b.HasOne("Govor.Core.Models.Users.Crypto.UserCryptoSession", "UserCryptoSession") + b.HasOne("Govor.Domain.Models.Users.Crypto.UserCryptoSession", "UserCryptoSession") .WithMany("OneTimePreKeys") .HasForeignKey("UserCryptoSessionId") .OnDelete(DeleteBehavior.Cascade) @@ -737,31 +745,31 @@ namespace Govor.Data.Migrations b.Navigation("UserCryptoSession"); }); - modelBuilder.Entity("Govor.Core.Models.Users.Crypto.SignedPreKey", b => + modelBuilder.Entity("Govor.Domain.Models.Users.Crypto.SignedPreKey", b => { - b.HasOne("Govor.Core.Models.Users.Crypto.UserCryptoSession", "UserCryptoSession") + b.HasOne("Govor.Domain.Models.Users.Crypto.UserCryptoSession", "UserCryptoSession") .WithOne("SignedPreKey") - .HasForeignKey("Govor.Core.Models.Users.Crypto.SignedPreKey", "UserCryptoSessionId") + .HasForeignKey("Govor.Domain.Models.Users.Crypto.SignedPreKey", "UserCryptoSessionId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); b.Navigation("UserCryptoSession"); }); - modelBuilder.Entity("Govor.Core.Models.Users.Crypto.UserCryptoSession", b => + modelBuilder.Entity("Govor.Domain.Models.Users.Crypto.UserCryptoSession", b => { - b.HasOne("Govor.Core.Models.Users.UserSession", "UserSession") + b.HasOne("Govor.Domain.Models.Users.UserSession", "UserSession") .WithOne("CryptoSession") - .HasForeignKey("Govor.Core.Models.Users.Crypto.UserCryptoSession", "UserSessionId") + .HasForeignKey("Govor.Domain.Models.Users.Crypto.UserCryptoSession", "UserSessionId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); b.Navigation("UserSession"); }); - modelBuilder.Entity("Govor.Core.Models.Users.User", b => + modelBuilder.Entity("Govor.Domain.Models.Users.User", b => { - b.HasOne("Govor.Core.Models.Invitation", "Invite") + b.HasOne("Govor.Domain.Models.Invitation", "Invite") .WithMany("Users") .HasForeignKey("InviteId") .OnDelete(DeleteBehavior.Cascade) @@ -770,16 +778,18 @@ namespace Govor.Data.Migrations b.Navigation("Invite"); }); - modelBuilder.Entity("Govor.Core.Models.Users.UserSession", b => + modelBuilder.Entity("Govor.Domain.Models.Users.UserSession", b => { - b.HasOne("Govor.Core.Models.Users.User", null) + b.HasOne("Govor.Domain.Models.Users.User", "User") .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); + + b.Navigation("User"); }); - modelBuilder.Entity("Govor.Core.Models.ChatGroup", b => + modelBuilder.Entity("Govor.Domain.Models.ChatGroup", b => { b.Navigation("Admins"); @@ -790,12 +800,12 @@ namespace Govor.Data.Migrations b.Navigation("Messages"); }); - modelBuilder.Entity("Govor.Core.Models.Invitation", b => + modelBuilder.Entity("Govor.Domain.Models.Invitation", b => { b.Navigation("Users"); }); - modelBuilder.Entity("Govor.Core.Models.Messages.Message", b => + modelBuilder.Entity("Govor.Domain.Models.Messages.Message", b => { b.Navigation("MediaAttachments"); @@ -804,12 +814,12 @@ namespace Govor.Data.Migrations b.Navigation("Reactions"); }); - modelBuilder.Entity("Govor.Core.Models.PrivateChat", b => + modelBuilder.Entity("Govor.Domain.Models.PrivateChat", b => { b.Navigation("Messages"); }); - modelBuilder.Entity("Govor.Core.Models.Users.Crypto.UserCryptoSession", b => + modelBuilder.Entity("Govor.Domain.Models.Users.Crypto.UserCryptoSession", b => { b.Navigation("OneTimePreKeys"); @@ -817,14 +827,14 @@ namespace Govor.Data.Migrations .IsRequired(); }); - modelBuilder.Entity("Govor.Core.Models.Users.User", b => + modelBuilder.Entity("Govor.Domain.Models.Users.User", b => { b.Navigation("ReceivedFriendRequests"); b.Navigation("SentFriendRequests"); }); - modelBuilder.Entity("Govor.Core.Models.Users.UserSession", b => + modelBuilder.Entity("Govor.Domain.Models.Users.UserSession", b => { b.Navigation("CryptoSession") .IsRequired(); diff --git a/Govor.Core/Models/ChatGroup.cs b/Govor.Domain/Models/ChatGroup.cs similarity index 93% rename from Govor.Core/Models/ChatGroup.cs rename to Govor.Domain/Models/ChatGroup.cs index 406854e..d6d8f30 100644 --- a/Govor.Core/Models/ChatGroup.cs +++ b/Govor.Domain/Models/ChatGroup.cs @@ -1,6 +1,6 @@ -using Govor.Core.Models.Messages; +using Govor.Domain.Models.Messages; -namespace Govor.Core.Models; +namespace Govor.Domain.Models; public class ChatGroup { diff --git a/Govor.Core/Models/Friendship.cs b/Govor.Domain/Models/Friendship.cs similarity index 85% rename from Govor.Core/Models/Friendship.cs rename to Govor.Domain/Models/Friendship.cs index 442bf37..725bab1 100644 --- a/Govor.Core/Models/Friendship.cs +++ b/Govor.Domain/Models/Friendship.cs @@ -1,6 +1,6 @@ -using Govor.Core.Models.Users; +using Govor.Domain.Models.Users; -namespace Govor.Core.Models; +namespace Govor.Domain.Models; public class Friendship { diff --git a/Govor.Core/Models/GroupAdmins.cs b/Govor.Domain/Models/GroupAdmins.cs similarity index 80% rename from Govor.Core/Models/GroupAdmins.cs rename to Govor.Domain/Models/GroupAdmins.cs index be21bfc..0f580d2 100644 --- a/Govor.Core/Models/GroupAdmins.cs +++ b/Govor.Domain/Models/GroupAdmins.cs @@ -1,4 +1,4 @@ -namespace Govor.Core.Models; +namespace Govor.Domain.Models; public class GroupAdmins { diff --git a/Govor.Core/Models/GroupInvitation.cs b/Govor.Domain/Models/GroupInvitation.cs similarity index 87% rename from Govor.Core/Models/GroupInvitation.cs rename to Govor.Domain/Models/GroupInvitation.cs index 3f135fd..e0d5055 100644 --- a/Govor.Core/Models/GroupInvitation.cs +++ b/Govor.Domain/Models/GroupInvitation.cs @@ -1,6 +1,6 @@ -using Govor.Core.Models.Users; +using Govor.Domain.Models.Users; -namespace Govor.Core.Models; +namespace Govor.Domain.Models; public class GroupInvitation { diff --git a/Govor.Core/Models/GroupMembership.cs b/Govor.Domain/Models/GroupMembership.cs similarity index 77% rename from Govor.Core/Models/GroupMembership.cs rename to Govor.Domain/Models/GroupMembership.cs index 509b19e..c27be6e 100644 --- a/Govor.Core/Models/GroupMembership.cs +++ b/Govor.Domain/Models/GroupMembership.cs @@ -1,4 +1,4 @@ -namespace Govor.Core.Models; +namespace Govor.Domain.Models; public class GroupMembership { @@ -8,4 +8,5 @@ public class GroupMembership public Guid? InvitationId { get; set; } public bool IsBanned { get; set; } public DateTime MemberSince { get; set; } + public ChatGroup ChatGroup { get; set; } } \ No newline at end of file diff --git a/Govor.Core/Models/Invitation.cs b/Govor.Domain/Models/Invitation.cs similarity index 93% rename from Govor.Core/Models/Invitation.cs rename to Govor.Domain/Models/Invitation.cs index 46e0555..b2ebf48 100644 --- a/Govor.Core/Models/Invitation.cs +++ b/Govor.Domain/Models/Invitation.cs @@ -1,6 +1,6 @@ -using Govor.Core.Models.Users; +using Govor.Domain.Models.Users; -namespace Govor.Core.Models; +namespace Govor.Domain.Models; public class Invitation { diff --git a/Govor.Core/Models/MediaFile.cs b/Govor.Domain/Models/MediaFile.cs similarity index 80% rename from Govor.Core/Models/MediaFile.cs rename to Govor.Domain/Models/MediaFile.cs index 940dbd5..c3ef8be 100644 --- a/Govor.Core/Models/MediaFile.cs +++ b/Govor.Domain/Models/MediaFile.cs @@ -1,6 +1,6 @@ -using Govor.Core.Models.Messages; +using Govor.Domain.Models.Messages; -namespace Govor.Core.Models; +namespace Govor.Domain.Models; public class MediaFile { @@ -20,5 +20,5 @@ public enum MediaOwnerType Message = 0, Avatar = 1, GroupAvatar = 2, - System = 3 // (Emoge, icons e.t.c) + System = 3 // (Emoge, icons � e.t.c) } \ No newline at end of file diff --git a/Govor.Core/Models/Messages/MediaAttachments.cs b/Govor.Domain/Models/Messages/MediaAttachments.cs similarity index 93% rename from Govor.Core/Models/Messages/MediaAttachments.cs rename to Govor.Domain/Models/Messages/MediaAttachments.cs index 99a5a6b..7e4ea58 100644 --- a/Govor.Core/Models/Messages/MediaAttachments.cs +++ b/Govor.Domain/Models/Messages/MediaAttachments.cs @@ -1,4 +1,4 @@ -namespace Govor.Core.Models.Messages; +namespace Govor.Domain.Models.Messages; public class MediaAttachments { diff --git a/Govor.Core/Models/Messages/Message.cs b/Govor.Domain/Models/Messages/Message.cs similarity index 96% rename from Govor.Core/Models/Messages/Message.cs rename to Govor.Domain/Models/Messages/Message.cs index d999f4b..c8e423b 100644 --- a/Govor.Core/Models/Messages/Message.cs +++ b/Govor.Domain/Models/Messages/Message.cs @@ -1,4 +1,4 @@ -namespace Govor.Core.Models.Messages; +namespace Govor.Domain.Models.Messages; public class Message { diff --git a/Govor.Core/Models/Messages/MessageReaction.cs b/Govor.Domain/Models/Messages/MessageReaction.cs similarity index 83% rename from Govor.Core/Models/Messages/MessageReaction.cs rename to Govor.Domain/Models/Messages/MessageReaction.cs index 1ce2382..0f0ea71 100644 --- a/Govor.Core/Models/Messages/MessageReaction.cs +++ b/Govor.Domain/Models/Messages/MessageReaction.cs @@ -1,6 +1,6 @@ -using Govor.Core.Models.Users; +using Govor.Domain.Models.Users; -namespace Govor.Core.Models.Messages; +namespace Govor.Domain.Models.Messages; public class MessageReaction { diff --git a/Govor.Core/Models/Messages/MessageView.cs b/Govor.Domain/Models/Messages/MessageView.cs similarity index 82% rename from Govor.Core/Models/Messages/MessageView.cs rename to Govor.Domain/Models/Messages/MessageView.cs index 0bb266a..13f78b8 100644 --- a/Govor.Core/Models/Messages/MessageView.cs +++ b/Govor.Domain/Models/Messages/MessageView.cs @@ -1,4 +1,4 @@ -namespace Govor.Core.Models.Messages; +namespace Govor.Domain.Models.Messages; public class MessageView { diff --git a/Govor.Core/Models/PrivateChat.cs b/Govor.Domain/Models/PrivateChat.cs similarity index 86% rename from Govor.Core/Models/PrivateChat.cs rename to Govor.Domain/Models/PrivateChat.cs index e043a92..53e7fde 100644 --- a/Govor.Core/Models/PrivateChat.cs +++ b/Govor.Domain/Models/PrivateChat.cs @@ -1,6 +1,6 @@ -using Govor.Core.Models.Messages; +using Govor.Domain.Models.Messages; -namespace Govor.Core.Models; +namespace Govor.Domain.Models; public class PrivateChat { diff --git a/Govor.Core/Models/Users/Admin.cs b/Govor.Domain/Models/Users/Admin.cs similarity index 81% rename from Govor.Core/Models/Users/Admin.cs rename to Govor.Domain/Models/Users/Admin.cs index c3e20bf..234535e 100644 --- a/Govor.Core/Models/Users/Admin.cs +++ b/Govor.Domain/Models/Users/Admin.cs @@ -1,6 +1,6 @@ using System.ComponentModel.DataAnnotations; -namespace Govor.Core.Models.Users; +namespace Govor.Domain.Models.Users; public class Admin { diff --git a/Govor.Core/Models/Users/Crypto/OneTimePreKey.cs b/Govor.Domain/Models/Users/Crypto/OneTimePreKey.cs similarity index 87% rename from Govor.Core/Models/Users/Crypto/OneTimePreKey.cs rename to Govor.Domain/Models/Users/Crypto/OneTimePreKey.cs index b356bb3..f8a7572 100644 --- a/Govor.Core/Models/Users/Crypto/OneTimePreKey.cs +++ b/Govor.Domain/Models/Users/Crypto/OneTimePreKey.cs @@ -1,4 +1,4 @@ -namespace Govor.Core.Models.Users.Crypto; +namespace Govor.Domain.Models.Users.Crypto; public class OneTimePreKey { diff --git a/Govor.Core/Models/Users/Crypto/SignedPreKey.cs b/Govor.Domain/Models/Users/Crypto/SignedPreKey.cs similarity index 86% rename from Govor.Core/Models/Users/Crypto/SignedPreKey.cs rename to Govor.Domain/Models/Users/Crypto/SignedPreKey.cs index c1b8b27..50381fa 100644 --- a/Govor.Core/Models/Users/Crypto/SignedPreKey.cs +++ b/Govor.Domain/Models/Users/Crypto/SignedPreKey.cs @@ -1,4 +1,4 @@ -namespace Govor.Core.Models.Users.Crypto; +namespace Govor.Domain.Models.Users.Crypto; public class SignedPreKey { diff --git a/Govor.Core/Models/Users/Crypto/UserCryptoSession.cs b/Govor.Domain/Models/Users/Crypto/UserCryptoSession.cs similarity index 88% rename from Govor.Core/Models/Users/Crypto/UserCryptoSession.cs rename to Govor.Domain/Models/Users/Crypto/UserCryptoSession.cs index 41403e6..a6a7c09 100644 --- a/Govor.Core/Models/Users/Crypto/UserCryptoSession.cs +++ b/Govor.Domain/Models/Users/Crypto/UserCryptoSession.cs @@ -1,4 +1,4 @@ -namespace Govor.Core.Models.Users.Crypto; +namespace Govor.Domain.Models.Users.Crypto; public class UserCryptoSession { diff --git a/Govor.Core/Models/Users/PrivacyRuleEntity.cs b/Govor.Domain/Models/Users/PrivacyRuleEntity.cs similarity index 91% rename from Govor.Core/Models/Users/PrivacyRuleEntity.cs rename to Govor.Domain/Models/Users/PrivacyRuleEntity.cs index 09f1fe0..f57d179 100644 --- a/Govor.Core/Models/Users/PrivacyRuleEntity.cs +++ b/Govor.Domain/Models/Users/PrivacyRuleEntity.cs @@ -1,4 +1,4 @@ -namespace Govor.Core.Models.Users; +namespace Govor.Domain.Models.Users; public class PrivacyRuleEntity { diff --git a/Govor.Core/Models/Users/PrivacyUserSettings.cs b/Govor.Domain/Models/Users/PrivacyUserSettings.cs similarity index 94% rename from Govor.Core/Models/Users/PrivacyUserSettings.cs rename to Govor.Domain/Models/Users/PrivacyUserSettings.cs index 001c38d..6d80c1a 100644 --- a/Govor.Core/Models/Users/PrivacyUserSettings.cs +++ b/Govor.Domain/Models/Users/PrivacyUserSettings.cs @@ -1,4 +1,4 @@ -namespace Govor.Core.Models.Users; +namespace Govor.Domain.Models.Users; public class PrivacyUserSettings { diff --git a/Govor.Core/Models/Users/User.cs b/Govor.Domain/Models/Users/User.cs similarity index 94% rename from Govor.Core/Models/Users/User.cs rename to Govor.Domain/Models/Users/User.cs index cefaf19..acb595a 100644 --- a/Govor.Core/Models/Users/User.cs +++ b/Govor.Domain/Models/Users/User.cs @@ -1,6 +1,6 @@ using System.ComponentModel.DataAnnotations; -namespace Govor.Core.Models.Users; +namespace Govor.Domain.Models.Users; public class User { diff --git a/Govor.Core/Models/Users/UserPushToken.cs b/Govor.Domain/Models/Users/UserPushToken.cs similarity index 89% rename from Govor.Core/Models/Users/UserPushToken.cs rename to Govor.Domain/Models/Users/UserPushToken.cs index 1ff716a..7d19263 100644 --- a/Govor.Core/Models/Users/UserPushToken.cs +++ b/Govor.Domain/Models/Users/UserPushToken.cs @@ -1,6 +1,4 @@ -using Microsoft.EntityFrameworkCore; - -namespace Govor.Core.Models.Users; +namespace Govor.Domain.Models.Users; public class UserPushToken { public Guid Id { get; set; } = Guid.NewGuid(); diff --git a/Govor.Core/Models/Users/UserSession.cs b/Govor.Domain/Models/Users/UserSession.cs similarity index 61% rename from Govor.Core/Models/Users/UserSession.cs rename to Govor.Domain/Models/Users/UserSession.cs index dcd448b..53205f5 100644 --- a/Govor.Core/Models/Users/UserSession.cs +++ b/Govor.Domain/Models/Users/UserSession.cs @@ -1,23 +1,24 @@ -using Govor.Core.Models.Users.Crypto; +using Govor.Domain.Models.Users.Crypto; -namespace Govor.Core.Models.Users; +namespace Govor.Domain.Models.Users; public class UserSession { public Guid Id { get; set; } = Guid.NewGuid(); public Guid UserId { get; set; } public string RefreshTokenHash { get; set; } = string.Empty; - public string DeviceInfo { get; set; } = string.Empty; // "Chrome on Windows" + public string DeviceInfo { get; set; } = string.Empty; public DateTime CreatedAt { get; set; } = DateTime.UtcNow; public DateTime ExpiresAt { get; set; } public bool IsRevoked { get; set; } = false; - // public DateTime? RevokedAt { get; set; } TODO: Clear old UserSessions - - public UserCryptoSession CryptoSession { get; set; } + + public User User { get; set; } = null!; + public UserCryptoSession CryptoSession { get; set; } = null!; public override bool Equals(object? obj) { - UserSession? userSession = obj as UserSession; + if (obj is not UserSession userSession) + return false; return Id == userSession.Id && UserId == userSession.UserId && @@ -27,4 +28,9 @@ public class UserSession ExpiresAt == userSession.ExpiresAt && IsRevoked == userSession.IsRevoked; } + + public override int GetHashCode() + { + return HashCode.Combine(Id, UserId, RefreshTokenHash, DeviceInfo, CreatedAt, ExpiresAt, IsRevoked); + } } \ No newline at end of file diff --git a/Govor.sln b/Govor.sln index 271c981..adbac74 100644 --- a/Govor.sln +++ b/Govor.sln @@ -4,10 +4,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Govor.API.Tests", "Govor.AP EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Govor.API", "Govor.API\Govor.API.csproj", "{EA8F272F-4276-438A-9DEA-C58860A440AE}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Govor.Core", "Govor.Core\Govor.Core.csproj", "{F7BB1EC7-63D6-4525-ADE4-E4AC937E219D}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Govor.Data", "Govor.Data\Govor.Data.csproj", "{E4EDB179-7EB5-468D-9C1F-0CBE2E5E459E}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Govor.ConsoleClient", "Govor.ConsoleClient\Govor.ConsoleClient.csproj", "{F4535DC3-BDFB-4EB2-B259-F92B6BBB535B}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{4ED5259A-6FB4-4D89-8E6B-4778DC68F7D4}" @@ -27,6 +23,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Govor.Data.Tests", "Govor.D EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Govor.ConsoleClient.Tests", "Govor.ConsoleClient.Tests\Govor.ConsoleClient.Tests.csproj", "{B1E79EB6-DBD3-4E82-AB6D-DCFCE6533965}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Govor.Domain", "Govor.Domain\Govor.Domain.csproj", "{868EAA88-A8E8-4508-B264-1AE3576D47C1}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -41,14 +39,6 @@ Global {EA8F272F-4276-438A-9DEA-C58860A440AE}.Debug|Any CPU.Build.0 = Debug|Any CPU {EA8F272F-4276-438A-9DEA-C58860A440AE}.Release|Any CPU.ActiveCfg = Release|Any CPU {EA8F272F-4276-438A-9DEA-C58860A440AE}.Release|Any CPU.Build.0 = Release|Any CPU - {F7BB1EC7-63D6-4525-ADE4-E4AC937E219D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F7BB1EC7-63D6-4525-ADE4-E4AC937E219D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F7BB1EC7-63D6-4525-ADE4-E4AC937E219D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F7BB1EC7-63D6-4525-ADE4-E4AC937E219D}.Release|Any CPU.Build.0 = Release|Any CPU - {E4EDB179-7EB5-468D-9C1F-0CBE2E5E459E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E4EDB179-7EB5-468D-9C1F-0CBE2E5E459E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E4EDB179-7EB5-468D-9C1F-0CBE2E5E459E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E4EDB179-7EB5-468D-9C1F-0CBE2E5E459E}.Release|Any CPU.Build.0 = Release|Any CPU {F4535DC3-BDFB-4EB2-B259-F92B6BBB535B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F4535DC3-BDFB-4EB2-B259-F92B6BBB535B}.Debug|Any CPU.Build.0 = Debug|Any CPU {F4535DC3-BDFB-4EB2-B259-F92B6BBB535B}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -73,17 +63,20 @@ Global {B1E79EB6-DBD3-4E82-AB6D-DCFCE6533965}.Debug|Any CPU.Build.0 = Debug|Any CPU {B1E79EB6-DBD3-4E82-AB6D-DCFCE6533965}.Release|Any CPU.ActiveCfg = Release|Any CPU {B1E79EB6-DBD3-4E82-AB6D-DCFCE6533965}.Release|Any CPU.Build.0 = Release|Any CPU + {868EAA88-A8E8-4508-B264-1AE3576D47C1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {868EAA88-A8E8-4508-B264-1AE3576D47C1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {868EAA88-A8E8-4508-B264-1AE3576D47C1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {868EAA88-A8E8-4508-B264-1AE3576D47C1}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution {15031CBD-F319-4755-BA91-B86F20BD8E37} = {4ED5259A-6FB4-4D89-8E6B-4778DC68F7D4} {EA8F272F-4276-438A-9DEA-C58860A440AE} = {114F53C1-B0AB-4BA0-9E36-0E811D1B3776} {F4535DC3-BDFB-4EB2-B259-F92B6BBB535B} = {114F53C1-B0AB-4BA0-9E36-0E811D1B3776} - {F7BB1EC7-63D6-4525-ADE4-E4AC937E219D} = {114F53C1-B0AB-4BA0-9E36-0E811D1B3776} - {E4EDB179-7EB5-468D-9C1F-0CBE2E5E459E} = {114F53C1-B0AB-4BA0-9E36-0E811D1B3776} {4E94907F-BE20-42A6-AB15-637850FEAD11} = {114F53C1-B0AB-4BA0-9E36-0E811D1B3776} {FC5EDCA8-FD58-4078-8FB1-2BDBB2F6CA3E} = {114F53C1-B0AB-4BA0-9E36-0E811D1B3776} {F56A64DF-2938-4BE0-83F2-B86429F19259} = {4ED5259A-6FB4-4D89-8E6B-4778DC68F7D4} {CF6B23EC-932A-4998-BA95-C94CAB7B092C} = {4ED5259A-6FB4-4D89-8E6B-4778DC68F7D4} {B1E79EB6-DBD3-4E82-AB6D-DCFCE6533965} = {4ED5259A-6FB4-4D89-8E6B-4778DC68F7D4} + {868EAA88-A8E8-4508-B264-1AE3576D47C1} = {114F53C1-B0AB-4BA0-9E36-0E811D1B3776} EndGlobalSection EndGlobal