Merge branch 'main' into feat/adding-h5p-tasks
All checks were successful
CI Pipeline / lint-and-test (pull_request) Successful in 2m30s
All checks were successful
CI Pipeline / lint-and-test (pull_request) Successful in 2m30s
This commit is contained in:
commit
0696ce409f
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -1,2 +0,0 @@
|
|||
#Wed Sep 02 15:03:29 CEST 2026
|
||||
gradle.version=9.5.1
|
||||
Binary file not shown.
Binary file not shown.
10
.idea/.gitignore
vendored
10
.idea/.gitignore
vendored
|
|
@ -1,10 +0,0 @@
|
|||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
# Ignored default folder with query files
|
||||
/queries/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CompilerConfiguration">
|
||||
<bytecodeTargetLevel target="21" />
|
||||
</component>
|
||||
</project>
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
|
||||
<data-source source="LOCAL" name="kidio_db@82.165.11.162" uuid="c8ad70de-d5fc-407a-9165-4f24328fa311">
|
||||
<driver-ref>postgresql</driver-ref>
|
||||
<synchronize>true</synchronize>
|
||||
<jdbc-driver>org.postgresql.Driver</jdbc-driver>
|
||||
<jdbc-url>jdbc:postgresql://82.165.11.162:5432/kidio_db</jdbc-url>
|
||||
<working-dir>$ProjectFileDir$</working-dir>
|
||||
</data-source>
|
||||
</component>
|
||||
</project>
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="GradleMigrationSettings" migrationVersion="1" />
|
||||
<component name="GradleSettings">
|
||||
<option name="linkedExternalProjectsSettings">
|
||||
<GradleProjectSettings>
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="modules">
|
||||
<set>
|
||||
<option value="$PROJECT_DIR$" />
|
||||
</set>
|
||||
</option>
|
||||
</GradleProjectSettings>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="KotlinJpsPluginSettings">
|
||||
<option name="externalSystemId" value="Gradle" />
|
||||
<option name="version" value="2.4.0" />
|
||||
</component>
|
||||
</project>
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" project-jdk-name="homebrew-26" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$" />
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
|
|
@ -14,6 +14,26 @@ import io.ktor.server.routing.*
|
|||
import org.mindrot.jbcrypt.BCrypt
|
||||
import java.util.UUID
|
||||
|
||||
fun isValidPassword(password: String): Boolean {
|
||||
if (password.length < 8) return false
|
||||
|
||||
val hasUppercase = password.any { it.isUpperCase() }
|
||||
val hasEmoji =
|
||||
password.any { char ->
|
||||
val type = Character.getType(char).toByte()
|
||||
type == Character.SURROGATE ||
|
||||
type == Character.OTHER_SYMBOL ||
|
||||
char.code in 0x1F600..0x1F64F ||
|
||||
char.code in 0x1F300..0x1F5FF ||
|
||||
char.code in 0x1F680..0x1F6FF ||
|
||||
char.code in 0x2600..0x26FF
|
||||
}
|
||||
|
||||
val hasSpecialChar = password.any { !it.isLetterOrDigit() && !hasEmoji }
|
||||
|
||||
return hasUppercase && hasSpecialChar && !hasEmoji
|
||||
}
|
||||
|
||||
fun Application.configureRouting(
|
||||
repository: KidioRepository,
|
||||
jwtService: JwtService,
|
||||
|
|
@ -27,6 +47,14 @@ fun Application.configureRouting(
|
|||
call.respond(HttpStatusCode.BadRequest, "Bitte füllen Sie alle Felder aus")
|
||||
return@post
|
||||
}
|
||||
if (!isValidPassword(registerRequest.passwordPlain)) {
|
||||
call.respond(
|
||||
HttpStatusCode.BadRequest,
|
||||
"Das Passwort muss mindestens 8 Zeichen lang sein, " +
|
||||
"mindestens einen Großbuchstaben und ein Sonderzeichen enthalten.",
|
||||
)
|
||||
return@post
|
||||
}
|
||||
if (registerRequest.parentPin.length != 4) {
|
||||
call.respond(HttpStatusCode.BadRequest, "Die Eltern-PIN muss genau 4 Ziffern lang sein")
|
||||
return@post
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ class ServerTest {
|
|||
setBody(
|
||||
"""{
|
||||
"email": "test@family.de",
|
||||
"passwordPlain": "strengGeheim1",
|
||||
"passwordPlain": "StrengGeheim1!",
|
||||
"familyName": "Familie Schmidt",
|
||||
"childAge": 8,
|
||||
"parentPin": "4321"
|
||||
|
|
@ -129,7 +129,7 @@ class ServerTest {
|
|||
setBody(
|
||||
"""{
|
||||
"email": "test@family.de",
|
||||
"passwordPlain": "strengGeheim1"
|
||||
"passwordPlain": "StrengGeheim1!"
|
||||
}""",
|
||||
)
|
||||
}
|
||||
|
|
@ -139,6 +139,50 @@ class ServerTest {
|
|||
assertEquals("Familie Schmidt", loginJson.familyName)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test registration rejects invalid passwords`() =
|
||||
testApplication {
|
||||
val jwtService = JwtService()
|
||||
val repository = InMemoryKidioRepository()
|
||||
|
||||
application {
|
||||
install(ServerContentNegotiation) {
|
||||
json()
|
||||
}
|
||||
configureSecurity(jwtService)
|
||||
configureRouting(repository, jwtService)
|
||||
}
|
||||
|
||||
val invalidPasswords =
|
||||
listOf(
|
||||
"Kurz1!",
|
||||
"keingrossbuch1!",
|
||||
"KeinSonder12",
|
||||
"Passwort123!😊",
|
||||
)
|
||||
|
||||
for (password in invalidPasswords) {
|
||||
val response =
|
||||
client.post("/api/v1/auth/register") {
|
||||
header(HttpHeaders.ContentType, ContentType.Application.Json.toString())
|
||||
setBody(
|
||||
"""{
|
||||
"email": "test_${System.currentTimeMillis()}@family.de",
|
||||
"passwordPlain": "$password",
|
||||
"familyName": "Familie Schmidt",
|
||||
"childAge": 8,
|
||||
"parentPin": "4321"
|
||||
}""",
|
||||
)
|
||||
}
|
||||
assertEquals(
|
||||
HttpStatusCode.BadRequest,
|
||||
response.status,
|
||||
"Passwort '$password' hätte abgelehnt werden müssen!",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test tasks endpoint and verify with jwt`() =
|
||||
testApplication {
|
||||
|
|
|
|||
Loading…
Reference in a new issue