Skip to content
Snippets Groups Projects
Commit 0f204399 authored by Adiv's avatar Adiv
Browse files

added profile pictures

parent e8c7fee7
No related branches found
No related tags found
No related merge requests found
...@@ -21,6 +21,7 @@ public class Constants ...@@ -21,6 +21,7 @@ public class Constants
public static class AzureBlobContainer public static class AzureBlobContainer
{ {
public const string ProfilePictures = "profile-pictures";
public const string BannerPictures = "banner-pictures"; public const string BannerPictures = "banner-pictures";
} }
......
namespace Group17profile.Controllers; namespace Group17profile.Controllers;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Middleware; using Middleware;
using Models.DTOs; using Models.DTOs;
...@@ -24,7 +25,7 @@ public class ProfileController : DefaultAuthenticationController ...@@ -24,7 +25,7 @@ public class ProfileController : DefaultAuthenticationController
{ {
try try
{ {
return Ok(await _profileService.GetProfileForUser(1)); return Ok(await _profileService.GetProfileForUser(UserId));
} }
catch (Exception ex) catch (Exception ex)
{ {
...@@ -48,12 +49,53 @@ public class ProfileController : DefaultAuthenticationController ...@@ -48,12 +49,53 @@ public class ProfileController : DefaultAuthenticationController
} }
} }
[HttpPost("UploadBannerPicture")] [HttpPost("UploadProfilePicture")]
[Consumes("multipart/form-data")] [Consumes("multipart/form-data")]
public async Task<ActionResult<ResponseEnvelope<ProfileDTO>>> UploadBannerPicture(IFormFile? profilePicture) public async Task<ActionResult<ResponseEnvelope<ProfileDTO>>> UploadProfilePicture(IFormFile? profilePicture)
{ {
if (profilePicture == null) if (profilePicture == null)
return BadRequest("Please upload a file."); return BadRequest("Please upload a file.");
return Ok(await _profileService.UploadBannerPicture(UserId, profilePicture)); return Ok(await _profileService.UploadProfilePicture(UserId, profilePicture));
}
[HttpPost("UploadBannerPicture")]
[Consumes("multipart/form-data")]
public async Task<ActionResult<ResponseEnvelope<ProfileDTO>>> UploadBannerPicture(IFormFile? bannerPicture)
{
if (bannerPicture == null)
return BadRequest("Please upload a file.");
return Ok(await _profileService.UploadBannerPicture(UserId, bannerPicture));
}
[HttpGet("GetProfileByUserId")]
[SwaggerResponse(200, Type = typeof(ResponseEnvelope<ProfileDTO>))]
[SwaggerResponse(400, Type = typeof(ResponseEnvelope<BadRequestObjectResult>))]
[AllowAnonymous]
public async Task<ActionResult<ResponseEnvelope<ProfileDTO>>> GetProfileByUserId(int userId)
{
try
{
return Ok(await _profileService.GetProfileForUser(userId));
}
catch (Exception ex)
{
return BadRequest(ex.Message);
}
}
[HttpPost("GetProfilesByUserIds")]
[SwaggerResponse(200, Type = typeof(ResponseEnvelope<List<ProfileDTO>>))]
[SwaggerResponse(400, Type = typeof(ResponseEnvelope<BadRequestObjectResult>))]
[AllowAnonymous]
public async Task<ActionResult<ResponseEnvelope<List<ProfileDTO>>>> GetProfilesByUserIds(List<int> userIds)
{
try
{
return Ok(await _profileService.GetProfilesByUserIds(userIds));
}
catch (Exception ex)
{
return BadRequest(ex.Message);
}
} }
} }
\ No newline at end of file
...@@ -7,6 +7,7 @@ public class ProfileDTO : DefaultGuidDTO ...@@ -7,6 +7,7 @@ public class ProfileDTO : DefaultGuidDTO
public int? UserId { get; set; } public int? UserId { get; set; }
public string? Biography { get; set; } public string? Biography { get; set; }
public string? ProfilePictureUrl { get; set; }
public string? BannerUrl { get; set; } public string? BannerUrl { get; set; }
public string? Gender { get; set; } public string? Gender { get; set; }
......
...@@ -7,6 +7,7 @@ public class Profile : DefaultGuidEntity ...@@ -7,6 +7,7 @@ public class Profile : DefaultGuidEntity
public int? UserId { get; set; } public int? UserId { get; set; }
public string? Biography { get; set; } public string? Biography { get; set; }
public string? ProfilePictureUrl { get; set; }
public string? BannerUrl { get; set; } public string? BannerUrl { get; set; }
public string? Gender { get; set; } public string? Gender { get; set; }
......
...@@ -9,24 +9,24 @@ public interface IProfileRepository ...@@ -9,24 +9,24 @@ public interface IProfileRepository
{ {
Task<Profile> CreateProfileAsync(Profile profile); Task<Profile> CreateProfileAsync(Profile profile);
Task<Profile?> GetProfileAsync(int userId); Task<Profile?> GetProfileAsync(int userId);
Task<List<Profile>> GetProfilesByUserIds(List<int> userIds);
Task<Profile> UpdateProfileAsync(int userId, string profileId, Profile profile); Task<Profile> UpdateProfileAsync(int userId, string profileId, Profile profile);
Task DeleteProfileAsync(int userId, string profileId); Task DeleteProfileAsync(int userId, string profileId);
Task<IEnumerable<Profile?>> GetProfilesByMoodAsync(string mood);
} }
public class ProfileRepository : IProfileRepository public class ProfileRepository : IProfileRepository
{ {
private readonly Container? _profileDetailsContainer; private readonly Container? _profileContainer;
public ProfileRepository(ProfileDbContext context) public ProfileRepository(ProfileDbContext context)
{ {
_profileDetailsContainer = context.Profile; _profileContainer = context.Profile;
} }
public async Task<Profile> CreateProfileAsync(Profile profile) public async Task<Profile> CreateProfileAsync(Profile profile)
{ {
var response = var response =
await _profileDetailsContainer?.CreateItemAsync(profile, await _profileContainer?.CreateItemAsync(profile,
new PartitionKey(profile.UserId.GetValueOrDefault()))!; new PartitionKey(profile.UserId.GetValueOrDefault()))!;
return response.Resource; return response.Resource;
} }
...@@ -38,7 +38,7 @@ public class ProfileRepository : IProfileRepository ...@@ -38,7 +38,7 @@ public class ProfileRepository : IProfileRepository
var query = new QueryDefinition("SELECT * FROM c WHERE c.UserId = @UserId") var query = new QueryDefinition("SELECT * FROM c WHERE c.UserId = @UserId")
.WithParameter("@UserId", userId); .WithParameter("@UserId", userId);
var iterator = _profileDetailsContainer?.GetItemQueryIterator<Profile>(query); var iterator = _profileContainer?.GetItemQueryIterator<Profile>(query);
if (iterator is {HasMoreResults: false}) return null; if (iterator is {HasMoreResults: false}) return null;
var response = await iterator.ReadNextAsync(); var response = await iterator.ReadNextAsync();
...@@ -50,31 +50,41 @@ public class ProfileRepository : IProfileRepository ...@@ -50,31 +50,41 @@ public class ProfileRepository : IProfileRepository
} }
} }
public async Task<Profile> UpdateProfileAsync(int userId, string profileId, Profile profile) public async Task<List<Profile>> GetProfilesByUserIds(List<int> userIds)
{ {
var response = await _profileDetailsContainer.ReplaceItemAsync(profile, profileId, new PartitionKey(userId)); try
return response.Resource; {
} var userIdsString = string.Join(",", userIds);
var queryString = $"SELECT * FROM c WHERE c.UserId IN ({userIdsString})";
var query = new QueryDefinition(queryString);
public async Task DeleteProfileAsync(int userId, string profileId) var iterator = _profileContainer?.GetItemQueryIterator<Profile>(query);
{
await _profileDetailsContainer.DeleteItemAsync<Profile>(profileId, new PartitionKey(userId));
}
public async Task<IEnumerable<Profile?>> GetProfilesByMoodAsync(string mood) if (iterator is {HasMoreResults: false}) return new List<Profile>();
{ var profiles = new List<Profile>();
var query = new QueryDefinition("SELECT * FROM c WHERE c.Mood = @mood")
.WithParameter("@mood", mood);
var iterator = _profileDetailsContainer?.GetItemQueryIterator<Profile>(query); while (iterator is {HasMoreResults: true})
{
var response = await iterator.ReadNextAsync();
profiles.AddRange(response);
}
var profiles = new List<Profile>(); return profiles;
while (iterator.HasMoreResults) }
catch (CosmosException ex) when (ex.StatusCode == HttpStatusCode.NotFound)
{ {
var response = await iterator.ReadNextAsync(); return new List<Profile>();
profiles.AddRange(response);
} }
}
public async Task<Profile> UpdateProfileAsync(int userId, string profileId, Profile profile)
{
var response = await _profileContainer.ReplaceItemAsync(profile, profileId, new PartitionKey(userId));
return response.Resource;
}
return profiles; public async Task DeleteProfileAsync(int userId, string profileId)
{
await _profileContainer.DeleteItemAsync<Profile>(profileId, new PartitionKey(userId));
} }
} }
\ No newline at end of file
...@@ -10,7 +10,9 @@ using Profile = Models.Entities.Profile; ...@@ -10,7 +10,9 @@ using Profile = Models.Entities.Profile;
public interface IProfileService public interface IProfileService
{ {
Task<ProfileDTO> GetProfileForUser(int userId); Task<ProfileDTO> GetProfileForUser(int userId);
Task<List<ProfileDTO>> GetProfilesByUserIds(List<int> userIds);
Task<ProfileDTO> CreateOrUpdateProfile(ProfileDTO profile, int userId); Task<ProfileDTO> CreateOrUpdateProfile(ProfileDTO profile, int userId);
Task<ProfileDTO> UploadProfilePicture(int userId, IFormFile profilePicture);
Task<ProfileDTO> UploadBannerPicture(int userId, IFormFile bannerPicture); Task<ProfileDTO> UploadBannerPicture(int userId, IFormFile bannerPicture);
} }
...@@ -32,6 +34,9 @@ public class ProfileService : IProfileService ...@@ -32,6 +34,9 @@ public class ProfileService : IProfileService
var profile = await _profileRepository.GetProfileAsync(userId); var profile = await _profileRepository.GetProfileAsync(userId);
if (profile == null) if (profile == null)
throw new ProfileException("Profile does not exist."); throw new ProfileException("Profile does not exist.");
if (!string.IsNullOrWhiteSpace(profile.ProfilePictureUrl))
profile.ProfilePictureUrl +=
_storageService.GetSasForFile(Constants.AzureBlobContainer.ProfilePictures, profile.ProfilePictureUrl);
if (!string.IsNullOrWhiteSpace(profile.BannerUrl)) if (!string.IsNullOrWhiteSpace(profile.BannerUrl))
profile.BannerUrl += profile.BannerUrl +=
_storageService.GetSasForFile(Constants.AzureBlobContainer.BannerPictures, profile.BannerUrl); _storageService.GetSasForFile(Constants.AzureBlobContainer.BannerPictures, profile.BannerUrl);
...@@ -47,6 +52,13 @@ public class ProfileService : IProfileService ...@@ -47,6 +52,13 @@ public class ProfileService : IProfileService
var age = DateTimeOffset.Now.Year - profile.DoB.GetValueOrDefault().Year; var age = DateTimeOffset.Now.Year - profile.DoB.GetValueOrDefault().Year;
if (age is <= 16 or >= 100) if (age is <= 16 or >= 100)
throw new ProfileException("Please enter valid age."); throw new ProfileException("Please enter valid age.");
if (!string.IsNullOrWhiteSpace(profile.ProfilePictureUrl))
{
var profilePictureUri = new Uri(profile.ProfilePictureUrl);
if (!string.IsNullOrWhiteSpace(profilePictureUri.Query))
profile.ProfilePictureUrl = profile.ProfilePictureUrl.Replace(profilePictureUri.Query, "");
}
if (!string.IsNullOrWhiteSpace(profile.BannerUrl)) if (!string.IsNullOrWhiteSpace(profile.BannerUrl))
{ {
var bannerUri = new Uri(profile.BannerUrl); var bannerUri = new Uri(profile.BannerUrl);
...@@ -55,6 +67,15 @@ public class ProfileService : IProfileService ...@@ -55,6 +67,15 @@ public class ProfileService : IProfileService
} }
var record = _mapper.Map<Profile>(profile); var record = _mapper.Map<Profile>(profile);
if (profile.FavouriteShows != null && profile.FavouriteShows.Count != 0)
{
var builder = new StringBuilder();
foreach (var show in profile.FavouriteShows)
builder.Append($"{show},");
record.FavouriteShows = builder.ToString();
}
var existing = await _profileRepository.GetProfileAsync(userId); var existing = await _profileRepository.GetProfileAsync(userId);
if (existing == null) if (existing == null)
{ {
...@@ -68,14 +89,9 @@ public class ProfileService : IProfileService ...@@ -68,14 +89,9 @@ public class ProfileService : IProfileService
record = await _profileRepository.UpdateProfileAsync(userId, record.Id.ToString(), record); record = await _profileRepository.UpdateProfileAsync(userId, record.Id.ToString(), record);
} }
if (profile.FavouriteShows != null && profile.FavouriteShows.Count != 0) if (!string.IsNullOrWhiteSpace(record.ProfilePictureUrl))
{ record.ProfilePictureUrl +=
var builder = new StringBuilder(); _storageService.GetSasForFile(Constants.AzureBlobContainer.ProfilePictures, record.ProfilePictureUrl);
foreach (var show in profile.FavouriteShows)
builder.Append($"{show},");
record.FavouriteShows = builder.ToString();
}
if (!string.IsNullOrWhiteSpace(record.BannerUrl)) if (!string.IsNullOrWhiteSpace(record.BannerUrl))
record.BannerUrl += record.BannerUrl +=
...@@ -84,6 +100,31 @@ public class ProfileService : IProfileService ...@@ -84,6 +100,31 @@ public class ProfileService : IProfileService
return _mapper.Map<ProfileDTO>(record); return _mapper.Map<ProfileDTO>(record);
} }
public async Task<ProfileDTO> UploadProfilePicture(int userId, IFormFile profilePicture)
{
var profile = await _profileRepository.GetProfileAsync(userId);
using var ms = new MemoryStream();
await profilePicture.CopyToAsync(ms);
ms.Position = 0;
var fileName = $"{userId}/{profilePicture.Name}";
var image = await _storageService.SaveImageAsJpgBlob(Constants.AzureBlobContainer.ProfilePictures, fileName,
ms);
if (profile == null)
{
profile = new Profile {ProfilePictureUrl = image.ToString(), Id = Guid.NewGuid(), UserId = userId};
profile = await _profileRepository.CreateProfileAsync(profile);
}
else
{
profile.ProfilePictureUrl = image.ToString();
profile = await _profileRepository.UpdateProfileAsync(userId, profile.Id.ToString(), profile);
}
profile.ProfilePictureUrl +=
_storageService.GetSasForFile(Constants.AzureBlobContainer.ProfilePictures, image.ToString());
return _mapper.Map<ProfileDTO>(profile);
}
public async Task<ProfileDTO> UploadBannerPicture(int userId, IFormFile bannerPicture) public async Task<ProfileDTO> UploadBannerPicture(int userId, IFormFile bannerPicture)
{ {
var profile = await _profileRepository.GetProfileAsync(userId); var profile = await _profileRepository.GetProfileAsync(userId);
...@@ -94,7 +135,7 @@ public class ProfileService : IProfileService ...@@ -94,7 +135,7 @@ public class ProfileService : IProfileService
var image = await _storageService.SaveImageAsJpgBlob(Constants.AzureBlobContainer.BannerPictures, fileName, ms); var image = await _storageService.SaveImageAsJpgBlob(Constants.AzureBlobContainer.BannerPictures, fileName, ms);
if (profile == null) if (profile == null)
{ {
profile = new Profile {BannerUrl = image.ToString(), UserId = userId}; profile = new Profile {BannerUrl = image.ToString(), Id = Guid.NewGuid(), UserId = userId};
profile = await _profileRepository.CreateProfileAsync(profile); profile = await _profileRepository.CreateProfileAsync(profile);
} }
else else
...@@ -107,4 +148,23 @@ public class ProfileService : IProfileService ...@@ -107,4 +148,23 @@ public class ProfileService : IProfileService
_storageService.GetSasForFile(Constants.AzureBlobContainer.BannerPictures, image.ToString()); _storageService.GetSasForFile(Constants.AzureBlobContainer.BannerPictures, image.ToString());
return _mapper.Map<ProfileDTO>(profile); return _mapper.Map<ProfileDTO>(profile);
} }
public async Task<List<ProfileDTO>> GetProfilesByUserIds(List<int> userIds)
{
var profiles = await _profileRepository.GetProfilesByUserIds(userIds);
var mapped = _mapper.ProjectTo<ProfileDTO>(profiles.AsQueryable()).ToList();
if (profiles.Count == 0) return mapped;
foreach (var profile in mapped)
{
if (!string.IsNullOrWhiteSpace(profile.ProfilePictureUrl))
profile.ProfilePictureUrl +=
_storageService.GetSasForFile(Constants.AzureBlobContainer.ProfilePictures,
profile.ProfilePictureUrl);
if (!string.IsNullOrWhiteSpace(profile.BannerUrl))
profile.BannerUrl +=
_storageService.GetSasForFile(Constants.AzureBlobContainer.BannerPictures, profile.BannerUrl);
}
return mapped;
}
} }
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment