Skip to content
This repository was archived by the owner on Mar 22, 2025. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions SimpleServer/SimpleServer.sln
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Payment.API", "src\Services
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Identity.Grpc", "src\Services\Identity\Identity.Grpc\Identity.Grpc.csproj", "{D4025862-FCFB-4FC4-BDDA-42127817C5B0}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Watchlist.API", "src\Services\WatchlistService\Watchlist.API\Watchlist.API.csproj", "{19FC313F-7235-41E9-9B3E-46D8736051D2}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -103,6 +105,10 @@ Global
{D4025862-FCFB-4FC4-BDDA-42127817C5B0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D4025862-FCFB-4FC4-BDDA-42127817C5B0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D4025862-FCFB-4FC4-BDDA-42127817C5B0}.Release|Any CPU.Build.0 = Release|Any CPU
{19FC313F-7235-41E9-9B3E-46D8736051D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{19FC313F-7235-41E9-9B3E-46D8736051D2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{19FC313F-7235-41E9-9B3E-46D8736051D2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{19FC313F-7235-41E9-9B3E-46D8736051D2}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -129,6 +135,7 @@ Global
{B28B8B14-5D5E-4F71-8D29-8F4FA518E63B} = {5DB32E24-821A-4265-8866-5FA3DD7E5E54}
{A2136994-728F-4D71-87F9-E11E6DD78790} = {D6B1FD89-8AD1-46A3-A89C-6A73DEFE7D81}
{D4025862-FCFB-4FC4-BDDA-42127817C5B0} = {96C41B3F-C50A-499A-8341-6BDC36B37389}
{19FC313F-7235-41E9-9B3E-46D8736051D2} = {EBA29E1D-1833-43D8-9B09-A2D80787B656}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C9B02C29-4D8B-4687-AB7D-9DF5642002D9}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,28 @@
"movies"
]
}
},
{
"DownstreamPathTemplate": "/api/watchList/{everything}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 5013
}
],
"UpstreamPathTemplate": "/watchList/{everything}",
"UpstreamHttpMethod": [
"GET",
"POST",
"DELETE"
],
"AuthenticationOptions": {
"AuthenticationProviderKey": "IdentityApiKey",
"AllowedScopes": [
"watchlist"
]
}
}
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@
"launchBrowser": true,
"launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}/swagger",
"environmentVariables": {},
"useSSL": true,
"publishAllPorts": true
"publishAllPorts": true,
"useSSL": true
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
using System;
using System.Security.Claims;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Watchlist.API.Repository.WatchList;

