Add user settings feature to update username and password
Signed-off-by: YoungSoo Shin <shinys000114@gmail.com>
This commit is contained in:
@@ -177,6 +177,8 @@ static esp_err_t setting_post_handler(httpd_req_t* req)
|
|||||||
cJSON* vin_climit_item = cJSON_GetObjectItem(root, "vin_current_limit");
|
cJSON* vin_climit_item = cJSON_GetObjectItem(root, "vin_current_limit");
|
||||||
cJSON* main_climit_item = cJSON_GetObjectItem(root, "main_current_limit");
|
cJSON* main_climit_item = cJSON_GetObjectItem(root, "main_current_limit");
|
||||||
cJSON* usb_climit_item = cJSON_GetObjectItem(root, "usb_current_limit");
|
cJSON* usb_climit_item = cJSON_GetObjectItem(root, "usb_current_limit");
|
||||||
|
cJSON* new_username_item = cJSON_GetObjectItem(root, "new_username");
|
||||||
|
cJSON* new_password_item = cJSON_GetObjectItem(root, "new_password");
|
||||||
|
|
||||||
if (mode_item && cJSON_IsString(mode_item))
|
if (mode_item && cJSON_IsString(mode_item))
|
||||||
{
|
{
|
||||||
@@ -322,6 +324,17 @@ static esp_err_t setting_post_handler(httpd_req_t* req)
|
|||||||
}
|
}
|
||||||
httpd_resp_sendstr(req, "{\"status\":\"current_limit_updated\"}");
|
httpd_resp_sendstr(req, "{\"status\":\"current_limit_updated\"}");
|
||||||
}
|
}
|
||||||
|
else if (new_username_item && cJSON_IsString(new_username_item) && new_password_item &&
|
||||||
|
cJSON_IsString(new_password_item))
|
||||||
|
{
|
||||||
|
const char* new_username = new_username_item->valuestring;
|
||||||
|
const char* new_password = new_password_item->valuestring;
|
||||||
|
|
||||||
|
nconfig_write(PAGE_USERNAME, new_username);
|
||||||
|
nconfig_write(PAGE_PASSWORD, new_password);
|
||||||
|
ESP_LOGI(TAG, "Username and password updated successfully.");
|
||||||
|
httpd_resp_sendstr(req, "{\"status\":\"user_credentials_updated\"}");
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Invalid payload");
|
httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Invalid payload");
|
||||||
|
|||||||
@@ -80,12 +80,58 @@ static esp_err_t login_handler(httpd_req_t* req)
|
|||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* username = username_json->valuestring;
|
const char* received_username = username_json->valuestring;
|
||||||
const char* password = password_json->valuestring;
|
const char* received_password = password_json->valuestring;
|
||||||
|
|
||||||
// TODO: Implement actual credential validation
|
// Get stored username and password from nconfig
|
||||||
// For now, a simple hardcoded check
|
size_t stored_username_len = 0;
|
||||||
if (strcmp(username, "admin") == 0 && strcmp(password, "password") == 0)
|
size_t stored_password_len = 0;
|
||||||
|
char* stored_username = NULL;
|
||||||
|
char* stored_password = NULL;
|
||||||
|
bool credentials_match = false;
|
||||||
|
|
||||||
|
if (nconfig_get_str_len(PAGE_USERNAME, &stored_username_len) == ESP_OK && stored_username_len > 1)
|
||||||
|
{
|
||||||
|
stored_username = (char*)malloc(stored_username_len);
|
||||||
|
if (stored_username)
|
||||||
|
{
|
||||||
|
if (nconfig_read(PAGE_USERNAME, stored_username, stored_username_len) != ESP_OK)
|
||||||
|
{
|
||||||
|
ESP_LOGE(TAG, "Failed to read stored username from nconfig");
|
||||||
|
free(stored_username);
|
||||||
|
stored_username = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nconfig_get_str_len(PAGE_PASSWORD, &stored_password_len) == ESP_OK && stored_password_len > 1)
|
||||||
|
{
|
||||||
|
stored_password = (char*)malloc(stored_password_len);
|
||||||
|
if (stored_password)
|
||||||
|
{
|
||||||
|
if (nconfig_read(PAGE_PASSWORD, stored_password, stored_password_len) != ESP_OK)
|
||||||
|
{
|
||||||
|
ESP_LOGE(TAG, "Failed to read stored password from nconfig");
|
||||||
|
free(stored_password);
|
||||||
|
stored_password = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stored_username && stored_password)
|
||||||
|
{
|
||||||
|
if (strcmp(received_username, stored_username) == 0 && strcmp(received_password, stored_password) == 0)
|
||||||
|
{
|
||||||
|
credentials_match = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stored_username)
|
||||||
|
free(stored_username);
|
||||||
|
if (stored_password)
|
||||||
|
free(stored_password);
|
||||||
|
|
||||||
|
if (credentials_match)
|
||||||
{
|
{
|
||||||
char* token = auth_generate_token();
|
char* token = auth_generate_token();
|
||||||
if (token)
|
if (token)
|
||||||
|
|||||||
@@ -197,6 +197,11 @@
|
|||||||
id="current-limit-settings-tab" role="tab" type="button">Current Limit
|
id="current-limit-settings-tab" role="tab" type="button">Current Limit
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
|
<li class="nav-item" role="presentation">
|
||||||
|
<button class="nav-link" data-bs-target="#user-settings-pane" data-bs-toggle="tab"
|
||||||
|
id="user-settings-tab" role="tab" type="button">User Settings
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
<li class="nav-item" role="presentation">
|
<li class="nav-item" role="presentation">
|
||||||
<button class="nav-link" id="device-settings-tab" data-bs-toggle="tab"
|
<button class="nav-link" id="device-settings-tab" data-bs-toggle="tab"
|
||||||
data-bs-target="#device-settings-pane" type="button" role="tab">Device
|
data-bs-target="#device-settings-pane" type="button" role="tab">Device
|
||||||
@@ -331,6 +336,28 @@
|
|||||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="tab-pane fade" id="user-settings-pane" role="tabpanel">
|
||||||
|
<form id="user-settings-form">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label" for="new-username">New Username</label>
|
||||||
|
<input class="form-control" id="new-username" required type="text">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label" for="new-password">New Password</label>
|
||||||
|
<input class="form-control" id="new-password" required type="password">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label" for="confirm-password">Confirm New Password</label>
|
||||||
|
<input class="form-control" id="confirm-password" required type="password">
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-end pt-3 border-top mt-3">
|
||||||
|
<button class="btn btn-primary me-2" id="user-settings-apply-button" type="submit">
|
||||||
|
Apply
|
||||||
|
</button>
|
||||||
|
<button class="btn btn-secondary" data-bs-dismiss="modal" type="button">Close</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
<div class="tab-pane fade" id="device-settings-pane" role="tabpanel">
|
<div class="tab-pane fade" id="device-settings-pane" role="tabpanel">
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="baud-rate-select" class="form-label">UART Baud Rate</label>
|
<label for="baud-rate-select" class="form-label">UART Baud Rate</label>
|
||||||
|
|||||||
@@ -171,3 +171,22 @@ export async function fetchVersion() {
|
|||||||
});
|
});
|
||||||
return await handleResponse(response).then(res => res.json());
|
return await handleResponse(response).then(res => res.json());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the user's username and password on the server.
|
||||||
|
* @param {string} newUsername The new username.
|
||||||
|
* @param {string} newPassword The new password.
|
||||||
|
* @returns {Promise<Object>} A promise that resolves to the server's JSON response.
|
||||||
|
* @throws {Error} Throws an error if the update fails.
|
||||||
|
*/
|
||||||
|
export async function updateUserSettings(newUsername, newPassword) {
|
||||||
|
const response = await fetch('/api/setting', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
...getAuthHeaders(),
|
||||||
|
},
|
||||||
|
body: JSON.stringify({new_username: newUsername, new_password: newPassword}),
|
||||||
|
});
|
||||||
|
return await handleResponse(response).then(res => res.json());
|
||||||
|
}
|
||||||
|
|||||||
@@ -44,6 +44,12 @@ const themeIconLogin = document.getElementById('theme-icon-login');
|
|||||||
const themeToggleMain = document.getElementById('theme-toggle');
|
const themeToggleMain = document.getElementById('theme-toggle');
|
||||||
const themeIconMain = document.getElementById('theme-icon');
|
const themeIconMain = document.getElementById('theme-icon');
|
||||||
|
|
||||||
|
// User Settings DOM Elements
|
||||||
|
const userSettingsForm = document.getElementById('user-settings-form');
|
||||||
|
const newUsernameInput = document.getElementById('new-username');
|
||||||
|
const newPasswordInput = document.getElementById('new-password');
|
||||||
|
const confirmPasswordInput = document.getElementById('confirm-password');
|
||||||
|
|
||||||
|
|
||||||
// --- WebSocket Event Handlers ---
|
// --- WebSocket Event Handlers ---
|
||||||
|
|
||||||
@@ -168,6 +174,38 @@ function handleLogout() {
|
|||||||
// For now, just hide the main content.
|
// For now, just hide the main content.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- User Settings Functions ---
|
||||||
|
async function handleUserSettingsSubmit(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
const newUsername = newUsernameInput.value;
|
||||||
|
const newPassword = newPasswordInput.value;
|
||||||
|
const confirmPassword = confirmPasswordInput.value;
|
||||||
|
|
||||||
|
if (!newUsername || !newPassword || !confirmPassword) {
|
||||||
|
alert('Please fill in all fields for username and password.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newPassword !== confirmPassword) {
|
||||||
|
alert('New password and confirm password do not match.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await api.updateUserSettings(newUsername, newPassword);
|
||||||
|
if (response && response.status === 'user_credentials_updated') {
|
||||||
|
alert('Username and password updated successfully. Please log in again with new credentials.');
|
||||||
|
handleLogout(); // Force logout to re-authenticate with new credentials
|
||||||
|
} else {
|
||||||
|
alert(`Failed to update credentials: ${response.message || 'Unknown error'}`);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error updating user settings:', error);
|
||||||
|
alert(`Error updating user settings: ${error.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// --- Theme Toggle Functions ---
|
// --- Theme Toggle Functions ---
|
||||||
function setupThemeToggles() {
|
function setupThemeToggles() {
|
||||||
// Initialize theme for login page
|
// Initialize theme for login page
|
||||||
@@ -230,6 +268,11 @@ function initializeMainAppContent() {
|
|||||||
setupEventListeners(); // Attach main app event listeners
|
setupEventListeners(); // Attach main app event listeners
|
||||||
logoutButton.addEventListener('click', handleLogout); // Attach logout listener
|
logoutButton.addEventListener('click', handleLogout); // Attach logout listener
|
||||||
connect();
|
connect();
|
||||||
|
|
||||||
|
// Attach user settings form listener
|
||||||
|
if (userSettingsForm) {
|
||||||
|
userSettingsForm.addEventListener('submit', handleUserSettingsSubmit);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function initialize() {
|
function initialize() {
|
||||||
|
|||||||
Reference in New Issue
Block a user