Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .idea/.name

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

38 changes: 38 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@

# ChatGPT App - Sicherheitsfeature Update

## Einleitung
In diesem Update haben ich mich auf die Verbesserung der Sicherheit und Benutzerfreundlichkeit der ChatGPT App konzentriert. Das Hauptziel war es, die App durch eine Passwortsicherung zu schützen.

### Verbesserungen
- **Passwortschutz:** Dieses Feature ermöglicht es den Benutzern, ihre Sitzungen durch ein individuelles Passwort zu sichern, was einen zusätzlichen Schutz gegen unbefugten Zugriff bietet.

## Anforderungen
Die Erweiterung zielt darauf ab, folgende Funktionen zu bieten:
- **Sicheres Login:** Ein robustes Login-System, das die Benutzerdaten durch ein Passwort schützt.
- **Modularität:** Ein Modul vorzubereiten um später ein Multi user system zu implementieren

## Umsetzung
### Programmierung
- **`LoginActivity`:** Eine neue Aktivität, die den Login-Prozess steuert. Hier wurde ein benutzerfreundliches Interface implementiert, das die Eingabe von Benutzername und Passwort ermöglicht.
- **`LoginDataSource`:** Ein neue Klasse, die eine anbindung an eine Datenbank/backend ermöglicht.
- **`LoggedInUser`:** Ein neue Klasse, die zum speichern des Users verwendet wird.

### Konfiguration
- **XML-Dateien:** Anpassungen in den XML-Dateien wurden vorgenommen, um das Layout und die Einstellungen der neuen Features zu unterstützen. Dies beinhaltet das Design der Login-Seite sowie die Struktur der Einstellungsmenüs.

## Probleme/Lessons Learned
### Herausforderungen
- **Zugriff auf App-Einstellungen:** Es gab Schwierigkeiten beim Implementieren der Einstellungen, insbesondere beim Speichern und Abrufen der Benutzerpräferenzen.
- **Startaktivität ändern:** Die Änderung der Startaktivität der App stellte eine Herausforderung dar, da dies eine tiefgreifende Anpassung des App-Flows erforderte.

### Lösungen und Erkenntnisse
- **Erkenntnisse:** Eine gründlichere Planung und Testphase hätte einige der Probleme verhindern können.

## Fazit
Das Projekt wurde nicht ganz erfolgreich umgesetzt. Der zeitliche Aufwand war größer als erwartet, aber das Endergebnis ist zufriedenstellend. Zukünftige Entwicklungen könnten die Implementierung von Firebase und zusätzliche Benutzereinstellungen umfassen.

## Zukünftige Entwicklungen
- **Firebase:** Für eine verbesserte Datenverwaltung und Authentifizierung.
- **Registrierungsmöglichkeit:** Ermöglicht es neuen Benutzern, eigene Konten zu erstellen.
- **Speichern von benutzerdefinierten Einstellungen:** Für eine personalisierte App-Erfahrung.
15 changes: 15 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ android {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
buildFeatures {
viewBinding true
}
}