namespace Watchlist.API.Controllers
{
[Authorize(Roles = "Member")]
[Route("api/watchList")]
public class SavedWatchListController : Controller
{
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly IWatchListRepository _watchListService;
private readonly ILogger<SavedWatchListController> _logger;

public SavedWatchListController(IWatchListRepository watchListService, ILogger<SavedWatchListController> logger, IHttpContextAccessor httpContextAccessor)
{
_watchListService = watchListService;
_logger = logger;
_httpContextAccessor = httpContextAccessor;
}

[HttpGet]
public async Task<ActionResult<List<string>>> GetWatchListAsync()
{
var userId = GetUserId();
return Ok(await _watchListService.GetWatchListAsync(userId));
}

private string GetUserId()
{
return _httpContextAccessor.HttpContext?.User.FindFirst(ClaimTypes.NameIdentifier)?.Value
?? throw new ArgumentNullException("User not found");
}

[HttpPost]
public async Task<ActionResult> AddMovieToWatchListAsync([FromBody] string movieId)
{
var userId = GetUserId();
await _watchListService.InsertToWatchedListAsync(userId, movieId);
return Ok();
}

[HttpDelete("{movieId}")]
public async Task<ActionResult> RemoveMovieFromWatchListAsync(string movieId)
{
var userId = GetUserId();
await _watchListService.RemoveFromWatchedListAsync(userId, movieId);
return Ok();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace Watchlist.API.Controllers
{
[Authorize(Roles = "Member")]
[Route("api/unfinishedWatchList")]
public class UnfinishedWatchListController : Controller
{

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@

namespace Watchlist.API.Entity
{
public class UnfinishedMovies
{
public string MovieId { get; set; } = string.Empty;

// total duration (in minutes)
public int ProgressDuarion { get; set; }

// Last watched
public DateTime LastWatched { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace Watchlist.API.Entity
{
public class UserUnfinishedMovies
{
public string UserId { get; set; } = string.Empty;

public List<UnfinishedMovies> UnfinishedMoviesList { get; set; } = new();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace Watchlist.API.Entity
{
public class UserWatchList
{
public string UserId { get; set; } = string.Empty;

public List<string> SavedMovieIds { get; set; } = new();
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using MongoDB.Driver;
using Watchlist.API.Entity;

namespace Watchlist.API.Infrastructure.Data
{
public interface IWatchListContext
{
IMongoCollection<UserWatchList> SavedMovies { get; }
IMongoCollection<UserUnfinishedMovies> UnfinishedMovies { get; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using System;
using MongoDB.Driver;
using Watchlist.API.Entity;

namespace Watchlist.API.Infrastructure.Data
{
public class WatchListContext : IWatchListContext
{
public WatchListContext(IConfiguration configuration)
{
var client = new MongoClient(configuration.GetValue<string>("DatabaseSettings:ConnectionString"));
var database = client.GetDatabase(configuration.GetValue<string>("DatabaseSettings:DatabaseName"));
SavedMovies = database.GetCollection<UserWatchList>("userSavedList");
UnfinishedMovies = database.GetCollection<UserUnfinishedMovies>("userUnfinishedMovies");
}

public WatchListContext()
{
}


public IMongoCollection<UserWatchList> SavedMovies { get; }

public IMongoCollection<UserUnfinishedMovies> UnfinishedMovies { get; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
using Watchlist.API.Infrastructure.Data;
using Watchlist.API.Repository.UnfinishedList;
using Watchlist.API.Repository.WatchList;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllers();

builder.Services.AddAuthentication("Bearer")
.AddJwtBearer("Bearer", options =>
{
options.RequireHttpsMetadata = false;
options.Authority = builder.Configuration["IdentityUrl"];
options.Audience = "watchlist";
});

// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

// DI for DbContext and Repository
builder.Services.AddScoped<IWatchListContext, WatchListContext>();
builder.Services.AddScoped<ISavedWatchListRepository, SavedWatchListRepository>();
builder.Services.AddScoped<IFinishedListRepository, FinishedListRepository>();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.UseAuthentication();
app.UseAuthorization();

app.MapControllers();

app.Run();

public partial class Program { }
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"$schema": "https://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:12245",
"sslPort": 44377
}
},
"profiles": {
"http": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "http://localhost:5013",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"dotnetRunMessages": true
},
"https": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "https://localhost:7085;http://localhost:5013",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"dotnetRunMessages": true
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System;

namespace Watchlist.API.Repository.WatchList
{
public interface ISavedWatchListRepository
{
// Add movie to watchlist
Task InsertToSavedWatchedListAsync(string userId, string movieId);
// Remove movie from watchlist
Task RemoveFromSavedWatchedListAsync(string userId, string movieId);
// Get watchlist
Task<List<string>> GetSavedWatchListAsync(string userId);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using MongoDB.Driver;
using Watchlist.API.Entity;
using Watchlist.API.Infrastructure.Data;

namespace Watchlist.API.Repository.WatchList
{
public class SavedWatchListRepository : ISavedWatchListRepository
{
private readonly IWatchListContext _context;

public SavedWatchListRepository(IWatchListContext context)
{
_context = context ?? throw new ArgumentNullException(nameof(context));
}

public async Task<List<string>> GetSavedWatchListAsync(string userId)
{
// Get all watch lists from database where userId == userId
return (await _context.SavedMovies.FindAsync(x => x.UserId == userId))
.FirstOrDefault()?.SavedMovieIds ?? new List<string>();
}

public async Task InsertToSavedWatchedListAsync(string userId, string movieId)
{
await _context.SavedMovies.UpdateOneAsync(
x => x.UserId == userId,
Builders<UserWatchList>.Update.AddToSet(x => x.SavedMovieIds, movieId),
new UpdateOptions { IsUpsert = true });
}

public async Task RemoveFromSavedWatchedListAsync(string userId, string movieId)
{
await _context.SavedMovies.UpdateOneAsync(
x => x.UserId == userId,
Builders<UserWatchList>.Update.Pull(x => x.SavedMovieIds, movieId));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using System;

namespace Watchlist.API.Repository.UnfinishedList
{
public class FinishedListRepository : IFinishedListRepository
{

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using System;

namespace Watchlist.API.Repository.UnfinishedList
{
public interface IFinishedListRepository
{

}
}
Loading