From 46852a9b5a1f32e8a0c0953019551c9bd3312232 Mon Sep 17 00:00:00 2001 From: Fawkes100 Date: Sat, 18 Jan 2025 20:46:05 +0100 Subject: [PATCH] Implement Login API --- app/build.gradle.kts | 4 + app/src/main/AndroidManifest.xml | 2 +- .../stormtales/notevault/MainActivity.java | 37 ++++++--- .../notevault/data/model/LoggedInUser.java | 23 ++++++ .../notevault/network/APICallback.java | 6 ++ .../notevault/network/NetworkModule.java | 36 +++++++++ .../notevault/network/auth/AuthAPI.java | 16 ++++ .../network/auth/AuthInterceptor.java | 29 +++++++ .../notevault/network/auth/AuthService.java | 81 +++++++++++++++++++ .../notevault/network/auth/LoginRequest.java | 11 +++ .../notevault/network/auth/LoginResponse.java | 22 +++++ .../notevault/network/auth/TokenManager.java | 31 +++++++ app/src/main/res/drawable/login.xml | 9 +++ app/src/main/res/drawable/logout.xml | 9 +++ app/src/main/res/layout/fragment_login.xml | 79 ++++++++++++++++++ app/src/main/res/menu/main.xml | 8 +- app/src/main/res/values/dimens.xml | 3 + app/src/main/res/values/strings.xml | 10 +++ gradle/libs.versions.toml | 2 + 19 files changed, 404 insertions(+), 14 deletions(-) create mode 100644 app/src/main/java/com/stormtales/notevault/data/model/LoggedInUser.java create mode 100644 app/src/main/java/com/stormtales/notevault/network/APICallback.java create mode 100644 app/src/main/java/com/stormtales/notevault/network/NetworkModule.java create mode 100644 app/src/main/java/com/stormtales/notevault/network/auth/AuthAPI.java create mode 100644 app/src/main/java/com/stormtales/notevault/network/auth/AuthInterceptor.java create mode 100644 app/src/main/java/com/stormtales/notevault/network/auth/AuthService.java create mode 100644 app/src/main/java/com/stormtales/notevault/network/auth/LoginRequest.java create mode 100644 app/src/main/java/com/stormtales/notevault/network/auth/LoginResponse.java create mode 100644 app/src/main/java/com/stormtales/notevault/network/auth/TokenManager.java create mode 100644 app/src/main/res/drawable/login.xml create mode 100644 app/src/main/res/drawable/logout.xml create mode 100644 app/src/main/res/layout/fragment_login.xml diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 6dfbb44..12b800a 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -41,9 +41,13 @@ dependencies { implementation(libs.navigation.fragment) implementation(libs.navigation.ui) implementation(libs.room.runtime) + implementation(libs.annotation) testImplementation(libs.junit) androidTestImplementation(libs.ext.junit) androidTestImplementation(libs.espresso.core) annotationProcessor(libs.room.compiler) implementation("com.github.chrisbanes:PhotoView:2.3.0") + implementation("com.squareup.retrofit2:retrofit:2.9.0") + implementation("com.squareup.retrofit2:converter-gson:2.9.0") + implementation("com.squareup.okhttp3:logging-interceptor:4.9.1") } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 8fc0a28..9abf83c 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,7 +1,7 @@ - + { + if (item.getItemId() == R.id.auth_action) { + if (new AuthService(getApplicationContext()).isLoggedIn()) { + //performLogout(); // Logout-Logik aufrufen + } else { + showLoginDialog(); // Zeige das Login-Fenster an + } + return true; } - });*/ + return false; + }); DrawerLayout drawer = binding.drawerLayout; NavigationView navigationView = binding.navView; // Passing each menu ID as a set of Ids because each @@ -60,4 +63,20 @@ public class MainActivity extends AppCompatActivity { return NavigationUI.navigateUp(navController, mAppBarConfiguration) || super.onSupportNavigateUp(); } + + @Override + public boolean onPrepareOptionsMenu(Menu menu) { + MenuItem loginItem = menu.findItem(R.id.auth_action); + if (new AuthService(this).isLoggedIn()) { + loginItem.setIcon(R.drawable.logout); // Setze das Logout-Symbol + } else { + loginItem.setIcon(R.drawable.login); // Setze das Login-Symbol + } + return super.onPrepareOptionsMenu(menu); + } + + public void showLoginDialog() { + /*LoginFragment loginFragment = new LoginFragment(); + loginFragment.show(getSupportFragmentManager(), "login");*/ + } } \ No newline at end of file diff --git a/app/src/main/java/com/stormtales/notevault/data/model/LoggedInUser.java b/app/src/main/java/com/stormtales/notevault/data/model/LoggedInUser.java new file mode 100644 index 0000000..d2b5be7 --- /dev/null +++ b/app/src/main/java/com/stormtales/notevault/data/model/LoggedInUser.java @@ -0,0 +1,23 @@ +package com.stormtales.notevault.data.model; + +/** + * Data class that captures user information for logged in users retrieved from LoginRepository + */ +public class LoggedInUser { + + private String userId; + private String displayName; + + public LoggedInUser(String userId, String displayName) { + this.userId = userId; + this.displayName = displayName; + } + + public String getUserId() { + return userId; + } + + public String getDisplayName() { + return displayName; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/stormtales/notevault/network/APICallback.java b/app/src/main/java/com/stormtales/notevault/network/APICallback.java new file mode 100644 index 0000000..840c89f --- /dev/null +++ b/app/src/main/java/com/stormtales/notevault/network/APICallback.java @@ -0,0 +1,6 @@ +package com.stormtales.notevault.network; + +public interface APICallback { + void onSuccess(); + void onError(String error); +} diff --git a/app/src/main/java/com/stormtales/notevault/network/NetworkModule.java b/app/src/main/java/com/stormtales/notevault/network/NetworkModule.java new file mode 100644 index 0000000..10b3bc1 --- /dev/null +++ b/app/src/main/java/com/stormtales/notevault/network/NetworkModule.java @@ -0,0 +1,36 @@ +package com.stormtales.notevault.network; + +import android.content.Context; +import android.content.SharedPreferences; +import com.stormtales.notevault.network.auth.AuthInterceptor; +import com.stormtales.notevault.network.auth.TokenManager; +import okhttp3.OkHttpClient; +import okhttp3.logging.HttpLoggingInterceptor; +import retrofit2.Retrofit; +import retrofit2.converter.gson.GsonConverterFactory; + +public class NetworkModule { + private static final String BASE_URL = "https://192.168.178.30:8000/"; + private static Retrofit retrofit; + + public static Retrofit getRetrofitInstance(Context context) { + if (retrofit == null) { + HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(); + loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY); + + TokenManager tokenManager = new TokenManager(context); + OkHttpClient client = new OkHttpClient.Builder() + .addInterceptor(new AuthInterceptor(tokenManager)) + .addInterceptor(loggingInterceptor) + .build(); + + retrofit = new Retrofit.Builder() + .baseUrl("http://192.168.178.30:8000/") + .client(client) + .addConverterFactory(GsonConverterFactory.create()) + .build(); + } + return retrofit; + } + +} diff --git a/app/src/main/java/com/stormtales/notevault/network/auth/AuthAPI.java b/app/src/main/java/com/stormtales/notevault/network/auth/AuthAPI.java new file mode 100644 index 0000000..c50a55d --- /dev/null +++ b/app/src/main/java/com/stormtales/notevault/network/auth/AuthAPI.java @@ -0,0 +1,16 @@ +package com.stormtales.notevault.network.auth; + +import retrofit2.Call; +import retrofit2.http.Body; +import retrofit2.http.Headers; +import retrofit2.http.POST; + +public interface AuthAPI { + + @POST("/login/") + Call login(@Body LoginRequest loginRequest); + + /*@POST("/register/") + @Headers("Content-Type: application/json") + Call registration(@Body RegisterRequest registerRequest);*/ +} diff --git a/app/src/main/java/com/stormtales/notevault/network/auth/AuthInterceptor.java b/app/src/main/java/com/stormtales/notevault/network/auth/AuthInterceptor.java new file mode 100644 index 0000000..ba73477 --- /dev/null +++ b/app/src/main/java/com/stormtales/notevault/network/auth/AuthInterceptor.java @@ -0,0 +1,29 @@ +package com.stormtales.notevault.network.auth; + +import okhttp3.Interceptor; +import okhttp3.Request; +import okhttp3.Response; + +import java.io.IOException; + +public class AuthInterceptor implements Interceptor { + private TokenManager tokenManager; + + public AuthInterceptor(TokenManager tokenManager) { + this.tokenManager = tokenManager; + } + + @Override + public Response intercept(Chain chain) throws IOException { + Request originalRequest = chain.request(); + + String token = tokenManager.getToken(); + if (token == null) { + return chain.proceed(originalRequest); + } + + Request authenticatedRequest = originalRequest.newBuilder() + .header("Authorization", "Bearer " + token).build(); + return chain.proceed(authenticatedRequest); + } +} diff --git a/app/src/main/java/com/stormtales/notevault/network/auth/AuthService.java b/app/src/main/java/com/stormtales/notevault/network/auth/AuthService.java new file mode 100644 index 0000000..6260828 --- /dev/null +++ b/app/src/main/java/com/stormtales/notevault/network/auth/AuthService.java @@ -0,0 +1,81 @@ +package com.stormtales.notevault.network.auth; + +import android.content.Context; +import android.text.TextUtils; +import com.stormtales.notevault.network.APICallback; +import com.stormtales.notevault.network.NetworkModule; +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; + +public class AuthService { + + private final AuthAPI authAPI; + private final TokenManager tokenManager; + + public AuthService(Context context) { + this.authAPI = NetworkModule.getRetrofitInstance(context).create(AuthAPI.class); + this.tokenManager = new TokenManager(context); + } + + public void performLogin(String email, String password, APICallback callback) { + LoginRequest loginRequest = new LoginRequest(email, password); + + authAPI.login(loginRequest).enqueue(new Callback() { + @Override + public void onResponse(Call call, Response response) { + if (response.isSuccessful() && response.body() != null) { + String token = response.body().getToken(); + saveToken(token); + // Erfolgsrückmeldung an den Callback senden + callback.onSuccess(); + } else { + // Fehlermeldung an den Callback senden + callback.onError("Login fehlgeschlagen. Überprüfe Benutzername und Passwort."); + } + } + + @Override + public void onFailure(Call call, Throwable t) { + // Netzwerkfehler an den Callback senden + callback.onError("Netzwerkfehler: " + t.getMessage()); + } + }); + } + + public void performRegistration(String email, String username, String password, APICallback callback) { + /*RegisterRequest registerRequest = new RegisterRequest(username, password, email); + authService.registration(registerRequest).enqueue(new Callback() { + + @Override + public void onResponse(Call call, Response response) { + if(response.isSuccessful() && response.body() != null) { + callback.onSuccess(); + } else { + callback.onError("Registration fehlgeschlagen. Überprüfe Benutzername und Passwort."); + } + } + + @Override + public void onFailure(Call call, Throwable throwable) { + callback.onError("Netzwerkfehler: " + throwable.getMessage()); + } + });*/ + } + + private void saveToken(String token) { + tokenManager.saveToken(token); + } + + public String getToken() { + return tokenManager.getToken(); + } + + public void logout() { + tokenManager.clearToken(); + } + + public boolean isLoggedIn() { + return !TextUtils.isEmpty(tokenManager.getToken()); + } +} diff --git a/app/src/main/java/com/stormtales/notevault/network/auth/LoginRequest.java b/app/src/main/java/com/stormtales/notevault/network/auth/LoginRequest.java new file mode 100644 index 0000000..ef2f887 --- /dev/null +++ b/app/src/main/java/com/stormtales/notevault/network/auth/LoginRequest.java @@ -0,0 +1,11 @@ +package com.stormtales.notevault.network.auth; + +public class LoginRequest { + private String email; + private String password; + + public LoginRequest(String email, String password) { + this.email = email; + this.password = password; + } +} diff --git a/app/src/main/java/com/stormtales/notevault/network/auth/LoginResponse.java b/app/src/main/java/com/stormtales/notevault/network/auth/LoginResponse.java new file mode 100644 index 0000000..3d4be92 --- /dev/null +++ b/app/src/main/java/com/stormtales/notevault/network/auth/LoginResponse.java @@ -0,0 +1,22 @@ +package com.stormtales.notevault.network.auth; + +public class LoginResponse { + private String token; + private String username; + + public String getToken() { + return token; + } + + public void setToken(String token) { + this.token = token; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } +} diff --git a/app/src/main/java/com/stormtales/notevault/network/auth/TokenManager.java b/app/src/main/java/com/stormtales/notevault/network/auth/TokenManager.java new file mode 100644 index 0000000..9d26548 --- /dev/null +++ b/app/src/main/java/com/stormtales/notevault/network/auth/TokenManager.java @@ -0,0 +1,31 @@ +package com.stormtales.notevault.network.auth; + +import android.content.Context; +import android.content.SharedPreferences; + +public class TokenManager { + private static final String PREF_NAME = "app_preferences"; + private static final String KEY_TOKEN = "jwt_token"; + + private SharedPreferences sharedPreferences; + + public TokenManager(Context context) { + sharedPreferences = context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE); + } + + public void saveToken(String token) { + SharedPreferences.Editor editor = sharedPreferences.edit(); + editor.putString(KEY_TOKEN, token); + editor.apply(); + } + + public String getToken() { + return sharedPreferences.getString(KEY_TOKEN, null); + } + + public void clearToken() { + SharedPreferences.Editor editor = sharedPreferences.edit(); + editor.remove(KEY_TOKEN); + editor.apply(); + } +} diff --git a/app/src/main/res/drawable/login.xml b/app/src/main/res/drawable/login.xml new file mode 100644 index 0000000..2e5aa22 --- /dev/null +++ b/app/src/main/res/drawable/login.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/logout.xml b/app/src/main/res/drawable/logout.xml new file mode 100644 index 0000000..d1d6253 --- /dev/null +++ b/app/src/main/res/drawable/logout.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/layout/fragment_login.xml b/app/src/main/res/layout/fragment_login.xml new file mode 100644 index 0000000..5b07473 --- /dev/null +++ b/app/src/main/res/layout/fragment_login.xml @@ -0,0 +1,79 @@ + + + + + + + +