fix: corrections de l'audit de sécurité et de robustesse
- VPN retiré : le contrôle reste activé (alerte parent, tunnel remonté après 30 s, autorisation redemandée à l'ouverture) - Horloge de référence : changer date/heure/fuseau ne contourne plus les plages horaires ni le temps d'écran (signalé au parent) - Mot de passe : PBKDF2 + attente croissante après 3 échecs ; conversion automatique des anciens hachages - Écrans protégés : aucun affichage avant chargement des réglages ; effacement du journal protégé - Signature release via keystore.properties (même clé que les versions publiées) - Sauvegarde Google : réglages, appairage et journal exclus - Alerte admin fiable (goAsync), relance refusée signalée, liste d'applis renvoyée à chaque installation, code d'appairage consommé - Journal thread-safe et sans recopie à chaque ligne ; correctifs lint - Tests unitaires (mot de passe, règles, versions, config Firebase) ; README aligné sur le comportement réel Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01R9CBCVP5oDu2sfoYPisNCQ
This commit is contained in:
1 parent
f33776bbb5
commit
e269e9932a
37 files changed
+809
-147
No files matched your search
@@ -0,0 +1,64 @@
|
||||
package com.jttools.datacontrol.guard
|
||||
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Test
|
||||
import java.time.LocalDateTime
|
||||
|
||||
class RulesTest {
|
||||
|
||||
// 2026-10-26 est un lundi.
|
||||
private fun at(day: Int, h: Int, m: Int = 0) = LocalDateTime.of(2026, 10, 25, h, m).plusDays(day.toLong())
|
||||
|
||||
private val json = """
|
||||
{"schedule":{"enabled":true,"cutsMobile":false,
|
||||
"windows":[{"days":[1,2,3,4,5],"start":480,"end":1200},{"days":[5],"start":1320,"end":120}]},
|
||||
"dailyLimitMin":90,
|
||||
"appLimits":[{"pkg":"com.game","min":30}],
|
||||
"blocked":["com.bad"],
|
||||
"bonus":{"date":"2026-10-26","globalMin":15,"apps":[{"pkg":"com.game","min":10}]}}
|
||||
""".trimIndent()
|
||||
|
||||
@Test fun `lecture complete`() {
|
||||
val r = Rules.parse(json)
|
||||
assertTrue(r.scheduleEnabled)
|
||||
assertFalse(r.scheduleCutsMobile)
|
||||
assertEquals(2, r.windows.size)
|
||||
assertEquals(90, r.dailyLimitMin)
|
||||
assertEquals(listOf(AppLimit("com.game", 30)), r.appLimits)
|
||||
assertEquals(setOf("com.bad"), r.blocked)
|
||||
assertEquals("2026-10-26", r.bonusDate)
|
||||
assertEquals(15, r.bonusGlobalMin)
|
||||
assertFalse(r.isEmpty)
|
||||
}
|
||||
|
||||
@Test fun `json vide ou invalide donne aucune regle`() {
|
||||
assertTrue(Rules.parse(null).isEmpty)
|
||||
assertTrue(Rules.parse("").isEmpty)
|
||||
assertTrue(Rules.parse("{pas du json").isEmpty)
|
||||
}
|
||||
|
||||
@Test fun `plage de journee`() {
|
||||
val r = Rules.parse(json)
|
||||
assertTrue(r.isOpenAt(at(1, 8))) // lundi 08:00 : début inclus
|
||||
assertTrue(r.isOpenAt(at(1, 19, 59)))
|
||||
assertFalse(r.isOpenAt(at(1, 20))) // fin exclue
|
||||
assertFalse(r.isOpenAt(at(1, 7, 59)))
|
||||
assertFalse(r.isOpenAt(at(6, 12))) // samedi : pas de plage de journée
|
||||
}
|
||||
|
||||
@Test fun `plage qui passe minuit deborde sur le lendemain`() {
|
||||
val r = Rules.parse(json)
|
||||
assertTrue(r.isOpenAt(at(5, 23))) // vendredi 23:00
|
||||
assertTrue(r.isOpenAt(at(6, 1, 30))) // samedi 01:30, suite de la plage du vendredi
|
||||
assertFalse(r.isOpenAt(at(6, 2)))
|
||||
assertFalse(r.isOpenAt(at(7, 1))) // dimanche 01:00 : pas de plage samedi soir
|
||||
}
|
||||
|
||||
@Test fun `prochaine ouverture`() {
|
||||
val r = Rules.parse(json)
|
||||
assertEquals("Reprise à 08:00.", r.nextOpeningText(at(1, 6)))
|
||||
assertEquals("Reprise à 08:00 (dans 2 j).", r.nextOpeningText(at(6, 12)))
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user