Implement Login Logic

This commit is contained in:
sebastian 2024-11-03 18:54:53 +01:00
parent 4649d2ffed
commit c49efba57d
14 changed files with 257 additions and 7 deletions

View File

@ -22,6 +22,10 @@ android {
isMinifyEnabled = false
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
}
debug {
// Setzt den Manifest-Platzhalter nur für den Debug-Build auf true
manifestPlaceholders["usesCleartextTraffic"] = "true"
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
@ -48,6 +52,10 @@ dependencies {
testImplementation(libs.junit)
androidTestImplementation(libs.ext.junit)
androidTestImplementation(libs.espresso.core)
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")
val room_version = "2.6.1" // Aktuelle Room-Version

View File

@ -2,6 +2,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
@ -11,6 +12,7 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.NoteVault"
android:usesCleartextTraffic="true"
tools:targetApi="31">
<activity
android:name=".MainActivity"

View File

@ -4,8 +4,10 @@ import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import android.view.Menu;
import android.widget.Toast;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.navigation.fragment.NavHostFragment;
@ -19,10 +21,12 @@ import androidx.drawerlayout.widget.DrawerLayout;
import androidx.appcompat.app.AppCompatActivity;
import core.notevault.data.*;
import core.notevault.databinding.ActivityMainBinding;
import core.notevault.sync.auth.LoginCallback;
import core.notevault.ui.gallery.GalleryFragment;
import core.notevault.ui.gallery.detail.ConcertSongSelector;
import core.notevault.ui.gallery.editor.ConcertEditorDialog;
import core.notevault.ui.home.HomeFragment;
import core.notevault.ui.login.LoginDialogFragment;
import core.notevault.ui.metadatadialog.MetaDataDialog;
import core.notevault.util.NoteSheetsUtil;
@ -70,6 +74,21 @@ public class MainActivity extends AppCompatActivity implements MetaDataDialog.On
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if(id == R.id.action_login) {
openLoginDialog();
return true;
}
return super.onOptionsItemSelected(item);
}
private void openLoginDialog() {
LoginDialogFragment loginDialogFragment = new LoginDialogFragment();
loginDialogFragment.show(getSupportFragmentManager(), "LOGIN_TAG");
}
@Override
public boolean onSupportNavigateUp() {
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main);
@ -177,4 +196,6 @@ public class MainActivity extends AppCompatActivity implements MetaDataDialog.On
}
}).start();
}
}

View File

@ -0,0 +1,19 @@
package core.notevault.sync;
import android.content.Context;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public class ApiClient {
private static Retrofit retrofit;
public static Retrofit getRetrofitInstance(Context context) {
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl("http://192.168.178.30:8080/")
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
}

View File

@ -0,0 +1,50 @@
package core.notevault.sync.auth;
import android.content.Context;
import android.content.SharedPreferences;
import core.notevault.sync.ApiClient;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class AuthRepository {
private final AuthService authService;
private final SharedPreferences preferences;
public AuthRepository(Context context) {
this.authService = ApiClient.getRetrofitInstance(context).create(AuthService.class);
this.preferences = context.getSharedPreferences("app_prefs", Context.MODE_PRIVATE);
}
public void performLogin(String username, String password, LoginCallback callback) {
LoginRequest loginRequest = new LoginRequest(username, password);
authService.login(loginRequest).enqueue(new Callback<LoginResponse>() {
@Override
public void onResponse(Call<LoginResponse> call, Response<LoginResponse> 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<LoginResponse> call, Throwable t) {
// Netzwerkfehler an den Callback senden
callback.onError("Netzwerkfehler: " + t.getMessage());
}
});
}
private void saveToken(String token) {
SharedPreferences.Editor editor = preferences.edit();
editor.putString("jwt_token", token);
editor.apply();
}
}

View File

@ -0,0 +1,11 @@
package core.notevault.sync.auth;
import retrofit2.Call;
import retrofit2.http.Body;
import retrofit2.http.POST;
public interface AuthService {
@POST("api/v1/auth/login")
Call<LoginResponse> login(@Body LoginRequest loginRequest);
}

View File

@ -0,0 +1,7 @@
package core.notevault.sync.auth;
public interface LoginCallback {
void onSuccess();
void onError(String error);
}

View File

@ -0,0 +1,13 @@
package core.notevault.sync.auth;
public class LoginRequest {
private String username;
private String password;
public LoginRequest(String username, String password) {
this.username = username;
this.password = password;
}
}

View File

@ -0,0 +1,22 @@
package core.notevault.sync.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;
}
}

View File

@ -0,0 +1,25 @@
package core.notevault.ui.login;
import android.content.Context;
import android.util.Log;
import android.widget.Toast;
import core.notevault.sync.auth.LoginCallback;
public class LoginCallBackImpl implements LoginCallback {
private Context context;
public LoginCallBackImpl(Context context) {
this.context = context;
}
@Override
public void onSuccess() {
Toast.makeText(context, "Login successfull", Toast.LENGTH_SHORT).show();
}
@Override
public void onError(String error) {
Log.d("Login", error);
Toast.makeText(context, "Login not successfull: " + error, Toast.LENGTH_LONG).show();
}
}

View File

@ -0,0 +1,41 @@
package core.notevault.ui.login;
import android.app.AlertDialog;
import android.app.Dialog;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.EditText;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.DialogFragment;
import core.notevault.R;
import core.notevault.sync.auth.AuthRepository;
public class LoginDialogFragment extends DialogFragment {
@NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
LayoutInflater inflater = requireActivity().getLayoutInflater();
View loginView = inflater.inflate(R.layout.fragment_login_dialog, null); // Ersetze 'your_dialog_layout' durch deinen Dateinamen
EditText usernameInput = loginView.findViewById(R.id.editTextUsername);
EditText passwordInput = loginView.findViewById(R.id.editTextPassword);
AuthRepository authRepository = new AuthRepository(this.getContext());
return new AlertDialog.Builder(requireContext())
.setView(loginView)
.setPositiveButton("Speichern", (dialog, which) -> {
String username = usernameInput.getText().toString();
String password = passwordInput.getText().toString();
authRepository.performLogin(username, password, new LoginCallBackImpl(this.getContext()));
} )
.setNegativeButton("Abbrechen", (dialog, which) -> {} )
.create();
}
}

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960">
<path
android:pathData="M480,840v-80h280v-560L480,200v-80h280q33,0 56.5,23.5T840,200v560q0,33 -23.5,56.5T760,840L480,840ZM400,680 L345,622 447,520L120,520v-80h327L345,338l55,-58 200,200 -200,200Z"
android:fillColor="#e8eaed"/>
</vector>

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- res/layout/dialog_login.xml -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<EditText
android:id="@+id/editTextUsername"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Username" />
<EditText
android:id="@+id/editTextPassword"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Password"
android:inputType="textPassword" />
</LinearLayout>

View File

@ -1,8 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:id="@+id/action_settings"
android:title="@string/action_settings"
android:orderInCategory="101"
app:showAsAction="never"/>
</menu>
<!-- res/menu/main_menu.xml -->
<menu xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/action_login"
android:title="Login"
android:icon="@drawable/login"
app:showAsAction="always"/> <!-- Wichtig: immer in der Toolbar anzeigen -->
</menu>