├── src
├── ChitChat.Application
│ ├── Models
│ │ ├── Dtos
│ │ │ ├── User
│ │ │ │ ├── UserProfileDto.cs
│ │ │ │ ├── Follow
│ │ │ │ │ ├── CreateFollowRequestDto.cs
│ │ │ │ │ └── FollowDto.cs
│ │ │ │ ├── Profile
│ │ │ │ │ ├── ProfileSearchQueryDto.cs
│ │ │ │ │ ├── ProfileRequestDto.cs
│ │ │ │ │ └── ProfileDto.cs
│ │ │ │ ├── RefreshTokenDto.cs
│ │ │ │ ├── LoginRequestDto.cs
│ │ │ │ ├── UserDto.cs
│ │ │ │ ├── LoginResponseDto.cs
│ │ │ │ └── RegisterationRequestDto.cs
│ │ │ ├── BaseResponseDto.cs
│ │ │ ├── Notification
│ │ │ │ ├── CreateUserNotificationDto.cs
│ │ │ │ ├── CreatePostNotificationDto.cs
│ │ │ │ ├── CreateCommentNotificationDto.cs
│ │ │ │ ├── CreateNotificationDto.cs
│ │ │ │ └── NotificationDto.cs
│ │ │ ├── Post
│ │ │ │ ├── UpdatePostRequestDto.cs
│ │ │ │ ├── Comments
│ │ │ │ │ ├── CommentRequestDto.cs
│ │ │ │ │ └── CommentDto.cs
│ │ │ │ ├── PostUserSearchQueryDto.cs
│ │ │ │ ├── PostSearchQueryDto.cs
│ │ │ │ ├── CreatePost
│ │ │ │ │ ├── CreatePostRequestDto.cs
│ │ │ │ │ └── CreatePostMediaRequestDto.cs
│ │ │ │ ├── PostMediaDto.cs
│ │ │ │ └── PostDto.cs
│ │ │ ├── Message
│ │ │ │ ├── RequestSendMessageDto.cs
│ │ │ │ ├── RequestSearchMessageDto.cs
│ │ │ │ └── MessageDto.cs
│ │ │ └── Conversation
│ │ │ │ ├── ConversationDetailDto.cs
│ │ │ │ └── ConversationDto.cs
│ │ ├── PaginationFilter.cs
│ │ └── ApiResult.cs
│ ├── GlobalUsing.cs
│ ├── Mapping
│ │ ├── IMappingProfileMarker.cs
│ │ ├── MessageProfile.cs
│ │ ├── ConversationProfile.cs
│ │ ├── CommentProfile.cs
│ │ ├── PostProfile.cs
│ │ ├── NotificationProfile.cs
│ │ └── UserProfile.cs
│ ├── Validators
│ │ ├── IValidatorMarker.cs
│ │ ├── Message
│ │ │ ├── RequestMessageValidator.cs
│ │ │ └── RequestSearchMessageValidator.cs
│ │ ├── Post
│ │ │ ├── CreatePostMediaRequestValidator.cs
│ │ │ └── CreatePostRequestValidator.cs
│ │ └── User
│ │ │ ├── ProfileRequestValidator.cs
│ │ │ └── RegisterationRequestValidator.cs
│ ├── MachineLearning
│ │ ├── Models
│ │ │ ├── PostPredictionModel.cs
│ │ │ └── ResponseRecommendationModel.cs
│ │ └── Services
│ │ │ ├── Interface
│ │ │ └── ITrainingModelService.cs
│ │ │ └── TrainingModelService.cs
│ ├── Helpers
│ │ ├── IClaimService.cs
│ │ ├── ICloudinaryService.cs
│ │ └── ITokenService.cs
│ ├── Exceptions
│ │ ├── UnauthorizeException.cs
│ │ ├── ForbiddenException.cs
│ │ ├── ConflictException.cs
│ │ ├── InvalidModelException.cs
│ │ ├── ApplicationException.cs
│ │ └── NotFoundException.cs
│ ├── Services
│ │ ├── Caching
│ │ │ ├── ICachingService.cs
│ │ │ └── CacheEntryOptions.cs
│ │ └── Interface
│ │ │ ├── IUserService.cs
│ │ │ ├── IProfileService.cs
│ │ │ ├── IFollowService.cs
│ │ │ ├── INotificationService.cs
│ │ │ ├── IConversationService.cs
│ │ │ └── IPostService.cs
│ ├── SignalR
│ │ └── Interface
│ │ │ ├── IConversationNotificationService.cs
│ │ │ └── IUserNotificationService.cs
│ ├── Localization
│ │ ├── ErrorText.cs
│ │ └── ValidationText.cs
│ ├── ChitChat.Application.csproj
│ └── DependencyInjection.cs
├── ChitChat.Domain
│ ├── Enums
│ │ ├── CommentType.cs
│ │ ├── UserRoles.cs
│ │ ├── ConversationType.cs
│ │ ├── UserStatus.cs
│ │ ├── MediaType.cs
│ │ ├── Gender.cs
│ │ ├── NotificationType.cs
│ │ ├── NotificationActionEnum.cs
│ │ ├── MessageStatus.cs
│ │ └── InteractionType.cs
│ ├── Identity
│ │ ├── ApplicationRole.cs
│ │ └── UserApplication.cs
│ ├── Entities
│ │ ├── BaseEntity.cs
│ │ ├── SystemEntities
│ │ │ ├── Notification
│ │ │ │ ├── UserNotification.cs
│ │ │ │ ├── PostNotification.cs
│ │ │ │ ├── CommentNotification.cs
│ │ │ │ └── Notification.cs
│ │ │ └── UserInteraction.cs
│ │ ├── PostEntities
│ │ │ ├── PostDetailTag.cs
│ │ │ ├── Reaction
│ │ │ │ ├── ReactionPost.cs
│ │ │ │ └── ReactionComment.cs
│ │ │ ├── PostMedia.cs
│ │ │ ├── Post.cs
│ │ │ └── Comment.cs
│ │ ├── ChatEntities
│ │ │ ├── ConversationDetail.cs
│ │ │ ├── Message.cs
│ │ │ └── Conversation.cs
│ │ ├── LoginHistory.cs
│ │ ├── BaseAuditedEntity.cs
│ │ └── UserEntities
│ │ │ ├── Profile.cs
│ │ │ ├── UserFollower.cs
│ │ │ └── UserFollowerRequest.cs
│ ├── GlobalUsing.cs
│ ├── Common
│ │ ├── IAuditedEntity.cs
│ │ ├── LocalizationSettings.cs
│ │ ├── ErrorDescription.cs
│ │ ├── PaginationResponse.cs
│ │ ├── NotificationRefText.cs
│ │ ├── UnixTimestampConverter.cs
│ │ ├── LocalizedText.cs
│ │ └── NotificationFormatter.cs
│ ├── MachineLearningEntities
│ │ └── UserInteractionModelItem.cs
│ ├── Exceptions
│ │ └── ResourceNotFoundException.cs
│ └── ChitChat.Domain.csproj
├── ChitChat.WebAPI
│ ├── ChitChat.WebAPI.http
│ ├── .sample.env
│ ├── appsettings.json
│ ├── appsettings.Development.json
│ ├── Controllers
│ │ ├── TrainingModelController.cs
│ │ ├── NotificationController.cs
│ │ └── UserController.cs
│ ├── appsettings.Production.json
│ ├── ChitChat.WebAPI.csproj
│ ├── Dockerfile
│ ├── Properties
│ │ └── launchSettings.json
│ └── Program.cs
├── ChitChat.Infrastructure
│ ├── SignalR
│ │ ├── Helpers
│ │ │ ├── HubEnum.cs
│ │ │ ├── HubEndpoint.cs
│ │ │ └── HubRoom.cs
│ │ ├── Hubs
│ │ │ ├── InterfaceClient
│ │ │ │ ├── IConversationClient.cs
│ │ │ │ └── IUserClient.cs
│ │ │ ├── UserHub.cs
│ │ │ └── ConversationHub.cs
│ │ ├── Services
│ │ │ ├── ConversationNotificationService.cs
│ │ │ └── UserNotificationService.cs
│ │ └── SignalRRegistration.cs
│ ├── Authorization
│ │ ├── AuthorizationRequirementBase.cs
│ │ └── AuthorizationRegisteration.cs
│ ├── GlobalUsing.cs
│ ├── CloudinaryConfiguration
│ │ ├── CloudinarySetting.cs
│ │ └── CloudinaryRegisteration.cs
│ ├── ConfigSetting
│ │ └── JWTConfigSetting.cs
│ ├── Caching
│ │ ├── CachingRegistrations.cs
│ │ └── MemoryCacheService.cs
│ ├── Logging
│ │ ├── SerilogOptions.cs
│ │ └── SerilogRegistration.cs
│ ├── Validations
│ │ └── ValidateModelAttribute.cs
│ ├── Services
│ │ ├── ClaimService.cs
│ │ ├── CloudinaryService.cs
│ │ └── TokenService.cs
│ ├── EntityFrameworkCore
│ │ ├── EntityFrameworkRegisteration.cs
│ │ └── Interceptor
│ │ │ └── ContextSaveChangeInterceptor.cs
│ ├── ChitChat.Infrastructure.csproj
│ ├── DependencyInjection.cs
│ └── Middleware
│ │ └── GlobalExceptionHandlerMiddleware.cs
├── ChitChat.DataAccess
│ ├── DatabaseConfiguration.cs
│ ├── GlobalUsing.cs
│ ├── Repositories
│ │ ├── Interface
│ │ │ ├── IRepositoryFactory.cs
│ │ │ ├── IConversationRepository.cs
│ │ │ ├── IUserFollowerRepository.cs
│ │ │ ├── IUserInteractionRepository.cs
│ │ │ ├── IUserRepository.cs
│ │ │ └── IBaseRepository.cs
│ │ ├── RepositoryFactory.cs
│ │ ├── UserInteractionRepository.cs
│ │ ├── UserFollowerRepository.cs
│ │ ├── ConversationRepository.cs
│ │ └── UserRepository.cs
│ ├── Configurations
│ │ ├── LoginHistoryConfiguration.cs
│ │ ├── ProfileConfiguration.cs
│ │ ├── PostMediaConfiguration.cs
│ │ ├── ConversationDetailConfiguration.cs
│ │ ├── PostDetailTagConfiguration).cs
│ │ ├── Notification
│ │ │ ├── UserNotificationConfiguration.cs
│ │ │ ├── PostNotificationConfiguration.cs
│ │ │ └── CommentNotificationConfiguration.cs
│ │ ├── MessageConfiguration.cs
│ │ ├── ReactionPostConfiguration.cs
│ │ ├── UserInteractionConfiguration.cs
│ │ ├── ReactionCommentConfiguration.cs
│ │ ├── UserFollowerConfiguration.cs
│ │ ├── UserFollowerRequestConfiguration.cs
│ │ ├── CommentConfiguration.cs
│ │ ├── ConversationConfiguration.cs
│ │ └── PostConfiguration.cs
│ ├── Data
│ │ ├── AutomatedMigration.cs
│ │ ├── ApplicationDbContext.cs
│ │ └── DbContextSeed.cs
│ ├── ChitChat.DataAccess.csproj
│ ├── DependenceInjection.cs
│ └── Migrations
│ │ ├── 20241123154958_ChangeCommentStatus.cs
│ │ ├── 20241117121420_V1Update.cs
│ │ └── 20241221022222_UpdaeFollower.cs
└── src.sln
├── test
└── ChitChat.Test
│ ├── Class1.cs
│ └── ChitChat.Test.csproj
├── .idea
└── .idea.ChitChatSolution
│ └── .idea
│ └── projectSettingsUpdater.xml
├── docker
└── DockerCompose
│ ├── launchSettings.json
│ ├── docker-compose.override.yml
│ ├── .dockerignore
│ ├── docker-compose.prod.yml
│ ├── docker-compose.yml
│ └── DockerCompose.dcproj
├── LICENSE
├── .github
└── workflows
│ └── deploy-prod.yml
├── .editorconfig
├── README.md
└── ChitChatSolution.sln
/src/ChitChat.Application/Models/Dtos/User/UserProfileDto.cs:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/ChitChat.Test/Class1.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Test
2 | {
3 | public class Class1
4 | {
5 |
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/ChitChat.Domain/Enums/CommentType.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Domain.Enums
2 | {
3 | public enum CommentType
4 | {
5 | Parent,
6 | Reply
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/GlobalUsing.cs:
--------------------------------------------------------------------------------
1 | global using System;
2 | global using System.Collections.Generic;
3 | global using System.Linq;
4 | global using System.Threading.Tasks;
5 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/Mapping/IMappingProfileMarker.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Application.Mapping
2 | {
3 | public interface IMappingProfileMarker
4 | {
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/Validators/IValidatorMarker.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Application.Validators
2 |
3 | {
4 | public interface IValidatorMarker
5 | {
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/ChitChat.Domain/Enums/UserRoles.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Domain.Enums
2 | {
3 | public enum UserRoles
4 | {
5 | Admin = 0,
6 | User = 1,
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/src/ChitChat.Domain/Enums/ConversationType.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Domain.Enums
2 | {
3 | public enum ConversationType
4 | {
5 | Person,
6 | Group
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/src/ChitChat.Domain/Enums/UserStatus.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Domain.Enums
2 | {
3 | public enum UserStatus
4 | {
5 | Private = 0,
6 | Public = 1
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/src/ChitChat.Domain/Enums/MediaType.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Domain.Enums
2 | {
3 | public enum MediaType
4 | {
5 | Image,
6 | Video,
7 |
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/ChitChat.Domain/Enums/Gender.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Domain.Enums
2 | {
3 | public enum Gender
4 | {
5 | Male,
6 | Female,
7 | Others
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/ChitChat.WebAPI/ChitChat.WebAPI.http:
--------------------------------------------------------------------------------
1 | @ChitChat.WebAPI_HostAddress = http://localhost:5251
2 |
3 | GET {{ChitChat.WebAPI_HostAddress}}/weatherforecast/
4 | Accept: application/json
5 |
6 | ###
7 |
--------------------------------------------------------------------------------
/src/ChitChat.Infrastructure/SignalR/Helpers/HubEnum.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Infrastructure.SignalR.Helpers
2 | {
3 | public enum HubEnum
4 | {
5 | Conversation,
6 | User
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/src/ChitChat.WebAPI/.sample.env:
--------------------------------------------------------------------------------
1 | SecretKey =
2 | TokenValidityInDays =
3 | RefreshTokenValidityInDays =
4 | Issuer =
5 | Audience =
6 | CloudinaryCloudName =
7 | CloudinaryApiKey =
8 | CloudinaryApiSecret =
--------------------------------------------------------------------------------
/src/ChitChat.DataAccess/DatabaseConfiguration.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.DataAccess
2 | {
3 | public class DatabaseConfiguration
4 | {
5 | public string ConnectionString { get; set; }
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/ChitChat.Domain/Enums/NotificationType.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Domain.Enums
2 | {
3 | public enum NotificationType
4 | {
5 | Post,
6 | Comment,
7 | User
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/ChitChat.Domain/Identity/ApplicationRole.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Identity;
2 |
3 | namespace ChitChat.Domain.Identity
4 | {
5 | public class ApplicationRole : IdentityRole
6 | {
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/Models/Dtos/BaseResponseDto.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Application.Models.Dtos
2 | {
3 | public abstract class BaseResponseDto
4 | {
5 | public Guid Id { get; set; }
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/ChitChat.DataAccess/GlobalUsing.cs:
--------------------------------------------------------------------------------
1 | global using System;
2 | global using System.Collections.Generic;
3 | global using System.Linq;
4 | global using System.Threading.Tasks;
5 | global using Microsoft.EntityFrameworkCore;
6 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/Models/Dtos/Notification/CreateUserNotificationDto.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Application.Models.Dtos.Notification
2 | {
3 | public class CreateUserNotificationDto : CreateNotificationDto
4 | {
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/Models/Dtos/Post/UpdatePostRequestDto.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Application.Models.Dtos.Post
2 | {
3 | public class UpdatePostRequestDto
4 | {
5 | public string Description { get; set; }
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/Models/Dtos/Message/RequestSendMessageDto.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Application.Models.Dtos.Message
2 | {
3 | public class RequestSendMessageDto
4 | {
5 | public string MessageText { get; set; }
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/Models/Dtos/Post/Comments/CommentRequestDto.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Application.Models.Dtos.Post.Comments
2 | {
3 | public class CommentRequestDto
4 | {
5 | public string Content { get; set; }
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/Models/Dtos/Post/PostUserSearchQueryDto.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Application.Models.Dtos.Post
2 | {
3 | public class PostUserSearchQueryDto : PaginationFilter
4 | {
5 | public string? UserId { get; set; }
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/Models/Dtos/User/Follow/CreateFollowRequestDto.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Application.Models.Dtos.User.Follow
2 | {
3 | public class CreateFollowRequestDto
4 | {
5 | public string FollowerId { get; set; }
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/.idea/.idea.ChitChatSolution/.idea/projectSettingsUpdater.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/src/ChitChat.Domain/Entities/BaseEntity.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Domain.Entities
2 | {
3 | public abstract class BaseEntity
4 | {
5 | public Guid Id { get; set; }
6 |
7 | public bool IsDeleted { get; set; } = false;
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/Models/Dtos/Post/PostSearchQueryDto.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Application.Models.Dtos.Post
2 | {
3 | public class PostSearchQueryDto : PaginationFilter
4 | {
5 | public string SearchText { get; set; } = string.Empty;
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/Models/Dtos/User/Profile/ProfileSearchQueryDto.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Application.Models.Dtos.User.Profile
2 | {
3 | public class ProfileSearchQueryDto : PaginationFilter
4 | {
5 | public string SearchText { get; set; }
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/Models/Dtos/User/RefreshTokenDto.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Application.Models.Dtos.User
2 | {
3 | public class RefreshTokenDto
4 | {
5 | public string RefreshToken { get; set; }
6 | public string AccessToken { get; set; }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/docker/DockerCompose/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "profiles": {
3 | "DockerDevEnv": {
4 | "commandName": "DockerCompose",
5 | "commandVersion": "1.0",
6 | "serviceActions": {
7 | "chitchat.webapi": "StartDebugging"
8 | }
9 | }
10 | }
11 | }
--------------------------------------------------------------------------------
/test/ChitChat.Test/ChitChat.Test.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net8.0
5 | enable
6 | enable
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/Models/Dtos/User/Follow/FollowDto.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Application.Models.Dtos.User.Follow
2 | {
3 | public class FollowDto : BaseResponseDto
4 | {
5 | public string UserId { get; set; }
6 | public UserDto User { get; set; }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/src/ChitChat.Infrastructure/Authorization/AuthorizationRequirementBase.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Authorization;
2 |
3 | namespace ChitChat.Infrastructure.Authorization
4 | {
5 | public abstract class AuthorizationRequirementBase : IAuthorizationRequirement
6 | {
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/Models/Dtos/Message/RequestSearchMessageDto.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Application.Models.Dtos.Message
2 | {
3 | public class RequestSearchMessageDto
4 | {
5 | public string Text { get; set; }
6 | public Guid ConversationId { get; set; }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/Models/Dtos/User/LoginRequestDto.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Application.Models.Dtos.User
2 | {
3 |
4 | public class LoginRequestDto
5 | {
6 |
7 | public string UserName { get; set; }
8 | public string Password { get; set; }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/ChitChat.Domain/Enums/NotificationActionEnum.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Domain.Enums
2 | {
3 | public enum NotificationActionEnum
4 | {
5 | LIKE_POST,
6 | COMMENT_POST,
7 | REPLY_COMMENT,
8 | USER_FOLLOW,
9 | LIKE_COMMENT
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/ChitChat.Infrastructure/GlobalUsing.cs:
--------------------------------------------------------------------------------
1 | global using System;
2 | global using System.Collections.Generic;
3 | global using System.Linq;
4 | global using System.Text;
5 | global using System.Threading.Tasks;
6 | global using Microsoft.EntityFrameworkCore;
7 | global using ChitChat.Domain.Entities;
8 |
--------------------------------------------------------------------------------
/src/ChitChat.Domain/Enums/MessageStatus.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Domain.Enums
2 | {
3 | public static class MessageStatus
4 | {
5 | public static string NORMAL = "normal";
6 | public static string EDITED = "edited";
7 | public static string UNSENT = "unsent";
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/ChitChat.Domain/GlobalUsing.cs:
--------------------------------------------------------------------------------
1 | global using ChitChat.Domain.Entities;
2 | global using ChitChat.Domain.Entities.PostEntities;
3 | global using System;
4 | global using System.Collections.Generic;
5 | global using System.Linq;
6 | global using ChitChat.Domain.Enums;
7 | global using ChitChat.Domain.Identity;
8 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/Models/Dtos/User/UserDto.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Application.Models.Dtos.User
2 | {
3 | public class UserDto
4 | {
5 | public string Id { get; set; }
6 | public string DisplayName { get; set; }
7 | public string AvatarUrl { get; set; }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/MachineLearning/Models/PostPredictionModel.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.ML.Data;
2 |
3 | namespace ChitChat.Application.MachineLearning.Models
4 | {
5 | public class PostPredictionModel
6 | {
7 | [ColumnName("Score")]
8 | public float Score { get; set; }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/Models/Dtos/Notification/CreatePostNotificationDto.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Application.Models.Dtos.Notification
2 | {
3 | public class CreatePostNotificationDto : CreateNotificationDto
4 | {
5 | public Guid Id { get; set; } = Guid.Empty;
6 | public Guid PostId { get; set; }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/src/ChitChat.Infrastructure/SignalR/Helpers/HubEndpoint.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Infrastructure.SignalR.Helpers
2 | {
3 | public static class HubEndpoint
4 | {
5 | public static string ConversationHubEndpoint = "hubs/conversation";
6 | public static string UserHubEndpoint = "hubs/user";
7 |
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/ChitChat.DataAccess/Repositories/Interface/IRepositoryFactory.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Domain.Entities;
2 |
3 | namespace ChitChat.DataAccess.Repositories.Interface
4 | {
5 | public interface IRepositoryFactory
6 | {
7 | IBaseRepository GetRepository() where TEntity : BaseEntity;
8 | }
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/Helpers/IClaimService.cs:
--------------------------------------------------------------------------------
1 | using System.Security.Claims;
2 |
3 | namespace ChitChat.Application.Helpers
4 | {
5 | public interface IClaimService
6 | {
7 | string GetUserId();
8 | string GetUserName();
9 | string GetLoginHistoryId(ClaimsIdentity? claimsIdentity = null);
10 |
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/ChitChat.Domain/Entities/SystemEntities/Notification/UserNotification.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Domain.Entities.SystemEntities.Notification
2 | {
3 | public class UserNotification : Notification
4 | {
5 | public UserNotification()
6 | {
7 | Type = NotificationType.User.ToString();
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/ChitChat.Infrastructure/CloudinaryConfiguration/CloudinarySetting.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Infrastructure.CloudinaryConfigurations
2 | {
3 | public class CloudinarySetting
4 | {
5 | public string CloudName { get; set; }
6 | public string ApiKey { get; set; }
7 | public string ApiSecret { get; set; }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/Models/Dtos/Post/CreatePost/CreatePostRequestDto.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Http;
2 |
3 | namespace ChitChat.Application.Models.Dtos.Post.CreatePost
4 | {
5 | public class CreatePostRequestDto
6 | {
7 | public List Files { get; set; }
8 | public string Description { get; set; }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/Exceptions/UnauthorizeException.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Application.Exceptions
2 | {
3 | public class UnauthorizeException : ApplicationException
4 | {
5 | public UnauthorizeException(string message) : base(message)
6 | {
7 | Code = Models.ApiResultErrorCodes.Unauthorize;
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/MachineLearning/Models/ResponseRecommendationModel.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Application.Models.Dtos.Post;
2 |
3 | namespace ChitChat.Application.MachineLearning.Models
4 | {
5 | public class ResponseRecommendationModel
6 | {
7 | public float Score { get; set; }
8 | public PostDto? Post { get; set; }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/ChitChat.Domain/Common/IAuditedEntity.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Domain.Common
2 | {
3 | public interface IAuditedEntity
4 | {
5 | public string CreatedBy { get; set; }
6 |
7 | public DateTime CreatedOn { get; set; }
8 |
9 | public string? UpdatedBy { get; set; }
10 |
11 | public DateTime? UpdatedOn { get; set; }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/Models/Dtos/Post/CreatePost/CreatePostMediaRequestDto.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Application.Models.Dtos.Post.CreatePost
2 | {
3 | public class CreatePostMediaRequestDto
4 | {
5 | public string MediaType { get; set; }
6 | public string MediaUrl { get; set; }
7 | public string Description { get; set; }
8 |
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/Services/Caching/ICachingService.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Application.Services.Caching
2 | {
3 | public interface ICachingService
4 | {
5 | Task Set(string key, T value);
6 | Task Get(string key);
7 | Task GetOrSetAsync(string key, Func> func);
8 | Task Remove(string key);
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/Models/Dtos/User/LoginResponseDto.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Application.Models.Dtos.User
2 | {
3 | public class LoginResponseDto
4 | {
5 | public UserDto User { get; set; }
6 | public string AccessToken { get; set; }
7 | public string RefreshToken { get; set; }
8 | public Guid LoginHistoryId { get; set; }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/Models/Dtos/Post/PostMediaDto.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Application.Models.Dtos.Post
2 | {
3 | public class PostMediaDto : BaseResponseDto
4 | {
5 | public string MediaType { get; set; }
6 | public string MediaUrl { get; set; }
7 | public int MediaOrder { get; set; }
8 | public string Description { get; set; }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/Exceptions/ForbiddenException.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Application.Models;
2 |
3 | namespace ChitChat.Application.Exceptions
4 | {
5 | public class ForbiddenException : ApplicationException
6 | {
7 | public ForbiddenException(string message) : base(message)
8 | {
9 | Code = ApiResultErrorCodes.Forbidden;
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/Models/Dtos/Notification/CreateCommentNotificationDto.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Application.Models.Dtos.Notification
2 | {
3 | public class CreateCommentNotificationDto : CreateNotificationDto
4 | {
5 | public Guid Id { get; set; } = Guid.Empty;
6 | public Guid PostId { get; set; }
7 | public Guid CommentId { get; set; }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/ChitChat.Domain/Entities/PostEntities/PostDetailTag.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Domain.Entities.PostEntities
2 | {
3 | public class PostDetailTag : BaseEntity
4 | {
5 | public Guid PostId { get; set; }
6 | public string Tag { get; set; }
7 | public bool IsDeleted { get; set; }
8 | public Post Post { get; set; } // Navigation property
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/ChitChat.Domain/Common/LocalizationSettings.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Domain.Common
2 | {
3 | public struct LocalizationSettings
4 | {
5 | public static readonly string[] Cultures = new[] { "vi-VN", "en-US" };
6 |
7 | public static readonly string DefaultCulture = Cultures[0];
8 |
9 | public static readonly string CultureQueryString = "culture";
10 | }
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/src/ChitChat.Domain/Entities/ChatEntities/ConversationDetail.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Domain.Entities.ChatEntities
2 | {
3 | public class ConversationDetail : BaseEntity
4 | {
5 | public Guid ConversationId { get; set; }
6 | public string UserId { get; set; }
7 | public Conversation Conversation { get; set; }
8 | public UserApplication User { get; set; }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/ChitChat.Domain/Common/ErrorDescription.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Domain.Common
2 | {
3 | public class ErrorDescription
4 | {
5 |
6 | public static readonly string InvalidAccessOrRefreshToken = LocalizedText.New("Invalid access token or refresh token")
7 | .AddDefaultText("Mã truy cập không hợp lệ")
8 | .ToString();
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/ChitChat.Domain/Entities/ChatEntities/Message.cs:
--------------------------------------------------------------------------------
1 | public class Message : BaseAuditedEntity
2 | {
3 | public Guid ConversationId { get; set; }
4 | public string SenderId { get; set; }
5 | public string MessageText { get; set; }
6 | public string Status { get; set; }
7 | public Conversation Conversation { get; set; }
8 | // Navigation property
9 | public UserApplication Sender { get; set; }
10 | }
11 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/Mapping/MessageProfile.cs:
--------------------------------------------------------------------------------
1 | using AutoMapper;
2 |
3 | using ChitChat.Application.Models.Dtos.Message;
4 |
5 | namespace ChitChat.Application.Mapping
6 | {
7 | public class MessageProfile : Profile
8 | {
9 | public MessageProfile()
10 | {
11 | CreateMap();
12 | CreateMap();
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/SignalR/Interface/IConversationNotificationService.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Application.Models.Dtos.Message;
2 |
3 | namespace ChitChat.Application.SignalR.Interface
4 | {
5 | public interface IConversationNotificationService
6 | {
7 | Task SendMessage(MessageDto message);
8 | Task UpdateMessage(MessageDto message);
9 | Task DeleteMessage(MessageDto message);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/ChitChat.Domain/Entities/LoginHistory.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Domain.Entities
2 | {
3 | public class LoginHistory:BaseEntity
4 | {
5 | public string UserId { get; set; }
6 | public DateTime? LoginTime { get; set; }
7 | public DateTime? LogoutTime { get; set; }
8 | public string? RefreshToken { get; set; }
9 | public DateTime? RefreshTokenExpiryTime { get; set; }
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/Exceptions/ConflictException.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Application.Models;
2 |
3 | namespace ChitChat.Application.Exceptions;
4 | public class ConflictException : ApplicationException
5 | {
6 | public ConflictException(string message, bool transactionRollback = true) : base(message)
7 | {
8 | Code = ApiResultErrorCodes.Conflict;
9 | TransactionRollback = transactionRollback;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/Helpers/ICloudinaryService.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Application.Models.Dtos.Post;
2 |
3 | using Microsoft.AspNetCore.Http;
4 |
5 | namespace ChitChat.Application.Helpers
6 | {
7 | public interface ICloudinaryService
8 | {
9 | Task> PostMediaToCloudAsync(List files, Guid postId);
10 | Task DeleteMediaFromCloudAsync(Guid postId, Guid postMediaId);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/ChitChat.Domain/Entities/PostEntities/Reaction/ReactionPost.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Domain.Entities.PostEntities.Reaction
2 | {
3 | public class ReactionPost : BaseAuditedEntity
4 | {
5 | public Guid PostId { get; set; }
6 | public string UserId { get; set; }
7 | public Post Post { get; set; } // Navigation property
8 | public UserApplication User { get; set; } // Navigation property
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/Localization/ErrorText.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Domain.Common;
2 |
3 | namespace ChitChat.Application.Localization
4 | {
5 | public static class ErrorTexts
6 | {
7 | public static readonly string InvalidAccessOrRefreshToken = LocalizedText.New("Invalid access token or refresh token")
8 | .AddDefaultText("Mã truy cập không hợp lệ")
9 | .ToString();
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/ChitChat.Domain/Entities/BaseAuditedEntity.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Domain.Common;
2 |
3 | namespace ChitChat.Domain.Entities
4 | {
5 | public abstract class BaseAuditedEntity : BaseEntity, IAuditedEntity
6 | {
7 | public string CreatedBy { get; set; }
8 |
9 | public DateTime CreatedOn { get; set; }
10 |
11 | public string? UpdatedBy { get; set; }
12 |
13 | public DateTime? UpdatedOn { get; set; }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/ChitChat.Domain/Entities/PostEntities/Reaction/ReactionComment.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Domain.Entities.PostEntities.Reaction
2 | {
3 | public class ReactionComment : BaseAuditedEntity
4 | {
5 | public Guid CommentId { get; set; }
6 | public string UserId { get; set; }
7 | public Comment Comment { get; set; } // Navigation property
8 | public UserApplication User { get; set; } // Navigation property
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/ChitChat.Domain/Entities/SystemEntities/Notification/PostNotification.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Domain.Entities.SystemEntities.Notification
2 | {
3 | public class PostNotification : Notification
4 | {
5 | public Guid PostId { get; set; }
6 | public Post Post { get; set; } // Navigation property
7 | public PostNotification()
8 | {
9 | Type = NotificationType.Post.ToString();
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/docker/DockerCompose/docker-compose.override.yml:
--------------------------------------------------------------------------------
1 | version: '3.4'
2 |
3 | services:
4 | chitchat.webapi:
5 | environment:
6 | - ASPNETCORE_ENVIRONMENT=Development
7 | - ASPNETCORE_HTTP_PORTS=8080
8 | - ASPNETCORE_HTTPS_PORTS=8081
9 | ports:
10 | - "8080"
11 | - "8081"
12 | volumes:
13 | - ${APPDATA}/Microsoft/UserSecrets:/home/app/.microsoft/usersecrets:ro
14 | - ${APPDATA}/ASP.NET/Https:/home/app/.aspnet/https:ro
--------------------------------------------------------------------------------
/src/ChitChat.Application/Mapping/ConversationProfile.cs:
--------------------------------------------------------------------------------
1 | using AutoMapper;
2 |
3 | using ChitChat.Application.Models.Dtos.Conversation;
4 |
5 | namespace ChitChat.Application.Mapping
6 | {
7 | public class ConversationProfile : Profile
8 | {
9 | public ConversationProfile()
10 | {
11 | CreateMap();
12 | CreateMap();
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/Models/Dtos/Notification/CreateNotificationDto.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Application.Models.Dtos.Notification
2 | {
3 | public abstract class CreateNotificationDto
4 | {
5 | public string Type { get; set; }
6 | public string Action { get; set; }
7 | public string Reference { get; set; }
8 | public string LastInteractorUserId { get; set; }
9 | public string ReceiverUserId { get; set; }
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/ChitChat.Domain/MachineLearningEntities/UserInteractionModelItem.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Application.MachineLearning.Models
2 | {
3 | public class UserInteractionModelItem
4 | {
5 | public string UserId { get; set; }
6 | public string PostId { get; set; }
7 | public string PostDescription { get; set; } = string.Empty;
8 | public float ReactionCount { get; set; }
9 | public float TotalPoint { get; set; }
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/Exceptions/InvalidModelException.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Application.Models;
2 |
3 | namespace ChitChat.Application.Exceptions;
4 |
5 | [Serializable]
6 | public class InvalidModelException : ApplicationException
7 | {
8 | public InvalidModelException(string message, bool transactionRollback = true) : base(message)
9 | {
10 | Code = ApiResultErrorCodes.ModelValidation;
11 | TransactionRollback = transactionRollback;
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/Mapping/CommentProfile.cs:
--------------------------------------------------------------------------------
1 | using AutoMapper;
2 |
3 | using ChitChat.Application.Models.Dtos.Post.Comments;
4 | using ChitChat.Domain.Entities.PostEntities;
5 |
6 | namespace ChitChat.Application.Mapping
7 | {
8 | public class CommentProfile : Profile
9 | {
10 | public CommentProfile()
11 | {
12 | CreateMap();
13 | CreateMap();
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/ChitChat.DataAccess/Repositories/Interface/IConversationRepository.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.DataAccess.Repositories.Interface;
2 |
3 | namespace ChitChat.DataAccess.Repositories.Interface
4 | {
5 | public interface IConversationRepository : IBaseRepository
6 | {
7 | Task> GetConversationByUserIdAsync(string userId);
8 | Task IsConversationExisted(string userSenderId, string userReceiverId);
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/ChitChat.Domain/Entities/SystemEntities/Notification/CommentNotification.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Domain.Entities.SystemEntities.Notification
2 | {
3 | public class CommentNotification : Notification
4 | {
5 | public Guid CommentId { get; set; }
6 | public Comment Comment { get; set; } // Navigation property
7 | public CommentNotification()
8 | {
9 | Type = NotificationType.Comment.ToString();
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/Validators/Message/RequestMessageValidator.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Application.Models.Dtos.Message;
2 |
3 | using FluentValidation;
4 |
5 | namespace ChitChat.Application.Validators.Message
6 | {
7 | public class RequestMessageValidator : AbstractValidator
8 | {
9 | public RequestMessageValidator()
10 | {
11 | RuleFor(message => message.MessageText).NotEmpty().NotNull();
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/ChitChat.DataAccess/Repositories/Interface/IUserFollowerRepository.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.DataAccess.Repositories.Interface;
2 | using ChitChat.Domain.Entities.UserEntities;
3 | using ChitChat.Domain.Identity;
4 |
5 | namespace ChitChat.DataAccess.Repositories.Interface
6 | {
7 | public interface IUserFollowerRepository : IBaseRepository
8 | {
9 | Task> GetRecommendedUsersAsync(string currentUserId, int pageSize);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/Models/Dtos/User/RegisterationRequestDto.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Application.Models.Dtos.User
2 | {
3 | public class RegisterationRequestDto
4 | {
5 | public string Email { get; set; }
6 | public string Password { get; set; }
7 | public string PhoneNumber { get; set; }
8 | public string LastName { get; set; }
9 | public string FirstName { get; set; }
10 |
11 | public string Role { get; set; }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/ChitChat.Domain/Entities/PostEntities/PostMedia.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Domain.Entities.PostEntities
2 | {
3 | public class PostMedia : BaseEntity
4 | {
5 | public Guid PostId { get; set; }
6 | public string MediaType { get; set; }
7 | public string MediaUrl { get; set; }
8 | public int MediaOrder { get; set; }
9 | public string Description { get; set; }
10 | public Post Post { get; set; } // Navigation property
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/Models/Dtos/Message/MessageDto.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Application.Models.Dtos.Message
2 | {
3 | public class MessageDto : BaseResponseDto
4 | {
5 | public string MessageText { get; set; }
6 | public DateTime CreatedOn { get; set; }
7 | public DateTime UpdateOn { get; set; }
8 | public string SenderId { get; set; }
9 | public Guid ConversationId { get; set; }
10 | public string Status { get; set; }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/ChitChat.Domain/Entities/UserEntities/Profile.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Domain.Entities.UserEntities
2 | {
3 | public class Profile : BaseEntity
4 | {
5 | public string UserApplicationId { get; set; }
6 | public string? Bio { get; set; }
7 | public DateTime DateOfBirth { get; set; }
8 | public string? Gender { get; set; }
9 | public string SearchData { get; set; }
10 | public UserApplication UserApplication { get; set; }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/Models/Dtos/User/Profile/ProfileRequestDto.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Application.Models.Dtos.User.Profile
2 | {
3 | public class ProfileRequestDto
4 | {
5 | public string DisplayName { get; set; }
6 | public string AvatarUrl { get; set; }
7 | public string PhoneNumber { get; set; }
8 | public string? Bio { get; set; }
9 | public DateTime DateOfBirth { get; set; }
10 | public string? Gender { get; set; }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/MachineLearning/Services/Interface/ITrainingModelService.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Application.MachineLearning.Models;
2 | using ChitChat.Domain.Entities.PostEntities;
3 |
4 | namespace ChitChat.Application.MachineLearning.Services.Interface
5 | {
6 | public interface ITrainingModelService
7 | {
8 | List GetRecommendationPostModel(string userId, List userInteractions, List postReccomendation);
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/ChitChat.Domain/Entities/UserEntities/UserFollower.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Domain.Entities.UserEntities
2 | {
3 | public class UserFollower : BaseEntity
4 | {
5 | public string UserId { get; set; }
6 | public string FollowerId { get; set; }
7 | public DateTime FollowedDate { get; set; }
8 |
9 | public UserApplication User { get; set; } // Navigation property
10 | public UserApplication Follower { get; set; } // Navigation property
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/src/ChitChat.DataAccess/Repositories/Interface/IUserInteractionRepository.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Application.MachineLearning.Models;
2 | using ChitChat.DataAccess.Repositories.Interface;
3 | using ChitChat.Domain.Entities.SystemEntities;
4 |
5 | namespace ChitChat.DataAccess.Repositories.Interface
6 | {
7 | public interface IUserInteractionRepository : IBaseRepository
8 | {
9 | Task> GetUserInteractionModelForTraining(int PageSize);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/ChitChat.Infrastructure/SignalR/Helpers/HubRoom.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Infrastructure.SignalR.Helpers
2 | {
3 | public class HubRoom
4 | {
5 | public static string ConversationHubJoinRoom(Guid conversationId)
6 | {
7 | return $"{HubEnum.Conversation.ToString()}: ${conversationId}";
8 | }
9 | public static string UserHubJoinRoom(string userId)
10 | {
11 | return $"{HubEnum.User.ToString()}: ${userId}";
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/Models/Dtos/Conversation/ConversationDetailDto.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Application.Models.Dtos.Message;
2 | using ChitChat.Application.Models.Dtos.User;
3 |
4 | namespace ChitChat.Application.Models.Dtos.Conversation
5 | {
6 | public class ConversationDetailDto : BaseResponseDto
7 | {
8 | public List UserReceivers { get; set; }
9 | public List UserReceiverIds { get; set; }
10 | public List Messages { get; set; }
11 |
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/Exceptions/ApplicationException.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Application.Models;
2 |
3 | namespace ChitChat.Application.Exceptions
4 | {
5 | [Serializable]
6 | public abstract class ApplicationException : Exception
7 | {
8 | public ApiResultErrorCodes Code { get; protected set; }
9 |
10 | public bool TransactionRollback { get; protected set; } = true;
11 |
12 | public ApplicationException(string message) : base(message)
13 | {
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/Services/Caching/CacheEntryOptions.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Application.Services.Caching
2 | {
3 | public class CacheEntryOptions
4 | {
5 | public TimeSpan SlidingExpiration { get; set; }
6 | public TimeSpan AbsoluteExpirationRelativeToNow { get; set; }
7 |
8 | public static CacheEntryOptions Default = new()
9 | {
10 | AbsoluteExpirationRelativeToNow = TimeSpan.FromDays(1),
11 | SlidingExpiration = TimeSpan.FromHours(1)
12 | };
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/Services/Interface/IUserService.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Application.Models.Dtos.User;
2 |
3 | namespace ChitChat.Application.Services.Interface
4 | {
5 | public interface IUserService
6 | {
7 | Task RegisterAsync(RegisterationRequestDto registerationRequestDto);
8 | Task LoginAsync(LoginRequestDto loginRequestDto);
9 | Task RefreshTokenAsync(RefreshTokenDto refreshTokenDto);
10 | Task LogoutAsync(Guid loginHistoryId);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/Helpers/ITokenService.cs:
--------------------------------------------------------------------------------
1 | using System.Security.Claims;
2 |
3 | using ChitChat.Domain.Entities;
4 | using ChitChat.Domain.Identity;
5 |
6 | namespace ChitChat.Application.Helpers
7 | {
8 | public interface ITokenService
9 | {
10 | (string token, int validDays) GenerateRefreshToken();
11 |
12 | Task GetPrincipalFromExpiredToken(string? token);
13 |
14 | string GenerateAccessToken(UserApplication user, IEnumerable roles, LoginHistory loginHistory);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/Validators/Message/RequestSearchMessageValidator.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Application.Models.Dtos.Message;
2 | using FluentValidation;
3 |
4 | namespace ChitChat.Application.Validators.Message
5 | {
6 | public class RequestSearchMessageValidator : AbstractValidator
7 | {
8 | public RequestSearchMessageValidator()
9 | {
10 | RuleFor(p => p.Text).NotNull().NotEmpty();
11 | RuleFor(p => p.ConversationId).NotNull().NotEmpty();
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/docker/DockerCompose/.dockerignore:
--------------------------------------------------------------------------------
1 | **/.classpath
2 | **/.dockerignore
3 | **/.env
4 | **/.git
5 | **/.gitignore
6 | **/.project
7 | **/.settings
8 | **/.toolstarget
9 | **/.vs
10 | **/.vscode
11 | **/*.*proj.user
12 | **/*.dbmdl
13 | **/*.jfm
14 | **/azds.yaml
15 | **/bin
16 | **/charts
17 | **/docker-compose*
18 | **/Dockerfile*
19 | **/node_modules
20 | **/npm-debug.log
21 | **/obj
22 | **/secrets.dev.yaml
23 | **/values.dev.yaml
24 | LICENSE
25 | README.md
26 | !**/.gitignore
27 | !.git/HEAD
28 | !.git/config
29 | !.git/packed-refs
30 | !.git/refs/heads/**
--------------------------------------------------------------------------------
/src/ChitChat.Application/Models/Dtos/Conversation/ConversationDto.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Application.Models.Dtos.Message;
2 | using ChitChat.Application.Models.Dtos.User;
3 |
4 | namespace ChitChat.Application.Models.Dtos.Conversation
5 | {
6 | public class ConversationDto : BaseResponseDto
7 | {
8 | public List UserReceivers { get; set; }
9 | public MessageDto? LastMessage { get; set; }
10 | public List UserReceiverIds { get; set; }
11 | public bool IsSeen { get; set; } = false;
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/ChitChat.DataAccess/Configurations/LoginHistoryConfiguration.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Domain.Entities;
2 |
3 | using Microsoft.EntityFrameworkCore.Metadata.Builders;
4 |
5 | namespace ChitChat.DataAccess.Configurations
6 | {
7 | public class LoginHistoryConfiguration : IEntityTypeConfiguration
8 | {
9 | public void Configure(EntityTypeBuilder modelBuilder)
10 | {
11 | // Conversation Detail
12 | modelBuilder
13 | .HasKey(c => c.Id);
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/ChitChat.Domain/Entities/SystemEntities/UserInteraction.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Domain.Entities.SystemEntities
2 | {
3 | public class UserInteraction : BaseEntity
4 | {
5 | public string UserId { get; set; }
6 | public Guid PostId { get; set; }
7 | public InteractionType InteractionType { get; set; }
8 | public DateTime InteractionDate { get; set; }
9 |
10 | public UserApplication User { get; set; } // Navigation property
11 | public Post Post { get; set; } // Navigation property
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/Services/Interface/IProfileService.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Application.Models.Dtos.User.Profile;
2 |
3 | namespace ChitChat.Application.Services.Interface
4 | {
5 | public interface IProfileService
6 | {
7 | Task> GetAllProfilesAsync(ProfileSearchQueryDto query);
8 | Task GetProfileByIdAsync(Guid userId);
9 | Task CreateProfileAsync(ProfileRequestDto request);
10 | Task UpdateProfileAsync(Guid userId, ProfileRequestDto request);
11 |
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/ChitChat.Domain/Common/PaginationResponse.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Domain.Common
2 | {
3 | public class PaginationResponse
4 | {
5 | public PaginationResponse()
6 | {
7 | Items = new List();
8 | }
9 |
10 | public int TotalCount { get; set; }
11 |
12 | public IEnumerable Items { get; set; }
13 |
14 | public int PageIndex { get; set; }
15 |
16 | public int PageSize { get; set; }
17 |
18 | public virtual List SortableFields { get; set; } = new();
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/Services/Interface/IFollowService.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Application.Models;
2 | using ChitChat.Application.Models.Dtos.User.Follow;
3 |
4 | namespace ChitChat.Application.Services.Interface
5 | {
6 | public interface IFollowService
7 | {
8 | Task ToggleFollowAsync(string otherUserId);
9 | Task> GetAllFollowingsAsync(string userId);
10 | Task> GetAllFollowerAsync(string userId);
11 | Task> GetRecommendFollowAsync(PaginationFilter filter);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/ChitChat.Domain/Common/NotificationRefText.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Domain.Common
2 | {
3 | public static class NotificationRefText
4 | {
5 | public static string PostRef(Guid postId)
6 | {
7 | return $"Post/{postId}";
8 | }
9 | public static string UserRef(string userId)
10 | {
11 | return $"User/{userId}";
12 | }
13 | public static string CommentRef(Guid postId, Guid commentId)
14 | {
15 | return $"Post/{postId}/Comment/{commentId}";
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/ChitChat.Infrastructure/ConfigSetting/JWTConfigSetting.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Infrastructure.ConfigSetting
2 | {
3 | public class JWTConfigSetting
4 | {
5 | public string SecretKey { get; set; } = string.Empty;
6 | public int TokenValidityInDays { get; set; } = 0;
7 | public int RefreshTokenValidityInDays { get; set; } = 0;
8 | public string Issuer { get; set; } = string.Empty;
9 | public string Audience { get; set; } = string.Empty;
10 | public static readonly string LoginHistoryIdClaimType = "LoginId";
11 |
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/ChitChat.Domain/Entities/UserEntities/UserFollowerRequest.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Domain.Entities.UserEntities
2 | {
3 | public class UserFollowerRequest:BaseEntity
4 | {
5 | public string UserId { get; set; }
6 | public string FollowerId { get; set; }
7 | public DateTime RequestDate { get; set; }
8 | public string Status { get; set; }
9 | public bool IsDeleted { get; set; }
10 |
11 | public UserApplication User { get; set; } // Navigation property
12 | public UserApplication Follower { get; set; } // Navigation property
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/ChitChat.Domain/Identity/UserApplication.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel.DataAnnotations;
2 |
3 | using Microsoft.AspNetCore.Identity;
4 |
5 | namespace ChitChat.Domain.Identity
6 | {
7 | public class UserApplication : IdentityUser
8 | {
9 | public DateTime LastLogin { get; set; }
10 | [MaxLength(255)]
11 | public string DisplayName { get; set; }
12 | [MaxLength(255)]
13 | public string? AvatarUrl { get; set; }
14 | public string? MediaAvatarType { get; set; }
15 | public UserStatus UserStatus { get; set; }
16 |
17 |
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/Models/PaginationFilter.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Application.Models
2 | {
3 | public class PaginationFilter
4 | {
5 | public int PageIndex { get; set; }
6 | public int PageSize { get; set; }
7 | public PaginationFilter()
8 | {
9 | this.PageIndex = 0;
10 | this.PageSize = 10;
11 | }
12 | public PaginationFilter(int pageIndex, int pageSize)
13 | {
14 | this.PageIndex = pageIndex < 0 ? 0 : pageIndex;
15 | this.PageSize = pageSize > 100 ? 100 : pageSize;
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/Models/Dtos/User/Profile/ProfileDto.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Application.Models.Dtos.User.Profile
2 | {
3 | public class ProfileDto
4 | {
5 | public Guid Id { get; set; }
6 | public string DisplayName { get; set; }
7 | public string AvatarUrl { get; set; }
8 | public string Email { get; set; }
9 | public string PhoneNumber { get; set; }
10 | public string? Bio { get; set; }
11 | public DateTime DateOfBirth { get; set; }
12 | public string? Gender { get; set; }
13 | public bool IsFollowed { get; set; }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/ChitChat.Infrastructure/Caching/CachingRegistrations.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Application.Services.Caching;
2 |
3 | using Microsoft.AspNetCore.Builder;
4 | using Microsoft.Extensions.DependencyInjection;
5 |
6 | namespace ChitChat.Infrastructure.Caching
7 | {
8 | public static class CachingRegistrations
9 | {
10 | public static WebApplicationBuilder AddCaching(this WebApplicationBuilder builder)
11 | {
12 | builder.Services
13 | .AddMemoryCache()
14 | .AddSingleton();
15 | return builder;
16 | }
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/src/ChitChat.Domain/Entities/ChatEntities/Conversation.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Domain.Entities.ChatEntities;
2 |
3 | public class Conversation : BaseAuditedEntity
4 | {
5 | public Guid? LastMessageId { get; set; }
6 | //public string userId1 { get; set; }
7 | //public string userId2 { get; set; }
8 |
9 | public Message? LastMessage { get; set; }
10 | public bool IsSeen { get; set; }
11 | public int NumOfUser { get; set; }
12 | public string ConversationType { get; set; }
13 |
14 | public IEnumerable Messages { get; set; }
15 | public IEnumerable ConversationDetails { get; set; }
16 | }
17 |
--------------------------------------------------------------------------------
/src/ChitChat.Domain/Entities/SystemEntities/Notification/Notification.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Domain.Entities.SystemEntities.Notification
2 | {
3 | public abstract class Notification : BaseAuditedEntity
4 | {
5 | public string Type { get; set; }
6 | public string Action { get; set; }
7 | public string Reference { get; set; }
8 | public string LastInteractorUserId { get; set; }
9 | public string ReceiverUserId { get; set; }
10 | public UserApplication LastInteractorUser { get; set; } // Navigation property
11 | public UserApplication ReceiverUser { get; set; } // Navigation property
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/ChitChat.DataAccess/Configurations/ProfileConfiguration.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Domain.Entities.UserEntities;
2 |
3 | using Microsoft.EntityFrameworkCore.Metadata.Builders;
4 |
5 | namespace ChitChat.DataAccess.Configurations
6 | {
7 | public class ProfileConfiguration : IEntityTypeConfiguration
8 | {
9 | public ProfileConfiguration() { }
10 |
11 | public void Configure(EntityTypeBuilder builder)
12 | {
13 | builder
14 | .HasOne(p => p.UserApplication)
15 | .WithOne()
16 | .HasForeignKey(p => p.UserApplicationId);
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/Models/Dtos/Post/Comments/CommentDto.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Application.Models.Dtos.User;
2 |
3 | namespace ChitChat.Application.Models.Dtos.Post.Comments
4 | {
5 | public class CommentDto : BaseResponseDto
6 | {
7 | public Guid PostId { get; set; }
8 | public string UserPostedId { get; set; }
9 | public string Content { get; set; }
10 | public List ReplyComments { get; set; }
11 | public UserDto UserPosted { get; set; }
12 | public bool IsReacted { get; set; }
13 | public int ReactionCount { get; set; }
14 | public DateTime CreatedOn { get; set; }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/docker/DockerCompose/docker-compose.prod.yml:
--------------------------------------------------------------------------------
1 | services:
2 | chitchat.webapi:
3 | image: ${DOCKER_REGISTRY-}chitchatwebapi
4 | build:
5 | context: ../../
6 | dockerfile: src/ChitChat.WebAPI/Dockerfile
7 | ports:
8 | - "80:8080"
9 | - "443:8081"
10 | environment:
11 | - ASPNETCORE_ENVIRONMENT=Production
12 | - ASPNETCORE_Kestrel__Certificates__Default__Path=/app/chitchat.pfx
13 | - ASPNETCORE_Kestrel__Certificates__Default__Password=chitchat
14 | env_file:
15 | - ../../src/ChitChat.WebAPI/.env
16 | networks:
17 | - productnetwork
18 | restart: unless-stopped
19 |
20 | networks:
21 | productnetwork:
22 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/Validators/Post/CreatePostMediaRequestValidator.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Application.Models.Dtos.Post.CreatePost;
2 | using ChitChat.Domain.Enums;
3 |
4 | using FluentValidation;
5 |
6 | namespace ChitChat.Application.Validators.Post
7 | {
8 | public class CreatePostMediaRequestValidator : AbstractValidator
9 | {
10 | public CreatePostMediaRequestValidator()
11 | {
12 | RuleFor(p => p.MediaType)
13 | .Must(value => Enum.TryParse(typeof(MediaType), value?.ToString(), out _))
14 | .WithMessage("Media type must be a valid enum value");
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/ChitChat.Domain/Entities/PostEntities/Post.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Domain.Entities.PostEntities
2 | {
3 | public class Post : BaseAuditedEntity
4 | {
5 | public string UserId { get; set; }
6 | public string Description { get; set; }
7 | public int CommentCount { get; set; } = 0;
8 | public int ReactionCount { get; set; } = 0;
9 | public UserApplication User { get; set; } // Navigation property
10 | public ICollection Comments { get; set; }
11 | public ICollection PostDetailTags { get; set; }
12 | public ICollection PostMedias { get; set; }
13 |
14 |
15 | }
16 | }
17 |
18 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/SignalR/Interface/IUserNotificationService.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Application.Models.Dtos.Conversation;
2 | using ChitChat.Application.Models.Dtos.Notification;
3 |
4 | namespace ChitChat.Application.SignalR.Interface
5 | {
6 | public interface IUserNotificationService
7 | {
8 | Task UpdateConversation(ConversationDto conversation, string userSenderId);
9 | Task AddConversation(ConversationDto conversation, string userSenderId);
10 | Task DeleteConversation(ConversationDto conversation, string userSenderId);
11 | Task NewNotification(NotificationDto notificationDto);
12 | Task UpdateNotification(NotificationDto notificationDto);
13 |
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/ChitChat.Domain/Common/UnixTimestampConverter.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json;
2 | using System.Text.Json.Serialization;
3 |
4 | namespace ChitChat.Domain.Common
5 | {
6 | public class UnixTimestampConverter : JsonConverter
7 | {
8 | public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
9 | {
10 | return DateTimeOffset.FromUnixTimeSeconds(reader.GetInt64()).UtcDateTime;
11 | }
12 |
13 | public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
14 | {
15 | writer.WriteNumberValue(new DateTimeOffset(value).ToUnixTimeSeconds());
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/ChitChat.DataAccess/Configurations/PostMediaConfiguration.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Domain.Entities.PostEntities;
2 | using Microsoft.EntityFrameworkCore.Metadata.Builders;
3 |
4 | namespace ChitChat.DataAccess.Configurations
5 | {
6 | public class PostMediaConfiguration : IEntityTypeConfiguration
7 | {
8 | public void Configure(EntityTypeBuilder modelBuilder)
9 | {
10 | // PostMedia
11 | modelBuilder.HasKey(pm => pm.Id);
12 |
13 | modelBuilder
14 | .HasOne(pm => pm.Post)
15 | .WithMany(p => p.PostMedias)
16 | .HasForeignKey(pm => pm.PostId)
17 | .OnDelete(DeleteBehavior.Cascade);
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/ChitChat.Domain/Entities/PostEntities/Comment.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Domain.Entities.PostEntities
2 | {
3 | public class Comment : BaseAuditedEntity
4 | {
5 | public Guid PostId { get; set; }
6 | public Guid? ParentCommentId { get; set; }
7 | public string UserPostedId { get; set; }
8 | public string Content { get; set; }
9 | public int ReactionCount { get; set; } = 0;
10 | public string CommentType { get; set; }
11 | public Post Post { get; set; } // Navigation property
12 | public Comment ParentComment { get; set; } // Navigation property
13 | public List ReplyComments { get; set; }
14 | public UserApplication UserPosted { get; set; }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/ChitChat.DataAccess/Repositories/RepositoryFactory.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.DataAccess.Repositories.Interface;
2 | using ChitChat.Domain.Entities;
3 |
4 | using Microsoft.Extensions.DependencyInjection;
5 |
6 | namespace ChitChat.DataAccess.Repositories
7 | {
8 | public class RepositoryFactory : IRepositoryFactory
9 | {
10 | private readonly IServiceProvider _serviceProvider;
11 |
12 | public RepositoryFactory(IServiceProvider serviceProvider)
13 | {
14 | this._serviceProvider = serviceProvider;
15 | }
16 |
17 | public IBaseRepository GetRepository() where TEntity : BaseEntity
18 | => this._serviceProvider.GetRequiredService>();
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/ChitChat.Infrastructure/SignalR/Hubs/InterfaceClient/IConversationClient.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Application.Models.Dtos.Message;
2 |
3 | namespace ChitChat.Infrastructure.SignalR.Hubs.InterfaceClient
4 | {
5 | public interface IConversationClient
6 | {
7 | Task ConversationJoined(string message);
8 | Task NewMessage(MessageDto message);
9 | Task UpdateMessage(MessageDto message);
10 | Task DeleteMessage(MessageDto message);
11 |
12 | // Calling
13 | Task ReceiveOffer(string connectionId, string sdp);
14 | Task ReceiveAnswer(string connectionId, string sdp);
15 | Task ReceiveIceCandidate(string connectionId, string candidate);
16 | Task ReceiveCall(Guid ConversationId);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/ChitChat.Infrastructure/SignalR/Hubs/InterfaceClient/IUserClient.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Application.Models.Dtos.Conversation;
2 | using ChitChat.Application.Models.Dtos.Notification;
3 |
4 | namespace ChitChat.Infrastructure.SignalR.Hubs.InterfaceClient
5 | {
6 | public interface IUserClient
7 | {
8 | Task UpdateConversation(ConversationDto conversation);
9 | Task AddConversation(ConversationDto conversation);
10 | Task DeleteConversation(ConversationDto conversation);
11 | // Other events
12 | Task NotifyNewFollower(string followerId, string followedUserId);
13 | Task AddNotification(NotificationDto notification);
14 | Task UpdateNotification(NotificationDto notification);
15 |
16 |
17 |
18 |
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/ChitChat.WebAPI/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft.AspNetCore": "Warning"
6 | }
7 | },
8 | "AllowedHosts": "*",
9 | "JWTConfigSetting": {
10 | "SecretKey": "55eaf009a21fa3c5fce7096ca201f24734df43de88484d7a017a8eb389343146df02cf096f0b",
11 | "TokenValidityInDays": 5,
12 | "RefreshTokenValidityInDays": 30,
13 | "Issuer": "Issuer",
14 | "Audience": "Audience"
15 | },
16 | "Database": {
17 | "ConnectionStrings": {
18 | "LocalConnection": "Server=mysql;Database=chitchatdb;User=root;Password=Password12345!;",
19 | "AWSConnection": "Server=mysql-chit-chat.crska2kww12j.ap-southeast-1.rds.amazonaws.com;Port=3306;Database=ChitChatDB;User=admin;Password=123admin;"
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/Validators/Post/CreatePostRequestValidator.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Application.Models.Dtos.Post.CreatePost;
2 |
3 | using FluentValidation;
4 |
5 | namespace ChitChat.Application.Validators.Post
6 | {
7 | public class CreatePostRequestValidator : AbstractValidator
8 | {
9 | public CreatePostRequestValidator()
10 | {
11 | RuleFor(x => x.Description)
12 | .NotEmpty()
13 | .WithMessage("Description is required")
14 | .MaximumLength(500)
15 | .WithMessage("Description must not exceed 100 characters");
16 | RuleFor(x => x.Files)
17 | .NotEmpty()
18 | .WithMessage("File is required");
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/ChitChat.DataAccess/Configurations/ConversationDetailConfiguration.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Domain.Entities.ChatEntities;
2 |
3 | using Microsoft.EntityFrameworkCore.Metadata.Builders;
4 |
5 | namespace ChitChat.DataAccess.Configurations
6 | {
7 | public class ConversationDetailConfiguration : IEntityTypeConfiguration
8 | {
9 | public void Configure(EntityTypeBuilder modelBuilder)
10 | {
11 | // Conversation Detail
12 | modelBuilder
13 | .HasKey(c => c.Id);
14 |
15 | modelBuilder
16 | .HasOne(m => m.Conversation)
17 | .WithMany(c => c.ConversationDetails)
18 | .HasForeignKey(m => m.ConversationId)
19 | ;
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/Models/Dtos/Post/PostDto.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Application.Models.Dtos.Post.Comments;
2 | using ChitChat.Application.Models.Dtos.User;
3 |
4 | namespace ChitChat.Application.Models.Dtos.Post
5 | {
6 |
7 | public class PostDto : BaseResponseDto
8 | {
9 | public string Description { get; set; } = "";
10 | public int ReactionCount { get; set; }
11 | public int CommentCount { get; set; }
12 | public ICollection Comments { get; set; }
13 | public ICollection PostMedias { get; set; }
14 | public DateTime CreatedOn { get; set; }
15 | public DateTime UpdatedOn { get; set; }
16 | public bool IsReacted { get; set; }
17 | public UserDto UserPosted
18 | { get; set; }
19 | }
20 | }
21 |
22 |
--------------------------------------------------------------------------------
/src/ChitChat.WebAPI/appsettings.Development.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft.AspNetCore": "Warning"
6 | }
7 | },
8 | "AllowedHosts": "*",
9 | "JWTConfigSetting": {
10 | "SecretKey": "55eaf009a21fa3c5fce7096ca201f24734df43de88484d7a017a8eb389343146df02cf096f0b",
11 | "TokenValidityInDays": 5,
12 | "RefreshTokenValidityInDays": 30,
13 | "Issuer": "Issuer",
14 | "Audience": "Audience"
15 | },
16 | "Database": {
17 | "ConnectionStrings": {
18 | "LocalConnection": "Server=mysql;Database=chitchatdb;User=root;Password=Password12345!;",
19 | "AWSConnection": "Server=mysql-chit-chat.crska2kww12j.ap-southeast-1.rds.amazonaws.com;Port=3306;Database=ChitChatDBDev;User=admin;Password=123admin;"
20 | }
21 | }
22 | }
--------------------------------------------------------------------------------
/src/ChitChat.DataAccess/Configurations/PostDetailTagConfiguration).cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Domain.Entities.PostEntities;
2 |
3 | using Microsoft.EntityFrameworkCore;
4 | using Microsoft.EntityFrameworkCore.Metadata.Builders;
5 |
6 | namespace ChitChat.DataAccess.Configurations
7 | {
8 | public class PostDetailTagConfiguration : IEntityTypeConfiguration
9 | {
10 | public void Configure(EntityTypeBuilder modelBuilder)
11 | {
12 | // PostDetailTag
13 | modelBuilder.HasKey(pdt => pdt.Id);
14 |
15 | modelBuilder
16 | .HasOne(pdt => pdt.Post)
17 | .WithMany(p => p.PostDetailTags)
18 | .HasForeignKey(pdt => pdt.PostId)
19 | .OnDelete(DeleteBehavior.Cascade);
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/ChitChat.DataAccess/Configurations/Notification/UserNotificationConfiguration.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Domain.Entities.SystemEntities.Notification;
2 |
3 | using Microsoft.EntityFrameworkCore.Metadata.Builders;
4 |
5 | namespace ChitChat.DataAccess.Configurations.Notification
6 | {
7 | public class UserNotificationConfiguration : IEntityTypeConfiguration
8 | {
9 | public void Configure(EntityTypeBuilder builder)
10 | {
11 | builder.HasKey(n => n.Id);
12 | builder.HasOne(n => n.ReceiverUser)
13 | .WithMany()
14 | .HasForeignKey(n => n.ReceiverUserId);
15 | builder.HasOne(n => n.LastInteractorUser)
16 | .WithMany()
17 | .HasForeignKey(n => n.LastInteractorUserId);
18 |
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/docker/DockerCompose/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: "3.4"
2 |
3 | services:
4 | chitchat.webapi:
5 | image: ${DOCKER_REGISTRY-}chitchatwebapi
6 | build:
7 | context: ../../
8 | dockerfile: src/ChitChat.WebAPI/Dockerfile
9 | ports:
10 | - "8080:8080"
11 | - "8081:8081"
12 | depends_on:
13 | - mysql
14 | environment:
15 | - ASPNETCORE_ENVIRONMENT=Development
16 | networks:
17 | - productnetwork
18 | restart: on-failure
19 |
20 | mysql:
21 | image: mysql:8.0.39
22 | environment:
23 | MYSQL_ROOT_PASSWORD: "Password12345!"
24 | MYSQL_DATABASE: chitchatdb
25 | ports:
26 | - "3306:3306"
27 | volumes:
28 | - mysqlvolumn:/var/lib/mysql
29 | networks:
30 | - productnetwork
31 |
32 | networks:
33 | productnetwork:
34 |
35 | volumes:
36 | mysqlvolumn:
37 |
--------------------------------------------------------------------------------
/src/ChitChat.Domain/Exceptions/ResourceNotFoundException.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Runtime.Serialization;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace ChitChat.Domain.Exceptions
9 | {
10 | [Serializable]
11 | public class ResourceNotFoundException : Exception
12 | {
13 | public ResourceNotFoundException() { }
14 |
15 | public ResourceNotFoundException(Type type) : base($"{type} is missing") { }
16 |
17 | protected ResourceNotFoundException(SerializationInfo info, StreamingContext context) : base(info, context) { }
18 |
19 | public ResourceNotFoundException(string? message) : base(message) { }
20 |
21 | public ResourceNotFoundException(string? message, Exception? innerException) : base(message, innerException) { }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/ChitChat.Domain/ChitChat.Domain.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net8.0
5 | ChitChat.Domain
6 | enable
7 | enable
8 |
9 |
10 |
11 |
12 |
13 |
14 | all
15 | runtime; build; native; contentfiles; analyzers; buildtransitive
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/src/ChitChat.DataAccess/Configurations/MessageConfiguration.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.EntityFrameworkCore.Metadata.Builders;
2 |
3 | namespace ChitChat.DataAccess.Configurations
4 | {
5 | public class MessageConfiguration : IEntityTypeConfiguration
6 | {
7 | public void Configure(EntityTypeBuilder modelBuilder)
8 | {
9 | // Configure primary key
10 | modelBuilder.HasKey(m => m.Id);
11 |
12 | // Configure relationship with Conversation
13 | modelBuilder
14 | .HasOne(m => m.Conversation)
15 | .WithMany(c => c.Messages)
16 | .HasForeignKey(m => m.ConversationId);
17 |
18 | // Configure relationship with Sender
19 | modelBuilder
20 | .HasOne(m => m.Sender)
21 | .WithMany()
22 | .HasForeignKey(m => m.SenderId);
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/Services/Interface/INotificationService.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Application.Models;
2 | using ChitChat.Application.Models.Dtos.Notification;
3 |
4 | namespace ChitChat.Application.Services.Interface
5 | {
6 | public interface INotificationService
7 | {
8 | Task> GetAllNotificationsAsync(PaginationFilter filter);
9 | /* Task CreateOrUpdateNotificationAsync(NotificationDto notificationDto, List notificationUser);
10 | Task CreateNotificationAsync(NotificationDto notificationDto, List notificationUser);*/
11 | Task CreateOrUpdatePostNotificationAsync(CreatePostNotificationDto createPostNotificationDto);
12 | Task CreateOrUpdateUserNotificationAsync(CreateUserNotificationDto createUserNotification);
13 | Task CreateOrUpdateCommentNotificationAsync(CreateCommentNotificationDto createUserNotification);
14 |
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/ChitChat.Infrastructure/SignalR/Hubs/UserHub.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Infrastructure.SignalR.Helpers;
2 | using ChitChat.Infrastructure.SignalR.Hubs.InterfaceClient;
3 |
4 | using Microsoft.AspNetCore.SignalR;
5 | using Microsoft.Extensions.Logging;
6 |
7 | namespace ChitChat.Infrastructure.SignalR.Hubs
8 | {
9 | public class UserHub : Hub
10 | {
11 | ILogger _logger;
12 | public UserHub(ILogger logger)
13 | {
14 | _logger = logger;
15 | }
16 | public override Task OnConnectedAsync()
17 | {
18 | _logger.LogInformation($"User {Context.ConnectionId} has joined to hubs");
19 | return base.OnConnectedAsync();
20 | }
21 | public async Task JoinUserHub(string userId)
22 | {
23 | await Groups.AddToGroupAsync(Context.ConnectionId, HubRoom.UserHubJoinRoom(userId));
24 | }
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/Models/Dtos/Notification/NotificationDto.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Application.Models.Dtos.Post;
2 | using ChitChat.Application.Models.Dtos.Post.Comments;
3 | using ChitChat.Application.Models.Dtos.User;
4 |
5 | namespace ChitChat.Application.Models.Dtos.Notification
6 | {
7 | public class NotificationDto : BaseResponseDto
8 | {
9 | public string Content { get; set; }
10 | public string Type { get; set; }
11 | public string Reference { get; set; }
12 | public string Action { get; set; }
13 | public string ReceiverUserId { get; set; }
14 | public PostDto? Post { get; set; } // Navigation property
15 | public CommentDto? Comment { get; set; } // Navigation property
16 | public UserDto LastInteractorUser { get; set; } // Navigation property
17 | public DateTime CreatedOn { get; set; }
18 | public DateTime UpdatedOn { get; set; }
19 |
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/ChitChat.DataAccess/Configurations/ReactionPostConfiguration.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Domain.Entities.PostEntities.Reaction;
2 |
3 | using Microsoft.EntityFrameworkCore.Metadata.Builders;
4 |
5 | namespace ChitChat.DataAccess.Configurations
6 | {
7 | public class ReactionPostConfiguration : IEntityTypeConfiguration
8 | {
9 | public void Configure(EntityTypeBuilder modelBuilder)
10 | {
11 | modelBuilder
12 | .HasKey(rp => new { rp.PostId, rp.UserId });
13 |
14 | modelBuilder
15 | .HasOne(rp => rp.Post)
16 | .WithMany()
17 | .HasForeignKey(rp => rp.PostId)
18 | .OnDelete(DeleteBehavior.Cascade);
19 |
20 | modelBuilder
21 | .HasOne(rp => rp.User)
22 | .WithMany()
23 | .HasForeignKey(rp => rp.UserId);
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/ChitChat.DataAccess/Configurations/UserInteractionConfiguration.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Domain.Entities.SystemEntities;
2 |
3 | using Microsoft.EntityFrameworkCore.Metadata.Builders;
4 |
5 | namespace ChitChat.DataAccess.Configurations
6 | {
7 | public class UserInteractionConfiguration : IEntityTypeConfiguration
8 | {
9 | public void Configure(EntityTypeBuilder modelBuilder)
10 | {
11 | // UserInteraction
12 | modelBuilder
13 | .HasKey(ui => ui.Id);
14 |
15 | modelBuilder
16 | .HasOne(ui => ui.User)
17 | .WithMany()
18 | .HasForeignKey(ui => ui.UserId);
19 |
20 | modelBuilder
21 | .HasOne(ui => ui.Post)
22 | .WithMany()
23 | .HasForeignKey(ui => ui.PostId)
24 | .OnDelete(DeleteBehavior.Restrict);
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/Validators/User/ProfileRequestValidator.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Application.Models.Dtos.User.Profile;
2 | using ChitChat.Domain.Enums;
3 |
4 | using FluentValidation;
5 |
6 | namespace ChitChat.Application.Validators.User
7 | {
8 | public class ProfileRequestValidator : AbstractValidator
9 | {
10 | public ProfileRequestValidator()
11 | {
12 | RuleFor(profile => profile.Gender)
13 | .NotNull()
14 | .NotEmpty()
15 | .Must(gender => Enum.TryParse(typeof(Gender), gender, true, out _))
16 | .WithMessage("Invalid gender value. Allowed values are: Male, Female, Other.");
17 | RuleFor(profile => profile.Bio)
18 | .NotNull()
19 | .NotEmpty();
20 | RuleFor(profile => profile.DateOfBirth)
21 | .NotEmpty()
22 | .NotNull();
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/ChitChat.DataAccess/Configurations/ReactionCommentConfiguration.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Domain.Entities.PostEntities.Reaction;
2 |
3 | using Microsoft.EntityFrameworkCore.Metadata.Builders;
4 |
5 | namespace ChitChat.DataAccess.Configurations
6 | {
7 | public class ReactionCommentConfiguration : IEntityTypeConfiguration
8 | {
9 | public void Configure(EntityTypeBuilder modelBuilder)
10 | {
11 | modelBuilder
12 | .HasKey(rc => new { rc.CommentId, rc.UserId });
13 |
14 | modelBuilder
15 | .HasOne(rc => rc.Comment)
16 | .WithMany()
17 | .HasForeignKey(rc => rc.CommentId)
18 | .OnDelete(DeleteBehavior.Cascade);
19 |
20 | modelBuilder
21 | .HasOne(rc => rc.User)
22 | .WithMany()
23 | .HasForeignKey(rc => rc.UserId);
24 |
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/Localization/ValidationText.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Domain.Common;
2 |
3 | namespace ChitChat.Application.Localization
4 | {
5 | public static class ValidationTexts
6 | {
7 | public static readonly LocalizedText NotFound = LocalizedText.New("{0} {1} not found").AddDefaultText("{0} {1} không tồn tại.");
8 | public static readonly LocalizedText Conflict = LocalizedText.New("{0} {1} is already existed").AddDefaultText("{0} với {1} đã tồn tại.");
9 | public static readonly LocalizedText NotValidate = LocalizedText.New("{0} {1} is not validated").AddDefaultText("{0} với {1} không hợp lệ.");
10 | public static readonly LocalizedText Forbidden = LocalizedText.New("Access to {0} {1} is forbidden").AddDefaultText("Quyền truy cập {0} với {1} bị cấm.");
11 | public static readonly LocalizedText Unauthorized = LocalizedText.New("Unauthorized access to {0} {1}").AddDefaultText("Truy cập trái phép {0} với {1}.");
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/Mapping/PostProfile.cs:
--------------------------------------------------------------------------------
1 | using AutoMapper;
2 |
3 | using ChitChat.Application.MachineLearning.Models;
4 | using ChitChat.Application.Models.Dtos.Post;
5 | using ChitChat.Application.Models.Dtos.Post.CreatePost;
6 | using ChitChat.Domain.Entities.PostEntities;
7 |
8 | namespace ChitChat.Application.Mapping
9 | {
10 | public class PostProfile : Profile
11 | {
12 | public PostProfile()
13 | {
14 | CreateMap().ForMember(dest => dest.UserPosted, opt => opt.MapFrom(src => src.User));
15 | CreateMap();
16 | CreateMap();
17 | CreateMap();
18 | CreateMap();
19 | CreateMap();
20 | CreateMap()
21 | .ConvertUsing(src => src.Post);
22 |
23 | //
24 |
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/ChitChat.DataAccess/Configurations/Notification/PostNotificationConfiguration.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Domain.Entities.SystemEntities.Notification;
2 |
3 | using Microsoft.EntityFrameworkCore.Metadata.Builders;
4 |
5 | namespace ChitChat.DataAccess.Configurations.Notification
6 | {
7 | public class PostNotificationConfiguration : IEntityTypeConfiguration
8 | {
9 | public void Configure(EntityTypeBuilder builder)
10 | {
11 | builder.HasKey(n => n.Id);
12 | builder.HasOne(n => n.ReceiverUser)
13 | .WithMany()
14 | .HasForeignKey(n => n.ReceiverUserId);
15 | builder.HasOne(n => n.LastInteractorUser)
16 | .WithMany()
17 | .HasForeignKey(n => n.LastInteractorUserId);
18 | builder.HasOne(n => n.Post)
19 | .WithMany()
20 | .HasForeignKey(n => n.PostId)
21 | .OnDelete(DeleteBehavior.Cascade);
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/ChitChat.Infrastructure/Logging/SerilogOptions.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Infrastructure.Logging
2 | {
3 | public class SerilogOptions
4 | {
5 | public bool Enabled { get; set; }
6 |
7 | public bool LogToConsole { get; set; }
8 |
9 | public long FileSizeLimitInBytes { get; set; } = 1024 * 2; //2Mb
10 |
11 | public int FlushFileToDiskInSeconds { get; set; } = 1;
12 |
13 | public SerilogSeqOptions? SeqOptions { get; set; }
14 |
15 | public SerilogApplicationInsightsOptions? ApplicationInsightsOptions { get; set; }
16 | }
17 |
18 |
19 | public class SerilogSeqOptions
20 | {
21 | public bool Enabled { set; get; }
22 | public string SeqUrl { get; set; } = string.Empty;
23 | public string SeqApiKey { get; set; } = string.Empty;
24 | }
25 |
26 | public class SerilogApplicationInsightsOptions
27 | {
28 | public bool Enabled { set; get; }
29 | public string ConnectionString { get; set; } = string.Empty;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/Exceptions/NotFoundException.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Application.Localization;
2 | using ChitChat.Application.Models;
3 |
4 | namespace ChitChat.Application.Exceptions
5 | {
6 | public class NotFoundException : ApplicationException
7 | {
8 | public NotFoundException(Guid id, Type type) : base(ValidationTexts.NotFound.Format(type.Name, id.ToString()))
9 | {
10 | Code = ApiResultErrorCodes.NotFound;
11 | }
12 |
13 | public NotFoundException(string code, Type type) : base(ValidationTexts.NotFound.Format(type.Name, code))
14 | {
15 | Code = ApiResultErrorCodes.NotFound;
16 | }
17 |
18 | public NotFoundException(string message) : base(message)
19 | {
20 | Code = ApiResultErrorCodes.NotFound;
21 | }
22 |
23 | public NotFoundException(int count, Type type) : base(ValidationTexts.NotFound.Format(count, type.Name))
24 | {
25 | Code = ApiResultErrorCodes.NotFound;
26 | }
27 | }
28 | }
--------------------------------------------------------------------------------
/src/ChitChat.DataAccess/Configurations/Notification/CommentNotificationConfiguration.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Domain.Entities.SystemEntities.Notification;
2 |
3 | using Microsoft.EntityFrameworkCore.Metadata.Builders;
4 |
5 | namespace ChitChat.DataAccess.Configurations.Notification
6 | {
7 | public class CommentNotificationConfiguration : IEntityTypeConfiguration
8 | {
9 | public void Configure(EntityTypeBuilder builder)
10 | {
11 | builder.HasKey(n => n.Id);
12 | builder.HasOne(n => n.ReceiverUser)
13 | .WithMany()
14 | .HasForeignKey(n => n.ReceiverUserId);
15 | builder.HasOne(n => n.LastInteractorUser)
16 | .WithMany()
17 | .HasForeignKey(n => n.LastInteractorUserId);
18 | builder.HasOne(n => n.Comment)
19 | .WithMany()
20 | .HasForeignKey(n => n.CommentId)
21 | .OnDelete(DeleteBehavior.Cascade);
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/ChitChat.Domain/Enums/InteractionType.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Domain.Entities.SystemEntities;
2 |
3 | namespace ChitChat.Domain.Enums
4 | {
5 | public enum InteractionType
6 | {
7 | Comment = 1,
8 | View = 2,
9 | Like = 3,
10 | Unlike = 4
11 | }
12 | public static class InteractionTypePoint
13 | {
14 | public static int GetInteractionPoint(UserInteraction userInteraction)
15 | {
16 | int basePoint = userInteraction.InteractionType switch
17 | {
18 | InteractionType.Comment => 5,
19 | InteractionType.View => 1,
20 | InteractionType.Like => 3,
21 | InteractionType.Unlike => -3,
22 | _ => 0
23 | };
24 |
25 | TimeSpan timeElapsed = DateTime.Now - userInteraction.InteractionDate;
26 | double decayFactor = Math.Max(0.3, 1.0 - timeElapsed.TotalDays / 60); // Giảm dần trong 60 ngày
27 | return (int)(basePoint * decayFactor);
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/ChitChat.DataAccess/Configurations/UserFollowerConfiguration.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Domain.Entities.UserEntities;
2 |
3 | using Microsoft.EntityFrameworkCore.Metadata.Builders;
4 |
5 | namespace ChitChat.DataAccess.Configurations
6 | {
7 | public class UserFollowerConfiguration : IEntityTypeConfiguration
8 | {
9 | public void Configure(EntityTypeBuilder modelBuilder)
10 | {
11 | // UserFollower
12 | modelBuilder
13 | .HasKey(uf => uf.Id);
14 |
15 | /* modelBuilder
16 | .Ignore(ufr => ufr.User);
17 |
18 | modelBuilder
19 | .Ignore(ufr => ufr.Follower);*/
20 | modelBuilder
21 | .HasOne(uf => uf.User)
22 | .WithMany()
23 | .HasForeignKey(uf => uf.UserId);
24 | modelBuilder
25 | .HasOne(uf => uf.Follower)
26 | .WithMany()
27 | .HasForeignKey(uf => uf.FollowerId);
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/ChitChat.DataAccess/Configurations/UserFollowerRequestConfiguration.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Domain.Entities.UserEntities;
2 |
3 | using Microsoft.EntityFrameworkCore.Metadata.Builders;
4 |
5 | namespace ChitChat.DataAccess.Configurations
6 | {
7 | public class UserFollowerRequestConfiguration : IEntityTypeConfiguration
8 | {
9 | public void Configure(EntityTypeBuilder modelBuilder)
10 | {
11 | // UserFollowerRequest
12 | modelBuilder
13 | .HasKey(u => u.Id);
14 | modelBuilder
15 | .Ignore(ufr => ufr.User);
16 | modelBuilder
17 | .Ignore(ufr => ufr.Follower);
18 | //modelBuilder
19 | // .HasOne(u => u.User)
20 | // .WithMany()
21 | //.HasForeignKey(u => u.UserId);
22 |
23 | //modelBuilder
24 | // .HasOne(u => u.Follower)
25 | // .WithMany()
26 | // .HasForeignKey(u => u.FollowerId);
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/ChitChat.DataAccess/Data/AutomatedMigration.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Domain.Identity;
2 |
3 | using Microsoft.AspNetCore.Identity;
4 | using Microsoft.Extensions.DependencyInjection;
5 |
6 | namespace ChitChat.DataAccess.Data
7 | {
8 | public static class AutomatedMigration
9 | {
10 | public static async Task MigrateAsync(IServiceProvider services)
11 | {
12 | var context = services.GetRequiredService();
13 |
14 | var database = context.Database;
15 |
16 | var pendingMigrations = await database.GetPendingMigrationsAsync();
17 |
18 | if (pendingMigrations.Any())
19 | {
20 | await database.MigrateAsync();
21 | }
22 |
23 | var userManager = services.GetRequiredService>();
24 |
25 | var roleManager = services.GetRequiredService>();
26 |
27 | await DbContextSeed.SeedDatabaseAsync(userManager, roleManager);
28 | }
29 | }
30 |
31 | }
32 |
33 |
--------------------------------------------------------------------------------
/src/ChitChat.WebAPI/Controllers/TrainingModelController.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Application.MachineLearning.Services.Interface;
2 | using ChitChat.DataAccess.Repositories.Interface;
3 |
4 | using Microsoft.AspNetCore.Mvc;
5 |
6 | namespace ChitChat.WebAPI.Controllers
7 | {
8 | [Route("api/[controller]")]
9 | [ApiController]
10 | public class TrainingModelController : ControllerBase
11 | {
12 | private readonly ITrainingModelService _trainingModelService;
13 | public TrainingModelController(ITrainingModelService trainingModelService
14 | , IUserRepository userRepository)
15 | {
16 | _trainingModelService = trainingModelService;
17 | }
18 | //[HttpGet]
19 | //[Route("{userId}")]
20 | //public async Task GetRecommendationPostModel(Guid userId)
21 | //{
22 | // var userInteractionModelItems = await _trainingModelService.GetRecommendationPostModel(userId.ToString());
23 | // return Ok(userInteractionModelItems);
24 | //}
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/ChitChat.Infrastructure/Validations/ValidateModelAttribute.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Application.Models;
2 | using Microsoft.AspNetCore.Mvc.Filters;
3 | using Microsoft.AspNetCore.Mvc;
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 |
10 | namespace ChitChat.Infrastructure.Validations
11 | {
12 | public class ValidateModelAttribute : Attribute, IAsyncResultFilter
13 | {
14 | public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
15 | {
16 | if (!context.ModelState.IsValid)
17 | {
18 | var errors = context.ModelState.Values
19 | .SelectMany(modelState => modelState.Errors)
20 | .Select(modelError => new ApiResultError(ApiResultErrorCodes.ModelValidation, modelError.ErrorMessage));
21 |
22 | context.Result = new BadRequestObjectResult(ApiResult.Failure(errors));
23 | }
24 |
25 | await next();
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/Services/Interface/IConversationService.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Application.Models;
2 | using ChitChat.Application.Models.Dtos.Conversation;
3 | using ChitChat.Application.Models.Dtos.Message;
4 |
5 | namespace ChitChat.Application.Services.Interface
6 | {
7 | public interface IConversationService
8 | {
9 | Task> GetAllConversationsAsync(PaginationFilter query);
10 | Task GetConversationsByIdAsync(Guid conversationId, int messagePageIndex, int messagePageSize);
11 | // post
12 | Task CreateConversationAsync(List userIds);
13 | Task SendMessageAsync(Guid conversationId, RequestSendMessageDto request);
14 | // Put
15 | Task UpdateMessageAsync(MessageDto message);
16 | Task UpdateConversationAsync(ConversationDto conversation);
17 | // Delete
18 | Task DeleteConversationAsync(Guid conversationId);
19 | Task DeleteMessageAsync(Guid messageId);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/Mapping/NotificationProfile.cs:
--------------------------------------------------------------------------------
1 | using AutoMapper;
2 |
3 | using ChitChat.Application.Models.Dtos.Notification;
4 | using ChitChat.Domain.Entities.SystemEntities.Notification;
5 |
6 | namespace ChitChat.Application.Mapping
7 | {
8 | public class NotificationProfile : Profile
9 | {
10 | public NotificationProfile()
11 | {
12 | CreateMap().ReverseMap();
13 | CreateMap()
14 | .ForMember(dest => dest.Post, opt => opt.MapFrom(p => p.Comment.Post))
15 | .ForPath(dest => dest.Post.Comments, opt => opt.Ignore());
16 |
17 |
18 | CreateMap();
19 | CreateMap();
20 | CreateMap().ReverseMap();
21 | CreateMap().ReverseMap();
22 | CreateMap().ReverseMap();
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/ChitChat.Infrastructure/CloudinaryConfiguration/CloudinaryRegisteration.cs:
--------------------------------------------------------------------------------
1 | using CloudinaryDotNet;
2 |
3 | using Microsoft.Extensions.DependencyInjection;
4 |
5 | namespace ChitChat.Infrastructure.CloudinaryConfigurations
6 | {
7 | public static class CloudinaryRegisteration
8 | {
9 | public static void AddCloudinary(this IServiceCollection services)
10 | {
11 | CloudinarySetting cloudinarySetting = new CloudinarySetting()
12 | {
13 | CloudName = Environment.GetEnvironmentVariable("CloudinaryCloudName"),
14 | ApiKey = Environment.GetEnvironmentVariable("CloudinaryApiKey"),
15 | ApiSecret = Environment.GetEnvironmentVariable("CloudinaryApiSecret")
16 | };
17 | Account account = new Account(cloudinarySetting.CloudName
18 | , cloudinarySetting.ApiKey
19 | , cloudinarySetting.ApiSecret);
20 | Cloudinary cloudinary = new Cloudinary(account);
21 | services.AddSingleton(cloudinary);
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 Tuan-Thanh Phan
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 |
--------------------------------------------------------------------------------
/src/ChitChat.WebAPI/appsettings.Production.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft.AspNetCore": "Warning"
6 | }
7 | },
8 | "AllowedHosts": "*",
9 | "JWTConfigSetting": {
10 | "SecretKey": "55eaf009a21fa3c5fce7096ca201f24734df43de88484d7a017a8eb389343146df02cf096f0b",
11 | "TokenValidityInDays": 5,
12 | "RefreshTokenValidityInDays": 30,
13 | "Issuer": "Issuer",
14 | "Audience": "Audience"
15 | },
16 | "Database": {
17 | "ConnectionStrings": {
18 | "LocalConnection": "Server=mysql;Database=chitchatdb;User=root;Password=Password12345!;",
19 | "AWSConnection": "Server=mysql-chit-chat.crska2kww12j.ap-southeast-1.rds.amazonaws.com;Port=3306;Database=ChitChatDB;User=admin;Password=123admin;"
20 | }
21 | },
22 | "Kestrel": {
23 | "Endpoints": {
24 | "Http": {
25 | "Url": "http://*:8080"
26 | },
27 | "Https": {
28 | "Url": "https://*:8081",
29 | "Certificate": {
30 | "Path": "/app/chitchat.pfx",
31 | "Password": "chitchat"
32 | }
33 | }
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/docker/DockerCompose/DockerCompose.dcproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 2.1
5 | Linux
6 | False
7 | 37fe7c74-3803-4e83-a00f-09a51f680d0a
8 | LaunchBrowser
9 | {Scheme}://localhost:{ServicePort}/swagger
10 | chitchat.webapi
11 |
12 |
13 |
14 |
15 |
16 | docker-compose.yml
17 |
18 |
19 |
20 |
21 | docker-compose.local.yml
22 | docker-compose.prod.yml
23 |
24 |
--------------------------------------------------------------------------------
/src/ChitChat.WebAPI/Controllers/NotificationController.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Application.Models;
2 | using ChitChat.Application.Models.Dtos.Notification;
3 | using ChitChat.Application.Services.Interface;
4 |
5 | using Microsoft.AspNetCore.Authorization;
6 | using Microsoft.AspNetCore.Mvc;
7 |
8 | namespace ChitChat.WebAPI.Controllers
9 | {
10 | [Route("api/[controller]")]
11 | [ApiController]
12 | [Authorize]
13 | public class NotificationController : ControllerBase
14 | {
15 | private readonly INotificationService _notificationService;
16 | public NotificationController(INotificationService notificationService)
17 | {
18 | this._notificationService = notificationService;
19 | }
20 | [HttpGet]
21 | [Route("")]
22 | [ProducesResponseType(typeof(ApiResult>), StatusCodes.Status200OK)] // OK với ProductResponse
23 | public async Task GetAllNotificationsAsync([FromQuery] PaginationFilter query)
24 | {
25 | return Ok(ApiResult>.Success(await _notificationService.GetAllNotificationsAsync(query)));
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/ChitChat.DataAccess/ChitChat.DataAccess.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net8.0
5 | ChitChat.DataAccess
6 | enable
7 | enable
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | all
17 | runtime; build; native; contentfiles; analyzers; buildtransitive
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/src/ChitChat.DataAccess/DependenceInjection.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.DataAccess.Repositories;
2 | using ChitChat.DataAccess.Repositories.Interface;
3 | using ChitChat.DataAccess.Repositories.Interface;
4 |
5 | using Microsoft.Extensions.Configuration;
6 | using Microsoft.Extensions.DependencyInjection;
7 |
8 | namespace ChitChat.DataAccess
9 | {
10 | public static class DependenceInjection
11 | {
12 | public static IServiceCollection AddDataAccessService(this IServiceCollection services, IConfiguration configuration)
13 | {
14 |
15 | services.AddRepositories();
16 | return services;
17 | }
18 | private static void AddRepositories(this IServiceCollection services)
19 | {
20 | services
21 | .AddScoped(typeof(IBaseRepository<>), typeof(BaseRepository<>))
22 | .AddScoped()
23 | .AddScoped()
24 | .AddScoped()
25 | .AddScoped()
26 | .AddScoped();
27 |
28 | }
29 |
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/ChitChat.Infrastructure/Services/ClaimService.cs:
--------------------------------------------------------------------------------
1 | using System.Security.Claims;
2 |
3 | using ChitChat.Application.Helpers;
4 | using ChitChat.Infrastructure.ConfigSetting;
5 |
6 | using Microsoft.AspNetCore.Http;
7 |
8 | namespace ChitChat.Infrastructure.Services
9 | {
10 | public class ClaimService : IClaimService
11 | {
12 | private readonly IHttpContextAccessor _httpContextAccessor;
13 |
14 | public ClaimService(IHttpContextAccessor httpContextAccessor) => this._httpContextAccessor = httpContextAccessor;
15 |
16 | public string GetUserId() => this.GetClaim(ClaimTypes.NameIdentifier);
17 |
18 | public string GetUserName() => this.GetClaim(ClaimTypes.Name);
19 | public string GetLoginHistoryId(ClaimsIdentity? claimsIdentity = null)
20 | {
21 | if (claimsIdentity is null)
22 | {
23 | return this.GetClaim(JWTConfigSetting.LoginHistoryIdClaimType);
24 | }
25 |
26 | return claimsIdentity.FindFirst(JWTConfigSetting.LoginHistoryIdClaimType)?.Value ?? string.Empty;
27 | }
28 |
29 | private string GetClaim(string key) => this._httpContextAccessor.HttpContext?.User?.FindFirst(key)?.Value ?? string.Empty;
30 |
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/ChitChat.Application.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net8.0
5 | ChitChat.Application
6 | enable
7 | enable
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/src/ChitChat.DataAccess/Migrations/20241123154958_ChangeCommentStatus.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.EntityFrameworkCore.Migrations;
2 |
3 | #nullable disable
4 |
5 | namespace ChitChat.DataAccess.Migrations
6 | {
7 | ///
8 | public partial class ChangeCommentStatus : Migration
9 | {
10 | ///
11 | protected override void Up(MigrationBuilder migrationBuilder)
12 | {
13 | migrationBuilder.AlterColumn(
14 | name: "CommentType",
15 | table: "Comments",
16 | type: "longtext",
17 | nullable: false,
18 | oldClrType: typeof(int),
19 | oldType: "int")
20 | .Annotation("MySql:CharSet", "utf8mb4");
21 | }
22 |
23 | ///
24 | protected override void Down(MigrationBuilder migrationBuilder)
25 | {
26 | migrationBuilder.AlterColumn(
27 | name: "CommentType",
28 | table: "Comments",
29 | type: "int",
30 | nullable: false,
31 | oldClrType: typeof(string),
32 | oldType: "longtext")
33 | .OldAnnotation("MySql:CharSet", "utf8mb4");
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/.github/workflows/deploy-prod.yml:
--------------------------------------------------------------------------------
1 | name: Deploy to AWS EC2
2 |
3 | on:
4 | pull_request:
5 | branches:
6 | - main
7 | types:
8 | - closed
9 |
10 | jobs:
11 | deploy:
12 | if: github.event.pull_request.merged == true && github.event.pull_request.merge_commit_sha != null
13 | runs-on: ubuntu-latest
14 |
15 | steps:
16 | - name: Checkout code
17 | uses: actions/checkout@v2
18 |
19 | - name: Set up SSH
20 | uses: webfactory/ssh-agent@v0.5.3
21 | with:
22 | ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
23 |
24 | - name: Deploy to EC2
25 | env:
26 | SSH_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
27 | run: |
28 | ssh -o StrictHostKeyChecking=no -i ~/.ssh/chit-chat-server.pem ubuntu@ec2-18-138-250-74.ap-southeast-1.compute.amazonaws.com << 'EOF'
29 | cd ~/chit-chat-backend
30 | git checkout main
31 | git pull origin main
32 | docker-compose -f ~/chit-chat-backend/docker/DockerCompose/docker-compose.prod.yml down
33 | docker system prune -a --volumes -f
34 | docker-compose -f ~/chit-chat-backend/docker/DockerCompose/docker-compose.prod.yml build
35 | docker-compose -f ~/chit-chat-backend/docker/DockerCompose/docker-compose.prod.yml up -d
36 | EOF
--------------------------------------------------------------------------------
/src/ChitChat.Application/Services/Interface/IPostService.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Application.Models.Dtos.Post;
2 | using ChitChat.Application.Models.Dtos.Post.Comments;
3 | using ChitChat.Application.Models.Dtos.Post.CreatePost;
4 |
5 | namespace ChitChat.Application.Services.Interface
6 | {
7 | public interface IPostService
8 | {
9 | Task> GetAllPostsAsync(PostUserSearchQueryDto query);
10 | Task GetPostByIdAsync(Guid postId);
11 | Task> GetReccomendationPostsAsync(PostSearchQueryDto query);
12 | Task> GetAllReplyCommentsAsync(Guid postId, Guid commentId);
13 | Task CreateNewPostAsync(CreatePostRequestDto requestDto);
14 | Task CreateNewCommentAsync(Guid postId, CommentRequestDto requestDto);
15 | Task CreateReplyCommentAsync(Guid postId, Guid parentCommentId, CommentRequestDto requestDto);
16 | Task UpdatePostByIdAsync(UpdatePostRequestDto postDto, Guid postId);
17 | Task ToggleReactPostAsync(Guid postId);
18 | Task UpdateCommentAsync(CommentRequestDto commentDto, Guid commentId);
19 | Task ToggleReactCommentAsync(Guid commentId);
20 | Task DeletePostByIdAsync(Guid postId);
21 | Task DeleteCommentByIdAsync(Guid commentId);
22 |
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/ChitChat.DataAccess/Configurations/CommentConfiguration.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Domain.Entities.PostEntities;
2 |
3 | using Microsoft.EntityFrameworkCore.Metadata.Builders;
4 |
5 | namespace ChitChat.DataAccess.Configurations
6 | {
7 | public class CommentConfiguration : IEntityTypeConfiguration
8 | {
9 | public void Configure(EntityTypeBuilder modelBuilder)
10 | {
11 | // Configure primary key
12 | modelBuilder.HasKey(c => c.Id);
13 |
14 | // Configure relationship with Post
15 | modelBuilder
16 | .HasOne(c => c.Post)
17 | .WithMany(p => p.Comments)
18 | .HasForeignKey(c => c.PostId)
19 | .OnDelete(DeleteBehavior.Cascade);
20 |
21 | // Configure relationship with ParentComment
22 | modelBuilder
23 | .HasOne(c => c.ParentComment)
24 | .WithMany(c => c.ReplyComments)
25 | .HasForeignKey(c => c.ParentCommentId)
26 | .OnDelete(DeleteBehavior.Cascade);
27 |
28 | // Configure relationship with UserPosted
29 | modelBuilder
30 | .HasOne(c => c.UserPosted)
31 | .WithMany()
32 | .HasForeignKey(c => c.UserPostedId)
33 | .OnDelete(DeleteBehavior.Cascade);
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/ChitChat.DataAccess/Configurations/ConversationConfiguration.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.EntityFrameworkCore.Metadata.Builders;
2 |
3 | namespace ChitChat.DataAccess.Configurations
4 | {
5 | public class ConversationConfiguration : IEntityTypeConfiguration
6 | {
7 | public void Configure(EntityTypeBuilder modelBuilder)
8 | {
9 | // Configure primary key
10 | modelBuilder.HasKey(c => c.Id);
11 |
12 | // Configure relationship with LastMessage
13 | modelBuilder
14 | .HasOne(c => c.LastMessage)
15 | .WithMany()
16 | .HasForeignKey(c => c.LastMessageId)
17 | .OnDelete(DeleteBehavior.Restrict);
18 |
19 | // Configure relationship with Messages
20 | modelBuilder
21 | .HasMany(c => c.Messages)
22 | .WithOne(m => m.Conversation)
23 | .HasForeignKey(m => m.ConversationId)
24 | .OnDelete(DeleteBehavior.Cascade);
25 |
26 | // Configure relationship with ConversationDetails
27 | modelBuilder
28 | .HasMany(c => c.ConversationDetails)
29 | .WithOne(cd => cd.Conversation)
30 | .HasForeignKey(cd => cd.ConversationId)
31 | .OnDelete(DeleteBehavior.Cascade);
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/ChitChat.Infrastructure/SignalR/Services/ConversationNotificationService.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Application.Models.Dtos.Message;
2 | using ChitChat.Application.SignalR.Interface;
3 | using ChitChat.Infrastructure.SignalR.Helpers;
4 | using ChitChat.Infrastructure.SignalR.Hubs;
5 | using ChitChat.Infrastructure.SignalR.Hubs.InterfaceClient;
6 |
7 | using Microsoft.AspNetCore.SignalR;
8 |
9 | namespace ChitChat.Infrastructure.SignalR.Services
10 | {
11 | public class ConversationNotificationService : IConversationNotificationService
12 | {
13 | private readonly IHubContext _hubContext;
14 | public ConversationNotificationService(IHubContext hubContext) => this._hubContext = hubContext;
15 | public async Task SendMessage(MessageDto message)
16 | {
17 | await _hubContext.Clients.Group(HubRoom.ConversationHubJoinRoom(message.ConversationId)).NewMessage(message);
18 | }
19 |
20 | public async Task UpdateMessage(MessageDto message)
21 | {
22 | await _hubContext.Clients.Group(HubRoom.ConversationHubJoinRoom(message.ConversationId)).UpdateMessage(message);
23 | }
24 | public async Task DeleteMessage(MessageDto message)
25 | {
26 | await _hubContext.Clients.Group(HubRoom.ConversationHubJoinRoom(message.ConversationId)).DeleteMessage(message);
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/ChitChat.Domain/Common/LocalizedText.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Domain.Common
2 | {
3 | public class LocalizedText
4 | {
5 | public string ResourceKey { get; init; } = default!;
6 |
7 | private readonly Dictionary Texts = new();
8 |
9 | public static LocalizedText New(string resourceKey) => new LocalizedText() { ResourceKey = resourceKey }
10 | .AddEnglishText(resourceKey)
11 | .AddDefaultText(resourceKey);
12 |
13 | private LocalizedText AddEnglishText(string text)
14 | {
15 | Texts["en-US"] = text;
16 | return this;
17 | }
18 |
19 | public LocalizedText AddDefaultText(string text)
20 | {
21 | Texts[LocalizationSettings.DefaultCulture] = text;
22 |
23 | return this;
24 | }
25 |
26 | public string Value
27 | {
28 | get
29 | {
30 | var culture = Thread.CurrentThread.CurrentCulture;
31 | return Texts[LocalizationSettings.DefaultCulture];
32 | }
33 | }
34 |
35 | public string Format(params object[] args)
36 | {
37 | if (!args.Any()) return Value;
38 |
39 | if (string.IsNullOrWhiteSpace(Value)) return Value;
40 |
41 | return string.Format(Value, args);
42 | }
43 |
44 | public override string ToString() => Value;
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/ChitChat.Infrastructure/SignalR/SignalRRegistration.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Application.SignalR.Interface;
2 | using ChitChat.Infrastructure.SignalR.Helpers;
3 | using ChitChat.Infrastructure.SignalR.Hubs;
4 | using ChitChat.Infrastructure.SignalR.Services;
5 |
6 | using Microsoft.AspNetCore.Builder;
7 | using Microsoft.AspNetCore.Routing;
8 | using Microsoft.Extensions.DependencyInjection;
9 |
10 | namespace ChitChat.Infrastructure.SignalR
11 | {
12 | public static class SignalRRegistration
13 | {
14 | public static WebApplicationBuilder AddSignalRRegistration(this WebApplicationBuilder builder)
15 | {
16 | builder.Services.AddSignalRService();
17 | return builder;
18 | }
19 | public static void AddSignalRHub(this IEndpointRouteBuilder route)
20 | {
21 | route.MapHub(HubEndpoint.UserHubEndpoint);
22 | route.MapHub(HubEndpoint.ConversationHubEndpoint);
23 | }
24 | private static IServiceCollection AddSignalRService(this IServiceCollection services)
25 | {
26 | services.AddSignalR();
27 | /* services.AddSingleton();*/
28 | services.AddScoped();
29 | services.AddScoped();
30 | return services;
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/ChitChat.WebAPI/ChitChat.WebAPI.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net8.0
5 | enable
6 | enable
7 | ChitChat.WebAPI
8 | 3803187d-c2f2-4669-9bf6-a9422c6a7832
9 | Linux
10 | ..\..
11 | ..\..\docker-compose.dcproj
12 | true
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | all
23 | runtime; build; native; contentfiles; analyzers; buildtransitive
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/Models/ApiResult.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Application.Models
2 | {
3 | public class ApiResult
4 | {
5 | private ApiResult() { }
6 |
7 | private ApiResult(bool succeeded, T result, IEnumerable errors)
8 | {
9 | Succeeded = succeeded;
10 | Result = result;
11 | Errors = errors;
12 | }
13 |
14 | public bool Succeeded { get; set; }
15 |
16 | public T Result { get; set; }
17 |
18 | public IEnumerable Errors { get; set; }
19 |
20 | public static ApiResult Success(T result)
21 | {
22 | return new ApiResult(true, result, new List());
23 | }
24 |
25 | public static ApiResult Failure(IEnumerable errors)
26 | {
27 | return new ApiResult(false, default, errors);
28 | }
29 | }
30 |
31 | public class ApiResultError
32 | {
33 | public string Code { get; set; }
34 |
35 | public string Message { get; set; }
36 |
37 | public ApiResultError(ApiResultErrorCodes code, string message)
38 | {
39 | Code = code.ToString();
40 | Message = message;
41 | }
42 | }
43 |
44 | public enum ApiResultErrorCodes
45 | {
46 | InternalServerError,
47 | ModelValidation,
48 | PermissionValidation,
49 | NotFound,
50 | Unauthorize,
51 | Forbidden,
52 | Conflict
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/ChitChat.WebAPI/Dockerfile:
--------------------------------------------------------------------------------
1 | # Stage 1: Base
2 | FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
3 | WORKDIR /app
4 | EXPOSE 8080
5 | EXPOSE 8081
6 |
7 | # Stage 2: Build
8 | FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
9 | ARG BUILD_CONFIGURATION=Release
10 | WORKDIR /src
11 |
12 | # Copy project files and restore dependencies
13 | COPY ["src/ChitChat.WebAPI/ChitChat.WebAPI.csproj", "ChitChat.WebAPI/"]
14 | COPY ["src/ChitChat.Infrastructure/ChitChat.Infrastructure.csproj", "ChitChat.Infrastructure/"]
15 | COPY ["src/ChitChat.Application/ChitChat.Application.csproj", "ChitChat.Application/"]
16 | COPY ["src/ChitChat.DataAccess/ChitChat.DataAccess.csproj", "ChitChat.DataAccess/"]
17 | COPY ["src/ChitChat.Domain/ChitChat.Domain.csproj", "ChitChat.Domain/"]
18 | RUN dotnet restore "ChitChat.WebAPI/ChitChat.WebAPI.csproj"
19 |
20 | # Copy the remaining source code and build
21 | COPY src/ .
22 | WORKDIR "/src/ChitChat.WebAPI"
23 | RUN dotnet build "ChitChat.WebAPI.csproj" -c $BUILD_CONFIGURATION -o /app/build
24 |
25 | # Stage 3: Publish
26 | FROM build AS publish
27 | RUN dotnet publish "ChitChat.WebAPI.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false
28 |
29 | # Stage 4: Final
30 | FROM base AS final
31 | WORKDIR /app
32 | COPY --from=publish /app/publish .
33 |
34 | # Copy SSL certificate if Production
35 | ARG ENVIRONMENT=Development
36 | COPY ["src/ChitChat.WebAPI/chitchat.pfx", "/app/chitchat.pfx"]
37 | RUN if [ "$ENVIRONMENT" = "Production" ]; then cp /app/chitchat.pfx /app/chitchat.pfx; fi
38 |
39 | ENTRYPOINT ["dotnet", "ChitChat.WebAPI.dll"]
40 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/Mapping/UserProfile.cs:
--------------------------------------------------------------------------------
1 | using AutoMapper;
2 |
3 | using ChitChat.Application.Models.Dtos.User;
4 | using ChitChat.Application.Models.Dtos.User.Profile;
5 | using ChitChat.Domain.Identity;
6 |
7 | namespace ChitChat.Application.Mapping
8 | {
9 | public class UserProfile : Profile
10 | {
11 | public UserProfile()
12 | {
13 | CreateMap();
14 | CreateMap();
15 | CreateMap();
16 | CreateMap();
17 | CreateMap();
18 | CreateMap();
19 | CreateMap()
20 | .ForMember(dest => dest.DisplayName, opt => opt.MapFrom(src => src.UserApplication != null ? src.UserApplication.DisplayName : string.Empty))
21 | .ForMember(dest => dest.AvatarUrl, opt => opt.MapFrom(src => src.UserApplication != null ? src.UserApplication.AvatarUrl : string.Empty))
22 | .ForMember(dest => dest.Email, opt => opt.MapFrom(src => src.UserApplication != null ? src.UserApplication.Email : string.Empty))
23 | .ForMember(dest => dest.PhoneNumber, opt => opt.MapFrom(src => src.UserApplication != null ? src.UserApplication.PhoneNumber : string.Empty));
24 | CreateMap();
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/ChitChat.DataAccess/Configurations/PostConfiguration.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Domain.Entities.PostEntities;
2 |
3 | using Microsoft.EntityFrameworkCore.Metadata.Builders;
4 |
5 | namespace ChitChat.DataAccess.Configurations
6 | {
7 | public class PostConfiguration : IEntityTypeConfiguration
8 | {
9 | public void Configure(EntityTypeBuilder modelBuilder)
10 | {
11 | // Post
12 | modelBuilder
13 | .HasKey(p => p.Id);
14 |
15 | // Configure relationship with User
16 | modelBuilder
17 | .HasOne(p => p.User)
18 | .WithMany()
19 | .HasForeignKey(p => p.UserId);
20 |
21 | // Configure relationship with Comments
22 | modelBuilder
23 | .HasMany(p => p.Comments)
24 | .WithOne(c => c.Post)
25 | .HasForeignKey(c => c.PostId)
26 | .OnDelete(DeleteBehavior.Cascade);
27 |
28 | // Configure relationship with PostDetailTags
29 | modelBuilder
30 | .HasMany(p => p.PostDetailTags)
31 | .WithOne(pdt => pdt.Post)
32 | .HasForeignKey(pdt => pdt.PostId)
33 | .OnDelete(DeleteBehavior.Cascade);
34 |
35 | // Configure relationship with PostMedias
36 | modelBuilder
37 | .HasMany(p => p.PostMedias)
38 | .WithOne(pm => pm.Post)
39 | .HasForeignKey(pm => pm.PostId)
40 | .OnDelete(DeleteBehavior.Cascade);
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/ChitChat.DataAccess/Repositories/Interface/IUserRepository.cs:
--------------------------------------------------------------------------------
1 | using System.Linq.Expressions;
2 |
3 | using ChitChat.Domain.Entities;
4 | using ChitChat.Domain.Identity;
5 |
6 | using Microsoft.EntityFrameworkCore.Query;
7 |
8 | namespace ChitChat.DataAccess.Repositories.Interface
9 | {
10 | public interface IUserRepository
11 | {
12 | IQueryable GetQuery();
13 |
14 | Task GetFirstAsync(Expression> predicate);
15 |
16 | Task GetFirstOrDefaultAsync(Expression> predicate);
17 | Task> GetAllAsync(Expression> predicate);
18 |
19 | Task> GetAllAsync(Expression> predicate, IEnumerable>> includes);
20 | Task> GetAllAsync(Expression> predicate, Func, IIncludableQueryable> includeQuery);
21 | Task> GetAllAsync(Expression> predicate, Func, IOrderedQueryable> sort);
22 | Task UpdateAsync(UserApplication entity);
23 |
24 | Task> UpdateRangeAsync(List entities);
25 |
26 | Task DeleteAsync(UserApplication entity);
27 |
28 | Task AnyAsync(Expression> predicate);
29 |
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/ChitChat.WebAPI/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "profiles": {
3 | "http": {
4 | "commandName": "Project",
5 | "launchBrowser": true,
6 | "launchUrl": "swagger",
7 | "environmentVariables": {
8 | "ASPNETCORE_ENVIRONMENT": "Development"
9 | },
10 | "dotnetRunMessages": true,
11 | "applicationUrl": "http://localhost:5251"
12 | },
13 | "https": {
14 | "commandName": "Project",
15 | "launchBrowser": true,
16 | "launchUrl": "swagger",
17 | "environmentVariables": {
18 | "ASPNETCORE_ENVIRONMENT": "Development"
19 | },
20 | "dotnetRunMessages": true,
21 | "applicationUrl": "https://localhost:7136;http://localhost:5251"
22 | },
23 | "IIS Express": {
24 | "commandName": "IISExpress",
25 | "launchBrowser": true,
26 | "launchUrl": "swagger",
27 | "environmentVariables": {
28 | "ASPNETCORE_ENVIRONMENT": "Development"
29 | }
30 | },
31 | "Container (Dockerfile)": {
32 | "commandName": "Docker",
33 | "launchBrowser": true,
34 | "launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}/swagger",
35 | "environmentVariables": {
36 | "ASPNETCORE_HTTPS_PORTS": "8081",
37 | "ASPNETCORE_HTTP_PORTS": "8080"
38 | },
39 | "publishAllPorts": true,
40 | "useSSL": true
41 | }
42 | },
43 | "$schema": "http://json.schemastore.org/launchsettings.json",
44 | "iisSettings": {
45 | "windowsAuthentication": false,
46 | "anonymousAuthentication": true,
47 | "iisExpress": {
48 | "applicationUrl": "http://localhost:45774",
49 | "sslPort": 44397
50 | }
51 | }
52 | }
--------------------------------------------------------------------------------
/src/ChitChat.DataAccess/Repositories/UserInteractionRepository.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Application.MachineLearning.Models;
2 | using ChitChat.DataAccess.Data;
3 | using ChitChat.DataAccess.Repositories.Interface;
4 | using ChitChat.Domain.Entities.SystemEntities;
5 | using ChitChat.Domain.Enums;
6 |
7 | namespace ChitChat.DataAccess.Repositories
8 | {
9 | public class UserInteractionRepository : BaseRepository, IUserInteractionRepository
10 | {
11 | public UserInteractionRepository(ApplicationDbContext context) : base(context)
12 | {
13 | }
14 |
15 | public async Task> GetUserInteractionModelForTraining(int pageSize)
16 | {
17 | var data = await DbSet
18 | .OrderByDescending(p => p.InteractionDate)
19 | .Include(p => p.Post)
20 | .Take(pageSize)
21 | .ToListAsync(); // Lấy dữ liệu từ database trước
22 |
23 | var userModelItems = data
24 | .GroupBy(p => new
25 | {
26 | p.UserId,
27 | p.PostId,
28 | PostDescription = p.Post.Description
29 | })
30 | .Select(g => new UserInteractionModelItem
31 | {
32 | UserId = g.Key.UserId,
33 | PostId = g.Key.PostId.ToString(),
34 | PostDescription = g.Key.PostDescription,
35 | TotalPoint = g.Sum(x => InteractionTypePoint.GetInteractionPoint(x))
36 | })
37 | .ToList();
38 | return userModelItems;
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/ChitChat.Domain/Common/NotificationFormatter.cs:
--------------------------------------------------------------------------------
1 | namespace ChitChat.Domain.Common
2 | {
3 | public static class NotificationFormatter
4 | {
5 | public static string FormatPostLikeNotification(string userAvatar, string userName, string postImage, string postDescription, DateTime dateTimeLike)
6 | {
7 | return $"{userAvatar} ({userName}) liked your post. ({postImage}, {postDescription}) - {dateTimeLike:yyyy-MM-dd HH:mm:ss}";
8 | }
9 |
10 | public static string FormatPostCommentNotification(string userAvatar, string userName, string postImage, string postDescription, DateTime dateTimeComment)
11 | {
12 | return $"{userAvatar} ({userName}) commented on your post. ({postImage}, {postDescription}) - {dateTimeComment:yyyy-MM-dd HH:mm:ss}";
13 | }
14 |
15 | public static string FormatCommentLikeNotification(string userAvatar, string userName, string myCommentContent, string postImage, DateTime dateTimeLike)
16 | {
17 | return $"{userAvatar} ({userName}) liked your comment: \"{myCommentContent}\" - ({postImage}) - {dateTimeLike:yyyy-MM-dd HH:mm:ss}";
18 | }
19 |
20 | public static string FormatCommentReplyNotification(string userAvatar, string userName, string myCommentContent, string postImage, DateTime dateTimeComment)
21 | {
22 | return $"{userAvatar} ({userName}) replied to your comment: \"{myCommentContent}\" - ({postImage}) - {dateTimeComment:yyyy-MM-dd HH:mm:ss}";
23 | }
24 |
25 | public static string FormatFollowerNotification(string userAvatar, string userName, DateTime dateTimeFollow)
26 | {
27 | return $"{userAvatar} ({userName}) started following you - {dateTimeFollow:yyyy-MM-dd HH:mm:ss}";
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/ChitChat.Infrastructure/Authorization/AuthorizationRegisteration.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Infrastructure.ConfigSetting;
2 |
3 | using Microsoft.AspNetCore.Authentication.JwtBearer;
4 | using Microsoft.AspNetCore.Builder;
5 | using Microsoft.Extensions.Configuration;
6 | using Microsoft.Extensions.DependencyInjection;
7 | using Microsoft.IdentityModel.Tokens;
8 |
9 | namespace ChitChat.Infrastructure.Authorization
10 | {
11 | internal static class AuthorizationRegisteration
12 | {
13 | public static WebApplicationBuilder AddAppAuthorization(this WebApplicationBuilder builder)
14 | {
15 | var jwtOption = builder.Configuration.GetSection(nameof(JWTConfigSetting)).Get();
16 | builder.Services.AddSingleton(jwtOption);
17 | var key = Encoding.ASCII.GetBytes(jwtOption.SecretKey);
18 |
19 | builder.Services.AddAuthentication(x =>
20 | {
21 | x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
22 | x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
23 | })
24 | .AddJwtBearer(x =>
25 | {
26 | x.RequireHttpsMetadata = false;
27 | x.SaveToken = true;
28 | x.TokenValidationParameters = new TokenValidationParameters
29 | {
30 | ValidateIssuerSigningKey = true,
31 | IssuerSigningKey = new SymmetricSecurityKey(key),
32 | ValidAudience = jwtOption.Audience,
33 | ValidIssuer = jwtOption.Issuer,
34 | ValidateLifetime = true
35 | };
36 | });
37 | return builder;
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/Validators/User/RegisterationRequestValidator.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Application.Models.Dtos.User;
2 |
3 | using FluentValidation;
4 | namespace ChitChat.Application.Validators.User
5 | {
6 | public class RegisterationRequestValidator : AbstractValidator
7 | {
8 | public RegisterationRequestValidator()
9 | {
10 | RuleFor(user => user.FirstName)
11 | .NotEmpty().WithMessage("First name is required.")
12 | .Length(1, 255).WithMessage("First name must be between 1 and 255 characters.");
13 |
14 | RuleFor(user => user.LastName)
15 | .NotEmpty().WithMessage("Last name is required.")
16 | .Length(1, 255).WithMessage("Last name must be between 1 and 255 characters.");
17 |
18 | /* RuleFor(user => user.AvatarUrl)
19 | .MaximumLength(255).WithMessage("Avatar URL must be up to 255 characters.");
20 |
21 | RuleFor(user => user.Bio)
22 | .MaximumLength(500).WithMessage("Bio must be up to 500 characters.");
23 |
24 | RuleFor(user => user.DateOfBirth)
25 | .LessThan(DateTime.Now).WithMessage("Date of birth must be in the past.");
26 |
27 | RuleFor(user => user.Gender)
28 | .Matches("^(Male|Female|Other)$").WithMessage("Gender must be Male, Female, or Other.");
29 |
30 | RuleFor(user => user.UserStatus)
31 | .IsInEnum().WithMessage("User status must be a valid value. User Status must is 0 {Private} and 1 {Public}");
32 | */
33 | RuleFor(user => user.Email)
34 | .EmailAddress().WithMessage("Email is not valid");
35 | }
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/src/ChitChat.Infrastructure/EntityFrameworkCore/EntityFrameworkRegisteration.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.DataAccess.Data;
2 | using ChitChat.DataAccess.Data.Interceptor;
3 |
4 | using Microsoft.AspNetCore.Builder;
5 | using Microsoft.Extensions.Configuration;
6 | using Microsoft.Extensions.DependencyInjection;
7 |
8 | namespace ChitChat.Infrastructure.EntityFrameworkCore
9 | {
10 | public static class EntityFrameworkRegisteration
11 | {
12 | public static WebApplicationBuilder AddEntityFramewordCore(this WebApplicationBuilder builder)
13 | {
14 | var configuration = builder.Configuration;
15 |
16 | builder.Services.AddScoped();
17 |
18 | builder.Services.AddDbContext((provider, options) =>
19 | {
20 | var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
21 | var connectionString = environment == "Development"
22 | ? configuration.GetSection("Database:ConnectionStrings").GetValue("LocalConnection")
23 | : configuration.GetSection("Database:ConnectionStrings").GetValue("AWSConnection");
24 |
25 | options
26 | .AddInterceptors(provider.GetRequiredService())
27 | .UseMySql(connectionString, new MySqlServerVersion(new Version(8, 0, 39)),
28 | opt =>
29 | {
30 | opt.MigrationsAssembly(typeof(ApplicationDbContext).Assembly.FullName);
31 | opt.EnableRetryOnFailure();
32 | });
33 | });
34 |
35 | builder.Services.AddScoped(sp => sp.GetRequiredService());
36 |
37 | return builder;
38 | }
39 |
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/ChitChat.Infrastructure/ChitChat.Infrastructure.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net8.0
5 | ChitChat.Infrastructure
6 | enable
7 | enable
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | all
19 | runtime; build; native; contentfiles; analyzers; buildtransitive
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/src/ChitChat.Infrastructure/Caching/MemoryCacheService.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Application.Services.Caching;
2 |
3 | using Microsoft.Extensions.Caching.Memory;
4 |
5 | namespace ChitChat.Infrastructure.Caching
6 | {
7 | public class MemoryCacheService : ICachingService
8 | {
9 | private readonly IMemoryCache _memoryCache;
10 |
11 | private MemoryCacheEntryOptions MemoryCacheEntryOptions = new()
12 | {
13 | AbsoluteExpirationRelativeToNow = CacheEntryOptions.Default.AbsoluteExpirationRelativeToNow,
14 | SlidingExpiration = CacheEntryOptions.Default.SlidingExpiration
15 | };
16 |
17 | public MemoryCacheService(IMemoryCache memoryCache)
18 | {
19 | this._memoryCache = memoryCache;
20 | }
21 |
22 | public async Task Set(string key, T value)
23 | {
24 | await Task.Yield();
25 | this._memoryCache.Set(key, value, this.MemoryCacheEntryOptions);
26 | }
27 |
28 | public async Task Get(string key)
29 | {
30 | await Task.Yield();
31 | this._memoryCache.TryGetValue(key, out var cacheEntry);
32 | return cacheEntry;
33 | }
34 |
35 | public async Task GetOrSetAsync(string key, Func> func)
36 | {
37 | var cacheEntry = await this._memoryCache.GetOrCreateAsync(key, async entry =>
38 | {
39 | entry
40 | .SetSlidingExpiration(this.MemoryCacheEntryOptions.SlidingExpiration!.Value)
41 | .SetAbsoluteExpiration(this.MemoryCacheEntryOptions.AbsoluteExpirationRelativeToNow!.Value);
42 |
43 | return await func();
44 | });
45 |
46 | return cacheEntry;
47 | }
48 |
49 | public async Task Remove(string key)
50 | {
51 | this._memoryCache.Remove(key);
52 | await Task.CompletedTask;
53 | }
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/src/ChitChat.DataAccess/Repositories/UserFollowerRepository.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.DataAccess.Data;
2 | using ChitChat.DataAccess.Repositories.Interface;
3 | using ChitChat.Domain.Entities.UserEntities;
4 | using ChitChat.Domain.Identity;
5 |
6 | namespace ChitChat.DataAccess.Repositories
7 | {
8 | public class UserFollowerRepository : BaseRepository, IUserFollowerRepository
9 | {
10 | public UserFollowerRepository(ApplicationDbContext context) : base(context)
11 | {
12 | }
13 |
14 | public async Task> GetRecommendedUsersAsync(string currentUserId, int pageSize)
15 | {
16 | var followedUsers = await this.Context.UserFollowers
17 | .Where(uf => uf.UserId == currentUserId)
18 | .Select(uf => uf.FollowerId)
19 | .ToListAsync();
20 | var recommendedUsers = await Context.UserFollowers
21 | .Where(uf => followedUsers.Contains(uf.UserId) // Người bạn của tôi theo dõi
22 | && uf.FollowerId != currentUserId // Không phải chính tôi
23 | && !followedUsers.Contains(uf.FollowerId))
24 | .Include(p => p.User)
25 | .Select(p => p.User)// Tôi chưa theo dõi họ
26 | .Distinct() // Loại bỏ trùng lặp
27 | .ToListAsync();
28 | var otherFollow = await Context.UserApplications
29 | .Where(p => p.Id != currentUserId// Tôi chưa theo dõi họ
30 | && !followedUsers.Contains(p.Id))// Họ chưa theo dõi tôi
31 | .ToListAsync();
32 | var allUsers = recommendedUsers
33 | .Concat(otherFollow) // Gộp với otherFollow
34 | .ToList();
35 | // Random hóa danh sách
36 | var randomUsers = allUsers.OrderBy(u => Guid.NewGuid()).ToList();
37 | return randomUsers.Take(pageSize).ToList();
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/ChitChat.Application/DependencyInjection.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 |
3 | using ChitChat.Application.MachineLearning.Services;
4 | using ChitChat.Application.MachineLearning.Services.Interface;
5 | using ChitChat.Application.Mapping;
6 | using ChitChat.Application.Services;
7 | using ChitChat.Application.Services.Interface;
8 | using ChitChat.Application.Validators;
9 |
10 | using FluentValidation;
11 |
12 | using Microsoft.Extensions.DependencyInjection;
13 | namespace ChitChat.Application
14 | {
15 | public static class DependencyInjection
16 | {
17 | public static IServiceCollection AddApplicationServices(this IServiceCollection services)
18 | {
19 | // Add Validators
20 |
21 | services.AddValidatorsFromAssembly(Assembly.GetExecutingAssembly())
22 | .AddValidatorsFromAssemblyContaining();
23 |
24 | // Add MediaR
25 |
26 | services.AddMediatR(cfg =>
27 | {
28 | cfg.RegisterServicesFromAssembly(Assembly.GetExecutingAssembly());
29 | });
30 |
31 | // Add AutoMapper
32 |
33 | services.AddAutoMapper(typeof(IMappingProfileMarker));
34 |
35 | // Add Services
36 | services.AddServices();
37 |
38 |
39 | return services;
40 | }
41 | public static IServiceCollection AddServices(this IServiceCollection services)
42 | {
43 | services.AddScoped();
44 | services.AddScoped();
45 | services.AddScoped();
46 | services.AddScoped();
47 | services.AddScoped();
48 | services.AddScoped();
49 | services.AddScoped();
50 | return services;
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/ChitChat.Infrastructure/SignalR/Hubs/ConversationHub.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Infrastructure.SignalR.Helpers;
2 | using ChitChat.Infrastructure.SignalR.Hubs.InterfaceClient;
3 |
4 | using Microsoft.AspNetCore.SignalR;
5 | using Microsoft.Extensions.Logging;
6 |
7 | namespace ChitChat.Infrastructure.SignalR.Hubs
8 | {
9 | public class ConversationHub : Hub
10 | {
11 | private readonly ILogger _logger;
12 | public ConversationHub(ILogger logger)
13 | {
14 | _logger = logger;
15 | }
16 | public override Task OnConnectedAsync() => base.OnConnectedAsync();
17 | public async Task JoinConversationGroup(Guid conversationId)
18 | {
19 | var roomId = HubRoom.ConversationHubJoinRoom(conversationId);
20 | await Groups.AddToGroupAsync(Context.ConnectionId, roomId);
21 | await Clients.Group(roomId).ConversationJoined($"{Context.ConnectionId} has joined the room {roomId}");
22 | }
23 | public async Task SendOffer(Guid conversationId, string sdp)
24 | {
25 | var roomId = HubRoom.ConversationHubJoinRoom(conversationId);
26 | await Clients.OthersInGroup(roomId).ReceiveOffer(Context.ConnectionId, sdp);
27 | }
28 |
29 | public async Task SendAnswer(Guid conversationId, string sdp)
30 | {
31 | var roomId = HubRoom.ConversationHubJoinRoom(conversationId);
32 | await Clients.OthersInGroup(roomId).ReceiveAnswer(Context.ConnectionId, sdp);
33 | }
34 |
35 | public async Task SendIceCandidate(Guid conversationId, string candidate)
36 | {
37 | var roomId = HubRoom.ConversationHubJoinRoom(conversationId);
38 | await Clients.OthersInGroup(roomId).ReceiveIceCandidate(Context.ConnectionId, candidate);
39 | }
40 | public async Task StartCall(Guid conversationId)
41 | {
42 | var roomId = HubRoom.ConversationHubJoinRoom(conversationId);
43 | await Clients.OthersInGroup(roomId).ReceiveCall(conversationId);
44 | }
45 |
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/ChitChat.WebAPI/Program.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.Application;
2 | using ChitChat.DataAccess;
3 | using ChitChat.DataAccess.Data;
4 | using ChitChat.Domain.Common;
5 | using ChitChat.Infrastructure;
6 | using ChitChat.Infrastructure.SignalR;
7 | using ChitChat.Infrastructure.Validations;
8 | using ChitChat.WebAPI;
9 |
10 | using FluentValidation;
11 | using FluentValidation.AspNetCore;
12 |
13 | var builder = WebApplication.CreateBuilder(args);
14 |
15 | // Add services to the container.
16 | var env = builder.Environment;
17 | builder.Configuration
18 | .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
19 | .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: false, reloadOnChange: true);
20 |
21 | DotNetEnv.Env.Load();
22 | ValidatorOptions.Global.DefaultRuleLevelCascadeMode = CascadeMode.Stop;
23 | builder.Services
24 | .AddFluentValidationAutoValidation()
25 | .AddFluentValidationClientsideAdapters()
26 | .AddControllers(config => config.Filters.Add(typeof(ValidateModelAttribute)))
27 | .AddJsonOptions(options =>
28 | {
29 | options.JsonSerializerOptions.Converters.Add(new UnixTimestampConverter());
30 | }); ;
31 | // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
32 | builder.Services.AddEndpointsApiExplorer();
33 | builder.Services.AddSwaggerGen();
34 | builder.Services
35 | .AddDataAccessService(builder.Configuration)
36 | .AddApplicationServices();
37 | builder
38 | .AddInfrastructure()
39 | .AddWebAPI()
40 | ;
41 | var app = builder.Build();
42 |
43 |
44 | // Configure the HTTP request pipeline.
45 | app.UseSwagger();
46 | app.UseSwaggerUI();
47 |
48 | // Migrate Database
49 | using var scope = app.Services.CreateAsyncScope();
50 | await AutomatedMigration.MigrateAsync(scope.ServiceProvider);
51 |
52 | app.UseHttpsRedirection();
53 | app.AddInfrastuctureApplication();
54 | app.UseAuthentication();
55 | app.UseAuthorization();
56 | app.AddSignalRHub();
57 | app.UseCors(corsPolicyBuilder => corsPolicyBuilder
58 | .AllowAnyOrigin()
59 | .AllowAnyMethod()
60 | .AllowAnyHeader()
61 | );
62 | app.MapControllers();
63 |
64 | app.Run();
65 |
66 |
--------------------------------------------------------------------------------
/src/ChitChat.DataAccess/Repositories/ConversationRepository.cs:
--------------------------------------------------------------------------------
1 | using ChitChat.DataAccess.Data;
2 | using ChitChat.DataAccess.Repositories.Interface;
3 | using ChitChat.Domain.Enums;
4 |
5 | namespace ChitChat.DataAccess.Repositories
6 | {
7 | public class ConversationRepository : BaseRepository, IConversationRepository
8 | {
9 | public ConversationRepository(ApplicationDbContext context) : base(context)
10 | {
11 | }
12 |
13 | public async Task> GetConversationByUserIdAsync(string userId)
14 | {
15 | var listConversation = await (from convDetail in Context.ConversationDetails
16 | join conv in Context.Conversations on convDetail.ConversationId equals conv.Id
17 | where convDetail.UserId == userId && conv.IsDeleted == false
18 | select conv)
19 | .Include(
20 | c => c.ConversationDetails
21 | )
22 | .Include(c => c.LastMessage)
23 | .AsNoTracking()
24 | .ToListAsync();
25 | return listConversation;
26 | }
27 |
28 | public async Task IsConversationExisted(string userSenderId, string userReceiverId)
29 | {
30 | Conversation? hasConversation = await Context.ConversationDetails
31 | .Where(cd2 => cd2.UserId == userReceiverId && cd2.Conversation.ConversationType == ConversationType.Person.ToString())
32 | .SelectMany(cd2 => Context.ConversationDetails
33 | .Where(cd1 => cd1.UserId == userSenderId && cd1.ConversationId == cd2.ConversationId))
34 | .Select(cd1 => cd1.Conversation)
35 | .SingleOrDefaultAsync();
36 | if (hasConversation != null)
37 | hasConversation.LastMessage = await Context.Messages.SingleOrDefaultAsync(p => p.Id == hasConversation.LastMessageId);
38 | return hasConversation;
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/ChitChat.DataAccess/Data/ApplicationDbContext.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 |
3 | using ChitChat.Domain.Entities;
4 | using ChitChat.Domain.Entities.ChatEntities;
5 | using ChitChat.Domain.Entities.PostEntities;
6 | using ChitChat.Domain.Entities.PostEntities.Reaction;
7 | using ChitChat.Domain.Entities.SystemEntities;
8 | using ChitChat.Domain.Entities.SystemEntities.Notification;
9 | using ChitChat.Domain.Entities.UserEntities;
10 | using ChitChat.Domain.Identity;
11 |
12 | using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
13 |
14 | namespace ChitChat.DataAccess.Data
15 | {
16 | public class ApplicationDbContext : IdentityDbContext
17 | {
18 | public DbSet UserApplications { get; set; }
19 | public DbSet UserFollowers { get; set; }
20 | public DbSet UserFollowerRequests { get; set; }
21 | public DbSet Conversations { get; set; }
22 | public DbSet ConversationDetails { get; set; }
23 | public DbSet LoginHistories { get; set; }
24 | public DbSet