Skip to content

Commit

Permalink
Merge pull request #31 from Alper-Soy/develop
Browse files Browse the repository at this point in the history
Prod - 08/26/2024
  • Loading branch information
Alper-Soy authored Aug 25, 2024
2 parents 4a6ed55 + ab415ea commit 2cacbf8
Show file tree
Hide file tree
Showing 40 changed files with 1,096 additions and 136 deletions.
14 changes: 7 additions & 7 deletions API/Controllers/AccountController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace API.Controllers;

[ApiController]
[Route("api/[controller]")]
public class AccountController(UserManager<User> userManager, TokenService tokenService) : ControllerBase
public class AccountController(UserManager<AppUser> userManager, TokenService tokenService) : ControllerBase
{
[AllowAnonymous]
[HttpPost("login")]
Expand Down Expand Up @@ -47,7 +47,7 @@ public async Task<ActionResult<AuthUserDto>> Register(RegisterDto registerDto)
}


var user = new User
var user = new AppUser
{
DisplayName = registerDto.DisplayName,
Email = registerDto.Email,
Expand All @@ -71,14 +71,14 @@ public async Task<ActionResult<AuthUserDto>> GetCurrentUser()
return CreateUserObject(user);
}

private AuthUserDto CreateUserObject(User user)
private AuthUserDto CreateUserObject(AppUser appUser)
{
return new AuthUserDto
{
DisplayName = user.DisplayName,
Image = user.Photos.FirstOrDefault(x => x.IsMain)?.Url,
Token = tokenService.CreateToken(user),
Username = user.UserName
DisplayName = appUser.DisplayName,
Image = appUser.Photos.FirstOrDefault(x => x.IsMain)?.Url,
Token = tokenService.CreateToken(appUser),
Username = appUser.UserName
};
}
}
21 changes: 21 additions & 0 deletions API/Controllers/FollowController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using Application.Features.Followers.Commands.FollowToggle;
using Application.Features.Followers.Queries.Follow;
using Microsoft.AspNetCore.Mvc;

namespace API.Controllers;

