├── .gitignore ├── README.md ├── SocialNetwork.Common ├── Mapping │ ├── IHaveCustomMapping.cs │ └── IMapFrom.cs └── SocialNetwork.Common.csproj ├── SocialNetwork.Data ├── Configurations │ ├── EventUserConfiguration.cs │ ├── FriendRequestConfiguration.cs │ ├── PostConfiguration.cs │ ├── UserConfiguration.cs │ └── UserInterestConfiguration.cs ├── DataConstants.cs ├── Entities │ ├── Comment.cs │ ├── Enums │ │ ├── Feeling.cs │ │ └── FriendRequestStatus.cs │ ├── Event.cs │ ├── EventUser.cs │ ├── FriendRequest.cs │ ├── Interest.cs │ ├── Message.cs │ ├── Photo.cs │ ├── Post.cs │ ├── User.cs │ ├── UserFriend.cs │ └── UserInterest.cs ├── Migrations │ ├── 20171216161858_Initial.Designer.cs │ ├── 20171216161858_Initial.cs │ ├── 20171218201559_Messages.Designer.cs │ ├── 20171218201559_Messages.cs │ ├── 20171219095136_Interests.Designer.cs │ ├── 20171219095136_Interests.cs │ ├── 20171219162332_Events.Designer.cs │ ├── 20171219162332_Events.cs │ └── SocialNetworkDbContextModelSnapshot.cs ├── SocialNetwork.Data.csproj └── SocialNetworkDbContext.cs ├── SocialNetwork.Services ├── ICommentService.cs ├── IEmailSender.cs ├── IEventService.cs ├── IFriendRequestService.cs ├── IMessangerService.cs ├── IPhotoService.cs ├── IPostService.cs ├── IService.cs ├── IUserService.cs ├── Implementations │ ├── CommentService.cs │ ├── EmailSender.cs │ ├── EventService.cs │ ├── FriendRequestService.cs │ ├── MessangerService.cs │ ├── PhotoService.cs │ ├── PostService.cs │ └── UserService.cs ├── Infrastructure │ ├── CustomDataStructures │ │ └── PaginatedList.cs │ └── ServiceConstants.cs ├── Models │ ├── CommentModel.cs │ ├── EventModel.cs │ ├── MessageModel.cs │ ├── PostModel.cs │ ├── ReceivedFriendRequestModel.cs │ ├── SentFriendRequestModel.cs │ ├── UserAccountModel.cs │ ├── UserListModel.cs │ └── UserModel.cs └── SocialNetwork.Services.csproj ├── SocialNetwork.Tests ├── Common │ └── Initializer.cs ├── Mocks │ └── MockCreator.cs ├── Services │ └── MessangerServiceTest.cs ├── SocialNetwork.Tests.csproj └── Web │ └── Controllers │ ├── CommentControllerTest.cs │ └── UserControllerTest.cs ├── SocialNetwork.Web ├── .bowerrc ├── Areas │ └── Admin │ │ ├── Controllers │ │ ├── AdminBaseController.cs │ │ ├── HomeController.cs │ │ └── UsersController.cs │ │ ├── Models │ │ └── Users │ │ │ └── UserEditModel.cs │ │ └── Views │ │ ├── Home │ │ └── Index.cshtml │ │ ├── Shared │ │ ├── Error.cshtml │ │ ├── _Layout.cshtml │ │ ├── _LoginPartial.cshtml │ │ └── _ValidationScriptsPartial.cshtml │ │ ├── Users │ │ ├── Delete.cshtml │ │ ├── Edit.cshtml │ │ └── Search.cshtml │ │ ├── _ViewImports.cshtml │ │ └── _ViewStart.cshtml ├── Controllers │ ├── AccountController.cs │ ├── CommentController.cs │ ├── EventsController.cs │ ├── FriendRequestsController.cs │ ├── HomeController.cs │ ├── ManageController.cs │ ├── MessangerController.cs │ ├── PostsController.cs │ └── UsersController.cs ├── Extensions │ ├── ApplicationBuilderExtensions.cs │ ├── ByteArrayExtensions.cs │ ├── ClaimsPrincipalExtensions.cs │ ├── ControllerExtensions.cs │ ├── EmailSenderExtensions.cs │ ├── ServiceCollectionExtensions.cs │ └── UrlHelperExtensions.cs ├── Hub │ └── ChatHub.cs ├── Infrastructure │ ├── CoreValidator.cs │ ├── CustomValidationAttributes │ │ └── AgeAttribute.cs │ ├── Filters │ │ └── ValidateModelStateAttribute.cs │ ├── GlobalConstants.cs │ └── Mapping │ │ └── AutoMapperProfile.cs ├── Models │ ├── AccountViewModels │ │ ├── ExternalLoginViewModel.cs │ │ ├── ForgotPasswordViewModel.cs │ │ ├── LoginViewModel.cs │ │ ├── LoginWith2faViewModel.cs │ │ ├── LoginWithRecoveryCodeViewModel.cs │ │ ├── RegisterViewModel.cs │ │ └── ResetPasswordViewModel.cs │ ├── Comment │ │ └── PostCommentCreateModel.cs │ ├── ErrorViewModel.cs │ ├── Events │ │ └── EventFormModel.cs │ ├── HomeViewModels │ │ └── EmailModel.cs │ ├── ManageViewModels │ │ ├── ChangePasswordViewModel.cs │ │ ├── EnableAuthenticatorViewModel.cs │ │ ├── ExternalLoginsViewModel.cs │ │ ├── GenerateRecoveryCodesViewModel.cs │ │ ├── IndexViewModel.cs │ │ ├── RemoveLoginViewModel.cs │ │ ├── SetPasswordViewModel.cs │ │ └── TwoFactorAuthenticationViewModel.cs │ ├── Messanger │ │ └── MessangerModel.cs │ └── PostsViewModels │ │ └── PostFormModel.cs ├── Program.cs ├── ScaffoldingReadMe.txt ├── SocialNetwork.Web.csproj ├── Startup.cs ├── Views │ ├── Account │ │ ├── AccessDenied.cshtml │ │ ├── ConfirmEmail.cshtml │ │ ├── ExternalLogin.cshtml │ │ ├── ForgotPassword.cshtml │ │ ├── ForgotPasswordConfirmation.cshtml │ │ ├── Lockout.cshtml │ │ ├── Login.cshtml │ │ ├── LoginWithRecoveryCode.cshtml │ │ ├── Register.cshtml │ │ ├── ResetPassword.cshtml │ │ ├── ResetPasswordConfirmation.cshtml │ │ └── SignedOut.cshtml │ ├── Comment │ │ └── Create.cshtml │ ├── Events │ │ ├── Create.cshtml │ │ └── Details.cshtml │ ├── Home │ │ ├── Contact.cshtml │ │ └── Index.cshtml │ ├── Manage │ │ ├── ChangePassword.cshtml │ │ ├── Disable2fa.cshtml │ │ ├── EnableAuthenticator.cshtml │ │ ├── ExternalLogins.cshtml │ │ ├── GenerateRecoveryCodes.cshtml │ │ ├── Index.cshtml │ │ ├── ManageNavPages.cs │ │ ├── ResetAuthenticator.cshtml │ │ ├── SetPassword.cshtml │ │ ├── _Layout.cshtml │ │ ├── _ManageNav.cshtml │ │ ├── _StatusMessage.cshtml │ │ └── _ViewImports.cshtml │ ├── Messanger │ │ └── Index.cshtml │ ├── Posts │ │ ├── Create.cshtml │ │ ├── Delete.cshtml │ │ ├── Edit.cshtml │ │ └── _PostForm.cshtml │ ├── Shared │ │ ├── Error.cshtml │ │ ├── _Layout.cshtml │ │ ├── _LoginPartial.cshtml │ │ └── _ValidationScriptsPartial.cshtml │ ├── Users │ │ ├── AccountDetails.cshtml │ │ ├── Index.cshtml │ │ ├── Search.cshtml │ │ └── _PostComments.cshtml │ ├── _ViewImports.cshtml │ └── _ViewStart.cshtml ├── appsettings.Development.json ├── appsettings.json ├── bower.json ├── bundleconfig.json └── wwwroot │ ├── css │ ├── site.css │ └── site.min.css │ ├── favicon.ico │ ├── images │ ├── banner1.svg │ ├── banner2.svg │ ├── banner3.svg │ └── banner4.svg │ ├── js │ ├── site.js │ └── site.min.js │ └── lib │ ├── bootstrap │ ├── .bower.json │ ├── LICENSE │ └── dist │ │ ├── css │ │ ├── bootstrap-theme.css │ │ ├── bootstrap-theme.css.map │ │ ├── bootstrap-theme.min.css │ │ ├── bootstrap-theme.min.css.map │ │ ├── bootstrap.css │ │ ├── bootstrap.css.map │ │ ├── bootstrap.min.css │ │ └── bootstrap.min.css.map │ │ ├── fonts │ │ ├── glyphicons-halflings-regular.eot │ │ ├── glyphicons-halflings-regular.svg │ │ ├── glyphicons-halflings-regular.ttf │ │ ├── glyphicons-halflings-regular.woff │ │ └── glyphicons-halflings-regular.woff2 │ │ └── js │ │ ├── bootstrap.js │ │ ├── bootstrap.min.js │ │ └── npm.js │ ├── jquery-validation-unobtrusive │ ├── .bower.json │ ├── jquery.validate.unobtrusive.js │ └── jquery.validate.unobtrusive.min.js │ ├── jquery-validation │ ├── .bower.json │ ├── LICENSE.md │ └── dist │ │ ├── additional-methods.js │ │ ├── additional-methods.min.js │ │ ├── jquery.validate.js │ │ └── jquery.validate.min.js │ ├── jquery │ ├── .bower.json │ ├── LICENSE.txt │ └── dist │ │ ├── jquery.js │ │ ├── jquery.min.js │ │ └── jquery.min.map │ └── signalr │ └── signalr-client-1.0.0-alpha2-final.js └── SocialNetwork.sln /README.md: -------------------------------------------------------------------------------- 1 | # Social-Network-ASP.NET-Core-MVC 2 | A simple social network application developped with ASP.NET Core MVC 3 | -------------------------------------------------------------------------------- /SocialNetwork.Common/Mapping/IHaveCustomMapping.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | 3 | namespace SocialNetwork.Common.Mapping 4 | { 5 | public interface IHaveCustomMapping 6 | { 7 | void ConfigureMapping(Profile profile); 8 | } 9 | } -------------------------------------------------------------------------------- /SocialNetwork.Common/Mapping/IMapFrom.cs: -------------------------------------------------------------------------------- 1 | namespace SocialNetwork.Common.Mapping 2 | { 3 | public interface IMapFrom 4 | { 5 | } 6 | } -------------------------------------------------------------------------------- /SocialNetwork.Common/SocialNetwork.Common.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp2.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /SocialNetwork.Data/Configurations/EventUserConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 3 | using SocialNetwork.Data.Entities; 4 | 5 | namespace SocialNetwork.Data.Configurations 6 | { 7 | public class EventUserConfiguration : IEntityTypeConfiguration 8 | { 9 | public void Configure(EntityTypeBuilder builder) 10 | { 11 | builder.HasKey(eu => new { eu.EventId, eu.UserId }); 12 | 13 | builder 14 | .HasOne(eu => eu.User) 15 | .WithMany(u => u.Events) 16 | .HasForeignKey(eu => eu.UserId); 17 | 18 | builder 19 | .HasOne(eu => eu.Event) 20 | .WithMany(e => e.Participants) 21 | .HasForeignKey(eu => eu.EventId); 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /SocialNetwork.Data/Configurations/FriendRequestConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 3 | using SocialNetwork.Data.Entities; 4 | 5 | namespace SocialNetwork.Data.Configurations 6 | { 7 | internal class FriendRequestConfiguration : IEntityTypeConfiguration 8 | { 9 | public void Configure(EntityTypeBuilder builder) 10 | { 11 | builder 12 | .HasOne(fr => fr.Sender) 13 | .WithMany(u => u.FriendRequestSent) 14 | .HasForeignKey(fr => fr.SenderId); 15 | 16 | builder 17 | .HasOne(fr => fr.Receiver) 18 | .WithMany(u => u.FriendRequestReceived) 19 | .HasForeignKey(fr => fr.ReceiverId); 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /SocialNetwork.Data/Configurations/PostConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 3 | using SocialNetwork.Data.Entities; 4 | 5 | namespace SocialNetwork.Data.Configurations 6 | { 7 | public class PostConfiguration : IEntityTypeConfiguration 8 | { 9 | public void Configure(EntityTypeBuilder builder) 10 | { 11 | builder 12 | .HasMany(p => p.Comments) 13 | .WithOne(c => c.Post) 14 | .HasForeignKey(c => c.PostId); 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /SocialNetwork.Data/Configurations/UserConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 3 | using SocialNetwork.Data.Entities; 4 | 5 | namespace SocialNetwork.Data.Configurations 6 | { 7 | public class UserConfiguration : IEntityTypeConfiguration 8 | { 9 | public void Configure(EntityTypeBuilder builder) 10 | { 11 | builder 12 | .HasMany(u => u.MessagesReceived) 13 | .WithOne(m => m.Receiver) 14 | .HasForeignKey(m => m.ReceiverId) 15 | .OnDelete(DeleteBehavior.Restrict); 16 | 17 | builder 18 | .HasMany(u => u.MessagesSent) 19 | .WithOne(m => m.Sender) 20 | .HasForeignKey(m => m.SenderId) 21 | .OnDelete(DeleteBehavior.Restrict); 22 | 23 | builder 24 | .HasMany(u => u.Friends) 25 | .WithOne(uf => uf.User) 26 | .HasForeignKey(uf => uf.UserId); 27 | 28 | builder 29 | .HasMany(u => u.OtherFriends) 30 | .WithOne(uf => uf.Friend) 31 | .HasForeignKey(uf => uf.FriendId); 32 | 33 | builder 34 | .HasMany(u => u.Photos) 35 | .WithOne(p => p.User) 36 | .HasForeignKey(p => p.UserId); 37 | 38 | builder 39 | .HasMany(u => u.Posts) 40 | .WithOne(p => p.User) 41 | .HasForeignKey(p => p.UserId); 42 | 43 | builder 44 | .HasMany(u => u.Comments) 45 | .WithOne(c => c.User) 46 | .HasForeignKey(c => c.UserId); 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /SocialNetwork.Data/Configurations/UserInterestConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 3 | using SocialNetwork.Data.Entities; 4 | 5 | namespace SocialNetwork.Data.Configurations 6 | { 7 | public class UserInterestConfiguration : IEntityTypeConfiguration 8 | { 9 | public void Configure(EntityTypeBuilder builder) 10 | { 11 | builder.HasKey(ui => new { ui.UserId, ui.InterestId }); 12 | 13 | builder 14 | .HasOne(ui => ui.User) 15 | .WithMany(u => u.Interests) 16 | .HasForeignKey(ui => ui.UserId); 17 | 18 | builder 19 | .HasOne(ui => ui.Interest) 20 | .WithMany(i => i.Users) 21 | .HasForeignKey(ui => ui.InterestId); 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /SocialNetwork.Data/DataConstants.cs: -------------------------------------------------------------------------------- 1 | namespace SocialNetwork.Data 2 | { 3 | public class DataConstants 4 | { 5 | public const int MaxPhotoLength = 5 * 1024 * 1024; 6 | public const int MaxMessageLength = 2000; 7 | public const int MaxInterestLength = 15; 8 | public const int MinInterestLength = 3; 9 | public const int MaxEventTitleLength = 30; 10 | public const int MaxUserAge = 130; 11 | public const int MinUserAge = 12; 12 | public const int NameMinLength = 2; 13 | public const int NameMaxLength = 50; 14 | } 15 | } -------------------------------------------------------------------------------- /SocialNetwork.Data/Entities/Comment.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel.DataAnnotations; 3 | 4 | namespace SocialNetwork.Data.Entities 5 | { 6 | public class Comment 7 | { 8 | public int Id { get; set; } 9 | 10 | [Required] 11 | public string Text { get; set; } 12 | 13 | public DateTime Date { get; set; } 14 | 15 | public string UserId { get; set; } 16 | 17 | public User User { get; set; } 18 | 19 | public int PostId { get; set; } 20 | 21 | public Post Post { get; set; } 22 | } 23 | } -------------------------------------------------------------------------------- /SocialNetwork.Data/Entities/Enums/Feeling.cs: -------------------------------------------------------------------------------- 1 | namespace SocialNetwork.Data.Entities.Enums 2 | { 3 | public enum Feeling 4 | { 5 | Happy = 0, 6 | Luky = 1, 7 | Great = 2, 8 | Dissapointed = 3, 9 | Miserable = 4 10 | } 11 | } -------------------------------------------------------------------------------- /SocialNetwork.Data/Entities/Enums/FriendRequestStatus.cs: -------------------------------------------------------------------------------- 1 | namespace SocialNetwork.Data.Entities.Enums 2 | { 3 | public enum FriendRequestStatus 4 | { 5 | Pending = 0, 6 | Accepted = 1, 7 | Declined = 2, 8 | Blocked = 3 9 | } 10 | } -------------------------------------------------------------------------------- /SocialNetwork.Data/Entities/Event.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | 5 | namespace SocialNetwork.Data.Entities 6 | { 7 | public class Event 8 | { 9 | public int Id { get; set; } 10 | 11 | [Url] 12 | public string ImageUrl { get; set; } 13 | 14 | [Required] 15 | [MaxLength(DataConstants.MaxEventTitleLength)] 16 | public string Title { get; set; } 17 | 18 | [Required] 19 | public string Location { get; set; } 20 | 21 | [Required] 22 | public string Description { get; set; } 23 | 24 | [Required] 25 | public DateTime DateStarts { get; set; } 26 | 27 | [Required] 28 | public DateTime DateEnds { get; set; } 29 | 30 | public ICollection Participants { get; set; } = new List(); 31 | } 32 | } -------------------------------------------------------------------------------- /SocialNetwork.Data/Entities/EventUser.cs: -------------------------------------------------------------------------------- 1 | namespace SocialNetwork.Data.Entities 2 | { 3 | public class EventUser 4 | { 5 | public string UserId { get; set; } 6 | 7 | public User User { get; set; } 8 | 9 | public int EventId { get; set; } 10 | 11 | public Event Event { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /SocialNetwork.Data/Entities/FriendRequest.cs: -------------------------------------------------------------------------------- 1 | using SocialNetwork.Data.Entities.Enums; 2 | using System.ComponentModel.DataAnnotations; 3 | 4 | namespace SocialNetwork.Data.Entities 5 | { 6 | public class FriendRequest 7 | { 8 | public string Id { get; set; } 9 | 10 | public string SenderId { get; set; } 11 | 12 | public User Sender { get; set; } 13 | 14 | public string ReceiverId { get; set; } 15 | 16 | public User Receiver { get; set; } 17 | 18 | [Required] 19 | public FriendRequestStatus FriendRequestStatus { get; set; } 20 | } 21 | } -------------------------------------------------------------------------------- /SocialNetwork.Data/Entities/Interest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.ComponentModel.DataAnnotations; 3 | 4 | namespace SocialNetwork.Data.Entities 5 | { 6 | public class Interest 7 | { 8 | public int Id { get; set; } 9 | 10 | [Required] 11 | [MaxLength(DataConstants.MaxInterestLength)] 12 | [MinLength(DataConstants.MinInterestLength)] 13 | public string Tag { get; set; } 14 | 15 | public ICollection Users { get; set; } = new List(); 16 | } 17 | } -------------------------------------------------------------------------------- /SocialNetwork.Data/Entities/Message.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel.DataAnnotations; 3 | 4 | namespace SocialNetwork.Data.Entities 5 | { 6 | public class Message 7 | { 8 | public int Id { get; set; } 9 | 10 | [Required] 11 | public string SenderId { get; set; } 12 | 13 | [Required] 14 | public User Sender { get; set; } 15 | 16 | [Required] 17 | public string ReceiverId { get; set; } 18 | 19 | [Required] 20 | public User Receiver { get; set; } 21 | 22 | [Required] 23 | [MaxLength(DataConstants.MaxMessageLength)] 24 | public string MessageText { get; set; } 25 | 26 | [Required] 27 | public DateTime DateSent { get; set; } 28 | 29 | public bool IsSeen { get; set; } 30 | } 31 | } -------------------------------------------------------------------------------- /SocialNetwork.Data/Entities/Photo.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace SocialNetwork.Data.Entities 4 | { 5 | public class Photo 6 | { 7 | public int Id { get; set; } 8 | 9 | [Required] 10 | [MaxLength(DataConstants.MaxPhotoLength)] 11 | public byte[] PhotoAsBytes { get; set; } 12 | 13 | public string UserId { get; set; } 14 | 15 | public User User { get; set; } 16 | 17 | public int? PostId { get; set; } 18 | 19 | public Post Post { get; set; } 20 | 21 | public bool IsProfilePicture { get; set; } 22 | } 23 | } -------------------------------------------------------------------------------- /SocialNetwork.Data/Entities/Post.cs: -------------------------------------------------------------------------------- 1 | using SocialNetwork.Data.Entities.Enums; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.ComponentModel.DataAnnotations; 5 | 6 | namespace SocialNetwork.Data.Entities 7 | { 8 | public class Post 9 | { 10 | public int Id { get; set; } 11 | 12 | [Required] 13 | public string Text { get; set; } 14 | 15 | public DateTime Date { get; set; } 16 | 17 | [Range(0, int.MaxValue)] 18 | public int Likes { get; set; } 19 | 20 | public byte[] Photo { get; set; } 21 | 22 | public string UserId { get; set; } 23 | 24 | public User User { get; set; } 25 | 26 | public Feeling Feeling { get; set; } 27 | 28 | public IEnumerable Comments { get; set; } = new List(); 29 | } 30 | } -------------------------------------------------------------------------------- /SocialNetwork.Data/Entities/User.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Identity; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | 5 | namespace SocialNetwork.Data.Entities 6 | { 7 | public class User : IdentityUser 8 | { 9 | [MinLength(DataConstants.NameMinLength), MaxLength(DataConstants.NameMaxLength)] 10 | public string FirstName { get; set; } 11 | 12 | [MinLength(DataConstants.NameMinLength), MaxLength(DataConstants.NameMaxLength)] 13 | public string LastName { get; set; } 14 | 15 | [Required] 16 | [Range(DataConstants.MinUserAge, DataConstants.MaxUserAge)] 17 | public int Age { get; set; } 18 | 19 | public bool IsDeleted { get; set; } = false; 20 | 21 | public IEnumerable Photos { get; set; } = new List(); 22 | 23 | [Required] 24 | [MaxLength(DataConstants.MaxPhotoLength)] 25 | public byte[] ProfilePicture { get; set; } 26 | 27 | public ICollection Posts { get; set; } = new List(); 28 | 29 | public ICollection Comments { get; set; } = new List(); 30 | 31 | public ICollection FriendRequestSent { get; set; } = new List(); 32 | 33 | public ICollection FriendRequestReceived { get; set; } = new List(); 34 | 35 | public ICollection MessagesSent { get; set; } = new List(); 36 | 37 | public ICollection MessagesReceived { get; set; } = new List(); 38 | 39 | public ICollection Friends { get; set; } = new List(); 40 | 41 | public ICollection OtherFriends { get; set; } = new List(); 42 | 43 | public ICollection Interests { get; set; } = new List(); 44 | 45 | public ICollection Events { get; set; } = new List(); 46 | } 47 | } -------------------------------------------------------------------------------- /SocialNetwork.Data/Entities/UserFriend.cs: -------------------------------------------------------------------------------- 1 | namespace SocialNetwork.Data.Entities 2 | { 3 | public class UserFriend 4 | { 5 | public string Id { get; set; } 6 | 7 | public string UserId { get; set; } 8 | 9 | public User User { get; set; } 10 | 11 | public string FriendId { get; set; } 12 | 13 | public User Friend { get; set; } 14 | } 15 | } -------------------------------------------------------------------------------- /SocialNetwork.Data/Entities/UserInterest.cs: -------------------------------------------------------------------------------- 1 | namespace SocialNetwork.Data.Entities 2 | { 3 | public class UserInterest 4 | { 5 | public int InterestId { get; set; } 6 | 7 | public Interest Interest { get; set; } 8 | 9 | public string UserId { get; set; } 10 | 11 | public User User { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /SocialNetwork.Data/Migrations/20171218201559_Messages.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore.Metadata; 2 | using Microsoft.EntityFrameworkCore.Migrations; 3 | using System; 4 | using System.Collections.Generic; 5 | 6 | namespace SocialNetwork.Data.Migrations 7 | { 8 | public partial class Messages : Migration 9 | { 10 | protected override void Up(MigrationBuilder migrationBuilder) 11 | { 12 | migrationBuilder.CreateTable( 13 | name: "Message", 14 | columns: table => new 15 | { 16 | Id = table.Column(nullable: false) 17 | .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), 18 | DateSent = table.Column(nullable: false), 19 | IsSeen = table.Column(nullable: false), 20 | MessageText = table.Column(maxLength: 2000, nullable: false), 21 | ReceiverId = table.Column(nullable: false), 22 | SenderId = table.Column(nullable: false) 23 | }, 24 | constraints: table => 25 | { 26 | table.PrimaryKey("PK_Message", x => x.Id); 27 | table.ForeignKey( 28 | name: "FK_Message_AspNetUsers_ReceiverId", 29 | column: x => x.ReceiverId, 30 | principalTable: "AspNetUsers", 31 | principalColumn: "Id", 32 | onDelete: ReferentialAction.Restrict); 33 | table.ForeignKey( 34 | name: "FK_Message_AspNetUsers_SenderId", 35 | column: x => x.SenderId, 36 | principalTable: "AspNetUsers", 37 | principalColumn: "Id", 38 | onDelete: ReferentialAction.Restrict); 39 | }); 40 | 41 | migrationBuilder.CreateIndex( 42 | name: "IX_Message_ReceiverId", 43 | table: "Message", 44 | column: "ReceiverId"); 45 | 46 | migrationBuilder.CreateIndex( 47 | name: "IX_Message_SenderId", 48 | table: "Message", 49 | column: "SenderId"); 50 | } 51 | 52 | protected override void Down(MigrationBuilder migrationBuilder) 53 | { 54 | migrationBuilder.DropTable( 55 | name: "Message"); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /SocialNetwork.Data/SocialNetwork.Data.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp2.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /SocialNetwork.Data/SocialNetworkDbContext.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Identity.EntityFrameworkCore; 2 | using Microsoft.EntityFrameworkCore; 3 | using SocialNetwork.Data.Configurations; 4 | using SocialNetwork.Data.Entities; 5 | 6 | namespace SocialNetwork.Data 7 | { 8 | public class SocialNetworkDbContext : IdentityDbContext 9 | { 10 | public DbSet Photos { get; set; } 11 | 12 | public DbSet Posts { get; set; } 13 | 14 | public DbSet Comments { get; set; } 15 | 16 | public DbSet FriendRequests { get; set; } 17 | 18 | public DbSet UserFriend { get; set; } 19 | 20 | public DbSet Messages { get; set; } 21 | 22 | public DbSet Events { get; set; } 23 | 24 | public DbSet Interests { get; set; } 25 | 26 | public SocialNetworkDbContext(DbContextOptions options) 27 | : base(options) 28 | { 29 | } 30 | 31 | protected override void OnModelCreating(ModelBuilder builder) 32 | { 33 | builder.ApplyConfiguration(new UserConfiguration()); 34 | builder.ApplyConfiguration(new FriendRequestConfiguration()); 35 | builder.ApplyConfiguration(new UserInterestConfiguration()); 36 | builder.ApplyConfiguration(new EventUserConfiguration()); 37 | builder.ApplyConfiguration(new PostConfiguration()); 38 | 39 | base.OnModelCreating(builder); 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /SocialNetwork.Services/ICommentService.cs: -------------------------------------------------------------------------------- 1 | using SocialNetwork.Services.Models; 2 | using System.Collections.Generic; 3 | 4 | namespace SocialNetwork.Services 5 | { 6 | public interface ICommentService : IService 7 | { 8 | void Create(string commentText, string userId, int postId); 9 | 10 | void DeleteCommentsByPostId(int postId); 11 | 12 | IEnumerable CommentsByPostId(int postId); 13 | } 14 | } -------------------------------------------------------------------------------- /SocialNetwork.Services/IEmailSender.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | namespace SocialNetwork.Services 4 | { 5 | public interface IEmailSender : IService 6 | { 7 | Task SendEmailAsync(string email, string subject, string message); 8 | } 9 | } -------------------------------------------------------------------------------- /SocialNetwork.Services/IEventService.cs: -------------------------------------------------------------------------------- 1 | using SocialNetwork.Services.Models; 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | namespace SocialNetwork.Services 6 | { 7 | public interface IEventService : IService 8 | { 9 | void Create(string imageUrl, string title, string location, string description, DateTime dateStarts, DateTime dateEnds, string creatorId); 10 | 11 | bool Exists(int id); 12 | 13 | EventModel Details(int id); 14 | 15 | IEnumerable UpcomingThreeEvents(); 16 | 17 | void AddUserToEvent(string userId, int eventId); 18 | } 19 | } -------------------------------------------------------------------------------- /SocialNetwork.Services/IFriendRequestService.cs: -------------------------------------------------------------------------------- 1 | namespace SocialNetwork.Services 2 | { 3 | public interface IFriendRequestService : IService 4 | { 5 | void Create(string senderId, string receiverId); 6 | 7 | void Accept(string senderId, string receiverId); 8 | 9 | void Delete(string senderId, string receiverId); 10 | 11 | void Decline(string senderId, string receiverId); 12 | 13 | bool Exists(string senderId, string receiverId); 14 | } 15 | } -------------------------------------------------------------------------------- /SocialNetwork.Services/IMessangerService.cs: -------------------------------------------------------------------------------- 1 | using SocialNetwork.Services.Infrastructure.CustomDataStructures; 2 | using SocialNetwork.Services.Models; 3 | 4 | namespace SocialNetwork.Services 5 | { 6 | public interface IMessangerService : IService 7 | { 8 | void Create(string senderId, string receiverId, string text); 9 | 10 | PaginatedList AllByUserIds(string userId, string otherUserId, int pageIndex, int pageSize); 11 | } 12 | } -------------------------------------------------------------------------------- /SocialNetwork.Services/IPhotoService.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Http; 2 | 3 | namespace SocialNetwork.Services 4 | { 5 | public interface IPhotoService : IService 6 | { 7 | int Create(IFormFile photo, string userId); 8 | 9 | bool PhotoExists(int photoId); 10 | 11 | byte[] PhotoAsBytes(IFormFile photo); 12 | } 13 | } -------------------------------------------------------------------------------- /SocialNetwork.Services/IPostService.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Http; 2 | using SocialNetwork.Data.Entities.Enums; 3 | using SocialNetwork.Services.Infrastructure.CustomDataStructures; 4 | using SocialNetwork.Services.Models; 5 | 6 | namespace SocialNetwork.Services 7 | { 8 | public interface IPostService : IService 9 | { 10 | void Create(string userId, Feeling feeling, string text, IFormFile photo); 11 | 12 | void Edit(int postId, Feeling feeling, string text, IFormFile photo); 13 | 14 | bool Exists(int id); 15 | 16 | bool UserIsAuthorizedToEdit(int postId, string userId); 17 | 18 | PaginatedList PostsByUserId(string userId, int pageIndex, int pageSize); 19 | 20 | PaginatedList FriendPostsByUserId(string userId, int pageIndex, int pageSize); 21 | 22 | PostModel PostById(int postId); 23 | 24 | void Delete(int postId); 25 | 26 | void Like(int postId); 27 | } 28 | } -------------------------------------------------------------------------------- /SocialNetwork.Services/IService.cs: -------------------------------------------------------------------------------- 1 | namespace SocialNetwork.Services 2 | { 3 | public interface IService 4 | { 5 | } 6 | } -------------------------------------------------------------------------------- /SocialNetwork.Services/IUserService.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Http; 2 | using SocialNetwork.Services.Infrastructure.CustomDataStructures; 3 | using SocialNetwork.Services.Models; 4 | using System.Collections.Generic; 5 | 6 | namespace SocialNetwork.Services 7 | { 8 | public interface IUserService : IService 9 | { 10 | UserModel GetById(string id); 11 | 12 | void AddProfilePicture(IFormFile photo, string userId); 13 | 14 | bool UserExists(string userId); 15 | 16 | UserAccountModel UserDetails(string userId, int pageIndex, int pageSize); 17 | 18 | UserAccountModel UserDetailsFriendsCommentsAndPosts(string userId, int pageIndex, int pageSize); 19 | 20 | bool CheckIfFriends(string requestUserId, string targetUserId); 21 | 22 | bool CheckIfDeleted(string userId); 23 | 24 | bool CheckIfDeletedByUserName(string username); 25 | 26 | void MakeFriends(string senderId, string receiverId); 27 | 28 | PaginatedList UsersBySearchTerm(string searchTerm, int pageIndex, int pageSize); 29 | 30 | PaginatedList All(int pageIndex, int pageSize); 31 | 32 | object GetUserFullName(string id); 33 | 34 | void EditUser(string id, string firstName, string lastName, int age, string email, string username); 35 | 36 | void DeleteUser(string id); 37 | 38 | List FriendsIds(string userId); 39 | } 40 | } -------------------------------------------------------------------------------- /SocialNetwork.Services/Implementations/CommentService.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper.QueryableExtensions; 2 | using SocialNetwork.Data; 3 | using SocialNetwork.Data.Entities; 4 | using SocialNetwork.Services.Models; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | 9 | namespace SocialNetwork.Services.Implementations 10 | { 11 | public class CommentService : ICommentService 12 | { 13 | private readonly SocialNetworkDbContext db; 14 | 15 | public CommentService(SocialNetworkDbContext db) 16 | { 17 | this.db = db; 18 | } 19 | 20 | public IEnumerable CommentsByPostId(int postId) 21 | { 22 | //TO DO - implement some paging in case there are many comments 23 | return this.db.Comments.Where(c => c.PostId == postId).OrderByDescending(c => c.Date).ProjectTo().ToList(); 24 | } 25 | 26 | public void Create(string commentText, string userId, int postId) 27 | { 28 | var comment = new Comment 29 | { 30 | Date = DateTime.UtcNow, 31 | Text = commentText, 32 | UserId = userId, 33 | PostId = postId 34 | }; 35 | 36 | this.db.Comments.Add(comment); 37 | this.db.SaveChanges(); 38 | } 39 | 40 | public void DeleteCommentsByPostId(int postId) 41 | { 42 | var comments = this.db.Comments.Where(c => c.PostId == postId); 43 | 44 | foreach (var comment in comments) 45 | { 46 | this.db.Remove(comment); 47 | } 48 | 49 | this.db.SaveChanges(); 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /SocialNetwork.Services/Implementations/EmailSender.cs: -------------------------------------------------------------------------------- 1 | using System.Net; 2 | using System.Net.Mail; 3 | using System.Threading.Tasks; 4 | 5 | namespace SocialNetwork.Services 6 | { 7 | // This class is used by the application to send email for account confirmation and password reset. 8 | // For more details see https://go.microsoft.com/fwlink/?LinkID=532713 9 | public class EmailSender : IEmailSender 10 | { 11 | public const string ApplicationName = "Social Network"; 12 | public const string ApplicationEmail = "lavishstory@gmail.com"; 13 | public const string ApplicationEmailPassword = "Lavishstory123"; 14 | public const string GmailSmtp = "smtp.gmail.com"; 15 | public const int Port = 587; 16 | 17 | public async Task SendEmailAsync(string email, string subject, string message) 18 | { 19 | using (var client = new SmtpClient(GmailSmtp, Port)) // netstat -l/a ... for checking available ports 20 | { 21 | client.EnableSsl = true; 22 | client.UseDefaultCredentials = false; 23 | client.Credentials = new NetworkCredential(ApplicationEmail, ApplicationEmailPassword); 24 | 25 | var mailMessage = new MailMessage(); 26 | mailMessage.To.Add(email); 27 | mailMessage.From = new MailAddress(ApplicationEmail, ApplicationName); 28 | mailMessage.Subject = subject; 29 | mailMessage.Body = message; 30 | mailMessage.IsBodyHtml = false; 31 | 32 | await client.SendMailAsync(mailMessage); 33 | } 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /SocialNetwork.Services/Implementations/EventService.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using AutoMapper.QueryableExtensions; 3 | using Microsoft.EntityFrameworkCore; 4 | using SocialNetwork.Data; 5 | using SocialNetwork.Data.Entities; 6 | using SocialNetwork.Services.Models; 7 | using System; 8 | using System.Collections.Generic; 9 | using System.Linq; 10 | 11 | namespace SocialNetwork.Services.Implementations 12 | { 13 | public class EventService : IEventService 14 | { 15 | private readonly SocialNetworkDbContext db; 16 | 17 | public EventService(SocialNetworkDbContext db) 18 | { 19 | this.db = db; 20 | } 21 | 22 | public void AddUserToEvent(string userId, int eventId) 23 | { 24 | if (this.Exists(eventId)) 25 | { 26 | var ev = this.db.Events 27 | .Include(e => e.Participants) 28 | .FirstOrDefault(e => e.Id == eventId); 29 | 30 | if (!ev.Participants.Any(p => p.UserId == userId)) 31 | { 32 | ev.Participants.Add(new EventUser 33 | { 34 | UserId = userId 35 | }); 36 | } 37 | 38 | this.db.SaveChanges(); 39 | } 40 | } 41 | 42 | public void Create(string imageUrl, string title, string location, string description, DateTime dateStarts, DateTime dateEnds, string creatorId) 43 | { 44 | var ev = new Event 45 | { 46 | ImageUrl = imageUrl, 47 | Title = title, 48 | Location = location, 49 | Description = description, 50 | DateEnds = dateEnds, 51 | DateStarts = dateStarts 52 | }; 53 | ev.Participants.Add(new EventUser { UserId = creatorId }); 54 | 55 | this.db.Events.Add(ev); 56 | this.db.SaveChanges(); 57 | } 58 | 59 | public EventModel Details(int id) 60 | { 61 | if (this.Exists(id)) 62 | { 63 | var ev = this.db.Events 64 | .Include(e => e.Participants) 65 | .FirstOrDefault(e => e.Id == id); 66 | 67 | return Mapper.Map(ev); 68 | } 69 | 70 | return null; 71 | } 72 | 73 | public bool Exists(int id) => this.db.Events.Any(e => e.Id == id); 74 | 75 | public IEnumerable UpcomingThreeEvents() 76 | { 77 | return this.db.Events.Where(e => e.DateEnds < DateTime.UtcNow).OrderBy(e => e.DateStarts).Take(3).ProjectTo().ToList(); 78 | } 79 | } 80 | } -------------------------------------------------------------------------------- /SocialNetwork.Services/Implementations/FriendRequestService.cs: -------------------------------------------------------------------------------- 1 | using SocialNetwork.Data; 2 | using SocialNetwork.Data.Entities; 3 | using SocialNetwork.Data.Entities.Enums; 4 | using System.Linq; 5 | 6 | namespace SocialNetwork.Services.Implementations 7 | { 8 | public class FriendRequestService : IFriendRequestService 9 | { 10 | private readonly SocialNetworkDbContext db; 11 | private readonly IUserService userService; 12 | 13 | public FriendRequestService(SocialNetworkDbContext db, IUserService userService) 14 | { 15 | this.db = db; 16 | this.userService = userService; 17 | } 18 | 19 | public void Accept(string senderId, string receiverId) 20 | { 21 | if (this.Exists(senderId, receiverId) && this.userService.UserExists(senderId) && this.userService.UserExists(receiverId)) 22 | { 23 | var friendRequest = db.FriendRequests.FirstOrDefault(fr => fr.ReceiverId == receiverId && fr.SenderId == senderId); 24 | friendRequest.FriendRequestStatus = FriendRequestStatus.Accepted; 25 | this.userService.MakeFriends(senderId, receiverId); 26 | this.db.SaveChanges(); 27 | } 28 | } 29 | 30 | public void Create(string senderId, string receiverId) 31 | { 32 | if (!this.Exists(senderId, receiverId) && this.userService.UserExists(senderId) && this.userService.UserExists(receiverId)) 33 | { 34 | var friendRequest = new FriendRequest 35 | { 36 | SenderId = senderId, 37 | ReceiverId = receiverId, 38 | FriendRequestStatus = FriendRequestStatus.Pending 39 | }; 40 | 41 | this.db.FriendRequests.Add(friendRequest); 42 | this.db.SaveChanges(); 43 | } 44 | } 45 | 46 | public void Decline(string senderId, string receiverId) 47 | { 48 | if (this.Exists(senderId, receiverId) && this.userService.UserExists(senderId) && this.userService.UserExists(receiverId)) 49 | { 50 | var friendRequest = db.FriendRequests.FirstOrDefault(fr => fr.ReceiverId == receiverId && fr.SenderId == senderId); 51 | this.db.Remove(friendRequest); 52 | this.db.SaveChanges(); 53 | } 54 | } 55 | 56 | public void Delete(string senderId, string receiverId) 57 | { 58 | throw new System.NotImplementedException(); 59 | } 60 | 61 | public bool Exists(string senderId, string receiverId) => 62 | this.db.FriendRequests.Any(fr => fr.SenderId == senderId && fr.ReceiverId == receiverId); 63 | } 64 | } -------------------------------------------------------------------------------- /SocialNetwork.Services/Implementations/MessangerService.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper.QueryableExtensions; 2 | using Microsoft.EntityFrameworkCore; 3 | using SocialNetwork.Data; 4 | using SocialNetwork.Data.Entities; 5 | using SocialNetwork.Services.Infrastructure.CustomDataStructures; 6 | using SocialNetwork.Services.Models; 7 | using System; 8 | using System.Collections.Generic; 9 | using System.Linq; 10 | 11 | namespace SocialNetwork.Services.Implementations 12 | { 13 | public class MessangerService : IMessangerService 14 | { 15 | private readonly SocialNetworkDbContext db; 16 | 17 | public MessangerService(SocialNetworkDbContext db) 18 | { 19 | this.db = db; 20 | } 21 | 22 | public List All() 23 | { 24 | return this.db 25 | .Messages 26 | .ProjectTo() 27 | .ToList(); 28 | } 29 | 30 | public PaginatedList AllByUserIds(string userId, string otherUserId, int pageIndex, int pageSize) 31 | { 32 | var messages = this.db 33 | .Messages 34 | .Where(m => (m.SenderId == userId && m.ReceiverId == otherUserId) || (m.SenderId == otherUserId && m.ReceiverId == userId)) 35 | .OrderBy(m => m.DateSent) 36 | .ProjectTo(); 37 | 38 | return messages != null ? PaginatedList.Create(messages.AsNoTracking(), pageIndex, pageSize) : null; 39 | } 40 | 41 | public void Create(string senderId, string receiverId, string text) 42 | { 43 | var message = new Message 44 | { 45 | SenderId = senderId, 46 | ReceiverId = receiverId, 47 | DateSent = DateTime.UtcNow, 48 | IsSeen = false, 49 | MessageText = text 50 | }; 51 | 52 | this.db.Add(message); 53 | this.db.SaveChanges(); 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /SocialNetwork.Services/Implementations/PhotoService.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Http; 2 | using SocialNetwork.Data; 3 | using SocialNetwork.Data.Entities; 4 | using System.IO; 5 | using System.Linq; 6 | 7 | namespace SocialNetwork.Services.Implementations 8 | { 9 | public class PhotoService : IPhotoService 10 | { 11 | private readonly SocialNetworkDbContext db; 12 | 13 | public PhotoService(SocialNetworkDbContext db) 14 | { 15 | this.db = db; 16 | } 17 | 18 | public int Create(IFormFile photo, string userId) 19 | { 20 | using (var memoryStream = new MemoryStream()) 21 | { 22 | photo.CopyTo(memoryStream); 23 | 24 | var instanceOfPhoto = new Photo 25 | { 26 | IsProfilePicture = false, 27 | PhotoAsBytes = memoryStream.ToArray(), 28 | UserId = userId 29 | }; 30 | 31 | db.Photos.Add(instanceOfPhoto); 32 | db.SaveChanges(); 33 | 34 | return instanceOfPhoto.Id; 35 | } 36 | } 37 | 38 | public byte[] PhotoAsBytes(IFormFile photo) 39 | { 40 | byte[] photoAsBytes; 41 | 42 | using (var memoryStream = new MemoryStream()) 43 | { 44 | photo.CopyTo(memoryStream); 45 | photoAsBytes = memoryStream.ToArray(); 46 | }; 47 | 48 | return photoAsBytes; 49 | } 50 | 51 | public bool PhotoExists(int photoId) => this.db.Photos.Any(p => p.Id == photoId); 52 | } 53 | } -------------------------------------------------------------------------------- /SocialNetwork.Services/Infrastructure/CustomDataStructures/PaginatedList.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace SocialNetwork.Services.Infrastructure.CustomDataStructures 6 | { 7 | public class PaginatedList : List 8 | { 9 | public int PageIndex { get; private set; } 10 | public int TotalPages { get; private set; } 11 | 12 | public PaginatedList(List items, int count, int pageIndex, int pageSize) 13 | { 14 | PageIndex = pageIndex; 15 | TotalPages = (int)Math.Ceiling(count / (double)pageSize); 16 | 17 | this.AddRange(items); 18 | } 19 | 20 | public bool HasPreviousPage => (PageIndex > 1); 21 | 22 | public bool HasNextPage => (PageIndex < TotalPages); 23 | 24 | public static PaginatedList Create(IQueryable source, int pageIndex, int pageSize) 25 | { 26 | var count = source.Count(); 27 | var items = source.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList(); 28 | return new PaginatedList(items, count, pageIndex, pageSize); 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /SocialNetwork.Services/Infrastructure/ServiceConstants.cs: -------------------------------------------------------------------------------- 1 | namespace SocialNetwork.Services.Infrastructure 2 | { 3 | public class ServiceConstants 4 | { 5 | public const string ImageRenderBaseString = "data:image; base64,"; 6 | public const string AdminUserName = "Administrator"; 7 | } 8 | } -------------------------------------------------------------------------------- /SocialNetwork.Services/Models/CommentModel.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using SocialNetwork.Common.Mapping; 3 | using SocialNetwork.Data.Entities; 4 | using System; 5 | 6 | namespace SocialNetwork.Services.Models 7 | { 8 | public class CommentModel : IMapFrom, IHaveCustomMapping 9 | { 10 | public int Id { get; set; } 11 | 12 | public string Text { get; set; } 13 | 14 | public DateTime Date { get; set; } 15 | 16 | public string UserId { get; set; } 17 | 18 | public string UserFullName { get; set; } 19 | 20 | public int PostId { get; set; } 21 | 22 | public byte[] UserProfilePicture { get; set; } 23 | 24 | public void ConfigureMapping(Profile profile) 25 | { 26 | profile.CreateMap() 27 | .ForMember(c => c.UserProfilePicture, cfg => cfg.MapFrom(c => c.User.ProfilePicture)) 28 | .ForMember(c => c.UserFullName, cfg => cfg.MapFrom(c => c.User.FirstName + " " + c.User.LastName)); 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /SocialNetwork.Services/Models/EventModel.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using SocialNetwork.Common.Mapping; 3 | using SocialNetwork.Data.Entities; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | 8 | namespace SocialNetwork.Services.Models 9 | { 10 | public class EventModel : IMapFrom, IHaveCustomMapping 11 | { 12 | public int Id { get; set; } 13 | 14 | public string ImageUrl { get; set; } 15 | 16 | public string Title { get; set; } 17 | 18 | public string Location { get; set; } 19 | 20 | public string Description { get; set; } 21 | 22 | public DateTime DateStarts { get; set; } 23 | 24 | public DateTime DateEnds { get; set; } 25 | 26 | public int ParticipantsCount { get; set; } 27 | 28 | public List ParticipantId { get; set; } = new List(); 29 | 30 | public void ConfigureMapping(Profile profile) 31 | { 32 | profile.CreateMap() 33 | .ForMember(e => e.ParticipantId, cfg => 34 | cfg.MapFrom(e => e.Participants.Select(p => p.UserId).ToList())) 35 | .ForMember(e => e.ParticipantsCount, cfg => cfg.MapFrom(e => e.Participants.Count)); 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /SocialNetwork.Services/Models/MessageModel.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using SocialNetwork.Common.Mapping; 3 | using SocialNetwork.Data.Entities; 4 | using System; 5 | 6 | namespace SocialNetwork.Services.Models 7 | { 8 | public class MessageModel : IMapFrom, IHaveCustomMapping 9 | { 10 | public string SenderId { get; set; } 11 | 12 | public string MessageText { get; set; } 13 | 14 | public DateTime DateSent { get; set; } 15 | 16 | public bool IsSeen { get; set; } 17 | 18 | public string SenderFullName { get; set; } 19 | 20 | public void ConfigureMapping(Profile profile) 21 | { 22 | profile.CreateMap() 23 | .ForMember(m => m.SenderFullName, cfg => cfg.MapFrom(m => m.Sender.FirstName + " " + m.Sender.LastName)); 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /SocialNetwork.Services/Models/PostModel.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using SocialNetwork.Common.Mapping; 3 | using SocialNetwork.Data.Entities; 4 | using SocialNetwork.Data.Entities.Enums; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | 9 | namespace SocialNetwork.Services.Models 10 | { 11 | public class PostModel : IMapFrom, IHaveCustomMapping 12 | { 13 | public int Id { get; set; } 14 | 15 | public string Text { get; set; } 16 | 17 | public DateTime Date { get; set; } 18 | 19 | public int Likes { get; set; } 20 | 21 | public byte[] Photo { get; set; } 22 | 23 | public byte[] UserProfilePicture { get; set; } 24 | 25 | public string UserId { get; set; } 26 | 27 | public string UserFullName { get; set; } 28 | 29 | public Feeling Feeling { get; set; } 30 | 31 | public IEnumerable Comments { get; set; } = new List(); 32 | 33 | public void ConfigureMapping(Profile profile) 34 | { 35 | profile.CreateMap() 36 | .ForMember(p => p.UserProfilePicture, cfg => cfg.MapFrom(p => p.User.ProfilePicture)) 37 | .ForMember(p => p.UserFullName, cfg => cfg.MapFrom(p => p.User.FirstName + " " + p.User.LastName)) 38 | .ForMember(p => p.Comments, cfg => cfg.MapFrom(p => Mapper.Map>(p.Comments))); 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /SocialNetwork.Services/Models/ReceivedFriendRequestModel.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using SocialNetwork.Common.Mapping; 3 | using SocialNetwork.Data.Entities; 4 | using SocialNetwork.Data.Entities.Enums; 5 | 6 | namespace SocialNetwork.Services.Models 7 | { 8 | public class ReceivedFriendRequestModel : IMapFrom, IHaveCustomMapping 9 | { 10 | public string Id { get; set; } 11 | 12 | public string SenderId { get; set; } 13 | 14 | public string SenderFullName { get; set; } 15 | 16 | public FriendRequestStatus FriendRequestStatus { get; set; } 17 | 18 | public void ConfigureMapping(Profile profile) 19 | { 20 | profile.CreateMap() 21 | .ForMember(f => f.SenderFullName, cfg => cfg.MapFrom(f => f.Sender.FirstName + " " + f.Sender.LastName)); 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /SocialNetwork.Services/Models/SentFriendRequestModel.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using SocialNetwork.Common.Mapping; 3 | using SocialNetwork.Data.Entities; 4 | using SocialNetwork.Data.Entities.Enums; 5 | 6 | namespace SocialNetwork.Services.Models 7 | { 8 | public class SentFriendRequestModel : IMapFrom, IHaveCustomMapping 9 | { 10 | public string Id { get; set; } 11 | 12 | public string ReceiverId { get; set; } 13 | 14 | public string ReceiverFullName { get; set; } 15 | 16 | public FriendRequestStatus FriendRequestStatus { get; set; } 17 | 18 | public void ConfigureMapping(Profile profile) 19 | { 20 | profile.CreateMap() 21 | .ForMember(f => f.ReceiverFullName, cfg => cfg.MapFrom(f => f.Receiver.FirstName + " " + f.Receiver.LastName)); 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /SocialNetwork.Services/Models/UserAccountModel.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using SocialNetwork.Common.Mapping; 3 | using SocialNetwork.Data.Entities; 4 | using SocialNetwork.Services.Infrastructure.CustomDataStructures; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | 8 | namespace SocialNetwork.Services.Models 9 | { 10 | public class UserAccountModel : IMapFrom, IHaveCustomMapping 11 | { 12 | public string Id { get; set; } 13 | 14 | public string FirstName { get; set; } 15 | 16 | public string LastName { get; set; } 17 | 18 | public int Age { get; set; } 19 | 20 | public byte[] ProfilePicture { get; set; } 21 | 22 | public PaginatedList Posts { get; set; } = null; 23 | 24 | public IEnumerable FriendRequestReceived { get; set; } = new List(); 25 | 26 | public IEnumerable FriendRequestSent { get; set; } = new List(); 27 | 28 | public IEnumerable Friends { get; set; } = new List(); 29 | 30 | public IEnumerable Events { get; set; } = new List(); 31 | 32 | public IEnumerable Interests { get; set; } = new List(); 33 | 34 | public void ConfigureMapping(Profile profile) 35 | { 36 | profile.CreateMap() 37 | .ForMember(u => u.Posts, cfg => cfg.Ignore()) 38 | .ForMember(u => u.Friends, cfg => cfg.Ignore()) 39 | .ForMember(u => u.Interests, cfg => cfg.MapFrom(u => u.Interests.Select(i => i.Interest.Tag).ToList())); 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /SocialNetwork.Services/Models/UserListModel.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using SocialNetwork.Common.Mapping; 3 | using SocialNetwork.Data.Entities; 4 | 5 | namespace SocialNetwork.Services.Models 6 | { 7 | public class UserListModel : IMapFrom, IHaveCustomMapping 8 | { 9 | public string Id { get; set; } 10 | 11 | public string FullName { get; set; } 12 | 13 | public int Age { get; set; } 14 | 15 | public int NumberOfPosts { get; set; } 16 | 17 | public byte[] ProfilePicture { get; set; } 18 | 19 | public void ConfigureMapping(Profile profile) 20 | { 21 | profile.CreateMap() 22 | .ForMember(u => u.FullName, cfg => cfg.MapFrom(u => u.FirstName + " " + u.LastName)) 23 | .ForMember(u => u.NumberOfPosts, cfg => cfg.MapFrom(u => u.Posts.Count)); 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /SocialNetwork.Services/Models/UserModel.cs: -------------------------------------------------------------------------------- 1 | using SocialNetwork.Common.Mapping; 2 | using SocialNetwork.Data.Entities; 3 | 4 | namespace SocialNetwork.Services.Models 5 | { 6 | public class UserModel : IMapFrom 7 | { 8 | public string Email { get; set; } 9 | 10 | public string FirstName { get; set; } 11 | 12 | public string LastName { get; set; } 13 | 14 | public string Username { get; set; } 15 | 16 | public int Age { get; set; } 17 | } 18 | } -------------------------------------------------------------------------------- /SocialNetwork.Services/SocialNetwork.Services.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp2.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /SocialNetwork.Tests/Common/Initializer.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using SocialNetwork.Web.Infrastructure.Mapping; 3 | 4 | namespace SocialNetwork.Tests.Common 5 | { 6 | public static class Initializer 7 | { 8 | public static void IniializeAuttoMapper() 9 | { 10 | Mapper.Initialize(cfg => cfg.AddProfile()); 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /SocialNetwork.Tests/Mocks/MockCreator.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using Moq; 3 | using SocialNetwork.Data; 4 | using SocialNetwork.Services.Implementations; 5 | using System; 6 | 7 | namespace SocialNetwork.Tests.Mocks 8 | { 9 | public class MockCreator 10 | { 11 | public static SocialNetworkDbContext GetDb() 12 | { 13 | var dbOptions = new DbContextOptionsBuilder() 14 | .UseInMemoryDatabase(Guid.NewGuid().ToString()) 15 | .Options; 16 | 17 | return new SocialNetworkDbContext(dbOptions); 18 | } 19 | 20 | public static Mock UserServiceMock() 21 | { 22 | return new Mock(GetDb(), null, null, null); 23 | } 24 | 25 | public static Mock PostServiceMock() 26 | { 27 | return new Mock(GetDb(), null, null); 28 | } 29 | 30 | public static Mock CommentServiceMock() 31 | { 32 | return new Mock(GetDb()); 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /SocialNetwork.Tests/Services/MessangerServiceTest.cs: -------------------------------------------------------------------------------- 1 | using FluentAssertions; 2 | using Microsoft.EntityFrameworkCore; 3 | using SocialNetwork.Data; 4 | using SocialNetwork.Data.Entities; 5 | using SocialNetwork.Services.Implementations; 6 | using SocialNetwork.Services.Infrastructure.CustomDataStructures; 7 | using SocialNetwork.Services.Models; 8 | using SocialNetwork.Tests.Common; 9 | using System; 10 | using System.Collections.Generic; 11 | using Xunit; 12 | 13 | namespace SocialNetwork.Tests.Services 14 | { 15 | public class MessangerServiceTest 16 | { 17 | [Fact] 18 | public void CheckIfReturnsAllMessagesByUserId() 19 | { 20 | const string UserId = "1"; 21 | const string OtherUserId = "2"; 22 | 23 | //Arrange 24 | Initializer.IniializeAuttoMapper(); 25 | 26 | var db = this.GetDb(); 27 | 28 | var message1 = new Message { Id = 1, SenderId = UserId, ReceiverId = OtherUserId }; 29 | var message2 = new Message { Id = 2, SenderId = OtherUserId, ReceiverId = UserId }; 30 | var message3 = new Message { Id = 3, SenderId = "3", ReceiverId = "4" }; 31 | 32 | db.AddRange(message1, message2, message3); 33 | db.SaveChanges(); 34 | 35 | var messangerService = new MessangerService(db); 36 | 37 | //Act 38 | List result = messangerService.All(); 39 | //var result = messangerService.AllByUserIds(OtherUserId, UserId, 1, 6); 40 | 41 | //Assert 42 | result 43 | .Should() 44 | .HaveCount(0); 45 | 46 | } 47 | 48 | private SocialNetworkDbContext GetDb() 49 | { 50 | var dbOptions = new DbContextOptionsBuilder() 51 | .UseInMemoryDatabase(Guid.NewGuid().ToString()) 52 | .Options; 53 | 54 | return new SocialNetworkDbContext(dbOptions); 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /SocialNetwork.Tests/SocialNetwork.Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp2.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /SocialNetwork.Tests/Web/Controllers/CommentControllerTest.cs: -------------------------------------------------------------------------------- 1 | using FluentAssertions; 2 | using Microsoft.AspNetCore.Authorization; 3 | using Microsoft.AspNetCore.Mvc; 4 | using SocialNetwork.Tests.Mocks; 5 | using SocialNetwork.Web.Controllers; 6 | using SocialNetwork.Web.Models.Comment; 7 | using System.Linq; 8 | using Xunit; 9 | 10 | namespace SocialNetwork.Tests.Web.Controllers 11 | { 12 | public class CommentControllerTest 13 | { 14 | [Fact] 15 | public void ControllerShouldBeOnlyForAuhtorizedUsers() 16 | { 17 | //Arrange 18 | var controller = typeof(CommentController); 19 | 20 | //Act 21 | var attributes = controller.GetCustomAttributes(true); 22 | 23 | //Assert 24 | attributes 25 | .Should() 26 | .Match(attr => attr.Any(a => a.GetType() == typeof(AuthorizeAttribute))); 27 | } 28 | 29 | [Fact] 30 | public void CheckIfCreateMethodReturnsViewWithErrorWhenModelTextIsEmpty() 31 | { 32 | //Arrange 33 | var postService = MockCreator.PostServiceMock(); 34 | var commentService = MockCreator.CommentServiceMock(); 35 | 36 | var controller = new CommentController(postService.Object, commentService.Object); 37 | 38 | var model = new PostCommentCreateModel 39 | { 40 | CommentText = "" 41 | }; 42 | 43 | //Act 44 | var result = controller.Create(model, null); 45 | 46 | //Assert 47 | result 48 | .Should() 49 | .BeOfType(); 50 | } 51 | 52 | [Fact] 53 | public void CheckIfCreateMethodReturnsRedirectWhenOk() 54 | { 55 | //Arrange 56 | var postService = MockCreator.PostServiceMock(); 57 | var commentService = MockCreator.CommentServiceMock(); 58 | 59 | var controller = new CommentController(postService.Object, commentService.Object); 60 | 61 | var model = new PostCommentCreateModel 62 | { 63 | CommentText = "Test" 64 | }; 65 | 66 | //Act 67 | var result = controller.Create(model, null); 68 | 69 | //Assert 70 | result 71 | .Should() 72 | .BeOfType(); 73 | } 74 | } 75 | } -------------------------------------------------------------------------------- /SocialNetwork.Tests/Web/Controllers/UserControllerTest.cs: -------------------------------------------------------------------------------- 1 | using FluentAssertions; 2 | using Microsoft.AspNetCore.Authorization; 3 | using Microsoft.AspNetCore.Mvc; 4 | using Moq; 5 | using SocialNetwork.Services.Models; 6 | using SocialNetwork.Tests.Mocks; 7 | using SocialNetwork.Web.Controllers; 8 | using System.Linq; 9 | using Xunit; 10 | 11 | namespace SocialNetwork.Tests.Web.Controllers 12 | { 13 | public class UserControllerTest 14 | { 15 | [Fact] 16 | public void ControllerShouldBeOnlyForAuhtorizedUsers() 17 | { 18 | //Arrange 19 | var controller = typeof(UsersController); 20 | 21 | //Act 22 | var attributes = controller.GetCustomAttributes(true); 23 | 24 | //Assert 25 | attributes 26 | .Should() 27 | .Match(attr => attr.Any(a => a.GetType() == typeof(AuthorizeAttribute))); 28 | } 29 | 30 | [Fact] 31 | public void IndexShouldReturnViewWhenModelsOK() 32 | { 33 | //Arrange 34 | var userService = MockCreator.UserServiceMock(); 35 | 36 | userService 37 | .Setup(u => 38 | u.UserDetailsFriendsCommentsAndPosts(It.IsAny(), It.IsAny(), It.IsAny())) 39 | .Returns(new UserAccountModel()); 40 | 41 | var controller = new UsersController(userService.Object); 42 | 43 | //Act 44 | var result = controller.Index(null); 45 | 46 | //Assert 47 | result 48 | .Should() 49 | .BeOfType(); 50 | } 51 | 52 | [Fact] 53 | public void IndexShouldReturnNotFoundwhenModelIsNull() 54 | { 55 | //Arrange 56 | var userService = MockCreator.UserServiceMock(); 57 | 58 | userService 59 | .Setup(u => 60 | u.UserDetailsFriendsCommentsAndPosts(It.IsAny(), It.IsAny(), It.IsAny())) 61 | .Returns(null); 62 | 63 | var controller = new UsersController(userService.Object); 64 | 65 | //Act 66 | var result = controller.Index(null); 67 | 68 | //Assert 69 | result 70 | .Should() 71 | .BeOfType(); 72 | } 73 | } 74 | } -------------------------------------------------------------------------------- /SocialNetwork.Web/.bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "directory": "wwwroot/lib" 3 | } 4 | -------------------------------------------------------------------------------- /SocialNetwork.Web/Areas/Admin/Controllers/AdminBaseController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Authorization; 2 | using Microsoft.AspNetCore.Mvc; 3 | using SocialNetwork.Web.Infrastructure; 4 | 5 | namespace SocialNetwork.Web.Areas.Admin.Controllers 6 | { 7 | [Area(GlobalConstants.AdminArea)] 8 | [Authorize(Roles = GlobalConstants.AdminRole)] 9 | public abstract class AdminBaseController : Controller 10 | { 11 | } 12 | } -------------------------------------------------------------------------------- /SocialNetwork.Web/Areas/Admin/Controllers/HomeController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | 3 | namespace SocialNetwork.Web.Areas.Admin.Controllers 4 | { 5 | public class HomeController : AdminBaseController 6 | { 7 | public IActionResult Index() 8 | { 9 | return View(); 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /SocialNetwork.Web/Areas/Admin/Controllers/UsersController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using AutoMapper; 3 | using Microsoft.AspNetCore.Mvc; 4 | using SocialNetwork.Services; 5 | using SocialNetwork.Web.Areas.Admin.Models.Users; 6 | using SocialNetwork.Web.Infrastructure; 7 | using SocialNetwork.Web.Infrastructure.Filters; 8 | 9 | namespace SocialNetwork.Web.Areas.Admin.Controllers 10 | { 11 | public class UsersController : AdminBaseController 12 | { 13 | private const int PageSize = 3; 14 | 15 | private readonly IUserService userService; 16 | 17 | public static object Index() 18 | { 19 | throw new NotImplementedException(); 20 | } 21 | 22 | public UsersController(IUserService userService) 23 | { 24 | this.userService = userService; 25 | } 26 | 27 | public IActionResult Search(string searchTerm, int? page) 28 | { 29 | ViewData[GlobalConstants.SearchTerm] = searchTerm; 30 | 31 | if (string.IsNullOrEmpty(searchTerm)) 32 | { 33 | var users = this.userService.All(page ?? 1, PageSize); 34 | return View(users); 35 | } 36 | else 37 | { 38 | var users = this.userService.UsersBySearchTerm(searchTerm, page ?? 1, PageSize); 39 | return View(users); 40 | } 41 | } 42 | 43 | public IActionResult Edit(string id) 44 | { 45 | if (!this.userService.UserExists(id)) 46 | { 47 | return NotFound(); 48 | } 49 | 50 | var userEditModel = Mapper.Map(this.userService.GetById(id)); 51 | 52 | return View(userEditModel); 53 | } 54 | 55 | [HttpPost] 56 | [ValidateModelState] 57 | public IActionResult Edit(string id, UserEditModel model) 58 | { 59 | if (!this.userService.UserExists(id)) 60 | { 61 | return NotFound(); 62 | } 63 | 64 | this.userService.EditUser(id, model.FirstName, model.LastName, model.Age, model.Email, model.Username); 65 | 66 | return RedirectToAction(nameof(Search), new { searchTerm = model.FirstName }); 67 | } 68 | 69 | public IActionResult Delete(string id) 70 | { 71 | if (!this.userService.UserExists(id)) 72 | { 73 | return NotFound(); 74 | } 75 | 76 | var userEditModel = Mapper.Map(this.userService.GetById(id)); 77 | 78 | return View(userEditModel); 79 | } 80 | 81 | [HttpPost] 82 | [ActionName("Delete")] 83 | public IActionResult Destroy(string id) 84 | { 85 | if (!this.userService.UserExists(id)) 86 | { 87 | return NotFound(); 88 | } 89 | 90 | this.userService.DeleteUser(id); 91 | 92 | return RedirectToAction(nameof(Search)); 93 | } 94 | } 95 | } -------------------------------------------------------------------------------- /SocialNetwork.Web/Areas/Admin/Models/Users/UserEditModel.cs: -------------------------------------------------------------------------------- 1 | using SocialNetwork.Web.Infrastructure.CustomValidationAttributes; 2 | using System.ComponentModel.DataAnnotations; 3 | 4 | namespace SocialNetwork.Web.Areas.Admin.Models.Users 5 | { 6 | public class UserEditModel 7 | { 8 | [Required] 9 | [EmailAddress] 10 | [Display(Name = "Email")] 11 | public string Email { get; set; } 12 | 13 | [Required] 14 | [Display(Name = "First Name")] 15 | [MinLength(2), MaxLength(50)] 16 | public string FirstName { get; set; } 17 | 18 | [Required] 19 | [Display(Name = "Last Name")] 20 | [MinLength(2), MaxLength(50)] 21 | public string LastName { get; set; } 22 | 23 | [Required] 24 | [Display(Name = "Username")] 25 | [MinLength(2), MaxLength(50)] 26 | public string Username { get; set; } 27 | 28 | [Required] 29 | [Age] 30 | public int Age { get; set; } 31 | } 32 | } -------------------------------------------------------------------------------- /SocialNetwork.Web/Areas/Admin/Views/Home/Index.cshtml: -------------------------------------------------------------------------------- 1 | 

