Skip to content
Merged
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
35 changes: 35 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Ignore Git stuff
.git
.gitignore

# Node / frontend build
node_modules
npm-debug.log
wwwroot

# .NET build artifacts
bin/
obj/
*.user
*.suo

# Logs and temp files
*.log
*.tmp
*.DS_Store

# Local environment and secrets
.env.*
appsettings.Development.json

# Docker-related
Dockerfile*
docker-compose.yml

# OS-specific junk
Thumbs.db

# Repo specific
.vscode
.vs
.github
71 changes: 25 additions & 46 deletions .github/workflows/main_budgetbud.yml
Original file line number Diff line number Diff line change
@@ -1,58 +1,37 @@
# Docs for the Azure Web Apps Deploy action: https://github.com/Azure/webapps-deploy
# More GitHub Actions for Azure: https://github.com/Azure/actions

name: Deploy to Production
name: Build and Push Docker Image

on:
push:
branches:
- main
workflow_dispatch:

env:
REGISTRY: docker.io
IMAGE_NAME: paradoxzero/budgetbud-alpine

jobs:
deploy:
runs-on: windows-latest
environment:
name: "Production"
url: ${{ steps.deploy-to-webapp.outputs.webapp-url }}
permissions:
id-token: write #This is required for requesting the JWT
build:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- name: Set up Node.js version
uses: actions/setup-node@v3
with:
node-version: "20.x"

- name: Build Client
run: |
npm install
npm run build --if-present
npm run test --if-present

- name: Set up .NET Core
uses: actions/setup-dotnet@v4
with:
dotnet-version: "8.x"

- name: Build Server
run: |
dotnet build --configuration Release
- name: Checkout source
uses: actions/checkout@v4

- name: Dotnet Publish
run: |
dotnet publish --configuration Release --output dist
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Login to Azure
uses: azure/login@v2
- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
client-id: ${{ secrets.AZUREAPPSERVICE_CLIENTID_D811F17711F44C24BFFB74BA7909FD66 }}
tenant-id: ${{ secrets.AZUREAPPSERVICE_TENANTID_9F5A4F52AFB14B6DB8B87ACE137C3E90 }}
subscription-id: ${{ secrets.AZUREAPPSERVICE_SUBSCRIPTIONID_6CFEAEA74C1044D98BDA21B27C81EAE3 }}
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

- name: "Deploy to Azure Web App"
uses: azure/webapps-deploy@v3
id: deploy-to-webapp
- name: Build and push image
uses: docker/build-push-action@v6
with:
app-name: "budgetbud"
slot-name: "Production"
package: dist
context: .
push: true
tags: |
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
76 changes: 0 additions & 76 deletions .github/workflows/main_budgetbudtest.yml

This file was deleted.

49 changes: 49 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# ===========================
# STAGE 1 - Frontend Build
# ===========================
FROM node:20-alpine AS frontend
WORKDIR /app

# Copy only what's needed for faster caching
# COPY package.json vite.config.ts ./
# COPY ui ./ui
# COPY app.html index.html demo.html ./
COPY . .

RUN npm install
RUN npm run build

# ===========================
# STAGE 2 - Backend Build
# ===========================
FROM mcr.microsoft.com/dotnet/sdk:9.0-alpine AS build
WORKDIR /src

COPY *.csproj ./
RUN dotnet restore

# Copy everything else
COPY . .
# Bring in prebuilt frontend from Stage 1
COPY --from=frontend /app/wwwroot ./wwwroot

RUN dotnet publish -c Release -o /app/publish

# ===========================
# STAGE 3 - Runtime
# ===========================
FROM mcr.microsoft.com/dotnet/aspnet:9.0-alpine AS final
WORKDIR /app

# Copy published output
COPY --from=build /app/publish .

# Environment variables
ENV ASPNETCORE_URLS=http://+:8080
ENV ASPNETCORE_ENVIRONMENT=Production

# Expose the app port
EXPOSE 8080

# Start the web server
ENTRYPOINT ["dotnet", "budgetbud.dll"]
8 changes: 4 additions & 4 deletions Properties/launchSettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:42516",
"sslPort": 44373
"applicationUrl": "http://localhost:8080",
"sslPort": 8080
}
},
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "http://localhost:5005",
"applicationUrl": "http://localhost:8080",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
Expand All @@ -22,7 +22,7 @@
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "https://localhost:7144;http://localhost:5005",
"applicationUrl": "https://localhost:8080",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
Expand Down
60 changes: 49 additions & 11 deletions Server.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,11 @@
* The source is available at: https://github.com/ParadoxZero/budgetbud
*/

using budgetbud.Services;
using budgetbud.Middlewares;
using budgetbud.Services;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.Google;

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
Expand All @@ -32,27 +35,62 @@
builder.Services.AddSwaggerGen();
}

if (builder.Environment.IsDevelopment())
builder.Services.AddSingleton<IIdentityService, BuiltInIdentityService>();

builder.Services.AddAuthentication(options =>
{
builder.Services.AddSingleton<IIdentityService, FakeIdentityService>();
}
else
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = GoogleDefaults.AuthenticationScheme;
})
.AddCookie(options =>
{
builder.Services.AddSingleton<IIdentityService, AzureIdentityService>();
}
options.LoginPath = "/login";
options.LogoutPath = "/logout";

// Persistent login
options.ExpireTimeSpan = TimeSpan.FromDays(30);
options.SlidingExpiration = true;

// So cookies persist across browser restarts
options.Cookie.IsEssential = true;
options.Cookie.HttpOnly = true;
options.Cookie.SameSite = SameSiteMode.Lax;
options.Cookie.SecurePolicy = CookieSecurePolicy.Always; // for https
})
.AddGoogle(options =>
{
options.ClientId = builder.Configuration.GetValue<string>("Auth:GoogleClientId");
options.ClientSecret = builder.Configuration.GetValue<string>("Auth:GoogleClientSecret");
});

builder.Services.AddSingleton<DbService>();
builder.Services.AddSingleton<UserDataService>();

var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseMiddleware<RedirectToLoginMiddleware>();
}
app.UseMiddleware<RedirectToLoginMiddleware>();

app.UseDefaultFiles();
app.UseStaticFiles();

app.MapGet("/login", async (HttpContext context) =>
{
// Start Google OAuth flow
await context.ChallengeAsync(
GoogleDefaults.AuthenticationScheme,
new AuthenticationProperties
{
RedirectUri = "/app.html", // where to go after successful login
IsPersistent = true
});
});


app.MapGet("/logout", async (HttpContext context) =>
{
await context.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
context.Response.Redirect("/index.html");
});

if (use_swagger)
{
app.UseSwagger();
Expand Down
2 changes: 2 additions & 0 deletions api/budget_controller.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,12 @@
using budgetbud.Exceptions;
using budgetbud.Models;
using budgetbud.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace budgetbud.Controllers;

[Authorize]
[ApiController]
[Route("api/[controller]")]
public class BudgetController : ControllerBase
Expand Down
Loading
Loading