using Spry; using Inversion; using Astralis; using Invercargill; using Invercargill.DataStructures; namespace Spry.Users.Components { /** * UserManagementPage - PageComponent orchestrating all user management components. * * This page provides a complete user management interface that includes: * - Permission check: Only accessible with "user-management" permission * - User list with search, filter, and pagination * - User form modal for create/edit operations * - Status messages (success/error alerts) * * Cross-Component Communication: * - Child components trigger actions via "UserManagementPage:ActionName" pattern * - The page handles these actions and updates child components accordingly * - Uses add_globals_from() to share globals with child components * * Required Permission: "user-management" * * Usage: * // Register as a page: * spry_cfg.add_page(new EndpointRoute("/admin/users")); * * This component uses the inject<> pattern for dependency injection. */ public class UserManagementPage : PageComponent { private PermissionService _permission_service = inject(); private UserService _user_service = inject(); private SessionService _session_service = inject(); private ComponentFactory _factory = inject(); private HttpContext _http_context = inject(); // ========================================================================= // State Properties (must be public for template expression access) // ========================================================================= public string? success_message { get; private set; default = null; } public string? error_message { get; private set; default = null; } public bool access_denied { get; private set; default = false; } // ========================================================================= // Component Implementation // ========================================================================= public override string markup { get { return """ User Management - Admin

User Management

Access Denied

You do not have permission to access this page.

"""; }} public async override void prepare() throws Error { // Check permission var auth_result = yield _session_service.authenticate_request_async(_http_context, _user_service); if (!auth_result.is_authenticated || auth_result.user == null) { access_denied = true; return; } var has_permission = yield _permission_service.has_permission_by_id_async( auth_result.user.id, PermissionService.USER_MANAGEMENT ); if (!has_permission) { access_denied = true; return; } // Share globals with child components var user_list = get_component_child("user-list"); if (user_list != null) { add_globals_from(user_list); } var user_form = get_component_child("user-form"); if (user_form != null) { add_globals_from(user_form); } } public async override void handle_action(string action) throws Error { // Check permission for all actions if (access_denied) { return; } var query = _http_context.request.query_params; switch (action) { case "CreateUser": yield handle_create_user_async(); break; case "EditUser": var user_id = get_query_value(query, "user_id"); yield handle_edit_user_async(user_id); break; case "ToggleActive": var user_id = get_query_value(query, "user_id"); yield handle_toggle_active_async(user_id); break; case "DeleteUser": var user_id = get_query_value(query, "user_id"); yield handle_delete_user_async(user_id); break; } } // ========================================================================= // Action Handlers // ========================================================================= private async void handle_create_user_async() throws Error { var user_form = get_component_child("user-form"); if (user_form != null) { user_form.show_create(); } success_message = null; error_message = null; } private async void handle_edit_user_async(string user_id) throws Error { if (user_id.length == 0) { error_message = "Invalid user ID"; return; } var user = yield _user_service.get_user_async(user_id); if (user == null) { error_message = "User not found"; return; } var user_form = get_component_child("user-form"); if (user_form != null) { user_form.set_user(user); } success_message = null; error_message = null; } private async void handle_toggle_active_async(string user_id) throws Error { // Note: Current User model doesn't have is_active field // This is a placeholder for future implementation error_message = "Toggle active functionality not yet implemented"; success_message = null; // Refresh the list var user_list = get_component_child("user-list"); if (user_list != null) { add_globals_from(user_list); } } private async void handle_delete_user_async(string user_id) throws Error { if (user_id.length == 0) { error_message = "Invalid user ID"; return; } // Prevent self-deletion var auth_result = yield _session_service.authenticate_request_async(_http_context, _user_service); if (auth_result.is_authenticated && auth_result.user != null) { if (auth_result.user.id == user_id) { error_message = "Cannot delete your own account"; success_message = null; // Refresh the list var user_list = get_component_child("user-list"); if (user_list != null) { add_globals_from(user_list); } return; } } // Delete the user try { yield _user_service.delete_user_async(user_id); success_message = "User deleted successfully"; error_message = null; } catch (Error e) { error_message = e.message; success_message = null; } // Refresh the list var user_list = get_component_child("user-list"); if (user_list != null) { add_globals_from(user_list); } } // ========================================================================= // Private Helpers // ========================================================================= private string get_query_value(Catalogue query, string key) { var value = query.get_any_or_default(key); return value != null ? ((!)value).strip() : ""; } } }