Hello Admin!

2 | -------------------------------------------------------------------------------- /SocialNetwork.Web/Areas/Admin/Views/Shared/Error.cshtml: -------------------------------------------------------------------------------- 1 | @model ErrorViewModel 2 | @{ 3 | ViewData["Title"] = "Error"; 4 | } 5 | 6 |

Error.

7 |

An error occurred while processing your request.

8 | 9 | @if (Model.ShowRequestId) 10 | { 11 |

12 | Request ID: @Model.RequestId 13 |

14 | } 15 | 16 |

Development Mode

17 |

18 | Swapping to Development environment will display more detailed information about the error that occurred. 19 |

20 |

21 | Development environment should not be enabled in deployed applications, as it can result in sensitive information from exceptions being displayed to end users. For local debugging, development environment can be enabled by setting the ASPNETCORE_ENVIRONMENT environment variable to Development, and restarting the application. 22 |

23 | -------------------------------------------------------------------------------- /SocialNetwork.Web/Areas/Admin/Views/Shared/_Layout.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | @ViewData["Title"] - SocialNetwork 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 29 | 30 | 31 | 47 |
48 | @RenderBody() 49 |
50 |
51 |

© 2017 - SocialNetwork

52 |
53 |
54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 68 | 74 | 75 | 76 | 77 | @RenderSection("Scripts", required: false) 78 | 79 | -------------------------------------------------------------------------------- /SocialNetwork.Web/Areas/Admin/Views/Shared/_LoginPartial.cshtml: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Identity 2 | @using SocialNetwork.Web.Models 3 | 4 | @inject SignInManager SignInManager 5 | @inject UserManager UserManager 6 | 7 | 14 | -------------------------------------------------------------------------------- /SocialNetwork.Web/Areas/Admin/Views/Shared/_ValidationScriptsPartial.cshtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 12 | 18 | 19 | -------------------------------------------------------------------------------- /SocialNetwork.Web/Areas/Admin/Views/Users/Delete.cshtml: -------------------------------------------------------------------------------- 1 | @model UserEditModel 2 | @{ 3 | ViewData["Title"] = "Delete User"; 4 | } 5 | 6 |

