Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: add postgresql #2

Draft
wants to merge 3 commits into
base: development
Choose a base branch
from
Draft
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
2 changes: 2 additions & 0 deletions Backend/Backend.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.10"/>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.0" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.2" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.6.2"/>
</ItemGroup>

Expand Down
23 changes: 23 additions & 0 deletions Backend/Database/PostgresDbContext.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using Backend.Models;
using Microsoft.EntityFrameworkCore;

namespace Backend.Database;

/// <summary>
/// Contains all information on the postgresql database, for the object-database mapping.
/// This allows using C# to run SQL queries on the database.
/// </summary>
public class PostgresDbContext : DbContext
{
/// <summary>Reference to the Activities relational table. </summary>
public DbSet<Activity> Activities { get; set; }
/// <summary>Reference to the Enrollments relational table. </summary>
public DbSet<Enrollment> Enrollments { get; set; }

/// <summary>
/// Creates information how to set up the object-database mapping, from C# to SQL, on the postgresql database.
/// </summary>
/// <param name="options">All parameters that define the database connection.</param>
public PostgresDbContext(DbContextOptions<PostgresDbContext> options) : base(options)
{ }
}
5 changes: 4 additions & 1 deletion Backend/Models/Activity.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
using Microsoft.EntityFrameworkCore;

#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
namespace Backend.Models;

[PrimaryKey(nameof(Id))]
public class Activity
{
/// <summary>
Expand All @@ -10,7 +13,7 @@ public class Activity
/// <summary>
/// The name of the activity.
/// </summary>
public string Name { get; set; }
public string Name { get; set; } // TODO: set max string length for performance?
/// <summary>
/// A description or arbitrary length, explaining everything there is to know about the activity.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
namespace Backend.Models;

public class Participation
public class Enrollment
{
/// <summary>
/// Reference to the unique identifier of the activity which is participated.
/// Reference to the unique identifier of the activity which is enrolled for.
/// </summary>
public uint ActivityId { get; set; }
/// <summary>
/// The ID of the user, as determined by the used OAuth application, which participated in the activity.
/// The ID of the user, as determined by the used OAuth application, which enrolls for the activity.
/// </summary>
public string UserId { get; set; }
}
45 changes: 36 additions & 9 deletions Backend/Program.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
using Backend.Database;
using Backend.Models;
using Microsoft.AspNetCore.Http.HttpResults;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddNpgsql<PostgresDbContext>(connectionString: builder.Configuration.GetConnectionString("Postgresql"));

var app = builder.Build();

Expand All @@ -18,17 +21,41 @@

app.UseHttpsRedirection();

app.MapGet("/activity", (uint activityId) =>
app.MapGet("/activity", async (PostgresDbContext db, uint activityId) =>
{
return new Activity()
{
Id = activityId,
Name = "Some activity",
Description = "Some activity description",
DateTimeStart = DateTimeOffset.Now,
};
// Simply fetch and return
Activity? activity = await db.Activities.FindAsync(activityId);
return activity != null ? Results.Ok(activity) : Results.NotFound();
})
// .WithName("GetWeatherForecast")
.WithOpenApi();

app.MapPost("/activity", async (PostgresDbContext db, Activity activity) =>
{
// First, ensure activity with same id does not exist yet
Activity? currentActivity = await db.Activities.FindAsync(activity.Id);
if (currentActivity != null)
return Results.BadRequest("Activity already exists with this Id.");

// Activity does not exist yet, create it
db.Activities.Add(activity);
await db.SaveChangesAsync();
return Results.Ok(activity.Id);
})
.WithOpenApi();

app.MapDelete("/activity", async (PostgresDbContext db, uint activityId) =>
{
// First, check if activity exists
Activity? activity = await db.Activities.FindAsync(activityId);
if (activity == null)
return Results.NotFound();

// Remove activity
db.Activities.Remove(activity);
await db.SaveChangesAsync();
return Results.Ok();
})
.WithName("GetWeatherForecast")
.WithOpenApi();

app.Run();
4 changes: 2 additions & 2 deletions Backend/Tavern.http
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
@Tavern_HostAddress = http://localhost:5273
@Tavern_HostAddress = http://localhost:8080

GET {{Tavern_HostAddress}}/weatherforecast/
GET {{Tavern_HostAddress}}/activity?activityId=1
Accept: application/json

###
3 changes: 3 additions & 0 deletions Backend/appsettings.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
{
"ConnectionStrings": {
"Postgresql": "postgres"
},
"Logging": {
"LogLevel": {
"Default": "Information",
Expand Down
24 changes: 22 additions & 2 deletions compose.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,26 @@
services:
tavern-backend:
image: backend
backend:
restart: unless-stopped
ports:
- "8080:8080"
build:
context: .
dockerfile: Backend/Dockerfile
networks:
- postgres-network

postgres:
image: postgres:17
restart: always
environment:
POSTGRES_PASSWORD: docker-secret # TODO: use docker secrets to store this password
volumes:
- postgres-data:$PGDATA
networks:
- postgres-network

volumes:
postgres-data:

networks:
postgres-network: