Files
wavelog/application/views/club/permissions.php
Fabian Berg c70c2ec5cd Clubstations for Wavelog (#1334)
* feat[clubstations]: New DB structure

* feat[clubstations]: Add clubstationstable in user managment

* feat[clubstations]: Show last operator

* feat[clubstations]: Better solution for last operator. tnx for the hint @int2001

* feat[clubstations]: New Club Model and Controller

* feat[clubstations]: Add "Add User" and "Edit User" functionality

* docs[clubstations]: move comment

* feat[clubstations]: Add "Delete Member" functionality

* feat[clubstations]: some enhancements and javascript

* fix[clubstations]: Wrong message class for flashmessages

* feat[clubstations]: Added Switch in the Header menu (not functional yet)

* feat[clubstations]: clubswitch modal

* fix[clubstations]: Load encryption library if not already loaded

* fix[clubstations]: Prevent direct login attempts to clubstations and enhance impersonation authorization

* fix[clubstations]: Typo

* feat[clubstations]: Only show the operator dialog if there is something fishy

* fix[user]: little UI bug

* feat[impersonate]: Add source uid to session data

* fix[impersonate]: logic adjustment

* feat[clubstations]: Add manage button in header menu for club officers

* fix[clubstations]: typo in permission level check

* fix[clubstations]: Full rights for the admin

* feat[impersonate]: Custom sessiondata

* feat[impersonate]: Implement stop impersonation feature with modal confirmation; "the way back"

* fix(modal): Fix bug where modal was hidden when mouse leaved the browser content

* docs(config): Adjust config description for special callsigns and clubstations

* feat(club): Add club access check helper

* typo

* fix[impersonation]: Better text

* feat(club): Selectize for a efficient user search

* feat(clubstations): Restrict clubstations based on users permission level part 1/x

* adjustments for dev merge

* Adjusted club right for the advanced logbook

* feat[user]: Refactoring of the Action Buttons in the user table

* fix[club_permissions]: normal button instead small one for club permissions

* remove unnecessary line break in modal body

* feat[clubstations]: Add Club Mode badge to the header

* fix[clubstations]: fix maintenance mode

* allow switch back on http

* feat(simplefle): display operator input based on club_access

* small UI adjustments

* small UI adjustments

* moved api page to a index.php file and added support for clubstations

* removed unused stuff

* typo

* radios and api keys

* missed one binding

* fix qso view, even officers do just see their own radios in QSO logging

* omit the need for a relogin to see the changes as an admin

* Omit the need for relogin after club changes in general. It's a question of UX. It's better to accept a little higher DB load (if clubstations are enabled) then the need of an user to relogin. There is some room for improvement by changing user_model->get_by_id() and adding a join there. This can be done later if we see that the load is too high

* If the user is not the creator of the API key, it's likely a clubstation. In this case the callsign of the clubstation can not be the same as the callsign of the user (operator call provided by the user). If this is the case, we need to use the callsign of the creator of the API key

* remove debug messages

* better UI in header

* found a typo

* full access in clubstations for admins (if accessed via admin usertable)

* adjusted text

* adjusted text

* adjust text

* reduce required chars

* bugfix: missing the correct authentication in case the admin was not member of the club. he wasn't able to switch back

* reduce debug messages

* fixed UI bug related to tooltips

* load js in controller

* upps..

* some UI adjustments

* corrected permissions

* if user gets delete we need to remove data in club_permissions and also api keys which were created by this user

* Notify members about new memberships or changes in permission level

* add spinner to save button

* make login/logout process more bulletproof

* remove the relogin cookie after the attempt

* better strategy

* bug where switch back failed if user is no admin

* make api keys more secure

* mask not owned api keys

* removed annoying link

* if a user gets removed from a club we also should delete the corresponding api keys and cat radios

* adjusted wiki link

* Auto creation of logbook and location when new user is created

* store and display locator in uppercase

* same for callsign

* fixed a bug in user/club creation

* Revert "Auto creation of logbook and location when new user is created"
We found another solution to which will be addressed in a second PR
This reverts commit f05f4b7bf0.

* Optimized SQL for stats at userlist

* Source query for lastop "out", because mysql<9.0 can't handle Windowed functions

* adjust migration

* add new columns to users table to get created_at and modified_at

* added a partial down function

* add operator dropdown for clubstations

* fix mig version

* Add some backend restrictions in case a user wants to try something funny with the club

---------

Co-authored-by: Andreas Kristiansen <6977712+AndreasK79@users.noreply.github.com>
Co-authored-by: int2001 <joerg@dj7nt.de>
2025-01-02 10:22:23 +01:00

342 lines
26 KiB
PHP

<div class="container">
<br>
<h2><?= sprintf(__("Club Permissions for %s"), $club->user_callsign); ?></h2>
<!-- <a class="btn btn-primary" href="<?= site_url('user'); ?>"><i class="fas fa-arrow-left"></i> <?= __("Go back"); ?></a> -->
<?php $this->load->view('layout/messages'); ?>
<div class="card mt-3">
<div class="card-header">
<?= __("Club Permissions"); ?>
</div>
<div class="card-body">
<p><?= __("In order for users to log QSOs with this club/special callsign, they need appropriate authorizations. Add users to the table below and set the appropriate permission."); ?></p>
<button class="btn btn-info" data-bs-toggle="modal" data-bs-target="#permissionsModal"><i class="fas fa-info-circle"></i> <?= __("See available Permissions"); ?></button>
<div class="modal fade bg-black bg-opacity-50" id="permissionsModal" aria-labelledby="permissionsLabel" aria-hidden="true" data-bs-backdrop="static" data-bs-keyboard="false">
<div class="modal-dialog modal-dialog-centered modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="permissionsLabel"><?= __("Available Permissions") ?></h5>
</div>
<div class="modal-body">
<div class="table-responsive">
<table class="table">
<thead class="table">
<tr>
<th><?= __("Action"); ?></th>
<th><?php echo $permissions[3]; ?></th>
<th><?php echo $permissions[9]; ?></th>
</tr>
</thead>
<tbody>
<tr>
<td><?= __("Log QSOs via Web GUI (live and post)"); ?></td>
<td><i class="fas fa-check text-success"></i></td>
<td><i class="fas fa-check text-success"></i></td>
</tr>
<tr class="empty-row">
<td colspan="3"></td>
</tr>
<tr>
<td><?= __("Log QSOs via API"); ?></td>
<td><i class="fas fa-check text-success"></i></td>
<td><i class="fas fa-check text-success"></i></td>
</tr>
<tr class="empty-row">
<td colspan="3"></td>
</tr>
<tr>
<td><?= __("Edit a QSO"); ?></td>
<td></td>
<td></td>
</tr>
<tr>
<td class="ps-5"><i class="fas fa-arrow-right me-3"></i><?= __("QSO was done by the operator"); ?></td>
<td><i class="fas fa-check text-success"></i></td>
<td><i class="fas fa-check text-success"></i></td>
</tr>
<tr>
<td class="ps-5"><i class="fas fa-arrow-right me-3"></i><?= __("QSO was done by another operator"); ?></td>
<td><i class="fas fa-times text-danger"></i></td>
<td><i class="fas fa-check text-success"></i></td>
</tr>
<tr class="empty-row">
<td colspan="3"></td>
</tr>
<tr>
<td><?= __("Delete a QSO"); ?></td>
<td></td>
<td></td>
</tr>
<tr>
<td class="ps-5"><i class="fas fa-arrow-right me-3"></i><?= __("QSO was done by the operator"); ?></td>
<td><i class="fas fa-check text-success"></i></td>
<td><i class="fas fa-check text-success"></i></td>
</tr>
<tr>
<td class="ps-5"><i class="fas fa-arrow-right me-3"></i><?= __("QSO was done by another operator"); ?></td>
<td><i class="fas fa-times text-danger"></i></td>
<td><i class="fas fa-check text-success"></i></td>
</tr>
<tr class="empty-row">
<td colspan="3"></td>
</tr>
<tr>
<td><?= __("Manage Stationsetup (edit/create logbooks and locations)"); ?></td>
<td><i class="fas fa-times text-danger"></i></td>
<td><i class="fas fa-check text-success"></i></td>
</tr>
<tr class="empty-row">
<td colspan="3"></td>
</tr>
<tr>
<td><?= __("Manage Third-Party services"); ?></td>
<td><i class="fas fa-times text-danger"></i></td>
<td><i class="fas fa-check text-success"></i></td>
</tr>
<tr class="empty-row">
<td colspan="3"></td>
</tr>
<tr>
<td><?= __("Import QSO per ADIF"); ?></td>
<td><i class="fas fa-times text-danger"></i></td>
<td><i class="fas fa-check text-success"></i></td>
</tr>
<tr class="empty-row">
<td colspan="3"></td>
</tr>
<tr>
<td><?= __("Export QSO per ADIF"); ?></td>
<td><i class="fas fa-times text-danger"></i></td>
<td><i class="fas fa-check text-success"></i></td>
</tr>
<tr class="empty-row">
<td colspan="3"></td>
</tr>
<tr>
<td><?= __("User Management"); ?></td>
<td></td>
<td></td>
</tr>
<tr>
<td class="ps-5"><i class="fas fa-arrow-right me-3"></i><?= __("Can create new users in Wavelog"); ?></td>
<td><i class="fas fa-times text-danger"></i></td>
<td><i class="fas fa-times text-danger"></i></td>
</tr>
<tr>
<td class="ps-5"><i class="fas fa-arrow-right me-3"></i><?= __("Can edit other users in Wavelog"); ?></td>
<td><i class="fas fa-times text-danger"></i></td>
<td><i class="fas fa-times text-danger"></i></td>
</tr>
<tr>
<td class="ps-5"><i class="fas fa-arrow-right me-3"></i><?= __("Can edit Club permissions and add/remove users"); ?></td>
<td><i class="fas fa-times text-danger"></i></td>
<td><i class="fas fa-check text-success"></i></td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal"><?= __("Close"); ?></button>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="card mt-3">
<div class="card-header">
<?= __("Users with Permissions"); ?>
</div>
<div class="card-body">
<button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#addUserModal">
<i class="fas fa-plus"></i> <?= __("Add User"); ?>
</button>
<div class="modal fade" id="addUserModal" tabindex="-1" aria-labelledby="addUserLabel" aria-hidden="true" data-bs-backdrop="static">
<div class="modal-dialog modal-dialog-centered" style="max-width: 700px;">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="addUserLabel"><?= __("Add new User to Club"); ?></h5>
</div>
<form action="<?= site_url('club/alter_member'); ?>" method="post">
<div class="modal-body">
<input type="hidden" name="club_id" value="<?php echo $club->user_id; ?>">
<p>
<?= sprintf(__("You can only add users to the %s Clubstation if they already exist on this Wavelog Server."), $club->user_callsign); ?>
<?= __("If they don't exist, please ask your Wavelog Administrator to create an account for them."); ?><br><br>
<?= __("Search for the user by their callsign or first/lastname and select the permission level."); ?>
</p>
<div class="table-responsive">
<table class="table">
<thead class="table">
<tr>
<th class="text-center"><?= __("User (Callsign or Name)"); ?></th>
<th class="text-center"><?= __("Permission"); ?></th>
</tr>
</thead>
<tbody>
<tr>
<td>
<input class="form-control" id="user_id" name="user_id" required />
<small class="form-text text-muted"><?= __("Type at least 2 characters."); ?></small>
</td>
<td>
<select class="form-select" id="permission" name="permission" required>
<option value="3"><?php echo $permissions[3]; ?></option>
<option value="9"><?php echo $permissions[9]; ?></option>
</select>
<div class="mt-2 form-check d-flex justify-content-end text-muted">
<input class="form-check-input me-2" type="checkbox" id="notify_user" name="notify_user">
<input type="hidden" name="notify_message" value="new_member">
<label class="form-check-label" for="notify_user">
<?= __("Notify the user via email"); ?>
</label>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-success ld-ext-right"><?= __("Save"); ?><div class="ld ld-ring ld-spin"></div></button>
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal"><?= __("Cancel"); ?></button>
</div>
</form>
</div>
</div>
</div>
<?php if (empty($club_members)) { ?>
<div class="text-center">
<h5><?= __("No users currently have access to this club station."); ?></h5>
</div>
<?php } else { ?>
<div class="table-responsive mt-3">
<table class="table table-striped table-hover" id="clubuserstable">
<thead>
<tr>
<th><?= __("Firstname"); ?></th>
<th><?= __("Lastname"); ?></th>
<th><?= __("Callsign"); ?></th>
<th><?= __("Username"); ?></th>
<th><?= __("E-Mail"); ?></th>
<th><?= __("Permission"); ?></th>
<th><?= __("Actions"); ?></th>
</tr>
</thead>
<tbody>
<?php foreach ($club_members as $member) { ?>
<tr>
<td style="text-align: center; vertical-align: middle;"><?php echo $member->user_firstname; ?></td>
<td style="text-align: center; vertical-align: middle;"><?php echo $member->user_lastname; ?></td>
<td style="text-align: center; vertical-align: middle;"><?php echo $member->user_callsign; ?></td>
<td style="text-align: center; vertical-align: middle;"><?php echo $member->user_name; ?></td>
<td style="text-align: center; vertical-align: middle;"><?php echo '<a href="mailto:' . $member->user_email . '">' . $member->user_email . '</a>'; ?></td>
<td style="text-align: center; vertical-align: middle;">
<?php if ($member->p_level == 3) { ?>
<span class="badge bg-info"><?php echo $permissions[3]; ?></span>
<?php } else if ($member->p_level == 9) { ?>
<span class="badge bg-warning"><?php echo $permissions[9]; ?></span>
<?php } ?>
<?php if ($member->user_type == 99) { ?>
<span class="badge bg-danger"><?= __("Wavelog Administrator"); ?></span>
<?php } ?>
</td>
<td style="text-align: center; vertical-align: middle;">
<button class="btn btn-primary btn-sm" data-bs-toggle="modal" data-bs-target="#editModal_<?php echo $member->user_id; ?>"><i class="fas fa-edit"></i> <?= __("Edit"); ?></button>
<div class="modal fade" id="editModal_<?php echo $member->user_id; ?>" tabindex="-1" aria-labelledby="editLabel_<?php echo $member->user_id; ?>" aria-hidden="true" data-bs-backdrop="static" data-bs-keyboard="false">
<div class="modal-dialog modal-dialog-centered" style="max-width: 700px;">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="editLabel_<?php echo $member->user_id; ?>"><?= __("Edit User"); ?></h5>
</div>
<form action="<?= site_url('club/alter_member'); ?>" method="post">
<div class="modal-body">
<input type="hidden" name="club_id" value="<?php echo $club->user_id; ?>">
<input type="hidden" name="user_id" value="<?php echo $member->user_id; ?>">
<p>
<?= __("You can modify the users permission level for this Clubstation."); ?>
</p>
<div class="table-responsive">
<table class="table">
<thead class="table">
<tr>
<th class="text-center"><?= __("User Callsign"); ?></th>
<th class="text-center"><?= __("Permission"); ?></th>
</tr>
</thead>
<tbody>
<tr>
<td class="text-center pt-3">
<p><b><?php echo $member->user_callsign; ?> - <?php echo $member->user_firstname . ' ' . $member->user_lastname; ?></b></p>
</td>
<td>
<select class="form-select" id="permission" name="permission" required>
<option value="3" <?php if ($member->p_level == 3) { echo 'selected'; } ?>><?php echo $permissions[3]; ?></option>
<option value="9" <?php if ($member->p_level == 9) { echo 'selected'; } ?>><?php echo $permissions[9]; ?></option>
</select>
<div class="mt-2 form-check d-flex justify-content-end text-muted">
<input class="form-check-input me-2" type="checkbox" id="notify_user" name="notify_user">
<input type="hidden" name="notify_message" value="modified_member">
<label class="form-check-label" for="notify_user">
<?= __("Notify the user via email about the change"); ?>
</label>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-success ld-ext-right"><?= __("Save"); ?><div class="ld ld-ring ld-spin"></div></button>
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal"><?= __("Cancel"); ?></button>
</div>
</form>
</div>
</div>
</div>
<button class="btn btn-danger btn-sm" data-bs-toggle="modal" data-bs-target="#deleteModal_<?php echo $member->user_id; ?>"><i class="fas fa-trash"></i> <?= __("Delete"); ?></button>
<div class="modal fade bg-black bg-opacity-50" id="deleteModal_<?php echo $member->user_id; ?>" tabindex="-1" aria-labelledby="deleteLabel_<?php echo $member->user_id; ?>" aria-hidden="true" data-bs-backdrop="static" data-bs-keyboard="false">
<div class="modal-dialog modal-dialog-centered modal-md">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="deleteLabel_<?php echo $member->user_id; ?>"><?= __("Delete User") ?></h5>
</div>
<form action="<?= site_url('club/delete_member'); ?>" method="post">
<div class="modal-body" style="text-align: center !important;">
<input type="hidden" name="club_id" value="<?php echo $club->user_id; ?>">
<input type="hidden" name="user_id" value="<?php echo $member->user_id; ?>">
<p><?= __("Are you sure you want to delete this user from the club?"); ?></p>
<div class="mb-3">
<p>
<?= sprintf(__("Callsign: %s"), $member->user_callsign); ?><br>
<?= sprintf(__("Role: %s"), $permissions[$member->p_level]); ?>
</p>
</div>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-danger"><?= __("Delete"); ?></button>
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal"><?= __("Cancel"); ?></button>
</div>
</form>
</div>
</div>
</div>
</td>
</tr>
<?php } ?>
</tbody>
</table>
<?php } ?>
</div>
</div>
</div>
</div>