@ViewData["Title"]

7 | 8 |
9 |
10 |
11 |
12 |
13 |
14 | 15 | 16 | 17 |
18 |
19 | 20 | 21 | 22 |
23 |
24 | 25 | 26 | 27 |
28 |
29 | 30 | 31 | 32 |
33 |
34 | 35 | 36 | 37 |
38 | 39 |
40 | 41 | 42 |
43 |
44 |
45 | 46 | @section Scripts { 47 | @await Html.PartialAsync("_ValidationScriptsPartial") 48 | } 49 | -------------------------------------------------------------------------------- /SocialNetwork.Web/Areas/Admin/Views/Users/Edit.cshtml: -------------------------------------------------------------------------------- 1 | @model UserEditModel 2 | @{ 3 | ViewData["Title"] = "Edit User"; 4 | } 5 | 6 |

@ViewData["Title"]

7 | 8 |
9 |
10 |
11 |
12 |
13 |
14 | 15 | 16 | 17 |
18 |
19 | 20 | 21 | 22 |
23 |
24 | 25 | 26 | 27 |
28 |
29 | 30 | 31 | 32 |
33 |
34 | 35 | 36 | 37 |
38 | 39 |
40 | 41 | 42 |
43 |
44 |
45 | 46 | @section Scripts { 47 | @await Html.PartialAsync("_ValidationScriptsPartial") 48 | } -------------------------------------------------------------------------------- /SocialNetwork.Web/Areas/Admin/Views/Users/Search.cshtml: -------------------------------------------------------------------------------- 1 | @model PaginatedList 2 | 3 | @{ 4 | ViewData["Title"] = "Search Users"; 5 | } 6 | 7 |

