From bba419bff0fdd2a37f88ab6dd1845ebebedc70ad Mon Sep 17 00:00:00 2001 From: "leni.beaulaton" Date: Wed, 26 Feb 2025 18:26:35 +0100 Subject: [PATCH] La page d'inscription fonctionne --- .../data/services/IServices.kt | 2 +- .../data/services/ServicesAPI.kt | 2 +- .../data/services/ServicesStub.kt | 30 +++- .../ui/components/hashPassword.kt | 14 ++ .../what_the_fantasy/ui/screens/LoginPage.kt | 13 +- .../what_the_fantasy/ui/screens/SignUpPage.kt | 131 +++++++++++++----- .../app/src/main/res/values-fr/strings.xml | 5 + .../app/src/main/res/values/strings.xml | 5 + 8 files changed, 152 insertions(+), 50 deletions(-) create mode 100644 What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/components/hashPassword.kt diff --git a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/data/services/IServices.kt b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/data/services/IServices.kt index df15ebd..2b8febf 100644 --- a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/data/services/IServices.kt +++ b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/data/services/IServices.kt @@ -6,7 +6,7 @@ interface IServices { fun EditPasswd(passwd : String, passwdValid : String) fun EditImage(imageURL : String) - fun CreateUser(username : String, email : String, passwd : String, imageURL: String) + fun CreateUser(username : String, email : String, passwd : String, imageURL: String) : Boolean fun getFavorite(username: String) fun SearchQuote(quote : String) diff --git a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/data/services/ServicesAPI.kt b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/data/services/ServicesAPI.kt index 9743f68..fdbcb49 100644 --- a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/data/services/ServicesAPI.kt +++ b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/data/services/ServicesAPI.kt @@ -17,7 +17,7 @@ class ServicesAPI : IServices { TODO("Not yet implemented") } - override fun CreateUser(username: String, email: String, passwd: String, imageURL: String) { + override fun CreateUser(username: String, email: String, passwd: String, imageURL: String) : Boolean { TODO("Not yet implemented") } diff --git a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/data/services/ServicesStub.kt b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/data/services/ServicesStub.kt index 8c84176..dc4519f 100644 --- a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/data/services/ServicesStub.kt +++ b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/data/services/ServicesStub.kt @@ -1,5 +1,12 @@ package com.example.what_the_fantasy.data.services +import android.annotation.SuppressLint +import android.util.Log +import com.example.what_the_fantasy.data.local.UserStub +import com.example.what_the_fantasy.data.model.User +import com.example.what_the_fantasy.ui.components.hashPassword +import java.time.LocalDate + class ServicesStub : IServices { override fun EditUsername(username: String) { TODO("Not yet implemented") @@ -17,10 +24,29 @@ class ServicesStub : IServices { TODO("Not yet implemented") } - override fun CreateUser(username: String, email: String, passwd: String, imageURL: String) { - TODO("Not yet implemented") + override fun CreateUser(username: String, email: String, passwd: String, imageURL: String) : Boolean { + val date =dateDuJour() + val passwordhash = hashPassword(passwd) + + //Check si user existe déjà + val users = UserStub.allUsers + for (user in users) { + if (user.username == username) { + return false + } + } + val user = User(100,username, email, imageURL, date, passwordhash) + //A ajouter au stub + Log.e("CreateUser", "User created: ${user.username} => ${user.password}") + return true + } + @SuppressLint("NewApi") + fun dateDuJour(): String { + val date = LocalDate.now() + return date.toString() + } override fun SearchQuote(quote: String) { TODO("Not yet implemented") } diff --git a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/components/hashPassword.kt b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/components/hashPassword.kt new file mode 100644 index 0000000..2f46a9d --- /dev/null +++ b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/components/hashPassword.kt @@ -0,0 +1,14 @@ +package com.example.what_the_fantasy.ui.components + +import java.security.MessageDigest + +fun hashPassword(password: String): String { + // SHA-256 + val digest = MessageDigest.getInstance("SHA-256") + + // Convertir mdp en bytes et appliquer le hash + val hashedBytes = digest.digest(password.toByteArray()) + + // Convertir le tableau de bytes en une chaîne hexadécimale + return hashedBytes.joinToString("") { "%02x".format(it) } +} \ No newline at end of file diff --git a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/LoginPage.kt b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/LoginPage.kt index 47309cc..9aec7bd 100644 --- a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/LoginPage.kt +++ b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/LoginPage.kt @@ -41,6 +41,7 @@ import com.example.what_the_fantasy.data.local.UserStub import com.example.what_the_fantasy.data.model.User import com.example.what_the_fantasy.ui.components.SpaceHeightComponent import com.example.what_the_fantasy.ui.components.TitlePageComponent +import com.example.what_the_fantasy.ui.components.hashPassword import com.example.what_the_fantasy.ui.theme.colorBackground import com.example.what_the_fantasy.ui.theme.gradienBox import java.security.MessageDigest @@ -148,18 +149,6 @@ fun validLogin(identifiant : String, passwd : String, users : List, navCon } } -fun hashPassword(password: String): String { - // SHA-256 - val digest = MessageDigest.getInstance("SHA-256") - - // Convertir mdp en bytes et appliquer le hash - val hashedBytes = digest.digest(password.toByteArray()) - - // Convertir le tableau de bytes en une chaîne hexadécimale - return hashedBytes.joinToString("") { "%02x".format(it) } -} - - @Composable fun CreateAccountButton(titleResId : Int, size : Int, color : Color, navController: () -> Unit){ val title = stringResource(id = titleResId) diff --git a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/SignUpPage.kt b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/SignUpPage.kt index 3e77782..d344889 100644 --- a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/SignUpPage.kt +++ b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/SignUpPage.kt @@ -15,8 +15,11 @@ import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Check import androidx.compose.material3.Button import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.Text @@ -45,10 +48,17 @@ import com.example.what_the_fantasy.ui.components.TitlePageComponent import com.example.what_the_fantasy.ui.theme.What_The_FantasyTheme import com.example.what_the_fantasy.ui.theme.colorBackground import com.example.what_the_fantasy.ui.theme.gradienBox +import com.example.what_the_fantasy.data.services.ServicesStub +import com.example.what_the_fantasy.ui.components.ErrorMessageProfileComponent @Composable fun SignUpPage(navController: NavController) { - + var username by remember { mutableStateOf("") } + var email by remember { mutableStateOf("") } + var password by remember { mutableStateOf("") } + var confirmPassword by remember { mutableStateOf("") } + var passwordVisible by remember { mutableStateOf(false) } + val servicesStub = ServicesStub() Box( modifier = Modifier @@ -67,14 +77,14 @@ fun SignUpPage(navController: NavController) { ) { TitlePageComponent(R.string.titleSignUp, 20,Color.White) - IdentifiantTextFieldSign(R.string.IdentifiantLogin) - EmailTextFieldSign("Email*") - PassWdTextFieldSign(R.string.PasswdLogin) - PassWdConfirmTextFieldSign(R.string.ConfirmPassWdSignUp) + IdentifiantTextFieldSign(R.string.IdentifiantLogin,identifiant = username,onValueChange = { username = it }) + EmailTextFieldSign(R.string.EmailSignUp, email, onValueChange = { email = it }) + PassWdTextFieldSign(R.string.PasswdLogin,password, onValueChange = { password = it },passwordVisible,onPasswordVisibilityChange = { passwordVisible = !passwordVisible }) + PassWdConfirmTextFieldSign(R.string.ConfirmPassWdSignUp,confirmPassword,onValueChange = { confirmPassword = it },passwordVisible,onPasswordVisibilityChange = { passwordVisible = !passwordVisible }) SpaceHeightComponent(16) - ConnexionButtonSign(R.string.ButtonSignUp,18, Color.White, Color.Black) + ConnexionButtonSign(R.string.ButtonSignUp,18, Color.White, Color.Black, username, email, password, confirmPassword, servicesStub, navController = navController) SpaceHeightComponent(16) - CreateAccountButtonSign(R.string.ButtonLogin,12, Color.White, navController = navController) + ReturnLogin(R.string.ButtonLogin,12, Color.White, navController = navController) } } @@ -84,50 +94,47 @@ fun SignUpPage(navController: NavController) { @Composable -fun IdentifiantTextFieldSign(textIdentifiantResId : Int){ +fun IdentifiantTextFieldSign(textIdentifiantResId : Int, identifiant: String, onValueChange: (String) -> Unit){ val textIdentifiant = stringResource(id = textIdentifiantResId) - var identifiant by remember { mutableStateOf("") } // Stocke la valeur du champ Column(modifier = Modifier.padding(top = 16.dp)) { OutlinedTextField( value = identifiant, - onValueChange = { identifiant = it }, + onValueChange = onValueChange, label = { Text(textIdentifiant) }, modifier = Modifier .fillMaxWidth() .padding(top = 8.dp), keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Text), - shape = RoundedCornerShape(16.dp) // 🔹 Bords arrondis + shape = RoundedCornerShape(16.dp) ) } } @Composable -fun EmailTextFieldSign(textIdentifiant : String){ - var identifiant by remember { mutableStateOf("") } // Stocke la valeur du champ +fun EmailTextFieldSign(textIdentifiantResId: Int, email: String, onValueChange: (String) -> Unit){ + val textIdentifiant = stringResource(id = textIdentifiantResId) Column(modifier = Modifier.padding(top = 16.dp)) { OutlinedTextField( - value = identifiant, - onValueChange = { identifiant = it }, + value = email, + onValueChange = onValueChange, label = { Text(textIdentifiant) }, modifier = Modifier .fillMaxWidth() .padding(top = 8.dp), keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Email), - shape = RoundedCornerShape(16.dp) // Bords arrondis + shape = RoundedCornerShape(16.dp) ) } } @Composable -fun PassWdTextFieldSign(textpasswdResId : Int){ +fun PassWdTextFieldSign(textpasswdResId : Int, passwd: String, onValueChange: (String) -> Unit, passwordVisible: Boolean, onPasswordVisibilityChange: () -> Unit){ val textpasswd = stringResource(id = textpasswdResId) - var passwd by remember { mutableStateOf("") } // Stocke la valeur du champ - var passwordVisible by remember { mutableStateOf(false) } // État pour afficher/masquer Column(modifier = Modifier.padding(top = 10.dp)) { OutlinedTextField( value = passwd, - onValueChange = { passwd = it }, + onValueChange = onValueChange, label = { Text(textpasswd) }, modifier = Modifier .fillMaxWidth() @@ -135,23 +142,22 @@ fun PassWdTextFieldSign(textpasswdResId : Int){ keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password), visualTransformation = if (passwordVisible) VisualTransformation.None else PasswordVisualTransformation(), trailingIcon = { - IconButton(onClick = { passwordVisible = !passwordVisible }) { + IconButton(onClick = onPasswordVisibilityChange) { + Icon(imageVector = Icons.Default.Check, contentDescription = "Valider") } }, - shape = RoundedCornerShape(16.dp) // 🔹 Bords arrondis + shape = RoundedCornerShape(16.dp) ) } } @Composable -fun PassWdConfirmTextFieldSign(textpasswdResId : Int){ +fun PassWdConfirmTextFieldSign(textpasswdResId : Int,confirmPassword: String, onValueChange: (String) -> Unit, passwordVisible: Boolean, onPasswordVisibilityChange: () -> Unit){ val textpasswd = stringResource(id = textpasswdResId) - var passwd by remember { mutableStateOf("") } // Stocke la valeur du champ - var passwordVisible by remember { mutableStateOf(false) } // État pour afficher/masquer Column(modifier = Modifier.padding(top = 10.dp)) { OutlinedTextField( - value = passwd, - onValueChange = { passwd = it }, + value = confirmPassword, + onValueChange = onValueChange, label = { Text(textpasswd) }, modifier = Modifier .fillMaxWidth() @@ -159,31 +165,88 @@ fun PassWdConfirmTextFieldSign(textpasswdResId : Int){ keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password), visualTransformation = if (passwordVisible) VisualTransformation.None else PasswordVisualTransformation(), trailingIcon = { - IconButton(onClick = { passwordVisible = !passwordVisible }) { + IconButton(onClick = onPasswordVisibilityChange) { + Icon(imageVector = Icons.Default.Check, contentDescription = "Valider") } }, - shape = RoundedCornerShape(16.dp) // 🔹 Bords arrondis + shape = RoundedCornerShape(16.dp) ) } } +// Validation de email +fun isValidEmail(email: String): Boolean { + val emailRegex = "[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,6}" + return email.matches(emailRegex.toRegex()) +} + +// Vérification mots de passe +fun arePasswordsMatching(password: String, confirmPassword: String): Boolean { + return password == confirmPassword +} @Composable -fun ConnexionButtonSign(titleResId : Int, size : Int, colorButton : Color, colorText : Color){ +fun ConnexionButtonSign( + titleResId: Int, + size: Int, + colorButton: Color, + colorText: Color, + username: String, + email: String, + password: String, + confirmPassword: String, + service: ServicesStub, + navController: NavController +) { val title = stringResource(id = titleResId) + var emailError by remember { mutableStateOf(false) } + var passwordError by remember { mutableStateOf(false) } + var usernameErrorEmpty by remember { mutableStateOf(false) } + var usernameErrorExist by remember { mutableStateOf(false) } + + Button( - onClick = { /* Action */ }, + onClick = { + emailError = !isValidEmail(email) + + passwordError = !arePasswordsMatching(password, confirmPassword) + + usernameErrorEmpty = username.isBlank() + + if (!emailError && !passwordError && !usernameErrorEmpty) { + usernameErrorExist = !service.CreateUser(username, email, password, "https://img.freepik.com/vecteurs-libre/personnage-magicien-malefique-fantaisie_1045-193.jpg?size=338&ext=jpg") + } + }, colors = ButtonDefaults.buttonColors(containerColor = colorButton), - modifier = Modifier - .fillMaxWidth(), + modifier = Modifier.fillMaxWidth(), ) { Text(title, fontSize = size.sp, color = colorText) } + + // Afficher erreurs + if (usernameErrorEmpty) { + ErrorMessageProfileComponent(R.string.ErrorUserEmptySignUp) + } + + if (usernameErrorExist) { + ErrorMessageProfileComponent(R.string.ErrorUserExistSignUp) + } + + if (emailError) { + ErrorMessageProfileComponent(R.string.ErrorEmailSignUp) + + } + if (passwordError) { + ErrorMessageProfileComponent(R.string.ErrorPasswordSignUp) + } + } + + @Composable -fun CreateAccountButtonSign(titleResId: Int, size: Int, color: Color, navController: NavController) { +fun ReturnLogin(titleResId: Int, size: Int, color: Color, navController: NavController) { val title = stringResource(id = titleResId) Text( text = title, diff --git a/What_The_Fantasy/app/src/main/res/values-fr/strings.xml b/What_The_Fantasy/app/src/main/res/values-fr/strings.xml index 9d55b61..899a998 100644 --- a/What_The_Fantasy/app/src/main/res/values-fr/strings.xml +++ b/What_The_Fantasy/app/src/main/res/values-fr/strings.xml @@ -16,6 +16,11 @@ Inscription Confirmer mot de passe* S\'inscrire + Email* + Email invalide + Les mots de passe ne correspondent pas + Le nom d\'utilisateur ne peut pas être vide + Le nom d\'utilisateur n\'est pas disponible //Page Profil Profil diff --git a/What_The_Fantasy/app/src/main/res/values/strings.xml b/What_The_Fantasy/app/src/main/res/values/strings.xml index c9ab3e1..4e02f70 100644 --- a/What_The_Fantasy/app/src/main/res/values/strings.xml +++ b/What_The_Fantasy/app/src/main/res/values/strings.xml @@ -15,6 +15,11 @@ Account creation Confirm your password* Create + Your email* + Invalid email + Passwords do not match + Username cannot be empty + Username is not available //Page Profil Profile