diff --git a/android-client/app/build.gradle b/android-client/app/build.gradle index 4bdcf72d..89b315a8 100644 --- a/android-client/app/build.gradle +++ b/android-client/app/build.gradle @@ -22,8 +22,8 @@ android { } } compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 + sourceCompatibility JavaVersion.VERSION_1_9 + targetCompatibility JavaVersion.VERSION_1_9 } buildFeatures { viewBinding true @@ -31,13 +31,15 @@ android { } dependencies { - implementation 'androidx.appcompat:appcompat:1.4.2' implementation 'com.google.android.material:material:1.6.1' implementation 'androidx.constraintlayout:constraintlayout:2.1.4' implementation 'androidx.navigation:navigation-fragment:2.4.2' implementation 'androidx.navigation:navigation-ui:2.4.2' implementation 'androidx.preference:preference:1.2.0' + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.squareup.retrofit2:converter-gson:2.6.1' + implementation 'com.google.code.gson:gson:2.9.0' implementation 'androidx.room:room-common:2.4.2' implementation 'androidx.room:room-runtime:2.4.2' implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0' diff --git a/android-client/app/src/main/AndroidManifest.xml b/android-client/app/src/main/AndroidManifest.xml index e92f9d3b..56fb3eee 100644 --- a/android-client/app/src/main/AndroidManifest.xml +++ b/android-client/app/src/main/AndroidManifest.xml @@ -15,7 +15,9 @@ android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.MaKore" - tools:targetApi="31"> + tools:targetApi="31" + android:usesCleartextTraffic="true" + > > signin(String username, String password) { + return userServiceAPI.signin(Map.of("username", username, "password", password)); + } + + public Call signup(String username, String password, String name) { + return userServiceAPI.signup(Map.of("username", username, "password", password, "name", name)); + } +} diff --git a/android-client/app/src/main/java/com/example/makore/api/UserServiceAPI.java b/android-client/app/src/main/java/com/example/makore/api/UserServiceAPI.java new file mode 100644 index 00000000..4176e07a --- /dev/null +++ b/android-client/app/src/main/java/com/example/makore/api/UserServiceAPI.java @@ -0,0 +1,15 @@ +package com.example.makore.api; + +import java.util.Map; + +import retrofit2.Call; +import retrofit2.http.Body; +import retrofit2.http.POST; + +public interface UserServiceAPI { + @POST("/api/contacts/signin") + Call> signin(@Body Map user); + + @POST("/api/contacts/signup") + Call signup(@Body Map user); +} diff --git a/android-client/app/src/main/java/com/example/makore/auth/SignInActivity.java b/android-client/app/src/main/java/com/example/makore/auth/SignInActivity.java index 8b823dc2..14991657 100644 --- a/android-client/app/src/main/java/com/example/makore/auth/SignInActivity.java +++ b/android-client/app/src/main/java/com/example/makore/auth/SignInActivity.java @@ -4,11 +4,19 @@ import android.content.SharedPreferences; import android.os.Bundle; +import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import com.example.makore.MainActivity; +import com.example.makore.api.UserAPI; import com.example.makore.databinding.ActivitySignInBinding; +import java.util.Map; + +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; + public class SignInActivity extends AppCompatActivity { private ActivitySignInBinding binding; @@ -38,19 +46,33 @@ protected void onCreate(Bundle savedInstanceState) { // Show error message binding.editTextPassword.setError("Password is empty"); } else { - // Check if the username and password is correct - if (username.equals("admin") && password.equals("admin")) { - // Save the username in the SharedPreferences - SharedPreferences.Editor editor = sharedpreferences.edit(); - editor.putString("username", username); - editor.apply(); - // Go to the main screen - Intent intent = new Intent(SignInActivity.this, MainActivity.class); - startActivity(intent); - } else { - // Show error message - binding.editTextUsername.setError("One of the fields is invalid"); - } + UserAPI userAPI = new UserAPI(); + Call> call = userAPI.signin(username, password); + call.enqueue(new Callback<>() { + @Override + public void onResponse(@NonNull Call> call, @NonNull Response> response) { + boolean success = response.isSuccessful(); + if (success) { + // Save username and password to shared preferences + SharedPreferences.Editor editor = sharedpreferences.edit(); + editor.putString("username", username); + editor.putString("token", response.body().get("token")); + editor.apply(); + // Go to main activity + Intent intent = new Intent(SignInActivity.this, MainActivity.class); + startActivity(intent); + } else { + // Show error message + binding.editTextUsername.setError("Invalid username or password"); + } + } + + @Override + public void onFailure(@NonNull Call> call, @NonNull Throwable t) { + // Show error message + binding.editTextUsername.setError("Error connecting to server"); + } + }); } }); } diff --git a/android-client/app/src/main/java/com/example/makore/auth/SignUpActivity.java b/android-client/app/src/main/java/com/example/makore/auth/SignUpActivity.java index 10a20b4f..45598ec0 100644 --- a/android-client/app/src/main/java/com/example/makore/auth/SignUpActivity.java +++ b/android-client/app/src/main/java/com/example/makore/auth/SignUpActivity.java @@ -4,11 +4,19 @@ import android.content.SharedPreferences; import android.os.Bundle; +import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import com.example.makore.MainActivity; +import com.example.makore.api.UserAPI; import com.example.makore.databinding.ActivitySignUpBinding; +import java.util.Map; + +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; + public class SignUpActivity extends AppCompatActivity { private ActivitySignUpBinding binding; @@ -71,15 +79,45 @@ protected void onCreate(Bundle savedInstanceState) { } else if (!displayName.matches("^[a-zA-Z '-.,]+$")) { binding.editTextDisplayName.setError("Display name can only contain letters, spaces, hyphens, periods, dots, and commas"); } - // If all the fields are valid, go to the main screen + + UserAPI userAPI = new UserAPI(); if (isValid) { - // Save the username in the SharedPreferences - SharedPreferences.Editor editor = sharedpreferences.edit(); - editor.putString("username", username); - editor.apply(); - // Go to the main screen - Intent intent = new Intent(SignUpActivity.this, MainActivity.class); - startActivity(intent); + Call signunCall = userAPI.signup(username, password, displayName); + signunCall.enqueue(new Callback<>() { + @Override + public void onResponse(@NonNull Call call, @NonNull retrofit2.Response response) { + if (response.isSuccessful()) { + Call> signinCall = userAPI.signin(username, password); + signinCall.enqueue(new Callback<>() { + @Override + public void onResponse(@NonNull Call> call, @NonNull Response> response) { + if (response.isSuccessful()) { + Map body = response.body(); + String token = body.get("token"); + SharedPreferences.Editor editor = sharedpreferences.edit(); + editor.putString("token", token); + editor.putString("username", username); + editor.apply(); + Intent intent = new Intent(SignUpActivity.this, MainActivity.class); + startActivity(intent); + } + } + + @Override + public void onFailure(@NonNull Call> call, @NonNull Throwable t) { + t.printStackTrace(); + } + }); + } else { + binding.editTextUsername.setError("Username already exists"); + } + } + + @Override + public void onFailure(@NonNull Call call, @NonNull Throwable t) { + + } + }); } }); } diff --git a/web-api/Controllers/ContactsController.cs b/web-api/Controllers/ContactsController.cs index 9b2621bc..0df9873d 100644 --- a/web-api/Controllers/ContactsController.cs +++ b/web-api/Controllers/ContactsController.cs @@ -138,12 +138,11 @@ public IActionResult SignUp([FromBody] JsonElement body) { // Sign up new user - string? username, password, confirmPassword, name; + string? username, password, name; try { username = body.GetProperty("username").GetString(); password = body.GetProperty("password").GetString(); - confirmPassword = body.GetProperty("confirmPassword").GetString(); name = body.GetProperty("name").GetString(); } catch (Exception) @@ -151,7 +150,7 @@ public IActionResult SignUp([FromBody] JsonElement body) return BadRequest(); } - if (username == null || password == null || confirmPassword == null || name == null) + if (username == null || password == null || name == null) { return BadRequest(); } @@ -162,11 +161,6 @@ public IActionResult SignUp([FromBody] JsonElement body) return BadRequest(); } - // Ensure passwords match - if (password != confirmPassword) - { - return BadRequest(); - } // Check if password contains at least one number, one lowercase and one uppercase character if (password.Length < 6 || !Regex.IsMatch(password, @"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).+$"))