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
15 changes: 13 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Regélő – Android alkalmazás (v1.3.1)
# Regélő – Android alkalmazás (v1.3.2)

Magyar írói és olvasói platform (Wattpad / Inkitt jellegű), Kotlin + Jetpack Compose.

Expand All @@ -23,7 +23,7 @@ Google Playre aláírt Android App Bundle-t (AAB) tölts fel, ne fejlesztői deb
4. Készítsd el az AAB-t, ellenőrizd a Play Console belső tesztcsatornáján, majd csak sikeres ellenőrzés után
indítsd a szélesebb körű kiadást.
5. Minden új feltöltés előtt növeld az `app/build.gradle.kts` fájlban a `versionCode` értékét. Jelenlegi értéke
`131`; ez azonos vagy kisebb értékkel nem tölthető fel frissítésként.
`132`; ez azonos vagy kisebb értékkel nem tölthető fel frissítésként.

### Parancssoros/CI aláírás
Biztonságos build/CI titokként add meg mind a négy környezeti változót:
Expand All @@ -48,6 +48,9 @@ a szerveroldali hitelesítés és RLS-szabályok adják. Service-role kulcsot ti
- Az alkalmazás API 37-et céloz. A `versionCode` frissítése és az aláírt bundle ellenőrzése még szükséges a kiadáshoz.
- A completion RPC-t használó kliens kiadása előtt a cél Supabase-környezeten legyen alkalmazva a
`supabase/2026-10-26_app_v1_4.sql` migráció.
- A fióktörlés biztonságos útvonalához alkalmazd a
`supabase/2026-10-26_app_v1_4_1.sql` migrációt, és telepítsd a `delete-account` Edge Functiont.
A mobilkliens nem használ adatbázis-fallbacket, így sikertelen fájltakarítás esetén nem törli a fiókot.
- A helyi Room-adatbázis SQLCipherrel titkosított. Meglévő telepítésen az indulási migráció WAL-ellenőrzőpontot
készít, külön titkosított példányon konvertál, ellenőrzi, majd atomi fájlcserével vált; hiba esetén az eredeti
adatbázis marad érintetlen. A véletlen adatvesztés elkerülésére ne töröld az alkalmazás adatait vagy Keystore-kulcsát.
Expand All @@ -73,13 +76,21 @@ Hivatalos e-mail: regeloapp@gmail.com · Hivatalos profil az appban: @regelohiva
Az olvasási előrehaladás sikertelen feltöltése WorkManager-újrapróbálást eredményez; a fájlimport a 40 MB-os
határt olvasás közben érvényesíti, nem a teljes fájl memóriába töltése után. Regressziós tesztek fedik le e
változtatások kritikus útvonalait.
- **1.3.2 – Biztonságos fióktörlés** – Az app csak a fájlokat is takarító `delete-account` Edge Functionön
keresztül töröl; hiba esetén jelzi, hogy a törlés eredménye nem igazolható, és nem indít fájlokat hátrahagyó
adatbázis-fallbacket. A Supabase RPC-jogosultság visszavonva, a Storage-mappák mélységhatárának elérése pedig
hibával leállítja a törlést a hiányos sikerjelzés helyett.
- **v1.4 backend-kiegészítés** – A könyv befejezésének mentése szerveroldali, idempotens művelet,
amely a budapesti naptári évet és az adatbázisban szereplő publikált/befejezett állapotot használja.
A rate limit párhuzamos kéréseknél is atomikusan érvényesül. A kliens nem ment tokent titkosítatlanul,
az adat-export a teljes, szerveroldali GDPR-exportot használja, és a Room frissítés nem törli csendben
az ismeretlen sémájú helyi adatokat. A helyi Room-adatbázis SQLCipherrel titkosított; a kulcs Keystore-ban
védett AES-GCM burkolással tárolódik, sérült vagy hiányzó kulcs esetén az alkalmazás az adatok törlése helyett
hibával leáll. A korábbi sima SQLite-fájlt ellenőrzött, atomi migráció alakítja át.
- **v1.4.1 backend-kiegészítés** – A fióktörlési RPC végrehajtása anon és bejelentkezett kliensek elől visszavonva,
így a Storage-fájlok törlését kihagyó közvetlen adatbázis-törlési útvonal nem használható. A kliens Edge Function
hibájánál megőrzi a fiókot, és hibát jelez; a Storage-listázás mélységkorlátja túllépésekor a törlés megáll,
nem jelenti sikeresnek a hiányos fájltakarítást.
- **Profilon kezelt írások** – A saját művek és piszkozatok, import, sorozatok, export, statisztika és törlés
a Profil fülön érhető el; az Írás fül a napi célra és írói kihívásokra összpontosít.
- **1.3.0** – Hivatalos kiadványok, adatvédelem és biztonság:
Expand Down
4 changes: 2 additions & 2 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ android {
applicationId = "hu.regelo.app"
minSdk = 26
targetSdk = 37
versionCode = 131
versionName = "1.3.1"
versionCode = 132
versionName = "1.3.2"

buildConfigField("String", "SUPABASE_URL", "\"https://pqmfezkvaslqedalwwnn.supabase.co\"")
// Nyilvános (publishable) kulcs – a sorszintű jogosultságok (RLS) védik az adatokat.
Expand Down
12 changes: 6 additions & 6 deletions app/src/main/java/hu/regelo/app/data/AuthRepository.kt
Original file line number Diff line number Diff line change
Expand Up @@ -188,20 +188,20 @@ class AuthRepository {
/**
* App Store / Google Play követelmény: a fiók és minden adata végleges törlése.
* Elsőként a delete-account Edge Function fut (a feltöltött képeket is törli a tárolókból);
* ha az nem érhető el, az adatbázis-függvény törli a fiókot és minden sorát.
* hiba esetén nem használunk adatbázis-fallbacket, mert az árván hagyhatja a feltöltött fájlokat.
*/
suspend fun deleteAccount() {
val deletedWithFiles = try {
try {
AppGraph.supabase.functions.invoke("delete-account")
true
} catch (e: CancellationException) {
throw e
} catch (e: Exception) {
hu.regelo.app.util.ErrorReporter.report(e, "delete-account-function")
false
throw IllegalStateException(
"A fióktörlés eredményét nem sikerült megerősíteni. Ellenőrizd a fiók állapotát, majd próbáld újra.",
e,
)
}
// Ha a függvény már törölte a fiókot, ez nem talál sort (a token még érvényes) – nem hiba.
if (!deletedWithFiles) AppGraph.supabase.postgrest.rpc("delete_own_account")
withContext(NonCancellable) {
AppGraph.messages.stop()
runCatching { auth.signOut() }
Expand Down
3 changes: 3 additions & 0 deletions supabase/2026-10-26_app_v1_4_1.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
-- Regélő app v1.4.1 – a fióktörlés csak a fájlokat is kezelő Edge Functionön keresztül történhet.
-- Az alkalmazás nem hívja ezt az RPC-t; közvetlen hozzáférés megkerülné a Storage-takarítást.
revoke execute on function public.delete_own_account() from public, anon, authenticated;
2 changes: 1 addition & 1 deletion supabase/functions/delete-account/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const admin: SupabaseClient = createClient(

/** Egy mappa összes fájlja (rekurzívan), a tároló gyökeréhez viszonyított útvonallal. */
async function listAll(bucket: string, prefix: string, depth = 0): Promise<string[]> {
if (depth > 6) return [];
if (depth > 6) throw new Error(`${bucket}: storage folder nesting limit exceeded`);
const paths: string[] = [];
for (let offset = 0; ; offset += PAGE) {
const { data, error } = await admin.storage.from(bucket).list(prefix, { limit: PAGE, offset });
Expand Down
7 changes: 7 additions & 0 deletions supabase/tests/rls_battery_v1_3.sql
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@ begin
and c.is_draft = false order by c.order_index desc limit 1), false);
end $$;

insert into t_log(ok, msg)
values (
not has_function_privilege('authenticated', 'public.delete_own_account()', 'EXECUTE')
and not has_function_privilege('anon', 'public.delete_own_account()', 'EXECUTE'),
'A fiók törlése csak a Storage-t is takarító Edge Functionön keresztül érhető el'
);

-- ================= A (hétköznapi felhasználó) =================
select set_config('request.jwt.claims', json_build_object('sub', current_setting('t.a'), 'role', 'authenticated')::text, true);
set local role authenticated;
Expand Down
Loading