Support Android emulator API access

Enable CORS in all environments and disable HTTPS redirect in dev.
Seed the database after migrations.
Make the API base URL configurable, defaulting to the Android
emulator host, and use per-config Android manifests.
This commit is contained in:
Tim Krampitz
2026-08-22 19:05:53 +02:00
parent 3296ecdfb3
commit 540cda102f
7 changed files with 142 additions and 11 deletions

View File

@@ -0,0 +1,89 @@
using Microsoft.EntityFrameworkCore;
using SlipItIn.Shared.Models;
namespace SlipItIn.Server.Data;
/// <summary>
/// Befüllt die Datenbank mit Testdaten (2 Testuser, einige Dutzend Phrasen),
/// wenn sie leer ist. Dient der Erleichterung manueller Tests.
/// </summary>
public static class DbSeeder
{
public static async Task SeedAsync(SlipItInDbContext context)
{
// Nur seeden, wenn die Datenbank leer ist
if (await context.Users.AnyAsync() || await context.Phrases.AnyAsync())
return;
var alice = new User
{
Username = "alice",
Email = "alice@test.local",
PasswordHash = BCrypt.Net.BCrypt.HashPassword("Test123!")
};
var bob = new User
{
Username = "bob",
Email = "bob@test.local",
PasswordHash = BCrypt.Net.BCrypt.HashPassword("Test123!")
};
context.Users.AddRange(alice, bob);
await context.SaveChangesAsync();
var phrases = new[]
{
"Das hat mir meine Oma schon immer gesagt.",
"Ich hab da mal eine Doku gesehen.",
"Das ist wie damals in der Grundschule.",
"Das muss man sich mal auf der Zunge zergehen lassen.",
"Da kommt mir direkt ein Lied in den Sinn.",
"Das ist wie beim Autofahren: Bremsen kann man immer noch.",
"Ich habe das Gefühl, wir reden aneinander vorbei.",
"Das würde ich an deiner Stelle nochmal überdenken.",
"Ich glaube, da steckt mehr dahinter.",
"Also ich finde, das riecht verdächtig nach Montag.",
"Das schmeckt nach mehr.",
"Da ist der Wurm drin.",
"Das hat hand und Fuß.",
"Das ist ein zweischneidiges Schwert.",
"Da liegt der Hase im Pfeffer.",
"Das ist wie ein guter Wein wird mit den Jahren besser.",
"Ich würde sagen: Glück im Unglück.",
"Das ist schon fast eine Wissenschaft für sich.",
"Man muss das Kind beim Namen nennen.",
"Das ist wie Weihnachten und Geburtstag zusammen.",
"Da geht mir das Herz auf.",
"Ich würde das jetzt nicht überbewerten.",
"Das kommt mir spanisch vor.",
"Das ist das Beste seit geschnittenem Brot.",
"Da bleibt kein Auge trocken.",
"Das ist wie Nägel mit Köpfen machen.",
"Ich habe da so eine Vermutung.",
"Das ist wie ein roter Faden.",
"Da platzt mir gleich der Kragen.",
"Ich bin da ganz bei dir.",
"Das muss man erstmal sacken lassen.",
"Das ist wie ein offenes Buch.",
"Da würde ich nicht drauf wetten.",
"Das ist wie eine Achterbahn der Gefühle.",
"Ich hab da ein ganz mieses Gefühl bei.",
"Das ist wie ein Dorn im Auge."
};
var random = new Random(42);
var creators = new[] { alice, bob };
foreach (var text in phrases)
{
context.Phrases.Add(new Phrase
{
Text = text,
CreatorId = creators[random.Next(creators.Length)].Id
});
}
await context.SaveChangesAsync();
}
}

View File

@@ -98,21 +98,28 @@ var app = builder.Build();
// Aspire Default Endpoints (Health Checks)
app.MapDefaultEndpoints();
// Migrations anwenden
// Migrations anwenden und Testdaten seeden (nur wenn die Datenbank leer ist)
using (var scope = app.Services.CreateScope())
{
var db = scope.ServiceProvider.GetRequiredService<SlipItInDbContext>();
db.Database.Migrate();
await DbSeeder.SeedAsync(db);
}
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.MapOpenApi();
app.UseCors("AllowAll");
}
app.UseCors("AllowAll");
// Beim Emulator/geräteübergreifenden Zugriff würde die HTTPS-Umleitung
// den Client auf eine nicht vertrauenswürdige Dev-Zertifikats-URL schicken.
if (!app.Environment.IsDevelopment())
{
app.UseHttpsRedirection();
}
app.UseAuthentication();
app.UseAuthorization();

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="de.krampitz.slipitin">
<application
android:allowBackup="true"
android:icon="@mipmap/appicon"
android:supportsRtl="true"
android:label="Slip It In"
android:usesCleartextTraffic="true" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
</manifest>

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="de.krampitz.slipitin">
<application
android:allowBackup="true"
android:icon="@mipmap/appicon"
android:supportsRtl="true"
android:label="Slip It In">
</application>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
</manifest>

View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="de.krampitz.slipitin">
<application android:allowBackup="true" android:icon="@mipmap/appicon" android:supportsRtl="true" android:label="Slip It In"></application>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
</manifest>

View File

@@ -4,9 +4,20 @@ namespace SlipItIn.Services;
public class AppConfigurationService : IAppConfigurationService
{
private const string ApiBaseUrlPreferenceKey = "api_base_url";
private const string DefaultApiBaseUrl = "https://localhost:7274";
private const string AndroidEmulatorApiBaseUrl = "http://10.0.2.2:5234";
public string ApiBaseUrl => DefaultApiBaseUrl;
public string ApiBaseUrl => Preferences.Default
.Get(ApiBaseUrlPreferenceKey, GetPlatformDefaultApiBaseUrl())
.TrimEnd('/');
public string HubUrl => $"{DefaultApiBaseUrl.TrimEnd('/')}/hubs/game";
public string HubUrl => $"{ApiBaseUrl}/hubs/game";
private static string GetPlatformDefaultApiBaseUrl()
{
return DeviceInfo.Platform == DevicePlatform.Android
? AndroidEmulatorApiBaseUrl
: DefaultApiBaseUrl;
}
}

View File

@@ -124,4 +124,12 @@
</MauiXaml>
</ItemGroup>
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)'=='Debug|net10.0-android'">
<AndroidManifest>Platforms\Android\AndroidManifest.Debug.xml</AndroidManifest>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)'=='Release|net10.0-android'">
<AndroidManifest>Platforms\Android\AndroidManifest.Release.xml</AndroidManifest>
</PropertyGroup>
</Project>