dependencies {
Expand All @@ -35,7 +38,19 @@ dependencies {
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'com.theokanning.openai-gpt3-java:service:0.14.0'
implementation 'androidx.preference:preference:1.2.0'
implementation 'androidx.annotation:annotation:1.7.0'
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.6.2'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
constraints {
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.0") {
because("kotlin-stdlib-jdk7 is now a part of kotlin-stdlib")
}
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.0") {
because("kotlin-stdlib-jdk8 is now a part of kotlin-stdlib")
}
}

}
15 changes: 10 additions & 5 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,23 @@
android:supportsRtl="true"
android:theme="@style/Theme.ChatGpt"
tools:targetApi="31">
<activity
android:name=".ui.login.LoginActivity"
android:exported="true"
android:label="@string/title_activity_login">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".PrefsActivity"
android:exported="false"
android:label="Settings" />
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import de.fhdw.app_entwicklung.chatgpt.model.Author;
import de.fhdw.app_entwicklung.chatgpt.model.Chat;
import de.fhdw.app_entwicklung.chatgpt.model.Message;
import de.fhdw.app_entwicklung.chatgpt.openai.ChatGpt;
import de.fhdw.app_entwicklung.chatgpt.openai.IChatGpt;
import de.fhdw.app_entwicklung.chatgpt.openai.MockChatGpt;
import de.fhdw.app_entwicklung.chatgpt.speech.LaunchSpeechRecognition;
Expand All @@ -45,7 +46,7 @@ public class MainFragment extends Fragment {
scrollToEnd();

MainActivity.backgroundExecutorService.execute(() -> {
IChatGpt chatGpt = new MockChatGpt(prefs.getApiToken(), prefs.getModel());
IChatGpt chatGpt = new ChatGpt(prefs.getApiToken(), prefs.getModel());
String answer = chatGpt.getChatCompletion(chat);

Message answerMessage = new Message(Author.Assistant, answer);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ public boolean speakOutLoud() {
return PreferenceManager.getDefaultSharedPreferences(context).getBoolean("read_out_loud", true);
}

public String getAppPassword() {
return PreferenceManager.getDefaultSharedPreferences(context).getString("app_password", "1234");
}

public String getApiToken() {
return PreferenceManager.getDefaultSharedPreferences(context).getString("api_token", "");
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package de.fhdw.app_entwicklung.chatgpt.data;

import static android.app.PendingIntent.getActivity;
import static androidx.core.content.ContentProviderCompat.requireContext;

import android.content.Context;
import android.content.ContextWrapper;

import androidx.fragment.app.Fragment;
import androidx.preference.PreferenceManager;

import de.fhdw.app_entwicklung.chatgpt.MainActivity;
import de.fhdw.app_entwicklung.chatgpt.MainFragment;
import de.fhdw.app_entwicklung.chatgpt.PrefsFacade;
import de.fhdw.app_entwicklung.chatgpt.data.model.LoggedInUser;
import de.fhdw.app_entwicklung.chatgpt.ui.login.LoginActivity;

import java.io.IOException;

/**
* Class that handles authentication w/ login credentials and retrieves user information.
*/
public class LoginDataSource {


public Result<LoggedInUser> login(String username, String password) {

try {

//String check = PreferenceManager.getDefaultSharedPreferences(context).getString("app_password", "1234");

String check = "debug"; // no access to context

if (password.equals(check)) {
LoggedInUser currentUser =
new LoggedInUser(
java.util.UUID.randomUUID().toString(),
username);
return new Result.Success<>(currentUser);
} else {
return new Result.Error(new IOException("Password Falsch"));
}
} catch (Exception e) {
return new Result.Error(new IOException("Error logging in", e));
}
}

public void logout() {
// TODO: revoke authentication
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package de.fhdw.app_entwicklung.chatgpt.data;

import de.fhdw.app_entwicklung.chatgpt.data.model.LoggedInUser;

/**
* Class that requests authentication and user information from the remote data source and
* maintains an in-memory cache of login status and user credentials information.
*/
public class LoginRepository {

private static volatile LoginRepository instance;

private LoginDataSource dataSource;

// If user credentials will be cached in local storage, it is recommended it be encrypted
// @see https://developer.android.com/training/articles/keystore
private LoggedInUser user = null;

// private constructor : singleton access
private LoginRepository(LoginDataSource dataSource) {
this.dataSource = dataSource;
}

public static LoginRepository getInstance(LoginDataSource dataSource) {
if (instance == null) {
instance = new LoginRepository(dataSource);
}
return instance;
}

public boolean isLoggedIn() {
return user != null;
}

public void logout() {
user = null;
dataSource.logout();
}

private void setLoggedInUser(LoggedInUser user) {
this.user = user;
// If user credentials will be cached in local storage, it is recommended it be encrypted
// @see https://developer.android.com/training/articles/keystore
}

public Result<LoggedInUser> login(String username, String password) {
// handle login
Result<LoggedInUser> result = dataSource.login(username, password);
if (result instanceof Result.Success) {
setLoggedInUser(((Result.Success<LoggedInUser>) result).getData());
}
return result;
}
}
48 changes: 48 additions & 0 deletions app/src/main/java/de/fhdw/app_entwicklung/chatgpt/data/Result.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package de.fhdw.app_entwicklung.chatgpt.data;

/**
* A generic class that holds a result success w/ data or an error exception.
*/
public class Result<T> {
// hide the private constructor to limit subclass types (Success, Error)
private Result() {
}

@Override
public String toString() {
if (this instanceof Result.Success) {
Result.Success success = (Result.Success) this;
return "Success[data=" + success.getData().toString() + "]";
} else if (this instanceof Result.Error) {
Result.Error error = (Result.Error) this;
return "Error[exception=" + error.getError().toString() + "]";
}
return "";
}

// Success sub-class
public final static class Success<T> extends Result {
private T data;

public Success(T data) {
this.data = data;
}

public T getData() {
return this.data;
}
}

// Error sub-class
public final static class Error extends Result {
private Exception error;

public Error(Exception error) {
this.error = error;
}

public Exception getError() {
return this.error;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package de.fhdw.app_entwicklung.chatgpt.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;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package de.fhdw.app_entwicklung.chatgpt.ui.login;

/**
* Class exposing authenticated user details to the UI.
*/
class LoggedInUserView {
private String displayName;
//... other data fields that may be accessible to the UI

LoggedInUserView(String displayName) {
this.displayName = displayName;
}

String getDisplayName() {
return displayName;
}
}
Loading