@ViewData["Title"]

8 | 9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | Find by Name or Username: 17 | 18 |
19 |
20 | | 21 | Back to Full List 22 |
23 |
24 |
25 |
26 |
27 |
28 | @if (Model.Any()) 29 | { 30 | 31 | var prevDisabled = !Model.HasPreviousPage ? "disabled" : ""; 32 | var nextDisabled = !Model.HasNextPage ? "disabled" : ""; 33 | 34 | @foreach (var user in Model) 35 | { 36 | 37 |
38 |
39 |
40 | Avatar 41 |
42 |
43 |
44 | @user.FullName 45 |
46 |
47 | Age: @user.Age 48 |
49 |
50 |
51 |
52 | Number of Posts: @user.NumberOfPosts 53 |
54 |
55 | Edit 59 | Delete 63 |
64 |
65 |
66 |
67 | 68 | } 69 | 70 |
71 | 85 |
86 | } 87 | else 88 | { 89 |
90 |
91 |
92 |

There are no user corresponding to your search!

93 |
94 |
95 |
96 | } 97 |
98 |
-------------------------------------------------------------------------------- /SocialNetwork.Web/Areas/Admin/Views/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Identity 2 | @using SocialNetwork.Web 3 | @using SocialNetwork.Web.Infrastructure 4 | @using SocialNetwork.Web.Models.HomeViewModels 5 | @using SocialNetwork.Web.Models.AccountViewModels 6 | @using SocialNetwork.Web.Models.ManageViewModels 7 | @using SocialNetwork.Web.Models.PostsViewModels 8 | @using SocialNetwork.Web.Models.Comment 9 | @using SocialNetwork.Web.Models.Messanger 10 | @using SocialNetwork.Web.Models.Events 11 | @using SocialNetwork.Web.Models 12 | @using SocialNetwork.Data.Entities 13 | @using SocialNetwork.Data.Entities.Enums 14 | @using SocialNetwork.Services.Models 15 | @using SocialNetwork.Web.Extensions 16 | @using SocialNetwork.Services.Infrastructure.CustomDataStructures 17 | @using SocialNetwork.Web.Areas.Admin.Models.Users 18 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 19 | -------------------------------------------------------------------------------- /SocialNetwork.Web/Areas/Admin/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "_Layout"; 3 | } 4 | -------------------------------------------------------------------------------- /SocialNetwork.Web/Controllers/CommentController.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using Microsoft.AspNetCore.Authorization; 3 | using Microsoft.AspNetCore.Mvc; 4 | using SocialNetwork.Services; 5 | using SocialNetwork.Web.Extensions; 6 | using SocialNetwork.Web.Infrastructure; 7 | using SocialNetwork.Web.Infrastructure.Filters; 8 | using SocialNetwork.Web.Models.Comment; 9 | 10 | namespace SocialNetwork.Web.Controllers 11 | { 12 | [Authorize] 13 | public class CommentController : Controller 14 | { 15 | private readonly IPostService postService; 16 | private readonly ICommentService commentService; 17 | 18 | public CommentController(IPostService postService, ICommentService commentService) 19 | { 20 | this.postService = postService; 21 | this.commentService = commentService; 22 | } 23 | 24 | public IActionResult Create(int postId) 25 | { 26 | var postCommentViewModel = this.postService.PostById(postId); 27 | 28 | PostCommentCreateModel postCommentCreateModel = Mapper.Map(postCommentViewModel); 29 | 30 | return this.ViewOrNotFound(postCommentCreateModel); 31 | } 32 | 33 | [HttpPost] 34 | [ValidateModelState] 35 | public IActionResult Create(PostCommentCreateModel model, string returnUrl = null) 36 | { 37 | if (CoreValidator.CheckIfStringIsNullOrEmpty(model.CommentText)) 38 | { 39 | ModelState.AddModelError(string.Empty, "You cannot submit an empty comment!"); 40 | return this.ViewOrNotFound(model); 41 | } 42 | 43 | this.commentService.Create(model.CommentText, User.GetUserId(), model.Id); 44 | return RedirectToAction("Index", "Users"); 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /SocialNetwork.Web/Controllers/EventsController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Authorization; 2 | using Microsoft.AspNetCore.Mvc; 3 | using SocialNetwork.Services; 4 | using SocialNetwork.Web.Extensions; 5 | using SocialNetwork.Web.Infrastructure.Filters; 6 | using SocialNetwork.Web.Models.Events; 7 | 8 | namespace SocialNetwork.Web.Controllers 9 | { 10 | [Authorize] 11 | public class EventsController : Controller 12 | { 13 | private readonly IEventService eventService; 14 | 15 | public EventsController(IEventService eventService) 16 | { 17 | this.eventService = eventService; 18 | } 19 | 20 | public IActionResult Create() 21 | { 22 | return View(); 23 | } 24 | 25 | [HttpPost] 26 | [ValidateModelState] 27 | public IActionResult Create(EventFormModel model) 28 | { 29 | this.eventService.Create( 30 | model.ImageUrl, 31 | model.Title, 32 | model.Location, 33 | model.Description, 34 | model.DateStarts, 35 | model.DateEnds, 36 | this.User.GetUserId()); 37 | 38 | return RedirectToAction("Index", "Users"); 39 | } 40 | 41 | public IActionResult Details(int id) 42 | { 43 | if (!this.eventService.Exists(id)) 44 | { 45 | return NotFound(); 46 | } 47 | 48 | return this.ViewOrNotFound(this.eventService.Details(id)); 49 | } 50 | 51 | public IActionResult JointEvent(int id) 52 | { 53 | if (!this.eventService.Exists(id)) 54 | { 55 | return NotFound(); 56 | } 57 | 58 | this.eventService.AddUserToEvent(User.GetUserId(), id); 59 | 60 | return RedirectToAction(nameof(Details), new { id = id }); 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /SocialNetwork.Web/Controllers/FriendRequestsController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Authorization; 2 | using Microsoft.AspNetCore.Mvc; 3 | using SocialNetwork.Services; 4 | using SocialNetwork.Web.Extensions; 5 | 6 | namespace SocialNetwork.Web.Controllers 7 | { 8 | [Authorize] 9 | public class FriendRequestsController : Controller 10 | { 11 | private readonly IFriendRequestService friendRequestService; 12 | private readonly IUserService userService; 13 | 14 | public FriendRequestsController(IFriendRequestService friendRequestService, IUserService userService) 15 | { 16 | this.friendRequestService = friendRequestService; 17 | this.userService = userService; 18 | } 19 | 20 | public IActionResult AddFriend(string senderId, string receiverId) 21 | { 22 | if (!this.userService.UserExists(senderId) || !this.userService.UserExists(receiverId) || senderId != this.User.GetUserId()) 23 | { 24 | return NotFound(); 25 | } 26 | 27 | this.friendRequestService.Create(senderId, receiverId); 28 | 29 | return RedirectToAction("AccountDetails", "Users", new { id = receiverId }); 30 | } 31 | 32 | public IActionResult Accept(string senderId, string receiverId) 33 | { 34 | this.friendRequestService.Accept(senderId, receiverId); 35 | return RedirectToAction("AccountDetails", "Users", new { id = senderId }); 36 | } 37 | 38 | public IActionResult Decline(string senderId, string receiverId) 39 | { 40 | this.friendRequestService.Decline(senderId, receiverId); 41 | return RedirectToAction("AccountDetails", "Users", new { id = senderId }); 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /SocialNetwork.Web/Controllers/HomeController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | using PaulMiami.AspNetCore.Mvc.Recaptcha; 3 | using SocialNetwork.Services; 4 | using SocialNetwork.Web.Infrastructure; 5 | using SocialNetwork.Web.Infrastructure.Filters; 6 | using SocialNetwork.Web.Models; 7 | using SocialNetwork.Web.Models.HomeViewModels; 8 | using System; 9 | using System.Diagnostics; 10 | using System.Text; 11 | 12 | namespace SocialNetwork.Web.Controllers 13 | { 14 | public class HomeController : Controller 15 | { 16 | private readonly IEmailSender emailSender; 17 | 18 | public HomeController(IEmailSender emailSender) 19 | { 20 | this.emailSender = emailSender; 21 | } 22 | 23 | public IActionResult Index() 24 | { 25 | if (this.User.IsInRole(GlobalConstants.AdminRole)) 26 | { 27 | return RedirectToAction("Index", "Home", new { area = GlobalConstants.AdminArea }); 28 | } 29 | if (!this.User.Identity.IsAuthenticated) 30 | { 31 | return RedirectToAction("Login", "Account"); 32 | } 33 | else 34 | { 35 | return RedirectToAction("Index", "Users"); 36 | } 37 | } 38 | 39 | public IActionResult Contact() 40 | { 41 | ViewData["Message"] = "Your contact page."; 42 | 43 | return View(); 44 | } 45 | 46 | [HttpPost] 47 | [ValidateModelState] 48 | [ValidateRecaptcha] 49 | public IActionResult Contact(EmailModel model) 50 | { 51 | StringBuilder message = new StringBuilder(); 52 | message.AppendLine($"From: {model.Name} {model.Email}"); 53 | message.AppendLine(); 54 | message.AppendLine(model.Message); 55 | 56 | try 57 | { 58 | this.emailSender.SendEmailAsync(GlobalConstants.SocialNetworkEmail, model.Subject, message.ToString()); 59 | ViewData["SuccessMessage"] = "Your email has been successfully sent!"; 60 | return View(model); 61 | } 62 | catch (Exception) 63 | { 64 | this.ModelState.AddModelError("EmailSenderror", "Something went wrong, please try again later!"); 65 | return View(model); 66 | } 67 | } 68 | 69 | public IActionResult Error() 70 | { 71 | return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier }); 72 | } 73 | } 74 | } -------------------------------------------------------------------------------- /SocialNetwork.Web/Controllers/MessangerController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Authorization; 2 | using Microsoft.AspNetCore.Mvc; 3 | using SocialNetwork.Services; 4 | using SocialNetwork.Web.Extensions; 5 | using SocialNetwork.Web.Infrastructure; 6 | using SocialNetwork.Web.Infrastructure.Filters; 7 | using SocialNetwork.Web.Models.Messanger; 8 | 9 | namespace SocialNetwork.Web.Controllers 10 | { 11 | [Authorize] 12 | public class MessangerController : Controller 13 | { 14 | private const int PageSize = 10; 15 | 16 | private readonly IUserService userService; 17 | private readonly IMessangerService messangerService; 18 | 19 | public MessangerController(IUserService userService, IMessangerService messangerService) 20 | { 21 | this.userService = userService; 22 | this.messangerService = messangerService; 23 | } 24 | 25 | public IActionResult Index(string id, int? pageIndex) 26 | { 27 | if (id == this.User.GetUserId() || !this.userService.CheckIfFriends(this.User.GetUserId(), id)) 28 | { 29 | return BadRequest(); 30 | } 31 | 32 | var messangerModel = new MessangerModel(); 33 | 34 | string compositeChatId = string.Compare(User.GetUserId(), id) > 0 ? User.GetUserId() + id : id + User.GetUserId(); 35 | 36 | ViewData[GlobalConstants.CompsiteChatId] = compositeChatId; 37 | ViewData[GlobalConstants.CounterPartFullName] = this.userService.GetUserFullName(id); 38 | 39 | messangerModel.Messages = this.messangerService.AllByUserIds(User.GetUserId(), id, pageIndex ?? 1, PageSize); 40 | 41 | return this.ViewOrNotFound(messangerModel); 42 | } 43 | 44 | [HttpPost] 45 | [ValidateModelState] 46 | public IActionResult Index(string id, int? pageIndex, MessangerModel model) 47 | { 48 | if (id == this.User.GetUserId() || !this.userService.CheckIfFriends(this.User.GetUserId(), id)) 49 | { 50 | return BadRequest(); 51 | } 52 | 53 | this.messangerService.Create(User.GetUserId(), id, model.MessageText); 54 | return RedirectToAction(nameof(Index), new { id, pageIndex }); 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /SocialNetwork.Web/Controllers/PostsController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Authorization; 2 | using Microsoft.AspNetCore.Mvc; 3 | using SocialNetwork.Data; 4 | using SocialNetwork.Services; 5 | using SocialNetwork.Web.Extensions; 6 | using SocialNetwork.Web.Infrastructure.Filters; 7 | using SocialNetwork.Web.Models.PostsViewModels; 8 | 9 | namespace SocialNetwork.Web.Controllers 10 | { 11 | [Authorize] 12 | public class PostsController : Controller 13 | { 14 | private readonly IPostService postService; 15 | 16 | public PostsController(IPostService postService) 17 | { 18 | this.postService = postService; 19 | } 20 | 21 | public IActionResult Create() 22 | { 23 | return View(); 24 | } 25 | 26 | [HttpPost] 27 | [ValidateModelState] 28 | public IActionResult Create(PostFormModel model) 29 | { 30 | if (model.Photo != null) 31 | { 32 | if (model.Photo.Length > DataConstants.MaxPhotoLength) 33 | { 34 | ModelState.AddModelError(string.Empty, "Your photo should be a valid image file with max size 5MB!"); 35 | return View(model); 36 | } 37 | } 38 | 39 | this.postService.Create(this.User.GetUserId(), model.Feeling, model.Text, model.Photo); 40 | 41 | return Redirect("/"); 42 | } 43 | 44 | public IActionResult Edit(int postId) 45 | { 46 | if (!this.postService.Exists(postId)) 47 | { 48 | return NotFound(); 49 | } 50 | 51 | var postInfo = this.postService.PostById(postId); 52 | 53 | ViewData["PostPhoto"] = postInfo.Photo; 54 | 55 | var postFormModel = new PostFormModel 56 | { 57 | Text = postInfo.Text, 58 | Feeling = postInfo.Feeling 59 | }; 60 | 61 | return this.ViewOrNotFound(postFormModel); 62 | } 63 | 64 | [HttpPost] 65 | [ValidateModelState] 66 | public IActionResult Edit(int postId, PostFormModel model) 67 | { 68 | if (!this.postService.UserIsAuthorizedToEdit(postId, this.User.GetUserId())) 69 | { 70 | return BadRequest(); 71 | } 72 | 73 | this.postService.Edit(postId, model.Feeling, model.Text, model.Photo); 74 | 75 | return RedirectToAction("AccountDetails", "Users", new { id = this.User.GetUserId() }); 76 | } 77 | 78 | public IActionResult Delete(int postId) 79 | { 80 | if (!this.postService.Exists(postId)) 81 | { 82 | return NotFound(); 83 | } 84 | 85 | var postInfo = this.postService.PostById(postId); 86 | 87 | ViewData["PostPhoto"] = postInfo.Photo; 88 | 89 | var postFormModel = new PostFormModel 90 | { 91 | Text = postInfo.Text, 92 | Feeling = postInfo.Feeling 93 | }; 94 | 95 | return this.ViewOrNotFound(postFormModel); 96 | } 97 | 98 | [HttpPost] 99 | [ActionName("Delete")] 100 | public IActionResult Destroy(int postId) 101 | { 102 | if (!this.postService.UserIsAuthorizedToEdit(postId, this.User.GetUserId())) 103 | { 104 | return BadRequest(); 105 | } 106 | 107 | this.postService.Delete(postId); 108 | 109 | return RedirectToAction("AccountDetails", "Users", new { id = this.User.GetUserId() }); 110 | } 111 | 112 | public IActionResult Like(int postId, int pageIndex) 113 | { 114 | if (!this.postService.Exists(postId)) 115 | { 116 | return this.NotFound(); 117 | } 118 | 119 | this.postService.Like(postId); 120 | 121 | return RedirectToAction("Index", "Users", new { page = pageIndex}); 122 | } 123 | } 124 | } -------------------------------------------------------------------------------- /SocialNetwork.Web/Controllers/UsersController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Authorization; 2 | using Microsoft.AspNetCore.Mvc; 3 | using SocialNetwork.Services; 4 | using SocialNetwork.Services.Models; 5 | using SocialNetwork.Web.Extensions; 6 | using SocialNetwork.Web.Infrastructure; 7 | 8 | namespace SocialNetwork.Web.Controllers 9 | { 10 | [Authorize] 11 | public class UsersController : Controller 12 | { 13 | private const int PageSize = 3; 14 | 15 | private readonly IUserService userService; 16 | 17 | public UsersController(IUserService userService) 18 | { 19 | this.userService = userService; 20 | } 21 | 22 | public IActionResult Index(int? page) 23 | { 24 | UserAccountModel user = this.userService.UserDetailsFriendsCommentsAndPosts(this.User.GetUserId(), page ?? 1, PageSize); 25 | 26 | return this.ViewOrNotFound(user); 27 | } 28 | 29 | public IActionResult AccountDetails(string id, int? page) 30 | { 31 | //could be optimized 32 | if (User.GetUserId() == id) 33 | { 34 | ViewData[GlobalConstants.Authorization] = GlobalConstants.FullAuthorization; 35 | } 36 | else if (this.userService.CheckIfFriends(User.GetUserId(), id)) 37 | { 38 | ViewData[GlobalConstants.Authorization] = GlobalConstants.FriendAuthorization; 39 | } 40 | else 41 | { 42 | ViewData[GlobalConstants.Authorization] = GlobalConstants.NoAuthorization; 43 | } 44 | 45 | UserAccountModel user = this.userService.UserDetails(id, page ?? 1, PageSize); 46 | 47 | return this.ViewOrNotFound(user); 48 | } 49 | 50 | public IActionResult Search(string searchTerm, int? page) 51 | { 52 | ViewData[GlobalConstants.SearchTerm] = searchTerm; 53 | 54 | if (string.IsNullOrEmpty(searchTerm)) 55 | { 56 | var users = this.userService.All(page ?? 1, PageSize); 57 | return this.ViewOrNotFound(users); 58 | } 59 | else 60 | { 61 | var users = this.userService.UsersBySearchTerm(searchTerm, page ?? 1, PageSize); 62 | return this.ViewOrNotFound(users); 63 | } 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /SocialNetwork.Web/Extensions/ApplicationBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Builder; 2 | using Microsoft.AspNetCore.Identity; 3 | using Microsoft.EntityFrameworkCore; 4 | using Microsoft.Extensions.DependencyInjection; 5 | using SocialNetwork.Data; 6 | using SocialNetwork.Data.Entities; 7 | using SocialNetwork.Web.Infrastructure; 8 | using System.Threading.Tasks; 9 | 10 | namespace SocialNetwork.Web.Extensions 11 | { 12 | public static class ApplicationBuilderExtensions 13 | { 14 | public static IApplicationBuilder UseDatabaseMigrations(this IApplicationBuilder app) 15 | { 16 | using (var serviceScope = app.ApplicationServices.GetRequiredService().CreateScope()) 17 | { 18 | serviceScope.ServiceProvider.GetService().Database.Migrate(); 19 | 20 | var userManager = serviceScope.ServiceProvider.GetService>(); 21 | 22 | var roleManager = serviceScope.ServiceProvider.GetService>(); 23 | 24 | Task.Run(async () => 25 | { 26 | var roleName = GlobalConstants.AdminRole; 27 | 28 | var roleExits = await roleManager.RoleExistsAsync(roleName); 29 | 30 | if (!roleExits) 31 | { 32 | var result = await roleManager.CreateAsync(new IdentityRole 33 | { 34 | Name = roleName 35 | }); 36 | } 37 | 38 | var adminUser = await userManager.FindByNameAsync(roleName); 39 | 40 | if (adminUser == null) 41 | { 42 | adminUser = new User 43 | { 44 | FirstName = "Administrator", 45 | LastName = "Administrator", 46 | Age = 23, 47 | Email = "admin@social.com", 48 | UserName = roleName, 49 | ProfilePicture = new byte[] {1, 2, 3} 50 | }; 51 | 52 | await userManager.CreateAsync(adminUser, "admin123"); 53 | 54 | await userManager.AddToRoleAsync(adminUser, roleName); 55 | } 56 | }) 57 | .GetAwaiter() 58 | .GetResult(); 59 | } 60 | return app; 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /SocialNetwork.Web/Extensions/ByteArrayExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace SocialNetwork.Web.Extensions 4 | { 5 | public static class ByteArrayExtensions 6 | { 7 | public static string ToRenderablePictureString(this byte[] array) 8 | { 9 | if (array == null) 10 | { 11 | return string.Empty; 12 | } 13 | return "data:image; base64," + Convert.ToBase64String(array); 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /SocialNetwork.Web/Extensions/ClaimsPrincipalExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Security.Claims; 3 | 4 | namespace SocialNetwork.Web.Extensions 5 | { 6 | public static class ClaimsPrincipalExtensions 7 | { 8 | public static string GetUserId(this ClaimsPrincipal principal) 9 | { 10 | if (principal == null) 11 | { 12 | //throw new ArgumentNullException(nameof(principal)); 13 | return null; 14 | } 15 | 16 | return principal.FindFirst(ClaimTypes.NameIdentifier)?.Value; 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /SocialNetwork.Web/Extensions/ControllerExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | 3 | namespace SocialNetwork.Web.Extensions 4 | { 5 | public static class ControllerExtensions 6 | { 7 | public static IActionResult ViewOrNotFound(this Controller controller, object model) 8 | { 9 | if (model == null) 10 | { 11 | return controller.NotFound(); 12 | } 13 | 14 | return controller.View(model); 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /SocialNetwork.Web/Extensions/EmailSenderExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text.Encodings.Web; 5 | using System.Threading.Tasks; 6 | using SocialNetwork.Web.Services; 7 | using SocialNetwork.Services; 8 | 9 | namespace SocialNetwork.Web.Services 10 | { 11 | public static class EmailSenderExtensions 12 | { 13 | public static Task SendEmailConfirmationAsync(this IEmailSender emailSender, string email, string link) 14 | { 15 | return emailSender.SendEmailAsync(email, "Confirm your email", 16 | $"Please confirm your account by clicking this link: link"); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /SocialNetwork.Web/Extensions/ServiceCollectionExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.DependencyInjection; 2 | using SocialNetwork.Services; 3 | using System.Linq; 4 | using System.Reflection; 5 | 6 | namespace SocialNetwork.Web.Extensions 7 | { 8 | public static class ServiceCollectionExtensions 9 | { 10 | public static IServiceCollection AddDomainServices(this IServiceCollection services) 11 | { 12 | Assembly 13 | .GetAssembly(typeof(IService)) 14 | .GetTypes() 15 | .Where(t => t.IsClass && t.GetInterfaces().Any(i => i.Name == $"I{t.Name}")) 16 | .Select(t => new 17 | { 18 | Interface = t.GetInterface($"I{t.Name}"), 19 | Implementation = t 20 | }) 21 | .ToList() 22 | .ForEach(s => services.AddTransient(s.Interface, s.Implementation)); 23 | 24 | return services; 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /SocialNetwork.Web/Extensions/UrlHelperExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using SocialNetwork.Web.Controllers; 6 | 7 | namespace Microsoft.AspNetCore.Mvc 8 | { 9 | public static class UrlHelperExtensions 10 | { 11 | public static string EmailConfirmationLink(this IUrlHelper urlHelper, string userId, string code, string scheme) 12 | { 13 | return urlHelper.Action( 14 | action: nameof(AccountController.ConfirmEmail), 15 | controller: "Account", 16 | values: new { userId, code }, 17 | protocol: scheme); 18 | } 19 | 20 | public static string ResetPasswordCallbackLink(this IUrlHelper urlHelper, string userId, string code, string scheme) 21 | { 22 | return urlHelper.Action( 23 | action: nameof(AccountController.ResetPassword), 24 | controller: "Account", 25 | values: new { userId, code }, 26 | protocol: scheme); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /SocialNetwork.Web/Hub/ChatHub.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.SignalR; 2 | using System.Threading.Tasks; 3 | 4 | namespace SocialNetwork.Web.Hub 5 | { 6 | public class ChatHub : Microsoft.AspNetCore.SignalR.Hub 7 | { 8 | public async Task Send(string message) 9 | { 10 | await this.Clients.All.InvokeAsync("Send", message); 11 | } 12 | 13 | public void Join(string groupName) 14 | { 15 | Groups.AddAsync(Context.ConnectionId, groupName); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /SocialNetwork.Web/Infrastructure/CoreValidator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace SocialNetwork.Web.Infrastructure 4 | { 5 | public static class CoreValidator 6 | { 7 | public static bool CheckIfStringIsNullOrEmpty(string input) => String.IsNullOrEmpty(input); 8 | } 9 | } -------------------------------------------------------------------------------- /SocialNetwork.Web/Infrastructure/CustomValidationAttributes/AgeAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel.DataAnnotations; 3 | 4 | namespace SocialNetwork.Web.Infrastructure.CustomValidationAttributes 5 | { 6 | public class AgeAttribute : ValidationAttribute 7 | { 8 | protected override ValidationResult IsValid(object value, ValidationContext validationContext) 9 | { 10 | int age; 11 | 12 | try 13 | { 14 | age = int.Parse(value.ToString()); 15 | if (age >= 12 && age <= 130) 16 | { 17 | return ValidationResult.Success; 18 | } 19 | else 20 | { 21 | return new ValidationResult("Age should be a number between 12 and 130!"); 22 | } 23 | } 24 | catch (Exception) 25 | { 26 | return new ValidationResult("Age should be a number between 12 and 130!"); 27 | } 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /SocialNetwork.Web/Infrastructure/Filters/ValidateModelStateAttribute.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | using Microsoft.AspNetCore.Mvc.Filters; 3 | using System.Linq; 4 | 5 | namespace SocialNetwork.Web.Infrastructure.Filters 6 | { 7 | public class ValidateModelStateAttribute : ActionFilterAttribute 8 | { 9 | public override void OnActionExecuting(ActionExecutingContext context) 10 | { 11 | if (!context.ModelState.IsValid) 12 | { 13 | var controller = context.Controller as Controller; 14 | 15 | if (controller == null) 16 | { 17 | return; 18 | } 19 | 20 | var model = context 21 | .ActionArguments 22 | .FirstOrDefault(a => a.Key.ToLower().Contains("model")) 23 | .Value; 24 | 25 | if (model == null) 26 | { 27 | return; 28 | } 29 | 30 | context.Result = controller.View(model); 31 | } 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /SocialNetwork.Web/Infrastructure/GlobalConstants.cs: -------------------------------------------------------------------------------- 1 | namespace SocialNetwork.Web.Infrastructure 2 | { 3 | public class GlobalConstants 4 | { 5 | public const string AdminRole = "Administrator"; 6 | public const string AdminArea = "Admin"; 7 | public const string SocialNetworkEmail = "lavishstory@gmail.com"; 8 | public const string Authorization = "Authorization"; 9 | public const string FullAuthorization = "Full"; 10 | public const string FriendAuthorization = "Friend"; 11 | public const string NoAuthorization = "None"; 12 | public const string SearchTerm = "searchTerm"; 13 | public const string CompsiteChatId = "compsiteChatId"; 14 | public const string CounterPartFullName = "countePartFullName"; 15 | } 16 | } -------------------------------------------------------------------------------- /SocialNetwork.Web/Infrastructure/Mapping/AutoMapperProfile.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using SocialNetwork.Common.Mapping; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Reflection; 7 | 8 | namespace SocialNetwork.Web.Infrastructure.Mapping 9 | { 10 | public class AutoMapperProfile : Profile 11 | { 12 | //this.CreateMap(); 13 | 14 | private readonly string[] Assemblies = new[] 15 | { 16 | "SocialNetwork.Web", 17 | "SocialNetwork.Data", 18 | "SocialNetwork.Services", 19 | "SocialNetwork.Common" 20 | }; 21 | 22 | public AutoMapperProfile() 23 | { 24 | var types = new List(); 25 | 26 | foreach (var assemblyName in this.Assemblies) 27 | { 28 | types.AddRange(Assembly.Load(assemblyName).GetTypes()); 29 | } 30 | 31 | types 32 | .Where(t => t.IsClass 33 | && !t.IsAbstract 34 | && t.GetInterfaces().Where(i => i.IsGenericType).Select(i => i.GetGenericTypeDefinition()).Contains(typeof(IMapFrom<>))) 35 | .Select(t => new 36 | { 37 | Source = t 38 | .GetInterfaces() 39 | .Where(i => i.IsGenericType) 40 | .Select(i => new 41 | { 42 | Definition = i.GetGenericTypeDefinition(), 43 | Arguments = i.GetGenericArguments() 44 | }) 45 | .Where(i => i.Definition == typeof(IMapFrom<>)) 46 | .SelectMany(i => i.Arguments) 47 | .First(), 48 | Destination = t 49 | }) 50 | .ToList() 51 | .ForEach(m => this.CreateMap(m.Source, m.Destination)); 52 | 53 | types 54 | .Where(t => t.IsClass && !t.IsAbstract && typeof(IHaveCustomMapping).IsAssignableFrom(t)) 55 | .Select(Activator.CreateInstance) 56 | .Cast() 57 | .ToList() 58 | .ForEach(m => m.ConfigureMapping(this)); 59 | } 60 | } 61 | } -------------------------------------------------------------------------------- /SocialNetwork.Web/Models/AccountViewModels/ExternalLoginViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace SocialNetwork.Web.Models.AccountViewModels 8 | { 9 | public class ExternalLoginViewModel 10 | { 11 | [Required] 12 | [EmailAddress] 13 | public string Email { get; set; } 14 | 15 | public string Name { get; set; } 16 | 17 | public byte[] Picture { get; set; } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /SocialNetwork.Web/Models/AccountViewModels/ForgotPasswordViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace SocialNetwork.Web.Models.AccountViewModels 8 | { 9 | public class ForgotPasswordViewModel 10 | { 11 | [Required] 12 | [EmailAddress] 13 | public string Email { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /SocialNetwork.Web/Models/AccountViewModels/LoginViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace SocialNetwork.Web.Models.AccountViewModels 8 | { 9 | public class LoginViewModel 10 | { 11 | [Required] 12 | public string Username { get; set; } 13 | 14 | [Required] 15 | [DataType(DataType.Password)] 16 | public string Password { get; set; } 17 | 18 | [Display(Name = "Remember me?")] 19 | public bool RememberMe { get; set; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SocialNetwork.Web/Models/AccountViewModels/LoginWith2faViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace SocialNetwork.Web.Models.AccountViewModels 8 | { 9 | public class LoginWith2faViewModel 10 | { 11 | [Required] 12 | [StringLength(7, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)] 13 | [DataType(DataType.Text)] 14 | [Display(Name = "Authenticator code")] 15 | public string TwoFactorCode { get; set; } 16 | 17 | [Display(Name = "Remember this machine")] 18 | public bool RememberMachine { get; set; } 19 | 20 | public bool RememberMe { get; set; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /SocialNetwork.Web/Models/AccountViewModels/LoginWithRecoveryCodeViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace SocialNetwork.Web.Models.AccountViewModels 8 | { 9 | public class LoginWithRecoveryCodeViewModel 10 | { 11 | [Required] 12 | [DataType(DataType.Text)] 13 | [Display(Name = "Recovery Code")] 14 | public string RecoveryCode { get; set; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /SocialNetwork.Web/Models/AccountViewModels/RegisterViewModel.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Http; 2 | using SocialNetwork.Web.Infrastructure.CustomValidationAttributes; 3 | using System.ComponentModel.DataAnnotations; 4 | 5 | namespace SocialNetwork.Web.Models.AccountViewModels 6 | { 7 | public class RegisterViewModel 8 | { 9 | [Required] 10 | [EmailAddress] 11 | [Display(Name = "Email")] 12 | public string Email { get; set; } 13 | 14 | [Required] 15 | [Display(Name = "First Name")] 16 | [MinLength(2), MaxLength(50)] 17 | public string FirstName { get; set; } 18 | 19 | [Required] 20 | [Display(Name = "Last Name")] 21 | [MinLength(2), MaxLength(50)] 22 | public string LastName { get; set; } 23 | 24 | [Required] 25 | [Display(Name = "Username")] 26 | [MinLength(2), MaxLength(50)] 27 | public string Username { get; set; } 28 | 29 | [Required] 30 | [Age] 31 | public int Age { get; set; } 32 | 33 | [Required] 34 | [Display(Name = "Upload a photo")] 35 | public IFormFile Photo { get; set; } 36 | 37 | [Required] 38 | [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 2)] 39 | [DataType(DataType.Password)] 40 | [Display(Name = "Password")] 41 | public string Password { get; set; } 42 | 43 | [DataType(DataType.Password)] 44 | [Display(Name = "Confirm password")] 45 | [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")] 46 | public string ConfirmPassword { get; set; } 47 | } 48 | } -------------------------------------------------------------------------------- /SocialNetwork.Web/Models/AccountViewModels/ResetPasswordViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace SocialNetwork.Web.Models.AccountViewModels 8 | { 9 | public class ResetPasswordViewModel 10 | { 11 | [Required] 12 | [EmailAddress] 13 | public string Email { get; set; } 14 | 15 | [Required] 16 | [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)] 17 | [DataType(DataType.Password)] 18 | public string Password { get; set; } 19 | 20 | [DataType(DataType.Password)] 21 | [Display(Name = "Confirm password")] 22 | [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")] 23 | public string ConfirmPassword { get; set; } 24 | 25 | public string Code { get; set; } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /SocialNetwork.Web/Models/Comment/PostCommentCreateModel.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using SocialNetwork.Common.Mapping; 3 | using SocialNetwork.Data.Entities.Enums; 4 | using SocialNetwork.Services.Models; 5 | using SocialNetwork.Web.Extensions; 6 | using System; 7 | using System.ComponentModel.DataAnnotations; 8 | 9 | namespace SocialNetwork.Web.Models.Comment 10 | { 11 | public class PostCommentCreateModel : IMapFrom, IHaveCustomMapping 12 | { 13 | public int Id { get; set; } 14 | 15 | public string Text { get; set; } 16 | 17 | public DateTime Date { get; set; } 18 | 19 | public int Likes { get; set; } 20 | 21 | public string Photo { get; set; } 22 | 23 | public string UserProfilePicture { get; set; } 24 | 25 | public string UserFullName { get; set; } 26 | 27 | public Feeling Feeling { get; set; } 28 | 29 | [Required] 30 | [Display(Name ="Comment:")] 31 | public string CommentText { get; set; } 32 | 33 | public void ConfigureMapping(Profile profile) 34 | { 35 | profile.CreateMap() 36 | .ForMember(p => p.CommentText, cfg => cfg.Ignore()) 37 | .ForMember(p => p.Photo, cfg => cfg.MapFrom(p => p.Photo.ToRenderablePictureString())) 38 | .ForMember(p => p.UserProfilePicture, cfg => cfg.MapFrom(p => p.UserProfilePicture.ToRenderablePictureString())); 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /SocialNetwork.Web/Models/ErrorViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace SocialNetwork.Web.Models 4 | { 5 | public class ErrorViewModel 6 | { 7 | public string RequestId { get; set; } 8 | 9 | public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); 10 | } 11 | } -------------------------------------------------------------------------------- /SocialNetwork.Web/Models/Events/EventFormModel.cs: -------------------------------------------------------------------------------- 1 | using SocialNetwork.Data; 2 | using System; 3 | using System.ComponentModel.DataAnnotations; 4 | 5 | namespace SocialNetwork.Web.Models.Events 6 | { 7 | public class EventFormModel 8 | { 9 | [Url] 10 | [Display(Name ="Image URL")] 11 | public string ImageUrl { get; set; } 12 | 13 | [Required] 14 | [MaxLength(DataConstants.MaxEventTitleLength)] 15 | public string Title { get; set; } 16 | 17 | [Required] 18 | public string Location { get; set; } 19 | 20 | [Required] 21 | public string Description { get; set; } 22 | 23 | [Required] 24 | [Display(Name = "Start Date")] 25 | public DateTime DateStarts { get; set; } 26 | 27 | [Required] 28 | [Display(Name = "End Date")] 29 | public DateTime DateEnds { get; set; } 30 | } 31 | } -------------------------------------------------------------------------------- /SocialNetwork.Web/Models/HomeViewModels/EmailModel.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace SocialNetwork.Web.Models.HomeViewModels 4 | { 5 | public class EmailModel 6 | { 7 | [Required] 8 | [StringLength(50)] 9 | [Display(Name = "Name")] 10 | public string Name { get; set; } 11 | 12 | [Required] 13 | [EmailAddress] 14 | [Display(Name = "Email")] 15 | public string Email { get; set; } 16 | 17 | [Required] 18 | [StringLength(50)] 19 | [Display(Name = "Subject")] 20 | public string Subject { get; set; } 21 | 22 | [Required] 23 | [Display(Name = "Message")] 24 | public string Message { get; set; } 25 | } 26 | } -------------------------------------------------------------------------------- /SocialNetwork.Web/Models/ManageViewModels/ChangePasswordViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace SocialNetwork.Web.Models.ManageViewModels 8 | { 9 | public class ChangePasswordViewModel 10 | { 11 | [Required] 12 | [DataType(DataType.Password)] 13 | [Display(Name = "Current password")] 14 | public string OldPassword { get; set; } 15 | 16 | [Required] 17 | [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)] 18 | [DataType(DataType.Password)] 19 | [Display(Name = "New password")] 20 | public string NewPassword { get; set; } 21 | 22 | [DataType(DataType.Password)] 23 | [Display(Name = "Confirm new password")] 24 | [Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")] 25 | public string ConfirmPassword { get; set; } 26 | 27 | public string StatusMessage { get; set; } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /SocialNetwork.Web/Models/ManageViewModels/EnableAuthenticatorViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.ComponentModel.DataAnnotations; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | 8 | namespace SocialNetwork.Web.Models.ManageViewModels 9 | { 10 | public class EnableAuthenticatorViewModel 11 | { 12 | [Required] 13 | [StringLength(7, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)] 14 | [DataType(DataType.Text)] 15 | [Display(Name = "Verification Code")] 16 | public string Code { get; set; } 17 | 18 | [ReadOnly(true)] 19 | public string SharedKey { get; set; } 20 | 21 | public string AuthenticatorUri { get; set; } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /SocialNetwork.Web/Models/ManageViewModels/ExternalLoginsViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Authentication; 6 | using Microsoft.AspNetCore.Identity; 7 | 8 | namespace SocialNetwork.Web.Models.ManageViewModels 9 | { 10 | public class ExternalLoginsViewModel 11 | { 12 | public IList CurrentLogins { get; set; } 13 | 14 | public IList OtherLogins { get; set; } 15 | 16 | public bool ShowRemoveButton { get; set; } 17 | 18 | public string StatusMessage { get; set; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /SocialNetwork.Web/Models/ManageViewModels/GenerateRecoveryCodesViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace SocialNetwork.Web.Models.ManageViewModels 8 | { 9 | public class GenerateRecoveryCodesViewModel 10 | { 11 | public string[] RecoveryCodes { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /SocialNetwork.Web/Models/ManageViewModels/IndexViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace SocialNetwork.Web.Models.ManageViewModels 8 | { 9 | public class IndexViewModel 10 | { 11 | public string Username { get; set; } 12 | 13 | public bool IsEmailConfirmed { get; set; } 14 | 15 | [Required] 16 | [EmailAddress] 17 | public string Email { get; set; } 18 | 19 | [Phone] 20 | [Display(Name = "Phone number")] 21 | public string PhoneNumber { get; set; } 22 | 23 | public string StatusMessage { get; set; } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /SocialNetwork.Web/Models/ManageViewModels/RemoveLoginViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace SocialNetwork.Web.Models.ManageViewModels 8 | { 9 | public class RemoveLoginViewModel 10 | { 11 | public string LoginProvider { get; set; } 12 | public string ProviderKey { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /SocialNetwork.Web/Models/ManageViewModels/SetPasswordViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace SocialNetwork.Web.Models.ManageViewModels 8 | { 9 | public class SetPasswordViewModel 10 | { 11 | [Required] 12 | [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)] 13 | [DataType(DataType.Password)] 14 | [Display(Name = "New password")] 15 | public string NewPassword { get; set; } 16 | 17 | [DataType(DataType.Password)] 18 | [Display(Name = "Confirm new password")] 19 | [Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")] 20 | public string ConfirmPassword { get; set; } 21 | 22 | public string StatusMessage { get; set; } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /SocialNetwork.Web/Models/ManageViewModels/TwoFactorAuthenticationViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace SocialNetwork.Web.Models.ManageViewModels 8 | { 9 | public class TwoFactorAuthenticationViewModel 10 | { 11 | public bool HasAuthenticator { get; set; } 12 | 13 | public int RecoveryCodesLeft { get; set; } 14 | 15 | public bool Is2faEnabled { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /SocialNetwork.Web/Models/Messanger/MessangerModel.cs: -------------------------------------------------------------------------------- 1 | using SocialNetwork.Data; 2 | using SocialNetwork.Services.Infrastructure.CustomDataStructures; 3 | using SocialNetwork.Services.Models; 4 | using System.ComponentModel.DataAnnotations; 5 | 6 | namespace SocialNetwork.Web.Models.Messanger 7 | { 8 | public class MessangerModel 9 | { 10 | public PaginatedList Messages { get; set; } 11 | 12 | [Required] 13 | [MaxLength(DataConstants.MaxMessageLength)] 14 | public string MessageText { get; set; } 15 | } 16 | } -------------------------------------------------------------------------------- /SocialNetwork.Web/Models/PostsViewModels/PostFormModel.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Http; 2 | using SocialNetwork.Data.Entities.Enums; 3 | using System.ComponentModel.DataAnnotations; 4 | 5 | namespace SocialNetwork.Web.Models.PostsViewModels 6 | { 7 | public class PostFormModel 8 | { 9 | [Required] 10 | [Display(Name = "What do you think?")] 11 | public string Text { get; set; } 12 | 13 | [Display(Name = "How do you feel?")] 14 | public Feeling Feeling { get; set; } 15 | 16 | [Display(Name = "Upload a photo")] 17 | public IFormFile Photo { get; set; } 18 | } 19 | } -------------------------------------------------------------------------------- /SocialNetwork.Web/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using Microsoft.AspNetCore; 7 | using Microsoft.AspNetCore.Hosting; 8 | using Microsoft.Extensions.Configuration; 9 | using Microsoft.Extensions.Logging; 10 | 11 | namespace SocialNetwork.Web 12 | { 13 | public class Program 14 | { 15 | public static void Main(string[] args) 16 | { 17 | BuildWebHost(args).Run(); 18 | } 19 | 20 | public static IWebHost BuildWebHost(string[] args) => 21 | WebHost.CreateDefaultBuilder(args) 22 | .UseStartup() 23 | .Build(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /SocialNetwork.Web/ScaffoldingReadMe.txt: -------------------------------------------------------------------------------- 1 | Scaffolding has generated all the files and added the required dependencies. 2 | 3 | However the Application's Startup code may required additional changes for things to work end to end. 4 | Add the following code to the Configure method in your Application's Startup class if not already done: 5 | 6 | app.UseMvc(routes => 7 | { 8 | route.MapRoute( 9 | name : "areas", 10 | template : "{area:exists}/{controller=Home}/{action=Index}/{id?}" 11 | ); 12 | }); 13 | -------------------------------------------------------------------------------- /SocialNetwork.Web/SocialNetwork.Web.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp2.0 5 | aspnet-SocialNetwork.Web-BAA67EAE-91A8-401C-B7F0-B000092ADDD3 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /SocialNetwork.Web/Startup.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using Microsoft.AspNetCore.Builder; 3 | using Microsoft.AspNetCore.Hosting; 4 | using Microsoft.AspNetCore.Identity; 5 | using Microsoft.AspNetCore.Mvc; 6 | using Microsoft.EntityFrameworkCore; 7 | using Microsoft.Extensions.Configuration; 8 | using Microsoft.Extensions.DependencyInjection; 9 | using PaulMiami.AspNetCore.Mvc.Recaptcha; 10 | using SocialNetwork.Data; 11 | using SocialNetwork.Data.Entities; 12 | using SocialNetwork.Web.Extensions; 13 | using SocialNetwork.Web.Hub; 14 | 15 | namespace SocialNetwork.Web 16 | { 17 | public class Startup 18 | { 19 | public Startup(IConfiguration configuration) 20 | { 21 | Configuration = configuration; 22 | } 23 | 24 | public IConfiguration Configuration { get; } 25 | 26 | // This method gets called by the runtime. Use this method to add services to the container. 27 | public void ConfigureServices(IServiceCollection services) 28 | { 29 | services.AddDbContext(options => 30 | options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))); 31 | 32 | services.AddIdentity(options => 33 | { 34 | options.Password.RequireDigit = false; 35 | options.Password.RequiredLength = 2; 36 | options.Password.RequireLowercase = false; 37 | options.Password.RequireUppercase = false; 38 | options.Password.RequireNonAlphanumeric = false; 39 | }) 40 | .AddEntityFrameworkStores() 41 | .AddDefaultTokenProviders(); 42 | 43 | // Add application services. 44 | services.AddDomainServices(); 45 | 46 | services.AddAutoMapper(); 47 | 48 | services.AddSignalR(); 49 | 50 | services.AddMvc(options => 51 | { 52 | options.Filters.Add(); 53 | }); 54 | 55 | services.AddRecaptcha(new RecaptchaOptions 56 | { 57 | SiteKey = Configuration["Recaptcha:SiteKey"], 58 | SecretKey = Configuration["Recaptcha:SecretKey"] 59 | }); 60 | 61 | services.AddAuthentication().AddFacebook(fo => 62 | { 63 | fo.AppId = Configuration["Authentication:Facebook:AppId"]; 64 | fo.AppSecret = Configuration["Authentication:Facebook:AppSecret"]; 65 | }); 66 | } 67 | 68 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 69 | public void Configure(IApplicationBuilder app, IHostingEnvironment env) 70 | { 71 | app.UseDatabaseMigrations(); 72 | 73 | if (env.IsDevelopment()) 74 | { 75 | app.UseDeveloperExceptionPage(); 76 | app.UseBrowserLink(); 77 | app.UseDatabaseErrorPage(); 78 | } 79 | else 80 | { 81 | app.UseExceptionHandler("/Home/Error"); 82 | } 83 | 84 | app.UseStaticFiles(); 85 | 86 | app.UseSignalR(routes => 87 | { 88 | routes.MapHub("chat"); 89 | }); 90 | 91 | app.UseAuthentication(); 92 | 93 | app.UseMvc(routes => 94 | { 95 | routes.MapRoute( 96 | name: "areas", 97 | template: "{area:exists}/{controller=Home}/{action=Index}/{id?}"); 98 | 99 | routes.MapRoute( 100 | name: "default", 101 | template: "{controller=Home}/{action=Index}/{id?}"); 102 | }); 103 | } 104 | } 105 | } -------------------------------------------------------------------------------- /SocialNetwork.Web/Views/Account/AccessDenied.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewData["Title"] = "Access denied"; 3 | } 4 | 5 |
6 |

ViewData["Title"]

7 |

You do not have access to this resource.

8 |
9 | -------------------------------------------------------------------------------- /SocialNetwork.Web/Views/Account/ConfirmEmail.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewData["Title"] = "Confirm email"; 3 | } 4 | 5 |

@ViewData["Title"]

6 |
7 |

8 | Thank you for confirming your email. 9 |

10 |
11 | -------------------------------------------------------------------------------- /SocialNetwork.Web/Views/Account/ExternalLogin.cshtml: -------------------------------------------------------------------------------- 1 | @model ExternalLoginViewModel 2 | @{ 3 | ViewData["Title"] = "Register"; 4 | } 5 | 6 |

@ViewData["Title"]

7 |

Associate your @ViewData["LoginProvider"] account.

8 |
9 | 10 |

11 | You've successfully authenticated with @ViewData["LoginProvider"]. 12 | Please enter an email address for this site below and click the Register button to finish 13 | logging in. 14 |

15 | 16 |
17 |
18 |
19 |
20 |
21 | 22 | 23 | 24 |
25 | 26 |
27 |
28 |
29 | 30 | @section Scripts { 31 | @await Html.PartialAsync("_ValidationScriptsPartial") 32 | } 33 | -------------------------------------------------------------------------------- /SocialNetwork.Web/Views/Account/ForgotPassword.cshtml: -------------------------------------------------------------------------------- 1 | @model ForgotPasswordViewModel 2 | @{ 3 | ViewData["Title"] = "Forgot your password?"; 4 | } 5 | 6 |

@ViewData["Title"]

7 |

Enter your email.

8 |
9 |
10 |
11 |
12 |
13 |
14 | 15 | 16 | 17 |
18 | 19 |
20 |
21 |
22 | 23 | @section Scripts { 24 | @await Html.PartialAsync("_ValidationScriptsPartial") 25 | } 26 | -------------------------------------------------------------------------------- /SocialNetwork.Web/Views/Account/ForgotPasswordConfirmation.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewData["Title"] = "Forgot password confirmation"; 3 | } 4 | 5 |

@ViewData["Title"]

6 |

7 | Please check your email to reset your password. 8 |

9 | -------------------------------------------------------------------------------- /SocialNetwork.Web/Views/Account/Lockout.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewData["Title"] = "Locked out"; 3 | } 4 | 5 |
6 |

@ViewData["Title"]

7 |

This account has been locked out, please try again later.

8 |
9 | -------------------------------------------------------------------------------- /SocialNetwork.Web/Views/Account/Login.cshtml: -------------------------------------------------------------------------------- 1 | @using System.Collections.Generic 2 | @using System.Linq 3 | @using Microsoft.AspNetCore.Http 4 | @using Microsoft.AspNetCore.Http.Authentication 5 | @model LoginViewModel 6 | @inject SignInManager SignInManager 7 | 8 | @{ 9 | ViewData["Title"] = "Log in"; 10 | } 11 | 12 |

@ViewData["Title"]

13 |
14 |
15 |
16 |
17 |

Use a local account to log in.

18 |
19 |
20 |
21 | 22 | 23 | 24 |
25 |
26 | 27 | 28 | 29 |
30 |
31 |
32 | 36 |
37 |
38 |
39 | 40 |
41 |
42 |

43 | Forgot your password? 44 |

45 |

46 | Register as a new user? 47 |

48 |
49 |
50 |
51 |
52 |
53 |
54 |

Use another service to log in.

55 |
56 | @{ 57 | var loginProviders = (await SignInManager.GetExternalAuthenticationSchemesAsync()).ToList(); 58 | if (loginProviders.Count == 0) 59 | { 60 |
61 |

62 | There are no external authentication services configured. See this article 63 | for details on setting up this ASP.NET application to support logging in via external services. 64 |

65 |
66 | } 67 | else 68 | { 69 |
70 |
71 |

72 | @foreach (var provider in loginProviders) 73 | { 74 | 75 | } 76 |

77 |
78 |
79 | } 80 | } 81 |
82 |
83 |
84 | 85 | @section Scripts { 86 | @await Html.PartialAsync("_ValidationScriptsPartial") 87 | } 88 | -------------------------------------------------------------------------------- /SocialNetwork.Web/Views/Account/LoginWithRecoveryCode.cshtml: -------------------------------------------------------------------------------- 1 | @model LoginWithRecoveryCodeViewModel 2 | @{ 3 | ViewData["Title"] = "Recovery code verification"; 4 | } 5 | 6 |

@ViewData["Title"]

7 |
8 |

9 | You have requested to login with a recovery code. This login will not be remembered until you provide 10 | an authenticator app code at login or disable 2FA and login again. 11 |

12 |
13 |
14 |
15 |
16 |
17 | 18 | 19 | 20 |
21 | 22 |
23 |
24 |
25 | 26 | @section Scripts { 27 | @await Html.PartialAsync("_ValidationScriptsPartial") 28 | } -------------------------------------------------------------------------------- /SocialNetwork.Web/Views/Account/Register.cshtml: -------------------------------------------------------------------------------- 1 | @model RegisterViewModel 2 | @{ 3 | ViewData["Title"] = "Inscription"; 4 | } 5 | 6 |

@ViewData["Title"]

7 | 8 |
9 |
10 |
11 |

Create a new account.

12 |
13 |
14 |
15 | 16 | 17 | 18 |
19 |
20 | 21 | 22 | 23 |
24 |
25 | 26 | 27 | 28 |
29 |
30 | 31 | 32 | 33 |
34 |
35 | 36 | 37 | 38 |
39 |
40 | 41 | 42 | 43 |
44 |
45 | 46 | 47 | 48 |
49 |
50 | 51 | 52 | 53 |
54 | 55 |
56 | 57 |
58 | 59 |
60 | 61 |
62 |
63 |
64 | 65 | @section Scripts { 66 | @await Html.PartialAsync("_ValidationScriptsPartial"), 67 | 68 | } -------------------------------------------------------------------------------- /SocialNetwork.Web/Views/Account/ResetPassword.cshtml: -------------------------------------------------------------------------------- 1 | @model ResetPasswordViewModel 2 | @{ 3 | ViewData["Title"] = "Reset password"; 4 | } 5 | 6 |

@ViewData["Title"]

7 |

Reset your password.

8 |
9 |
10 |
11 |
12 |
13 | 14 |
15 | 16 | 17 | 18 |
19 |
20 | 21 | 22 | 23 |
24 |
25 | 26 | 27 | 28 |
29 | 30 |
31 |
32 |
33 | 34 | @section Scripts { 35 | @await Html.PartialAsync("_ValidationScriptsPartial") 36 | } 37 | -------------------------------------------------------------------------------- /SocialNetwork.Web/Views/Account/ResetPasswordConfirmation.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewData["Title"] = "Reset password confirmation"; 3 | } 4 | 5 |

@ViewData["Title"]

6 |

7 | Your password has been reset. Please click here to log in. 8 |

9 | -------------------------------------------------------------------------------- /SocialNetwork.Web/Views/Account/SignedOut.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewData["Title"] = "Signed out"; 3 | } 4 | 5 |

@ViewData["Title"]

6 |

7 | You have successfully signed out. 8 |

9 | -------------------------------------------------------------------------------- /SocialNetwork.Web/Views/Comment/Create.cshtml: -------------------------------------------------------------------------------- 1 | @model PostCommentCreateModel 2 | @{ 3 | ViewData["Title"] = "Submit a Comment"; 4 | } 5 | 6 |
7 |

@ViewData["Title"]

8 | 9 |
10 |
11 |
12 |
13 |
14 | Avatar 15 |
16 |
17 |
@Model.UserFullName is feeling @Model.Feeling.ToString()
18 |
@Model.Date.ToShortDateString()
19 |
20 |
21 |
22 |
23 |

@Model.Text

24 |
25 |
26 | 27 | @if (!string.IsNullOrEmpty(Model.Photo) && Model.Photo != null) 28 | { 29 | 30 |
31 | Avatar 32 |
33 | 34 | } 35 |
36 |
37 | @Model.Likes Likes 38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | 50 | 51 | 52 |
53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | Cancel 63 |
64 | 65 |
66 |
67 | 68 | @section Scripts { 69 | @await Html.PartialAsync("_ValidationScriptsPartial") 70 | } -------------------------------------------------------------------------------- /SocialNetwork.Web/Views/Events/Create.cshtml: -------------------------------------------------------------------------------- 1 | @model EventFormModel 2 | @{ 3 | ViewData["Title"] = "Create Your Event"; 4 | } 5 | 6 |

@ViewData["Title"]

7 | 8 |
9 |
10 |
11 |
12 |
13 |
14 | 15 | 16 | 17 |
18 |
19 | 20 | 21 | 22 |
23 |
24 | 25 | 26 | 27 |
28 |
29 | 30 | 31 | 32 |
33 |
34 | 35 | 36 | 37 |
38 |
39 | 40 | 41 | 42 |
43 |
44 | 45 | Cancel 46 |
47 |
48 |
49 | 50 | @section Scripts { 51 | @await Html.PartialAsync("_ValidationScriptsPartial") 52 | } -------------------------------------------------------------------------------- /SocialNetwork.Web/Views/Events/Details.cshtml: -------------------------------------------------------------------------------- 1 | @model EventModel 2 |
3 |
4 |
5 |

@Model.Title

6 | Event 7 |

@Model.Location

8 |

@Model.DateStarts.ToShortDateString()

9 |

@Model.Description

10 | Participants: @Model.ParticipantsCount 11 |
12 |
13 | @if (!Model.ParticipantId.Contains(User.GetUserId())) 14 | { 15 | Going 16 | } 17 | 18 | Back 19 |
20 |
21 |
-------------------------------------------------------------------------------- /SocialNetwork.Web/Views/Home/Contact.cshtml: -------------------------------------------------------------------------------- 1 | @model EmailModel 2 | @{ 3 | ViewData["Title"] = "Contact us"; 4 | } 5 | 6 | 13 |
14 |
15 |
16 |

@ViewData["Title"]

17 |
Please use the following form to send us an email.
18 |
19 |
20 |
21 | 22 | 23 | 24 |
25 |
26 | 27 | 28 | 29 |
30 |
31 | 32 | 33 | 34 |
35 |
36 | 37 | 38 | 39 |
40 | 41 |
42 | 43 |
44 | 45 |
46 | 47 |
48 |

@ViewData["SuccessMessage"]

49 |
50 |
51 | @section Scripts { 52 | @await Html.PartialAsync("_ValidationScriptsPartial"), 53 | 54 | } -------------------------------------------------------------------------------- /SocialNetwork.Web/Views/Manage/ChangePassword.cshtml: -------------------------------------------------------------------------------- 1 | @model ChangePasswordViewModel 2 | @{ 3 | ViewData["Title"] = "Change password"; 4 | ViewData.AddActivePage(ManageNavPages.ChangePassword); 5 | } 6 | 7 |

@ViewData["Title"]

8 | @Html.Partial("_StatusMessage", Model.StatusMessage) 9 |
10 |
11 |
12 |
13 |
14 | 15 | 16 | 17 |
18 |
19 | 20 | 21 | 22 |
23 |
24 | 25 | 26 | 27 |
28 | 29 |
30 |
31 |
32 | 33 | @section Scripts { 34 | @await Html.PartialAsync("_ValidationScriptsPartial") 35 | } 36 | -------------------------------------------------------------------------------- /SocialNetwork.Web/Views/Manage/Disable2fa.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewData["Title"] = "Disable two-factor authentication (2FA)"; 3 | ViewData.AddActivePage(ManageNavPages.TwoFactorAuthentication); 4 | } 5 | 6 |

@ViewData["Title"]

7 | 8 | 19 | 20 |
21 |
22 | 23 |
24 |
25 | -------------------------------------------------------------------------------- /SocialNetwork.Web/Views/Manage/EnableAuthenticator.cshtml: -------------------------------------------------------------------------------- 1 | @model EnableAuthenticatorViewModel 2 | @{ 3 | ViewData["Title"] = "Enable authenticator"; 4 | ViewData.AddActivePage(ManageNavPages.TwoFactorAuthentication); 5 | } 6 | 7 |

@ViewData["Title"]

8 |
9 |

To use an authenticator app go through the following steps:

10 |
    11 |
  1. 12 |

    13 | Download a two-factor authenticator app like Microsoft Authenticator for 14 | Windows Phone, 15 | Android and 16 | iOS or 17 | Google Authenticator for 18 | Android and 19 | iOS. 20 |

    21 |
  2. 22 |
  3. 23 |

    Scan the QR Code or enter this key @Model.SharedKey into your two factor authenticator app. Spaces and casing do not matter.

    24 |
    To enable QR code generation please read our documentation.
    25 |
    26 |
    27 |
  4. 28 |
  5. 29 |

    30 | Once you have scanned the QR code or input the key above, your two factor authentication app will provide you 31 | with a unique code. Enter the code in the confirmation box below. 32 |

    33 |
    34 |
    35 |
    36 |
    37 | 38 | 39 | 40 |
    41 | 42 |
    43 |
    44 |
    45 |
    46 |
  6. 47 |
48 |
49 | 50 | @section Scripts { 51 | @await Html.PartialAsync("_ValidationScriptsPartial") 52 | } 53 | -------------------------------------------------------------------------------- /SocialNetwork.Web/Views/Manage/ExternalLogins.cshtml: -------------------------------------------------------------------------------- 1 | @model ExternalLoginsViewModel 2 | @{ 3 | ViewData["Title"] = "Manage your external logins"; 4 | ViewData.AddActivePage(ManageNavPages.ExternalLogins); 5 | } 6 | 7 | @Html.Partial("_StatusMessage", Model.StatusMessage) 8 | @if (Model.CurrentLogins?.Count > 0) 9 | { 10 |

Registered Logins

11 | 12 | 13 | @foreach (var login in Model.CurrentLogins) 14 | { 15 | 16 | 17 | 33 | 34 | } 35 | 36 |
@login.LoginProvider 18 | @if (Model.ShowRemoveButton) 19 | { 20 |
21 |
22 | 23 | 24 | 25 |
26 |
27 | } 28 | else 29 | { 30 | @:   31 | } 32 |
37 | } 38 | @if (Model.OtherLogins?.Count > 0) 39 | { 40 |

Add another service to log in.

41 |
42 |
43 |
44 |

45 | @foreach (var provider in Model.OtherLogins) 46 | { 47 | 48 | } 49 |

50 |
51 |
52 | } 53 | -------------------------------------------------------------------------------- /SocialNetwork.Web/Views/Manage/GenerateRecoveryCodes.cshtml: -------------------------------------------------------------------------------- 1 | @model GenerateRecoveryCodesViewModel 2 | @{ 3 | ViewData["Title"] = "Recovery codes"; 4 | ViewData.AddActivePage(ManageNavPages.TwoFactorAuthentication); 5 | } 6 | 7 |

@ViewData["Title"]

8 | 17 |
18 |
19 | @for (var row = 0; row < Model.RecoveryCodes.Count(); row += 2) 20 | { 21 | @Model.RecoveryCodes[row] @Model.RecoveryCodes[row + 1]
22 | } 23 |
24 |
-------------------------------------------------------------------------------- /SocialNetwork.Web/Views/Manage/Index.cshtml: -------------------------------------------------------------------------------- 1 | @model IndexViewModel 2 | @{ 3 | ViewData["Title"] = "Profile"; 4 | ViewData.AddActivePage(ManageNavPages.Index); 5 | } 6 | 7 |

@ViewData["Title"]

8 | @Html.Partial("_StatusMessage", Model.StatusMessage) 9 |
10 |
11 |
12 |
13 |
14 | 15 | 16 |
17 |
18 | 19 | @if (Model.IsEmailConfirmed) 20 | { 21 |
22 | 23 | 24 |
25 | } 26 | else 27 | { 28 | 29 | 30 | } 31 | 32 |
33 |
34 | 35 | 36 | 37 |
38 | 39 |
40 |
41 |
42 | 43 | @section Scripts { 44 | @await Html.PartialAsync("_ValidationScriptsPartial") 45 | } 46 | -------------------------------------------------------------------------------- /SocialNetwork.Web/Views/Manage/ManageNavPages.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Mvc.Rendering; 6 | using Microsoft.AspNetCore.Mvc.ViewFeatures; 7 | 8 | namespace SocialNetwork.Web.Views.Manage 9 | { 10 | public static class ManageNavPages 11 | { 12 | public static string ActivePageKey => "ActivePage"; 13 | 14 | public static string Index => "Index"; 15 | 16 | public static string ChangePassword => "ChangePassword"; 17 | 18 | public static string ExternalLogins => "ExternalLogins"; 19 | 20 | public static string TwoFactorAuthentication => "TwoFactorAuthentication"; 21 | 22 | public static string IndexNavClass(ViewContext viewContext) => PageNavClass(viewContext, Index); 23 | 24 | public static string ChangePasswordNavClass(ViewContext viewContext) => PageNavClass(viewContext, ChangePassword); 25 | 26 | public static string ExternalLoginsNavClass(ViewContext viewContext) => PageNavClass(viewContext, ExternalLogins); 27 | 28 | public static string TwoFactorAuthenticationNavClass(ViewContext viewContext) => PageNavClass(viewContext, TwoFactorAuthentication); 29 | 30 | public static string PageNavClass(ViewContext viewContext, string page) 31 | { 32 | var activePage = viewContext.ViewData["ActivePage"] as string; 33 | return string.Equals(activePage, page, StringComparison.OrdinalIgnoreCase) ? "active" : null; 34 | } 35 | 36 | public static void AddActivePage(this ViewDataDictionary viewData, string activePage) => viewData[ActivePageKey] = activePage; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /SocialNetwork.Web/Views/Manage/ResetAuthenticator.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewData["Title"] = "Reset authenticator key"; 3 | ViewData.AddActivePage(ManageNavPages.TwoFactorAuthentication); 4 | } 5 | 6 |

@ViewData["Title"]

7 | 17 |
18 |
19 | 20 |
21 |
-------------------------------------------------------------------------------- /SocialNetwork.Web/Views/Manage/SetPassword.cshtml: -------------------------------------------------------------------------------- 1 | @model SetPasswordViewModel 2 | @{ 3 | ViewData["Title"] = "Set password"; 4 | ViewData.AddActivePage(ManageNavPages.ChangePassword); 5 | } 6 | 7 |

Set your password

8 | @Html.Partial("_StatusMessage", Model.StatusMessage) 9 |

10 | You do not have a local username/password for this site. Add a local 11 | account so you can log in without an external login. 12 |

13 |
14 |
15 |
16 |
17 |
18 | 19 | 20 | 21 |
22 |
23 | 24 | 25 | 26 |
27 | 28 |
29 |
30 |
31 | 32 | @section Scripts { 33 | @await Html.PartialAsync("_ValidationScriptsPartial") 34 | } 35 | -------------------------------------------------------------------------------- /SocialNetwork.Web/Views/Manage/_Layout.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "/Views/Shared/_Layout.cshtml"; 3 | } 4 | 5 |

Manage your account

6 | 7 |
8 |

Change your account settings

9 |
10 |
11 |
12 | @await Html.PartialAsync("_ManageNav") 13 |
14 |
15 | @RenderBody() 16 |
17 |
18 |
19 | 20 | @section Scripts { 21 | @RenderSection("Scripts", required: false) 22 | } 23 | 24 | -------------------------------------------------------------------------------- /SocialNetwork.Web/Views/Manage/_ManageNav.cshtml: -------------------------------------------------------------------------------- 1 | @using SocialNetwork.Web.Views.Manage 2 | @inject SignInManager SignInManager 3 | @{ 4 | var hasExternalLogins = (await SignInManager.GetExternalAuthenticationSchemesAsync()).Any(); 5 | } 6 | 7 | 15 | 16 | -------------------------------------------------------------------------------- /SocialNetwork.Web/Views/Manage/_StatusMessage.cshtml: -------------------------------------------------------------------------------- 1 | @model string 2 | 3 | @if (!String.IsNullOrEmpty(Model)) 4 | { 5 | var statusMessageClass = Model.StartsWith("Error") ? "danger" : "success"; 6 | 10 | } 11 | -------------------------------------------------------------------------------- /SocialNetwork.Web/Views/Manage/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @using SocialNetwork.Web.Views.Manage -------------------------------------------------------------------------------- /SocialNetwork.Web/Views/Messanger/Index.cshtml: -------------------------------------------------------------------------------- 1 | @model MessangerModel 2 | @{ 3 | ViewData["Title"] = "Messanger"; 4 | } 5 | 6 |
7 |
8 |
9 |

Social Network Messenger

10 |

@ViewData[GlobalConstants.CounterPartFullName]

11 | @if (Model.Messages.Any()) 12 | { 13 | 14 | @foreach (var m in Model.Messages) 15 | { 16 | if (m.SenderId == this.User.GetUserId()) 17 | { 18 |
19 | @m.SenderFullName - @m.DateSent 20 |
@m.MessageText
21 |
22 | } 23 | else 24 | { 25 |
26 | @m.SenderFullName - @m.DateSent 27 |
@m.MessageText
28 |
29 | } 30 | 31 | } 32 | 33 | } 34 | else 35 | { 36 |
37 |

38 |

Say hello to your friend in order to start chatting :)
39 |

40 |
41 | } 42 |
43 |
44 |
45 | 46 |
47 |
48 |
49 |
50 |
51 | 52 | 53 | 54 |
55 | 56 | Cancel 57 |
58 |
59 |
60 |
61 | 62 | @section Scripts { 63 | @await Html.PartialAsync("_ValidationScriptsPartial") 64 | } -------------------------------------------------------------------------------- /SocialNetwork.Web/Views/Posts/Create.cshtml: -------------------------------------------------------------------------------- 1 | @model PostFormModel 2 | @{ 3 | ViewData["Title"] = "Create Post"; 4 | } 5 |

@ViewData["Title"]

6 |
7 |
8 | @Html.Partial("_PostForm", Model) 9 |
10 |
11 | 12 | @section Scripts { 13 | @await Html.PartialAsync("_ValidationScriptsPartial") 14 | } -------------------------------------------------------------------------------- /SocialNetwork.Web/Views/Posts/Delete.cshtml: -------------------------------------------------------------------------------- 1 | @model PostFormModel 2 | @{ 3 | ViewData["Title"] = "Delete Post"; 4 | } 5 |

@ViewData["Title"]

6 |
7 |
8 |
9 |
10 |
11 |
12 | 13 | 14 | 15 |
16 |
17 | 18 | 19 | 20 |
21 |
22 | 23 | 24 |
25 |
26 |
27 |
28 | -------------------------------------------------------------------------------- /SocialNetwork.Web/Views/Posts/Edit.cshtml: -------------------------------------------------------------------------------- 1 | @model PostFormModel 2 | @{ 3 | ViewData["Title"] = "Edit Post"; 4 | } 5 |

@ViewData["Title"]

6 |
7 |
8 | @Html.Partial("_PostForm", Model) 9 |
10 |
11 | 12 | @section Scripts { 13 | @await Html.PartialAsync("_ValidationScriptsPartial") 14 | } 15 | -------------------------------------------------------------------------------- /SocialNetwork.Web/Views/Posts/_PostForm.cshtml: -------------------------------------------------------------------------------- 1 | @model PostFormModel 2 |
3 |
4 |
5 |
6 | 7 | 8 | 9 |
10 |
11 | 12 | 13 | 14 |
15 | 16 |
17 | 18 | .png and .jpeg accepted 19 | 20 | 21 |
22 | 23 |
24 | 25 | 26 |
27 |
-------------------------------------------------------------------------------- /SocialNetwork.Web/Views/Shared/Error.cshtml: -------------------------------------------------------------------------------- 1 | @model ErrorViewModel 2 | @{ 3 | ViewData["Title"] = "Error"; 4 | } 5 | 6 |

Error.

7 |

An error occurred while processing your request.

8 | 9 | @if (Model.ShowRequestId) 10 | { 11 |

12 | Request ID: @Model.RequestId 13 |

14 | } 15 | 16 |

Development Mode

17 |

18 | Swapping to Development environment will display more detailed information about the error that occurred. 19 |

20 |

21 | Development environment should not be enabled in deployed applications, as it can result in sensitive information from exceptions being displayed to end users. For local debugging, development environment can be enabled by setting the ASPNETCORE_ENVIRONMENT environment variable to Development, and restarting the application. 22 |

23 | -------------------------------------------------------------------------------- /SocialNetwork.Web/Views/Shared/_Layout.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | @ViewData["Title"] - SocialNetwork 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 29 | 30 | 31 | 50 |
51 | @RenderBody() 52 |
53 |
54 |

© 2017 - SocialNetwork

55 |
56 |
57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 71 | 77 | 78 | 79 | 80 | @RenderSection("Scripts", required: false) 81 | 82 | -------------------------------------------------------------------------------- /SocialNetwork.Web/Views/Shared/_LoginPartial.cshtml: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Identity 2 | @using SocialNetwork.Web.Models 3 | 4 | @inject SignInManager SignInManager 5 | @inject UserManager UserManager 6 | 7 | @if (SignInManager.IsSignedIn(User)) 8 | { 9 | 10 | 11 | 18 | 22 | } 23 | else 24 | { 25 | 29 | } -------------------------------------------------------------------------------- /SocialNetwork.Web/Views/Shared/_ValidationScriptsPartial.cshtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 12 | 18 | 19 | -------------------------------------------------------------------------------- /SocialNetwork.Web/Views/Users/Search.cshtml: -------------------------------------------------------------------------------- 1 | @model PaginatedList 2 | 3 | @{ 4 | ViewData["Title"] = "Search Users"; 5 | } 6 | 7 |

@ViewData["Title"]

8 | 9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | Find by Name or Username: 17 | 18 |
19 |
20 | | 21 | Back to Full List 22 |
23 |
24 |
25 |
26 |
27 |
28 | @if (Model.Any()) 29 | { 30 | 31 | var prevDisabled = !Model.HasPreviousPage ? "disabled" : ""; 32 | var nextDisabled = !Model.HasNextPage ? "disabled" : ""; 33 | 34 | @foreach (var user in Model) 35 | { 36 | 37 |
38 |
39 |
40 | Avatar 41 |
42 |
43 |
44 | @user.FullName 45 |
46 |
47 | Age: @user.Age 48 |
49 |
50 |
51 |
52 | Number of Posts: @user.NumberOfPosts 53 |
54 |
55 |
56 |
57 | 58 | } 59 | 60 |
61 | 75 |
76 | } 77 | else 78 | { 79 |
80 |
81 |
82 |

There are no user corresponding to your search!

83 |
84 |
85 |
86 | } 87 |
88 |
-------------------------------------------------------------------------------- /SocialNetwork.Web/Views/Users/_PostComments.cshtml: -------------------------------------------------------------------------------- 1 | @model List 2 | 4 | 5 | @if (Model.Count <= 2) 6 | { 7 | @foreach (var comment in Model) 8 | { 9 |
10 |
11 | Avatar 12 |
13 |
14 |
15 | @comment.UserFullName 16 | @comment.Text 17 |
18 |
@comment.Date.ToShortDateString()
19 |
20 |
21 |
22 | } 23 | } 24 | else 25 | { 26 | @for (int i = 0; i <= 1; i++) 27 | { 28 |
29 |
30 | Avatar 31 |
32 |
33 |
34 | @Model[i].UserFullName 35 | @Model[i].Text 36 |
37 |
@Model[i].Date.ToShortDateString()
38 |
39 |
40 |
41 | } 42 | 60 | } 61 | 62 | @if (Model.Count > 2) 63 | { 64 |
65 | 66 | 67 |
68 | } 69 | 70 | 77 | 78 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /SocialNetwork.Web/Views/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Identity 2 | @using SocialNetwork.Web 3 | @using SocialNetwork.Web.Infrastructure 4 | @using SocialNetwork.Web.Models.HomeViewModels 5 | @using SocialNetwork.Web.Models.AccountViewModels 6 | @using SocialNetwork.Web.Models.ManageViewModels 7 | @using SocialNetwork.Web.Models.PostsViewModels 8 | @using SocialNetwork.Web.Models.Comment 9 | @using SocialNetwork.Web.Models.Messanger 10 | @using SocialNetwork.Web.Models.Events 11 | @using SocialNetwork.Web.Models.InterestViewModels 12 | @using SocialNetwork.Web.Models 13 | @using SocialNetwork.Data.Entities 14 | @using SocialNetwork.Data.Entities.Enums 15 | @using SocialNetwork.Services.Models 16 | @using SocialNetwork.Web.Extensions 17 | @using SocialNetwork.Services.Infrastructure.CustomDataStructures 18 | @addTagHelper *, PaulMiami.AspNetCore.Mvc.Recaptcha 19 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 20 | -------------------------------------------------------------------------------- /SocialNetwork.Web/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "_Layout"; 3 | } 4 | -------------------------------------------------------------------------------- /SocialNetwork.Web/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "IncludeScopes": false, 4 | "LogLevel": { 5 | "Default": "Debug", 6 | "System": "Information", 7 | "Microsoft": "Information" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /SocialNetwork.Web/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "ConnectionStrings": { 3 | "DefaultConnection": "Server=.;Database=SocialNetwork;Trusted_Connection=True;MultipleActiveResultSets=true" 4 | }, 5 | "Logging": { 6 | "IncludeScopes": false, 7 | "LogLevel": { 8 | "Default": "Warning" 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /SocialNetwork.Web/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "asp.net", 3 | "private": true, 4 | "dependencies": { 5 | "bootstrap": "3.3.7", 6 | "jquery": "2.2.0", 7 | "jquery-validation": "1.14.0", 8 | "jquery-validation-unobtrusive": "3.2.6" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /SocialNetwork.Web/bundleconfig.json: -------------------------------------------------------------------------------- 1 | // Configure bundling and minification for the project. 2 | // More info at https://go.microsoft.com/fwlink/?LinkId=808241 3 | [ 4 | { 5 | "outputFileName": "wwwroot/css/site.min.css", 6 | // An array of relative input file paths. Globbing patterns supported 7 | "inputFiles": [ 8 | "wwwroot/css/site.css" 9 | ] 10 | }, 11 | { 12 | "outputFileName": "wwwroot/js/site.min.js", 13 | "inputFiles": [ 14 | "wwwroot/js/site.js" 15 | ], 16 | // Optionally specify minification options 17 | "minify": { 18 | "enabled": true, 19 | "renameLocals": true 20 | }, 21 | // Optionally generate .map file 22 | "sourceMap": false 23 | } 24 | ] 25 | -------------------------------------------------------------------------------- /SocialNetwork.Web/wwwroot/css/site.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding-top: 50px; 3 | padding-bottom: 20px; 4 | } 5 | 6 | /* Wrapping element */ 7 | /* Set some basic padding to keep content from hitting the edges */ 8 | .body-content { 9 | padding-left: 15px; 10 | padding-right: 15px; 11 | } 12 | 13 | /* Carousel */ 14 | .carousel-caption p { 15 | font-size: 20px; 16 | line-height: 1.4; 17 | } 18 | 19 | /* Make .svg files in the carousel display properly in older browsers */ 20 | .carousel-inner .item img[src$=".svg"] { 21 | width: 100%; 22 | } 23 | 24 | /* QR code generator */ 25 | #qrCode { 26 | margin: 15px; 27 | } 28 | 29 | /* Hide/rearrange for smaller screens */ 30 | @media screen and (max-width: 767px) { 31 | /* Hide captions */ 32 | .carousel-caption { 33 | display: none; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /SocialNetwork.Web/wwwroot/css/site.min.css: -------------------------------------------------------------------------------- 1 | body{padding-top:50px;padding-bottom:20px}.body-content{padding-left:15px;padding-right:15px}.carousel-caption p{font-size:20px;line-height:1.4}.carousel-inner .item img[src$=".svg"]{width:100%}#qrCode{margin:15px}@media screen and (max-width:767px){.carousel-caption{display:none}} -------------------------------------------------------------------------------- /SocialNetwork.Web/wwwroot/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/balov/Social-Network-ASP.NET-Core-MVC/f3a473878d480677871f9a41f498713958ddfd28/SocialNetwork.Web/wwwroot/favicon.ico -------------------------------------------------------------------------------- /SocialNetwork.Web/wwwroot/js/site.js: -------------------------------------------------------------------------------- 1 | // Write your JavaScript code. 2 | -------------------------------------------------------------------------------- /SocialNetwork.Web/wwwroot/js/site.min.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/balov/Social-Network-ASP.NET-Core-MVC/f3a473878d480677871f9a41f498713958ddfd28/SocialNetwork.Web/wwwroot/js/site.min.js -------------------------------------------------------------------------------- /SocialNetwork.Web/wwwroot/lib/bootstrap/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bootstrap", 3 | "description": "The most popular front-end framework for developing responsive, mobile first projects on the web.", 4 | "keywords": [ 5 | "css", 6 | "js", 7 | "less", 8 | "mobile-first", 9 | "responsive", 10 | "front-end", 11 | "framework", 12 | "web" 13 | ], 14 | "homepage": "http://getbootstrap.com", 15 | "license": "MIT", 16 | "moduleType": "globals", 17 | "main": [ 18 | "less/bootstrap.less", 19 | "dist/js/bootstrap.js" 20 | ], 21 | "ignore": [ 22 | "/.*", 23 | "_config.yml", 24 | "CNAME", 25 | "composer.json", 26 | "CONTRIBUTING.md", 27 | "docs", 28 | "js/tests", 29 | "test-infra" 30 | ], 31 | "dependencies": { 32 | "jquery": "1.9.1 - 3" 33 | }, 34 | "version": "3.3.7", 35 | "_release": "3.3.7", 36 | "_resolution": { 37 | "type": "version", 38 | "tag": "v3.3.7", 39 | "commit": "0b9c4a4007c44201dce9a6cc1a38407005c26c86" 40 | }, 41 | "_source": "https://github.com/twbs/bootstrap.git", 42 | "_target": "v3.3.7", 43 | "_originalSource": "bootstrap", 44 | "_direct": true 45 | } -------------------------------------------------------------------------------- /SocialNetwork.Web/wwwroot/lib/bootstrap/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2011-2016 Twitter, Inc. 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 13 | all 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 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /SocialNetwork.Web/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/balov/Social-Network-ASP.NET-Core-MVC/f3a473878d480677871f9a41f498713958ddfd28/SocialNetwork.Web/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /SocialNetwork.Web/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/balov/Social-Network-ASP.NET-Core-MVC/f3a473878d480677871f9a41f498713958ddfd28/SocialNetwork.Web/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /SocialNetwork.Web/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/balov/Social-Network-ASP.NET-Core-MVC/f3a473878d480677871f9a41f498713958ddfd28/SocialNetwork.Web/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /SocialNetwork.Web/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/balov/Social-Network-ASP.NET-Core-MVC/f3a473878d480677871f9a41f498713958ddfd28/SocialNetwork.Web/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /SocialNetwork.Web/wwwroot/lib/bootstrap/dist/js/npm.js: -------------------------------------------------------------------------------- 1 | // This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment. 2 | require('../../js/transition.js') 3 | require('../../js/alert.js') 4 | require('../../js/button.js') 5 | require('../../js/carousel.js') 6 | require('../../js/collapse.js') 7 | require('../../js/dropdown.js') 8 | require('../../js/modal.js') 9 | require('../../js/tooltip.js') 10 | require('../../js/popover.js') 11 | require('../../js/scrollspy.js') 12 | require('../../js/tab.js') 13 | require('../../js/affix.js') -------------------------------------------------------------------------------- /SocialNetwork.Web/wwwroot/lib/jquery-validation-unobtrusive/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery-validation-unobtrusive", 3 | "version": "3.2.6", 4 | "homepage": "https://github.com/aspnet/jquery-validation-unobtrusive", 5 | "description": "Add-on to jQuery Validation to enable unobtrusive validation options in data-* attributes.", 6 | "main": [ 7 | "jquery.validate.unobtrusive.js" 8 | ], 9 | "ignore": [ 10 | "**/.*", 11 | "*.json", 12 | "*.md", 13 | "*.txt", 14 | "gulpfile.js" 15 | ], 16 | "keywords": [ 17 | "jquery", 18 | "asp.net", 19 | "mvc", 20 | "validation", 21 | "unobtrusive" 22 | ], 23 | "authors": [ 24 | "Microsoft" 25 | ], 26 | "license": "http://www.microsoft.com/web/webpi/eula/net_library_eula_enu.htm", 27 | "repository": { 28 | "type": "git", 29 | "url": "git://github.com/aspnet/jquery-validation-unobtrusive.git" 30 | }, 31 | "dependencies": { 32 | "jquery-validation": ">=1.8", 33 | "jquery": ">=1.8" 34 | }, 35 | "_release": "3.2.6", 36 | "_resolution": { 37 | "type": "version", 38 | "tag": "v3.2.6", 39 | "commit": "13386cd1b5947d8a5d23a12b531ce3960be1eba7" 40 | }, 41 | "_source": "git://github.com/aspnet/jquery-validation-unobtrusive.git", 42 | "_target": "3.2.6", 43 | "_originalSource": "jquery-validation-unobtrusive" 44 | } -------------------------------------------------------------------------------- /SocialNetwork.Web/wwwroot/lib/jquery-validation/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery-validation", 3 | "homepage": "http://jqueryvalidation.org/", 4 | "repository": { 5 | "type": "git", 6 | "url": "git://github.com/jzaefferer/jquery-validation.git" 7 | }, 8 | "authors": [ 9 | "Jörn Zaefferer " 10 | ], 11 | "description": "Form validation made easy", 12 | "main": "dist/jquery.validate.js", 13 | "keywords": [ 14 | "forms", 15 | "validation", 16 | "validate" 17 | ], 18 | "license": "MIT", 19 | "ignore": [ 20 | "**/.*", 21 | "node_modules", 22 | "bower_components", 23 | "test", 24 | "demo", 25 | "lib" 26 | ], 27 | "dependencies": { 28 | "jquery": ">= 1.7.2" 29 | }, 30 | "version": "1.14.0", 31 | "_release": "1.14.0", 32 | "_resolution": { 33 | "type": "version", 34 | "tag": "1.14.0", 35 | "commit": "c1343fb9823392aa9acbe1c3ffd337b8c92fed48" 36 | }, 37 | "_source": "git://github.com/jzaefferer/jquery-validation.git", 38 | "_target": ">=1.8", 39 | "_originalSource": "jquery-validation" 40 | } -------------------------------------------------------------------------------- /SocialNetwork.Web/wwwroot/lib/jquery-validation/LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | ===================== 3 | 4 | Copyright Jörn Zaefferer 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /SocialNetwork.Web/wwwroot/lib/jquery/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery", 3 | "main": "dist/jquery.js", 4 | "license": "MIT", 5 | "ignore": [ 6 | "package.json" 7 | ], 8 | "keywords": [ 9 | "jquery", 10 | "javascript", 11 | "browser", 12 | "library" 13 | ], 14 | "homepage": "https://github.com/jquery/jquery-dist", 15 | "version": "2.2.0", 16 | "_release": "2.2.0", 17 | "_resolution": { 18 | "type": "version", 19 | "tag": "2.2.0", 20 | "commit": "6fc01e29bdad0964f62ef56d01297039cdcadbe5" 21 | }, 22 | "_source": "git://github.com/jquery/jquery-dist.git", 23 | "_target": "2.2.0", 24 | "_originalSource": "jquery" 25 | } -------------------------------------------------------------------------------- /SocialNetwork.Web/wwwroot/lib/jquery/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright jQuery Foundation and other contributors, https://jquery.org/ 2 | 3 | This software consists of voluntary contributions made by many 4 | individuals. For exact contribution history, see the revision history 5 | available at https://github.com/jquery/jquery 6 | 7 | The following license applies to all parts of this software except as 8 | documented below: 9 | 10 | ==== 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining 13 | a copy of this software and associated documentation files (the 14 | "Software"), to deal in the Software without restriction, including 15 | without limitation the rights to use, copy, modify, merge, publish, 16 | distribute, sublicense, and/or sell copies of the Software, and to 17 | permit persons to whom the Software is furnished to do so, subject to 18 | the following conditions: 19 | 20 | The above copyright notice and this permission notice shall be 21 | included in all copies or substantial portions of the Software. 22 | 23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 27 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 28 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 29 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 30 | 31 | ==== 32 | 33 | All files located in the node_modules and external directories are 34 | externally maintained libraries used by this software which have their 35 | own licenses; we recommend you read them, as their terms may differ from 36 | the terms above. 37 | -------------------------------------------------------------------------------- /SocialNetwork.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26730.16 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SocialNetwork.Web", "SocialNetwork.Web\SocialNetwork.Web.csproj", "{8EAD3798-0ABA-4513-85DF-3A04DB76543F}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SocialNetwork.Data", "SocialNetwork.Data\SocialNetwork.Data.csproj", "{23C6F383-FBEF-4438-85F7-D302C72C5784}" 9 | EndProject 10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SocialNetwork.Services", "SocialNetwork.Services\SocialNetwork.Services.csproj", "{5197F78B-518E-4551-A579-9A7ABC84011F}" 11 | EndProject 12 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SocialNetwork.Common", "SocialNetwork.Common\SocialNetwork.Common.csproj", "{4EDAB766-1329-4C60-8CF5-AF656D092F57}" 13 | EndProject 14 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SocialNetwork.Tests", "SocialNetwork.Tests\SocialNetwork.Tests.csproj", "{FBE65C3D-B379-468A-A576-011112122BA2}" 15 | EndProject 16 | Global 17 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 18 | Debug|Any CPU = Debug|Any CPU 19 | Release|Any CPU = Release|Any CPU 20 | EndGlobalSection 21 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 22 | {8EAD3798-0ABA-4513-85DF-3A04DB76543F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 23 | {8EAD3798-0ABA-4513-85DF-3A04DB76543F}.Debug|Any CPU.Build.0 = Debug|Any CPU 24 | {8EAD3798-0ABA-4513-85DF-3A04DB76543F}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {8EAD3798-0ABA-4513-85DF-3A04DB76543F}.Release|Any CPU.Build.0 = Release|Any CPU 26 | {23C6F383-FBEF-4438-85F7-D302C72C5784}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {23C6F383-FBEF-4438-85F7-D302C72C5784}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {23C6F383-FBEF-4438-85F7-D302C72C5784}.Release|Any CPU.ActiveCfg = Release|Any CPU 29 | {23C6F383-FBEF-4438-85F7-D302C72C5784}.Release|Any CPU.Build.0 = Release|Any CPU 30 | {5197F78B-518E-4551-A579-9A7ABC84011F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 31 | {5197F78B-518E-4551-A579-9A7ABC84011F}.Debug|Any CPU.Build.0 = Debug|Any CPU 32 | {5197F78B-518E-4551-A579-9A7ABC84011F}.Release|Any CPU.ActiveCfg = Release|Any CPU 33 | {5197F78B-518E-4551-A579-9A7ABC84011F}.Release|Any CPU.Build.0 = Release|Any CPU 34 | {4EDAB766-1329-4C60-8CF5-AF656D092F57}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 35 | {4EDAB766-1329-4C60-8CF5-AF656D092F57}.Debug|Any CPU.Build.0 = Debug|Any CPU 36 | {4EDAB766-1329-4C60-8CF5-AF656D092F57}.Release|Any CPU.ActiveCfg = Release|Any CPU 37 | {4EDAB766-1329-4C60-8CF5-AF656D092F57}.Release|Any CPU.Build.0 = Release|Any CPU 38 | {FBE65C3D-B379-468A-A576-011112122BA2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 39 | {FBE65C3D-B379-468A-A576-011112122BA2}.Debug|Any CPU.Build.0 = Debug|Any CPU 40 | {FBE65C3D-B379-468A-A576-011112122BA2}.Release|Any CPU.ActiveCfg = Release|Any CPU 41 | {FBE65C3D-B379-468A-A576-011112122BA2}.Release|Any CPU.Build.0 = Release|Any CPU 42 | EndGlobalSection 43 | GlobalSection(SolutionProperties) = preSolution 44 | HideSolutionNode = FALSE 45 | EndGlobalSection 46 | GlobalSection(ExtensibilityGlobals) = postSolution 47 | SolutionGuid = {5AEB56A2-C13E-4D6A-AD6D-ECE224040199} 48 | EndGlobalSection 49 | EndGlobal 50 | --------------------------------------------------------------------------------