Integrate register and login APIs

This commit is contained in:
Dylan Sarrazyn
2024-08-14 17:32:17 +02:00
parent 9a867daee9
commit ad17edb8f3
15 changed files with 277 additions and 37 deletions
+8
View File
@@ -0,0 +1,8 @@
extends Control
@onready var button: Button = $Button
func _on_button_pressed():
var res = await ServerManager.login("sarrazyndylan@gmail.com", "kalulu")
print(res)
+29
View File
@@ -0,0 +1,29 @@
[gd_scene load_steps=2 format=3 uid="uid://4buyb18au5l5"]
[ext_resource type="Script" path="res://control.gd" id="1_hpsys"]
[node name="Control" 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_hpsys")
[node name="Button" type="Button" parent="."]
layout_mode = 1
anchors_preset = 8
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
offset_left = -6.0
offset_top = -6.0
offset_right = 6.0
offset_bottom = 6.0
grow_horizontal = 2
grow_vertical = 2
text = "LOGIN"
[connection signal="pressed" from="Button" to="." method="_on_button_pressed"]
Binary file not shown.
Binary file not shown.
+1
View File
@@ -28,6 +28,7 @@ buses/default_bus_layout="res://resources/audio_buses/main_audio_bus_layout.tres
LessonLogger="*res://sources/utils/autoloads/lesson_logger.gd"
Database="*res://sources/utils/autoloads/Database.gd"
UserDataManager="*res://sources/utils/autoloads/user_data_manager.gd"
ServerManager="*res://sources/utils/autoloads/ServerManager.tscn"
MusicManager="*res://sources/utils/autoloads/music_manager.tscn"
Validation="*res://addons/godot-form-validator/validation.gd"
OpeningCurtain="*res://sources/utils/autoloads/opening_curtain.tscn"
File diff suppressed because one or more lines are too long
+7 -3
View File
@@ -13,6 +13,10 @@ enum Level {
@export var level : Level
@export var age : int
func _to_string():
return "{Code: %s, Name: %s, Level: %s, Age: %d}" % [code, name, Level.keys()[level], age]
func to_dict() -> Dictionary:
return {
"code": code,
"name": name,
"level": level,
"age": age
}
+38 -4
View File
@@ -15,11 +15,32 @@ enum EducationMethod {
@export var account_type : AccountType
@export var education_method : EducationMethod
@export var devices_count : int
var devices_count : int
@export var students : Dictionary # int : Array[StudentData]
@export var email : String
@export var password : String # Temporary
var password : String
@export var token: String
@export var last_modified: String
func update_from_dict(dict: Dictionary) -> void:
account_type = dict.account_type
education_method = dict.education_method
email = dict.email
token = dict.token
last_modified = dict.last_modified
students.clear()
for device: String in dict.students.keys():
var device_students: Array[StudentData] = []
for s: Dictionary in dict.students[device]:
var student = StudentData.new()
student.code = str(s.code)
student.name = s.name
student.age = s.age
student.level = s.level
device_students.append(student)
students[int(device)] = device_students
func get_new_code() -> String :
var used_codes = []
@@ -48,5 +69,18 @@ func get_students_count() -> int :
return count
func _to_string():
return "{Account Type: %s, Education Method: %s, Devices count: %d, Students: %s, Email: %s, Password: %s}" % [AccountType.keys()[account_type], EducationMethod.keys()[education_method], devices_count, str(students), email, password]
func to_dict() -> Dictionary:
var dict = {
"account_type": account_type,
"email": email,
"password": password,
"education_method": education_method,
}
dict["students"] = {}
for device in students.keys():
dict["students"][device] = []
for s: StudentData in students[device]:
dict["students"][device].append(s.to_dict())
return dict
+8 -3
View File
@@ -56,8 +56,13 @@ func _on_validate_button_pressed() -> void:
if not validator.validate():
return
# Login
if UserDataManager.login(account_type, email_field.text, password_field.text, int(device_id_field.value)):
logged_in.emit()
# Request server for login
var res = await ServerManager.login(account_type, int(device_id_field.value), email_field.text, password_field.text)
if res.code == 200:
# Login
if UserDataManager.login(res.body):
logged_in.emit()
else:
login_message.visible = true
else:
login_message.visible = true
+8 -2
View File
@@ -104,9 +104,15 @@ func _on_step_completed(step : Step):
progress_bar.max_value = current_steps.size()
if progress_bar.value == current_steps.size()-1:
if UserDataManager.register(register_data):
get_tree().change_scene_to_file(next_scene_path)
# Send register via API
var res = await ServerManager.register(register_data.to_dict())
if res.code == 200:
register_data.last_modified = res.body.last_modified
register_data.token = res.body.token
if UserDataManager.register(register_data):
get_tree().change_scene_to_file(next_scene_path)
else:
# TODO Add a popup that explains the error
print("Impossible to register")
else:
_go_to_step(progress_bar.value+1)
@@ -0,0 +1,24 @@
extends Step
@onready var api_email_field_error: Label = %APIEmailFieldError
func _on_validate_button_pressed():
api_email_field_error.visible = false
# Validate the fields
if not form_validator.validate():
push_warning("Validation failed (" + str(self) + ")")
return
# Writes data in object
if not form_binder.write():
push_warning("Impossible to write data in object (" + str(self) + ")")
return
var res = await ServerManager.check_email(data.email)
if res.code != 200:
api_email_field_error.visible = true
return
if _on_next():
next.emit(self)
@@ -1,6 +1,7 @@
[gd_scene load_steps=15 format=3 uid="uid://cwqcybk5tvbly"]
[gd_scene load_steps=16 format=3 uid="uid://cwqcybk5tvbly"]
[ext_resource type="PackedScene" uid="uid://bxd3i06rqpxf0" path="res://sources/menus/register/steps/base_step.tscn" id="1_66bx5"]
[ext_resource type="Script" path="res://sources/menus/register/steps/credentials_step.gd" id="2_mqaqr"]
[ext_resource type="Script" path="res://addons/godot-form-validator/control_validator.gd" id="3_hblcf"]
[ext_resource type="Script" path="res://addons/godot-form-validator/rules/required_rule.gd" id="4_4ltsd"]
[ext_resource type="Script" path="res://addons/godot-form-validator/rules/email_rule.gd" id="5_cnymo"]
@@ -41,6 +42,7 @@ skip_validation = false
rules = Array[Resource("res://addons/godot-form-validator/rules/validator_rule.gd")]([SubResource("Resource_5jooi"), SubResource("Resource_104uy")])
[node name="CredentialsStep" instance=ExtResource("1_66bx5")]
script = ExtResource("2_mqaqr")
step_name = "credentials"
question = "CREDENTIALS_PROMPT"
@@ -82,6 +84,14 @@ text = "Test"
label_settings = ExtResource("7_sndyb")
vertical_alignment = 1
[node name="APIEmailFieldError" type="Label" parent="FormValidator/FormBinder/Control/Background/FormMargin/FormContainer/EmailContainer/VBoxContainer" index="2"]
unique_name_in_owner = true
visible = false
layout_mode = 2
text = "USED_EMAIL_ADDRESS"
label_settings = ExtResource("7_sndyb")
vertical_alignment = 1
[node name="HBoxContainer" type="HBoxContainer" parent="FormValidator/FormBinder/Control/Background/FormMargin/FormContainer" index="1"]
layout_mode = 2
size_flags_vertical = 8
@@ -0,0 +1,28 @@
[gd_scene load_steps=4 format=3 uid="uid://yk1u0ohwwgb3"]
[ext_resource type="Script" path="res://sources/utils/autoloads/server_manager.gd" id="1_n6vsh"]
[sub_resource type="Gradient" id="Gradient_dx825"]
colors = PackedColorArray(0.2, 0.2, 0.2, 0.505882, 0.2, 0.2, 0.2, 0.505882)
[sub_resource type="GradientTexture1D" id="GradientTexture1D_68deq"]
gradient = SubResource("Gradient_dx825")
[node name="ServerManager" type="CanvasLayer"]
script = ExtResource("1_n6vsh")
[node name="HTTPRequest" type="HTTPRequest" parent="."]
timeout = 30.0
[node name="TextureRect" type="TextureRect" parent="."]
visible = false
top_level = true
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
mouse_filter = 0
texture = SubResource("GradientTexture1D_68deq")
[connection signal="request_completed" from="HTTPRequest" to="." method="_on_http_request_request_completed"]
+78
View File
@@ -0,0 +1,78 @@
extends CanvasLayer
signal request_completed(code: int, body: Dictionary)
@onready var http_request: HTTPRequest = $HTTPRequest
@onready var loading_rect: TextureRect = $TextureRect
# TODO Put in a file
const URL: String = "https://uqkpbayw1k.execute-api.eu-west-3.amazonaws.com/dev/"
# Response from the last request
var code: int
var json: Dictionary
func check_email(email: String) -> Dictionary:
await _get_request("checkemail", {"mail" : email})
return _response()
func register(data: Dictionary) -> Dictionary:
await _post_json_request("register", data)
return _response()
func login(type: TeacherSettings.AccountType, device:int, mail: String, password: String) -> Dictionary:
await _get_request("login", {"type":type, "device":device, "mail": mail, "password": password})
return _response()
#region Sender functions
func _response() -> Dictionary:
return {
"code" : code,
"body" : json
}
func _get_request(URI: String, params: Dictionary) -> void:
loading_rect.visible = true
code = 0
json = {}
var req: = URL + URI
var is_first_param: bool = true
for key in params.keys():
if is_first_param:
req += "?"
is_first_param = false
else:
req += "&"
req += str(key) + "=" + str(params[key])
if http_request.request(req) == 0:
await request_completed
func _post_json_request(URI: String, data: Dictionary) -> void:
loading_rect.visible = true
code = 0
json = {}
var req: = URL + URI
var headers: = ["Content-Type: application/json"]
var json = JSON.stringify(data)
print(json)
if http_request.request(req, headers, HTTPClient.METHOD_POST, json) == 0:
await request_completed
#endregion
func _on_http_request_request_completed(result, response_code, headers, body):
code = response_code
print("Response received : " + str(code))
print(headers)
if body:
json = JSON.parse_string(body.get_string_from_utf8())
print(json)
request_completed.emit(response_code, json)
loading_rect.visible = false
+25 -12
View File
@@ -51,28 +51,41 @@ func register(register_settings : TeacherSettings) -> bool:
return true
func login(type : TeacherSettings.AccountType, teacher : String, password : String, device_id : int) -> bool:
if not _device_settings or not teacher or not password or device_id == 0:
# Allow the user to log-in from the server
func login(infos: Dictionary) -> bool:
if not _device_settings or not infos:
return false
var path := _get_teacher_settings_path(teacher)
if not FileAccess.file_exists(path):
if not infos.has("device_ID") or not infos.device_ID:
return false
var temp_teacher_settings = load(path) as TeacherSettings
if not temp_teacher_settings or temp_teacher_settings.password != password or temp_teacher_settings.account_type != type or device_id not in temp_teacher_settings.students.keys():
if not infos.has("email") or not infos.email:
return false
# Handles teacher settings
teacher_settings = temp_teacher_settings
if not infos.has("account_type") or infos.account_type < 0 or infos.account_type > 1:
return false
if not infos.has("token") or not infos.token:
return false
# Handles device settings
_device_settings.teacher = teacher
_device_settings.device_id = device_id
_device_settings.teacher = infos.email
_device_settings.device_id = infos.device_ID
_save_device_settings()
var path := get_teacher_settings_path()
# Create the folder locally if it doesn't exists
if not FileAccess.file_exists(path):
DirAccess.make_dir_recursive_absolute(get_teacher_folder())
teacher_settings = TeacherSettings.new()
else:
teacher_settings = load(path) as TeacherSettings
# TODO Check if the last_modified is more recent
teacher_settings.update_from_dict(infos)
_save_teacher_settings()
return true
func logout() -> void: