feat: verrouillage parental et désactivation par code du serveur

Le parent verrouille le téléphone à distance sur un écran de blocage plein
écran (ParentalLockActivity) que seul un code à usage unique généré par le
serveur permet de lever. La désactivation du contrôle (couper la protection,
dissocier, quitter le mode propriétaire, retirer l'anti-désinstallation) exige
désormais, sur un téléphone associé, ce code du serveur au lieu du mot de passe
local : l'enfant ne peut plus rien désactiver sans l'accord du parent.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R9CBCVP5oDu2sfoYPisNCQ
This commit is contained in:
tuxgyverandClaude Opus 4.8 committed 2026-10-25 21:26:41 +01:00
1 parent b138a15513
commit c66302a2bd
19 files changed
+436 -19

No files matched your search

@@ -24,7 +24,9 @@ data class AppSettings(
/** Mode réseau appliqué par le serveur : open, allowlist ou cut. */
val serverMode: String = "open",
val serverModeReason: String = "",
val policyVersion: Long = 0L
val policyVersion: Long = 0L,
/** Téléphone verrouillé à distance par le parent : un code du serveur est exigé pour le déverrouiller. */
val parentalLocked: Boolean = false
) {
val isPaired: Boolean get() = link != null
@@ -48,6 +48,7 @@ class SettingsRepository @Inject constructor(
val PASSWORD_FAILS = intPreferencesKey("password_fails")
val PASSWORD_LOCK_UNTIL = longPreferencesKey("password_lock_until")
val RULES_JSON = stringPreferencesKey("rules_json")
val PARENTAL_LOCKED = booleanPreferencesKey("parental_locked")
val USAGE_DAY = stringPreferencesKey("usage_day")
val USAGE_JSON = stringPreferencesKey("usage_json")
val CLOCK_SKEW_MS = longPreferencesKey("clock_skew_ms")
@@ -101,7 +102,8 @@ class SettingsRepository @Inject constructor(
link = FamilyLink.fromJson(prefs[Keys.LINK_JSON]),
serverMode = prefs[Keys.SERVER_MODE] ?: defaults.serverMode,
serverModeReason = prefs[Keys.SERVER_MODE_REASON] ?: defaults.serverModeReason,
policyVersion = prefs[Keys.POLICY_VERSION] ?: defaults.policyVersion
policyVersion = prefs[Keys.POLICY_VERSION] ?: defaults.policyVersion,
parentalLocked = prefs[Keys.PARENTAL_LOCKED] ?: defaults.parentalLocked
)
}
@@ -121,6 +123,11 @@ class SettingsRepository @Inject constructor(
context.dataStore.edit { it[Keys.CONTROL_ENABLED] = enabled }
}
/** Verrouillage parental plein écran (commande « plock » du parent, levé par un code du serveur). */
suspend fun setParentalLocked(locked: Boolean) {
context.dataStore.edit { it[Keys.PARENTAL_LOCKED] = locked }
}
suspend fun updatePlan(
planLimitMo: Long,
planPriceEuro: Double,