├── .tool-versions ├── docker ├── .env ├── docker-compose.yaml └── docker-compose.override.yaml ├── apps ├── allow │ ├── test │ │ ├── Agree.Allow.Test │ │ │ ├── Usings.cs │ │ │ ├── TestBase.cs │ │ │ ├── DependencyInjectionContainer.cs │ │ │ └── Agree.Allow.Test.csproj │ │ └── Agree.Allow.Domain.Test │ │ │ ├── Usings.cs │ │ │ ├── testsettings.json │ │ │ ├── Handlers │ │ │ └── Queries │ │ │ │ └── GetAccountByIdHandlerTest.cs │ │ │ ├── Tokens │ │ │ └── TokenTest.cs │ │ │ ├── Agree.Allow.Domain.Test.csproj │ │ │ ├── DiscriminatorTagTest.cs │ │ │ └── DiscriminatorTagFactoryTest.cs │ └── src │ │ ├── Agree.Allow.Domain │ │ ├── Requests │ │ │ ├── RefreshTokenRequest.cs │ │ │ ├── PasswordLoginRequest.cs │ │ │ ├── IAuthenticationRequest.cs │ │ │ ├── GetClientApplicationByAccessKeyRequest.cs │ │ │ ├── ValidateTokenRequest.cs │ │ │ ├── GetAccountByIdRequest.cs │ │ │ ├── SearchAccountsRequest.cs │ │ │ └── CreateAccountRequest.cs │ │ ├── IPasswordManager.cs │ │ ├── Tokens │ │ │ ├── JwtConfiguration.cs │ │ │ ├── Token.cs │ │ │ ├── RefreshTokenFactory.cs │ │ │ └── AccessTokenFactory.cs │ │ ├── Specifications │ │ │ ├── ClientApplicationAccessKeyEqualSpecification.cs │ │ │ ├── TagEqualSpecification.cs │ │ │ ├── UserIdEqualSpecification.cs │ │ │ ├── EmailEqualSpecification.cs │ │ │ ├── NameTagLikeSpecification.cs │ │ │ ├── UserNameEqualSpecification.cs │ │ │ └── NameTagEqualSpecification.cs │ │ ├── Results │ │ │ ├── TokenValidationResult.cs │ │ │ ├── CreateAccountResult.cs │ │ │ └── AuthenticationResult.cs │ │ ├── ClientApplication.cs │ │ ├── Agree.Allow.Domain.csproj │ │ ├── Handlers │ │ │ ├── Queries │ │ │ │ ├── GetAccountByIdHandler.cs │ │ │ │ ├── SearchAccountsHandler.cs │ │ │ │ └── GetClientApplicationByAccessKeyHandler.cs │ │ │ └── Commands │ │ │ │ ├── ValidateTokenHandler.cs │ │ │ │ ├── RefreshTokenHandler.cs │ │ │ │ └── PasswordLoginHandler.cs │ │ ├── DiscriminatorTagFactory.cs │ │ └── UserAccount.cs │ │ ├── Agree.Allow.Presentation │ │ ├── appsettings.json │ │ ├── Accounts │ │ │ └── ViewModels │ │ │ │ ├── AuthenticationViewModel.cs │ │ │ │ └── UserAccountViewModel.cs │ │ ├── Exceptions │ │ │ ├── EmptyBodyException.cs │ │ │ └── InvalidGrantTypeException.cs │ │ ├── Program.cs │ │ ├── appsettings.Example.json │ │ ├── Agree.Allow.Presentation.csproj │ │ ├── Properties │ │ │ └── launchSettings.json │ │ └── CustomControllerBase.cs │ │ ├── Agree.Allow.Infrastructure.Data │ │ ├── MappingProfile.cs │ │ ├── DatabaseOperationResult.cs │ │ ├── ApplicationDbContextFactory.cs │ │ ├── ClientApplicationDbModel.cs │ │ ├── ApplicationDbContext.cs │ │ ├── UserAccountDbModel.cs │ │ └── Agree.Allow.Infrastructure.Data.csproj │ │ ├── Agree.Allow.Infrastructure │ │ ├── BCryptPasswordManager.cs │ │ └── Agree.Allow.Infrastructure.csproj │ │ └── Agree.Allow.Infrastructure.IoC │ │ └── Agree.Allow.Infrastructure.IoC.csproj ├── accord │ ├── src │ │ ├── Agree.Accord.Domain │ │ │ ├── Servers │ │ │ │ ├── Requests │ │ │ │ │ ├── SendServerInviteRequest.cs │ │ │ │ │ ├── JoinServerRequest.cs │ │ │ │ │ ├── CreateServerInviteRequest.cs │ │ │ │ │ ├── GetServerByIdRequest.cs │ │ │ │ │ ├── SearchServersRequest.cs │ │ │ │ │ ├── CreateServerRequest.cs │ │ │ │ │ └── CreateCategoryRequest.cs │ │ │ │ ├── ServerPrivacy.cs │ │ │ │ ├── Specifications │ │ │ │ │ ├── BaseServerSpecification.cs │ │ │ │ │ ├── ServerVisibleToUserSpecification.cs │ │ │ │ │ ├── ServerInviteIdEqualSpecification.cs │ │ │ │ │ ├── ServerIdEqualSpecification.cs │ │ │ │ │ ├── BaseServerPaginatedSpecification.cs │ │ │ │ │ └── ServerInfoLikeSpecification.cs │ │ │ │ ├── Results │ │ │ │ │ ├── CreateServerResult.cs │ │ │ │ │ ├── CreateCategoryResult.cs │ │ │ │ │ └── JoinServerResult.cs │ │ │ │ ├── ServerInvite.cs │ │ │ │ ├── ServerRolePermission.cs │ │ │ │ ├── Category.cs │ │ │ │ ├── Handlers │ │ │ │ │ ├── Queries │ │ │ │ │ │ ├── GetServerByIdHandler.cs │ │ │ │ │ │ └── SearchServerHandler.cs │ │ │ │ │ └── Commands │ │ │ │ │ │ ├── CreateServerHandler.cs │ │ │ │ │ │ └── CreateCategoryHandler.cs │ │ │ │ ├── ServerMember.cs │ │ │ │ ├── ServerRole.cs │ │ │ │ └── Server.cs │ │ │ ├── Exceptions │ │ │ │ ├── FriendshipAlreadyAcceptedException.cs │ │ │ │ └── FriendshipRequestNotForUserException.cs │ │ │ ├── User.cs │ │ │ ├── Social │ │ │ │ ├── Notifications │ │ │ │ │ ├── FriendshipRequestAcceptedNotification.cs │ │ │ │ │ ├── FriendshipRequestCreatedNotification.cs │ │ │ │ │ ├── FriendshipRequestDeclinedNotification.cs │ │ │ │ │ └── DirectMessageCreatedNotification.cs │ │ │ │ ├── Specifications │ │ │ │ │ ├── FriendshipAcceptedSpecification.cs │ │ │ │ │ ├── SentFriendshipRequestSpecification.cs │ │ │ │ │ ├── FriendshipExistsSpecification.cs │ │ │ │ │ ├── ReceivedFriendshipRequestSpecification.cs │ │ │ │ │ ├── DirectMessageIdEqualSpecification.cs │ │ │ │ │ └── DirectMessageFromOrToFriendSpecification.cs │ │ │ │ ├── Results │ │ │ │ │ ├── DirectMessageResult.cs │ │ │ │ │ ├── RemoveFriendResult.cs │ │ │ │ │ ├── FriendshipRequestResult.cs │ │ │ │ │ └── DirectMessageReadResult.cs │ │ │ │ ├── IDirectMessageRepository.cs │ │ │ │ └── Handlers │ │ │ │ │ ├── Queries │ │ │ │ │ ├── GetFriendChatHandler.cs │ │ │ │ │ ├── GetDirectMessageByIdHandler.cs │ │ │ │ │ ├── GetUserSentFriendshipRequestsHandler.cs │ │ │ │ │ ├── GetUserReceivedFriendshipRequestsHandler.cs │ │ │ │ │ └── GetFriendsFromUserHandler.cs │ │ │ │ │ └── Commands │ │ │ │ │ ├── RemoveFriendHandler.cs │ │ │ │ │ ├── MarkDirectMessageAsReadHandler.cs │ │ │ │ │ ├── DeclineFriendshipRequestHandler.cs │ │ │ │ │ └── AcceptFriendshipRequestHandler.cs │ │ │ ├── Requests │ │ │ │ ├── GetFriendsFromUserRequest.cs │ │ │ │ ├── GetUserSentFriendshipRequestsRequest.cs │ │ │ │ ├── GetUserReceivedFriendshipRequestsRequest.cs │ │ │ │ ├── GetDirectMessageByIdRequest.cs │ │ │ │ ├── RemoveFriendRequest.cs │ │ │ │ ├── AcceptFriendshipRequestRequest.cs │ │ │ │ ├── DeclineFriendshipRequestRequest.cs │ │ │ │ ├── MarkDirectMessageAsReadRequest.cs │ │ │ │ ├── SendFriendshipRequestRequest.cs │ │ │ │ ├── SendDirectMessageRequest.cs │ │ │ │ └── GetFriendChatRequest.cs │ │ │ ├── Friendship.cs │ │ │ ├── Agree.Accord.Domain.csproj │ │ │ └── FriendshipRequest.cs │ │ ├── Agree.Accord.Presentation │ │ │ ├── appsettings.json │ │ │ ├── Shared │ │ │ │ ├── HubEvents.cs │ │ │ │ ├── SocketHub.cs │ │ │ │ ├── CustomControllerBase.cs │ │ │ │ └── CustomHubBase.cs │ │ │ ├── Responses │ │ │ │ ├── GenericResponse.cs │ │ │ │ └── ValidationErrorResponse.cs │ │ │ ├── Program.cs │ │ │ ├── Agree.Accord.Presentation.csproj │ │ │ ├── appsettings.Example.json │ │ │ ├── Properties │ │ │ │ └── launchSettings.json │ │ │ ├── Social │ │ │ │ ├── ViewModels │ │ │ │ │ ├── FriendshipRequestViewModel.cs │ │ │ │ │ └── DirectMessageViewModel.cs │ │ │ │ ├── Handlers │ │ │ │ │ ├── DirectMessageCreatedNotificationHandler.cs │ │ │ │ │ ├── FriendshipRequestCreatedNotificationHandler.cs │ │ │ │ │ ├── FriendshipRequestAcceptedNotificationHandler.cs │ │ │ │ │ └── FriendshipRequestDeclinedNotificationHandler.cs │ │ │ │ └── Controllers │ │ │ │ │ └── FriendsController.cs │ │ │ └── Servers │ │ │ │ └── ViewModels │ │ │ │ ├── ServerViewModel.cs │ │ │ │ └── RoleViewModel.cs │ │ ├── Agree.Accord.Infrastructure │ │ │ ├── Configuration │ │ │ │ └── NativeMailProviderOptions.cs │ │ │ ├── Agree.Accord.Infrastructure.csproj │ │ │ └── Providers │ │ │ │ └── NativeMailProvider.cs │ │ ├── Agree.Accord.Infrastructure.Data │ │ │ ├── DatabaseOperationResult.cs │ │ │ ├── ApplicationDbContextFactory.cs │ │ │ ├── Agree.Accord.Infrastructure.Data.csproj │ │ │ └── FriendshipRepository.cs │ │ └── Agree.Accord.Infrastructure.IoC │ │ │ └── Agree.Accord.Infrastructure.IoC.csproj │ ├── .config │ │ └── dotnet-tools.json │ ├── test │ │ └── Agree.Accord.Domain.Test │ │ │ ├── Agree.Accord.Domain.Test.csproj │ │ │ └── DiscriminatorTagTest.cs │ └── .vscode │ │ ├── launch.json │ │ ├── settings.json │ │ └── tasks.json └── concord_old │ ├── src │ ├── react-app-env.d.ts │ ├── logic │ │ ├── models │ │ │ ├── AccordErrorList.ts │ │ │ ├── Account.ts │ │ │ ├── Server.ts │ │ │ └── ServerPermissions.ts │ │ ├── services │ │ │ ├── ICache.ts │ │ │ ├── ILogger.ts │ │ │ ├── implementations │ │ │ │ ├── LocalStorageCache.ts │ │ │ │ ├── ConsoleLogger.ts │ │ │ │ └── AxiosHttpClient.ts │ │ │ └── IHttpClient.ts │ │ ├── hooks │ │ │ ├── useServers.ts │ │ │ ├── useSyncCacheState.ts │ │ │ └── useAllow.tsx │ │ ├── mappings │ │ │ └── ApiResponseToModelMapper.ts │ │ └── contexts │ │ │ └── ContextContainer.tsx │ ├── presentation │ │ ├── components │ │ │ ├── avatar │ │ │ │ ├── FriendListItem.scss │ │ │ │ ├── ServerAvatar.scss │ │ │ │ ├── UserAvatar.tsx │ │ │ │ └── FriendListItem.tsx │ │ │ ├── form │ │ │ │ ├── SquareButton.tsx │ │ │ │ ├── Button.tsx │ │ │ │ ├── TextInput.tsx │ │ │ │ └── PasswordInput.tsx │ │ │ └── nav │ │ │ │ └── ServerBar.tsx │ │ ├── assets │ │ │ ├── bg404.png │ │ │ └── bglogin.png │ │ ├── layouts │ │ │ ├── SettingsLayout.scss │ │ │ └── DashboardLayout.tsx │ │ ├── hooks │ │ │ ├── useI18n.ts │ │ │ ├── useInputState.ts │ │ │ ├── useBreakpoints.ts │ │ │ └── useLoading.ts │ │ ├── pages │ │ │ ├── settings │ │ │ │ ├── ProfileSettingsPage.tsx │ │ │ │ └── AppearanceSettingsPage.tsx │ │ │ ├── dashboard │ │ │ │ ├── HomePage.tsx │ │ │ │ └── ServerCreate.tsx │ │ │ └── error │ │ │ │ └── NotFoundPage.tsx │ │ ├── App.tsx │ │ ├── styles │ │ │ ├── theme.ts │ │ │ └── utils.scss │ │ └── Routes.tsx │ ├── validation │ │ ├── IValidator.ts │ │ └── RegisterValidator.ts │ ├── i18n │ │ └── index.ts │ ├── index.tsx │ └── reportWebVitals.ts │ ├── public │ ├── robots.txt │ ├── favicon.ico │ ├── apple-icon.png │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ ├── favicon-96x96.png │ ├── ms-icon-144x144.png │ ├── ms-icon-150x150.png │ ├── ms-icon-310x310.png │ ├── ms-icon-70x70.png │ ├── apple-icon-57x57.png │ ├── apple-icon-60x60.png │ ├── apple-icon-72x72.png │ ├── apple-icon-76x76.png │ ├── android-icon-144x144.png │ ├── android-icon-192x192.png │ ├── android-icon-36x36.png │ ├── android-icon-48x48.png │ ├── android-icon-72x72.png │ ├── android-icon-96x96.png │ ├── apple-icon-114x114.png │ ├── apple-icon-120x120.png │ ├── apple-icon-144x144.png │ ├── apple-icon-152x152.png │ ├── apple-icon-180x180.png │ ├── apple-icon-precomposed.png │ ├── browserconfig.xml │ └── manifest.json │ ├── .env.example │ ├── .gitignore │ ├── tsconfig.json │ ├── README.md │ ├── .vscode │ └── settings.json │ ├── .eslintrc.js │ └── package.json ├── .vscode ├── settings.json ├── launch.json └── tasks.json └── LICENSE /.tool-versions: -------------------------------------------------------------------------------- 1 | dotnet 6.0.401 2 | -------------------------------------------------------------------------------- /docker/.env: -------------------------------------------------------------------------------- 1 | COMPOSE_PROJECT_NAME=agree -------------------------------------------------------------------------------- /apps/allow/test/Agree.Allow.Test/Usings.cs: -------------------------------------------------------------------------------- 1 | global using Xunit; -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Servers/Requests/SendServerInviteRequest.cs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/concord_old/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /apps/concord_old/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /apps/concord_old/src/logic/models/AccordErrorList.ts: -------------------------------------------------------------------------------- 1 | export type AccordErrorList = Record 2 | -------------------------------------------------------------------------------- /apps/concord_old/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vassourita/agree/HEAD/apps/concord_old/public/favicon.ico -------------------------------------------------------------------------------- /apps/concord_old/public/apple-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vassourita/agree/HEAD/apps/concord_old/public/apple-icon.png -------------------------------------------------------------------------------- /apps/allow/test/Agree.Allow.Domain.Test/Usings.cs: -------------------------------------------------------------------------------- 1 | global using System; 2 | global using Agree.Allow.Domain; 3 | global using Xunit; -------------------------------------------------------------------------------- /apps/concord_old/.env.example: -------------------------------------------------------------------------------- 1 | REACT_APP_ALLOW_URL=http://localhost:5000/api 2 | REACT_APP_ACCORD_URL=http://localhost:4000/api 3 | -------------------------------------------------------------------------------- /apps/concord_old/public/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vassourita/agree/HEAD/apps/concord_old/public/favicon-16x16.png -------------------------------------------------------------------------------- /apps/concord_old/public/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vassourita/agree/HEAD/apps/concord_old/public/favicon-32x32.png -------------------------------------------------------------------------------- /apps/concord_old/public/favicon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vassourita/agree/HEAD/apps/concord_old/public/favicon-96x96.png -------------------------------------------------------------------------------- /apps/concord_old/public/ms-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vassourita/agree/HEAD/apps/concord_old/public/ms-icon-144x144.png -------------------------------------------------------------------------------- /apps/concord_old/public/ms-icon-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vassourita/agree/HEAD/apps/concord_old/public/ms-icon-150x150.png -------------------------------------------------------------------------------- /apps/concord_old/public/ms-icon-310x310.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vassourita/agree/HEAD/apps/concord_old/public/ms-icon-310x310.png -------------------------------------------------------------------------------- /apps/concord_old/public/ms-icon-70x70.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vassourita/agree/HEAD/apps/concord_old/public/ms-icon-70x70.png -------------------------------------------------------------------------------- /apps/concord_old/public/apple-icon-57x57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vassourita/agree/HEAD/apps/concord_old/public/apple-icon-57x57.png -------------------------------------------------------------------------------- /apps/concord_old/public/apple-icon-60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vassourita/agree/HEAD/apps/concord_old/public/apple-icon-60x60.png -------------------------------------------------------------------------------- /apps/concord_old/public/apple-icon-72x72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vassourita/agree/HEAD/apps/concord_old/public/apple-icon-72x72.png -------------------------------------------------------------------------------- /apps/concord_old/public/apple-icon-76x76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vassourita/agree/HEAD/apps/concord_old/public/apple-icon-76x76.png -------------------------------------------------------------------------------- /apps/concord_old/public/android-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vassourita/agree/HEAD/apps/concord_old/public/android-icon-144x144.png -------------------------------------------------------------------------------- /apps/concord_old/public/android-icon-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vassourita/agree/HEAD/apps/concord_old/public/android-icon-192x192.png -------------------------------------------------------------------------------- /apps/concord_old/public/android-icon-36x36.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vassourita/agree/HEAD/apps/concord_old/public/android-icon-36x36.png -------------------------------------------------------------------------------- /apps/concord_old/public/android-icon-48x48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vassourita/agree/HEAD/apps/concord_old/public/android-icon-48x48.png -------------------------------------------------------------------------------- /apps/concord_old/public/android-icon-72x72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vassourita/agree/HEAD/apps/concord_old/public/android-icon-72x72.png -------------------------------------------------------------------------------- /apps/concord_old/public/android-icon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vassourita/agree/HEAD/apps/concord_old/public/android-icon-96x96.png -------------------------------------------------------------------------------- /apps/concord_old/public/apple-icon-114x114.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vassourita/agree/HEAD/apps/concord_old/public/apple-icon-114x114.png -------------------------------------------------------------------------------- /apps/concord_old/public/apple-icon-120x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vassourita/agree/HEAD/apps/concord_old/public/apple-icon-120x120.png -------------------------------------------------------------------------------- /apps/concord_old/public/apple-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vassourita/agree/HEAD/apps/concord_old/public/apple-icon-144x144.png -------------------------------------------------------------------------------- /apps/concord_old/public/apple-icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vassourita/agree/HEAD/apps/concord_old/public/apple-icon-152x152.png -------------------------------------------------------------------------------- /apps/concord_old/public/apple-icon-180x180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vassourita/agree/HEAD/apps/concord_old/public/apple-icon-180x180.png -------------------------------------------------------------------------------- /apps/concord_old/src/presentation/components/avatar/FriendListItem.scss: -------------------------------------------------------------------------------- 1 | .FriendListItemContainer.active { 2 | background-color: #5a189a; 3 | } 4 | -------------------------------------------------------------------------------- /apps/concord_old/public/apple-icon-precomposed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vassourita/agree/HEAD/apps/concord_old/public/apple-icon-precomposed.png -------------------------------------------------------------------------------- /apps/concord_old/src/presentation/assets/bg404.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vassourita/agree/HEAD/apps/concord_old/src/presentation/assets/bg404.png -------------------------------------------------------------------------------- /apps/concord_old/src/presentation/assets/bglogin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vassourita/agree/HEAD/apps/concord_old/src/presentation/assets/bglogin.png -------------------------------------------------------------------------------- /apps/concord_old/src/presentation/layouts/SettingsLayout.scss: -------------------------------------------------------------------------------- 1 | .SettingsLayoutNavLinkContainer > a.active { 2 | background-color: var(--chakra-colors-brand-800); 3 | } 4 | -------------------------------------------------------------------------------- /apps/concord_old/src/logic/models/Account.ts: -------------------------------------------------------------------------------- 1 | export type Account = { 2 | id: string 3 | tag: string 4 | email: string 5 | userName: string 6 | verified: boolean 7 | } 8 | -------------------------------------------------------------------------------- /apps/concord_old/src/validation/IValidator.ts: -------------------------------------------------------------------------------- 1 | import { ValidationError } from 'yup' 2 | 3 | export interface IValidator { 4 | validate(input: T): Promise 5 | } 6 | -------------------------------------------------------------------------------- /apps/allow/src/Agree.Allow.Domain/Requests/RefreshTokenRequest.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Allow.Domain.Requests; 2 | 3 | public record RefreshTokenRequest(string RefreshToken) : IAuthenticationRequest 4 | { 5 | } -------------------------------------------------------------------------------- /apps/allow/src/Agree.Allow.Domain/Requests/PasswordLoginRequest.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Allow.Domain.Requests; 2 | 3 | public record PasswordLoginRequest(string EmailAddress, string Password) : IAuthenticationRequest 4 | { 5 | } -------------------------------------------------------------------------------- /apps/concord_old/src/logic/models/Server.ts: -------------------------------------------------------------------------------- 1 | export type Server = { 2 | name: string 3 | privacy: number 4 | privacyStr: string 5 | description: string 6 | roles: [] 7 | members: [] 8 | categories: [] 9 | } 10 | -------------------------------------------------------------------------------- /apps/accord/.config/dotnet-tools.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "isRoot": true, 4 | "tools": { 5 | "dotnet-ef": { 6 | "version": "6.0.7", 7 | "commands": [ 8 | "dotnet-ef" 9 | ] 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /apps/allow/src/Agree.Allow.Presentation/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | }, 8 | "AllowedHosts": "*" 9 | } 10 | -------------------------------------------------------------------------------- /apps/allow/src/Agree.Allow.Domain/Requests/IAuthenticationRequest.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Allow.Domain.Requests; 2 | 3 | using Agree.Allow.Domain.Results; 4 | using MediatR; 5 | 6 | public interface IAuthenticationRequest : IRequest 7 | { 8 | } -------------------------------------------------------------------------------- /apps/allow/src/Agree.Allow.Domain/Requests/GetClientApplicationByAccessKeyRequest.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Allow.Domain.Requests; 2 | 3 | using MediatR; 4 | 5 | public record GetClientApplicationByAccessKeyRequest(string AccessKey) : IRequest 6 | { 7 | } -------------------------------------------------------------------------------- /apps/concord_old/src/logic/models/ServerPermissions.ts: -------------------------------------------------------------------------------- 1 | export type ServerPermissions = { 2 | canAddUsers: string 3 | canRemoveUsers: string 4 | canUpdateServerDescription: string 5 | canUpdateServerName: string 6 | canUpdateServerPrivacy: string 7 | } 8 | -------------------------------------------------------------------------------- /apps/allow/src/Agree.Allow.Domain/Requests/ValidateTokenRequest.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Allow.Domain.Requests; 2 | 3 | using Agree.Allow.Domain.Results; 4 | using MediatR; 5 | 6 | public record ValidateTokenRequest(string Token) : IRequest 7 | { 8 | } -------------------------------------------------------------------------------- /apps/concord_old/src/logic/services/ICache.ts: -------------------------------------------------------------------------------- 1 | export interface ICache { 2 | get (key: string): string | null 3 | get (key: string): T | null 4 | set (key: string, value: string): void 5 | set (key: string, value: T): void 6 | delete (key: string): void 7 | } 8 | -------------------------------------------------------------------------------- /apps/concord_old/src/i18n/index.ts: -------------------------------------------------------------------------------- 1 | import { Resource } from '../presentation/contexts/I18nContext' 2 | 3 | import enUS from './en-US.json' 4 | import ptBR from './pt-BR.json' 5 | 6 | export const resource: Resource = { 7 | 'en-US': enUS, 8 | 'pt-BR': ptBR 9 | } 10 | -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Servers/ServerPrivacy.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain.Servers; 2 | 3 | /// 4 | /// Representation of a server privacy level. 5 | /// 6 | public enum ServerPrivacy 7 | { 8 | Public, 9 | Private, 10 | Secret 11 | } -------------------------------------------------------------------------------- /apps/concord_old/src/logic/services/ILogger.ts: -------------------------------------------------------------------------------- 1 | export type LoggingLevel = 'info' | 'warn' | 'error' 2 | 3 | export interface ILogger { 4 | log(level: LoggingLevel, message: any): void 5 | info(message: any): void 6 | warn(message: any): void 7 | error(message: any): void 8 | } 9 | -------------------------------------------------------------------------------- /apps/concord_old/src/presentation/hooks/useI18n.ts: -------------------------------------------------------------------------------- 1 | import { useContext } from 'react' 2 | import { I18nContext, I18nContextProps } from '../contexts/I18nContext' 3 | 4 | export function useI18n (): I18nContextProps { 5 | const ctx = useContext(I18nContext) 6 | 7 | return ctx 8 | } 9 | -------------------------------------------------------------------------------- /apps/allow/src/Agree.Allow.Domain/Requests/GetAccountByIdRequest.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Allow.Domain.Requests; 2 | 3 | using System; 4 | using System.ComponentModel.DataAnnotations; 5 | using MediatR; 6 | 7 | public record GetAccountByIdRequest([Required] Guid Id) : IRequest 8 | { 9 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Presentation/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | }, 9 | "AllowedHosts": "*" 10 | } 11 | -------------------------------------------------------------------------------- /apps/allow/src/Agree.Allow.Domain/IPasswordManager.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Allow.Domain; 2 | 3 | using System.Threading.Tasks; 4 | 5 | public interface IPasswordManager 6 | { 7 | Task HashAsync(string password); 8 | 9 | Task CompareAsync(string hashed, string password); 10 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.exclude": { 3 | "**/.git": true, 4 | "**/.svn": true, 5 | "**/.hg": true, 6 | "**/CVS": true, 7 | "**/.DS_Store": true, 8 | "**/Thumbs.db": true, 9 | "**/obj": true, 10 | "**/bin": true, 11 | } 12 | } -------------------------------------------------------------------------------- /apps/concord_old/src/presentation/pages/settings/ProfileSettingsPage.tsx: -------------------------------------------------------------------------------- 1 | import { Flex, Heading } from '@chakra-ui/layout' 2 | 3 | export function ProfileSettingsPage (): JSX.Element { 4 | return ( 5 | 6 | Meu perfil 7 | 8 | ) 9 | } 10 | -------------------------------------------------------------------------------- /apps/allow/src/Agree.Allow.Presentation/Accounts/ViewModels/AuthenticationViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Allow.Presentation.Accounts.ViewModels; 2 | 3 | using Agree.Allow.Domain.Tokens; 4 | 5 | public record AuthenticationViewModel(TokenCollection Tokens) 6 | : TokenCollection(Tokens.RefreshToken, Tokens.AccessToken); -------------------------------------------------------------------------------- /apps/concord_old/public/browserconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | #ffffff -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Exceptions/FriendshipAlreadyAcceptedException.cs: -------------------------------------------------------------------------------- 1 | using Agree.SharedKernel.Exceptions; 2 | 3 | public class FriendshipAlreadyAcceptedException : DomainException 4 | { 5 | public FriendshipAlreadyAcceptedException() : base("Accepted", "Friendship already accepted.") 6 | { 7 | } 8 | } -------------------------------------------------------------------------------- /apps/concord_old/src/logic/hooks/useServers.ts: -------------------------------------------------------------------------------- 1 | import { useContext } from 'react' 2 | import { ServerContext, ServerContextProps } from '../contexts/ServerContext' 3 | 4 | export function useServers (): ServerContextProps { 5 | const ctx = useContext(ServerContext) 6 | 7 | return { 8 | ...ctx 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /apps/concord_old/src/presentation/pages/settings/AppearanceSettingsPage.tsx: -------------------------------------------------------------------------------- 1 | import { Flex, Heading } from '@chakra-ui/layout' 2 | 3 | export function AppearanceSettingsPage (): JSX.Element { 4 | return ( 5 | 6 | Aparência e tema 7 | 8 | ) 9 | } 10 | -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Exceptions/FriendshipRequestNotForUserException.cs: -------------------------------------------------------------------------------- 1 | using Agree.SharedKernel.Exceptions; 2 | 3 | public class FriendshipRequestNotForUserException : DomainException 4 | { 5 | public FriendshipRequestNotForUserException() : base("To", "Friendship request not for the user.") 6 | { 7 | } 8 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/User.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain; 2 | 3 | using System; 4 | 5 | public class User 6 | { 7 | public Guid Id { get; private set; } 8 | public string Username { get; private set; } 9 | public string Tag { get; private set; } 10 | public virtual string NameTag => $"{Username}#{Tag}"; 11 | } -------------------------------------------------------------------------------- /apps/allow/src/Agree.Allow.Domain/Tokens/JwtConfiguration.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Allow.Domain.Tokens; 2 | 3 | public class JwtConfiguration 4 | { 5 | public string SigningKey { get; set; } 6 | public string Issuer { get; set; } 7 | public int AccessTokenExpiresInMinutes { get; set; } 8 | public int RefreshTokenExpiresInDays { get; set; } 9 | } -------------------------------------------------------------------------------- /apps/allow/src/Agree.Allow.Domain/Requests/SearchAccountsRequest.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Allow.Domain.Requests; 2 | 3 | using System.Collections.Generic; 4 | using Agree.SharedKernel.Data; 5 | using MediatR; 6 | 7 | public class SearchAccountsRequest : Pagination, IRequest> 8 | { 9 | public string Query { get; set; } 10 | } -------------------------------------------------------------------------------- /apps/concord_old/src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom' 3 | import { App } from './presentation/App' 4 | import reportWebVitals from './reportWebVitals' 5 | 6 | ReactDOM.render( 7 | 8 | 9 | , 10 | document.getElementById('root') 11 | ) 12 | 13 | reportWebVitals() 14 | -------------------------------------------------------------------------------- /apps/concord_old/src/presentation/components/avatar/ServerAvatar.scss: -------------------------------------------------------------------------------- 1 | .ServerAvatarContainer { 2 | position: relative; 3 | & > .active::after { 4 | content: ''; 5 | width: 60px; 6 | height: 60px; 7 | right: -5px; 8 | bottom: -5px; 9 | position: absolute; 10 | border: 2px solid white; 11 | border-radius: 13px; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /docker/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: '3.7' 2 | 3 | services: 4 | accord_postgres: 5 | image: postgres:13-alpine 6 | allow_postgres: 7 | image: postgres:13-alpine 8 | 9 | volumes: 10 | accord_postgres_volume: 11 | allow_postgres_volume: 12 | 13 | 14 | networks: 15 | accord-network: 16 | driver: bridge 17 | allow-network: 18 | driver: bridge 19 | -------------------------------------------------------------------------------- /apps/allow/src/Agree.Allow.Presentation/Exceptions/EmptyBodyException.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Allow.Presentation.Exceptions; 2 | 3 | using System; 4 | using Agree.SharedKernel.Exceptions; 5 | 6 | [Serializable] 7 | public class EmptyBodyException : AgreeException 8 | { 9 | public EmptyBodyException() 10 | : base("Body", "Empty request body") 11 | { 12 | } 13 | } -------------------------------------------------------------------------------- /apps/concord_old/src/presentation/pages/dashboard/HomePage.tsx: -------------------------------------------------------------------------------- 1 | import { Flex, Heading } from '@chakra-ui/layout' 2 | import { useLocation } from 'react-router' 3 | 4 | export function HomePage () : JSX.Element { 5 | const location = useLocation() 6 | 7 | return ( 8 | 9 | {location.pathname} 10 | 11 | ) 12 | } 13 | -------------------------------------------------------------------------------- /apps/concord_old/src/presentation/pages/dashboard/ServerCreate.tsx: -------------------------------------------------------------------------------- 1 | import { Flex, Heading } from '@chakra-ui/layout' 2 | 3 | export function ServerCreate (): JSX.Element { 4 | return ( 5 | 6 | 7 | Criar novo servidor 8 | 9 | 10 | ) 11 | } 12 | -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Social/Notifications/FriendshipRequestAcceptedNotification.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain.Social.Notifications; 2 | 3 | using MediatR; 4 | 5 | public class FriendshipRequestAcceptedNotification : INotification 6 | { 7 | public FriendshipRequestAcceptedNotification(Friendship friendship) 8 | => Friendship = friendship; 9 | 10 | public Friendship Friendship { get; } 11 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Social/Notifications/FriendshipRequestCreatedNotification.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain.Social.Notifications; 2 | 3 | using MediatR; 4 | 5 | public class FriendshipRequestCreatedNotification : INotification 6 | { 7 | public FriendshipRequestCreatedNotification(Friendship friendship) 8 | => Friendship = friendship; 9 | 10 | public Friendship Friendship { get; } 11 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Social/Notifications/FriendshipRequestDeclinedNotification.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain.Social.Notifications; 2 | 3 | using MediatR; 4 | 5 | public class FriendshipRequestDeclinedNotification : INotification 6 | { 7 | public FriendshipRequestDeclinedNotification(Friendship friendship) 8 | => Friendship = friendship; 9 | 10 | public Friendship Friendship { get; } 11 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Social/Notifications/DirectMessageCreatedNotification.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain.Social.Notifications; 2 | 3 | using MediatR; 4 | 5 | public class DirectMessageCreatedNotification : INotification 6 | { 7 | public DirectMessageCreatedNotification(DirectMessage directMessage) 8 | => DirectMessage = directMessage; 9 | 10 | public DirectMessage DirectMessage { get; } 11 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Presentation/Shared/HubEvents.cs: -------------------------------------------------------------------------------- 1 | public static class HubEvents 2 | { 3 | public const string FriendshipRequestCreated = "FriendshipRequestCreated"; 4 | public const string FriendshipRequestDeclined = "FriendshipRequestDeclined"; 5 | public const string FriendshipRequestAccepted = "FriendshipRequestAccepted"; 6 | 7 | public const string DirectMessageCreated = "DirectMessageCreated"; 8 | 9 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Presentation/Responses/GenericResponse.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Presentation.Responses; 2 | 3 | public class GenericResponse 4 | { 5 | public GenericResponse(object data) => Data = data; 6 | 7 | public object Data { get; private set; } 8 | } 9 | 10 | public class GenericResponse 11 | { 12 | public GenericResponse(T data) => Data = data; 13 | 14 | public T Data { get; private set; } 15 | } -------------------------------------------------------------------------------- /apps/allow/src/Agree.Allow.Domain/Specifications/ClientApplicationAccessKeyEqualSpecification.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Allow.Domain.Specifications; 2 | 3 | using Agree.SharedKernel.Data; 4 | 5 | public class ClientApplicationAccessKeyEqualSpecification : Specification 6 | { 7 | public ClientApplicationAccessKeyEqualSpecification(string accessKey) 8 | => Expression = x 9 | => x.AccessKey == accessKey; 10 | } -------------------------------------------------------------------------------- /apps/concord_old/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | 25 | .env -------------------------------------------------------------------------------- /apps/concord_old/src/presentation/hooks/useInputState.ts: -------------------------------------------------------------------------------- 1 | import { ChangeEventHandler, useState } from 'react' 2 | 3 | export function useInputState (defaultValue?: string): [string, ChangeEventHandler] { 4 | const [state, setState] = useState(defaultValue || '') 5 | 6 | const onChange: ChangeEventHandler = (e) => { 7 | setState(e.target.value) 8 | } 9 | 10 | return [state, onChange] 11 | } 12 | -------------------------------------------------------------------------------- /apps/concord_old/src/presentation/App.tsx: -------------------------------------------------------------------------------- 1 | import { BrowserRouter } from 'react-router-dom' 2 | 3 | import { Routes } from './Routes' 4 | import { ContextContainer } from '../logic/contexts/ContextContainer' 5 | 6 | import './styles/utils.scss' 7 | 8 | export function App (): JSX.Element { 9 | return ( 10 | 11 | 12 | 13 | 14 | 15 | ) 16 | } 17 | -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Servers/Requests/JoinServerRequest.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain.Servers.Requests; 2 | 3 | using System; 4 | using Agree.Accord.Domain.Identity; 5 | using Agree.Accord.Domain.Servers.Results; 6 | using MediatR; 7 | 8 | public class JoinServerRequest : IRequest 9 | { 10 | public Guid ServerId { get; set; } 11 | public UserAccount User { get; set; } 12 | public Guid? InviteId { get; set; } 13 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Servers/Requests/CreateServerInviteRequest.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain.Servers.Requests; 2 | 3 | using System; 4 | using Agree.Accord.Domain.Identity; 5 | using Agree.Accord.Domain.Servers.Results; 6 | using MediatR; 7 | 8 | public class CreateServerInviteRequest : IRequest 9 | { 10 | public Guid ServerId { get; set; } 11 | public UserAccount Inviter { get; set; } 12 | public DateTime ExpirationDate { get; set; } 13 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Infrastructure/Configuration/NativeMailProviderOptions.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Infrastructure.Configuration; 2 | 3 | /// 4 | /// The configuration for the class. 5 | /// 6 | public class NativeMailProviderOptions 7 | { 8 | public string Host { get; set; } 9 | public int Port { get; set; } 10 | public string UserName { get; set; } 11 | public string Password { get; set; } 12 | } -------------------------------------------------------------------------------- /apps/allow/src/Agree.Allow.Domain/Specifications/TagEqualSpecification.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Allow.Domain.Specifications; 2 | 3 | using Agree.SharedKernel.Data; 4 | 5 | public class TagEqualSpecification : Specification 6 | { 7 | public TagEqualSpecification(DiscriminatorTag tag) 8 | => Expression = x 9 | => x.Tag == tag; 10 | 11 | public TagEqualSpecification(UserAccount account) 12 | => Expression = x 13 | => x.Tag == account.Tag; 14 | } -------------------------------------------------------------------------------- /apps/concord_old/src/logic/mappings/ApiResponseToModelMapper.ts: -------------------------------------------------------------------------------- 1 | import { Server } from '../models/Server' 2 | 3 | export class ApiResponseToModelMapper { 4 | public static mapServer (data: any): Server { 5 | return { 6 | name: data.name, 7 | description: data.description, 8 | members: data.members, 9 | categories: data.categories, 10 | roles: data.roles, 11 | privacy: data.privacy, 12 | privacyStr: data.privacy_str 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Requests/GetFriendsFromUserRequest.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain.Social.Requests; 2 | 3 | using System.Collections.Generic; 4 | using System.ComponentModel.DataAnnotations; 5 | using MediatR; 6 | 7 | public class GetFriendsFromUserRequest : IRequest> 8 | { 9 | public GetFriendsFromUserRequest() { } 10 | public GetFriendsFromUserRequest(User user) => User = user; 11 | 12 | [Required] 13 | public User User { get; set; } 14 | } -------------------------------------------------------------------------------- /apps/concord_old/src/presentation/styles/theme.ts: -------------------------------------------------------------------------------- 1 | import { extendTheme } from '@chakra-ui/react' 2 | 3 | export const theme = extendTheme({ 4 | colors: { 5 | brand: { 6 | 900: '#201F29', 7 | 800: '#20152F', 8 | 700: '#3C096C', 9 | 600: '#5A189A', 10 | 500: '#7B2CBF', 11 | 400: '#9D4EDD' 12 | } 13 | }, 14 | fonts: { 15 | heading: 'Sarabun', 16 | body: 'Sarabun' 17 | }, 18 | config: { 19 | initialColorMode: 'dark' 20 | } 21 | }) 22 | -------------------------------------------------------------------------------- /apps/allow/src/Agree.Allow.Domain/Results/TokenValidationResult.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Allow.Domain.Results; 2 | 3 | using Agree.SharedKernel; 4 | 5 | public class TokenValidationResult : Result 6 | { 7 | private TokenValidationResult(UserAccount user) : base(user) 8 | { } 9 | private TokenValidationResult() : base() 10 | { } 11 | 12 | public static TokenValidationResult Ok(UserAccount user) => new(user); 13 | public static TokenValidationResult Fail() => new(); 14 | } -------------------------------------------------------------------------------- /apps/allow/src/Agree.Allow.Domain/Specifications/UserIdEqualSpecification.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Allow.Domain.Specifications; 2 | 3 | using System; 4 | using Agree.SharedKernel.Data; 5 | 6 | public class UserIdEqualSpecification : Specification 7 | { 8 | public UserIdEqualSpecification(Guid id) 9 | => Expression = x 10 | => x.Id == id; 11 | 12 | public UserIdEqualSpecification(UserAccount account) 13 | => Expression = x 14 | => x.Id == account.Id; 15 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Presentation/Responses/ValidationErrorResponse.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Presentation.Responses; 2 | 3 | using Agree.Accord.SharedKernel; 4 | 5 | /// 6 | /// The response to a validation error. 7 | /// 8 | public class ValidationErrorResponse 9 | { 10 | public ValidationErrorResponse(ErrorList errors) => Errors = errors; 11 | public ErrorList Errors { get; private set; } 12 | public string Message => "One or more validation errors occurred."; 13 | } -------------------------------------------------------------------------------- /apps/allow/src/Agree.Allow.Domain/Specifications/EmailEqualSpecification.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Allow.Domain.Specifications; 2 | 3 | using Agree.SharedKernel.Data; 4 | 5 | public class EmailEqualSpecification : Specification 6 | { 7 | public EmailEqualSpecification(string email) 8 | => Expression = x 9 | => x.EmailAddress == email; 10 | 11 | public EmailEqualSpecification(UserAccount account) 12 | => Expression = x 13 | => x.EmailAddress == account.EmailAddress; 14 | } -------------------------------------------------------------------------------- /apps/concord_old/src/presentation/hooks/useBreakpoints.ts: -------------------------------------------------------------------------------- 1 | import { useBreakpoint } from '@chakra-ui/media-query' 2 | 3 | export function useBreakpoints (): boolean[] { 4 | const breakpoint = useBreakpoint() 5 | 6 | return [ 7 | breakpoint === 'base', 8 | ['base', 'sm'].includes(breakpoint || ''), 9 | ['base', 'sm', 'md'].includes(breakpoint || ''), 10 | ['base', 'sm', 'md', 'lg'].includes(breakpoint || ''), 11 | ['base', 'sm', 'md', 'lg', ' xl'].includes(breakpoint || '') 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /apps/concord_old/src/reportWebVitals.ts: -------------------------------------------------------------------------------- 1 | import { ReportHandler } from 'web-vitals' 2 | 3 | const reportWebVitals = (onPerfEntry?: ReportHandler): void => { 4 | if (onPerfEntry && onPerfEntry instanceof Function) { 5 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 6 | getCLS(onPerfEntry) 7 | getFID(onPerfEntry) 8 | getFCP(onPerfEntry) 9 | getLCP(onPerfEntry) 10 | getTTFB(onPerfEntry) 11 | }) 12 | } 13 | } 14 | 15 | export default reportWebVitals 16 | -------------------------------------------------------------------------------- /apps/allow/src/Agree.Allow.Domain/Results/CreateAccountResult.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Allow.Domain.Results; 2 | 3 | using Agree.SharedKernel; 4 | 5 | public class CreateAccountResult : Result 6 | { 7 | private CreateAccountResult(UserAccount user) : base((user)) 8 | { } 9 | private CreateAccountResult(ErrorList error) : base(error) 10 | { } 11 | 12 | public static CreateAccountResult Ok(UserAccount user) => new(user); 13 | public static CreateAccountResult Fail(ErrorList data) => new(data); 14 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Servers/Specifications/BaseServerSpecification.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Linq.Expressions; 4 | using Agree.Accord.Domain.Servers; 5 | using Agree.Accord.SharedKernel.Data; 6 | 7 | public abstract class BaseServerSpecification : AndSpecification 8 | { 9 | public BaseServerSpecification(Expression> expression, Guid userId) 10 | : base(new GenericSpecification(expression), new ServerVisibleToUserSpecification(userId)) 11 | { } 12 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Servers/Specifications/ServerVisibleToUserSpecification.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using Agree.Accord.Domain.Servers; 4 | using Agree.Accord.SharedKernel.Data; 5 | 6 | public class ServerVisibleToUserSpecification : Specification 7 | { 8 | public ServerVisibleToUserSpecification(Guid userId) 9 | => Expression = x 10 | => (x.PrivacyLevel == ServerPrivacy.Public || x.PrivacyLevel == ServerPrivacy.Private) 11 | || x.Members.Any(m => m.UserId == userId); 12 | } -------------------------------------------------------------------------------- /apps/allow/src/Agree.Allow.Presentation/Program.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Allow.Presentation; 2 | 3 | using Microsoft.AspNetCore.Hosting; 4 | using Microsoft.Extensions.Hosting; 5 | 6 | public class Program 7 | { 8 | public static void Main(string[] args) => CreateHostBuilder(args).Build().Run(); 9 | 10 | public static IHostBuilder CreateHostBuilder(string[] args) 11 | => Host 12 | .CreateDefaultBuilder(args) 13 | .ConfigureWebHostDefaults(webBuilder => webBuilder.UseStartup()); 14 | } 15 | -------------------------------------------------------------------------------- /apps/allow/src/Agree.Allow.Presentation/appsettings.Example.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | }, 9 | "JwtConfiguration": { 10 | "SigningKey": "someMD5", 11 | "Audience": "http://localhost", 12 | "Issuer": "http://localhost:5000/" 13 | }, 14 | "ConnectionStrings": { 15 | "DefaultConnection": "Server=localhost;Port=4001;Uid=docker;Pwd=docker;Database=accord_db" 16 | } 17 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Infrastructure.Data/DatabaseOperationResult.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Infrastructure.Data; 2 | 3 | using Agree.Accord.SharedKernel; 4 | 5 | /// 6 | /// A result of a no-return database operation. 7 | /// 8 | public class DatabaseOperationResult : Result 9 | { 10 | private DatabaseOperationResult(bool succeeded) : base(succeeded) 11 | { } 12 | public static IResult Ok() => new DatabaseOperationResult(true); 13 | public static IResult Fail() => new DatabaseOperationResult(false); 14 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Presentation/Program.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Presentation; 2 | 3 | using Microsoft.AspNetCore.Hosting; 4 | using Microsoft.Extensions.Hosting; 5 | 6 | public class Program 7 | { 8 | public static void Main(string[] args) => CreateHostBuilder(args).Build().Run(); 9 | 10 | public static IHostBuilder CreateHostBuilder(string[] args) 11 | => Host 12 | .CreateDefaultBuilder(args) 13 | .ConfigureWebHostDefaults(webBuilder => webBuilder.UseStartup()); 14 | } 15 | -------------------------------------------------------------------------------- /apps/allow/src/Agree.Allow.Domain/Results/AuthenticationResult.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Allow.Domain.Results; 2 | 3 | using Agree.Allow.Domain.Tokens; 4 | using Agree.SharedKernel; 5 | 6 | public class AuthenticationResult : Result 7 | { 8 | private AuthenticationResult(TokenCollection tokens) : base(tokens) 9 | { } 10 | private AuthenticationResult() : base() 11 | { } 12 | 13 | public static AuthenticationResult Ok(TokenCollection tokens) => new(tokens); 14 | public static AuthenticationResult Fail() => new(); 15 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Servers/Specifications/ServerInviteIdEqualSpecification.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain.Servers.Specifications; 2 | 3 | using System; 4 | using Agree.Accord.SharedKernel.Data; 5 | 6 | public class ServerInviteIdEqualSpecification : Specification 7 | { 8 | public ServerInviteIdEqualSpecification(Guid id) 9 | => Expression = x 10 | => x.Id == id; 11 | 12 | public ServerInviteIdEqualSpecification(ServerInvite invite) 13 | => Expression = x 14 | => x.Id == invite.Id; 15 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Presentation/Shared/SocketHub.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Presentation.Shared; 2 | 3 | using System.Threading.Tasks; 4 | using Agree.Accord.Domain.Identity; 5 | using Agree.Accord.Domain.Identity.Requests; 6 | using Agree.Accord.Presentation.Identity.ViewModels; 7 | using MediatR; 8 | using Microsoft.AspNetCore.SignalR; 9 | using Microsoft.Extensions.Logging; 10 | 11 | public class SocketHub : CustomHubBase 12 | { 13 | public SocketHub(ILogger logger, IMediator mediator) 14 | : base(logger, mediator) { } 15 | } -------------------------------------------------------------------------------- /apps/allow/src/Agree.Allow.Domain/Tokens/Token.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Allow.Domain.Tokens; 2 | 3 | public class Token 4 | { 5 | public Token(string tokenValue, long expiresIn, string type) 6 | { 7 | TokenValue = tokenValue; 8 | ExpiresIn = expiresIn; 9 | Type = type; 10 | } 11 | 12 | public string TokenValue { get; private set; } 13 | 14 | public long ExpiresIn { get; private set; } 15 | 16 | public string Type { get; private set; } 17 | } 18 | 19 | public record TokenCollection(Token AccessToken, Token RefreshToken); -------------------------------------------------------------------------------- /apps/concord_old/src/logic/services/implementations/LocalStorageCache.ts: -------------------------------------------------------------------------------- 1 | import { ICache } from '../ICache' 2 | 3 | export class LocalStorageCache implements ICache { 4 | get (key: string): T | null { 5 | const item = localStorage.getItem(key) 6 | if (!item) { 7 | return null 8 | } 9 | return JSON.parse(item) as T 10 | } 11 | 12 | set (key: string, value: T): void { 13 | localStorage.setItem(key, JSON.stringify(value)) 14 | } 15 | 16 | delete (key: string): void { 17 | localStorage.removeItem(key) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Infrastructure/Agree.Accord.Infrastructure.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | net6.0 10 | 2.0 11 | enable 12 | 13 | -------------------------------------------------------------------------------- /apps/concord_old/src/presentation/layouts/DashboardLayout.tsx: -------------------------------------------------------------------------------- 1 | import { Flex } from '@chakra-ui/layout' 2 | import { PropsWithChildren } from 'react' 3 | import { ServerBar } from '../components/nav/ServerBar' 4 | import { SideBar } from '../components/nav/SideBar' 5 | 6 | export function DashboardLayout ({ children }: PropsWithChildren): JSX.Element { 7 | return ( 8 | 9 | 10 | 11 | 12 | {children} 13 | 14 | 15 | ) 16 | } 17 | -------------------------------------------------------------------------------- /apps/allow/src/Agree.Allow.Infrastructure.Data/MappingProfile.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Allow.Infrastructure.Data; 2 | 3 | using Agree.Allow.Domain; 4 | using AutoMapper; 5 | 6 | public class MappingProfile : Profile 7 | { 8 | public MappingProfile() 9 | { 10 | CreateMap() 11 | .ForMember(dest => dest.Tag, opt => opt.MapFrom(src => src.Tag.Value)); 12 | CreateMap() 13 | .ForMember(dest => dest.Tag, opt => opt.MapFrom(src => DiscriminatorTag.Parse(src.Tag))); 14 | } 15 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Requests/GetUserSentFriendshipRequestsRequest.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain.Social.Requests; 2 | 3 | using System.Collections.Generic; 4 | using System.ComponentModel.DataAnnotations; 5 | using Agree.Accord.Domain.Social; 6 | using MediatR; 7 | 8 | public class GetUserSentFriendshipRequestsRequest : IRequest> 9 | { 10 | public GetUserSentFriendshipRequestsRequest() { } 11 | public GetUserSentFriendshipRequestsRequest(User user) => User = user; 12 | 13 | [Required] 14 | public User User { get; set; } 15 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Social/Specifications/FriendshipAcceptedSpecification.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain.Social.Specifications; 2 | 3 | using System; 4 | using Agree.Accord.SharedKernel.Data; 5 | 6 | /// 7 | /// A specification that checks if a friendship has been accepted. 8 | /// 9 | public class FriendshipAcceptedSpecification : Specification 10 | { 11 | public FriendshipAcceptedSpecification(Guid userId) 12 | => Expression = x 13 | => (x.ToId == userId && x.Accepted) || (x.FromId == userId && x.Accepted); 14 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Servers/Results/CreateServerResult.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain.Servers.Results; 2 | 3 | using Agree.Accord.Domain.Servers; 4 | using Agree.Accord.SharedKernel; 5 | 6 | public class CreateServerResult : Result 7 | { 8 | private CreateServerResult(Server server) : base(server) 9 | { } 10 | private CreateServerResult(ErrorList error) : base(error) 11 | { } 12 | 13 | public static CreateServerResult Ok(Server server) => new(server); 14 | public static CreateServerResult Fail(ErrorList data) => new(data); 15 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Social/Specifications/SentFriendshipRequestSpecification.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain.Social.Specifications; 2 | 3 | using System; 4 | using Agree.Accord.SharedKernel.Data; 5 | 6 | /// 7 | /// A specification that checks if a given friendship request has been sent but not accepted yet. 8 | /// 9 | public class SentFriendshipRequestSpecification : Specification 10 | { 11 | public SentFriendshipRequestSpecification(Guid userId) 12 | => Expression = x 13 | => x.FromId == userId && !x.Accepted; 14 | } -------------------------------------------------------------------------------- /apps/allow/src/Agree.Allow.Infrastructure.Data/DatabaseOperationResult.cs: -------------------------------------------------------------------------------- 1 | using Agree.SharedKernel; 2 | 3 | namespace Agree.Allow.Infrastructure.Data 4 | { 5 | public class DatabaseOperationResult : Result 6 | { 7 | private DatabaseOperationResult(bool succeeded) : base(succeeded) 8 | { } 9 | public static IResult Ok() 10 | { 11 | return new DatabaseOperationResult(true); 12 | } 13 | 14 | public static IResult Fail() 15 | { 16 | return new DatabaseOperationResult(false); 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /apps/concord_old/src/logic/hooks/useSyncCacheState.ts: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react' 2 | import { ICache } from '../services/ICache' 3 | 4 | export function useSyncCacheState (cache: ICache, key: string, defaultValue?: T): [() => T | null | null, (value: T | null) => void, () => void] { 5 | useEffect(() => { 6 | if (!cache.get(key) && !!defaultValue) { 7 | cache.set(key, defaultValue) 8 | } 9 | }, []) 10 | 11 | return [ 12 | () => cache.get(key), 13 | (value: T | null) => cache.set(key, value), 14 | () => cache.delete(key) 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Social/Specifications/FriendshipExistsSpecification.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain.Social.Specifications; 2 | 3 | using System; 4 | using Agree.Accord.SharedKernel.Data; 5 | 6 | /// 7 | /// A specification that checks if a friendship exists between two users. 8 | /// 9 | public class FriendshipExistsSpecification : Specification 10 | { 11 | public FriendshipExistsSpecification(Guid from, Guid to) 12 | => Expression = x 13 | => (x.ToId == to && x.FromId == from) || (x.ToId == from && x.FromId == to); 14 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Requests/GetUserReceivedFriendshipRequestsRequest.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain.Social.Requests; 2 | 3 | using System.Collections.Generic; 4 | using System.ComponentModel.DataAnnotations; 5 | using Agree.Accord.Domain.Social; 6 | using MediatR; 7 | 8 | public class GetUserReceivedFriendshipRequestsRequest : IRequest> 9 | { 10 | public GetUserReceivedFriendshipRequestsRequest() { } 11 | public GetUserReceivedFriendshipRequestsRequest(User user) => User = user; 12 | 13 | [Required] 14 | public User User { get; set; } 15 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Servers/Specifications/ServerIdEqualSpecification.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain.Servers.Specifications; 2 | 3 | using System; 4 | using Agree.Accord.Domain.Servers; 5 | using Agree.Accord.SharedKernel.Data; 6 | 7 | /// 8 | /// A specification that checks if the server id of a given server is equal to a given value. 9 | /// 10 | public class ServerIdEqualSpecification : BaseServerSpecification 11 | { 12 | public ServerIdEqualSpecification(Guid serverId, Guid userId) 13 | : base((s) => s.Id == serverId, userId) 14 | { } 15 | } -------------------------------------------------------------------------------- /apps/concord_old/src/presentation/styles/utils.scss: -------------------------------------------------------------------------------- 1 | .hide-scrollbar { 2 | -ms-overflow-style: none; /* IE and Edge */ 3 | scrollbar-width: none; /* Firefox */ 4 | &::-webkit-scrollbar { 5 | display: none; 6 | } 7 | } 8 | 9 | .custom-scrollbar { 10 | &::-webkit-scrollbar { 11 | width: 3px; 12 | height: 5px; 13 | } 14 | &::-webkit-scrollbar-thumb { 15 | background: #5a189a; 16 | border-radius: 5px; 17 | } 18 | &::-webkit-scrollbar-thumb:hover { 19 | background: #7b2cbf; 20 | } 21 | &::-webkit-scrollbar-track { 22 | background: none; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Requests/GetDirectMessageByIdRequest.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain.Social.Requests; 2 | 3 | using System; 4 | using System.ComponentModel.DataAnnotations; 5 | using MediatR; 6 | 7 | /// 8 | /// The request to get a direct message by its Id. 9 | /// 10 | public class GetDirectMessagebyIdRequest : IRequest 11 | { 12 | /// 13 | /// The id of the direct message to be retrieved. 14 | /// 15 | /// The direct message id. 16 | [Required] 17 | public Guid Id { get; set; } 18 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Social/Specifications/ReceivedFriendshipRequestSpecification.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain.Social.Specifications; 2 | 3 | using System; 4 | using Agree.Accord.SharedKernel.Data; 5 | 6 | /// 7 | /// A specification that checks if a given friendship request has been received but not accepted yet. 8 | /// 9 | public class ReceivedFriendshipRequestSpecification : Specification 10 | { 11 | public ReceivedFriendshipRequestSpecification(Guid userId) 12 | => Expression = x 13 | => x.ToId == userId && !x.Accepted; 14 | } -------------------------------------------------------------------------------- /apps/allow/test/Agree.Allow.Domain.Test/testsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | }, 9 | "JwtConfiguration": { 10 | "SigningKey": "d6f3c6b9bb9f3be036c93196f93906c7", 11 | "Issuer": "http://localhost:5000/", 12 | "AccessTokenExpiresInMinutes": 30, 13 | "RefreshTokenExpiresInDays": 30 14 | }, 15 | "ConnectionStrings": { 16 | "DefaultConnection": ":memory:" 17 | } 18 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Servers/Results/CreateCategoryResult.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain.Servers.Results; 2 | 3 | using Agree.Accord.Domain.Servers; 4 | using Agree.Accord.SharedKernel; 5 | 6 | public class CreateCategoryResult : Result 7 | { 8 | private CreateCategoryResult(Category category) : base(category) 9 | { } 10 | private CreateCategoryResult(ErrorList error) : base(error) 11 | { } 12 | 13 | public static CreateCategoryResult Ok(Category category) => new(category); 14 | public static CreateCategoryResult Fail(ErrorList data) => new(data); 15 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Servers/Specifications/BaseServerPaginatedSpecification.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Linq.Expressions; 4 | using Agree.Accord.Domain.Servers; 5 | using Agree.Accord.SharedKernel.Data; 6 | 7 | public abstract class BaseServerPaginatedSpecification : PaginatedAndSpecification 8 | { 9 | public BaseServerPaginatedSpecification(Expression> expression, Guid userId, IPagination pagination) 10 | : base(new GenericSpecification(expression), new ServerVisibleToUserSpecification(userId), pagination) 11 | { } 12 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Presentation/Agree.Accord.Presentation.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net6.0 4 | enable 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /apps/allow/src/Agree.Allow.Infrastructure/BCryptPasswordManager.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Allow.Infrastructure.Providers; 2 | 3 | using System; 4 | using System.Threading.Tasks; 5 | using Agree.Allow.Domain; 6 | 7 | public class BCryptPasswordManager : IPasswordManager, IDisposable 8 | { 9 | public Task HashAsync(string password) 10 | => Task.Run(() => BCrypt.Net.BCrypt.HashPassword(password)); 11 | 12 | public Task CompareAsync(string hashed, string password) 13 | => Task.Run(() => BCrypt.Net.BCrypt.Verify(password, hashed)); 14 | 15 | public void Dispose() => GC.SuppressFinalize(this); 16 | } -------------------------------------------------------------------------------- /apps/allow/src/Agree.Allow.Domain/ClientApplication.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Allow.Domain; 2 | 3 | using Agree.SharedKernel; 4 | 5 | public class ClientApplication : IEntity 6 | { 7 | public ClientApplication(string name, string audienceName) 8 | { 9 | Id = Guid.NewGuid(); 10 | Name = name; 11 | AudienceName = audienceName; 12 | AccessKey = Guid.NewGuid().ToString("N"); 13 | } 14 | 15 | public Guid Id { get; private set; } 16 | public string Name { get; private set; } 17 | public string AudienceName { get; private set; } 18 | public string AccessKey { get; private set; } 19 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Friendship.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain; 2 | 3 | using System; 4 | using Agree.SharedKernel; 5 | 6 | public class Friendship : IEntity 7 | { 8 | public Friendship(User from, User to) 9 | { 10 | Id = Guid.NewGuid(); 11 | From = from; 12 | To = to; 13 | CreatedAt = DateTime.UtcNow; 14 | } 15 | 16 | public Guid Id { get; private set; } 17 | public User From { get; private set; } 18 | public User To { get; private set; } 19 | 20 | public DateTime CreatedAt { get; private set; } 21 | public DateTime AcceptedAt { get; private set; } 22 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Servers/ServerInvite.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain.Servers; 2 | 3 | using System; 4 | using Agree.Accord.SharedKernel; 5 | 6 | public class ServerInvite : IEntity 7 | { 8 | public Guid Id { get; private set; } 9 | public Server Server { get; private set; } 10 | public DateTime ExpirationDate { get; private set; } 11 | public bool IsExpired => ExpirationDate < DateTime.UtcNow; 12 | 13 | public ServerInvite(Server server, DateTime expirationDate) 14 | { 15 | Id = Guid.NewGuid(); 16 | Server = server; 17 | ExpirationDate = expirationDate; 18 | } 19 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Requests/RemoveFriendRequest.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain.Social.Requests; 2 | 3 | using Agree.Accord.Domain.Social.Results; 4 | using MediatR; 5 | using System; 6 | using System.ComponentModel.DataAnnotations; 7 | 8 | public class RemoveFriendRequest : IRequest 9 | { 10 | public RemoveFriendRequest() { } 11 | 12 | public RemoveFriendRequest(User user, Guid friendId) 13 | { 14 | User = user; 15 | FriendId = friendId; 16 | } 17 | 18 | [Required] 19 | public User User { get; set; } 20 | 21 | [Required] 22 | public Guid FriendId { get; set; } 23 | } -------------------------------------------------------------------------------- /apps/allow/src/Agree.Allow.Domain/Specifications/NameTagLikeSpecification.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Allow.Domain.Specifications; 2 | 3 | using System; 4 | using System.Linq.Expressions; 5 | using Agree.SharedKernel.Data; 6 | 7 | public class NameTagLikeSpecification : Specification, IPaginatedSpecification 8 | { 9 | public NameTagLikeSpecification(string query, IPagination pagination) 10 | { 11 | Expression = x 12 | => (x.Username + "#" + x.Tag).ToLower().Contains(query.ToLower()); 13 | 14 | Pagination = pagination; 15 | } 16 | 17 | public IPagination Pagination { get; private set; } 18 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Servers/Results/JoinServerResult.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain.Servers.Results; 2 | 3 | using Agree.Accord.SharedKernel; 4 | 5 | /// 6 | /// The result of joining a server. 7 | /// 8 | public class JoinServerResult : Result 9 | { 10 | private JoinServerResult(ServerMember serverMember) : base(serverMember) 11 | { } 12 | private JoinServerResult(ErrorList error) : base(error) 13 | { } 14 | 15 | public static JoinServerResult Ok(ServerMember serverMember) => new(serverMember); 16 | public static JoinServerResult Fail(ErrorList data) => new(data); 17 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Agree.Accord.Domain.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | net6.0 11 | 2.0 12 | enable 13 | 14 | -------------------------------------------------------------------------------- /apps/allow/src/Agree.Allow.Presentation/Exceptions/InvalidGrantTypeException.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Allow.Presentation.Exceptions; 2 | 3 | using System; 4 | using System.Runtime.Serialization; 5 | using Agree.SharedKernel; 6 | using Agree.SharedKernel.Exceptions; 7 | 8 | [Serializable] 9 | public class InvalidGrantTypeException : AgreeException 10 | { 11 | public InvalidGrantTypeException(string grantType) 12 | : base("grant_type", $"Invalid grant type '{grantType}'. Must be 'refresh_token' or 'password'.") 13 | { 14 | } 15 | 16 | public InvalidGrantTypeException() 17 | : base("grant_type", "Empty grant type") 18 | { 19 | } 20 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Social/Specifications/DirectMessageIdEqualSpecification.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain.Social.Specifications; 2 | 3 | using System; 4 | using Agree.Accord.SharedKernel.Data; 5 | 6 | /// 7 | /// A specification that checks if the message id of a given message is equal to a given value. 8 | /// 9 | public class DirectMessageIdEqualSpecification : Specification 10 | { 11 | public DirectMessageIdEqualSpecification(Guid id) => Expression = x => x.Id == id; 12 | 13 | public DirectMessageIdEqualSpecification(DirectMessage message) 14 | => Expression = x 15 | => x.Id == message.Id; 16 | } -------------------------------------------------------------------------------- /apps/allow/src/Agree.Allow.Domain/Agree.Allow.Domain.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Social/Results/DirectMessageResult.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain.Social.Results; 2 | 3 | using Agree.Accord.SharedKernel; 4 | 5 | /// 6 | /// The result of an operation on a direct message request. 7 | /// 8 | public class DirectMessageResult : Result 9 | { 10 | private DirectMessageResult(DirectMessage message) : base(message) 11 | { } 12 | private DirectMessageResult(ErrorList error) : base(error) 13 | { } 14 | 15 | public static DirectMessageResult Ok(DirectMessage message) => new(message); 16 | public static DirectMessageResult Fail(ErrorList data) => new(data); 17 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Social/Results/RemoveFriendResult.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain.Social.Results; 2 | 3 | using Agree.Accord.SharedKernel; 4 | 5 | /// 6 | /// The result of an operation on a friendship removal request. 7 | /// 8 | public class RemoveFriendResult : Result 9 | { 10 | private RemoveFriendResult(Friendship friendship) : base(friendship) 11 | { } 12 | private RemoveFriendResult(ErrorList error) : base(error) 13 | { } 14 | 15 | public static RemoveFriendResult Ok(Friendship friendship) => new(friendship); 16 | public static RemoveFriendResult Fail(ErrorList data) => new(data); 17 | } -------------------------------------------------------------------------------- /apps/allow/src/Agree.Allow.Infrastructure.Data/ApplicationDbContextFactory.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Allow.Infrastructure.Data; 2 | 3 | using Microsoft.EntityFrameworkCore; 4 | using Microsoft.EntityFrameworkCore.Design; 5 | 6 | public class ApplicationDbContextFactory : IDesignTimeDbContextFactory 7 | { 8 | public ApplicationDbContext CreateDbContext(string[] args) 9 | { 10 | var optionsBuilder = new DbContextOptionsBuilder(); 11 | 12 | optionsBuilder.UseNpgsql("Server=localhost;Port=4001;Uid=docker;Pwd=docker;Database=allow_db"); 13 | 14 | return new ApplicationDbContext(optionsBuilder.Options); 15 | } 16 | } -------------------------------------------------------------------------------- /apps/allow/src/Agree.Allow.Infrastructure.Data/ClientApplicationDbModel.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Allow.Infrastructure.Data; 2 | 3 | using System.ComponentModel.DataAnnotations; 4 | using System.ComponentModel.DataAnnotations.Schema; 5 | 6 | [Table("ClientApplications")] 7 | public class ClientApplicationDbModel 8 | { 9 | [Key] 10 | public Guid Id { get; private set; } 11 | 12 | [Required] 13 | [MaxLength(100)] 14 | public string Name { get; private set; } 15 | 16 | [Required] 17 | [MaxLength(100)] 18 | public string AudienceName { get; private set; } 19 | 20 | [Required] 21 | [MaxLength(100)] 22 | public string AccessKey { get; private set; } 23 | } -------------------------------------------------------------------------------- /apps/allow/src/Agree.Allow.Infrastructure/Agree.Allow.Infrastructure.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | net6.0 14 | enable 15 | enable 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Social/Results/FriendshipRequestResult.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain.Social.Results; 2 | 3 | using Agree.Accord.SharedKernel; 4 | 5 | /// 6 | /// The result of an operation on a friendship request. 7 | /// 8 | public class FriendshipRequestResult : Result 9 | { 10 | private FriendshipRequestResult(Friendship friendship) : base(friendship) 11 | { } 12 | private FriendshipRequestResult(ErrorList error) : base(error) 13 | { } 14 | 15 | public static FriendshipRequestResult Ok(Friendship friendship) => new(friendship); 16 | public static FriendshipRequestResult Fail(ErrorList data) => new(data); 17 | } -------------------------------------------------------------------------------- /apps/concord_old/src/logic/services/IHttpClient.ts: -------------------------------------------------------------------------------- 1 | export type HttpMethod = 'post' | 'get' | 'put' | 'delete' 2 | 3 | export enum HttpStatusCode { 4 | OK = 200, 5 | CREATED = 201, 6 | NOCONTENT = 204, 7 | BADREQUEST = 400, 8 | UNAUTHORIZED = 401, 9 | FORBIDDEN = 403, 10 | NOTFOUND = 404, 11 | SERVERERROR = 500 12 | } 13 | 14 | export type HttpRequest = { 15 | url: string 16 | method: HttpMethod 17 | body?: any 18 | headers?: any 19 | } 20 | 21 | export type HttpResponse = { 22 | statusCode: HttpStatusCode 23 | body?: T 24 | headers?: any 25 | } 26 | 27 | export interface IHttpClient { 28 | request: (data: HttpRequest) => Promise> 29 | } 30 | -------------------------------------------------------------------------------- /apps/concord_old/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "esModuleInterop": true, 12 | "allowSyntheticDefaultImports": true, 13 | "strict": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "module": "esnext", 17 | "moduleResolution": "node", 18 | "resolveJsonModule": true, 19 | "downlevelIteration": true, 20 | "isolatedModules": true, 21 | "noEmit": true, 22 | "jsx": "react-jsx" 23 | }, 24 | "include": [ 25 | "src" 26 | ] 27 | } -------------------------------------------------------------------------------- /apps/allow/src/Agree.Allow.Infrastructure.Data/ApplicationDbContext.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Allow.Infrastructure.Data; 2 | 3 | using System; 4 | using Microsoft.EntityFrameworkCore; 5 | 6 | public class ApplicationDbContext : DbContext 7 | { 8 | public ApplicationDbContext(DbContextOptions options) 9 | : base(options) { } 10 | 11 | public DbSet UserAccounts { get; set; } 12 | public DbSet ClientApplications { get; set; } 13 | 14 | protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) 15 | => optionsBuilder 16 | .LogTo(Console.WriteLine) 17 | .EnableSensitiveDataLogging(); 18 | } -------------------------------------------------------------------------------- /apps/concord_old/src/logic/services/implementations/ConsoleLogger.ts: -------------------------------------------------------------------------------- 1 | import { ILogger, LoggingLevel } from '../ILogger' 2 | 3 | export class ConsoleLogger implements ILogger { 4 | public log (level: LoggingLevel, message: unknown): void { 5 | if (process.env.NODE_ENV !== 'production') console[level](message) 6 | } 7 | 8 | public info (message: unknown): void { 9 | if (process.env.NODE_ENV !== 'production') console.log(message) 10 | } 11 | 12 | public warn (message: unknown): void { 13 | if (process.env.NODE_ENV !== 'production') console.warn(message) 14 | } 15 | 16 | public error (message: unknown): void { 17 | if (process.env.NODE_ENV !== 'production') console.error(message) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Presentation/appsettings.Example.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | }, 9 | "JwtConfiguration": { 10 | "SigningKey": "someMD5", 11 | "Audience": "http://localhost", 12 | "Issuer": "http://localhost:5000/" 13 | }, 14 | "ConnectionStrings": { 15 | "DefaultConnection": "Server=localhost;Port=4001;Uid=docker;Pwd=docker;Database=accord_db" 16 | }, 17 | "Providers": { 18 | "NativeMailProvider": { 19 | "Host": "smtp.mailtrap.io", 20 | "Port": "2525", 21 | "UserName": "", 22 | "Password": "" 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Social/IDirectMessageRepository.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain.Social; 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Threading.Tasks; 6 | using Agree.Accord.Domain.Social.Requests; 7 | using Agree.Accord.SharedKernel.Data; 8 | 9 | /// 10 | /// The interface for a repository of direct messages. Has all the methods from a generic IRepository, plus a paginated lookup method. 11 | /// 12 | public interface IDirectMessageRepository : IRepository 13 | { 14 | /// 15 | /// Searches for direct messages between two users. 16 | /// 17 | Task> SearchAsync(GetFriendChatRequest request); 18 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Servers/ServerRolePermission.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain.Servers; 2 | 3 | public class ServerRolePermission 4 | { 5 | public ServerRolePermission(ServerResource resource, ServerAction action) 6 | { 7 | Resource = resource; 8 | Action = action; 9 | } 10 | 11 | public ServerResource Resource { get; private set; } 12 | public ServerAction Action { get; private set; } 13 | 14 | 15 | public enum ServerResource 16 | { 17 | Server, 18 | Category, 19 | Channel, 20 | Message, 21 | Role 22 | } 23 | 24 | public enum ServerAction 25 | { 26 | Create, 27 | Read, 28 | Update, 29 | Delete 30 | } 31 | } -------------------------------------------------------------------------------- /apps/concord_old/src/presentation/components/avatar/UserAvatar.tsx: -------------------------------------------------------------------------------- 1 | import { Image } from '@chakra-ui/image' 2 | import { Box, Flex } from '@chakra-ui/layout' 3 | import { ChakraProps } from '@chakra-ui/system' 4 | 5 | type ServerAvatarProps = { 6 | w?: string 7 | avatarUrl: string 8 | } & ChakraProps 9 | 10 | export function UserAvatar ({ w, avatarUrl, ...rest }: ServerAvatarProps): JSX.Element { 11 | return ( 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | ) 20 | } 21 | -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Requests/AcceptFriendshipRequestRequest.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain.Social.Requests; 2 | 3 | using System; 4 | using System.ComponentModel.DataAnnotations; 5 | using MediatR; 6 | using Agree.Accord.Domain.Social.Results; 7 | 8 | public class AcceptFriendshipRequestRequest : IRequest 9 | { 10 | public AcceptFriendshipRequestRequest() { } 11 | 12 | public AcceptFriendshipRequestRequest(User loggedUser, Guid friendshipRequestId) 13 | { 14 | LoggedUser = loggedUser; 15 | FriendshipRequestId = friendshipRequestId; 16 | } 17 | 18 | [Required] 19 | public User LoggedUser { get; set; } 20 | 21 | [Required] 22 | public Guid FriendshipRequestId { get; set; } 23 | } -------------------------------------------------------------------------------- /apps/concord_old/src/presentation/components/form/SquareButton.tsx: -------------------------------------------------------------------------------- 1 | import { Button, ButtonProps as ChakraButtonProps } from '@chakra-ui/button' 2 | import { ReactNode } from 'react' 3 | 4 | type SquareButtonProps = { 5 | icon: ReactNode 6 | w: string 7 | } & ChakraButtonProps 8 | 9 | export function SquareButton ({ icon, w, ...rest }: SquareButtonProps): JSX.Element { 10 | return ( 11 | 22 | ) 23 | } 24 | -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Requests/DeclineFriendshipRequestRequest.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain.Social.Requests; 2 | 3 | using System; 4 | using System.ComponentModel.DataAnnotations; 5 | using MediatR; 6 | using Agree.Accord.Domain.Social.Results; 7 | 8 | public class DeclineFriendshipRequestRequest : IRequest 9 | { 10 | public DeclineFriendshipRequestRequest() { } 11 | 12 | public DeclineFriendshipRequestRequest(User loggedUser, Guid friendshipRequestId) 13 | { 14 | LoggedUser = loggedUser; 15 | FriendshipRequestId = friendshipRequestId; 16 | } 17 | 18 | [Required] 19 | public User LoggedUser { get; set; } 20 | 21 | [Required] 22 | public Guid FriendshipRequestId { get; set; } 23 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Social/Results/DirectMessageReadResult.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain.Social.Results; 2 | 3 | using System.Collections.Generic; 4 | using Agree.Accord.SharedKernel; 5 | 6 | /// 7 | /// The result of a request to read a direct message. 8 | /// 9 | public class DirectMessagesReadResult : Result, ErrorList> 10 | { 11 | private DirectMessagesReadResult(IEnumerable message) : base(message) 12 | { } 13 | private DirectMessagesReadResult(ErrorList error) : base(error) 14 | { } 15 | 16 | public static DirectMessagesReadResult Ok(IEnumerable message) => new(message); 17 | public static DirectMessagesReadResult Fail(ErrorList data) => new(data); 18 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Servers/Specifications/ServerInfoLikeSpecification.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain.Servers.Specifications; 2 | 3 | using System; 4 | using Agree.Accord.Domain.Servers; 5 | using Agree.Accord.SharedKernel.Data; 6 | 7 | /// 8 | /// A specification that checks if the server id of a given server is equal to a given value. 9 | /// 10 | public class ServerInfoLikeSpecification : BaseServerPaginatedSpecification 11 | { 12 | public ServerInfoLikeSpecification(string query, Guid userId, IPagination pagination) 13 | : base( 14 | (s) => s.Name.ToLower().Contains(query.ToLower()) || s.Description.ToLower().Contains(query.ToLower()), 15 | userId, 16 | pagination 17 | ) 18 | { } 19 | } -------------------------------------------------------------------------------- /apps/allow/src/Agree.Allow.Presentation/Agree.Allow.Presentation.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | net6.0 15 | enable 16 | enable 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /apps/concord_old/README.md: -------------------------------------------------------------------------------- 1 | # Concord :tv: 2 | 3 | Concord is the Agree main dashboard, built with CRA and Chakra UI. 4 | 5 | I decided to divide it into three layers: 6 | - The presentation layer, where is located most of the jsx and styling 7 | - The logic layer, where I use React Contexts and Hooks to manage the entire application business rules 8 | - The validation layer, where things get validated :P 9 | 10 | ### Dependency Injection 11 | 12 | I think there is something very cool on how I handle DI in this project. Since I'm using hooks and contexts, there are no classes (and consequently no constructors for DI) so I inject my services into the props of the contexts providers on a "DI Container"-like component, but the contexts depend purely on interfaces so there is a very low coupling on the logic layer. -------------------------------------------------------------------------------- /apps/allow/src/Agree.Allow.Domain/Specifications/UserNameEqualSpecification.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Allow.Domain.Specifications; 2 | 3 | using System; 4 | using System.Linq.Expressions; 5 | using Agree.SharedKernel.Data; 6 | 7 | public class UserNameEqualSpecification : Specification, IOrderedSpecification 8 | { 9 | public UserNameEqualSpecification(string username, bool orderByTag = false) 10 | { 11 | Expression = x 12 | => x.Username == username; 13 | 14 | if (orderByTag) 15 | { 16 | OrderingExpression = x => x.Tag; 17 | IsDescending = true; 18 | } 19 | } 20 | 21 | public Expression> OrderingExpression { get; private set; } 22 | 23 | public bool IsDescending { get; private set; } 24 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Infrastructure.Data/ApplicationDbContextFactory.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Infrastructure.Data; 2 | 3 | using Microsoft.EntityFrameworkCore; 4 | using Microsoft.EntityFrameworkCore.Design; 5 | 6 | /// 7 | /// A factory for creating instances during design-time builds. 8 | /// 9 | public class ApplicationDbContextFactory : IDesignTimeDbContextFactory 10 | { 11 | public ApplicationDbContext CreateDbContext(string[] args) 12 | { 13 | var optionsBuilder = new DbContextOptionsBuilder(); 14 | 15 | optionsBuilder.UseNpgsql("Server=localhost;Port=4001;Uid=docker;Pwd=docker;Database=accord_db"); 16 | 17 | return new ApplicationDbContext(optionsBuilder.Options); 18 | } 19 | } -------------------------------------------------------------------------------- /docker/docker-compose.override.yaml: -------------------------------------------------------------------------------- 1 | version: '3.9' 2 | 3 | services: 4 | accord_postgres: 5 | container_name: 'accord_postgres' 6 | restart: always 7 | ports: 8 | - 4001:5432 9 | environment: 10 | - POSTGRES_PASSWORD=docker 11 | - POSTGRES_USER=docker 12 | - POSTGRES_DB=accord_db 13 | volumes: 14 | - accord_postgres_volume:/var/lib/postgresql/data 15 | networks: 16 | - accord-network 17 | 18 | allow_postgres: 19 | container_name: 'allow_postgres' 20 | restart: always 21 | ports: 22 | - 4002:5432 23 | environment: 24 | - POSTGRES_PASSWORD=docker 25 | - POSTGRES_USER=docker 26 | - POSTGRES_DB=allow_db 27 | volumes: 28 | - allow_postgres_volume:/var/lib/postgresql/data 29 | networks: 30 | - allow-network 31 | -------------------------------------------------------------------------------- /apps/allow/test/Agree.Allow.Test/TestBase.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Allow.Test; 2 | 3 | using Agree.Allow.Domain; 4 | using Agree.SharedKernel.Data; 5 | using Microsoft.Extensions.DependencyInjection; 6 | 7 | public class TestBase 8 | { 9 | private readonly DependencyInjectionContainer _container = new(); 10 | 11 | protected T Resolve() 12 | { 13 | return _container.Services.GetRequiredService(); 14 | } 15 | 16 | protected async Task CreateTestUserAccount(DiscriminatorTag tag = null) 17 | { 18 | var account = new UserAccount("testuser", "test@somemail", "somehash", tag ?? DiscriminatorTag.Parse(0)); 19 | var repository = Resolve>(); 20 | await repository.InsertAsync(account); 21 | await repository.CommitAsync(); 22 | return account; 23 | } 24 | } -------------------------------------------------------------------------------- /apps/concord_old/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "workbench.colorCustomizations": { 3 | "activityBar.activeBackground": "#3399ff", 4 | "activityBar.activeBorder": "#bf0060", 5 | "activityBar.background": "#3399ff", 6 | "activityBar.foreground": "#15202b", 7 | "activityBar.inactiveForeground": "#15202b99", 8 | "activityBarBadge.background": "#bf0060", 9 | "activityBarBadge.foreground": "#e7e7e7", 10 | "statusBar.background": "#007fff", 11 | "statusBar.foreground": "#e7e7e7", 12 | "statusBarItem.hoverBackground": "#3399ff", 13 | "titleBar.activeBackground": "#007fff", 14 | "titleBar.activeForeground": "#e7e7e7", 15 | "titleBar.inactiveBackground": "#007fff99", 16 | "titleBar.inactiveForeground": "#e7e7e799" 17 | }, 18 | "peacock.color": "#007fff" 19 | } -------------------------------------------------------------------------------- /apps/allow/test/Agree.Allow.Domain.Test/Handlers/Queries/GetAccountByIdHandlerTest.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Allow.Domain.Test.Handlers.Queries; 2 | 3 | using Agree.Allow.Domain.Handlers.Queries; 4 | using Agree.Allow.Domain.Requests; 5 | using Agree.Allow.Test; 6 | using Agree.SharedKernel.Data; 7 | 8 | public class GetAccountByIdHandlerTest : TestBase 9 | { 10 | [Fact] 11 | public async Task Handle_WithExistingId_ShouldReturnAccount() 12 | { 13 | // Arrange 14 | var account = await CreateTestUserAccount(); 15 | var repository = Resolve>(); 16 | var sut = new GetAccountByIdHandler(repository); 17 | 18 | // Act 19 | var result = await sut.Handle(new GetAccountByIdRequest(account.Id), CancellationToken.None); 20 | 21 | // Assert 22 | Assert.Equal(account.Id, result.Id); 23 | } 24 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Servers/Requests/GetServerByIdRequest.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain.Servers.Requests; 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | using Agree.Accord.SharedKernel.Data; 6 | using MediatR; 7 | 8 | /// 9 | /// Represents a request to get a server by its id, taking into account the server's privacy settings. 10 | /// 11 | public class GetServerByIdRequest : IRequest 12 | { 13 | /// 14 | /// The id of the server to get. 15 | /// 16 | /// The id of the server. 17 | public Guid ServerId { get; set; } 18 | 19 | /// 20 | /// The id of the user that is searching. 21 | /// Useful to filter out secret servers. 22 | /// 23 | /// The id of the user that is searching. 24 | public Guid UserId { get; set; } 25 | } -------------------------------------------------------------------------------- /apps/allow/src/Agree.Allow.Domain/Handlers/Queries/GetAccountByIdHandler.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Allow.Domain.Handlers.Queries; 2 | 3 | using System; 4 | using System.Threading; 5 | using System.Threading.Tasks; 6 | using Agree.Allow.Domain; 7 | using Agree.Allow.Domain.Requests; 8 | using Agree.Allow.Domain.Specifications; 9 | using Agree.SharedKernel.Data; 10 | using MediatR; 11 | 12 | public class GetAccountByIdHandler : IRequestHandler 13 | { 14 | private readonly IRepository _accountRepository; 15 | 16 | public GetAccountByIdHandler(IRepository accountRepository) => _accountRepository = accountRepository; 17 | 18 | public async Task Handle(GetAccountByIdRequest request, CancellationToken cancellationToken) 19 | => await _accountRepository.GetFirstAsync(new UserIdEqualSpecification(request.Id)); 20 | } -------------------------------------------------------------------------------- /apps/allow/test/Agree.Allow.Test/DependencyInjectionContainer.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Allow.Test; 2 | 3 | using System.Reflection; 4 | using Agree.Allow.Infrastructure.IoC; 5 | using Agree.SharedKernel.Data; 6 | using Microsoft.Extensions.Configuration; 7 | using Microsoft.Extensions.DependencyInjection; 8 | 9 | public class DependencyInjectionContainer 10 | { 11 | public readonly IServiceProvider Services; 12 | 13 | public DependencyInjectionContainer() 14 | { 15 | var configuration = new ConfigurationBuilder() 16 | .AddJsonFile("testsettings.json") 17 | .Build(); 18 | 19 | Services = new ServiceCollection() 20 | .AddAllowInfrastructure(configuration, Assembly.GetAssembly(typeof(DependencyInjectionContainer))) 21 | .AddSingleton(typeof(IRepository<,>), typeof(TestRepository<,>)) 22 | .BuildServiceProvider(); 23 | } 24 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Servers/Category.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain.Servers; 2 | 3 | using System; 4 | using Agree.Accord.SharedKernel; 5 | 6 | /// 7 | /// A server category. 8 | /// 9 | public class Category : IEntity 10 | { 11 | /// EF ctor 12 | protected Category() { } 13 | 14 | public Category(string name, Server server) 15 | { 16 | Id = Guid.NewGuid(); 17 | Name = name; 18 | Position = Server.Categories.Count; 19 | Server = server; 20 | ServerId = server.Id; 21 | } 22 | 23 | public Guid Id { get; set; } 24 | public string Name { get; set; } 25 | public int Position { get; set; } 26 | 27 | public Guid ServerId { get; set; } 28 | public Server Server { get; set; } 29 | 30 | public static Category CreateDefaultWelcomeCategory(Server server) 31 | => new($"Welcome to {server.Name}!", server); 32 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Requests/MarkDirectMessageAsReadRequest.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain.Social.Requests; 2 | 3 | using System; 4 | using System.ComponentModel.DataAnnotations; 5 | using Agree.Accord.Domain.Social.Results; 6 | using MediatR; 7 | 8 | /// 9 | /// The request to mark a direct message as read. 10 | /// 11 | public class MarkDirectMessageAsReadRequest : IRequest 12 | { 13 | public MarkDirectMessageAsReadRequest() { } 14 | 15 | /// 16 | /// The direct message Id to be marked as read. 17 | /// 18 | /// The direct message Id. 19 | [Required] 20 | public Guid DirectMessageId { get; set; } 21 | 22 | /// 23 | /// The user marking the direct message as read. 24 | /// 25 | /// The user account. 26 | [Required] 27 | public UserAccount Requester { get; set; } 28 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Social/Specifications/DirectMessageFromOrToFriendSpecification.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain.Social.Specifications; 2 | 3 | using System; 4 | using Agree.Accord.SharedKernel.Data; 5 | 6 | public class DirectMessageFromOrToFriendPaginatedSpecification : PaginatedSpecification 7 | { 8 | public DirectMessageFromOrToFriendPaginatedSpecification(Guid requesterId, Guid friendId, IPagination pagination) 9 | : base(pagination) 10 | => Expression = x 11 | => (x.From.Id == friendId && x.To.Id == requesterId) || (x.To.Id == friendId && x.From.Id == requesterId); 12 | } 13 | 14 | public class DirectMessageFromOrToFriendSpecification : Specification 15 | { 16 | public DirectMessageFromOrToFriendSpecification(Guid requesterId, Guid friendId) 17 | => Expression = x 18 | => (x.From.Id == friendId && x.To.Id == requesterId) || (x.To.Id == friendId && x.From.Id == requesterId); 19 | } -------------------------------------------------------------------------------- /apps/allow/src/Agree.Allow.Domain/Handlers/Queries/SearchAccountsHandler.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Allow.Domain.Handlers.Queries; 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Threading; 6 | using System.Threading.Tasks; 7 | using Agree.Allow.Domain; 8 | using Agree.Allow.Domain.Requests; 9 | using Agree.Allow.Domain.Specifications; 10 | using Agree.SharedKernel.Data; 11 | using MediatR; 12 | 13 | public class SearchAccountsHandler : IRequestHandler> 14 | { 15 | private readonly IRepository _accountRepository; 16 | 17 | public SearchAccountsHandler(IRepository accountRepository) => _accountRepository = accountRepository; 18 | 19 | public async Task> Handle(SearchAccountsRequest request, CancellationToken cancellationToken) 20 | => await _accountRepository.GetAllAsync(new NameTagLikeSpecification(request.Query, request)); 21 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Servers/Requests/SearchServersRequest.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain.Servers.Requests; 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | using Agree.Accord.SharedKernel.Data; 6 | using MediatR; 7 | 8 | /// 9 | /// Represents a request to search paginated server by a query, taking into account the server's privacy settings. 10 | /// 11 | public class SearchServersRequest : Pagination, IRequest> 12 | { 13 | /// 14 | /// The query to search for. This will be used to search for the server name or description. 15 | /// 16 | /// The query to search for. 17 | public string Query { get; set; } 18 | 19 | /// 20 | /// The id of the user that is searching. 21 | /// Useful to filter out secret servers. 22 | /// 23 | /// The id of the user that is searching. 24 | public Guid UserId { get; set; } 25 | } -------------------------------------------------------------------------------- /apps/allow/src/Agree.Allow.Domain/Specifications/NameTagEqualSpecification.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Allow.Domain.Specifications; 2 | 3 | using System.Linq.Expressions; 4 | using Agree.SharedKernel.Data; 5 | 6 | public class NameTagEqualSpecification : Specification, IOrderedSpecification 7 | { 8 | public NameTagEqualSpecification(DiscriminatorTag tag, string userName, bool orderByTag = false) 9 | { 10 | Expression = x 11 | => x.Username == userName && x.Tag == tag; 12 | 13 | if (orderByTag) 14 | { 15 | OrderingExpression = x => x.Tag; 16 | IsDescending = true; 17 | } 18 | } 19 | 20 | public NameTagEqualSpecification(UserAccount account) 21 | => Expression = x 22 | => x.Username == account.Username && x.Tag == account.Tag; 23 | 24 | public Expression> OrderingExpression { get; private set; } 25 | public bool IsDescending { get; private set; } 26 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Requests/SendFriendshipRequestRequest.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain.Social.Requests; 2 | 3 | using Agree.Accord.Domain.Social.Results; 4 | using MediatR; 5 | using System.ComponentModel.DataAnnotations; 6 | 7 | /// 8 | /// The request to send a friendship request. 9 | /// 10 | public class SendFriendshipRequestRequest : IRequest 11 | { 12 | public SendFriendshipRequestRequest() { } 13 | 14 | /// 15 | /// The user sending the friendship request. 16 | /// 17 | /// The user account. 18 | [Required] 19 | public User From { get; set; } 20 | 21 | /// 22 | /// The user receiving the friendship request nametag. 23 | /// Must be a valid user nametag. 24 | /// 25 | /// The receiver user account nametag. 26 | [Required] 27 | [RegularExpression(@"^([a-zA-Z0-9_-]{0,}#[0-9]{4})$")] 28 | public string ToNameTag { get; set; } 29 | } -------------------------------------------------------------------------------- /apps/allow/src/Agree.Allow.Domain/DiscriminatorTagFactory.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Allow.Domain; 2 | 3 | using System; 4 | using System.Threading.Tasks; 5 | using Agree.Allow.Domain.Specifications; 6 | using Agree.SharedKernel.Data; 7 | 8 | public class DiscriminatorTagFactory 9 | { 10 | private readonly IRepository _accountRepository; 11 | 12 | public DiscriminatorTagFactory(IRepository accountRepository) => _accountRepository = accountRepository; 13 | 14 | public async Task GenerateDiscriminatorTagAsync(string username) 15 | { 16 | DiscriminatorTag tag = DiscriminatorTag.Parse(0); 17 | 18 | var sameNameTagCheck = await _accountRepository.GetFirstAsync(new UserNameEqualSpecification(username, true)); 19 | 20 | if (sameNameTagCheck == null) 21 | return tag; 22 | 23 | tag = sameNameTagCheck.Tag.Increment(); 24 | 25 | if (tag.Value > 9999) 26 | return null; 27 | 28 | return tag; 29 | } 30 | } -------------------------------------------------------------------------------- /apps/allow/src/Agree.Allow.Infrastructure.Data/UserAccountDbModel.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Allow.Infrastructure.Data; 2 | 3 | using System; 4 | using Agree.SharedKernel; 5 | using System.Security.Claims; 6 | using Agree.Allow.Domain; 7 | using System.ComponentModel.DataAnnotations.Schema; 8 | using System.ComponentModel.DataAnnotations; 9 | using Microsoft.EntityFrameworkCore; 10 | 11 | [Table("UserAccounts")] 12 | [Index("Tag", "Username", IsUnique = true)] 13 | public class UserAccountDbModel 14 | { 15 | [Key] 16 | public Guid Id { get; private set; } 17 | 18 | [Required] 19 | [MaxLength(255)] 20 | public string EmailAddress { get; private set; } 21 | 22 | [Required] 23 | [MaxLength(40)] 24 | public string Username { get; private set; } 25 | 26 | [Required] 27 | [MaxLength(400)] 28 | public string PasswordHash { get; private set; } 29 | 30 | [Required] 31 | [MaxLength(4)] 32 | public ushort Tag { get; private set; } 33 | 34 | public DateTime CreatedAt { get; private set; } 35 | } -------------------------------------------------------------------------------- /apps/allow/src/Agree.Allow.Presentation/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/launchsettings.json", 3 | "iisSettings": { 4 | "windowsAuthentication": false, 5 | "anonymousAuthentication": true, 6 | "iisExpress": { 7 | "applicationUrl": "http://localhost:11113", 8 | "sslPort": 44357 9 | } 10 | }, 11 | "profiles": { 12 | "Agree.Allow.Presentation": { 13 | "commandName": "Project", 14 | "dotnetRunMessages": true, 15 | "launchBrowser": true, 16 | "launchUrl": "swagger", 17 | "applicationUrl": "https://localhost:7100;http://localhost:5267", 18 | "environmentVariables": { 19 | "ASPNETCORE_ENVIRONMENT": "Development" 20 | } 21 | }, 22 | "IIS Express": { 23 | "commandName": "IISExpress", 24 | "launchBrowser": true, 25 | "launchUrl": "swagger", 26 | "environmentVariables": { 27 | "ASPNETCORE_ENVIRONMENT": "Development" 28 | } 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Presentation/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/launchsettings.json", 3 | "iisSettings": { 4 | "windowsAuthentication": false, 5 | "anonymousAuthentication": true, 6 | "iisExpress": { 7 | "applicationUrl": "http://localhost:53661", 8 | "sslPort": 44348 9 | } 10 | }, 11 | "profiles": { 12 | "IIS Express": { 13 | "commandName": "IISExpress", 14 | "launchBrowser": true, 15 | "launchUrl": "swagger", 16 | "environmentVariables": { 17 | "ASPNETCORE_ENVIRONMENT": "Development" 18 | } 19 | }, 20 | "Agree.Accord.Presentation": { 21 | "commandName": "Project", 22 | "dotnetRunMessages": "true", 23 | "launchBrowser": true, 24 | "launchUrl": "swagger", 25 | "applicationUrl": "https://localhost:5001;http://localhost:5000", 26 | "environmentVariables": { 27 | "ASPNETCORE_ENVIRONMENT": "Development" 28 | } 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Social/Handlers/Queries/GetFriendChatHandler.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain.Social.Handlers.Queries; 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Threading; 6 | using System.Threading.Tasks; 7 | using Agree.Accord.Domain.Social.Requests; 8 | using Agree.Accord.Domain.Social.Specifications; 9 | using Agree.Accord.SharedKernel.Data; 10 | using MediatR; 11 | 12 | /// 13 | /// Handles the retrieval of a direct message by its Id. 14 | /// 15 | public class GetFriendChatHandler : IRequestHandler> 16 | { 17 | private readonly IDirectMessageRepository _directMessageRepository; 18 | 19 | public GetFriendChatHandler(IDirectMessageRepository directMessageRepository) => _directMessageRepository = directMessageRepository; 20 | 21 | public async Task> Handle(GetFriendChatRequest request, CancellationToken cancellationToken) 22 | => await _directMessageRepository.SearchAsync(request); 23 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Infrastructure.Data/Agree.Accord.Infrastructure.Data.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net6.0 4 | 2.0 5 | enable 6 | 7 | 8 | 9 | 10 | 11 | runtime; build; native; contentfiles; analyzers; buildtransitive 12 | all 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Social/Handlers/Queries/GetDirectMessageByIdHandler.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain.Social.Handlers.Queries; 2 | 3 | using System; 4 | using System.Threading; 5 | using System.Threading.Tasks; 6 | using Agree.Accord.Domain.Social.Requests; 7 | using Agree.Accord.Domain.Social.Specifications; 8 | using Agree.Accord.SharedKernel.Data; 9 | using MediatR; 10 | 11 | /// 12 | /// Handles the retrieval of a direct message by its Id. 13 | /// 14 | public class GetDirectMessageByIdHandler : IRequestHandler 15 | { 16 | private readonly IDirectMessageRepository _directMessageRepository; 17 | 18 | public GetDirectMessageByIdHandler(IDirectMessageRepository directMessageRepository) => _directMessageRepository = directMessageRepository; 19 | 20 | public async Task Handle(GetDirectMessagebyIdRequest request, CancellationToken cancellationToken) 21 | => await _directMessageRepository.GetFirstAsync(new DirectMessageIdEqualSpecification(request.Id)); 22 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/FriendshipRequest.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain; 2 | 3 | using System; 4 | using Agree.SharedKernel; 5 | 6 | public class FriendshipRequest : IEntity 7 | { 8 | public FriendshipRequest(User from, User to) 9 | { 10 | Id = Guid.NewGuid(); 11 | From = from; 12 | To = to; 13 | Accepted = false; 14 | SentAt = DateTime.UtcNow; 15 | } 16 | 17 | public Guid Id { get; private set; } 18 | public User From { get; private set; } 19 | public User To { get; private set; } 20 | public bool Accepted { get; private set; } 21 | 22 | public DateTime SentAt { get; private set; } 23 | public DateTime AcceptedAt { get; private set; } 24 | 25 | public void Accept(User acceptingUser) 26 | { 27 | if (Accepted) 28 | throw new FriendshipAlreadyAcceptedException(); 29 | if (acceptingUser != To) 30 | throw new FriendshipRequestNotForUserException(); 31 | Accepted = true; 32 | AcceptedAt = DateTime.UtcNow; 33 | } 34 | } -------------------------------------------------------------------------------- /apps/allow/src/Agree.Allow.Presentation/CustomControllerBase.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Allow.Presentation; 2 | 3 | using System.Net; 4 | using System.Threading.Tasks; 5 | using Agree.Allow.Domain; 6 | using Agree.Allow.Domain.Requests; 7 | using MediatR; 8 | using Microsoft.AspNetCore.Mvc; 9 | 10 | public class CustomControllerBase : ControllerBase 11 | { 12 | protected readonly IMediator _mediator; 13 | 14 | public CustomControllerBase(IMediator mediator) => _mediator = mediator; 15 | 16 | protected UserAccount CurrentlyLoggedUser => 17 | HttpContext.User.Identity.IsAuthenticated 18 | ? UserAccount.FromClaims(HttpContext.User) 19 | : null; 20 | 21 | protected async Task GetAuthenticatedUserAccount() 22 | => await _mediator.Send(new GetAccountByIdRequest(CurrentlyLoggedUser.Id)); 23 | 24 | protected IActionResult InternalServerError() => StatusCode((int)HttpStatusCode.InternalServerError); 25 | 26 | protected IActionResult InternalServerError(object obj) => StatusCode((int)HttpStatusCode.InternalServerError, obj); 27 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Servers/Handlers/Queries/GetServerByIdHandler.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain.Servers.Handlers.Queries; 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Threading; 6 | using System.Threading.Tasks; 7 | using Agree.Accord.Domain.Servers; 8 | using Agree.Accord.Domain.Servers.Requests; 9 | using Agree.Accord.Domain.Servers.Specifications; 10 | using Agree.Accord.SharedKernel.Data; 11 | using MediatR; 12 | 13 | /// 14 | /// Handles the search of a by its id. 15 | /// 16 | public class GetServerByIdHandler : IRequestHandler 17 | { 18 | private readonly IRepository _serverRepository; 19 | 20 | public GetServerByIdHandler(IRepository accountRepository) => _serverRepository = accountRepository; 21 | 22 | public async Task Handle(GetServerByIdRequest request, CancellationToken cancellationToken) 23 | => await _serverRepository.GetFirstAsync(new ServerIdEqualSpecification(request.ServerId, request.UserId)); 24 | } -------------------------------------------------------------------------------- /apps/concord_old/src/presentation/pages/error/NotFoundPage.tsx: -------------------------------------------------------------------------------- 1 | import { Img } from '@chakra-ui/image' 2 | import { Flex, Heading, Text } from '@chakra-ui/layout' 3 | import { useI18n } from '../../hooks/useI18n' 4 | 5 | import LogoImage from '../../assets/agreew.svg' 6 | import BgImage from '../../assets/bg404.png' 7 | 8 | export function NotFoundPage (): JSX.Element { 9 | const { t } = useI18n() 10 | 11 | return ( 12 | 13 | Agree logo 14 | 15 | 404 NOT FOUND 16 | 17 | 18 | {t`Congratulations! You found our little mascot secret page!`} 19 | 20 | 21 | {t`Just kidding. Actually this page doesn't exists...`} 22 | 23 | 24 | {t`Kinda paradoxal don't you think?`} 25 | 26 | 27 | ) 28 | } 29 | -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Presentation/Social/ViewModels/FriendshipRequestViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Presentation.Social.ViewModels; 2 | 3 | using Agree.Accord.Domain.Social; 4 | using Agree.Accord.Presentation.Identity.ViewModels; 5 | 6 | /// 7 | /// The view model for a friendship request. 8 | /// 9 | public class FriendshipRequestViewModel 10 | { 11 | public UserAccountViewModel From { get; private set; } 12 | public UserAccountViewModel To { get; private set; } 13 | public bool Accepted { get; private set; } 14 | 15 | /// 16 | /// Creates a new instance of the class from a friendship entity. 17 | /// 18 | /// The friendship entity. 19 | /// The view model. 20 | public static FriendshipRequestViewModel FromEntity(Friendship entity) => new() 21 | { 22 | From = UserAccountViewModel.FromEntity(entity.From), 23 | To = UserAccountViewModel.FromEntity(entity.To), 24 | Accepted = entity.Accepted 25 | }; 26 | } -------------------------------------------------------------------------------- /apps/concord_old/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Agree", 3 | "description": "Agree is a text, voice and video communication service based on Discord", 4 | "icons": [ 5 | { 6 | "src": "/android-icon-36x36.png", 7 | "sizes": "36x36", 8 | "type": "image/png", 9 | "density": "0.75" 10 | }, 11 | { 12 | "src": "/android-icon-48x48.png", 13 | "sizes": "48x48", 14 | "type": "image/png", 15 | "density": "1.0" 16 | }, 17 | { 18 | "src": "/android-icon-72x72.png", 19 | "sizes": "72x72", 20 | "type": "image/png", 21 | "density": "1.5" 22 | }, 23 | { 24 | "src": "/android-icon-96x96.png", 25 | "sizes": "96x96", 26 | "type": "image/png", 27 | "density": "2.0" 28 | }, 29 | { 30 | "src": "/android-icon-144x144.png", 31 | "sizes": "144x144", 32 | "type": "image/png", 33 | "density": "3.0" 34 | }, 35 | { 36 | "src": "/android-icon-192x192.png", 37 | "sizes": "192x192", 38 | "type": "image/png", 39 | "density": "4.0" 40 | } 41 | ] 42 | } 43 | -------------------------------------------------------------------------------- /apps/concord_old/src/logic/services/implementations/AxiosHttpClient.ts: -------------------------------------------------------------------------------- 1 | import axios, { AxiosResponse } from 'axios' 2 | import { HttpRequest, HttpResponse, IHttpClient } from '../IHttpClient' 3 | 4 | export class AxiosHttpClient implements IHttpClient { 5 | public constructor () { 6 | axios.interceptors.response.use(response => { 7 | return response 8 | }, error => { 9 | return error 10 | }) 11 | } 12 | 13 | public async request (data: HttpRequest): Promise> { 14 | let axiosResponse: AxiosResponse 15 | try { 16 | axiosResponse = await axios.request({ 17 | url: data.url, 18 | method: data.method, 19 | data: data.body, 20 | headers: data.headers, 21 | withCredentials: true, 22 | validateStatus: () => true 23 | }) 24 | } catch (error) { 25 | console.log(error) 26 | axiosResponse = error.response 27 | } 28 | return { 29 | statusCode: Number(axiosResponse.status), 30 | body: axiosResponse.data, 31 | headers: axiosResponse.headers 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Servers/Handlers/Queries/SearchServerHandler.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain.Servers.Handlers.Queries; 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Threading; 6 | using System.Threading.Tasks; 7 | using Agree.Accord.Domain.Servers; 8 | using Agree.Accord.Domain.Servers.Requests; 9 | using Agree.Accord.Domain.Servers.Specifications; 10 | using Agree.Accord.SharedKernel.Data; 11 | using MediatR; 12 | 13 | /// 14 | /// Handles the search of paginated s by a query. 15 | /// 16 | public class SearchServersHandler : IRequestHandler> 17 | { 18 | private readonly IRepository _serverRepository; 19 | 20 | public SearchServersHandler(IRepository serverRepository) => _serverRepository = serverRepository; 21 | 22 | public async Task> Handle(SearchServersRequest request, CancellationToken cancellationToken) 23 | => await _serverRepository.GetAllAsync(new ServerInfoLikeSpecification(request.Query, request.UserId, request)); 24 | } -------------------------------------------------------------------------------- /apps/concord_old/src/logic/hooks/useAllow.tsx: -------------------------------------------------------------------------------- 1 | import { useContext } from 'react' 2 | import { Redirect, Route, RouteProps } from 'react-router' 3 | import { AllowContext, AllowContextProps } from '../contexts/AllowContext' 4 | 5 | export function useAllow (): AllowContextProps { 6 | const ctx = useContext(AllowContext) 7 | 8 | return { 9 | ...ctx 10 | } 11 | } 12 | 13 | export function AuthenticatedRoute ({ component, ...rest }: RouteProps): JSX.Element { 14 | const ctx = useContext(AllowContext) 15 | const Component = component as any 16 | return ( 17 | ( 18 | ctx.isAuthenticated 19 | ? 20 | : 21 | )} /> 22 | ) 23 | } 24 | 25 | export function UnauthenticatedRoute ({ component, ...rest }: RouteProps): JSX.Element { 26 | const ctx = useContext(AllowContext) 27 | const Component = component as any 28 | return ( 29 | ( 30 | !ctx.isAuthenticated 31 | ? 32 | : 33 | )} /> 34 | ) 35 | } 36 | -------------------------------------------------------------------------------- /apps/concord_old/src/presentation/components/form/Button.tsx: -------------------------------------------------------------------------------- 1 | import { Button as ChakraButton, ButtonProps as ChakraButtonProps } from '@chakra-ui/button' 2 | import { ReactElement, ReactNode } from 'react' 3 | 4 | type ButtonProps = { 5 | rightIcon?: ReactElement 6 | leftIcon?: ReactElement 7 | children: ReactNode 8 | w?: string | string[] | { base?: string, sm?: string, md?: string, lg?: string, xl?: string } 9 | h?: string | string[] | { base?: string, sm?: string, md?: string, lg?: string, xl?: string } 10 | } & ChakraButtonProps 11 | 12 | export function Button ({ rightIcon, leftIcon, children, w, h, ...rest }: ButtonProps): JSX.Element { 13 | return ( 14 | 24 | {children} 25 | 26 | ) 27 | } 28 | -------------------------------------------------------------------------------- /apps/allow/src/Agree.Allow.Domain/Handlers/Queries/GetClientApplicationByAccessKeyHandler.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Allow.Domain.Handlers.Queries; 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Threading; 6 | using System.Threading.Tasks; 7 | using Agree.Allow.Domain; 8 | using Agree.Allow.Domain.Requests; 9 | using Agree.Allow.Domain.Specifications; 10 | using Agree.SharedKernel.Data; 11 | using MediatR; 12 | 13 | public class GetClientApplicationByAccessKeyHandler : IRequestHandler 14 | { 15 | private readonly IRepository _clientApplicationRepository; 16 | 17 | public GetClientApplicationByAccessKeyHandler(IRepository clientApplicationRepository) 18 | => _clientApplicationRepository = clientApplicationRepository; 19 | 20 | public async Task Handle(GetClientApplicationByAccessKeyRequest request, CancellationToken cancellationToken) 21 | => await _clientApplicationRepository.GetFirstAsync(new ClientApplicationAccessKeyEqualSpecification(request.AccessKey)); 22 | } -------------------------------------------------------------------------------- /apps/allow/src/Agree.Allow.Infrastructure.Data/Agree.Allow.Infrastructure.Data.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | runtime; build; native; contentfiles; analyzers; buildtransitive 9 | all 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | net6.0 20 | enable 21 | enable 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Vinicius Vassão 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Servers/ServerMember.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain.Servers; 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Collections.ObjectModel; 6 | using Agree.Accord.Domain.Identity; 7 | using Agree.Accord.SharedKernel; 8 | 9 | /// 10 | /// Represents a member of a server. 11 | /// Works as a pivot entity between and . 12 | /// 13 | public class ServerMember : IEntity 14 | { 15 | // EF ctor 16 | protected ServerMember() { } 17 | 18 | public ServerMember(UserAccount user, Server server) 19 | { 20 | User = user; 21 | UserId = user.Id; 22 | Server = server; 23 | ServerId = server.Id; 24 | Roles = new Collection(); 25 | } 26 | 27 | public virtual string Id => $"{UserId}_{ServerId}"; 28 | public Guid UserId { get; private set; } 29 | public UserAccount User { get; private set; } 30 | public Guid ServerId { get; private set; } 31 | public Server Server { get; private set; } 32 | public ICollection Roles { get; private set; } 33 | } -------------------------------------------------------------------------------- /apps/concord_old/src/presentation/components/avatar/FriendListItem.tsx: -------------------------------------------------------------------------------- 1 | import { Box, Link, ListItem, Text } from '@chakra-ui/layout' 2 | import { UserAvatar } from './UserAvatar' 3 | import { NavLink as RouterNavLink } from 'react-router-dom' 4 | 5 | import './FriendListItem.scss' 6 | 7 | export type FriendListItemProps = { 8 | to: string 9 | avatarUrl: string 10 | } 11 | 12 | export function FriendListItem ({ to, avatarUrl }: FriendListItemProps): JSX.Element { 13 | return ( 14 | 15 | 16 | 17 | 18 | MyFriend 19 | Online 20 | 21 | 22 | 23 | ) 24 | } 25 | -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Social/Handlers/Queries/GetUserSentFriendshipRequestsHandler.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain.Social.Handlers.Queries; 2 | 3 | using System.Collections.Generic; 4 | using System.Threading; 5 | using System.Threading.Tasks; 6 | using Agree.Accord.Domain.Social.Requests; 7 | using Agree.Accord.Domain.Social.Specifications; 8 | using Agree.Accord.SharedKernel.Data; 9 | using MediatR; 10 | 11 | /// 12 | /// Handles the retrieval of a user's sent friendship requests. 13 | /// 14 | public class GetUserSentFriendshipRequestsHandler : IRequestHandler> 15 | { 16 | private readonly IRepository _friendshipRepository; 17 | 18 | public GetUserSentFriendshipRequestsHandler(IRepository friendshipRepository) => _friendshipRepository = friendshipRepository; 19 | 20 | public async Task> Handle(GetUserSentFriendshipRequestsRequest request, CancellationToken cancellationToken) 21 | => await _friendshipRepository.GetAllAsync(new SentFriendshipRequestSpecification(request.User.Id)); 22 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Presentation/Social/Handlers/DirectMessageCreatedNotificationHandler.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain.Social.Notifications; 2 | 3 | using System.Threading; 4 | using System.Threading.Tasks; 5 | using Agree.Accord.Presentation; 6 | using Agree.Accord.Presentation.Shared; 7 | using Agree.Accord.Presentation.Social.ViewModels; 8 | using MediatR; 9 | using Microsoft.AspNetCore.SignalR; 10 | 11 | public class DirectMessageCreatedNotificationHandler : INotificationHandler 12 | { 13 | private readonly IHubContext _hubContext; 14 | 15 | public DirectMessageCreatedNotificationHandler(IHubContext hubContext) 16 | => _hubContext = hubContext; 17 | 18 | public async Task Handle(DirectMessageCreatedNotification notification, CancellationToken cancellationToken) 19 | { 20 | await _hubContext.Clients 21 | .User(notification.DirectMessage.To.Id.ToString()) 22 | .SendAsync( 23 | HubEvents.DirectMessageCreated, 24 | DirectMessageViewModel.FromEntity(notification.DirectMessage) 25 | ); 26 | } 27 | } -------------------------------------------------------------------------------- /apps/allow/src/Agree.Allow.Presentation/Accounts/ViewModels/UserAccountViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Allow.Presentation.Accounts.ViewModels; 2 | 3 | using System.Security.Claims; 4 | using System; 5 | using Agree.Allow.Domain; 6 | using System.Linq; 7 | 8 | public class UserAccountViewModel 9 | { 10 | public Guid Id { get; private set; } 11 | public string Username { get; private set; } 12 | public string Tag { get; private set; } 13 | public string NameTag => $"{Username}#{Tag}"; 14 | 15 | public static UserAccountViewModel FromEntity(UserAccount entity) => new() 16 | { 17 | Id = entity.Id, 18 | Username = entity.Username, 19 | Tag = entity.Tag.ToString(), 20 | }; 21 | 22 | public static UserAccountViewModel FromClaims(ClaimsPrincipal principal) 23 | { 24 | var nameTag = principal.Identity.Name; 25 | var split = nameTag.Split('#'); 26 | return new UserAccountViewModel 27 | { 28 | Id = Guid.Parse(principal.Claims.First(c => c.Type == ClaimTypes.NameIdentifier).Value), 29 | Username = split.First(), 30 | Tag = split.Last(), 31 | }; 32 | } 33 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Presentation/Social/Handlers/FriendshipRequestCreatedNotificationHandler.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain.Social.Notifications; 2 | 3 | using System.Threading; 4 | using System.Threading.Tasks; 5 | using Agree.Accord.Presentation; 6 | using Agree.Accord.Presentation.Shared; 7 | using Agree.Accord.Presentation.Social.ViewModels; 8 | using MediatR; 9 | using Microsoft.AspNetCore.SignalR; 10 | 11 | public class FriendshipRequestCreatedNotificationHandler : INotificationHandler 12 | { 13 | private readonly IHubContext _hubContext; 14 | 15 | public FriendshipRequestCreatedNotificationHandler(IHubContext hubContext) 16 | => _hubContext = hubContext; 17 | 18 | public async Task Handle(FriendshipRequestCreatedNotification notification, CancellationToken cancellationToken) 19 | { 20 | await _hubContext.Clients 21 | .User(notification.Friendship.ToId.ToString()) 22 | .SendAsync( 23 | HubEvents.FriendshipRequestCreated, 24 | FriendshipRequestViewModel.FromEntity(notification.Friendship) 25 | ); 26 | } 27 | } -------------------------------------------------------------------------------- /apps/allow/test/Agree.Allow.Domain.Test/Tokens/TokenTest.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Allow.Domain.Test.Tokens; 2 | 3 | using System.IdentityModel.Tokens.Jwt; 4 | using Agree.Allow.Domain.Tokens; 5 | using Agree.Allow.Test; 6 | 7 | public abstract class TokenTest : TestBase 8 | { 9 | protected JwtSecurityToken DecodeToken(string token) 10 | { 11 | var handler = new JwtSecurityTokenHandler(); 12 | var decoded = handler.ReadJwtToken(token); 13 | return decoded; 14 | } 15 | 16 | protected async Task<(UserAccount, string)> GenerateAccessToken() 17 | { 18 | var accessTokenFactory = Resolve(); 19 | var account = await CreateTestUserAccount(); 20 | var token = await accessTokenFactory.GenerateAsync(account); 21 | return (account, token.TokenValue); 22 | } 23 | 24 | protected async Task<(UserAccount, string)> GenerateRefreshToken() 25 | { 26 | var refreshTokenFactory = Resolve(); 27 | var account = await CreateTestUserAccount(); 28 | var token = await refreshTokenFactory.GenerateAsync(account); 29 | return (account, token.TokenValue); 30 | } 31 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Social/Handlers/Queries/GetUserReceivedFriendshipRequestsHandler.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain.Social.Handlers.Queries; 2 | 3 | using System.Collections.Generic; 4 | using System.Threading; 5 | using System.Threading.Tasks; 6 | using Agree.Accord.Domain.Social.Requests; 7 | using Agree.Accord.Domain.Social.Specifications; 8 | using Agree.Accord.SharedKernel.Data; 9 | using MediatR; 10 | 11 | /// 12 | /// Handles the retrieval of a user's received friendship requests. 13 | /// 14 | public class GetUserReceivedFriendshipRequestsHandler : IRequestHandler> 15 | { 16 | private readonly IRepository _friendshipRepository; 17 | 18 | public GetUserReceivedFriendshipRequestsHandler(IRepository friendshipRepository) => _friendshipRepository = friendshipRepository; 19 | 20 | public async Task> Handle(GetUserReceivedFriendshipRequestsRequest request, CancellationToken cancellationToken) 21 | => await _friendshipRepository.GetAllAsync(new ReceivedFriendshipRequestSpecification(request.User.Id)); 22 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Presentation/Social/Handlers/FriendshipRequestAcceptedNotificationHandler.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain.Social.Notifications; 2 | 3 | using System.Threading; 4 | using System.Threading.Tasks; 5 | using Agree.Accord.Presentation; 6 | using Agree.Accord.Presentation.Shared; 7 | using Agree.Accord.Presentation.Social.ViewModels; 8 | using MediatR; 9 | using Microsoft.AspNetCore.SignalR; 10 | 11 | public class FriendshipRequestAcceptedNotificationHandler : INotificationHandler 12 | { 13 | private readonly IHubContext _hubContext; 14 | 15 | public FriendshipRequestAcceptedNotificationHandler(IHubContext hubContext) 16 | => _hubContext = hubContext; 17 | 18 | public async Task Handle(FriendshipRequestAcceptedNotification notification, CancellationToken cancellationToken) 19 | { 20 | await _hubContext.Clients 21 | .User(notification.Friendship.FromId.ToString()) 22 | .SendAsync( 23 | HubEvents.FriendshipRequestAccepted, 24 | FriendshipRequestViewModel.FromEntity(notification.Friendship) 25 | ); 26 | } 27 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Presentation/Social/Handlers/FriendshipRequestDeclinedNotificationHandler.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain.Social.Notifications; 2 | 3 | using System.Threading; 4 | using System.Threading.Tasks; 5 | using Agree.Accord.Presentation; 6 | using Agree.Accord.Presentation.Shared; 7 | using Agree.Accord.Presentation.Social.ViewModels; 8 | using MediatR; 9 | using Microsoft.AspNetCore.SignalR; 10 | 11 | public class FriendshipRequestDeclinedNotificationHandler : INotificationHandler 12 | { 13 | private readonly IHubContext _hubContext; 14 | 15 | public FriendshipRequestDeclinedNotificationHandler(IHubContext hubContext) 16 | => _hubContext = hubContext; 17 | 18 | public async Task Handle(FriendshipRequestDeclinedNotification notification, CancellationToken cancellationToken) 19 | { 20 | await _hubContext.Clients 21 | .User(notification.Friendship.FromId.ToString()) 22 | .SendAsync( 23 | HubEvents.FriendshipRequestDeclined, 24 | FriendshipRequestViewModel.FromEntity(notification.Friendship) 25 | ); 26 | } 27 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Social/Handlers/Queries/GetFriendsFromUserHandler.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain.Social.Handlers.Queries; 2 | 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading; 6 | using System.Threading.Tasks; 7 | using Agree.Accord.Domain.Social.Requests; 8 | using Agree.Accord.Domain.Social.Specifications; 9 | using Agree.Accord.SharedKernel.Data; 10 | using MediatR; 11 | 12 | /// 13 | /// Handles the retrieval of a user's friends. 14 | /// 15 | public class GetFriendsFromUserHandler : IRequestHandler> 16 | { 17 | private readonly IRepository _friendshipRepository; 18 | 19 | public GetFriendsFromUserHandler(IRepository friendshipRepository) => _friendshipRepository = friendshipRepository; 20 | 21 | public async Task> Handle(GetFriendsFromUserRequest request, CancellationToken cancellationToken) 22 | { 23 | var friends = await _friendshipRepository.GetAllAsync(new FriendshipAcceptedSpecification(request.User.Id)); 24 | return friends.Select(friendship => friendship.ToId == request.User.Id ? friendship.From : friendship.To); 25 | } 26 | } -------------------------------------------------------------------------------- /apps/accord/test/Agree.Accord.Domain.Test/Agree.Accord.Domain.Test.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net6.0 4 | false 5 | 6 | 7 | 8 | 9 | 2.0 10 | 11 | 12 | 13 | 14 | 15 | runtime; build; native; contentfiles; analyzers; buildtransitive 16 | all 17 | 18 | 19 | runtime; build; native; contentfiles; analyzers; buildtransitive 20 | all 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Infrastructure.IoC/Agree.Accord.Infrastructure.IoC.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net6.0 4 | 2.0 5 | enable 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /apps/accord/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | // Use IntelliSense to find out which attributes exist for C# debugging 6 | // Use hover for the description of the existing attributes 7 | // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md 8 | "name": ".NET Core Launch (web)", 9 | "type": "coreclr", 10 | "request": "launch", 11 | "preLaunchTask": "build", 12 | // If you have changed target frameworks, make sure to update the program path. 13 | "program": "${workspaceFolder}/src/Agree.Accord.Presentation/bin/Debug/net6.0/Agree.Accord.Presentation.dll", 14 | "args": [], 15 | "cwd": "${workspaceFolder}/src/Agree.Accord.Presentation", 16 | "stopAtEntry": false, 17 | "env": { 18 | "ASPNETCORE_ENVIRONMENT": "Development" 19 | }, 20 | "sourceFileMap": { 21 | "/Views": "${workspaceFolder}/Views" 22 | } 23 | }, 24 | { 25 | "name": ".NET Core Attach", 26 | "type": "coreclr", 27 | "request": "attach" 28 | } 29 | ] 30 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Servers/Requests/CreateServerRequest.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain.Servers.Requests; 2 | 3 | using System.ComponentModel.DataAnnotations; 4 | using Agree.Accord.Domain.Identity; 5 | using Agree.Accord.Domain.Servers.Results; 6 | using MediatR; 7 | 8 | /// 9 | /// The representation of a request to create a new server. 10 | /// 11 | public class CreateServerRequest : IRequest 12 | { 13 | /// 14 | /// The server name. 15 | /// 16 | /// The server name. 17 | [Required] 18 | [MaxLength(50)] 19 | public string Name { get; set; } 20 | 21 | /// 22 | /// The server description. 23 | /// 24 | /// The server description. 25 | [MaxLength(300)] 26 | public string Description { get; set; } 27 | 28 | /// 29 | /// The server privacy level. 30 | /// 31 | /// The server privacy level. 32 | [Required] 33 | public ServerPrivacy PrivacyLevel { get; set; } 34 | 35 | /// 36 | /// The user that created the server. 37 | /// 38 | /// The user that created the server. 39 | public UserAccount Owner { get; set; } 40 | } -------------------------------------------------------------------------------- /apps/concord_old/src/presentation/hooks/useLoading.ts: -------------------------------------------------------------------------------- 1 | import { useEffect, useRef, useState } from 'react' 2 | 3 | type LoadingHook = { 4 | isLoading: boolean 5 | loadingMessage?: string 6 | loadingTime: number 7 | initLoading(message: string): void 8 | stopLoading(): void 9 | } 10 | 11 | export function useLoading (): LoadingHook { 12 | const [isLoading, setIsLoading] = useState(false) 13 | const [loadingMessage, setLoadingMessage] = useState() 14 | const [loadingTime, setLoadingTime] = useState(0) 15 | 16 | const loadingTimeout = useRef(null) 17 | 18 | function initLoading (message: string): void { 19 | setIsLoading(true) 20 | setLoadingMessage(message) 21 | } 22 | 23 | function stopLoading (): void { 24 | setIsLoading(false) 25 | setLoadingMessage(undefined) 26 | } 27 | 28 | useEffect(() => { 29 | if (isLoading) { 30 | if (loadingTime !== 0) { 31 | loadingTimeout.current = setTimeout(() => { 32 | setLoadingTime(current => current + 1) 33 | }, 1000) as any 34 | } 35 | } else { 36 | clearTimeout(loadingTimeout.current as any) 37 | } 38 | }, [isLoading]) 39 | 40 | return { 41 | isLoading, 42 | loadingMessage, 43 | loadingTime, 44 | initLoading, 45 | stopLoading 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Presentation/Shared/CustomControllerBase.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Presentation.Shared; 2 | 3 | using System.Net; 4 | using System.Threading.Tasks; 5 | using Agree.Accord.Domain.Identity; 6 | using Agree.Accord.Domain.Identity.Requests; 7 | using MediatR; 8 | using Microsoft.AspNetCore.Mvc; 9 | 10 | /// 11 | /// A custom that provides useful and common methods for all controllers. 12 | /// 13 | public class CustomControllerBase : ControllerBase 14 | { 15 | public const string AccessTokenCookieName = "agreeaccord_accesstoken"; 16 | protected readonly IMediator _mediator; 17 | 18 | public CustomControllerBase(IMediator mediator) => _mediator = mediator; 19 | 20 | protected UserAccount CurrentlyLoggedUser => 21 | HttpContext.User.Identity.IsAuthenticated 22 | ? UserAccount.FromClaims(HttpContext.User) 23 | : null; 24 | 25 | protected async Task GetAuthenticatedUserAccount() 26 | => await _mediator.Send(new GetAccountByIdRequest(CurrentlyLoggedUser.Id)); 27 | 28 | protected IActionResult InternalServerError() => StatusCode((int)HttpStatusCode.InternalServerError); 29 | 30 | protected IActionResult InternalServerError(object obj) => StatusCode((int)HttpStatusCode.InternalServerError, obj); 31 | } -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | // Use IntelliSense to find out which attributes exist for C# debugging 6 | // Use hover for the description of the existing attributes 7 | // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md 8 | "name": ".NET Core Launch (web) - Agree.Accord.Presentation", 9 | "type": "coreclr", 10 | "request": "launch", 11 | "preLaunchTask": "build_accord", 12 | // If you have changed target frameworks, make sure to update the program path. 13 | "program": "${workspaceFolder}/apps/accord/src/Agree.Accord.Presentation/bin/Debug/net6.0/Agree.Accord.Presentation.dll", 14 | "args": [], 15 | "cwd": "${workspaceFolder}/apps/accord/src/Agree.Accord.Presentation", 16 | "stopAtEntry": false, 17 | "env": { 18 | "ASPNETCORE_ENVIRONMENT": "Development" 19 | }, 20 | "sourceFileMap": { 21 | "/Views": "${workspaceFolder}/Views" 22 | } 23 | }, 24 | { 25 | "name": ".NET Core Attach", 26 | "type": "coreclr", 27 | "request": "attach" 28 | } 29 | ] 30 | } -------------------------------------------------------------------------------- /apps/accord/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.exclude": { 3 | "**/.git": true, 4 | "**/.svn": true, 5 | "**/.hg": true, 6 | "**/CVS": true, 7 | "**/.DS_Store": true, 8 | "**/obj": true, 9 | "**/bin": true 10 | }, 11 | "discord.enabled": true, 12 | "workbench.colorCustomizations": { 13 | "activityBar.activeBackground": "#8a2ca2", 14 | "activityBar.activeBorder": "#af9530", 15 | "activityBar.background": "#8a2ca2", 16 | "activityBar.foreground": "#e7e7e7", 17 | "activityBar.inactiveForeground": "#e7e7e799", 18 | "activityBarBadge.background": "#af9530", 19 | "activityBarBadge.foreground": "#15202b", 20 | "statusBar.background": "#68217a", 21 | "statusBar.foreground": "#e7e7e7", 22 | "statusBarItem.hoverBackground": "#8a2ca2", 23 | "titleBar.activeBackground": "#68217a", 24 | "titleBar.activeForeground": "#e7e7e7", 25 | "titleBar.inactiveBackground": "#68217a99", 26 | "titleBar.inactiveForeground": "#e7e7e799", 27 | "commandCenter.border": "#e7e7e799", 28 | "sash.hoverBorder": "#8a2ca2", 29 | "statusBarItem.remoteBackground": "#68217a", 30 | "statusBarItem.remoteForeground": "#e7e7e7" 31 | }, 32 | "peacock.remoteColor": "#68217a" 33 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Servers/Requests/CreateCategoryRequest.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain.Servers.Requests; 2 | 3 | using System.ComponentModel.DataAnnotations; 4 | using Agree.Accord.Domain.Identity; 5 | using MediatR; 6 | using Agree.Accord.Domain.Servers.Results; 7 | using System; 8 | 9 | /// 10 | /// The representation of a request to create a new category. 11 | /// 12 | public class CreateCategoryRequest : IRequest 13 | { 14 | /// 15 | /// The server id that the category belongs to. 16 | /// 17 | /// The server id. 18 | [Required] 19 | public Guid ServerId { get; set; } 20 | 21 | /// 22 | /// The category name. 23 | /// 24 | /// The category name. 25 | [Required] 26 | [MaxLength(80)] 27 | public string Name { get; set; } 28 | 29 | /// 30 | /// The category position when displayed. 31 | /// 32 | /// The category position when displayed. 33 | [Required] 34 | public int Position { get; set; } 35 | 36 | /// 37 | /// The user that created the category. 38 | /// 39 | /// The user that created the category. 40 | public UserAccount Requester { get; set; } 41 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Requests/SendDirectMessageRequest.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain.Social.Requests; 2 | 3 | using System; 4 | using System.ComponentModel.DataAnnotations; 5 | using Agree.Accord.Domain.Social.Results; 6 | using MediatR; 7 | 8 | /// 9 | /// The request to send a direct message. 10 | /// 11 | public class SendDirectMessageRequest : IRequest 12 | { 13 | public SendDirectMessageRequest() { } 14 | 15 | /// 16 | /// The user sending the direct message. 17 | /// 18 | /// The sender user account. 19 | [Required] 20 | public UserAccount From { get; set; } 21 | 22 | /// 23 | /// The user receiving the direct message. 24 | /// 25 | /// The receiver user account id. 26 | [Required] 27 | public Guid ToId { get; set; } 28 | 29 | /// 30 | /// The content of the direct message. 31 | /// 32 | /// The message content. 33 | [Required] 34 | [MaxLength(400)] 35 | public string MessageText { get; set; } 36 | 37 | /// 38 | /// The Id of the message this message is replying to. 39 | /// 40 | /// The reply to message id. 41 | public Guid? InReplyToId { get; set; } 42 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Requests/GetFriendChatRequest.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain.Social.Requests; 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | using System.ComponentModel.DataAnnotations; 6 | using MediatR; 7 | 8 | /// 9 | /// The request to get the chat between two users. 10 | /// 11 | public class GetFriendChatRequest : IRequest> 12 | { 13 | public GetFriendChatRequest() { } 14 | 15 | /// 16 | /// The id of the direct message to be retrieved. 17 | /// 18 | /// The friend id. 19 | [Required] 20 | public Guid FriendId { get; set; } 21 | 22 | /// 23 | /// The id of the user who is retrieving the chat. 24 | /// 25 | /// The user id. 26 | [Required] 27 | public Guid UserId { get; set; } 28 | 29 | /// 30 | /// The number of items to be retrieved. 31 | /// 32 | /// The number of items. 33 | [Required] 34 | [Range(1, 100)] 35 | public int PageSize { get; set; } 36 | 37 | /// 38 | /// The Id of the first item to be retrieved. 39 | /// Determines from which item the pagination will start. 40 | /// 41 | /// The first item id. 42 | public Guid StartAtId { get; set; } 43 | } -------------------------------------------------------------------------------- /apps/allow/test/Agree.Allow.Test/Agree.Allow.Test.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | enable 6 | enable 7 | 8 | false 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | runtime; build; native; contentfiles; analyzers; buildtransitive 18 | all 19 | 20 | 21 | runtime; build; native; contentfiles; analyzers; buildtransitive 22 | all 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /apps/allow/src/Agree.Allow.Infrastructure.IoC/Agree.Allow.Infrastructure.IoC.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | net6.0 19 | enable 20 | enable 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /apps/concord_old/src/presentation/components/form/TextInput.tsx: -------------------------------------------------------------------------------- 1 | import { InputLeftElement, Input, InputGroup, InputProps } from '@chakra-ui/input' 2 | 3 | import { ReactNode } from 'react' 4 | 5 | type TextInputProps = { 6 | icon: ReactNode 7 | placeholder: string 8 | type?: string 9 | w?: string | string[] | { base?: string, sm?: string, md?: string, lg?: string, xl?: string } 10 | } & InputProps 11 | 12 | export function TextInput ({ icon, placeholder, type = 'text', w = 'full', ...rest }: TextInputProps): JSX.Element { 13 | return ( 14 | 24 | 30 | {icon} 31 | 32 | 43 | 44 | ) 45 | } 46 | -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Infrastructure.Data/FriendshipRepository.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Infrastructure.Data; 2 | 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using Agree.Accord.Domain.Social; 7 | using Agree.Accord.SharedKernel.Data; 8 | using Microsoft.EntityFrameworkCore; 9 | 10 | /// 11 | /// A custom implementation for using Entity Framework. 12 | /// 13 | public class FriendshipRepository : GenericRepository, IRepository 14 | { 15 | public FriendshipRepository(ApplicationDbContext dbContext) 16 | : base(dbContext) { } 17 | 18 | public new async Task> GetAllAsync(Specification specification) 19 | { 20 | var result = await _dbContext.Set() 21 | .Where(specification.Expression) 22 | .Include(f => f.From) 23 | .Include(f => f.To) 24 | .ToListAsync(); 25 | return result; 26 | } 27 | 28 | public new async Task GetFirstAsync(Specification specification) 29 | { 30 | var result = await _dbContext.Set() 31 | .Where(specification.Expression) 32 | .Include(f => f.From) 33 | .Include(f => f.To) 34 | .FirstOrDefaultAsync(); 35 | return result; 36 | } 37 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Infrastructure/Providers/NativeMailProvider.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Infrastructure.Providers; 2 | 3 | using System; 4 | using System.Net; 5 | using System.Net.Mail; 6 | using System.Threading.Tasks; 7 | using Agree.Accord.Domain.Providers; 8 | using Agree.Accord.Infrastructure.Configuration; 9 | using Microsoft.Extensions.Options; 10 | 11 | /// 12 | /// A implementation of using C#'s native . 13 | /// 14 | public class NativeMailProvider : IMailProvider, IDisposable 15 | { 16 | private readonly SmtpClient _client; 17 | private const string DefaultSender = "noreply@agree.com"; 18 | 19 | public NativeMailProvider(IOptions options) => _client = new SmtpClient(options.Value.Host, options.Value.Port) 20 | { 21 | Credentials = new NetworkCredential(options.Value.UserName, options.Value.Password), 22 | EnableSsl = true 23 | }; 24 | 25 | public Task SendMailAsync(string to, string subject, string body, bool isBodyHtml = true) 26 | { 27 | var message = new MailMessage(DefaultSender, to, subject, body) 28 | { 29 | IsBodyHtml = isBodyHtml 30 | }; 31 | _client.SendAsync(message, null); 32 | 33 | return Task.CompletedTask; 34 | } 35 | 36 | public void Dispose() 37 | { 38 | _client.Dispose(); 39 | GC.SuppressFinalize(this); 40 | } 41 | } -------------------------------------------------------------------------------- /apps/concord_old/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | browser: true, 4 | es2021: true 5 | }, 6 | extends: [ 7 | 'plugin:react/recommended', 8 | 'standard', 9 | 'plugin:@typescript-eslint/recommended' 10 | ], 11 | parser: '@typescript-eslint/parser', 12 | parserOptions: { 13 | ecmaFeatures: { 14 | jsx: true 15 | }, 16 | ecmaVersion: 12, 17 | sourceType: 'module' 18 | }, 19 | plugins: [ 20 | 'react', 21 | '@typescript-eslint' 22 | ], 23 | settings: { 24 | 'import/resolver': { 25 | typescript: {} 26 | } 27 | }, 28 | rules: { 29 | 'react/react-in-jsx-scope': 'off', 30 | 'no-use-before-define': 'off', 31 | '@typescript-eslint/no-use-before-define': ['error'], 32 | 'react/jsx-filename-extension': ['warn', { extensions: ['.tsx'] }], 33 | 'no-shadow': 'off', 34 | '@typescript-eslint/no-shadow': ['error'], 35 | '@typescript-eslint/no-explicit-any': 'off', 36 | 'no-template-curly-in-string': 'off', 37 | 'import/no-duplicates': 'off', 38 | 'import/prefer-default-export': 'off', 39 | 'import/extensions': [ 40 | 'error', 41 | 'ignorePackages', 42 | { 43 | ts: 'never', 44 | tsx: 'never' 45 | } 46 | ], 47 | '@typescript-eslint/no-unused-vars': [ 48 | 'warn', 49 | { 50 | argsIgnorePattern: '_' 51 | } 52 | ], 53 | '@typescript-eslint/explicit-module-boundary-types': 'off' 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /apps/concord_old/src/logic/contexts/ContextContainer.tsx: -------------------------------------------------------------------------------- 1 | import { ChakraProvider } from '@chakra-ui/react' 2 | import { PropsWithChildren } from 'react' 3 | import { CookiesProvider } from 'react-cookie' 4 | import { resource } from '../../i18n' 5 | import { I18nProvider } from '../../presentation/contexts/I18nContext' 6 | import { theme } from '../../presentation/styles/theme' 7 | import { AxiosHttpClient } from '../services/implementations/AxiosHttpClient' 8 | import { ConsoleLogger } from '../services/implementations/ConsoleLogger' 9 | import { LocalStorageCache } from '../services/implementations/LocalStorageCache' 10 | import { AllowProvider } from './AllowContext' 11 | import { ServerProvider } from './ServerContext' 12 | 13 | const axiosHttpClient = new AxiosHttpClient() 14 | const localStorageCache = new LocalStorageCache() 15 | const consoleLogger = new ConsoleLogger() 16 | 17 | export function ContextContainer ({ children }: PropsWithChildren): JSX.Element { 18 | return ( 19 | 20 | 21 | 22 | 23 | 24 | {children} 25 | 26 | 27 | 28 | 29 | 30 | ) 31 | } 32 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "label": "build_accord", 6 | "command": "dotnet", 7 | "type": "process", 8 | "args": [ 9 | "build", 10 | "${workspaceFolder}/apps/accord/src/Agree.Accord.Presentation/Agree.Accord.Presentation.csproj", 11 | "/property:GenerateFullPaths=true", 12 | "/consoleloggerparameters:NoSummary" 13 | ], 14 | "problemMatcher": "$msCompile" 15 | }, 16 | { 17 | "label": "publish_accord", 18 | "command": "dotnet", 19 | "type": "process", 20 | "args": [ 21 | "publish", 22 | "${workspaceFolder}/apps/accord/src/Agree.Accord.Presentation/Agree.Accord.Presentation.csproj", 23 | "/property:GenerateFullPaths=true", 24 | "/consoleloggerparameters:NoSummary" 25 | ], 26 | "problemMatcher": "$msCompile" 27 | }, 28 | { 29 | "label": "watch_accord", 30 | "command": "dotnet", 31 | "type": "process", 32 | "args": [ 33 | "watch", 34 | "run", 35 | "--project", 36 | "${workspaceFolder}/apps/accord/src/Agree.Accord.Presentation/Agree.Accord.Presentation.csproj" 37 | ], 38 | "problemMatcher": "$msCompile" 39 | } 40 | ] 41 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Presentation/Shared/CustomHubBase.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Presentation.Shared; 2 | 3 | using System.Threading.Tasks; 4 | using Agree.Accord.Domain.Identity; 5 | using Agree.Accord.Domain.Identity.Requests; 6 | using MediatR; 7 | using Microsoft.AspNetCore.SignalR; 8 | using Microsoft.Extensions.Logging; 9 | 10 | /// 11 | /// A custom that provides useful and common methods for all hubs. 12 | /// 13 | public class CustomHubBase : Hub 14 | { 15 | public const string AccessTokenCookieName = "agreeaccord_accesstoken"; 16 | 17 | private readonly ILogger _logger; 18 | 19 | protected readonly IMediator _mediator; 20 | 21 | public CustomHubBase(ILogger logger, IMediator mediator) 22 | { 23 | _logger = logger; 24 | _mediator = mediator; 25 | } 26 | 27 | protected UserAccount CurrentlyLoggedUser => 28 | Context.User.Identity.IsAuthenticated 29 | ? UserAccount.FromClaims(Context.User) 30 | : null; 31 | 32 | protected async Task GetAuthenticatedUserAccount() 33 | => await _mediator.Send(new GetAccountByIdRequest(CurrentlyLoggedUser.Id)); 34 | 35 | public string GetConnectionId() => Context.ConnectionId; 36 | 37 | public override async Task OnConnectedAsync() 38 | { 39 | await base.OnConnectedAsync(); 40 | _logger.LogInformation("New connection on hub: {0}", CurrentlyLoggedUser.NameTag); 41 | } 42 | } -------------------------------------------------------------------------------- /apps/accord/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "label": "build", 6 | "command": "dotnet", 7 | "type": "process", 8 | "args": [ 9 | "build", 10 | "${workspaceFolder}/src/Agree.Accord.Presentation/Agree.Accord.Presentation.csproj", 11 | "/property:GenerateFullPaths=true", 12 | "/consoleloggerparameters:NoSummary" 13 | ], 14 | "problemMatcher": "$msCompile" 15 | }, 16 | { 17 | "label": "publish", 18 | "command": "dotnet", 19 | "type": "process", 20 | "args": [ 21 | "publish", 22 | "${workspaceFolder}/src/Agree.Accord.Presentation/Agree.Accord.Presentation.csproj", 23 | "/property:GenerateFullPaths=true", 24 | "/consoleloggerparameters:NoSummary" 25 | ], 26 | "problemMatcher": "$msCompile" 27 | }, 28 | { 29 | "label": "watch", 30 | "command": "dotnet", 31 | "type": "process", 32 | "args": [ 33 | "watch", 34 | "run", 35 | "${workspaceFolder}/src/Agree.Accord.Presentation/Agree.Accord.Presentation.csproj", 36 | "/property:GenerateFullPaths=true", 37 | "/consoleloggerparameters:NoSummary" 38 | ], 39 | "problemMatcher": "$msCompile" 40 | } 41 | ] 42 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Presentation/Social/ViewModels/DirectMessageViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Presentation.Social.ViewModels; 2 | 3 | using System; 4 | using Agree.Accord.Domain.Social; 5 | using Agree.Accord.Presentation.Identity.ViewModels; 6 | 7 | /// 8 | /// The view model for a direct message. 9 | /// 10 | public class DirectMessageViewModel 11 | { 12 | public Guid Id { get; private set; } 13 | public string Text { get; private set; } 14 | public UserAccountViewModel From { get; private set; } 15 | public UserAccountViewModel To { get; private set; } 16 | public DirectMessageViewModel InReplyTo { get; private set; } 17 | public bool Read { get; private set; } 18 | public DateTime CreatedAt { get; private set; } 19 | 20 | /// 21 | /// Creates a new instance of the class from a direct message entity. 22 | /// 23 | /// The direct message entity. 24 | /// The view model. 25 | public static DirectMessageViewModel FromEntity(DirectMessage entity, bool hideReply = false) => new() 26 | { 27 | Id = entity.Id, 28 | From = UserAccountViewModel.FromEntity(entity.From), 29 | To = UserAccountViewModel.FromEntity(entity.To), 30 | InReplyTo = entity.InReplyTo != null ? FromEntity(entity.InReplyTo, true) : null, 31 | Read = entity.Read, 32 | Text = entity.Text, 33 | CreatedAt = entity.CreatedAt 34 | }; 35 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Presentation/Servers/ViewModels/ServerViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Presentation.Servers.ViewModels; 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using Agree.Accord.Domain.Servers; 7 | using Agree.Accord.Presentation.Identity.ViewModels; 8 | 9 | /// 10 | /// A server view model. 11 | /// 12 | public class ServerViewModel 13 | { 14 | public Guid Id { get; private set; } 15 | public string Name { get; private set; } 16 | public string Description { get; private set; } 17 | public string PrivacyLevel { get; private set; } 18 | public DateTime CreatedAt { get; private set; } 19 | 20 | public IEnumerable Roles { get; private set; } 21 | 22 | public IEnumerable Members { get; private set; } 23 | 24 | /// 25 | /// Creates a new instance of the class from a server entity. 26 | /// 27 | /// The server. 28 | /// The view model. 29 | public static ServerViewModel FromEntity(Server entity) => new() 30 | { 31 | Id = entity.Id, 32 | Name = entity.Name, 33 | Description = entity.Description, 34 | PrivacyLevel = entity.PrivacyLevel.ToString(), 35 | CreatedAt = entity.CreatedAt, 36 | Roles = entity.Roles.Select(r => RoleViewModel.FromEntity(r, true)), 37 | Members = entity.Members.Select(sm => UserAccountViewModel.FromEntity(sm.User)) 38 | }; 39 | } -------------------------------------------------------------------------------- /apps/allow/test/Agree.Allow.Domain.Test/Agree.Allow.Domain.Test.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | enable 6 | enable 7 | 8 | false 9 | 10 | 11 | 12 | 13 | 14 | 15 | runtime; build; native; contentfiles; analyzers; buildtransitive 16 | all 17 | 18 | 19 | runtime; build; native; contentfiles; analyzers; buildtransitive 20 | all 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | PreserveNewest 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Presentation/Servers/ViewModels/RoleViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Presentation.Servers.ViewModels; 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using Agree.Accord.Domain.Servers; 7 | using Agree.Accord.Presentation.Identity.ViewModels; 8 | 9 | /// 10 | /// A role view model. 11 | /// 12 | public class RoleViewModel 13 | { 14 | /// 15 | /// The role Id. 16 | /// 17 | public Guid Id { get; private set; } 18 | 19 | /// 20 | /// The role name. 21 | /// 22 | public string Name { get; private set; } 23 | 24 | /// 25 | /// The server this role belongs to. 26 | /// 27 | public ServerViewModel Server { get; private set; } 28 | 29 | /// 30 | /// The server members with this role. 31 | /// 32 | public IEnumerable Members { get; private set; } 33 | 34 | /// 35 | /// Creates a new instance of the class from a server entity. 36 | /// 37 | /// The server. 38 | /// The view model. 39 | public static RoleViewModel FromEntity(ServerRole entity, bool hideServer = false) => new() 40 | { 41 | Id = entity.Id, 42 | Name = entity.Name, 43 | Server = hideServer ? null : ServerViewModel.FromEntity(entity.Server), 44 | Members = entity.ServerMembers.Select(sm => UserAccountViewModel.FromEntity(sm.User)) 45 | }; 46 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Social/Handlers/Commands/RemoveFriendHandler.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain.Social.Handlers.Commands; 2 | 3 | using System.Threading; 4 | using System.Threading.Tasks; 5 | using Agree.Accord.Domain.Social.Requests; 6 | using Agree.Accord.Domain.Social.Results; 7 | using Agree.Accord.Domain.Social.Specifications; 8 | using Agree.Accord.SharedKernel; 9 | using Agree.Accord.SharedKernel.Data; 10 | using MediatR; 11 | 12 | /// 13 | /// Handles the removal of a friend. 14 | /// 15 | public class RemoveFriendHandler : IRequestHandler 16 | { 17 | private readonly IRepository _friendshipRepository; 18 | 19 | public RemoveFriendHandler(IRepository friendshipRepository) => _friendshipRepository = friendshipRepository; 20 | 21 | public async Task Handle(RemoveFriendRequest request, CancellationToken cancellationToken) 22 | { 23 | var friendship = await _friendshipRepository.GetFirstAsync(new FriendshipExistsSpecification(request.User.Id, request.FriendId)); 24 | 25 | if (friendship == null) 26 | return RemoveFriendResult.Fail(new ErrorList("Friendship", "Friendship does not exist.")); 27 | if (!friendship.Accepted) 28 | return RemoveFriendResult.Fail(new ErrorList("Friendship", "You are not friends with this user.")); 29 | 30 | await _friendshipRepository.DeleteAsync(friendship); 31 | await _friendshipRepository.CommitAsync(); 32 | 33 | return RemoveFriendResult.Ok(friendship); 34 | } 35 | } -------------------------------------------------------------------------------- /apps/allow/src/Agree.Allow.Domain/Handlers/Commands/ValidateTokenHandler.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Allow.Domain.Handlers.Commands; 2 | 3 | using System; 4 | using System.Threading; 5 | using System.Threading.Tasks; 6 | using Agree.Allow.Domain.Requests; 7 | using Agree.Allow.Domain.Results; 8 | using Agree.Allow.Domain.Tokens; 9 | using Agree.SharedKernel.Data; 10 | using MediatR; 11 | 12 | public class ValidateTokenHandler : IRequestHandler 13 | { 14 | private readonly IRepository _accountRepository; 15 | private readonly AccessTokenFactory _accessTokenFactory; 16 | private readonly RefreshTokenFactory _refreshTokenFactory; 17 | private readonly TokenValidator _tokenValidator; 18 | 19 | public ValidateTokenHandler(IRepository accountRepository, 20 | AccessTokenFactory accessTokenFactory, 21 | RefreshTokenFactory refreshTokenFactory, 22 | TokenValidator tokenValidator) 23 | { 24 | _accountRepository = accountRepository; 25 | _accessTokenFactory = accessTokenFactory; 26 | _refreshTokenFactory = refreshTokenFactory; 27 | _tokenValidator = tokenValidator; 28 | } 29 | 30 | public async Task Handle(ValidateTokenRequest request, CancellationToken cancellationToken) 31 | { 32 | var user = await _tokenValidator.ValidateAsync(request.Token); 33 | 34 | if (user == null) 35 | return TokenValidationResult.Fail(); 36 | 37 | return TokenValidationResult.Ok(user); 38 | } 39 | } -------------------------------------------------------------------------------- /apps/concord_old/src/validation/RegisterValidator.ts: -------------------------------------------------------------------------------- 1 | import * as Yup from 'yup' 2 | 3 | import { IValidator } from './IValidator' 4 | 5 | export type RegisterInput = { 6 | email: string 7 | userName: string 8 | password: string 9 | confirmPassword: string 10 | } 11 | 12 | export class RegisterValidator implements IValidator { 13 | public async validate (input: RegisterInput): Promise { 14 | const schema = Yup.object().shape({ 15 | email: Yup.string().required('Email is required') 16 | .email('Email must be a valid email address'), 17 | userName: Yup.string().required('UserName is required') 18 | .min(1, 'UserName must have at least ${min} characters') 19 | .max(20, 'UserName must not have more than ${max} characters'), 20 | password: Yup.string().required('Password is required') 21 | .min(6, 'Password must have at least ${min} characters') 22 | .max(255, 'Password must not have more than ${max} characters') 23 | .matches( 24 | /^(?=.*[A-Z])(?=.*\d)(?=.*[a-z])[A-Za-z\d!@#$%&*_-]{6,}$/, 25 | 'Password must contain one uppercase, one lowercase and one digit characters' 26 | ), 27 | confirmPassword: Yup.string().required('Password confirmation is required') 28 | .oneOf([Yup.ref('password'), null], 'Passwords must match') 29 | }) 30 | 31 | try { 32 | await schema.validate(input, { abortEarly: false }) 33 | return null 34 | } catch (error) { 35 | if (error instanceof Yup.ValidationError) { 36 | return error 37 | } 38 | return null 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /apps/allow/test/Agree.Allow.Domain.Test/DiscriminatorTagTest.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Allow.Domain.Test; 2 | 3 | public class DiscriminatorTagTest 4 | { 5 | [Theory] 6 | [InlineData(0, true)] 7 | [InlineData("0000", true)] 8 | [InlineData(1, true)] 9 | [InlineData("1", true)] 10 | [InlineData("01", true)] 11 | [InlineData("001", true)] 12 | [InlineData("0001", true)] 13 | [InlineData("00001", false)] 14 | [InlineData(11, true)] 15 | [InlineData(111, true)] 16 | [InlineData(1111, true)] 17 | [InlineData("0111", true)] 18 | [InlineData(11111, false)] 19 | [InlineData("01111", false)] 20 | [InlineData("", false)] 21 | [InlineData(" ", false)] 22 | [InlineData("a", false)] 23 | [InlineData("a1", false)] 24 | public void TryParse_ShouldParseValuesCorrectly(object value, bool isValidTag) 25 | { 26 | if (DiscriminatorTag.TryParse(value, out var tag)) 27 | { 28 | if (isValidTag) 29 | { 30 | Assert.Equal(value.ToString().PadLeft(4, '0'), tag.ToString()); 31 | Assert.Equal(ushort.Parse(value.ToString()), tag.Value); 32 | } 33 | else 34 | { 35 | Assert.Equal("0000", tag.ToString()); 36 | Assert.Equal(0, tag.Value); 37 | } 38 | } 39 | } 40 | 41 | [Fact] 42 | public void NewTag_ShouldReturnTagBetween1And9999() 43 | { 44 | for (var i = 0; i < 1000000; i++) 45 | { 46 | var tag = DiscriminatorTag.NewTag(); 47 | Assert.True(tag.Value >= 1); 48 | Assert.True(tag.Value <= 9999); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /apps/allow/src/Agree.Allow.Domain/Tokens/RefreshTokenFactory.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Allow.Domain.Tokens; 2 | 3 | using System; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Security.Claims; 7 | using System.IdentityModel.Tokens.Jwt; 8 | using Microsoft.Extensions.Options; 9 | using Microsoft.IdentityModel.Tokens; 10 | 11 | public class RefreshTokenFactory 12 | { 13 | private readonly JwtConfiguration _jwtConfiguration; 14 | 15 | public RefreshTokenFactory(IOptions jwtConfiguration) 16 | { 17 | _jwtConfiguration = jwtConfiguration.Value; 18 | } 19 | 20 | private Token GenerateRefreshTokenCore(UserAccount account) 21 | { 22 | var tokenHandler = new JwtSecurityTokenHandler(); 23 | var key = Encoding.ASCII.GetBytes(_jwtConfiguration.SigningKey); 24 | 25 | var expiresIn = DateTime.UtcNow.AddDays(_jwtConfiguration.RefreshTokenExpiresInDays); 26 | var tokenDescriptor = new SecurityTokenDescriptor 27 | { 28 | Subject = new ClaimsIdentity(new Claim[] 29 | { 30 | new Claim(JwtRegisteredClaimNames.Sub, account.Id.ToString()), 31 | new Claim("rsh", "y") 32 | }), 33 | Issuer = _jwtConfiguration.Issuer, 34 | Expires = expiresIn, 35 | SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature) 36 | }; 37 | 38 | var token = tokenHandler.CreateJwtSecurityToken(tokenDescriptor); 39 | return new Token(tokenHandler.WriteToken(token), ((DateTimeOffset)expiresIn).ToUnixTimeSeconds(), "Bearer"); 40 | } 41 | 42 | public Task GenerateAsync(UserAccount account) => Task.Run(() => GenerateRefreshTokenCore(account)); 43 | } -------------------------------------------------------------------------------- /apps/allow/src/Agree.Allow.Domain/Handlers/Commands/RefreshTokenHandler.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Allow.Domain.Handlers.Commands; 2 | 3 | using System; 4 | using System.Threading; 5 | using System.Threading.Tasks; 6 | using Agree.Allow.Domain.Requests; 7 | using Agree.Allow.Domain.Results; 8 | using Agree.Allow.Domain.Tokens; 9 | using Agree.SharedKernel.Data; 10 | using MediatR; 11 | 12 | public class RefreshTokenHandler : IRequestHandler 13 | { 14 | private readonly IRepository _accountRepository; 15 | private readonly AccessTokenFactory _accessTokenFactory; 16 | private readonly RefreshTokenFactory _refreshTokenFactory; 17 | private readonly TokenValidator _tokenValidator; 18 | 19 | public RefreshTokenHandler(IRepository accountRepository, 20 | AccessTokenFactory accessTokenFactory, 21 | RefreshTokenFactory refreshTokenFactory, 22 | TokenValidator tokenValidator) 23 | { 24 | _accountRepository = accountRepository; 25 | _accessTokenFactory = accessTokenFactory; 26 | _refreshTokenFactory = refreshTokenFactory; 27 | _tokenValidator = tokenValidator; 28 | } 29 | 30 | public async Task Handle(RefreshTokenRequest request, CancellationToken cancellationToken) 31 | { 32 | var user = await _tokenValidator.ValidateAsync(request.RefreshToken, true); 33 | 34 | if (user == null) 35 | return AuthenticationResult.Fail(); 36 | 37 | var accessToken = await _accessTokenFactory.GenerateAsync(user); 38 | var refreshToken = await _refreshTokenFactory.GenerateAsync(user); 39 | 40 | return AuthenticationResult.Ok(new TokenCollection(accessToken, refreshToken)); 41 | } 42 | } -------------------------------------------------------------------------------- /apps/concord_old/src/presentation/components/form/PasswordInput.tsx: -------------------------------------------------------------------------------- 1 | import { useDisclosure } from '@chakra-ui/hooks' 2 | import { InputLeftElement, Input, InputGroup, InputRightElement, InputProps } from '@chakra-ui/input' 3 | 4 | import { ReactNode } from 'react' 5 | import { FiEye, FiEyeOff } from 'react-icons/fi' 6 | 7 | type PasswordInputProps = { 8 | icon: ReactNode 9 | placeholder: string 10 | w?: string | string[] | { base?: string, sm?: string, md?: string, lg?: string, xl?: string } 11 | } & InputProps 12 | 13 | export function PasswordInput ({ icon, placeholder, w = 'full', ...rest }: PasswordInputProps): JSX.Element { 14 | const { isOpen, onToggle } = useDisclosure() 15 | 16 | return ( 17 | 27 | 33 | {icon} 34 | 35 | 46 | 53 | {isOpen ? : } 54 | 55 | 56 | ) 57 | } 58 | -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Servers/Handlers/Commands/CreateServerHandler.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain.Servers.Handlers.Commands; 2 | 3 | using System; 4 | using System.Threading; 5 | using System.Threading.Tasks; 6 | using Agree.Accord.Domain.Servers.Requests; 7 | using Agree.Accord.Domain.Servers.Results; 8 | using Agree.Accord.SharedKernel; 9 | using Agree.Accord.SharedKernel.Data; 10 | using MediatR; 11 | 12 | /// 13 | /// Handles the creation of a new . 14 | /// 15 | public class CreateServerHandler : IRequestHandler 16 | { 17 | private readonly IRepository _serverRepository; 18 | 19 | public CreateServerHandler(IRepository serverRepository) 20 | => _serverRepository = serverRepository; 21 | 22 | public async Task Handle(CreateServerRequest request, CancellationToken cancellationToken) 23 | { 24 | var validationResult = AnnotationValidator.TryValidate(request); 25 | 26 | if (validationResult.Failed) 27 | return CreateServerResult.Fail(validationResult.Error.ToErrorList()); 28 | 29 | var server = new Server(request.Name, request.PrivacyLevel, request.Description); 30 | 31 | var category = Category.CreateDefaultWelcomeCategory(server); 32 | server.Categories.Add(category); 33 | 34 | var adminRole = ServerRole.CreateDefaultAdminRole(server); 35 | server.Roles.Add(adminRole); 36 | 37 | var ownerAsMember = new ServerMember(request.Owner, server); 38 | ownerAsMember.Roles.Add(adminRole); 39 | server.Members.Add(ownerAsMember); 40 | 41 | await _serverRepository.InsertAsync(server); 42 | await _serverRepository.CommitAsync(); 43 | 44 | return CreateServerResult.Ok(server); 45 | } 46 | } -------------------------------------------------------------------------------- /apps/accord/test/Agree.Accord.Domain.Test/DiscriminatorTagTest.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain.Test; 2 | 3 | using System; 4 | using Agree.Accord.Domain.Identity; 5 | using Xunit; 6 | 7 | public class DiscriminatorTagTest 8 | { 9 | [Theory] 10 | [InlineData(0, true)] 11 | [InlineData("0000", true)] 12 | [InlineData(1, true)] 13 | [InlineData("1", true)] 14 | [InlineData("01", true)] 15 | [InlineData("001", true)] 16 | [InlineData("0001", true)] 17 | [InlineData("00001", false)] 18 | [InlineData(11, true)] 19 | [InlineData(111, true)] 20 | [InlineData(1111, true)] 21 | [InlineData("0111", true)] 22 | [InlineData(11111, false)] 23 | [InlineData("01111", false)] 24 | [InlineData("", false)] 25 | [InlineData(" ", false)] 26 | [InlineData("a", false)] 27 | [InlineData("a1", false)] 28 | public void TryParse_ShouldParseValuesCorrectly(object value, bool isValidTag) 29 | { 30 | if (DiscriminatorTag.TryParse(value, out var tag)) 31 | { 32 | if (isValidTag) 33 | { 34 | Assert.Equal(value.ToString().PadLeft(4, '0'), tag.ToString()); 35 | Assert.Equal(ushort.Parse(value.ToString()), tag.Value); 36 | } 37 | else 38 | { 39 | Assert.Equal("0000", tag.ToString()); 40 | Assert.Equal(0, tag.Value); 41 | } 42 | } 43 | } 44 | 45 | [Fact] 46 | public void NewTag_ShouldReturnTagBetween1And9999() 47 | { 48 | var oneMillion = 1000000; 49 | for (var i = 0; i < oneMillion; i++) 50 | { 51 | var tag = DiscriminatorTag.NewTag(); 52 | Assert.True(tag.Value >= 1); 53 | Assert.True(tag.Value <= 9999); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Servers/ServerRole.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain.Servers; 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Collections.ObjectModel; 6 | using Agree.Accord.SharedKernel; 7 | 8 | /// 9 | /// A role in a server. 10 | /// 11 | public class ServerRole : IEntity 12 | { 13 | // EF ctor 14 | protected ServerRole() { } 15 | 16 | public ServerRole(string name, Server server) 17 | { 18 | Id = Guid.NewGuid(); 19 | Name = name; 20 | Server = server; 21 | ServerId = server.Id; 22 | ServerMembers = new Collection(); 23 | Permissions = new Collection(); 24 | } 25 | 26 | /// 27 | /// Creates a new role with default admin permissions for a server. 28 | /// 29 | public static ServerRole CreateDefaultAdminRole(Server server) 30 | => new("Admin", server); 31 | 32 | /// 33 | /// The role Id. 34 | /// 35 | public Guid Id { get; private set; } 36 | 37 | /// 38 | /// The role name. 39 | /// 40 | public string Name { get; private set; } 41 | 42 | /// 43 | /// The server Id this role belongs to. 44 | /// 45 | public Guid ServerId { get; private set; } 46 | 47 | /// 48 | /// The server this role belongs to. 49 | /// 50 | public Server Server { get; private set; } 51 | 52 | /// 53 | /// The server members with this role. 54 | /// 55 | public ICollection ServerMembers { get; private set; } 56 | 57 | /// 58 | /// The permissions this role has. 59 | /// 60 | public ICollection Permissions { get; private set; } 61 | } -------------------------------------------------------------------------------- /apps/allow/src/Agree.Allow.Domain/Requests/CreateAccountRequest.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Allow.Domain.Requests; 2 | 3 | using System.ComponentModel.DataAnnotations; 4 | using Agree.Allow.Domain.Results; 5 | using MediatR; 6 | 7 | public class CreateAccountRequest : IRequest 8 | { 9 | [Required(ErrorMessage = "Email is required.")] 10 | [EmailAddress(ErrorMessage = "Email must be a valid email address.")] 11 | [MaxLength(255, ErrorMessage = "Email must have less than 255 characters.")] 12 | public string EmailAddress { get; set; } 13 | 14 | [Required(ErrorMessage = "Username is required.")] 15 | [MinLength(1, ErrorMessage = "Username must have at least 1 character.")] 16 | [MaxLength(40, ErrorMessage = "Username must have less than 40 characters.")] 17 | [RegularExpression(UsernameRegEx, ErrorMessage = "Username must only contain alfabetic characters, digits, _ and -.")] 18 | public string Username { get; set; } 19 | 20 | [Required(ErrorMessage = "Password is required.")] 21 | [MinLength(6, ErrorMessage = "Password must have at least 6 characters.")] 22 | [MaxLength(80, ErrorMessage = "Password must have less than 80 characters.")] 23 | [RegularExpression(PasswordRegEx, ErrorMessage = "Password must contain at least one uppercase character, one lowercase character, and a digit.")] 24 | public string Password { get; set; } 25 | 26 | [Required(ErrorMessage = "Password confirmation is required.")] 27 | [Compare("Password", ErrorMessage = "Passwords doesn't match.")] 28 | public string PasswordConfirmation { get; set; } 29 | 30 | private const string UsernameRegEx = @"[a-zA-Z0-9_-]*"; 31 | 32 | private const string PasswordRegEx = @"(^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).*$)?(^(?=.*\d)(?=.*[a-z])(?=.*[@#$%^&+=]).*$)?(^(?=.*\d)(?=.*[A-Z])(?=.*[@#$%^&+=]).*$)?(^(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=]).*$)?"; 33 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Social/Handlers/Commands/MarkDirectMessageAsReadHandler.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain.Social.Handlers.Commands; 2 | 3 | using System; 4 | using System.Threading; 5 | using System.Threading.Tasks; 6 | using Agree.Accord.Domain.Social.Requests; 7 | using Agree.Accord.Domain.Social.Results; 8 | using Agree.Accord.Domain.Social.Specifications; 9 | using Agree.Accord.SharedKernel; 10 | using Agree.Accord.SharedKernel.Data; 11 | using MediatR; 12 | 13 | /// 14 | /// Handles the marking of a direct message as read. 15 | /// 16 | public class MarkDirectMessageAsReadHandler : IRequestHandler 17 | { 18 | private readonly IRepository _directMessageRepository; 19 | 20 | public MarkDirectMessageAsReadHandler(IRepository directMessageRepository) 21 | => _directMessageRepository = directMessageRepository; 22 | 23 | public async Task Handle(MarkDirectMessageAsReadRequest request, CancellationToken cancellationToken) 24 | { 25 | var directMessage = await _directMessageRepository.GetFirstAsync(new DirectMessageIdEqualSpecification(request.DirectMessageId)); 26 | if (directMessage == null) 27 | { 28 | return DirectMessageResult.Fail(new ErrorList("DirectMessageId", "Direct message not found.")); 29 | } 30 | if (directMessage.From.Id != request.Requester.Id) 31 | { 32 | return DirectMessageResult.Fail(new ErrorList("DirectMessageId", "Direct message was not sent to you.")); 33 | } 34 | 35 | directMessage.MarkRead(); 36 | 37 | await _directMessageRepository.UpdateAsync(directMessage); 38 | await _directMessageRepository.CommitAsync(); 39 | 40 | return DirectMessageResult.Ok(directMessage); 41 | } 42 | } -------------------------------------------------------------------------------- /apps/concord_old/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "agree-concord", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@chakra-ui/react": "^1.4.1", 7 | "@emotion/react": "^11", 8 | "@emotion/styled": "^11", 9 | "@testing-library/jest-dom": "^5.11.4", 10 | "@testing-library/react": "^11.1.0", 11 | "@testing-library/user-event": "^12.1.10", 12 | "@types/jest": "^26.0.15", 13 | "@types/node": "^12.0.0", 14 | "@types/react": "^17.0.3", 15 | "@types/react-dom": "^17.0.3", 16 | "axios": "^0.21.1", 17 | "date-fns": "^2.21.3", 18 | "framer-motion": "^4", 19 | "react": "^17.0.1", 20 | "react-cookie": "^4.0.3", 21 | "react-dom": "^17.0.1", 22 | "react-icons": "^4.2.0", 23 | "react-router-dom": "^5.2.0", 24 | "react-scripts": "4.0.3", 25 | "react-use": "^17.2.4", 26 | "sass": "^1.32.11", 27 | "ts-results": "^3.3.0", 28 | "typescript": "^4.1.2", 29 | "web-vitals": "^1.0.1", 30 | "yup": "^0.32.9" 31 | }, 32 | "scripts": { 33 | "start": "react-scripts start", 34 | "build": "react-scripts build", 35 | "test": "react-scripts test", 36 | "eject": "react-scripts eject" 37 | }, 38 | "browserslist": { 39 | "production": [ 40 | ">0.2%", 41 | "not dead", 42 | "not op_mini all" 43 | ], 44 | "development": [ 45 | "last 1 chrome version", 46 | "last 1 firefox version", 47 | "last 1 safari version" 48 | ] 49 | }, 50 | "devDependencies": { 51 | "@types/react-router-dom": "^5.1.7", 52 | "@typescript-eslint/eslint-plugin": "^4.19.0", 53 | "@typescript-eslint/parser": "^4.19.0", 54 | "eslint": "^7.22.0", 55 | "eslint-config-standard": "^16.0.2", 56 | "eslint-import-resolver-typescript": "^2.4.0", 57 | "eslint-plugin-import": "^2.22.1", 58 | "eslint-plugin-node": "^11.1.0", 59 | "eslint-plugin-promise": "^4.3.1", 60 | "eslint-plugin-react": "^7.23.0" 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /apps/allow/test/Agree.Allow.Domain.Test/DiscriminatorTagFactoryTest.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Allow.Domain.Test; 2 | 3 | using Agree.Allow.Test; 4 | 5 | public class DiscriminatorTagFactoryTest : TestBase 6 | { 7 | [Fact] 8 | public async Task GenerateDiscriminatorTagAsync_WithExistingTag_ReturnsNewTag() 9 | { 10 | // Arrange 11 | var sut = Resolve(); 12 | 13 | // Act 14 | var tag1 = await sut.GenerateDiscriminatorTagAsync("testuser"); 15 | var user1 = await CreateTestUserAccount(tag1); 16 | for (var i = 0; i < 9999; i++) 17 | { 18 | var tag2 = await sut.GenerateDiscriminatorTagAsync("testuser"); 19 | var user2 = await CreateTestUserAccount(tag2); 20 | 21 | // Assert 22 | Assert.NotEqual(tag1, tag2); 23 | } 24 | } 25 | 26 | [Fact] 27 | public async Task GenerateDiscriminatorTagAsync_WithMoreThan10000ExistingTags_ReturnsNull() 28 | { 29 | // Arrange 30 | var sut = Resolve(); 31 | 32 | // Act 33 | var tag1 = await sut.GenerateDiscriminatorTagAsync("testuser"); 34 | var user1 = await CreateTestUserAccount(tag1); 35 | for (var i = 0; i < 9999; i++) 36 | { 37 | var tag2 = await sut.GenerateDiscriminatorTagAsync("testuser"); 38 | var user2 = await CreateTestUserAccount(tag2); 39 | } 40 | 41 | var tag3 = await sut.GenerateDiscriminatorTagAsync("testuser"); 42 | 43 | // Assert 44 | Assert.Null(tag3); 45 | } 46 | 47 | [Fact] 48 | public async Task GenerateDiscriminatorTagAsync_WithNoExistingTags_ReturnsTag0() 49 | { 50 | // Arrange 51 | var sut = Resolve(); 52 | 53 | // Act 54 | var tag = await sut.GenerateDiscriminatorTagAsync("testuser"); 55 | 56 | // Assert 57 | Assert.Equal(0, tag.Value); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /apps/allow/src/Agree.Allow.Domain/UserAccount.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Allow.Domain; 2 | 3 | using System; 4 | using Agree.SharedKernel; 5 | using System.Security.Claims; 6 | using System.IdentityModel.Tokens.Jwt; 7 | 8 | public class UserAccount : IEntity 9 | { 10 | public UserAccount(string username, string emailAddress, string passwordHash, DiscriminatorTag tag) 11 | { 12 | Id = Guid.NewGuid(); 13 | Username = username; 14 | EmailAddress = emailAddress; 15 | PasswordHash = passwordHash; 16 | Tag = tag; 17 | CreatedAt = DateTime.UtcNow; 18 | } 19 | 20 | public Guid Id { get; private set; } 21 | 22 | public string EmailAddress { get; private set; } 23 | 24 | public string PasswordHash { get; private set; } 25 | 26 | public string Username { get; private set; } 27 | 28 | public virtual string NameTag => $"{Username}#{Tag}"; 29 | 30 | public DiscriminatorTag Tag { get; private set; } 31 | 32 | public DateTime CreatedAt { get; private set; } 33 | 34 | public ClaimsPrincipal ToClaimsPrincipal() => new(new ClaimsIdentity(new[] 35 | { 36 | new Claim(JwtRegisteredClaimNames.Sub, Id.ToString()), 37 | new Claim(JwtRegisteredClaimNames.Name, NameTag), 38 | new Claim(JwtRegisteredClaimNames.Email, EmailAddress) 39 | })); 40 | 41 | public static UserAccount FromClaims(ClaimsPrincipal principal) 42 | { 43 | var id = Guid.Parse(principal.FindFirstValue(JwtRegisteredClaimNames.Sub)); 44 | var nameTag = principal.FindFirstValue(JwtRegisteredClaimNames.Name); 45 | var emailAddress = principal.FindFirstValue(JwtRegisteredClaimNames.Email); 46 | 47 | var username = nameTag.Split('#')[0]; 48 | var tag = (DiscriminatorTag)Enum.Parse(typeof(DiscriminatorTag), nameTag.Split('#')[1]); 49 | 50 | return new UserAccount(username, emailAddress, null, tag) { Id = id }; 51 | } 52 | } -------------------------------------------------------------------------------- /apps/concord_old/src/presentation/Routes.tsx: -------------------------------------------------------------------------------- 1 | import { Switch, Route, Redirect } from 'react-router-dom' 2 | import { AuthenticatedRoute, UnauthenticatedRoute } from '../logic/hooks/useAllow' 3 | import { DashboardLayout } from './layouts/DashboardLayout' 4 | import { AuthPage } from './pages/account/AuthPage' 5 | import { HomePage } from './pages/dashboard/HomePage' 6 | import { NotFoundPage } from './pages/error/NotFoundPage' 7 | import { SettingsLayout } from './layouts/SettingsLayout' 8 | import { ServerSearch } from './pages/dashboard/ServerSearch' 9 | import { ServerCreate } from './pages/dashboard/ServerCreate' 10 | 11 | export function Routes (): JSX.Element { 12 | return ( 13 | 14 | ( 17 | 18 | ( 19 | 20 | }/> 21 | }/> 22 | }/> 23 | }/> 24 | }/> 25 | }/> 26 | }/> 27 | 28 | )}/> 29 | 30 | )}/> 31 | 32 | ( 33 | 34 | )}/> 35 | 36 | 37 | 38 | 39 | 40 | ) 41 | } 42 | -------------------------------------------------------------------------------- /apps/concord_old/src/presentation/components/nav/ServerBar.tsx: -------------------------------------------------------------------------------- 1 | import { Box, Flex, List } from '@chakra-ui/layout' 2 | import { FiCompass, FiPlus, FiSettings } from 'react-icons/fi' 3 | 4 | import IconImg from '../../assets/iconw.svg' 5 | import { useI18n } from '../../hooks/useI18n' 6 | import { ServerAvatar } from '../avatar/ServerAvatar' 7 | 8 | export function ServerBar (): JSX.Element { 9 | const { t } = useI18n() 10 | 11 | return ( 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | {Array.from(Array(6).keys()).map(i => ( 25 | 26 | ))} 27 | 28 | } marginY="0.5rem" /> 29 | 30 | } marginY="0.5rem" /> 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | } marginTop="1.75rem" /> 39 | 40 | 41 | 42 | 43 | ) 44 | } 45 | -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Social/Handlers/Commands/DeclineFriendshipRequestHandler.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain.Social.Handlers.Commands; 2 | 3 | using System.Threading; 4 | using System.Threading.Tasks; 5 | using Agree.Accord.Domain.Social.Notifications; 6 | using Agree.Accord.Domain.Social.Requests; 7 | using Agree.Accord.Domain.Social.Results; 8 | using Agree.Accord.Domain.Social.Specifications; 9 | using Agree.Accord.SharedKernel; 10 | using Agree.Accord.SharedKernel.Data; 11 | using MediatR; 12 | 13 | /// 14 | /// Handles the declining of a friendship request. 15 | /// 16 | public class DeclineFriendshipRequestHandler : IRequestHandler 17 | { 18 | private readonly IRepository _friendshipRepository; 19 | private readonly IMediator _mediator; 20 | 21 | public DeclineFriendshipRequestHandler(IRepository friendshipRepository, IMediator mediator) 22 | { 23 | _friendshipRepository = friendshipRepository; 24 | _mediator = mediator; 25 | } 26 | 27 | public async Task Handle(DeclineFriendshipRequestRequest request, CancellationToken cancellationToken) 28 | { 29 | var friendshipRequest = await _friendshipRepository.GetFirstAsync(new FriendshipExistsSpecification(request.FromUserId, request.LoggedUser.Id)); 30 | if (friendshipRequest == null) 31 | return FriendshipRequestResult.Fail(new ErrorList("Friendship", "Friendship request does not exist.")); 32 | if (friendshipRequest.Accepted) 33 | return FriendshipRequestResult.Fail(new ErrorList("Friendship", "Friendship request already accepted.")); 34 | 35 | await _friendshipRepository.DeleteAsync(friendshipRequest); 36 | await _friendshipRepository.CommitAsync(); 37 | 38 | await _mediator.Publish(new FriendshipRequestDeclinedNotification(friendshipRequest), cancellationToken); 39 | 40 | return FriendshipRequestResult.Ok(friendshipRequest); 41 | } 42 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Servers/Handlers/Commands/CreateCategoryHandler.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain.Servers.Handlers.Commands; 2 | 3 | using System; 4 | using System.Threading; 5 | using System.Threading.Tasks; 6 | using Agree.Accord.Domain.Servers.Requests; 7 | using Agree.Accord.Domain.Servers.Results; 8 | using Agree.Accord.Domain.Servers; 9 | using Agree.Accord.SharedKernel; 10 | using Agree.Accord.SharedKernel.Data; 11 | using MediatR; 12 | using Agree.Accord.Domain.Servers.Specifications; 13 | 14 | /// 15 | /// Handles the creation of a new . 16 | /// 17 | public class CreateCategoryHandler : IRequestHandler 18 | { 19 | private readonly IRepository _categoryRepository; 20 | private readonly IRepository _serverRepository; 21 | 22 | public CreateCategoryHandler(IRepository categoryRepository, IRepository serverRepository) 23 | { 24 | _categoryRepository = categoryRepository; 25 | _serverRepository = serverRepository; 26 | } 27 | 28 | public async Task Handle(CreateCategoryRequest request, CancellationToken cancellationToken) 29 | { 30 | var validationResult = AnnotationValidator.TryValidate(request); 31 | var errors = new ErrorList(); 32 | 33 | if (validationResult.Failed) 34 | errors.AddErrors(validationResult.Error); 35 | 36 | var server = await _serverRepository.GetFirstAsync(new ServerIdEqualSpecification(request.ServerId, request.Requester.Id)); 37 | 38 | if (server == null) 39 | errors.AddError("ServerId", "The server does not exist."); 40 | 41 | if (errors.HasErrors()) 42 | return CreateCategoryResult.Fail(errors); 43 | 44 | var category = new Category(request.Name, server); 45 | 46 | await _categoryRepository.InsertAsync(category); 47 | await _categoryRepository.CommitAsync(); 48 | 49 | return CreateCategoryResult.Ok(category); 50 | } 51 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Social/Handlers/Commands/AcceptFriendshipRequestHandler.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain.Social.Handlers.Commands; 2 | 3 | using System.Threading; 4 | using System.Threading.Tasks; 5 | using Agree.Accord.Domain.Social.Notifications; 6 | using Agree.Accord.Domain.Social.Requests; 7 | using Agree.Accord.Domain.Social.Results; 8 | using Agree.Accord.Domain.Social.Specifications; 9 | using Agree.Accord.SharedKernel; 10 | using Agree.Accord.SharedKernel.Data; 11 | using MediatR; 12 | 13 | /// 14 | /// Handles the acceptance of a friendship request. 15 | /// 16 | public class AcceptFriendshipRequestHandler : IRequestHandler 17 | { 18 | private readonly IRepository _friendshipRepository; 19 | private readonly IMediator _mediator; 20 | 21 | public AcceptFriendshipRequestHandler(IRepository friendshipRepository, IMediator mediator) 22 | { 23 | _friendshipRepository = friendshipRepository; 24 | _mediator = mediator; 25 | } 26 | 27 | public async Task Handle(AcceptFriendshipRequestRequest request, CancellationToken cancellationToken) 28 | { 29 | var friendshipRequest = await _friendshipRepository.GetFirstAsync(new FriendshipExistsSpecification(request.FromUserId, request.LoggedUser.Id)); 30 | if (friendshipRequest == null) 31 | return FriendshipRequestResult.Fail(new ErrorList("Friendship", "Friendship request does not exist.")); 32 | if (friendshipRequest.Accepted) 33 | return FriendshipRequestResult.Fail(new ErrorList("Friendship", "Friendship request already accepted.")); 34 | 35 | friendshipRequest.Accept(); 36 | 37 | await _friendshipRepository.UpdateAsync(friendshipRequest); 38 | await _friendshipRepository.CommitAsync(); 39 | 40 | await _mediator.Publish(new FriendshipRequestAcceptedNotification(friendshipRequest), cancellationToken); 41 | 42 | return FriendshipRequestResult.Ok(friendshipRequest); 43 | } 44 | } -------------------------------------------------------------------------------- /apps/allow/src/Agree.Allow.Domain/Handlers/Commands/PasswordLoginHandler.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Allow.Domain.Handlers.Commands; 2 | 3 | using System; 4 | using System.Threading; 5 | using System.Threading.Tasks; 6 | using Agree.Allow.Domain.Requests; 7 | using Agree.Allow.Domain.Results; 8 | using Agree.Allow.Domain.Specifications; 9 | using Agree.Allow.Domain.Tokens; 10 | using Agree.SharedKernel.Data; 11 | using MediatR; 12 | 13 | public class PasswordLoginHandler : IRequestHandler 14 | { 15 | private readonly IRepository _accountRepository; 16 | private readonly IPasswordManager _passwordManager; 17 | private readonly AccessTokenFactory _accessTokenFactory; 18 | private readonly RefreshTokenFactory _refreshTokenFactory; 19 | 20 | public PasswordLoginHandler(IRepository accountRepository, 21 | AccessTokenFactory acessTokenFactory, 22 | RefreshTokenFactory refreshTokenFactory, 23 | IPasswordManager passwordManager) 24 | { 25 | _accountRepository = accountRepository; 26 | _accessTokenFactory = acessTokenFactory; 27 | _refreshTokenFactory = refreshTokenFactory; 28 | _passwordManager = passwordManager; 29 | } 30 | 31 | public async Task Handle(PasswordLoginRequest request, CancellationToken cancellationToken) 32 | { 33 | var user = await _accountRepository.GetFirstAsync(new EmailEqualSpecification(request.EmailAddress)); 34 | 35 | if (user == null) 36 | return AuthenticationResult.Fail(); 37 | 38 | var passwordValid = await _passwordManager.CompareAsync(user.PasswordHash, request.Password); 39 | 40 | if (!passwordValid) 41 | return AuthenticationResult.Fail(); 42 | 43 | var accessToken = await _accessTokenFactory.GenerateAsync(user); 44 | var refreshToken = await _refreshTokenFactory.GenerateAsync(user); 45 | 46 | return AuthenticationResult.Ok(new TokenCollection(accessToken, refreshToken)); 47 | } 48 | } -------------------------------------------------------------------------------- /apps/allow/src/Agree.Allow.Domain/Tokens/AccessTokenFactory.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Allow.Domain.Tokens; 2 | 3 | using System; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Security.Claims; 7 | using System.IdentityModel.Tokens.Jwt; 8 | using Microsoft.Extensions.Options; 9 | using Microsoft.IdentityModel.Tokens; 10 | 11 | public class AccessTokenFactory 12 | { 13 | private readonly JwtConfiguration _jwtConfiguration; 14 | 15 | public AccessTokenFactory(IOptions jwtConfiguration) 16 | { 17 | _jwtConfiguration = jwtConfiguration.Value; 18 | } 19 | 20 | private Token GenerateAccessTokenCore(UserAccount account) 21 | { 22 | var tokenHandler = new JwtSecurityTokenHandler(); 23 | var key = Encoding.ASCII.GetBytes(_jwtConfiguration.SigningKey); 24 | 25 | var expiresIn = DateTime.UtcNow.AddMinutes(_jwtConfiguration.AccessTokenExpiresInMinutes); 26 | var tokenDescriptor = new SecurityTokenDescriptor 27 | { 28 | Subject = new ClaimsIdentity(new Claim[] 29 | { 30 | new Claim(JwtRegisteredClaimNames.Name, account.NameTag), 31 | new Claim(JwtRegisteredClaimNames.Sub, account.Id.ToString()), 32 | new Claim(JwtRegisteredClaimNames.Email, account.EmailAddress) 33 | }), 34 | Issuer = _jwtConfiguration.Issuer, 35 | Expires = expiresIn, 36 | SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature), 37 | }; 38 | 39 | var token = tokenHandler.CreateJwtSecurityToken(tokenDescriptor); 40 | return new Token(tokenHandler.WriteToken(token), ((DateTimeOffset)expiresIn).ToUnixTimeSeconds(), "Bearer"); 41 | } 42 | 43 | /// 44 | /// Generates a access token for a given user. 45 | /// 46 | /// The user account. 47 | /// The generated access token. 48 | public Task GenerateAsync(UserAccount account) => Task.Run(() => GenerateAccessTokenCore(account)); 49 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Domain/Servers/Server.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Domain.Servers; 2 | 3 | using System.Collections.ObjectModel; 4 | using System.Collections.Generic; 5 | using System; 6 | using Agree.Accord.SharedKernel; 7 | 8 | /// 9 | /// A message server. 10 | /// 11 | public class Server : IEntity 12 | { 13 | /// EF ctor 14 | protected Server() 15 | { 16 | Members = new Collection(); 17 | Roles = new Collection(); 18 | Categories = new Collection(); 19 | } 20 | 21 | public Server(string name, ServerPrivacy privacyLevel, string description = null) 22 | { 23 | Id = Guid.NewGuid(); 24 | Name = name; 25 | Description = description; 26 | PrivacyLevel = privacyLevel; 27 | CreatedAt = DateTime.UtcNow; 28 | Members = new Collection(); 29 | Roles = new Collection(); 30 | Categories = new Collection(); 31 | } 32 | 33 | /// 34 | /// The server id. 35 | /// 36 | public Guid Id { get; private set; } 37 | 38 | /// 39 | /// The server name. 40 | /// 41 | public string Name { get; private set; } 42 | 43 | /// 44 | /// The server description. 45 | /// 46 | public string Description { get; private set; } 47 | 48 | /// 49 | /// The server privacy level. 50 | /// 51 | public ServerPrivacy PrivacyLevel { get; private set; } 52 | 53 | /// 54 | /// The server creation date. 55 | /// 56 | public DateTime CreatedAt { get; private set; } 57 | 58 | /// 59 | /// The server members in a N-N pivot collection. 60 | /// 61 | public ICollection Members { get; private set; } 62 | 63 | /// 64 | /// The server roles. 65 | /// 66 | public ICollection Roles { get; private set; } 67 | 68 | /// 69 | /// The server categories. 70 | /// 71 | public ICollection Categories { get; private set; } 72 | } -------------------------------------------------------------------------------- /apps/accord/src/Agree.Accord.Presentation/Social/Controllers/FriendsController.cs: -------------------------------------------------------------------------------- 1 | namespace Agree.Accord.Presentation.Social.Controllers; 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | using Agree.Accord.Domain.Social.Requests; 8 | using Agree.Accord.Presentation.Identity.ViewModels; 9 | using Agree.Accord.Presentation.Responses; 10 | using Agree.Accord.Presentation.Shared; 11 | using MediatR; 12 | using Microsoft.AspNetCore.Authorization; 13 | using Microsoft.AspNetCore.Http; 14 | using Microsoft.AspNetCore.Mvc; 15 | 16 | /// 17 | /// A controller for managing friends. 18 | /// 19 | [ApiController] 20 | [Route("api/friends")] 21 | [Authorize] 22 | public class FriendsController : CustomControllerBase 23 | { 24 | public FriendsController(IMediator mediator) : base(mediator) { } 25 | 26 | [HttpGet] 27 | [Route("")] 28 | [Authorize] 29 | [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(GenericResponse>))] 30 | public async Task Index() 31 | { 32 | var friends = await _mediator.Send(new GetFriendsFromUserRequest(await GetAuthenticatedUserAccount())); 33 | return Ok(new GenericResponse(friends.Select(UserAccountViewModel.FromEntity))); 34 | } 35 | 36 | [HttpDelete] 37 | [Route("{friendId:guid}")] 38 | [Authorize] 39 | [ProducesResponseType(StatusCodes.Status204NoContent)] 40 | [ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ValidationErrorResponse))] 41 | public async Task Delete([FromRoute] Guid friendId) 42 | { 43 | var result = await _mediator.Send(new RemoveFriendRequest(await GetAuthenticatedUserAccount(), friendId)); 44 | if (result.Failed) 45 | { 46 | return BadRequest(new ValidationErrorResponse(result.Error)); 47 | } 48 | 49 | // await _hubContext.Clients 50 | // .User(friendId.ToString()) 51 | // .SendAsync( 52 | // FriendshipHub.FriendshipRemovedMessage, 53 | // FriendshipRequestViewModel.FromEntity(result.Data) 54 | // ); 55 | 56 | return NoContent(); 57 | } 58 | } --------------------------------------------------------------------------------