cloudlog/application/controllers/User.php
Peter Goodhall 4fe8ca4093 Handle AMSAT override for OscarWatch
Add a persisted `force_amsat` OscarWatch user option, expose it on the user edit form, and keep the AMSAT upload setting in sync when OscarWatch status uploads are enabled. The controller now defaults unchecked values correctly and shows a notice when OscarWatch disables direct AMSAT uploads or when the override keeps both enabled.
2026-08-04 13:15:01 +01:00

1944 lines
75 KiB
PHP

<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
class User extends CI_Controller
{
function __construct()
{
parent::__construct();
$this->lang->load(array(
'account',
'lotw',
'eqsl',
'admin',
));
}
/**
* Index method for the User controller.
* This method loads the user model, authorizes the user, and displays the user accounts.
*/
public function index()
{
$this->load->model('user_model');
// Check if the user is authorized
if (!$this->user_model->authorize(99)) {
$this->session->set_flashdata('notice', 'You\'re not allowed to do that!');
redirect('dashboard');
}
// Get the user accounts
$data['results'] = $this->user_model->users();
// Set the page title
$data['page_title'] = $this->lang->line('admin_user_accounts');
// Load the views
$this->load->view('interface_assets/header', $data);
$this->load->view('user/main');
$this->load->view('interface_assets/footer');
}
function add()
{
$this->load->model('user_model');
if (!$this->user_model->authorize(99)) {
$this->session->set_flashdata('notice', 'You\'re not allowed to do that!');
redirect('dashboard');
}
$data['existing_languages'] = $this->find();
$this->load->model('bands');
$this->load->library('form_validation');
$this->form_validation->set_rules('user_name', 'Username', 'required');
$this->form_validation->set_rules('user_email', 'E-mail', 'required');
$this->form_validation->set_rules('user_password', 'Password', 'required');
$this->form_validation->set_rules('user_type', 'Type', 'required');
$this->form_validation->set_rules('user_firstname', 'First name', 'required');
$this->form_validation->set_rules('user_lastname', 'Last name', 'required');
$this->form_validation->set_rules('user_callsign', 'Callsign', 'trim|required|callback_check_unique_callsign');
$this->form_validation->set_rules('user_locator', 'Locator', 'required');
$this->form_validation->set_rules('user_locator', 'Locator', 'callback_check_locator');
$this->form_validation->set_rules('user_timezone', 'Timezone', 'required');
$data['user_add'] = true;
$data['user_form_action'] = site_url('user/add');
$data['bands'] = $this->bands->get_user_bands();
// Get themes list
$data['themes'] = $this->user_model->getThemes();
// Get timezones
$data['timezones'] = $this->user_model->timezones();
$data['language'] = 'english';
// Set defaults
$data['dashboard_upcoming_dx_card'] = false;
$data['dashboard_dxpedition_sat_worked'] = false;
$data['dashboard_qslcard_card'] = false;
$data['dashboard_eqslcard_card'] = false;
$data['dashboard_lotw_card'] = false;
$data['dashboard_vuccgrids_card'] = false;
$data['dashboard_map_greyline'] = true;
$dashboard_options = $this->user_options_model->get_options('dashboard')->result();
foreach ($dashboard_options as $item) {
$option_name = $item->option_name;
$option_key = $item->option_key;
$option_value = $item->option_value;
if ($option_name == 'dashboard_upcoming_dx_card' && $option_key == 'enabled') {
if ($item->option_value == 'true') {
$data['dashboard_upcoming_dx_card'] = true;
} else {
$data['dashboard_upcoming_dx_card'] = false;
}
}
if ($option_name == 'dashboard_dxpedition_sat_worked' && $option_key == 'enabled') {
if ($item->option_value == 'true') {
$data['dashboard_dxpedition_sat_worked'] = true;
} else {
$data['dashboard_dxpedition_sat_worked'] = false;
}
}
if ($option_name == 'dashboard_qslcards_card' && $option_key == 'enabled') {
if ($item->option_value == 'true') {
$data['dashboard_qslcard_card'] = true;
} else {
$data['dashboard_qslcard_card'] = false;
}
}
if ($option_name == 'dashboard_eqslcards_card' && $option_key == 'enabled') {
if ($item->option_value == 'true') {
$data['dashboard_eqslcard_card'] = true;
} else {
$data['dashboard_eqslcard_card'] = false;
}
}
if ($option_name == 'dashboard_lotw_card' && $option_key == 'enabled') {
if ($item->option_value == 'true') {
$data['dashboard_lotw_card'] = true;
} else {
$data['dashboard_lotw_card'] = false;
}
}
if ($option_name == 'dashboard_vuccgrids_card' && $option_key == 'enabled') {
if ($item->option_value == 'true') {
$data['dashboard_vuccgrids_card'] = true;
} else {
$data['dashboard_vuccgrids_card'] = false;
}
}
if ($option_name == 'dashboard_map_greyline' && $option_key == 'enabled') {
if ($item->option_value == 'true') {
$data['dashboard_map_greyline'] = true;
} else {
$data['dashboard_map_greyline'] = false;
}
}
}
if ($this->form_validation->run() == FALSE) {
$data['page_title'] = "Add User";
$data['measurement_base'] = $this->config->item('measurement_base');
$this->load->view('interface_assets/header', $data);
if ($this->input->post('user_name')) {
$data['user_name'] = $this->input->post('user_name');
$data['user_email'] = $this->input->post('user_email');
$data['user_password'] = $this->input->post('user_password');
$data['user_type'] = $this->input->post('user_type');
$data['user_firstname'] = $this->input->post('user_firstname');
$data['user_lastname'] = $this->input->post('user_lastname');
$data['user_callsign'] = $this->input->post('user_callsign');
$data['user_locator'] = $this->input->post('user_locator');
$data['user_timezone'] = $this->input->post('user_timezone');
$data['user_measurement_base'] = $this->input->post('user_measurement_base');
$data['user_stylesheet'] = $this->input->post('user_stylesheet');
$data['user_qth_lookup'] = $this->input->post('user_qth_lookup');
$data['user_sota_lookup'] = $this->input->post('user_sota_lookup');
$data['user_wwff_lookup'] = $this->input->post('user_wwff_lookup');
$data['user_pota_lookup'] = $this->input->post('user_pota_lookup');
$data['user_show_notes'] = $this->input->post('user_show_notes');
$data['user_column1'] = $this->input->post('user_column1');
$data['user_column2'] = $this->input->post('user_column2');
$data['user_column3'] = $this->input->post('user_column3');
$data['user_column4'] = $this->input->post('user_column4');
$data['user_column5'] = $this->input->post('user_column5');
$data['user_show_profile_image'] = $this->input->post('user_show_profile_image');
$data['user_previous_qsl_type'] = $this->input->post('user_previous_qsl_type');
$data['user_amsat_status_upload'] = $this->input->post('user_amsat_status_upload');
$data['user_oscarwatch_status_upload'] = $this->input->post('user_oscarwatch_status_upload');
$data['user_mastodon_url'] = $this->input->post('user_mastodon_url');
$data['user_default_band'] = $this->input->post('user_default_band');
$data['user_default_confirmation'] = ($this->input->post('user_default_confirmation_qsl') !== null ? 'Q' : '') . ($this->input->post('user_default_confirmation_lotw') !== null ? 'L' : '') . ($this->input->post('user_default_confirmation_eqsl') !== null ? 'E' : '') . ($this->input->post('user_default_confirmation_qrz') !== null ? 'Z' : '');
$data['user_qso_end_times'] = $this->input->post('user_qso_end_times');
$data['user_quicklog'] = $this->input->post('user_quicklog');
$data['user_quicklog_enter'] = $this->input->post('user_quicklog_enter');
$data['user_hamsat_key'] = $this->input->post('user_hamsat_key');
$data['user_hamsat_workable_only'] = $this->input->post('user_hamsat_workable_only');
$data['user_oscarwatch_token'] = $this->input->post('user_oscarwatch_token');
$data['user_winkey'] = $this->input->post('user_winkey');
$data['user_winkey_websocket'] = $this->input->post('user_winkey_websocket');
$data['user_remote_operation'] = $this->input->post('user_remote_operation');
$data['language'] = $this->input->post('language');
$this->load->view('user/edit', $data);
} else {
$this->load->view('user/edit', $data);
}
$this->load->view('interface_assets/footer');
} else {
switch ($this->user_model->add(
$this->input->post('user_name'),
$this->input->post('user_password'),
$this->input->post('user_email'),
$this->input->post('user_type'),
$this->input->post('user_firstname'),
$this->input->post('user_lastname'),
$this->input->post('user_callsign'),
$this->input->post('user_locator'),
$this->input->post('user_timezone'),
$this->input->post('user_measurement_base'),
$this->input->post('user_date_format'),
$this->input->post('user_stylesheet'),
$this->input->post('user_qth_lookup'),
$this->input->post('user_sota_lookup'),
$this->input->post('user_wwff_lookup'),
$this->input->post('user_pota_lookup'),
$this->input->post('user_show_notes'),
$this->input->post('user_column1'),
$this->input->post('user_column2'),
$this->input->post('user_column3'),
$this->input->post('user_column4'),
$this->input->post('user_column5'),
$this->input->post('user_show_profile_image'),
$this->input->post('user_previous_qsl_type'),
$this->input->post('user_amsat_status_upload'),
$this->input->post('user_mastodon_url'),
$this->input->post('user_default_band'),
($this->input->post('user_default_confirmation_qsl') !== null ? 'Q' : '') . ($this->input->post('user_default_confirmation_lotw') !== null ? 'L' : '') . ($this->input->post('user_default_confirmation_eqsl') !== null ? 'E' : '') . ($this->input->post('user_default_confirmation_qrz') !== null ? 'Z' : ''),
$this->input->post('user_qso_end_times'),
$this->input->post('user_quicklog'),
$this->input->post('user_quicklog_enter'),
$this->input->post('language'),
$this->input->post('user_hamsat_key'),
$this->input->post('user_hamsat_workable_only'),
$this->input->post('user_callbook_type'),
$this->input->post('user_callbook_username'),
$this->input->post('user_callbook_password'),
$this->input->post('user_winkey'),
$this->input->post('user_winkey_websocket'),
$this->input->post('user_remote_operation')
)) {
// Check for errors
case EUSERNAMEEXISTS:
$data['username_error'] = 'Username <b>' . $this->input->post('user_name') . '</b> already in use!';
break;
case EEMAILEXISTS:
$data['email_error'] = 'E-mail address <b>' . $this->input->post('user_email') . '</b> already in use!';
break;
case ECALLSIGNEXISTS:
$data['callsign_error'] = 'Callsign <b>' . strtoupper($this->input->post('user_callsign')) . '</b> already in use!';
break;
case EPASSWORDINVALID:
$data['password_error'] = 'Invalid password!';
break;
// All okay, return to user screen
case OK:
// Send welcome email to new user if checkbox is checked
if ($this->input->post('send_welcome_email') == '1') {
$this->send_welcome_email(
$this->input->post('user_email'),
$this->input->post('user_name'),
$this->input->post('user_password'),
$this->input->post('user_firstname'),
$this->input->post('user_lastname'),
$this->input->post('user_callsign')
);
}
$this->session->set_flashdata('notice', 'User ' . $this->input->post('user_name') . ' added');
redirect('user');
return;
}
$data['page_title'] = "Users";
$this->load->view('interface_assets/header', $data);
$data['user_name'] = $this->input->post('user_name');
$data['user_email'] = $this->input->post('user_email');
$data['user_password'] = $this->input->post('user_password');
$data['user_type'] = $this->input->post('user_type');
$data['user_firstname'] = $this->input->post('user_firstname');
$data['user_lastname'] = $this->input->post('user_lastname');
$data['user_callsign'] = $this->input->post('user_callsign');
$data['user_locator'] = $this->input->post('user_locator');
$data['user_measurement_base'] = $this->input->post('user_measurement_base');
$data['user_stylesheet'] = $this->input->post('user_stylesheet');
$data['user_qth_lookup'] = $this->input->post('user_qth_lookup');
$data['user_sota_lookup'] = $this->input->post('user_sota_lookup');
$data['user_wwff_lookup'] = $this->input->post('user_wwff_lookup');
$data['user_pota_lookup'] = $this->input->post('user_pota_lookup');
$data['user_show_notes'] = $this->input->post('user_show_notes');
$data['user_column1'] = $this->input->post('user_column1');
$data['user_column2'] = $this->input->post('user_column2');
$data['user_column3'] = $this->input->post('user_column3');
$data['user_column4'] = $this->input->post('user_column4');
$data['user_column5'] = $this->input->post('user_column5');
$data['user_show_profile_image'] = $this->input->post('user_show_profile_image');
$data['user_previous_qsl_type'] = $this->input->post('user_previous_qsl_type');
$data['user_amsat_status_upload'] = $this->input->post('user_amsat_status_upload');
$data['user_mastodon_url'] = $this->input->post('user_mastodon_url');
$data['user_default_band'] = $this->input->post('user_default_band');
$data['user_default_confirmation'] = ($this->input->post('user_default_confirmation_qsl') !== null ? 'Q' : '') . ($this->input->post('user_default_confirmation_lotw') !== null ? 'L' : '') . ($this->input->post('user_default_confirmation_eqsl') !== null ? 'E' : '') . ($this->input->post('user_default_confirmation_qrz') !== null ? 'Z' : '');
$data['user_qso_end_times'] = $this->input->post('user_qso_end_times');
$data['user_quicklog'] = $this->input->post('user_quicklog');
$data['user_quicklog_enter'] = $this->input->post('user_quicklog_enter');
$data['language'] = $this->input->post('language');
$this->load->view('user/edit', $data);
$this->load->view('interface_assets/footer');
}
}
function find()
{
$existing_langs = array();
$lang_path = APPPATH . 'language';
$results = scandir($lang_path);
foreach ($results as $result) {
if ($result === '.' or $result === '..') continue;
if (is_dir(APPPATH . 'language' . '/' . $result)) {
$dirs[] = $result;
}
}
return $dirs;
}
function edit()
{
$this->load->model('user_model');
if (($this->session->userdata('user_id') == '') || ((!$this->user_model->authorize(99)) && ($this->session->userdata('user_id') != $this->uri->segment(3)))) {
$this->session->set_flashdata('notice', 'You\'re not allowed to do that!');
redirect('dashboard');
}
$query = $this->user_model->get_by_id($this->uri->segment(3));
$data['existing_languages'] = $this->find();
$this->load->model('bands');
$this->load->library('form_validation');
$this->form_validation->set_rules('user_name', 'Username', 'required|xss_clean');
$this->form_validation->set_rules('user_email', 'E-mail', 'required|xss_clean');
if ($this->session->userdata('user_type') == 99) {
$this->form_validation->set_rules('user_type', 'Type', 'required|xss_clean|callback_check_last_admin_role');
}
$this->form_validation->set_rules('user_firstname', 'First name', 'required|xss_clean');
$this->form_validation->set_rules('user_lastname', 'Last name', 'required|xss_clean');
$this->form_validation->set_rules('user_callsign', 'Callsign', 'trim|required|xss_clean|callback_check_unique_callsign');
$this->form_validation->set_rules('user_clublog_name', 'Clublog Email', 'callback_check_clublog_email');
$this->form_validation->set_rules('user_locator', 'Locator', 'callback_check_locator');
$this->form_validation->set_rules('user_timezone', 'Timezone', 'required');
$data['user_form_action'] = site_url('user/edit') . "/" . $this->uri->segment(3);;
$data['bands'] = $this->bands->get_user_bands();
// Get themes list
$data['themes'] = $this->user_model->getThemes();
// Get timezones
$data['timezones'] = $this->user_model->timezones();
if ($this->form_validation->run() == FALSE) {
$data['page_title'] = "Edit User";
$q = $query->row();
$data['id'] = $q->user_id;
if ($this->input->post('user_name', true)) {
$data['user_name'] = $this->input->post('user_name', true);
} else {
$data['user_name'] = $q->user_name;
}
if ($this->input->post('user_email', true)) {
$data['user_email'] = $this->input->post('user_email', true);
} else {
$data['user_email'] = $q->user_email;
}
if ($this->input->post('user_password', true)) {
$data['user_password'] = $this->input->post('user_password', true);
} else {
$data['user_password'] = $q->user_password;
}
if ($this->input->post('user_type', true)) {
$data['user_type'] = $this->input->post('user_type', true);
} else {
$data['user_type'] = $q->user_type;
}
if ($this->input->post('user_callsign', true)) {
$data['user_callsign'] = $this->input->post('user_callsign', true);
} else {
$data['user_callsign'] = $q->user_callsign;
}
if ($this->input->post('user_locator', true)) {
$data['user_locator'] = $this->input->post('user_locator', true);
} else {
$data['user_locator'] = $q->user_locator;
}
if ($this->input->post('user_firstname', true)) {
$data['user_firstname'] = $this->input->post('user_firstname', true);
} else {
$data['user_firstname'] = $q->user_firstname;
}
if ($this->input->post('user_lastname', true)) {
$data['user_lastname'] = $this->input->post('user_lastname', true);
} else {
$data['user_lastname'] = $q->user_lastname;
}
if ($this->input->post('user_callsign', true)) {
$data['user_callsign'] = $this->input->post('user_callsign', true);
} else {
$data['user_callsign'] = $q->user_callsign;
}
if ($this->input->post('user_locator', true)) {
$data['user_locator'] = $this->input->post('user_locator', true);
} else {
$data['user_locator'] = $q->user_locator;
}
if ($this->input->post('user_timezone')) {
$data['user_timezone'] = $this->input->post('user_timezone', true);
} else {
$data['user_timezone'] = $q->user_timezone;
}
if ($this->input->post('user_lotw_name')) {
$data['user_lotw_name'] = $this->input->post('user_lotw_name', true);
} else {
$data['user_lotw_name'] = $q->user_lotw_name;
}
if ($this->input->post('user_clublog_name')) {
$data['user_clublog_name'] = $this->input->post('user_clublog_name', true);
} else {
$data['user_clublog_name'] = $q->user_clublog_name;
}
if ($this->input->post('user_clublog_password')) {
$data['user_clublog_password'] = $this->input->post('user_clublog_password', true);
} else {
$data['user_clublog_password'] = $q->user_clublog_password;
}
if ($this->input->post('user_lotw_password')) {
$data['user_lotw_password'] = $this->input->post('user_lotw_password', true);
} else {
$data['user_lotw_password'] = $q->user_lotw_password;
}
if ($this->input->post('user_eqsl_name')) {
$data['user_eqsl_name'] = $this->input->post('user_eqsl_name', true);
} else {
$data['user_eqsl_name'] = $q->user_eqsl_name;
}
if ($this->input->post('user_eqsl_password')) {
$data['user_eqsl_password'] = $this->input->post('user_eqsl_password', true);
} else {
$data['user_eqsl_password'] = null;
}
if ($this->input->post('user_measurement_base')) {
$data['user_measurement_base'] = $this->input->post('user_measurement_base', true);
} else {
$data['user_measurement_base'] = $q->user_measurement_base;
}
if ($this->input->post('user_date_format')) {
$data['user_date_format'] = $this->input->post('user_date_format', true);
} else {
$data['user_date_format'] = $q->user_date_format;
}
if ($this->input->post('language')) {
$data['language'] = $this->input->post('language', true);
} else {
$data['language'] = $q->language;
}
if ($this->input->post('user_stylesheet')) {
$data['user_stylesheet'] = $this->input->post('user_stylesheet', true);
} else {
$data['user_stylesheet'] = $q->user_stylesheet;
}
if ($this->input->post('user_qth_lookup')) {
$data['user_qth_lookup'] = $this->input->post('user_qth_lookup', true);
} else {
$data['user_qth_lookup'] = $q->user_qth_lookup;
}
if ($this->input->post('user_sota_lookup')) {
$data['user_sota_lookup'] = $this->input->post('user_sota_lookup', true);
} else {
$data['user_sota_lookup'] = $q->user_sota_lookup;
}
if ($this->input->post('user_wwff_lookup')) {
$data['user_wwff_lookup'] = $this->input->post('user_wwff_lookup', true);
} else {
$data['user_wwff_lookup'] = $q->user_wwff_lookup;
}
if ($this->input->post('user_pota_lookup')) {
$data['user_pota_lookup'] = $this->input->post('user_pota_lookup', true);
} else {
$data['user_pota_lookup'] = $q->user_pota_lookup;
}
if ($this->input->post('user_show_notes')) {
$data['user_show_notes'] = $this->input->post('user_show_notes', true);
} else {
$data['user_show_notes'] = $q->user_show_notes;
}
if ($this->input->post('user_qso_end_times')) {
$data['user_qso_end_times'] = $this->input->post('user_qso_end_times', true);
} else {
$data['user_qso_end_times'] = $q->user_qso_end_times;
}
if ($this->input->post('user_quicklog')) {
$data['user_quicklog'] = $this->input->post('user_quicklog', true);
} else {
$data['user_quicklog'] = $q->user_quicklog;
}
if ($this->input->post('user_quicklog_enter')) {
$data['user_quicklog_enter'] = $this->input->post('user_quicklog_enter', true);
} else {
$data['user_quicklog_enter'] = $q->user_quicklog_enter;
}
if ($this->input->post('user_show_profile_image')) {
$data['user_show_profile_image'] = $this->input->post('user_show_profile_image', false);
} else {
$data['user_show_profile_image'] = $q->user_show_profile_image;
}
if ($this->input->post('user_previous_qsl_type')) {
$data['user_previous_qsl_type'] = $this->input->post('user_previous_qsl_type', false);
} else {
$data['user_previous_qsl_type'] = $q->user_previous_qsl_type;
}
if ($this->input->post('user_amsat_status_upload')) {
$data['user_amsat_status_upload'] = $this->input->post('user_amsat_status_upload', false);
} else {
$data['user_amsat_status_upload'] = $q->user_amsat_status_upload;
}
if ($this->input->post('user_mastodon_url')) {
$data['user_mastodon_url'] = $this->input->post('user_mastodon_url', false);
} else {
$data['user_mastodon_url'] = $q->user_mastodon_url;
}
if ($this->input->post('user_default_band')) {
$data['user_default_band'] = $this->input->post('user_default_band', false);
} else {
$data['user_default_band'] = $q->user_default_band;
}
if ($this->input->post('user_default_confirmation')) {
$data['user_default_confirmation'] = ($this->input->post('user_default_confirmation_qsl') !== null ? 'Q' : '') . ($this->input->post('user_default_confirmation_lotw') !== null ? 'L' : '') . ($this->input->post('user_default_confirmation_eqsl') !== null ? 'E' : '') . ($this->input->post('user_default_confirmation_qrz') !== null ? 'Z' : '');
} else {
$data['user_default_confirmation'] = $q->user_default_confirmation;
}
if ($this->input->post('user_column1')) {
$data['user_column1'] = $this->input->post('user_column1', true);
} else {
$data['user_column1'] = $q->user_column1;
}
if ($this->input->post('user_column2')) {
$data['user_column2'] = $this->input->post('user_column2', true);
} else {
$data['user_column2'] = $q->user_column2;
}
if ($this->input->post('user_column3')) {
$data['user_column3'] = $this->input->post('user_column3', true);
} else {
$data['user_column3'] = $q->user_column3;
}
if ($this->input->post('user_column4')) {
$data['user_column4'] = $this->input->post('user_column4', true);
} else {
$data['user_column4'] = $q->user_column4;
}
if ($this->input->post('user_column5')) {
$data['user_column5'] = $this->input->post('user_column5', true);
} else {
$data['user_column5'] = $q->user_column5;
}
if ($this->input->post('user_winkey')) {
$data['user_winkey'] = $this->input->post('user_winkey', true);
} else {
$data['user_winkey'] = $q->winkey;
}
if ($this->input->post('user_winkey_websocket')) {
$data['user_winkey_websocket'] = $this->input->post('user_winkey_websocket', true);
} else {
$data['user_winkey_websocket'] = $q->winkey_websocket;
}
if ($this->input->post('user_remote_operation')) {
$data['user_remote_operation'] = $this->input->post('user_remote_operation', true);
} else {
$remote_operation_option = $this->user_options_model->get_options(
'remote_operation',
array('option_name' => 'enabled', 'option_key' => 'value'),
$this->uri->segment(3)
)->row();
$data['user_remote_operation'] = isset($remote_operation_option->option_value)
? (((string)$remote_operation_option->option_value === 'true' || (string)$remote_operation_option->option_value === '1') ? 1 : 0)
: (isset($q->remote_operation) ? $q->remote_operation : 0);
}
$this->load->model('user_options_model');
$callbook_type_object = $this->user_options_model->get_options('callbook')->result();
if ($this->input->post('user_callbook_type', true)) {
$data['user_callbook_type'] = $this->input->post('user_callbook_type', true);
} else {
if (isset($callbook_type_object[1]->option_value)) {
$data['user_callbook_type'] = $callbook_type_object[1]->option_value;
} else {
$data['user_callbook_type'] = "";
}
}
// Handle user_callbook_username
if ($this->input->post('user_callbook_username', true)) {
$data['user_callbook_username'] = $this->input->post('user_callbook_username', true);
} else {
if (isset($callbook_type_object[2]->option_value)) {
$data['user_callbook_username'] = $callbook_type_object[2]->option_value;
} else {
$data['user_callbook_username'] = "";
}
}
// Handle user_callbook_password
if ($this->input->post('user_callbook_password', true)) {
$data['user_callbook_password'] = $this->input->post('user_callbook_password', true);
} else {
if (isset($callbook_type_object[0]->option_value)) {
$data['user_callbook_password'] = $callbook_type_object[0]->option_value;
} else {
$data['user_callbook_password'] = "";
}
}
$this->load->model('user_options_model');
$edited_user_id = $q->user_id ?? $this->session->userdata('user_id');
$hamsat_user_object = $this->user_options_model->get_options('hamsat', null, $edited_user_id)->result();
$oscarwatch_token_object = $this->user_options_model->get_options('oscarwatch', array('option_name' => 'api_token', 'option_key' => 'value'), $edited_user_id)->result();
$oscarwatch_status_option = $this->user_options_model->get_options('oscarwatch', array('option_name' => 'status_upload', 'option_key' => 'enabled'), $edited_user_id)->row();
$oscarwatch_force_amsat_option = $this->user_options_model->get_options('oscarwatch', array('option_name' => 'force_amsat', 'option_key' => 'enabled'), $edited_user_id)->row();
if ($this->input->post('user_hamsat_key', true)) {
$data['user_hamsat_key'] = $this->input->post('user_hamsat_key', true);
} else {
// get $q->hamsat_key if its set if not null
if (isset($hamsat_user_object[0]->option_value)) {
$data['user_hamsat_key'] = $hamsat_user_object[0]->option_value;
} else {
$data['user_hamsat_key'] = "";
}
}
if ($this->input->post('user_hamsat_workable_only')) {
$data['user_hamsat_workable_only'] = $this->input->post('user_hamsat_workable_only', false);
} else {
if (isset($hamsat_user_object[1]->option_value)) {
$data['user_hamsat_workable_only'] = $hamsat_user_object[1]->option_value;
} else {
$data['user_hamsat_workable_only'] = "";
}
}
if ($this->input->post('user_oscarwatch_token', true)) {
$data['user_oscarwatch_token'] = $this->input->post('user_oscarwatch_token', true);
} else {
if (isset($oscarwatch_token_object[0]->option_value)) {
$data['user_oscarwatch_token'] = $oscarwatch_token_object[0]->option_value;
} else {
$data['user_oscarwatch_token'] = "";
}
}
if ($this->input->post('user_oscarwatch_status_upload') !== null) {
$data['user_oscarwatch_status_upload'] = $this->input->post('user_oscarwatch_status_upload', false);
} else {
$data['user_oscarwatch_status_upload'] = isset($oscarwatch_status_option->option_value) ? $oscarwatch_status_option->option_value : '0';
}
if ($this->input->post('user_force_amsat_status_upload') !== null) {
$data['user_force_amsat_status_upload'] = $this->input->post('user_force_amsat_status_upload', false);
} else {
$data['user_force_amsat_status_upload'] = isset($oscarwatch_force_amsat_option->option_value) ? $oscarwatch_force_amsat_option->option_value : '0';
}
// Set defaults
$data['dashboard_upcoming_dx_card'] = false;
$data['dashboard_dxpedition_sat_worked'] = false;
$data['dashboard_qslcard_card'] = false;
$data['dashboard_eqslcard_card'] = false;
$data['dashboard_lotw_card'] = false;
$data['dashboard_vuccgrids_card'] = false;
$data['dashboard_map_greyline'] = true;
$data['menu_show_qsl_cards'] = true;
$data['menu_show_sstv_images'] = false;
$dashboard_options = $this->user_options_model->get_options('dashboard')->result();
foreach ($dashboard_options as $item) {
$option_name = $item->option_name;
$option_key = $item->option_key;
$option_value = $item->option_value;
if ($option_name == 'dashboard_upcoming_dx_card' && $option_key == 'enabled') {
if ($item->option_value == 'true') {
$data['dashboard_upcoming_dx_card'] = true;
} else {
$data['dashboard_upcoming_dx_card'] = false;
}
}
if ($option_name == 'dashboard_dxpedition_sat_worked' && $option_key == 'enabled') {
if ($item->option_value == 'true') {
$data['dashboard_dxpedition_sat_worked'] = true;
} else {
$data['dashboard_dxpedition_sat_worked'] = false;
}
}
if ($option_name == 'dashboard_qslcards_card' && $option_key == 'enabled') {
if ($item->option_value == 'true') {
$data['dashboard_qslcard_card'] = true;
} else {
$data['dashboard_qslcard_card'] = false;
}
}
if ($option_name == 'dashboard_eqslcards_card' && $option_key == 'enabled') {
if ($item->option_value == 'true') {
$data['dashboard_eqslcard_card'] = true;
} else {
$data['dashboard_eqslcard_card'] = false;
}
}
if ($option_name == 'dashboard_lotw_card' && $option_key == 'enabled') {
if ($item->option_value == 'true') {
$data['dashboard_lotw_card'] = true;
} else {
$data['dashboard_lotw_card'] = false;
}
}
if ($option_name == 'dashboard_vuccgrids_card' && $option_key == 'enabled') {
if ($item->option_value == 'true') {
$data['dashboard_vuccgrids_card'] = true;
} else {
$data['dashboard_vuccgrids_card'] = false;
}
}
if ($option_name == 'dashboard_map_greyline' && $option_key == 'enabled') {
if ($item->option_value == 'true') {
$data['dashboard_map_greyline'] = true;
} else {
$data['dashboard_map_greyline'] = false;
}
}
}
$menu_options = $this->user_options_model->get_options('menu')->result();
foreach ($menu_options as $item) {
if ($item->option_name == 'show_qsl_cards' && $item->option_key == 'enabled') {
$data['menu_show_qsl_cards'] = ($item->option_value == 'true');
}
if ($item->option_name == 'show_sstv_images' && $item->option_key == 'enabled') {
$data['menu_show_sstv_images'] = ($item->option_value == 'true');
}
}
// [QSO Form] Load field visibility preferences
$data['qso_fields'] = [
'rst' => true, 'name' => true, 'qth' => true, 'locator' => true, 'comment' => true,
'station_tab' => true, 'freq_tx' => true, 'freq_rx' => true, 'band_rx' => true,
'transmit_power' => true, 'operator_callsign' => true,
'general_tab' => true, 'iota' => true, 'sota' => true, 'wwff' => true, 'pota' => true,
'sig' => true, 'dok' => true, 'usa_state' => true,
'satellite_tab' => true, 'notes_tab' => true, 'qsl_tab' => true,
'dxcluster_tab' => true,
];
$qso_form_opts = $this->user_options_model->get_options('qso_form')->result();
foreach ($qso_form_opts as $qfo_item) {
if ($qfo_item->option_key == 'visible' && array_key_exists($qfo_item->option_name, $data['qso_fields'])) {
$data['qso_fields'][$qfo_item->option_name] = ($qfo_item->option_value == 'true');
}
}
// [MAP Custom] GET user options //
$this->load->model('user_options_model');
$options_object = $this->user_options_model->get_options('map_custom')->result();
if (count($options_object) > 0) {
foreach ($options_object as $row) {
if ($row->option_name == 'icon') {
$option_value = json_decode($row->option_value, true);
foreach ($option_value as $ktype => $vtype) {
if ($this->input->post('user_map_' . $row->option_key . '_icon')) {
$data['user_map_' . $row->option_key . '_' . $ktype] = $this->input->post('user_map_' . $row->option_key . '_' . $ktype, true);
} else {
$data['user_map_' . $row->option_key . '_' . $ktype] = $vtype;
}
}
} else {
$data['user_map_' . $row->option_name . '_' . $row->option_key] = $row->option_value;
}
}
} else {
$data['user_map_qso_icon'] = "fas fa-dot-circle";
$data['user_map_qso_color'] = "#FF0000";
$data['user_map_station_icon'] = "0";
$data['user_map_station_color'] = "#0000FF";
$data['user_map_qsoconfirm_icon'] = "0";
$data['user_map_qsoconfirm_color'] = "#00AA00";
$data['user_map_gridsquare_show'] = "0";
}
$data['map_icon_select'] = array(
'station' => array('0', 'fas fa-home', 'fas fa-broadcast-tower', 'fas fa-user', 'fas fa-dot-circle'),
'qso' => array('fas fa-broadcast-tower', 'fas fa-user', 'fas fa-dot-circle'),
'qsoconfirm' => array('0', 'fas fa-broadcast-tower', 'fas fa-user', 'fas fa-dot-circle', 'fas fa-check-circle')
);
$this->load->view('interface_assets/header', $data);
$this->load->view('user/edit', $data);
$this->load->view('interface_assets/footer');
} else {
unset($data);
$post_data = $this->input->post();
if (!isset($post_data['user_winkey'])) {
$post_data['user_winkey'] = '0';
}
if (!isset($post_data['user_winkey_websocket'])) {
$post_data['user_winkey_websocket'] = '0';
}
if (!isset($post_data['user_remote_operation'])) {
$post_data['user_remote_operation'] = '0';
}
if (!isset($post_data['user_amsat_status_upload'])) {
$post_data['user_amsat_status_upload'] = '0';
}
if (!isset($post_data['user_oscarwatch_status_upload'])) {
$post_data['user_oscarwatch_status_upload'] = '0';
}
if (!isset($post_data['user_force_amsat_status_upload'])) {
$post_data['user_force_amsat_status_upload'] = '0';
}
$oscarwatch_enabled = ((string)$post_data['user_oscarwatch_status_upload'] === '1');
$force_amsat_enabled = ((string)$post_data['user_force_amsat_status_upload'] === '1');
$oscarwatch_notice_message = '';
if ($oscarwatch_enabled) {
if (!$force_amsat_enabled) {
$post_data['user_amsat_status_upload'] = '0';
$oscarwatch_notice_message = 'AMSAT Status Upload in Cloudlog was disabled because OscarWatch Status Upload is enabled. OscarWatch also forwards to AMSAT Status unless you disable forwarding in your OscarWatch account.';
} else {
$oscarwatch_notice_message = 'OscarWatch Status Upload is enabled and AMSAT Status Upload remains enabled by your override. OscarWatch also forwards to AMSAT Status unless you disable forwarding in your OscarWatch account.';
}
}
switch ($this->user_model->edit($post_data)) {
// Check for errors
case EUSERNAMEEXISTS:
$data['username_error'] = 'Username <b>' . $this->input->post('user_name', true) . '</b> already in use!';
break;
case EEMAILEXISTS:
$data['email_error'] = 'E-mail address <b>' . $this->input->post('user_email', true) . '</b> already in use!';
break;
case ECALLSIGNEXISTS:
$data['callsign_error'] = 'Callsign <b>' . strtoupper($this->input->post('user_callsign', true)) . '</b> already in use!';
break;
case ELASTADMIN:
$data['usertype_error'] = 'At least one admin account must remain. You cannot change the only admin to another role.';
break;
case EPASSWORDINVALID:
$data['password_error'] = 'Invalid password!';
break;
// All okay, return to user screen
case OK:
if ($this->session->userdata('user_id') == $this->uri->segment(3)) { // Editing own User? Set cookie!
$cookie = array(
'name' => 'language',
'value' => $this->input->post('language', true),
'expire' => time() + 1000,
'secure' => FALSE
);
$this->input->set_cookie($cookie);
}
if ($this->session->userdata('user_id') == $this->input->post('id', true)) {
// Handle user_callbook_password
if (isset($_POST['user_callbook_password']) && !empty($_POST['user_callbook_password'])) {
// Handle user_callbook_type
if (isset($_POST['user_callbook_type'])) {
$this->user_options_model->set_option('callbook', 'callbook_type', array('value' => $_POST['user_callbook_type']));
} else {
$this->user_options_model->set_option('callbook', 'callbook_type', array('value' => ''));
}
// Handle user_callbook_username
if (isset($_POST['user_callbook_username'])) {
$this->user_options_model->set_option('callbook', 'callbook_username', array('value' => $_POST['user_callbook_username']));
} else {
$this->user_options_model->set_option('callbook', 'callbook_username', array('value' => ''));
}
// Load the encryption library
$this->load->library('encryption');
// Encrypt the password
$encrypted_password = $this->encryption->encrypt($_POST['user_callbook_password']);
// Save the encrypted password
$this->user_options_model->set_option('callbook', 'callbook_password', array('value' => $encrypted_password));
// if callbook type is QRZ
if ($_POST['user_callbook_type'] == 'QRZ') {
// Lookup using QRZ
$this->load->library('qrz');
$qrz_session_key = $this->qrz->session($_POST['user_callbook_username'], $_POST['user_callbook_password']);
$this->session->set_userdata('qrz_session_key', $qrz_session_key);
} elseif ($_POST['user_callbook_type'] == "HamQTH") {
$this->load->library('hamqth');
$hamqth_session_key = $this->hamqth->session($_POST['user_callbook_username'], $_POST['user_callbook_password']);
$this->session->set_userdata('hamqth_session_key', $hamqth_session_key);
}
// Update Session data
$this->session->set_userdata('callbook_type', $_POST['user_callbook_type']);
$this->session->set_userdata('callbook_username', $_POST['user_callbook_username']);
$this->session->set_userdata('callbook_password', $encrypted_password);
}
if (isset($_POST['user_dashboard_enable_dxpedition_card'])) {
$this->user_options_model->set_option('dashboard', 'dashboard_upcoming_dx_card', array('enabled' => 'true'));
} else {
$this->user_options_model->set_option('dashboard', 'dashboard_upcoming_dx_card', array('enabled' => 'false'));
}
if (isset($_POST['user_dashboard_dxpedition_sat_worked'])) {
$this->user_options_model->set_option('dashboard', 'dashboard_dxpedition_sat_worked', array('enabled' => 'true'));
} else {
$this->user_options_model->set_option('dashboard', 'dashboard_dxpedition_sat_worked', array('enabled' => 'false'));
}
if (isset($_POST['user_dashboard_enable_qslcards_card'])) {
$this->user_options_model->set_option('dashboard', 'dashboard_qslcards_card', array('enabled' => 'true'));
} else {
$this->user_options_model->set_option('dashboard', 'dashboard_qslcards_card', array('enabled' => 'false'));
}
if (isset($_POST['user_dashboard_enable_eqslcards_card'])) {
$this->user_options_model->set_option('dashboard', 'dashboard_eqslcards_card', array('enabled' => 'true'));
} else {
$this->user_options_model->set_option('dashboard', 'dashboard_eqslcards_card', array('enabled' => 'false'));
}
if (isset($_POST['user_dashboard_enable_lotw_card'])) {
$this->user_options_model->set_option('dashboard', 'dashboard_lotw_card', array('enabled' => 'true'));
} else {
$this->user_options_model->set_option('dashboard', 'dashboard_lotw_card', array('enabled' => 'false'));
}
if (isset($_POST['user_dashboard_enable_vuccgrids_card'])) {
$this->user_options_model->set_option('dashboard', 'dashboard_vuccgrids_card', array('enabled' => 'true'));
} else {
$this->user_options_model->set_option('dashboard', 'dashboard_vuccgrids_card', array('enabled' => 'false'));
}
if (isset($_POST['user_dashboard_enable_map_greyline'])) {
$this->user_options_model->set_option('dashboard', 'dashboard_map_greyline', array('enabled' => 'true'));
} else {
$this->user_options_model->set_option('dashboard', 'dashboard_map_greyline', array('enabled' => 'false'));
}
if (isset($_POST['user_menu_show_sstv_images'])) {
$this->user_options_model->set_option('menu', 'show_sstv_images', array('enabled' => 'true'));
$this->session->set_userdata('user_show_sstv_images', true);
} else {
$this->user_options_model->set_option('menu', 'show_sstv_images', array('enabled' => 'false'));
$this->session->set_userdata('user_show_sstv_images', false);
}
if (isset($_POST['user_menu_show_qsl_cards'])) {
$this->user_options_model->set_option('menu', 'show_qsl_cards', array('enabled' => 'true'));
$this->session->set_userdata('user_show_qsl_cards', true);
} else {
$this->user_options_model->set_option('menu', 'show_qsl_cards', array('enabled' => 'false'));
$this->session->set_userdata('user_show_qsl_cards', false);
}
if (isset($post_data['user_remote_operation']) && (string)$post_data['user_remote_operation'] === '1') {
$this->user_options_model->set_option('remote_operation', 'enabled', array('value' => 'true'));
} else {
$this->user_options_model->set_option('remote_operation', 'enabled', array('value' => 'false'));
}
// [QSO Form] Save field visibility preferences
$qso_field_keys = ['rst', 'name', 'qth', 'locator', 'comment',
'station_tab', 'freq_tx', 'freq_rx', 'band_rx', 'transmit_power', 'operator_callsign',
'general_tab', 'iota', 'sota', 'wwff', 'pota', 'sig', 'dok', 'usa_state',
'satellite_tab', 'notes_tab', 'qsl_tab', 'dxcluster_tab'];
foreach ($qso_field_keys as $qso_key) {
$this->user_options_model->set_option('qso_form', $qso_key,
['visible' => isset($_POST['qso_field_' . $qso_key]) ? 'true' : 'false']);
}
// [MAP Custom] ADD to user options //
$array_icon = array('station', 'qso', 'qsoconfirm');
foreach ($array_icon as $icon) {
$data_options['user_map_' . $icon . '_icon'] = xss_clean($this->input->post('user_map_' . $icon . '_icon', true));
$data_options['user_map_' . $icon . '_color'] = xss_clean($this->input->post('user_map_' . $icon . '_color', true));
}
$this->load->model('user_options_model');
if (!empty($data_options['user_map_qso_icon'])) {
foreach ($array_icon as $icon) {
$json = json_encode(array('icon' => $data_options['user_map_' . $icon . '_icon'], 'color' => $data_options['user_map_' . $icon . '_color']));
$this->user_options_model->set_option('map_custom', 'icon', array($icon => $json));
}
$this->user_options_model->set_option('map_custom', 'gridsquare', array('show' => xss_clean($this->input->post('user_map_gridsquare_show', true))));
} else {
$this->user_options_model->del_option('map_custom', 'icon');
$this->user_options_model->del_option('map_custom', 'gridsquare');
}
$remote_operation_status_message = ((string)$post_data['user_remote_operation'] === '1')
? 'Remote Operation enabled.'
: 'Remote Operation disabled.';
$this->session->set_flashdata('success', lang('account_user') . ' ' . $this->input->post('user_name', true) . ' ' . lang('account_word_edited') . ' ' . $remote_operation_status_message);
if ($oscarwatch_notice_message !== '') {
$this->session->set_flashdata('notice', $oscarwatch_notice_message);
}
if ($this->session->userdata('user_id') == $this->input->post('id', true)) {
$this->user_model->update_session($this->input->post('id', true));
}
redirect('user/edit/' . $this->uri->segment(3));
} else {
$this->session->set_flashdata('success', lang('account_user') . ' ' . $this->input->post('user_name', true) . ' ' . lang('account_word_edited'));
if ($oscarwatch_notice_message !== '') {
$this->session->set_flashdata('notice', $oscarwatch_notice_message);
}
redirect('user');
}
return;
}
$data['page_title'] = "Edit User";
$this->load->view('interface_assets/header', $data);
$data['user_name'] = $this->input->post('user_name', true);
$data['user_email'] = $this->input->post('user_email', true);
$data['user_password'] = $this->input->post('user_password', true);
$data['user_type'] = $this->input->post('user_type', true);
$data['user_firstname'] = $this->input->post('user_firstname', true);
$data['user_lastname'] = $this->input->post('user_lastname', true);
$data['user_callsign'] = $this->input->post('user_callsign', true);
$data['user_locator'] = $this->input->post('user_locator', true);
$data['user_timezone'] = $this->input->post('user_timezone', true);
$data['user_stylesheet'] = $this->input->post('user_stylesheet');
$data['user_qth_lookup'] = $this->input->post('user_qth_lookup');
$data['user_sota_lookup'] = $this->input->post('user_sota_lookup');
$data['user_wwff_lookup'] = $this->input->post('user_wwff_lookup');
$data['user_pota_lookup'] = $this->input->post('user_pota_lookup');
$data['user_show_notes'] = $this->input->post('user_show_notes');
$data['user_column1'] = $this->input->post('user_column1');
$data['user_column2'] = $this->input->post('user_column2');
$data['user_column3'] = $this->input->post('user_column3');
$data['user_column4'] = $this->input->post('user_column4');
$data['user_column4'] = $this->input->post('user_column4');
$data['user_column5'] = $this->input->post('user_column5');
$data['user_show_profile_image'] = $this->input->post('user_show_profile_image');
$data['user_previous_qsl_type'] = $this->input->post('user_previous_qsl_type');
$data['user_amsat_status_upload'] = $this->input->post('user_amsat_status_upload');
$data['user_oscarwatch_status_upload'] = $this->input->post('user_oscarwatch_status_upload');
$data['user_force_amsat_status_upload'] = $this->input->post('user_force_amsat_status_upload');
$data['user_mastodon_url'] = $this->input->post('user_mastodon_url');
$data['user_default_band'] = $this->input->post('user_default_band');
$data['user_default_confirmation'] = ($this->input->post('user_default_confirmation_qsl') !== null ? 'Q' : '') . ($this->input->post('user_default_confirmation_lotw') !== null ? 'L' : '') . ($this->input->post('user_default_confirmation_eqsl') !== null ? 'E' : '') . ($this->input->post('user_default_confirmation_qrz') !== null ? 'Z' : '');
$data['user_qso_end_times'] = $this->input->post('user_qso_end_times');
$data['user_quicklog'] = $this->input->post('user_quicklog');
$data['user_quicklog_enter'] = $this->input->post('user_quicklog_enter');
$data['language'] = $this->input->post('language');
$data['user_winkey'] = $this->input->post('user_winkey');
$data['user_winkey_websocket'] = $this->input->post('user_winkey_websocket');
$data['user_hamsat_key'] = $this->input->post('user_hamsat_key');
$data['user_hamsat_workable_only'] = $this->input->post('user_hamsat_workable_only');
$data['user_oscarwatch_token'] = $this->input->post('user_oscarwatch_token');
$this->load->view('user/edit');
$this->load->view('interface_assets/footer');
}
}
public function validate_oscarwatch_token()
{
$this->load->model('user_model');
if (!$this->user_model->authorize(2)) {
return $this->output
->set_content_type('application/json')
->set_status_header(403)
->set_output(json_encode(array('ok' => false, 'message' => 'Not authorized')));
}
$token = trim((string)$this->input->post('token', true));
if ($token === '') {
return $this->output
->set_content_type('application/json')
->set_status_header(400)
->set_output(json_encode(array('ok' => false, 'message' => 'Please enter an OscarWatch API token first.')));
}
if (!function_exists('curl_init')) {
return $this->output
->set_content_type('application/json')
->set_status_header(500)
->set_output(json_encode(array('ok' => false, 'message' => 'Token validation is unavailable because cURL is not installed.')));
}
$request = curl_init('https://oscarwatch.org/api/v1/me');
curl_setopt($request, CURLOPT_RETURNTRANSFER, true);
curl_setopt($request, CURLOPT_TIMEOUT, 10);
curl_setopt($request, CURLOPT_HTTPHEADER, array(
'Authorization: Bearer ' . $token,
'Accept: application/json',
));
$response = curl_exec($request);
$http_code = curl_getinfo($request, CURLINFO_HTTP_CODE);
$curl_error = curl_errno($request) ? curl_error($request) : '';
curl_close($request);
if ($curl_error !== '') {
return $this->output
->set_content_type('application/json')
->set_status_header(502)
->set_output(json_encode(array('ok' => false, 'message' => 'Could not reach OscarWatch: ' . $curl_error)));
}
if ($http_code === 200) {
return $this->output
->set_content_type('application/json')
->set_output(json_encode(array('ok' => true, 'message' => 'OscarWatch token is valid.')));
}
if ($http_code === 401) {
return $this->output
->set_content_type('application/json')
->set_status_header(401)
->set_output(json_encode(array('ok' => false, 'message' => 'OscarWatch token is invalid.')));
}
return $this->output
->set_content_type('application/json')
->set_status_header(400)
->set_output(json_encode(array('ok' => false, 'message' => 'OscarWatch validation failed (HTTP ' . $http_code . ').')));
}
function profile()
{
$this->load->model('user_model');
if (!$this->user_model->authorize(2)) {
$this->session->set_flashdata('notice', 'You\'re not allowed to do that!');
redirect('dashboard');
}
$query = $this->user_model->get_by_id($this->session->userdata('user_id'));
$q = $query->row();
$data['page_title'] = "Profile";
$data['user_name'] = $q->user_name;
$data['user_type'] = $q->user_type;
$data['user_email'] = $q->user_email;
$data['user_firstname'] = $q->user_firstname;
$data['user_lastname'] = $q->user_lastname;
$data['user_callsign'] = $q->user_callsign;
$data['user_locator'] = $q->user_locator;
$this->load->view('interface_assets/header', $data);
$this->load->view('user/profile');
$this->load->view('interface_assets/footer');
}
/**
* Deletes a user by their ID.
*
* This function first loads the 'user_model'. It then checks if the current user has the authorization level of 99.
* If not, it sets a flash message and redirects the user to the dashboard.
*
* If the user is authorized, it gets the user to be deleted by their ID from the URI segment 3.
* It then calls the 'delete' function from the 'user_model' with the user ID as a parameter.
*
* If the 'delete' function executes successfully, it sets the HTTP status code to 200.
* If the 'delete' function fails, it sets the HTTP status code to 500.
*
* @param int $id The ID of the user to delete.
*/
function delete_new($id)
{
$this->load->model('user_model');
if (!$this->user_model->authorize(99)) {
$this->session->set_flashdata('notice', 'You\'re not allowed to do that!');
redirect('dashboard');
}
$query = $this->user_model->get_by_id($this->uri->segment(3));
// call $this->user_model->delete and if no errors return true
if ($this->user_model->delete($id)) {
// request responds with a 200 status code and empty content
$this->output->set_status_header(200);
} else {
// request responds with a 500 status code and empty content
$this->output->set_status_header(500);
}
}
function delete()
{
$this->load->model('user_model');
if (!$this->user_model->authorize(99)) {
$this->session->set_flashdata('notice', 'You\'re not allowed to do that!');
redirect('dashboard');
}
$query = $this->user_model->get_by_id($this->uri->segment(3));
$this->load->library('form_validation');
$this->form_validation->set_rules('id', 'user_id', 'required');
$data = $query->row();
if ($this->form_validation->run() == FALSE) {
$this->load->view('interface_assets/header', $data);
$this->load->view('user/delete');
$this->load->view('interface_assets/footer');
} else {
if ($this->user_model->delete($data->user_id)) {
$this->session->set_flashdata('notice', 'User deleted');
redirect('user');
} else {
$this->session->set_flashdata('notice', '<b>Database error:</b> Could not delete user!');
redirect('user');
}
}
}
function login()
{
// Check our version and run any migrations
$this->load->library('Migration');
$this->load->library('encryption');
$this->migration->current();
$this->load->model('user_model');
$query = $this->user_model->get($this->input->post('user_name', true));
$this->load->library('form_validation');
$this->form_validation->set_rules('user_name', 'Username', 'required');
$this->form_validation->set_rules('user_password', 'Password', 'required');
$data['user'] = $query->row();
// Read the cookie remeber_me and log the user in
if ($this->input->cookie(config_item('cookie_prefix') . 'remember_me')) {
try {
$encrypted_string = $this->input->cookie(config_item('cookie_prefix') . 'remember_me');
$decrypted_string = $this->encryption->decrypt($encrypted_string);
$this->user_model->update_session($decrypted_string);
$this->user_model->set_last_login($decrypted_string);
log_message('debug', '[User ID: ' . $decrypted_string . '] Remember Me Login Successful');
redirect('dashboard');
} catch (Exception $e) {
// Something went wrong with the cookie
log_message('error', 'Remember Me Login Failed');
$this->session->set_flashdata('error', 'Remember Me Login Failed');
redirect('user/login');
}
}
if ($this->form_validation->run() == FALSE) {
$data['page_title'] = "Login";
$this->load->view('interface_assets/mini_header', $data);
$this->load->view('user/login');
$this->load->view('interface_assets/footer');
} else {
if ($this->user_model->login() == 1) {
$this->session->set_flashdata('notice', 'User logged in');
$this->user_model->update_session($data['user']->user_id);
$this->user_model->set_last_login($data['user']->user_id);
$cookie = array(
'name' => 'language',
'value' => $data['user']->language,
'expire' => time() + 1000,
'secure' => FALSE
);
// Create a remember me cookie
if ($this->input->post('remember_me') == '1') {
$encrypted_string = $this->encryption->encrypt($data['user']->user_id);
$cookie = array(
'name' => 'remember_me',
'value' => $encrypted_string,
'expire' => '1209600',
'secure' => FALSE
);
$this->input->set_cookie($cookie);
}
redirect('dashboard');
} else {
$this->session->set_flashdata('error', 'Incorrect username or password!');
redirect('user/login');
}
}
}
// Public signup (open registration)
public function signup()
{
// Gate: open registration must be enabled
if ($this->config->item('disable_open_registration') || $this->optionslib->get_option('open_registration') != 'true') {
$this->session->set_flashdata('notice', 'Registration is currently disabled.');
redirect('user/login');
return;
}
$this->load->helper(array('form', 'url'));
$this->load->model('user_model');
$this->load->library('form_validation');
// Validation rules
$this->form_validation->set_rules('user_name', 'Username', 'required');
$this->form_validation->set_rules('user_email', 'E-mail', 'required|valid_email');
$this->form_validation->set_rules('user_password', 'Password', 'required');
$this->form_validation->set_rules('user_password_confirm', 'Password Confirmation', 'required|matches[user_password]');
$this->form_validation->set_rules('user_firstname', 'First name', 'required');
$this->form_validation->set_rules('user_lastname', 'Last name', 'required');
$this->form_validation->set_rules('user_callsign', 'Callsign', 'trim|required|callback_check_unique_callsign');
$this->form_validation->set_rules('user_locator', 'Locator', 'callback_check_locator');
$this->form_validation->set_rules('user_timezone', 'Timezone', 'required');
// Timezones for select
$data['timezones'] = $this->user_model->timezones();
$data['page_title'] = 'Sign Up';
if ($this->form_validation->run() == FALSE) {
// Show form
$this->load->view('interface_assets/mini_header', $data);
$this->load->view('user/signup', $data);
$this->load->view('interface_assets/footer');
return;
}
// Defaults for new users
$user_type = 3; // operator (per config auth_level)
$measurement = 'M';
$user_date_format = 'd/m/y';
$user_stylesheet = $this->optionslib->get_option('option_theme') ?: 'default';
$user_qth_lookup = 0;
$user_sota_lookup = 0;
$user_wwff_lookup = 0;
$user_pota_lookup = 0;
$user_show_notes = 0;
$user_column1 = '';
$user_column2 = '';
$user_column3 = '';
$user_column4 = '';
$user_column5 = '';
$user_show_profile_image = 0;
$user_previous_qsl_type = '';
$user_amsat_status_upload = '';
$user_mastodon_url = '';
$user_default_band = '';
$user_default_confirmation = '';
$user_qso_end_times = 0;
$user_quicklog = 0;
$user_quicklog_enter = 1; // 1 = search, 0 = log
$language = 'english';
$user_hamsat_key = '';
$user_hamsat_workable_only = '';
$callbook_type = '';
$callbook_username = '';
$callbook_password = '';
// Attempt to create user
switch ($this->user_model->add(
$this->input->post('user_name', true),
$this->input->post('user_password', true),
$this->input->post('user_email', true),
$user_type,
$this->input->post('user_firstname', true),
$this->input->post('user_lastname', true),
$this->input->post('user_callsign', true),
$this->input->post('user_locator', true),
$this->input->post('user_timezone', true),
$measurement,
$user_date_format,
$user_stylesheet,
$user_qth_lookup,
$user_sota_lookup,
$user_wwff_lookup,
$user_pota_lookup,
$user_show_notes,
$user_column1,
$user_column2,
$user_column3,
$user_column4,
$user_column5,
$user_show_profile_image,
$user_previous_qsl_type,
$user_amsat_status_upload,
$user_mastodon_url,
$user_default_band,
$user_default_confirmation,
$user_qso_end_times,
$user_quicklog,
$user_quicklog_enter,
$language,
$user_hamsat_key,
$user_hamsat_workable_only,
$callbook_type,
$callbook_username,
$callbook_password
)) {
case EUSERNAMEEXISTS:
$data['username_error'] = 'Username <b>' . $this->input->post('user_name', true) . '</b> already in use!';
break;
case EEMAILEXISTS:
$data['email_error'] = 'E-mail address <b>' . $this->input->post('user_email', true) . '</b> already in use!';
break;
case ECALLSIGNEXISTS:
$data['callsign_error'] = 'Callsign <b>' . strtoupper($this->input->post('user_callsign', true)) . '</b> already in use!';
break;
case EPASSWORDINVALID:
$data['password_error'] = 'Invalid password!';
break;
case OK:
// Send a welcome email (without password) if email is configured
if ($this->optionslib->get_option('emailProtocol') != '') {
// Fetch newly created user by username
$new_user_q = $this->user_model->get($this->input->post('user_name', true));
if ($new_user_q && $new_user_q->num_rows() > 0) {
$u = $new_user_q->row();
$this->load->library('email');
if ($this->optionslib->get_option('emailProtocol') == "smtp") {
$config = Array(
'protocol' => $this->optionslib->get_option('emailProtocol'),
'smtp_crypto' => $this->optionslib->get_option('smtpEncryption'),
'smtp_host' => $this->optionslib->get_option('smtpHost'),
'smtp_port' => $this->optionslib->get_option('smtpPort'),
'smtp_user' => $this->optionslib->get_option('smtpUsername'),
'smtp_pass' => $this->optionslib->get_option('smtpPassword'),
'crlf' => "\r\n",
'newline' => "\r\n"
);
$this->email->initialize($config);
}
$email_data = array(
'username' => $u->user_name,
'user_firstname' => $u->user_firstname,
'user_lastname' => $u->user_lastname,
'callsign' => $u->user_callsign,
'email' => $u->user_email,
'base_url' => base_url(),
);
$message = $this->load->view('email/welcome_reminder.php', $email_data, TRUE);
$this->email->from($this->optionslib->get_option('emailAddress'), $this->optionslib->get_option('emailSenderName'));
$this->email->to($u->user_email);
$this->email->subject('Welcome to Cloudlog');
$this->email->message($message);
if (!$this->email->send()) {
log_message('error', 'Failed to send signup welcome email to ' . $u->user_email . '. Error: ' . $this->email->print_debugger());
}
}
}
$this->session->set_flashdata('success', 'Account created. You can now log in.');
redirect('user/login');
return;
}
// If we get here, something went wrong; re-render form with errors
$this->load->view('interface_assets/mini_header', $data);
$this->load->view('user/signup', $data);
$this->load->view('interface_assets/footer');
}
function logout()
{
$this->load->model('user_model');
$user_name = $this->session->userdata('user_name');
// Delete remember_me cookie
setcookie('remember_me', '', time() - 3600, '/');
$this->user_model->clear_session();
$this->session->set_flashdata('notice', 'User ' . $user_name . ' logged out.');
redirect('dashboard');
}
/**
* Function: forgot_password
*
* Allows users to input an email address and a password will be sent to that address.
*
*/
function forgot_password()
{
$this->load->helper(array('form', 'url'));
$this->load->library('form_validation');
$this->form_validation->set_rules('email', 'Email', 'required');
if ($this->form_validation->run() == FALSE) {
$data['page_title'] = "Forgot Password";
$this->load->view('interface_assets/mini_header', $data);
$this->load->view('user/forgot_password');
$this->load->view('interface_assets/footer');
} else {
// Check email address exists
$this->load->model('user_model');
$check_email = $this->user_model->check_email_address($this->input->post('email', true));
if ($check_email == TRUE) {
// Generate password reset code 50 characters long
$this->load->helper('string');
$reset_code = random_string('alnum', 50);
$this->user_model->set_password_reset_code($this->input->post('email', true), $reset_code);
// Send email with reset code
$this->data['reset_code'] = $reset_code;
$this->load->library('email');
if ($this->optionslib->get_option('emailProtocol') == "smtp") {
$config = array(
'protocol' => $this->optionslib->get_option('emailProtocol'),
'smtp_crypto' => $this->optionslib->get_option('smtpEncryption'),
'smtp_host' => $this->optionslib->get_option('smtpHost'),
'smtp_port' => $this->optionslib->get_option('smtpPort'),
'smtp_user' => $this->optionslib->get_option('smtpUsername'),
'smtp_pass' => $this->optionslib->get_option('smtpPassword'),
'crlf' => "\r\n",
'newline' => "\r\n"
);
$this->email->initialize($config);
}
$message = $this->load->view('email/forgot_password', $this->data, TRUE);
$this->email->from($this->optionslib->get_option('emailAddress'), $this->optionslib->get_option('emailSenderName'));
$this->email->to($this->input->post('email', true));
$this->email->subject('Cloudlog Account Password Reset');
$this->email->message($message);
if (!$this->email->send()) {
// Redirect to login page with message
$this->session->set_flashdata('warning', 'Email settings are incorrect.');
redirect('user/login');
} else {
// Redirect to login page with message
$this->session->set_flashdata('notice', 'Password Reset Processed.');
redirect('user/login');
}
} else {
// No account found just return to login page
$this->session->set_flashdata('notice', 'Password Reset Processed.');
redirect('user/login');
}
}
}
// Send an E-Mail to the user. Function is similar to forgot_password()
function admin_send_passwort_reset()
{
$this->load->model('user_model');
if (!$this->user_model->authorize(99)) {
$this->session->set_flashdata('notice', 'You\'re not allowed to do that!');
redirect('dashboard');
}
$query = $this->user_model->get_by_id($this->uri->segment(3));
$this->load->library('form_validation');
$this->form_validation->set_rules('id', 'user_id', 'required');
$data = $query->row();
if ($this->form_validation->run() != FALSE) {
$this->session->set_flashdata('notice', 'Something went wrong! User has no user_id.');
redirect('user');
} else {
// Check email address exists
$this->load->model('user_model');
$check_email = $this->user_model->check_email_address($data->user_email);
if ($check_email == TRUE) {
// Generate password reset code 50 characters long
$this->load->helper('string');
$reset_code = random_string('alnum', 50);
$this->user_model->set_password_reset_code(($data->user_email), $reset_code);
// Send email with reset code and first Name of the User
$this->data['reset_code'] = $reset_code;
$this->data['user_firstname'] = $data->user_firstname; // We can call the user by their first name in the E-Mail
$this->data['user_callsign'] = $data->user_callsign;
$this->data['user_name'] = $data->user_name;
$this->load->library('email');
if ($this->optionslib->get_option('emailProtocol') == "smtp") {
$config = array(
'protocol' => $this->optionslib->get_option('emailProtocol'),
'smtp_crypto' => $this->optionslib->get_option('smtpEncryption'),
'smtp_host' => $this->optionslib->get_option('smtpHost'),
'smtp_port' => $this->optionslib->get_option('smtpPort'),
'smtp_user' => $this->optionslib->get_option('smtpUsername'),
'smtp_pass' => $this->optionslib->get_option('smtpPassword'),
'crlf' => "\r\n",
'newline' => "\r\n"
);
$this->email->initialize($config);
}
$message = $this->load->view('email/admin_reset_password', $this->data, TRUE);
$this->email->from($this->optionslib->get_option('emailAddress'), $this->optionslib->get_option('emailSenderName'));
$this->email->to($data->user_email);
$this->email->subject('Cloudlog Account Password Reset');
$this->email->message($message);
if (!$this->email->send()) {
// Redirect to user page with message
$this->session->set_flashdata('danger', lang('admin_email_settings_incorrect'));
redirect('user');
} else {
// Redirect to user page with message
$this->session->set_flashdata('success', lang('admin_password_reset_processed'));
redirect('user');
}
} else {
// No account found just return to user page
$this->session->set_flashdata('danger', 'Nothing done. No user found.');
redirect('user');
}
}
}
function reset_password($reset_code = NULL)
{
$data['reset_code'] = $reset_code;
if ($reset_code != NULL) {
$this->load->helper(array('form', 'url'));
$this->load->library('form_validation');
$this->form_validation->set_rules('password', 'Password', 'required');
$this->form_validation->set_rules('password_confirm', 'Password Confirmation', 'required|matches[password]');
if ($this->form_validation->run() == FALSE) {
$data['page_title'] = "Reset Password";
$this->load->view('interface_assets/mini_header', $data);
$this->load->view('user/reset_password');
$this->load->view('interface_assets/footer');
} else {
// Lets reset the password!
$this->load->model('user_model');
$this->user_model->reset_password($this->input->post('password', true), $reset_code);
$this->session->set_flashdata('notice', 'Password Reset.');
redirect('user/login');
}
} else {
redirect('user/login');
}
}
function check_clublog_email($email)
{
$email = $this->input->post('user_clublog_name');
// Allow empty email (user may not use Clublog)
if (empty($email)) return true;
// Validate email format
if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
return true;
} else {
$this->form_validation->set_message('check_clublog_email', 'Clublog username must be a valid email address as Clublog no longer accepts callsigns as usernames.');
return false;
}
}
function check_unique_callsign($callsign)
{
$this->load->model('user_model');
$callsign = strtoupper(trim((string) $callsign));
if ($callsign === '') {
return true;
}
$exclude_user_id = $this->input->post('id', true);
if ($exclude_user_id === NULL || $exclude_user_id === '') {
$exclude_user_id = $this->uri->segment(3);
}
if ($this->user_model->exists_by_callsign($callsign, $exclude_user_id)) {
$this->form_validation->set_message('check_unique_callsign', 'The callsign ' . $callsign . ' is already in use.');
return false;
}
return true;
}
function check_last_admin_role($user_type)
{
$this->load->model('user_model');
$user_id = $this->input->post('id', true);
if ($user_id === NULL || $user_id === '') {
$user_id = $this->uri->segment(3);
}
if ($user_id && $this->user_model->would_remove_last_admin($user_id, $user_type)) {
$this->form_validation->set_message('check_last_admin_role', 'At least one admin account must remain. You cannot change the only admin to another role.');
return false;
}
return true;
}
function check_locator($grid)
{
$grid = $this->input->post('user_locator');
// Allow empty locator
if (preg_match('/^$/', $grid)) return true;
// Allow 6-digit locator
if (preg_match('/^[A-Ra-r]{2}[0-9]{2}[A-Za-z]{2}$/', $grid)) return true;
// Allow 4-digit locator
else if (preg_match('/^[A-Ra-r]{2}[0-9]{2}$/', $grid)) return true;
// Allow 4-digit grid line
else if (preg_match('/^[A-Ra-r]{2}[0-9]{2},[A-Ra-r]{2}[0-9]{2}$/', $grid)) return true;
// Allow 4-digit grid corner
else if (preg_match('/^[A-Ra-r]{2}[0-9]{2},[A-Ra-r]{2}[0-9]{2},[A-Ra-r]{2}[0-9]{2},[A-Ra-r]{2}[0-9]{2}$/', $grid)) return true;
// Allow 2-digit locator
else if (preg_match('/^[A-Ra-r]{2}$/', $grid)) return true;
// Allow 8-digit locator
else if (preg_match('/^[A-Ra-r]{2}[0-9]{2}[A-Za-z]{2}[0-9]{2}$/', $grid)) return true;
else {
$this->form_validation->set_message('check_locator', 'Please check value for grid locator (' . strtoupper($grid) . ').');
return false;
}
}
private function send_welcome_email($email, $username, $password, $firstname, $lastname, $callsign) {
// Send welcome email to new user with login credentials
// Check if email is configured
if ($this->optionslib->get_option('emailProtocol') == '') {
log_message('info', 'Email not configured - skipping welcome email for new user');
return;
}
// Load email library
$this->load->library('email');
// Configure SMTP if needed
if ($this->optionslib->get_option('emailProtocol') == "smtp") {
$config = Array(
'protocol' => $this->optionslib->get_option('emailProtocol'),
'smtp_crypto' => $this->optionslib->get_option('smtpEncryption'),
'smtp_host' => $this->optionslib->get_option('smtpHost'),
'smtp_port' => $this->optionslib->get_option('smtpPort'),
'smtp_user' => $this->optionslib->get_option('smtpUsername'),
'smtp_pass' => $this->optionslib->get_option('smtpPassword'),
'crlf' => "\r\n",
'newline' => "\r\n"
);
$this->email->initialize($config);
}
// Prepare email data
$email_data = array(
'username' => $username,
'password' => $password,
'user_firstname' => $firstname,
'user_lastname' => $lastname,
'callsign' => $callsign,
'email' => $email,
'base_url' => base_url(),
);
$message = $this->load->view('email/welcome.php', $email_data, TRUE);
$this->email->from($this->optionslib->get_option('emailAddress'), $this->optionslib->get_option('emailSenderName'));
$this->email->to($email);
$this->email->subject('Welcome to Cloudlog - Your Account Has Been Created');
$this->email->message($message);
if (!$this->email->send()) {
log_message('error', 'Failed to send welcome email to ' . $email . '. Error: ' . $this->email->print_debugger());
} else {
log_message('info', 'Welcome email sent to ' . $email);
}
}
public function resend_welcome_email($user_id) {
// Resend welcome email to existing user (without password)
$this->load->model('user_model');
// Check authorization
if (!$this->user_model->authorize(99)) {
$this->session->set_flashdata('notice', 'You\'re not allowed to do that!');
redirect('dashboard');
}
// Get user details
$user_query = $this->user_model->get_by_id($user_id);
if ($user_query->num_rows() == 0) {
$this->session->set_flashdata('danger', 'User not found');
redirect('user');
return;
}
$user = $user_query->row();
// Check if email is configured
if ($this->optionslib->get_option('emailProtocol') == '') {
$this->session->set_flashdata('danger', 'Email is not configured. Please configure email settings first.');
redirect('user');
return;
}
// Load email library
$this->load->library('email');
// Configure SMTP if needed
if ($this->optionslib->get_option('emailProtocol') == "smtp") {
$config = Array(
'protocol' => $this->optionslib->get_option('emailProtocol'),
'smtp_crypto' => $this->optionslib->get_option('smtpEncryption'),
'smtp_host' => $this->optionslib->get_option('smtpHost'),
'smtp_port' => $this->optionslib->get_option('smtpPort'),
'smtp_user' => $this->optionslib->get_option('smtpUsername'),
'smtp_pass' => $this->optionslib->get_option('smtpPassword'),
'crlf' => "\r\n",
'newline' => "\r\n"
);
$this->email->initialize($config);
}
// Prepare email data (without password)
$email_data = array(
'username' => $user->user_name,
'user_firstname' => $user->user_firstname,
'user_lastname' => $user->user_lastname,
'callsign' => $user->user_callsign,
'email' => $user->user_email,
'base_url' => base_url(),
);
// Use the reminder template without password
$message = $this->load->view('email/welcome_reminder.php', $email_data, TRUE);
$this->email->from($this->optionslib->get_option('emailAddress'), $this->optionslib->get_option('emailSenderName'));
$this->email->to($user->user_email);
$this->email->subject('Cloudlog Account Reminder');
$this->email->message($message);
if (!$this->email->send()) {
log_message('error', 'Failed to resend welcome email to ' . $user->user_email . '. Error: ' . $this->email->print_debugger());
$this->session->set_flashdata('danger', 'Failed to send email to ' . $user->user_email);
} else {
log_message('info', 'Welcome reminder email sent to ' . $user->user_email);
$this->session->set_flashdata('success', 'Welcome email sent to ' . $user->user_name . ' (' . $user->user_email . ')');
}
redirect('user');
}
}