feat: add src

closes #6
This commit is contained in:
cswimr 2025-01-29 18:09:21 +00:00
parent 93b6009d31
commit 8bcb8127bf
Signed by: cswimr
GPG key ID: 0EC431A8DA8F8087
12 changed files with 411 additions and 1 deletions

15
Data/MyhmContext.cs Normal file
View file

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Myhm.Models;
namespace Myhm.Data
{
public class MyhmContext(DbContextOptions<MyhmContext> options) : DbContext(options)
{
//public DbSet<Myhm.Models.Ban> Ban { get; set; } = default!;
}
}

View file

@ -0,0 +1,17 @@
namespace Myhm.Models
{
public class MyhmConfiguration
{
public required string GlobalToken { get; init; }
public required string DatabaseConnectionString { get; init; }
public required DatabaseTypes DatabaseType { get; init; }
public bool UseSentry { get; init; } = true;
public bool UseSwagger { get; init; } = true;
public bool LogRequests { get; init; } = true;
}
public enum DatabaseTypes
{
PostgresSQL,
}
}

120
Program.cs Normal file
View file

@ -0,0 +1,120 @@
using System.Reflection;
using Microsoft.EntityFrameworkCore;
using Microsoft.OpenApi.Models;
using Myhm.Data;
using Myhm.Models;
using Myhm.Util.SwaggerTheme;
var builder = WebApplication.CreateBuilder(args);
// Configuration
var config = builder.Configuration.GetSection("Configuration").Get<MyhmConfiguration>();
builder.Services.Configure<MyhmConfiguration>(builder.Configuration.GetSection("Configuration"));
if (config?.GlobalToken == "CHANGE-ME")
{
throw new InvalidOperationException(
"Global token is not a valid value, please set the `CONFIGURATION__GLOBALTOKEN` environment variable to a random value. `openssl rand -hex 64` is a good way to generate a random value."
);
}
// Initialize Database
builder.Services.AddDbContextFactory<MyhmContext>(options =>
options.UseNpgsql(builder.Configuration.GetConnectionString("MyhmContext"))
);
// Sentry
if (config?.UseSentry == true)
{
builder.WebHost.UseSentry();
}
// Add services to the container.
builder.Services.AddHttpLogging(o => { });
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(opts =>
{
opts.SwaggerDoc(
"v1",
new OpenApiInfo
{
Title = "Myhm API",
Version = "v1",
Description = "",
}
);
opts.AddSecurityDefinition(
"Bearer",
new OpenApiSecurityScheme
{
Description =
"JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"",
Name = "Authorization",
In = ParameterLocation.Header,
Type = SecuritySchemeType.ApiKey,
Scheme = "Bearer",
}
);
opts.AddSecurityRequirement(
new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer",
},
Scheme = "oauth2",
Name = "Bearer",
In = ParameterLocation.Header,
},
new List<string>()
},
}
);
var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
opts.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, xmlFile));
});
var app = builder.Build();
var assembly = Assembly.GetExecutingAssembly();
foreach (var resource in assembly.GetManifestResourceNames())
{
app.Logger.LogDebug("Resource: {Resource}", resource);
}
if (config?.UseSwagger == true)
{
app.UseSwagger();
app.UseSwaggerUI(CustomStyle.CustomModern);
}
if (config?.LogRequests == true)
{
app.UseHttpLogging();
}
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error", createScopeForErrors: true);
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseAntiforgery();
// if (app.Environment.IsDevelopment())
// {
// app.Logger.LogInformation(
// "Development mode detected, printing configuration: {Configuration}",
// config?.ToJson()
// );
// }
app.Run();

View file

