diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..3729ff0 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,25 @@ +**/.classpath +**/.dockerignore +**/.env +**/.git +**/.gitignore +**/.project +**/.settings +**/.toolstarget +**/.vs +**/.vscode +**/*.*proj.user +**/*.dbmdl +**/*.jfm +**/azds.yaml +**/bin +**/charts +**/docker-compose* +**/Dockerfile* +**/node_modules +**/npm-debug.log +**/obj +**/secrets.dev.yaml +**/values.dev.yaml +LICENSE +README.md \ No newline at end of file diff --git a/Nevyn.sln b/Nevyn.sln new file mode 100644 index 0000000..11d3e6d --- /dev/null +++ b/Nevyn.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.2.32616.157 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nevyn", "Nevyn\Nevyn.csproj", "{423CD237-7404-4355-868F-CE5861835258}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {423CD237-7404-4355-868F-CE5861835258}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {423CD237-7404-4355-868F-CE5861835258}.Debug|Any CPU.Build.0 = Debug|Any CPU + {423CD237-7404-4355-868F-CE5861835258}.Release|Any CPU.ActiveCfg = Release|Any CPU + {423CD237-7404-4355-868F-CE5861835258}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {0A418FE4-56F9-461C-BB0D-C63F1FFD9EFC} + EndGlobalSection +EndGlobal diff --git a/Nevyn/.config/dotnet-tools.json b/Nevyn/.config/dotnet-tools.json new file mode 100644 index 0000000..d7a0783 --- /dev/null +++ b/Nevyn/.config/dotnet-tools.json @@ -0,0 +1,12 @@ +{ + "version": 1, + "isRoot": true, + "tools": { + "microsoft.dotnet-msidentity": { + "version": "1.0.3", + "commands": [ + "dotnet-msidentity" + ] + } + } +} \ No newline at end of file diff --git a/Nevyn/Controllers/MoneyController.cs b/Nevyn/Controllers/MoneyController.cs new file mode 100644 index 0000000..e6fb5f3 --- /dev/null +++ b/Nevyn/Controllers/MoneyController.cs @@ -0,0 +1,98 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Nevyn.Models; + +namespace Nevyn.Controllers +{ + [Route("api/[controller]")] + [ApiController] + public class MoneyController : ControllerBase + { + private readonly MoneyContext _context; + + public MoneyController(MoneyContext context) + { + _context = context; + } + + // GET: api/ShoppingLists + [HttpGet] + public async Task>> GetWallet() + { + return await _context.UpdateWallet.Select(x => ItemToDTO(x)).ToListAsync(); + } + + // GET: api/ShoppingLists/5 + [HttpGet("{id}")] + public async Task> GetWallet(long id) + { + var wallet = await _context.UpdateWallet.FindAsync(id); + + if (wallet == null) + { + return NotFound(); + } + + return ItemToDTO(wallet); + } + + // PUT: api/ShoppingLists/5 + // To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754 + [HttpPut] + public async Task PutWallet(long id, Wallet wallet) + { + + var currentWallet = await _context.UpdateWallet.FindAsync(wallet.Id); + if (currentWallet == null) + { + return NotFound(); + } + currentWallet.Kort = wallet.Kort; + currentWallet.Buffert = wallet.Buffert; + currentWallet.Fonder = wallet.Fonder; + currentWallet.Spara = wallet.Spara; + + + await _context.SaveChangesAsync(); + + return NoContent(); + } + + // POST: api/ShoppingLists + // To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754 + [HttpPost] + public async Task> PostWallet(Wallet inputWallet) + { + + var wallet = new Wallet + { + Buffert = inputWallet.Buffert, + Fonder = inputWallet.Fonder, + Kort = inputWallet.Kort, + Spara = inputWallet.Spara, + }; + + _context.UpdateWallet.Add(wallet); + await _context.SaveChangesAsync(); + + return CreatedAtAction( + nameof(GetWallet), + new { id = wallet.Id }, + ItemToDTO(wallet)); + } + + private static WalletDTO ItemToDTO(Wallet wallet) => + new WalletDTO + { + Kort = wallet.Kort, + TotalAmount = wallet.TotalAmount, + AmountLeftPerDay = wallet.MoneyUntilSalary, + Debug = "There is " + wallet.DaysLeftUntilSalary + " days left", + }; + } +} diff --git a/Nevyn/Controllers/ShoppingListsController.cs b/Nevyn/Controllers/ShoppingListsController.cs new file mode 100644 index 0000000..b236017 --- /dev/null +++ b/Nevyn/Controllers/ShoppingListsController.cs @@ -0,0 +1,127 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Nevyn.Models; + +namespace Nevyn.Controllers +{ + [Route("api/[controller]")] + [ApiController] + public class ShoppingListsController : ControllerBase + { + private readonly ShoppingContext _context; + + public ShoppingListsController(ShoppingContext context) + { + _context = context; + } + + // GET: api/ShoppingLists + [HttpGet] + public async Task>> GetUpdateShopping() + { + return await _context.UpdateShopping.Select(x => ItemToDTO(x)).ToListAsync(); + } + + // GET: api/ShoppingLists/5 + [HttpGet("{id}")] + public async Task> GetShoppingList(long id) + { + var shoppingList = await _context.UpdateShopping.FindAsync(id); + + if (shoppingList == null) + { + return NotFound(); + } + + return ItemToDTO(shoppingList); + } + + // PUT: api/ShoppingLists/5 + // To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754 + [HttpPut("{id}")] + public async Task PutShoppingList(long id, ShoppingListDTO shoppingListDTO) + { + if (id != shoppingListDTO.Id) + { + return BadRequest(); + } + + //_context.Entry(shoppingList).State = EntityState.Modified; + + var shoppingList = await _context.UpdateShopping.FindAsync(id); + if (shoppingList == null) + { + return NotFound(); + } + + shoppingList.Name = shoppingListDTO.Name; + shoppingList.IsComplete = shoppingListDTO.IsComplete; + + + try + { + await _context.SaveChangesAsync(); + } + catch (DbUpdateConcurrencyException) when (!ShoppingListExists(id)) + { + return NotFound(); + } + + return NoContent(); + } + + // POST: api/ShoppingLists + // To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754 + [HttpPost] + public async Task> PostShoppingList(ShoppingListDTO shoppingListDTO) + { + + var shoppingList = new ShoppingList + { + IsComplete = shoppingListDTO.IsComplete, + Name = shoppingListDTO.Name + }; + + _context.UpdateShopping.Add(shoppingList); + await _context.SaveChangesAsync(); + + return CreatedAtAction( + nameof(GetShoppingList), + new { id = shoppingList.Id }, + ItemToDTO(shoppingList)); + } + + // DELETE: api/ShoppingLists/5 + [HttpDelete("{id}")] + public async Task DeleteShoppingList(long id) + { + var shoppingList = await _context.UpdateShopping.FindAsync(id); + if (shoppingList == null) + { + return NotFound(); + } + + _context.UpdateShopping.Remove(shoppingList); + await _context.SaveChangesAsync(); + + return NoContent(); + } + + private bool ShoppingListExists(long id) + { + return _context.UpdateShopping.Any(e => e.Id == id); + } + private static ShoppingListDTO ItemToDTO(ShoppingList shoppingList) => + new ShoppingListDTO + { + Id = shoppingList.Id, + Name = shoppingList.Name, + IsComplete = shoppingList.IsComplete + }; + } +} diff --git a/Nevyn/Dockerfile b/Nevyn/Dockerfile new file mode 100644 index 0000000..9eb946d --- /dev/null +++ b/Nevyn/Dockerfile @@ -0,0 +1,22 @@ +#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging. + +FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base +WORKDIR /app +EXPOSE 80 +EXPOSE 443 + +FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build +WORKDIR /src +COPY ["Nevyn/Nevyn.csproj", "Nevyn/"] +RUN dotnet restore "Nevyn/Nevyn.csproj" +COPY . . +WORKDIR "/src/Nevyn" +RUN dotnet build "Nevyn.csproj" -c Release -o /app/build + +FROM build AS publish +RUN dotnet publish "Nevyn.csproj" -c Release -o /app/publish + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "Nevyn.dll"] \ No newline at end of file diff --git a/Nevyn/Models/Money.cs b/Nevyn/Models/Money.cs new file mode 100644 index 0000000..f65a2e0 --- /dev/null +++ b/Nevyn/Models/Money.cs @@ -0,0 +1,61 @@ +using System; +namespace Nevyn.Models +{ + public class Wallet + { + public int Id { get; set; } + public int TotalAmount + { + get + { + return this.Kort + this.Buffert + this.Spara + this.Fonder; + } + } + public int Kort { get; set; } + public int Buffert { get; set; } + public int Spara { get; set; } + public int Fonder { get; set; } + + public int MoneyUntilSalary { + get + { + DateTime payDay = SalaryCalculator.CalculatePayDay(DateTime.Now); + this.DaysLeftUntilSalary = (payDay - DateTime.Now).Days; + return this.Kort / this.DaysLeftUntilSalary; + } + } + public int DaysLeftUntilSalary { get; set; } + + public class SalaryCalculator + { + public static DateTime CalculatePayDay(DateTime date) + { + // Get the 25th of the current month + var payDay = new DateTime(date.Year, date.Month, 25); + + // If the 25th is on a weekend, get the previous Friday + if (payDay.DayOfWeek == DayOfWeek.Saturday) + { + payDay = payDay.AddDays(-1); + } + else if (payDay.DayOfWeek == DayOfWeek.Sunday) + { + payDay = payDay.AddDays(-2); + } + + return payDay; + } + } + + } + + public class WalletDTO + { + public int Id { get; set; } + public int TotalAmount { get; set; } + public int AmountLeftPerDay { get; set; } + public int Kort { get; set; } + public string Debug { get; set; } + } + +} diff --git a/Nevyn/Models/MoneyContext.cs b/Nevyn/Models/MoneyContext.cs new file mode 100644 index 0000000..39c2ad4 --- /dev/null +++ b/Nevyn/Models/MoneyContext.cs @@ -0,0 +1,14 @@ +using Microsoft.EntityFrameworkCore; + +namespace Nevyn.Models +{ + public class MoneyContext : DbContext + { + public MoneyContext(DbContextOptions options) : base(options) + { + + } + + public DbSet UpdateWallet { get; set; } = null!; + } +} diff --git a/Nevyn/Models/ShoppingContext.cs b/Nevyn/Models/ShoppingContext.cs new file mode 100644 index 0000000..914fbaa --- /dev/null +++ b/Nevyn/Models/ShoppingContext.cs @@ -0,0 +1,14 @@ +using Microsoft.EntityFrameworkCore; + +namespace Nevyn.Models +{ + public class ShoppingContext : DbContext + { + public ShoppingContext(DbContextOptions options) : base(options) + { + + } + + public DbSet UpdateShopping { get; set; } = null!; + } +} diff --git a/Nevyn/Models/ShoppingList.cs b/Nevyn/Models/ShoppingList.cs new file mode 100644 index 0000000..42a99a7 --- /dev/null +++ b/Nevyn/Models/ShoppingList.cs @@ -0,0 +1,20 @@ +namespace Nevyn.Models +{ + public class ShoppingList + { + public long Id { get; set; } + public int Amount { get; set; } + public string? Name { get; set; } + public bool IsComplete { get; set; } + public string? Secret { get; set; } + + } + public class ShoppingListDTO + { + public long Id { get; set; } + public int Amount { get; set; } + public string? Name { get; set; } + public bool IsComplete { get; set; } + + } +} diff --git a/Nevyn/Nevyn.csproj b/Nevyn/Nevyn.csproj new file mode 100644 index 0000000..d770bf0 --- /dev/null +++ b/Nevyn/Nevyn.csproj @@ -0,0 +1,28 @@ + + + + net6.0 + enable + enable + aspnet-Nevyn-7C7F87FA-EADD-461B-8418-8C03C2EF8DB3 + Linux + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + diff --git a/Nevyn/Program.cs b/Nevyn/Program.cs new file mode 100644 index 0000000..615bfcd --- /dev/null +++ b/Nevyn/Program.cs @@ -0,0 +1,37 @@ +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.Identity.Web; +using Microsoft.EntityFrameworkCore; +using Nevyn.Models; + +var builder = WebApplication.CreateBuilder(args); + +// Add services to the container. +//builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) + +builder.Services.AddControllers(); +// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle +builder.Services.AddDbContext(opt => + opt.UseInMemoryDatabase("ShoppingList")); +builder.Services.AddDbContext(opt => + opt.UseInMemoryDatabase("Wallet")); +builder.Services.AddEndpointsApiExplorer(); +builder.Services.AddSwaggerGen(); + +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(); diff --git a/Nevyn/Properties/launchSettings.json b/Nevyn/Properties/launchSettings.json new file mode 100644 index 0000000..152cb9c --- /dev/null +++ b/Nevyn/Properties/launchSettings.json @@ -0,0 +1,38 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:8080", + "sslPort": 44397 + } + }, + "profiles": { + "Nevyn": { + "commandName": "Project", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "http://localhost:8080", + "dotnetRunMessages": true + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "Docker": { + "commandName": "Docker", + "launchBrowser": true, + "launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}/swagger", + "publishAllPorts": true, + "useSSL": true + } + } +} \ No newline at end of file diff --git a/Nevyn/Properties/serviceDependencies.json b/Nevyn/Properties/serviceDependencies.json new file mode 100644 index 0000000..dbc3a36 --- /dev/null +++ b/Nevyn/Properties/serviceDependencies.json @@ -0,0 +1,9 @@ +{ + "dependencies": { + "identityapp1": { + "type": "identityapp", + "connectionId": "AzureAD:ClientSecret", + "dynamicId": null + } + } +} \ No newline at end of file diff --git a/Nevyn/Properties/serviceDependencies.local.json b/Nevyn/Properties/serviceDependencies.local.json new file mode 100644 index 0000000..9077a71 --- /dev/null +++ b/Nevyn/Properties/serviceDependencies.local.json @@ -0,0 +1,10 @@ +{ + "dependencies": { + "identityapp1": { + "secretStore": "LocalSecretsFile", + "type": "identityapp.secretStore", + "connectionId": "AzureAD:ClientSecret", + "dynamicId": null + } + } +} \ No newline at end of file diff --git a/Nevyn/appsettings.Development.json b/Nevyn/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/Nevyn/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/Nevyn/appsettings.json b/Nevyn/appsettings.json new file mode 100644 index 0000000..10f68b8 --- /dev/null +++ b/Nevyn/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +}