{= # # # # save_data.cfv (Users) # # # include "templates.util.base_util"; include "templates.util.rbac.rbac_util"; include "templates.admin_pages.scheduler.verify_schedule_rbac"; debug_message("\n#### users save_data.cfv START \n"); string session_id = volatile.session_id; bool is_root_admin = get_is_root_admin(); string page_token = v.fp.page_token; # # Check RBAC permissions # if ((is_root_admin or get_admin_feature_permission(session_id, "users", "edit")) and get_is_valid_page_token(session_id, "users", page_token)) then ( # # # # Note, we have to handle existing password checksums and the root_admin which is not part of users! # # # debug_message("\n" . node_as_string("v.fp") . "\n"); node deleted_users = "v.fp.deleted_users"; node new_users_node = "v.fp.users"; node original_users_node = "users"; string licensing_features = get_licensing_features(); bool is_enterprise = (licensing_features eq "enterprise"); # # Check add/delete permission for non-root-admin users # string errorMessage; if (!is_root_admin) then ( # Get users_backup # users_backup is send from client side to verify number of users prior any add/delete operation # We use the client side number because the server side number could have changed by other user # or other browser window. node users_backup = "v.fp.users_backup"; int number_of_users = num_subnodes(new_users_node); int number_of_users_in_backup = num_subnodes(users_backup); # The users prior any changes on client side # debug_message("#### number_of_users: " . number_of_users . "\n"); # debug_message("#### number_of_users_in_backup: " . number_of_users_in_backup . "\n"); if (number_of_users != number_of_users_in_backup) then ( bool is_add_permission = get_admin_feature_permission(session_id, "users", "add"); bool is_delete_permission = get_admin_feature_permission(session_id, "users", "delete"); # debug_message("#### is_add_permission: " . is_add_permission . "\n"); # debug_message("#### is_delete_permission: " . is_delete_permission . "\n"); if (!is_add_permission and number_of_users > number_of_users_in_backup) then ( error(lang_admin.users.new_users_without_add_permission); ) else if (!is_delete_permission and number_of_users < number_of_users_in_backup) then ( error(lang_admin.users.deleted_users_without_delete_permission); ); ); ); # # # # # # Update new_users_node (add password checksums, remove helper nodes) # # # # # node item; string user_node_name; bool is_new; string password; string password_checksum; int password_creation_time; node original_user; node ori_password_checksum_history; node password_checksum_history; delete_node("v.empty_password_checksum_history"); v.empty_password_checksum_history = ""; foreach item new_users_node ( user_node_name = node_name(item); # KHP 08/Aug/2010 - make sure there is no manipulated "root_admin" node name if (user_node_name ne "root_admin") then ( is_new = @item{"is_new"}; password = @item{"password"}; # # # Handle password # # if (is_new or (password ne "")) then ( # We have a new password or an existing password has been modified password_checksum = md5_digest(@item{"password"}); password_creation_time = now(); # Handle password_checksum_history if (!is_new and original_users_node?{user_node_name}) then ( original_user = original_users_node{user_node_name}; if (original_user?{"password_checksum_history"}) then ( ori_password_checksum_history = original_user{"password_checksum_history"}; ) else ( ori_password_checksum_history = "v.empty_password_checksum_history"; ); ) else ( # Set empty node! ori_password_checksum_history = "v.empty_password_checksum_history"; ); ) else ( # There is no passowrd, so it must be from an existing user debug_message("\n#### get_password from existing original_users_node! \n"); debug_message("\n#### user_node_name: " . user_node_name . "\n"); if (original_users_node?{user_node_name}) then ( original_user = original_users_node{user_node_name}; debug_message("\n#### ORIGINAL USER NODE EXISTS \n"); password_checksum = @original_user{"password_checksum"}; password_creation_time = if (original_user?{"password_creation_time"}) then (@original_user{"password_creation_time"}) else (now()); # Handle password_checksum_history if (original_user?{"password_checksum_history"}) then ( ori_password_checksum_history = original_user{"password_checksum_history"}; ) else ( ori_password_checksum_history = "v.empty_password_checksum_history"; ); ) else ( # This case should not happen but is possible if someone else modified users at the same time debug_message("\n#### ORIGINAL USER NODE DOES NOT EXIST \n"); password_checksum = ""; password_creation_time = now(); ori_password_checksum_history = "v.empty_password_checksum_history"; ); ); debug_message("\n#### is_new: " . is_new . "\n"); debug_message("\n#### password_checksum: " . password_checksum . "\n"); debug_message("\n#### password_creation_time: " . password_creation_time . "\n"); set_subnode_value(item, "password_checksum", password_checksum); set_subnode_value(item, "password_creation_time", password_creation_time); # debug_message("\n#### ori_password_checksum_history:\n" . node_as_string(ori_password_checksum_history) . "\n"); # # Handle the password_checksum_history # if (num_subnodes(ori_password_checksum_history) > 0) then ( # Clone ori_password_checksum_history to item clone_node(ori_password_checksum_history, item . ".password_checksum_history"); password_checksum_history = item{"password_checksum_history"}; # To make sure that the current password_checksum is the last item in the history # we delete the password_checksum from the history and re-add it. if (password_checksum_history?{password_checksum}) then ( # Delete password_checksum in history delete_node(password_checksum_history{password_checksum}); ); ); # New password_checksum_history item or re-add step. # Now re-add the password_checksum in password_checksum_history which # ensures that the current password_checksum is the last item in # the history. item . ".password_checksum_history." . password_checksum = ""; # # KHP-RC # Check the number of tracked password checksums in password_checksum_history. # We may want to remove some of them if the exceed a specific number. # # # Remove helper nodes # delete_node(item{"is_new"}); delete_node(item{"password"}); ) else ( # Insecure, most likely manipulated node name, delete this user delete_node(item); ); ); # # # # Add existing root_admin to new_users_node # # # insert_node(new_users_node, original_users_node{"root_admin"}, 0); # # # # Save new_users_node # # # delete_node("users"); clone_node(new_users_node, "users"); save_node("users"); # # # # Clean system dependencies from deleted users # # # # KHP-RC, clean system from deleted users # # # Check scheduler RBAC integrity # # verify_schedule_rbac(is_enterprise); # # # Response # # "saveChangesResponse()\n"; ) else ( # No permission to access this resource (URL) display_no_permission_html(); ); =}