@ -0,0 +1,23 @@
{
"$schema": "https://json.schemastore.org/launchsettings.json",
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": false,
"applicationUrl": "http://localhost:5054",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": false,
"applicationUrl": "https://localhost:7076;http://localhost:5054",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

View file

@ -1,2 +1 @@
# myhm-commission

View file

@ -0,0 +1,26 @@
using System.Security.Cryptography;
using System.Text;
namespace Myhm.Util;
public class RandomStringGenerator
{
private static readonly char[] chars =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*+?".ToCharArray();
public static string GenerateRandomString(int length)
{
var stringBuilder = new StringBuilder();
using (var rng = RandomNumberGenerator.Create())
{
byte[] buffer = new byte[1];
for (int i = 0; i < length; i++)
{
rng.GetBytes(buffer);
var randomIndex = buffer[0] % chars.Length;
stringBuilder.Append(chars[randomIndex]);
}
}
return stringBuilder.ToString();
}
}

View file

@ -0,0 +1,12 @@
using System;
using AspNetCore.Swagger.Themes;
namespace Myhm.Util.SwaggerTheme;
public class CustomStyle : ModernStyle
{
protected CustomStyle(string fileName)
: base(fileName) { }
public static CustomStyle CustomModern => new("modern.custom.css");
}

View file

@ -0,0 +1,117 @@
:root {
/* Light mode (Catppuccin Latte) */
--catppuccin-pink: #ea76cb;
--catppuccin-mauve: #8839ef;
--catppuccin-red: #d20f39;
--catppuccin-maroon: #e64553;
--catppuccin-peach: #fe640b;
--catppuccin-yellow: #df8e1d;
--catppuccin-green: #40a02b;
--catppuccin-teal: #179299;
--catppuccin-sky: #04a5e5;
--catppuccin-sapphire: #209fb5;
--catppuccin-blue: #1e66f5;
--catppuccin-lavender: #7287fd;
--catppuccin-text: #4c4f69;
--catppuccin-subtext1: #5c5f77;
--catppuccin-subtext0: #6c6f85;
--catppuccin-overlay2: #7c7f93;
--catppuccin-overlay1: #8c8fa1;
--catppuccin-overlay0: #9ca0b0;
--catppuccin-surface2: #acb0be;
--catppuccin-surface1: #bcc0cc;
--catppuccin-surface0: #ccd0da;
--catppuccin-base: #eff1f5;
--catppuccin-mantle: #e6e9ef;
--catppuccin-crust: #dce0e8;
--link: var(--catppuccin-blue);
--link-hover: var(--catppuccin-sapphire);
--accent: var(--catppuccin-green);
--error: var(--catppuccin-red);
/* Body */
--body-background-color: var(--catppuccin-base);
--swagger-main-color: var(--catppuccin-text);
--scrollbar-thumb-color: var(--catppuccin-surface1);
--scrollbar-thumb-hover-color: var(--catppuccin-surface0);
/* Loading */
--loading-container-border-color: var(--accent);
/* Errors Container */
--errors-wrapper-background-color: var(--catppuccin-surface0);
--errors-wrapper-border-color: var(--error);
--errors-wrapper-errors-color: var(--error);
/* Topbar */
--topbar-background-color: var(--catppuccin-surface0);
--topbar-pinned-background-color: var(--catppuccin-surface0);
--topbar-border-color: var(--accent);
--topbar-select-label-color: var(--catppuccin-text);
--topbar-select-border-color: var(--accent);
/* Infobox */
--swagger-info-link: var(--link);
--swagger-info-link-hover: var(--link-hover);
--api-version-background-color: var(--catppuccin-surface2);
--api-version-stamp-background-color: var(--accent);
--api-version-color: var(--catppuccin-base);
/* Authorization */
--btn-authorize-background-color: var(--catppuccin-surface0);
--btn-authorize-border-color: var(--catppuccin-green);
--btn-authorize-font-color: var(--catppuccin-green);
--btn-authorize-svg-fill-color: var(--catppuccin-green);
--auth-container-background-color: var(--catppuccin-surface0);
--auth-container-errors-color: var(--catppuccin-red);
--auth-wrapper-background-color: var(--catppuccin-mantle);
--auth-wrapper-border-color: var(--accent);
/* Form Elements */
--select-border-color: var(--accent);
--input-background-color: var(--catppuccin-surface0);
--input-border-color: var(--accent);
--input-invalid-border-color: var(--error);
--input-disabled-background-color: var(--catppuccin-crust);
--input-disabled-border-color: var(--catppuccin-surface1);
/* Dialog */
--dialog-background-color: var(--catppuccin-mantle);
--dialog-border-color: var(--accent);
}
.swagger-ui .topbar .download-url-wrapper input[type="text"], .swagger-ui .topbar .download-url-wrapper .select-label select {
background-color: var(--catppuccin-surface0);
color: var(--catppuccin-text);
}
@media (prefers-color-scheme: dark) {
:root {
/* Dark mode (Catppuccin Mocha) */
--catppuccin-pink: #f5c2e7;
--catppuccin-mauve: #cba6f7;
--catppuccin-red: #f38ba8;
--catppuccin-maroon: #eba0ac;
--catppuccin-peach: #fab387;
--catppuccin-yellow: #f9e2af;
--catppuccin-green: #a6e3a1;
--catppuccin-teal: #94e2d5;
--catppuccin-sky: #89dceb;
--catppuccin-sapphire: #74c7ec;
--catppuccin-blue: #89b4fa;
--catppuccin-lavender: #b4befe;
--catppuccin-text: #cdd6f4;
--catppuccin-subtext1: #bac2de;
--catppuccin-subtext0: #a6adc8;
--catppuccin-overlay2: #9399b2;
--catppuccin-overlay1: #7f849c;
--catppuccin-overlay0: #6c7086;
--catppuccin-surface2: #585b70;
--catppuccin-surface1: #45475a;
--catppuccin-surface0: #313244;
--catppuccin-base: #1e1e2e;
--catppuccin-mantle: #181825;
--catppuccin-crust: #11111b;
}
}

View file

@ -0,0 +1,12 @@
{
"Logging": {
"LogLevel": {
"Default": "Trace"
}
},
"Configuration": {
// DO NOT USE THIS AUTHTOKEN IN PRODUCTION!!!
"AuthToken": "hi",
"UseSentry": false
}
}

27
appsettings.json Normal file
View file

@ -0,0 +1,27 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning",
"Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware": "Information"
}
},
"AllowedHosts": "*",
"Configuration": {
"AuthToken": "CHANGE-ME",
"UseSwagger": true,
"LogRequests": true,
"UseSentry": true
},
"Sentry": {
"Dsn": "https://64a43934d4e6b76fce9b2307e1787188@sentry.csw.im/8",
"SendDefaultPii": true,
"MaxRequestBodySize": "Always",
"MinimumBreadcrumbLevel": "Debug",
"MinimumEventLevel": "Warning",
"AttachStackTrace": true,
"Debug": true,
"DiagnosticLevel": "Error",
"TracesSampleRate": 1.0
}
}

20
myhm-commission.csproj Normal file
View file

@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<RootNamespace>Myhm</RootNamespace>
</PropertyGroup>
<ItemGroup>
<EmbeddedResource Include="Util\SwaggerTheme\modern.custom.css" />
<PackageReference Include="AspNetCore.SwaggerUI.Themes" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.1" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.3" />
<PackageReference Include="Sentry.AspNetCore" Version="5.0.1" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="7.2.0" />
</ItemGroup>
</Project>

22
myhm-commission.sln Normal file
View file

@ -0,0 +1,22 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "myhm-commission", "myhm-commission.csproj", "{D39B0551-B762-4BD9-81DC-FF49FB7F8439}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{D39B0551-B762-4BD9-81DC-FF49FB7F8439}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D39B0551-B762-4BD9-81DC-FF49FB7F8439}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D39B0551-B762-4BD9-81DC-FF49FB7F8439}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D39B0551-B762-4BD9-81DC-FF49FB7F8439}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal