From 85711e42cd63ca7e4628e3776a9c038ee6e8fe68 Mon Sep 17 00:00:00 2001 From: hz Date: Sun, 23 Nov 2025 09:41:26 -0600 Subject: [PATCH] Adding Log in / log out behavior --- README.txt | 7 ++ game/README.txt | 9 --- game/project.godot | 1 + game/scenes/UI/auth_state.gd | 15 ++++ game/scenes/UI/auth_state.gd.uid | 1 + game/scenes/UI/login_screen.gd | 48 ++++++++++++ game/scenes/UI/login_screen.gd.uid | 1 + game/scenes/UI/login_screen.tscn | 117 ++++++++++++++++++++++++++++ game/scenes/UI/menu_music.gd | 1 + game/scenes/UI/start_screen.gd | 41 +++++++++- game/scenes/UI/start_screen.tscn | 49 ++++++++---- microservices/Auth/appsettings.json | 4 +- 12 files changed, 267 insertions(+), 27 deletions(-) create mode 100644 README.txt delete mode 100644 game/README.txt create mode 100644 game/scenes/UI/auth_state.gd create mode 100644 game/scenes/UI/auth_state.gd.uid create mode 100644 game/scenes/UI/login_screen.gd create mode 100644 game/scenes/UI/login_screen.gd.uid create mode 100644 game/scenes/UI/login_screen.tscn diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..20be14e --- /dev/null +++ b/README.txt @@ -0,0 +1,7 @@ +Auth Microservice swagger is accessible at https://pauth.ranaze.com/swagger/index.html + +Test Users: + SUPER/SUPER - Super User + test1/test1 - Super User + test3/test3 - User + \ No newline at end of file diff --git a/game/README.txt b/game/README.txt deleted file mode 100644 index c6156ee..0000000 --- a/game/README.txt +++ /dev/null @@ -1,9 +0,0 @@ -Perforce Connection String: ssl:perforce.ranaze.com:443 - -Git ↔ Perforce quick map -repo → depot (//depot/...) -branch → stream (e.g., //depot/main, //depot/alice) -clone → workspace/client (local view + metadata) -commit → changelist (pending → submitted) -PR/MR → shelve + review (with Swarm) or merge up from task stream -.gitignore → P4IGNORE file (e.g., .p4ignore) diff --git a/game/project.godot b/game/project.godot index 6e9ef39..f235398 100644 --- a/game/project.godot +++ b/game/project.godot @@ -23,6 +23,7 @@ bus_layout="res://audio/bus_layout.tres" MenuMusic="*res://scenes/UI/menu_music.tscn" MenuSfx="*res://scenes/UI/menu_sfx.tscn" +AuthState="*res://scenes/UI/auth_state.gd" [dotnet] diff --git a/game/scenes/UI/auth_state.gd b/game/scenes/UI/auth_state.gd new file mode 100644 index 0000000..6f18171 --- /dev/null +++ b/game/scenes/UI/auth_state.gd @@ -0,0 +1,15 @@ +extends Node + +var is_logged_in: bool = false +var access_token: String = "" +var username: String = "" + +func set_session(new_username: String, token: String) -> void: + is_logged_in = true + username = new_username + access_token = token + +func clear_session() -> void: + is_logged_in = false + username = "" + access_token = "" diff --git a/game/scenes/UI/auth_state.gd.uid b/game/scenes/UI/auth_state.gd.uid new file mode 100644 index 0000000..de9087c --- /dev/null +++ b/game/scenes/UI/auth_state.gd.uid @@ -0,0 +1 @@ +uid://ccloj2rh4dche diff --git a/game/scenes/UI/login_screen.gd b/game/scenes/UI/login_screen.gd new file mode 100644 index 0000000..9f2863d --- /dev/null +++ b/game/scenes/UI/login_screen.gd @@ -0,0 +1,48 @@ +extends Control + +const AUTH_LOGIN_URL := "https://pauth.ranaze.com/api/Auth/login" + +@onready var _username_input: LineEdit = %UsernameInput +@onready var _password_input: LineEdit = %PasswordInput +@onready var _login_request: HTTPRequest = %LoginRequest +@onready var _error_label: Label = %ErrorLabel + +func _on_log_in_button_pressed() -> void: + var username := _username_input.text.strip_edges() + var password := _password_input.text + if username.is_empty() or password.is_empty(): + _show_error("Username and password required.") + return + + var payload := { + "username": username, + "password": password, + } + var headers := PackedStringArray(["Content-Type: application/json"]) + var err := _login_request.request(AUTH_LOGIN_URL, headers, HTTPClient.METHOD_POST, JSON.stringify(payload)) + if err != OK: + _show_error("Failed to send login request.") + +func _on_login_request_completed(result: int, response_code: int, _headers: PackedStringArray, body: PackedByteArray) -> void: + var body_text := body.get_string_from_utf8() + if result != HTTPRequest.RESULT_SUCCESS: + _show_error("Network error. Please try again.") + return + + if response_code >= 200 and response_code < 300: + var response: Variant = JSON.parse_string(body_text) + if typeof(response) == TYPE_DICTIONARY: + #print("Login success for %s" % response.get("username", "unknown")) + #print("Access Token: %s" % response.get("accessToken", "")) + var token := String(response.get("accessToken", "")) + var username := String(response.get("username", "")) + AuthState.set_session(username, token) + get_tree().change_scene_to_file("res://scenes/UI/start_screen.tscn") + else: + _show_error("Login failed. Check your credentials.") + +func _on_back_button_pressed() -> void: + get_tree().change_scene_to_file("res://scenes/UI/start_screen.tscn") + +func _show_error(message: String) -> void: + _error_label.text = message diff --git a/game/scenes/UI/login_screen.gd.uid b/game/scenes/UI/login_screen.gd.uid new file mode 100644 index 0000000..dc91b5d --- /dev/null +++ b/game/scenes/UI/login_screen.gd.uid @@ -0,0 +1 @@ +uid://bnrhapdcfvp04 diff --git a/game/scenes/UI/login_screen.tscn b/game/scenes/UI/login_screen.tscn new file mode 100644 index 0000000..007072d --- /dev/null +++ b/game/scenes/UI/login_screen.tscn @@ -0,0 +1,117 @@ +[gd_scene load_steps=5 format=3 uid="uid://fmp1tah03kew"] + +[ext_resource type="Script" path="res://scenes/UI/login_screen.gd" id="1_jqkpi"] +[ext_resource type="Texture2D" uid="uid://dhuosr0p605gj" path="res://assets/images/pp_start_bg.png" id="2_2n6di"] +[ext_resource type="Theme" uid="uid://tn8qndst18d6" path="res://themes/title_font_theme.tres" id="3_c4k70"] +[ext_resource type="Theme" uid="uid://wpxmub0n2dr3" path="res://themes/button_theme.tres" id="4_gx673"] + +[node name="LoginScreen" type="Control"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1_jqkpi") + +[node name="TextureRect" type="TextureRect" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("2_2n6di") + +[node name="MarginContainer" type="MarginContainer" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +theme_override_constants/margin_left = 80 +theme_override_constants/margin_top = 40 +theme_override_constants/margin_right = 80 +theme_override_constants/margin_bottom = 40 + +[node name="ContentCenter" type="CenterContainer" parent="MarginContainer"] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="ContentVBox" type="VBoxContainer" parent="MarginContainer/ContentCenter"] +layout_mode = 2 +size_flags_horizontal = 4 +size_flags_vertical = 4 +theme_override_constants/separation = 24 + +[node name="TitleLabel" type="Label" parent="MarginContainer/ContentCenter/ContentVBox"] +layout_mode = 2 +size_flags_horizontal = 4 +theme = ExtResource("3_c4k70") +text = "ACCOUNT LOGIN" +horizontal_alignment = 1 + +[node name="FormVBox" type="VBoxContainer" parent="MarginContainer/ContentCenter/ContentVBox"] +layout_mode = 2 +size_flags_horizontal = 4 +theme_override_constants/separation = 8 +custom_minimum_size = Vector2(480, 0) + +[node name="UsernameLabel" type="Label" parent="MarginContainer/ContentCenter/ContentVBox/FormVBox"] +layout_mode = 2 +text = "Username" + +[node name="UsernameInput" type="LineEdit" parent="MarginContainer/ContentCenter/ContentVBox/FormVBox"] +unique_name_in_owner = true +layout_mode = 2 +placeholder_text = "enter username" +caret_blink = true + +[node name="PasswordLabel" type="Label" parent="MarginContainer/ContentCenter/ContentVBox/FormVBox"] +layout_mode = 2 +text = "Password" + +[node name="PasswordInput" type="LineEdit" parent="MarginContainer/ContentCenter/ContentVBox/FormVBox"] +unique_name_in_owner = true +layout_mode = 2 +placeholder_text = "enter password" +secret = true + +[node name="ButtonVBox" type="VBoxContainer" parent="MarginContainer/ContentCenter/ContentVBox"] +layout_mode = 2 +size_flags_horizontal = 4 +theme_override_constants/separation = 12 + +[node name="ErrorLabel" type="Label" parent="MarginContainer/ContentCenter/ContentVBox/ButtonVBox"] +unique_name_in_owner = true +layout_mode = 2 +theme = ExtResource("3_c4k70") +horizontal_alignment = 1 +theme_override_font_sizes/font_size = 26 +theme_override_colors/font_color = Color(1, 0.2, 0.2, 1) + +[node name="LogInButton" type="Button" parent="MarginContainer/ContentCenter/ContentVBox/ButtonVBox"] +layout_mode = 2 +size_flags_horizontal = 4 +theme = ExtResource("4_gx673") +text = "LOG IN" +text_alignment = 1 + +[node name="BackButton" type="Button" parent="MarginContainer/ContentCenter/ContentVBox/ButtonVBox"] +layout_mode = 2 +size_flags_horizontal = 4 +theme = ExtResource("4_gx673") +text = "BACK" +text_alignment = 1 + +[node name="LoginRequest" type="HTTPRequest" parent="."] +unique_name_in_owner = true + +[connection signal="pressed" from="MarginContainer/ContentCenter/ContentVBox/ButtonVBox/LogInButton" to="." method="_on_log_in_button_pressed"] +[connection signal="pressed" from="MarginContainer/ContentCenter/ContentVBox/ButtonVBox/BackButton" to="." method="_on_back_button_pressed"] +[connection signal="request_completed" from="LoginRequest" to="." method="_on_login_request_completed"] diff --git a/game/scenes/UI/menu_music.gd b/game/scenes/UI/menu_music.gd index 23de7c4..c39db1f 100644 --- a/game/scenes/UI/menu_music.gd +++ b/game/scenes/UI/menu_music.gd @@ -3,6 +3,7 @@ extends AudioStreamPlayer const MENU_SCENES: Dictionary = { "res://scenes/UI/start_screen.tscn": true, "res://scenes/UI/Settings.tscn": true, + "res://scenes/UI/login_screen.tscn": true, } const CONFIG_PATH := "user://settings.cfg" diff --git a/game/scenes/UI/start_screen.gd b/game/scenes/UI/start_screen.gd index dbc509f..c958d87 100644 --- a/game/scenes/UI/start_screen.gd +++ b/game/scenes/UI/start_screen.gd @@ -1,10 +1,16 @@ extends Control +const AUTH_LOGOUT_URL := "https://pauth.ranaze.com/api/Auth/logout" + +@onready var _login_button: Button = $MarginContainer/CenterContainer/ContentVBox/VBoxContainer/LogInButton +@onready var _logout_request: HTTPRequest = %LogoutRequest + func _ready(): _register_focus_sounds() + _update_login_button() func _register_focus_sounds() -> void: - var button_container := $MarginContainer/MarginContainer/VBoxContainer + var button_container := $MarginContainer/CenterContainer/ContentVBox/VBoxContainer for child in button_container.get_children(): if child is BaseButton: var button: BaseButton = child @@ -22,6 +28,39 @@ func _on_settings_button_pressed(): func _on_quit_button_pressed(): get_tree().quit() +func _on_log_in_button_pressed(): + if AuthState.is_logged_in: + _request_logout() + else: + get_tree().change_scene_to_file("res://scenes/UI/login_screen.tscn") + func _on_menu_item_focus() -> void: if MenuSfx: MenuSfx.play_hover() + +func _request_logout() -> void: + if AuthState.access_token.is_empty(): + AuthState.clear_session() + _update_login_button() + return + var headers := PackedStringArray([ + "Authorization: Bearer %s" % AuthState.access_token, + ]) + var err := _logout_request.request(AUTH_LOGOUT_URL, headers, HTTPClient.METHOD_POST) + if err != OK: + push_warning("Failed to send logout request: %s" % err) + AuthState.clear_session() + _update_login_button() + +func _on_logout_request_completed(result: int, response_code: int, _headers: PackedStringArray, body: PackedByteArray) -> void: + var body_text := body.get_string_from_utf8() + if result != HTTPRequest.RESULT_SUCCESS or response_code < 200 or response_code >= 300: + push_warning("Logout failed (%s/%s): %s" % [result, response_code, body_text]) + AuthState.clear_session() + _update_login_button() + +func _update_login_button() -> void: + if AuthState.is_logged_in: + _login_button.text = "LOG OUT" + else: + _login_button.text = "LOG IN" diff --git a/game/scenes/UI/start_screen.tscn b/game/scenes/UI/start_screen.tscn index 943271b..4d9c20d 100644 --- a/game/scenes/UI/start_screen.tscn +++ b/game/scenes/UI/start_screen.tscn @@ -4,6 +4,7 @@ [ext_resource type="Theme" uid="uid://wpxmub0n2dr3" path="res://themes/button_theme.tres" id="1_tx5wa"] [ext_resource type="Texture2D" uid="uid://dhuosr0p605gj" path="res://assets/images/pp_start_bg.png" id="2_r2jwc"] [ext_resource type="Theme" uid="uid://tn8qndst18d6" path="res://themes/title_font_theme.tres" id="4_hm208"] + [node name="StartScreen" type="Control"] layout_mode = 3 anchors_preset = 15 @@ -34,7 +35,16 @@ theme_override_constants/margin_top = 10 theme_override_constants/margin_right = 10 theme_override_constants/margin_bottom = 10 -[node name="Label" type="Label" parent="MarginContainer"] +[node name="CenterContainer" type="CenterContainer" parent="MarginContainer"] +layout_mode = 2 + +[node name="ContentVBox" type="VBoxContainer" parent="MarginContainer/CenterContainer"] +layout_mode = 2 +size_flags_horizontal = 4 +size_flags_vertical = 8 +theme_override_constants/separation = 10 + +[node name="Label" type="Label" parent="MarginContainer/CenterContainer/ContentVBox"] layout_mode = 2 size_flags_horizontal = 4 theme = ExtResource("4_hm208") @@ -42,40 +52,49 @@ text = "PROJECT PROMISCUOUS" horizontal_alignment = 1 -[node name="MarginContainer" type="MarginContainer" parent="MarginContainer"] +[node name="TitleSpacer" type="Control" parent="MarginContainer/CenterContainer/ContentVBox"] +custom_minimum_size = Vector2(0, 40) layout_mode = 2 -size_flags_horizontal = 4 -size_flags_vertical = 8 -theme_override_constants/margin_top = 10 -theme_override_constants/margin_bottom = 60 -[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/MarginContainer"] +[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/CenterContainer/ContentVBox"] layout_mode = 2 size_flags_horizontal = 4 size_flags_vertical = 8 theme_override_constants/separation = 6 -[node name="StartButton" type="Button" parent="MarginContainer/MarginContainer/VBoxContainer"] +[node name="LogInButton" type="Button" parent="MarginContainer/CenterContainer/ContentVBox/VBoxContainer"] layout_mode = 2 -size_flags_horizontal = 8 +size_flags_horizontal = 4 size_flags_vertical = 4 theme = ExtResource("1_tx5wa") -text = "START " +text = "LOG IN" -[node name="SettingsButton" type="Button" parent="MarginContainer/MarginContainer/VBoxContainer"] +[node name="StartButton" type="Button" parent="MarginContainer/CenterContainer/ContentVBox/VBoxContainer"] +layout_mode = 2 +size_flags_horizontal = 4 +size_flags_vertical = 4 +theme = ExtResource("1_tx5wa") +text = "START" + +[node name="SettingsButton" type="Button" parent="MarginContainer/CenterContainer/ContentVBox/VBoxContainer"] layout_mode = 2 size_flags_horizontal = 4 size_flags_vertical = 4 theme = ExtResource("1_tx5wa") text = "SETTINGS" -[node name="QuitButton" type="Button" parent="MarginContainer/MarginContainer/VBoxContainer"] +[node name="QuitButton" type="Button" parent="MarginContainer/CenterContainer/ContentVBox/VBoxContainer"] layout_mode = 2 size_flags_horizontal = 4 size_flags_vertical = 4 theme = ExtResource("1_tx5wa") text = "QUIT" -[connection signal="pressed" from="MarginContainer/MarginContainer/VBoxContainer/StartButton" to="." method="_on_start_button_pressed"] -[connection signal="pressed" from="MarginContainer/MarginContainer/VBoxContainer/SettingsButton" to="." method="_on_settings_button_pressed"] -[connection signal="pressed" from="MarginContainer/MarginContainer/VBoxContainer/QuitButton" to="." method="_on_quit_button_pressed"] +[node name="LogoutRequest" type="HTTPRequest" parent="."] +unique_name_in_owner = true + +[connection signal="pressed" from="MarginContainer/CenterContainer/ContentVBox/VBoxContainer/LogInButton" to="." method="_on_log_in_button_pressed"] +[connection signal="pressed" from="MarginContainer/CenterContainer/ContentVBox/VBoxContainer/StartButton" to="." method="_on_start_button_pressed"] +[connection signal="pressed" from="MarginContainer/CenterContainer/ContentVBox/VBoxContainer/SettingsButton" to="." method="_on_settings_button_pressed"] +[connection signal="pressed" from="MarginContainer/CenterContainer/ContentVBox/VBoxContainer/QuitButton" to="." method="_on_quit_button_pressed"] +[connection signal="request_completed" from="LogoutRequest" to="." method="_on_logout_request_completed"] diff --git a/microservices/Auth/appsettings.json b/microservices/Auth/appsettings.json index 60fb5db..40a1fb6 100644 --- a/microservices/Auth/appsettings.json +++ b/microservices/Auth/appsettings.json @@ -1,7 +1,7 @@ { "Kestrel": { "Endpoints": { "Http": { "Url": "http://0.0.0.0:5000" } } }, - "MongoDB": { "ConnectionString": "mongodb://192.168.86.50:27017", "DatabaseName": "GameDb" }, - "Jwt": { "Key": "SuperUltraSecureJwtKeyWithAtLeast32Chars!!", "Issuer": "GameAuthApi", "Audience": "game-auth-api" }, + "MongoDB": { "ConnectionString": "mongodb://192.168.86.50:27017", "DatabaseName": "promiscuity" }, + "Jwt": { "Key": "SuperUltraSecureJwtKeyWithAtLeast32Chars!!", "Issuer": "promiscuity", "Audience": "promiscuity-auth-api" }, "Logging": { "LogLevel": { "Default": "Information" } }, "AllowedHosts": "*" }