slp_permission_column !== null) { return $this->slp_permission_column; } if ($this->db->field_exists('permission_level', 'station_logbooks_permissions')) { $this->slp_permission_column = 'permission_level'; return $this->slp_permission_column; } if ($this->db->field_exists('access_level', 'station_logbooks_permissions')) { $this->slp_permission_column = 'access_level'; return $this->slp_permission_column; } // Legacy fallback to avoid hard failures on partially migrated instances. $this->slp_permission_column = 'permission'; return $this->slp_permission_column; } function show_all() { // Get owned logbooks and shared logbooks with access level $user_id = $this->session->userdata('user_id'); $permission_column = $this->get_slp_permission_column(); // If no user is logged in, return empty result if ($user_id === NULL || $user_id === FALSE) { $this->db->from('station_logbooks'); $this->db->where('1 = 0'); // Always false condition return $this->db->get(); } $this->db->select('station_logbooks.*, CASE WHEN station_logbooks.user_id = '.$this->db->escape($user_id).' THEN "owner" ELSE slp.'.$permission_column.' END as access_level', FALSE); $this->db->from('station_logbooks'); $this->db->join('station_logbooks_permissions slp', 'slp.logbook_id = station_logbooks.logbook_id AND slp.user_id = '.$this->db->escape($user_id), 'left'); $this->db->group_start(); $this->db->where('station_logbooks.user_id', $user_id); $this->db->or_where('slp.user_id', $user_id); $this->db->group_end(); $this->db->order_by('station_logbooks.logbook_name', 'ASC'); return $this->db->get(); } function CountAllStationLogbooks() { // count all logbooks $this->db->where('user_id =', NULL); $query = $this->db->get('station_logbooks'); return $query->num_rows(); } function add() { // Create data array with field values $data = array( 'user_id' => $this->session->userdata('user_id'), 'logbook_name' => xss_clean($this->input->post('stationLogbook_Name', true)), ); // Insert Records $this->db->insert('station_logbooks', $data); $logbook_id = $this->db->insert_id(); // check if user has no active logbook yet if ($this->session->userdata('active_station_logbook') === null) { // set logbook active $this->set_logbook_active($logbook_id); // update user session data $CI =& get_instance(); $CI->load->model('user_model'); $CI->user_model->update_session($this->session->userdata('user_id')); } return $logbook_id; } function CreateDefaultLogbook() { // Get the first USER ID from user table in the database $id = $this->db->get("users")->row()->user_id; $data = array( 'user_id' => $id, 'logbook_name' => "Default Logbook", ); $this->db->insert('station_logbooks', $data); $logbook_id = $this->db->insert_id(); $this->set_logbook_active($logbook_id, $id); } function delete($id) { // Clean ID $clean_id = $this->security->xss_clean($id); // do not delete active logbook if ($this->session->userdata('active_station_logbook') === $clean_id) { return; } // Delete logbook $this->db->where('user_id', $this->session->userdata('user_id')); $this->db->where('logbook_id', $id); $this->db->delete('station_logbooks'); } function edit() { $data = array( 'logbook_name' => xss_clean($this->input->post('station_logbook_name', true)), ); $this->db->where('user_id', $this->session->userdata('user_id')); $this->db->where('logbook_id', xss_clean($this->input->post('logbook_id', true))); $this->db->update('station_logbooks', $data); } function set_logbook_active($id, $user_id = null) { // Clean input $cleanId = xss_clean($id); // check if user_id is set if ($user_id === null) { $user_id = $this->session->userdata('user_id'); } else { $user_id = xss_clean($user_id); } // be sure that logbook belongs to user if (!$this->check_logbook_is_accessible($cleanId)) { return; } $data = array( 'active_station_logbook' => $cleanId, ); $this->db->where('user_id', $user_id); $this->db->update('users', $data); } function logbook($id) { // Clean ID $clean_id = $this->security->xss_clean($id); $user_id = $this->session->userdata('user_id'); // If no user is logged in, return empty result if ($user_id === NULL || $user_id === FALSE) { $this->db->from('station_logbooks'); $this->db->where('1 = 0'); // Always false condition return $this->db->get(); } // Get logbook if user owns it OR has shared access $this->db->select('station_logbooks.*'); $this->db->from('station_logbooks'); $this->db->join('station_logbooks_permissions slp', 'slp.logbook_id = station_logbooks.logbook_id AND slp.user_id = '.$this->db->escape($user_id), 'left'); $this->db->where('station_logbooks.logbook_id', $clean_id); $this->db->group_start(); $this->db->where('station_logbooks.user_id', $user_id); $this->db->or_where('slp.user_id', $user_id); $this->db->group_end(); return $this->db->get(); } function find_name($id) { // Clean ID $clean_id = $this->security->xss_clean($id); $this->db->where('user_id', $this->session->userdata('user_id')); $this->db->where('logbook_id', $clean_id); $query = $this->db->get('station_logbooks'); if ($query->num_rows() > 0){ foreach ($query->result() as $row) { return $row->logbook_name; } } else{ return "n/a"; } } // Creates relationship between a logbook and a station location function create_logbook_location_link($logbook_id, $location_id) { // Clean ID $clean_logbook_id = $this->security->xss_clean($logbook_id); $clean_location_id = $this->security->xss_clean($location_id); // be sure that logbook belongs to user if (!$this->check_logbook_is_accessible($clean_logbook_id)) { return; } // be sure that station belongs to user $CI =& get_instance(); $CI->load->model('Stations'); if (!$CI->Stations->check_station_is_accessible($clean_location_id)) { return; } // Create data array with field values $data = array( 'station_logbook_id' => $clean_logbook_id, 'station_location_id' => $clean_location_id, ); // Insert Record $this->db->insert('station_logbooks_relationship', $data); } function relationship_exists($logbook_id, $location_id) { $this->db->where('station_logbook_id', $logbook_id); $this->db->where('station_location_id', $location_id); $query = $this->db->get('station_logbooks_relationship'); if ($query->num_rows() > 0){ return true; } else{ return false; } } function public_slug_exists($slug) { $this->db->where('public_slug', $this->security->xss_clean($slug)); $query = $this->db->get('station_logbooks'); if ($query->num_rows() > 0){ return true; } else{ return false; } } function public_slug_exists_logbook_id($slug) { $this->db->where('public_slug', $this->security->xss_clean($slug)); $query = $this->db->get('station_logbooks'); if ($query->num_rows() > 0){ foreach ($query->result() as $row) { return $row->logbook_id; } } else{ return false; } } function public_slugs_by_user($user_id) { $clean_user_id = $this->security->xss_clean($user_id); $this->db->select('logbook_id, logbook_name, public_slug'); $this->db->from('station_logbooks'); $this->db->where('user_id', $clean_user_id); $this->db->where('public_slug IS NOT NULL', null, false); $this->db->where("public_slug != ''", null, false); $this->db->order_by('logbook_name', 'ASC'); return $this->db->get(); } function public_slugs_accessible_by_user($user_id) { $clean_user_id = $this->security->xss_clean($user_id); $permission_column = $this->get_slp_permission_column(); $this->db->select('station_logbooks.logbook_id, station_logbooks.logbook_name, station_logbooks.public_slug, CASE WHEN station_logbooks.user_id = '.$this->db->escape($clean_user_id).' THEN "owner" ELSE slp.'.$permission_column.' END as access_level', FALSE); $this->db->from('station_logbooks'); $this->db->join('station_logbooks_permissions slp', 'slp.logbook_id = station_logbooks.logbook_id AND slp.user_id = '.$this->db->escape($clean_user_id), 'left'); $this->db->group_start(); $this->db->where('station_logbooks.user_id', $clean_user_id); $this->db->or_where('slp.user_id', $clean_user_id); $this->db->group_end(); $this->db->where('station_logbooks.public_slug IS NOT NULL', null, false); $this->db->where("station_logbooks.public_slug != ''", null, false); $this->db->order_by('station_logbooks.logbook_name', 'ASC'); return $this->db->get(); } function is_public_slug_available($slug) { // Clean public_slug $clean_slug = $this->security->xss_clean($slug); $this->db->where('public_slug', $clean_slug); $query = $this->db->get('station_logbooks'); if ($query->num_rows() > 0){ return false; } else{ return true; } } function save_public_search($public_search, $logbook_id) { $data = array( 'public_search' => xss_clean($public_search), ); $this->db->where('user_id', $this->session->userdata('user_id')); $this->db->where('logbook_id', xss_clean($logbook_id)); $this->db->update('station_logbooks', $data); } function save_public_radio_status($public_radio_status, $logbook_id) { $data = array( 'public_radio_status' => xss_clean($public_radio_status), ); $this->db->where('user_id', $this->session->userdata('user_id')); $this->db->where('logbook_id', xss_clean($logbook_id)); $this->db->update('station_logbooks', $data); } function save_public_slug($public_slug, $logbook_id) { $data = array( 'public_slug' => xss_clean($public_slug), ); $this->db->where('user_id', $this->session->userdata('user_id')); $this->db->where('logbook_id', xss_clean($logbook_id)); $this->db->update('station_logbooks', $data); } function remove_public_slug($logbook_id) { $this->db->set('public_slug', null); $this->db->where('user_id', $this->session->userdata('user_id')); $this->db->where('logbook_id', xss_clean($logbook_id)); $this->db->update('station_logbooks'); } function list_logbook_relationships($logbook_id) { // Check cache first to avoid redundant queries if (isset($this->relationship_cache[$logbook_id])) { return $this->relationship_cache[$logbook_id]; } $relationships_array = array(); $this->db->where('station_logbook_id', $logbook_id); $query = $this->db->get('station_logbooks_relationship'); if ($query->num_rows() > 0){ foreach ($query->result() as $row) { array_push($relationships_array, $row->station_location_id); } // Cache the result $this->relationship_cache[$logbook_id] = $relationships_array; return $relationships_array; } else{ // Cache empty result $this->relationship_cache[$logbook_id] = array(); return array(); } } function list_logbooks_linked($logbook_id) { $relationships_array = array(); $this->db->where('station_logbook_id', $logbook_id); $query = $this->db->get('station_logbooks_relationship'); if ($query->num_rows() > 0){ foreach ($query->result() as $row) { array_push($relationships_array, $row->station_location_id); } $current_user_id = $this->session->userdata('user_id'); // Handle NULL user_id to prevent SQL errors if ($current_user_id === NULL || $current_user_id === FALSE) { $is_shared_case = '1 as is_shared'; // All are shared if no user logged in } else { $is_shared_case = 'CASE WHEN station_profile.user_id = '.$this->db->escape($current_user_id).' THEN 0 ELSE 1 END as is_shared'; } $this->db->select('station_profile.*, dxcc_entities.name as station_country, dxcc_entities.end as end, users.user_callsign as owner_callsign, '.$is_shared_case, FALSE); $this->db->where_in('station_id', $relationships_array); $this->db->join('dxcc_entities','station_profile.station_dxcc = dxcc_entities.adif','left outer'); $this->db->join('users','station_profile.user_id = users.user_id','left'); $query = $this->db->get('station_profile'); return $query; } else{ return false; } } function delete_relationship($logbook_id, $station_id) { // Clean ID $clean_logbook_id = $this->security->xss_clean($logbook_id); $clean_station_id = $this->security->xss_clean($station_id); // be sure that logbook belongs to user if (!$this->check_logbook_is_accessible($clean_logbook_id)) { return; } // be sure that station belongs to user $CI =& get_instance(); $CI->load->model('Stations'); if (!$CI->Stations->check_station_is_accessible($clean_station_id)) { return; } // Delete relationship $this->db->where('station_logbook_id', $clean_logbook_id); $this->db->where('station_location_id', $clean_station_id); $this->db->delete('station_logbooks_relationship'); } public function check_logbook_is_accessible($id, $min_level = 'read') { // First check if user is the owner (existing behavior - highest priority) $permission_column = $this->get_slp_permission_column(); $this->db->select('logbook_id'); $this->db->where('user_id', $this->session->userdata('user_id')); $this->db->where('logbook_id', $id); $query = $this->db->get('station_logbooks'); if ($query->num_rows() == 1) { return true; // Owner always has full access } // Check if user has shared access via permissions table $this->db->select($permission_column.' as permission_level', FALSE); $this->db->where('logbook_id', $id); $this->db->where('user_id', $this->session->userdata('user_id')); $query = $this->db->get('station_logbooks_permissions'); if ($query->num_rows() == 1) { $permission = $query->row()->permission_level; // Map permission levels to hierarchy $levels = array('read' => 1, 'write' => 2, 'admin' => 3); $user_level = isset($levels[$permission]) ? $levels[$permission] : 0; $required_level = isset($levels[$min_level]) ? $levels[$min_level] : 1; return ($user_level >= $required_level); } return false; } public function is_logbook_owner($id) { // Check if current user is the owner of the logbook $this->db->select('logbook_id'); $this->db->where('user_id', $this->session->userdata('user_id')); $this->db->where('logbook_id', $id); $query = $this->db->get('station_logbooks'); return ($query->num_rows() == 1); } public function get_user_permission($logbook_id, $user_id) { // Get the permission level for a specific user on a specific logbook // Returns 'owner', permission level, or null $permission_column = $this->get_slp_permission_column(); // Check if user is owner $this->db->select('logbook_id'); $this->db->where('user_id', $user_id); $this->db->where('logbook_id', $logbook_id); $query = $this->db->get('station_logbooks'); if ($query->num_rows() == 1) { return 'owner'; } // Check permissions table $this->db->select($permission_column.' as permission_level', FALSE); $this->db->where('logbook_id', $logbook_id); $this->db->where('user_id', $user_id); $query = $this->db->get('station_logbooks_permissions'); if ($query->num_rows() == 1) { return $query->row()->permission_level; } return null; } public function add_logbook_permission($logbook_id, $user_id, $permission_level = 'read') { // Add a user to a logbook with specified permission level // Only owner or admin can add users // Returns array with 'success' and 'is_new' keys $permission_column = $this->get_slp_permission_column(); $clean_logbook_id = $this->security->xss_clean($logbook_id); $clean_user_id = $this->security->xss_clean($user_id); $clean_permission = $this->security->xss_clean($permission_level); // Validate permission level $valid_permissions = array('read', 'write', 'admin'); if (!in_array($clean_permission, $valid_permissions)) { return array('success' => false, 'is_new' => false); } // Check if current user has admin rights or is owner if (!$this->is_logbook_owner($clean_logbook_id) && !$this->check_logbook_is_accessible($clean_logbook_id, 'admin')) { return array('success' => false, 'is_new' => false); } // Check if permission already exists $this->db->where('logbook_id', $clean_logbook_id); $this->db->where('user_id', $clean_user_id); $existing = $this->db->get('station_logbooks_permissions'); $is_new = ($existing->num_rows() == 0); if ($existing->num_rows() > 0) { // Update existing permission $data = array( $permission_column => $clean_permission, 'modified' => date('Y-m-d H:i:s'), ); $this->db->where('logbook_id', $clean_logbook_id); $this->db->where('user_id', $clean_user_id); $this->db->update('station_logbooks_permissions', $data); } else { // Insert new permission $data = array( 'logbook_id' => $clean_logbook_id, 'user_id' => $clean_user_id, $permission_column => $clean_permission, ); $this->db->insert('station_logbooks_permissions', $data); } return array('success' => true, 'is_new' => $is_new); } public function remove_logbook_permission($logbook_id, $user_id) { // Remove a user's access to a logbook // Only owner or admin can remove users $clean_logbook_id = $this->security->xss_clean($logbook_id); $clean_user_id = $this->security->xss_clean($user_id); // Check if current user has admin rights or is owner if (!$this->is_logbook_owner($clean_logbook_id) && !$this->check_logbook_is_accessible($clean_logbook_id, 'admin')) { return false; } $this->db->where('logbook_id', $clean_logbook_id); $this->db->where('user_id', $clean_user_id); $this->db->delete('station_logbooks_permissions'); return true; } public function list_logbook_collaborators($logbook_id) { // Get all users with access to a logbook (excluding owner) // Returns array of users with their permission levels $permission_column = $this->get_slp_permission_column(); $clean_logbook_id = $this->security->xss_clean($logbook_id); // Get owner information $this->db->select('station_logbooks.user_id, users.user_callsign, users.user_email, "owner" as permission_level, "" as created_at'); $this->db->from('station_logbooks'); $this->db->join('users', 'users.user_id = station_logbooks.user_id'); $this->db->where('station_logbooks.logbook_id', $clean_logbook_id); $owner_query = $this->db->get(); // Get shared users $this->db->select('slp.user_id, users.user_callsign, users.user_email, slp.'.$permission_column.' as permission_level, slp.created_at', FALSE); $this->db->from('station_logbooks_permissions slp'); $this->db->join('users', 'users.user_id = slp.user_id'); $this->db->where('slp.logbook_id', $clean_logbook_id); $this->db->order_by('slp.created_at', 'DESC'); $shared_query = $this->db->get(); $results = array(); // Add owner first if ($owner_query->num_rows() > 0) { $results[] = $owner_query->row(); } // Add shared users if ($shared_query->num_rows() > 0) { foreach ($shared_query->result() as $row) { $results[] = $row; } } return $results; } public function find_active_station_logbook_from_userid($userid) { $this->db->select('active_station_logbook'); $this->db->where('user_id', $userid); $query = $this->db->get('users'); if ($query->num_rows() > 0){ foreach ($query->result() as $row) { return $row->active_station_logbook; } } else { return 0; } } function public_search_enabled($logbook_id) { $this->db->select('public_search'); $this->db->where('logbook_id', $logbook_id); $query = $this->db->get('station_logbooks'); return $query->result_array()[0]['public_search']; } } ?>