public class FollowController : BaseApiController
{
[HttpPost("{username}")]
public async Task<IActionResult> Follow(string username)
{
return HandleResult(await Mediator.Send(new FollowToggleCommand
{ TargetUsername = username }));
}

[HttpGet("{username}")]
public async Task<IActionResult> GetFollowings(string username, string predicate)
{
return HandleResult(await Mediator.Send(new GetFollowQuery { Username = username, Predicate = predicate }));
}
}
2 changes: 1 addition & 1 deletion API/Extensions/IdentityServiceExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public static class IdentityServiceExtensions
{
public static IServiceCollection AddIdentityServices(this IServiceCollection services, IConfiguration config)
{
services.AddIdentityCore<User>(opt =>
services.AddIdentityCore<AppUser>(opt =>
{
opt.Password.RequireNonAlphanumeric = false;
opt.User.RequireUniqueEmail = true;
Expand Down
2 changes: 1 addition & 1 deletion API/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
try
{
var context = services.GetRequiredService<DataContext>();
var userManager = services.GetRequiredService<UserManager<User>>();
var userManager = services.GetRequiredService<UserManager<AppUser>>();
await context.Database.MigrateAsync();
await Seed.SeedData(context, userManager);
}
Expand Down
8 changes: 4 additions & 4 deletions API/Services/Auth/TokenService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ namespace API.Services.Auth;

public class TokenService(IConfiguration config)
{
public string CreateToken(User user)
public string CreateToken(AppUser appUser)
{
var claims = new List<Claim>
{
new(ClaimTypes.Name, user.UserName),
new(ClaimTypes.NameIdentifier, user.Id),
new(ClaimTypes.Email, user.Email)
new(ClaimTypes.Name, appUser.UserName),
new(ClaimTypes.NameIdentifier, appUser.Id),
new(ClaimTypes.Email, appUser.Email)
};

var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(config["TokenKey"]));
Expand Down
Binary file modified API/activity-hub.db
Binary file not shown.
23 changes: 16 additions & 7 deletions Application/Core/MappingProfiles.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,29 @@ public class MappingProfiles : Profile
{
public MappingProfiles()
{
string currentUsername = null;
CreateMap<Activity, Activity>();

CreateMap<Activity, ActivityDto>()
.ForMember(d => d.HostUsername, o => o.MapFrom(s => s.Attendees
.FirstOrDefault(x => x.IsHost).User.UserName));
.FirstOrDefault(x => x.IsHost).AppUser.UserName));

CreateMap<ActivityAttendee, AttendeeDto>()
.ForMember(d => d.DisplayName, o => o.MapFrom(s => s.User.DisplayName))
.ForMember(d => d.Username, o => o.MapFrom(s => s.User.UserName))
.ForMember(d => d.Bio, o => o.MapFrom(s => s.User.Bio))
.ForMember(d => d.Image, o => o.MapFrom(s => s.User.Photos.FirstOrDefault(x => x.IsMain).Url));
.ForMember(d => d.DisplayName, o => o.MapFrom(s => s.AppUser.DisplayName))
.ForMember(d => d.Username, o => o.MapFrom(s => s.AppUser.UserName))
.ForMember(d => d.Bio, o => o.MapFrom(s => s.AppUser.Bio))
.ForMember(d => d.Image, o => o.MapFrom(s => s.AppUser.Photos.FirstOrDefault(x => x.IsMain).Url))
.ForMember(d => d.FollowersCount, o => o.MapFrom(s => s.AppUser.Followers.Count))
.ForMember(d => d.FollowingCount, o => o.MapFrom(s => s.AppUser.Followings.Count))
.ForMember(d => d.Following,
o => o.MapFrom(s => s.AppUser.Followers.Any(x => x.Observer.UserName == currentUsername)));

CreateMap<User, Features.Profiles.Contracts.ProfileDto>()
.ForMember(d => d.Image, s => s.MapFrom(o => o.Photos.FirstOrDefault(x => x.IsMain).Url));
CreateMap<AppUser, Features.Profiles.Contracts.ProfileDto>()
.ForMember(d => d.Image, s => s.MapFrom(o => o.Photos.FirstOrDefault(x => x.IsMain).Url))
.ForMember(d => d.FollowersCount, o => o.MapFrom(s => s.Followers.Count))
.ForMember(d => d.FollowingCount, o => o.MapFrom(s => s.Followings.Count))
.ForMember(d => d.Following,
o => o.MapFrom(s => s.Followers.Any(x => x.Observer.UserName == currentUsername)));

CreateMap<Comment, CommentDto>()
.ForMember(d => d.DisplayName, o => o.MapFrom(s => s.Author.DisplayName))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public async Task<Result<Unit>> Handle(CreateActivityCommand request, Cancellati

var attendee = new ActivityAttendee
{
User = user,
AppUser = user,
Activity = request.Activity,
IsHost = true
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Application.Core;
using Application.Features.Activities.Contracts;
using Application.Interfaces;
using AutoMapper;
using AutoMapper.QueryableExtensions;
using MediatR;
Expand All @@ -8,12 +9,13 @@

namespace Application.Features.Activities.Queries.GetActivities;

public class GetActivitiesHandler(DataContext context, IMapper mapper)
public class GetActivitiesHandler(DataContext context, IMapper mapper, IUserAccessor userAccessor)
: IRequestHandler<GetActivitiesQuery, Result<List<ActivityDto>>>
{
public async Task<Result<List<ActivityDto>>> Handle(GetActivitiesQuery request, CancellationToken cancellationToken)
{
var activities = await context.Activities.ProjectTo<ActivityDto>(mapper.ConfigurationProvider)
var activities = await context.Activities.ProjectTo<ActivityDto>(mapper.ConfigurationProvider,
new { currentUsername = userAccessor.GetUsername() })
.ToListAsync(cancellationToken);

return Result<List<ActivityDto>>.Success(activities);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Application.Core;
using Application.Features.Activities.Contracts;
using Application.Interfaces;
using AutoMapper;
using AutoMapper.QueryableExtensions;
using MediatR;
Expand All @@ -8,12 +9,13 @@

namespace Application.Features.Activities.Queries.GetActivity;

public class GetActivityHandler(DataContext context, IMapper mapper)
public class GetActivityHandler(DataContext context, IMapper mapper, IUserAccessor userAccessor)
: IRequestHandler<GetActivityQuery, Result<ActivityDto>>
{
public async Task<Result<ActivityDto>> Handle(GetActivityQuery request, CancellationToken cancellationToken)
{
var activity = await context.Activities.ProjectTo<ActivityDto>(mapper.ConfigurationProvider)
var activity = await context.Activities.ProjectTo<ActivityDto>(mapper.ConfigurationProvider,
new { currentUsername = userAccessor.GetUsername() })
.FirstOrDefaultAsync(x => x.Id == request.Id);

return Result<ActivityDto>.Success(activity);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@ public async Task<Result<Unit>> Handle(UpdateAttendanceCommand request, Cancella

if (user == null) return null;

var activity = await context.Activities.Include(a => a.Attendees).ThenInclude(u => u.User)
var activity = await context.Activities.Include(a => a.Attendees).ThenInclude(u => u.AppUser)
.SingleOrDefaultAsync(x => x.Id == request.Id);

if (activity == null) return null;

var hostUsername = activity.Attendees.FirstOrDefault(x => x.IsHost)?.User?.UserName;
var hostUsername = activity.Attendees.FirstOrDefault(x => x.IsHost)?.AppUser?.UserName;

var attendance = activity.Attendees.FirstOrDefault(x => x.User.UserName == user.UserName);
var attendance = activity.Attendees.FirstOrDefault(x => x.AppUser.UserName == user.UserName);

if (attendance != null && hostUsername == user.UserName) activity.IsCancelled = !activity.IsCancelled;

Expand All @@ -34,7 +34,7 @@ public async Task<Result<Unit>> Handle(UpdateAttendanceCommand request, Cancella
{
attendance = new ActivityAttendee
{
User = user,
AppUser = user,
Activity = activity,
IsHost = false
};
Expand Down
3 changes: 3 additions & 0 deletions Application/Features/Attendance/Contracts/AttendeeDto.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,7 @@ public class AttendeeDto
public string DisplayName { get; set; }
public string Bio { get; set; }
public string Image { get; set; }
public bool Following { get; set; }
public int FollowersCount { get; set; }
public int FollowingCount { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using Application.Core;
using MediatR;

namespace Application.Features.Followers.Commands.FollowToggle;

public class FollowToggleCommand : IRequest<Result<Unit>>
{
public string TargetUsername { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using Application.Core;
using Application.Interfaces;
using Domain.Entities;
using MediatR;
using Microsoft.EntityFrameworkCore;
using Persistence;

namespace Application.Features.Followers.Commands.FollowToggle;

public class FollowToggleHandler(DataContext context, IUserAccessor userAccessor)
: IRequestHandler<FollowToggleCommand, Result<Unit>>
{
public async Task<Result<Unit>> Handle(FollowToggleCommand request, CancellationToken cancellationToken)
{
var observer = await context.Users.FirstOrDefaultAsync(x =>
x.UserName == userAccessor.GetUsername());

var target = await context.Users.FirstOrDefaultAsync(x =>
x.UserName == request.TargetUsername);

if (target == null) return null;

var following = await context.UserFollowings.FindAsync(observer.Id, target.Id);

if (following == null)
{
following = new UserFollowing
{
Observer = observer,
Target = target
};

context.UserFollowings.Add(following);
}
else
{
context.UserFollowings.Remove(following);
}

var success = await context.SaveChangesAsync() > 0;

return success ? Result<Unit>.Success(Unit.Value) : Result<Unit>.Failure("Failed to update following");
}
}
39 changes: 39 additions & 0 deletions Application/Features/Followers/Queries/Follow/GetFollowHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using Application.Core;
using Application.Features.Profiles.Contracts;
using Application.Interfaces;
using AutoMapper;
using AutoMapper.QueryableExtensions;
using MediatR;
using Microsoft.EntityFrameworkCore;
using Persistence;

namespace Application.Features.Followers.Queries.Follow;

public class GetFollowHandler(DataContext context, IMapper mapper, IUserAccessor userAccessor)
: IRequestHandler<GetFollowQuery, Result<List<ProfileDto>>>
{
public async Task<Result<List<ProfileDto>>> Handle(GetFollowQuery request, CancellationToken cancellationToken)
{
var profiles = new List<ProfileDto>();

switch (request.Predicate)
{
case "followers":
profiles = await context.UserFollowings.Where(x => x.Target.UserName == request.Username)
.Select(u => u.Observer)
.ProjectTo<ProfileDto>(mapper.ConfigurationProvider,
new { currentUsername = userAccessor.GetUsername() })
.ToListAsync();
break;
case "following":
profiles = await context.UserFollowings.Where(x => x.Observer.UserName == request.Username)
.Select(u => u.Target)
.ProjectTo<ProfileDto>(mapper.ConfigurationProvider,
new { currentUsername = userAccessor.GetUsername() })
.ToListAsync();
break;
}

return Result<List<ProfileDto>>.Success(profiles);
}
}
11 changes: 11 additions & 0 deletions Application/Features/Followers/Queries/Follow/GetFollowQuery.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using Application.Core;
using Application.Features.Profiles.Contracts;
using MediatR;

namespace Application.Features.Followers.Queries.Follow;

public class GetFollowQuery : IRequest<Result<List<ProfileDto>>>
{
public string Predicate { get; set; }
public string Username { get; set; }
}
3 changes: 3 additions & 0 deletions Application/Features/Profiles/Contracts/ProfileDto.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,8 @@ public class ProfileDto
public string DisplayName { get; set; }
public string Bio { get; set; }
public string Image { get; set; }
public bool Following { get; set; }
public int FollowersCount { get; set; }
public int FollowingCount { get; set; }
public ICollection<Photo> Photos { get; set; }
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Application.Core;
using Application.Features.Profiles.Contracts;
using Application.Interfaces;
using AutoMapper;
using AutoMapper.QueryableExtensions;
using MediatR;
Expand All @@ -8,13 +9,13 @@

namespace Application.Features.Profiles.Queries.GetProfile;

public class GetProfileHandler(DataContext context, IMapper mapper)
public class GetProfileHandler(DataContext context, IMapper mapper, IUserAccessor userAccessor)
: IRequestHandler<GetProfileQuery, Result<ProfileDto>>
{
public async Task<Result<ProfileDto>> Handle(GetProfileQuery request, CancellationToken cancellationToken)
{
var user = await context.Users
.ProjectTo<ProfileDto>(mapper.ConfigurationProvider)
.ProjectTo<ProfileDto>(mapper.ConfigurationProvider, new { currentUsername = userAccessor.GetUsername() })
.SingleOrDefaultAsync(x => x.Username == request.Username);

return Result<ProfileDto>.Success(user);
Expand Down
2 changes: 1 addition & 1 deletion Domain/Entities/ActivityAttendee.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ namespace Domain.Entities;
public class ActivityAttendee
{
public string UserId { get; set; }
public User User { get; set; }
public AppUser AppUser { get; set; }
public Guid ActivityId { get; set; }
public Activity Activity { get; set; }
public bool IsHost { get; set; }
Expand Down
4 changes: 3 additions & 1 deletion Domain/Entities/User.cs → Domain/Entities/AppUser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@

namespace Domain.Entities;

public class User : IdentityUser
public class AppUser : IdentityUser
{
public string DisplayName { get; set; }
public string Bio { get; set; }
public ICollection<ActivityAttendee> Activities { get; set; }
public ICollection<Photo> Photos { get; set; }
public ICollection<UserFollowing> Followings { get; set; }
public ICollection<UserFollowing> Followers { get; set; }
}
2 changes: 1 addition & 1 deletion Domain/Entities/Comment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ public class Comment
{
public int Id { get; set; }
public string Body { get; set; }
public User Author { get; set; }
public AppUser Author { get; set; }
public Activity Activity { get; set; }
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
}
Loading

0 comments on commit 2cacbf8

Please sign in to comment.