Compare commits

...

29 Commits

Author SHA1 Message Date
Mario Voigt a936333a97 bugfix 2023-04-12 02:02:18 +02:00
Josh Panter ff31aff5c2
fix #34 (default role overides role assignment at times) 2021-12-28 19:51:25 -05:00
Josh Panter 475417ff91
version bump
for bug fixes
2021-12-28 17:55:55 -05:00
Josh Panter 87560573c6
Merge pull request #45 from rizlas/master
YOURLS_USER constant checking. Hook activated plugin.
2021-12-28 17:38:28 -05:00
Josh Panter 63d91b01fd
Merge pull request #39 from Filoz/patch-1
fix defined()
2021-12-28 17:32:23 -05:00
rizlas 16e7899a63 Check of constant YOURLS_USER via defined function. Changed hook to activated_plugin in amp_activated function. Previously hook was not working in a docker deploy 2021-10-19 21:42:01 +02:00
Filippo Lazzarini e3cb3401c1
fix defined()
A little fix on defined function call
2021-07-17 09:13:34 +02:00
Josh Panter d7d5d00b78
version bump 2021-06-17 20:09:07 -04:00
Josh Panter 6d84f6e0e2
Merge branch 'master' of https://github.com/joshp23/YOURLS-AuthMgrPlus 2021-06-17 19:47:03 -04:00
Josh Panter 37c769d44b
anon user fix 2021-06-17 19:46:05 -04:00
Josh Panter 0277e6b114
Merge pull request #32 from markkrj/add-username-column
Add username column to links table
2021-06-03 09:45:39 -04:00
Marcos de Oliveira 9512298328 Add username column to links table
* Create `array_insert` function

This was needed because array_splice does not work on associative
arrays.

* Add hook functions to insert username column and cells
* Add javascript to increment number of columns in HTML
2021-04-06 11:20:40 -03:00
joshp 338e0299f1
Liberpay to Dogecoin 2021-03-14 01:26:15 -05:00
joshp 727c9d8c35
button filter fix 2021-03-13 02:13:46 -05:00
joshp abd6231fc7
small clean up 2021-03-13 00:49:42 -05:00
joshp 33e1402ce4
remove disallowed buttons from admin page 2021-03-13 00:43:02 -05:00
joshp 93b4a263c3
fix #19 2021-03-12 01:18:42 -05:00
joshp 09ab9fd0e6
fix #30 2021-03-12 00:12:04 -05:00
joshp 5d37ab7c4d
version bump 2020-09-02 21:03:47 -04:00
Josh Panter e89f6c4770
Merge pull request #25 from ueickmann/master
Fix for issue #24 "Editor can delete other users links (including admin's)"
2020-09-02 18:45:12 -04:00
Ulrich 110fc6e680 Update plugin.php
Removed semicolon according to issue #24 "Editor can delete other users links (including admin's)"
2020-08-14 15:00:29 +02:00
ueickmann 3262c12253
Update README.md 2020-08-14 08:00:14 +02:00
joshp 65e50a60f4
repair filter type hooks 2020-07-26 02:22:28 -04:00
joshp da0d928b3c
allow custom ajax actions by default 2020-07-24 03:23:06 -04:00
joshp c06277a42a
better activation behavior 2020-07-22 01:28:28 -04:00
Josh Panter 458ac8bd48
Merge pull request #22 from umlaeute/feature/default_role
default role for authenticated users
2020-07-22 01:23:08 -04:00
IOhannes m zmölnig d108d42290 Bumped version number 2020-06-24 18:16:08 +02:00
IOhannes m zmölnig 496fbf6d40 Document "add_default_role" 2020-06-23 11:23:10 +02:00
IOhannes m zmölnig de07ea53c6 amp_default_role for logged-in users (that have no explicit role) 2020-06-23 11:20:50 +02:00
2 changed files with 168 additions and 67 deletions

View File

@ -1,7 +1,7 @@
YOURLS-AuthMgrPlus
=====================
This plugin manages essential YOURLS funtions and seperates user data with role-based access controls (RBAC). With access controls enabled, you can safely delegate access to the admin pages and API while keeping link data private. You share an installation, log on, add a link, and nobody else sees it.
This plugin manages essential YOURLS functions and separates user data with role-based access controls (RBAC). With access controls enabled, you can safely delegate access to the admin pages and API while keeping link data private. You share an installation, log on, add a link, and nobody else sees it.
Features
--------
@ -11,22 +11,23 @@ Features
- All plugin pages, including main management page, hidden to non-admins by default. Easy to unblock pages.
- Plenty of hooks to filter Roles, Role Capabilities, and _any_ of the default data environemnt (such as plugin page visibility)
- Fine(r) tuned API access
- PHP 7 compatible
- PHP 8 compatible
- No tracking of admins or editors by default
Requirements
------------
- YOURLS 1.7.3 +
- Incompatable Plugins:
- Incompatible Plugins:
- nicwaller's [`authmgr`](https://github.com/nicwaller/yourls-authmgr-plugin)
- Ian Barber's [`Seperate Users`](https://github.com/ianbarber/Yourls-Separate-Users)
Installation
------------
1. Download the [latest release](https://github.com/joshp23/YOURLS-AuthMgrPlus) of ythis plugin.
1. Download the [latest release](https://github.com/joshp23/YOURLS-AuthMgrPlus) of this plugin.
1. Copy the `authMgrPlus` folder into your `user/plugins` folder for YOURLS.
1. Set up some parameters for authMgrPlus (details below)
1. Activate the plugin with the plugin manager in the YOURLS admin interface.
1. If you have pre-existing links in your database, you will have to manually asign them a user via an sql querry.
Default Roles
-------------
@ -73,13 +74,17 @@ $amp_allowed_plugin_pages = array(
```
Explore the code to see how to set `$amp_role_capabilities` and `$amp_anon_capabilities`. These are set to defaults in the `amp_env_check()` function.
You can also assign a default role to all logged-in users that have no explicit role (note, case sensative):
```
$amp_default_role = "Editor";
```
#### NOTE:
This is a fork of nicwaller's [Authmgr](https://github.com/nicwaller/yourls-authmgr-plugin) merged with Ian barber's[Seperate User's](https://github.com/joshp23/Yourls-Separate-Users) plugin. Both code bases underwent heavy rewrites, and have been extensively updated and tightly integrated here, resulting in a lean and highly functional user authorization management environment.
This is a fork of nicwaller's [Authmgr](https://github.com/nicwaller/yourls-authmgr-plugin) merged with Ian barber's [Separate Users](https://github.com/joshp23/Yourls-Separate-Users) plugin. Both code bases underwent heavy rewrites, and have been extensively updated and tightly integrated here, resulting in a lean and highly functional user authorization management environment.
### Support Dev
All of my published code is developed and maintained in spare time, if you would like to support development of this, or any of my published code, I have set up a Liberpay account for just this purpose. Thank you.
<noscript><a href="https://liberapay.com/joshu42/donate"><img alt="Donate using Liberapay" src="https://liberapay.com/assets/widgets/donate.svg"></a></noscript>
### Tips
Dogecoin: DARhgg9q3HAWYZuN95DKnFonADrSWUimy3
License
-------

View File

@ -3,7 +3,7 @@
Plugin Name: Auth Manager Plus
Plugin URI: https://github.com/joshp23/YOURLS-AuthMgrPlus
Description: Role Based Access Controlls with seperated user data for authenticated users
Version: 2.1.2
Version: 2.3.1
Author: Josh Panter, nicwaller, Ian Barber <ian.barber@gmail.com>
Author URI: https://unfettered.net
*/
@ -24,6 +24,7 @@ class ampCap {
const AddURL = 'AddURL';
const DeleteURL = 'DeleteURL';
const EditURL = 'EditURL';
const ShareURL = 'ShareURL';
const Traceless = 'Traceless';
const ManageAnonURL = 'ManageAnonURL';
const ManageUsrsURL = 'ManageUsrsURL';
@ -76,28 +77,26 @@ function amp_intercept_admin() {
yourls_add_notice('Access Denied');
}
$action_capability_map = array(
'add' => ampCap::AddURL,
'delete' => ampCap::DeleteURL,
'edit_display' => ampCap::EditURL,
'edit_save' => ampCap::EditURL,
'activate' => ampCap::ManagePlugins,
'deactivate' => ampCap::ManagePlugins,
);
// allow manipulation of this list ( be mindfull of extending Authmp Capability class if needed )
yourls_apply_filter( 'amp_action_capability_map', $action_capability_map);
// allow manipulation of this list ( be mindfull of extending Auth mp Capability class if needed )
$action_capability_map = yourls_apply_filter( 'amp_action_capability_map',
array( 'add' => ampCap::AddURL,
'delete' => ampCap::DeleteURL,
'edit_display' => ampCap::EditURL,
'edit_save' => ampCap::EditURL,
'activate' => ampCap::ManagePlugins,
'deactivate' => ampCap::ManagePlugins,
) );
// Key actions like Add/Edit/Delete are AJAX requests
if ( yourls_is_Ajax() ) {
// Define some boundaries for ownership
$restricted_actions = array( 'edit_display',
'edit_save',
'delete'
);
// Allow some flexability with those boundaries
yourls_apply_filter( 'amp_restricted_ajax_actions', $restricted_actions );
$restricted_actions = yourls_apply_filter( 'amp_restricted_ajax_actions',
array( 'edit_display',
'edit_save',
'delete'
) );
$action_keyword = $_REQUEST['action'];
$cap_needed = $action_capability_map[$action_keyword];
@ -151,6 +150,41 @@ function amp_intercept_admin() {
}
}
/*
* Cosmetic filter: removes disallowed buttons from link list per short link
*/
yourls_add_filter( 'table_add_row_action_array', 'amp_ajax_button_check' );
function amp_ajax_button_check( $actions, $keyword ) {
// define the amp capabilities that map to the buttons
$button_cap_map = array('stats' => ampCap::ViewStats,
'share' => ampCap::ShareURL,
'edit' => ampCap::EditURL,
'delete' => ampCap::DeleteURL,
);
$button_cap_map = yourls_apply_filter( 'amp_button_capability_map', $button_cap_map );
// define restricted buttons
$restricted_buttons = array('delete', 'edit');
if ( 'YOURLS_PRIVATE_INFOS' === true )
$restricted_buttons += ['stats'];
$restricted_buttons = yourls_apply_filter( 'amp_restricted_buttons', $restricted_buttons );
// unset any disallowed buttons
foreach ( $actions as $action => $vars ) {
$cap_needed = $button_cap_map[$action];
if ( in_array( $action, $restricted_buttons) )
$show = amp_manage_keyword( $keyword, $cap_needed );
else
$show = amp_have_capability( $cap_needed );
if (!$show)
unset( $actions[$action] );
}
return $actions;
}
/*
* Cosmetic filter: removes disallowed plugins from link list
*/
@ -160,24 +194,27 @@ function amp_admin_sublinks( $links ) {
global $amp_allowed_plugin_pages;
if ( amp_have_capability( ampCap::ManagePlugins ) !== true) {
foreach( $links['plugins'] as $link => $ar ) {
if(!in_array($link, $amp_allowed_plugin_pages) )
unset($links['plugins'][$link]);
if( empty( $links['plugins'] ) ) {
unset($links['plugins']);
} else {
if ( amp_have_capability( ampCap::ManagePlugins ) !== true) {
if(!empty($links['plugins'])) {
foreach( $links['plugins'] as $link => $ar ) {
if(!in_array($link, $amp_allowed_plugin_pages) )
unset($links['plugins'][$link]);
}
}
}
if(!empty($links['plugins'])) {
sort($links['plugins']);
}
}
if( empty( $links['plugins'] ) )
yourls_add_filter( 'admin_links', 'amp_admin_links' );
sort($links['plugins']);
return $links;
}
function amp_admin_links( $links ) {
unset($links['plugins']);
return $links;
}
/*
* Cosmetic filter: displays currently available roles
* by hovering mouse over the username in logout link.
@ -219,6 +256,7 @@ function amp_have_capability( $capability ) {
global $amp_anon_capabilities;
global $amp_role_capabilities;
global $amp_admin_ipranges;
global $amp_default_role;
// Make sure the environment has been setup
amp_env_check();
@ -232,13 +270,16 @@ function amp_have_capability( $capability ) {
if ( !amp_is_valid_user() ) //XXX
return false;
// List capabilities of particular user role
$user = YOURLS_USER !== false ? YOURLS_USER : NULL;
$user = defined('YOURLS_USER') ? YOURLS_USER : NULL;
$user_caps = array();
foreach ( $amp_role_capabilities as $rolename => $rolecaps ) {
if ( amp_user_has_role( $user, $rolename ) ) {
$user_caps = array_merge( $user_caps, $rolecaps );
}
}
if ( amp_user_is_assigned ( $user ) )
foreach ( $amp_role_capabilities as $rolename => $rolecaps )
if ( amp_user_has_role( $user, $rolename ) )
$user_caps = array_merge( $user_caps, $rolecaps );
elseif ( isset( $amp_default_role ) && in_array ($amp_default_role, array_keys( $amp_role_capabilities ) ) )
$user_caps = $amp_role_capabilities [ $amp_default_role ];
$user_caps = array_unique( $user_caps );
// Is the requested capability in this list?
$return = in_array( $capability, $user_caps );
@ -253,9 +294,27 @@ function amp_have_capability( $capability ) {
break;
}
}
return $return;
}
// Determine if a user has been assigned a role
function amp_user_is_assigned ( $username ) {
global $amp_role_assignment;
if ( empty( $amp_role_assignment ) )
return false;
$return = false;
foreach ( $amp_role_assignment as $role )
if ( in_array( $username, $role ) ) {
$return = true;
break;
}
return $return;
}
// Determine whether a specific user has a role.
function amp_user_has_role( $username, $rolename ) {
@ -289,7 +348,7 @@ function amp_admin_list_where($where) {
if ( amp_have_capability( ampCap::ViewAll ) )
return $where; // Allow admin/editor users to see the lot.
$user = YOURLS_USER !== false ? YOURLS_USER : NULL;
$user = defined('YOURLS_USER') ? YOURLS_USER : NULL;
$where['sql'] = $where['sql'] . " AND (`user` = :user OR `user` IS NULL) ";
$where['binds']['user'] = $user;
@ -335,7 +394,7 @@ function amp_get_db_stats( $return, $where ) {
// or... filter results
global $ydb;
$table_url = YOURLS_DB_TABLE_URL;
$user = YOURLS_USER !== false ? YOURLS_USER : NULL;
$user = defined('YOURLS_USER') ? YOURLS_USER : NULL;
$where['sql'] = $where['sql'] . " AND (`user` = :user OR `user` IS NULL) ";
$where['binds']['user'] = $user;
@ -379,6 +438,7 @@ function amp_env_check() {
ampCap::AddURL,
ampCap::EditURL,
ampCap::DeleteURL,
ampCap::ShareURL,
ampCap::Traceless,
ampCap::ManageAnonURL,
ampCap::ManageUsrsURL,
@ -393,6 +453,7 @@ function amp_env_check() {
ampCap::AddURL,
ampCap::EditURL,
ampCap::DeleteURL,
ampCap::ShareURL,
ampCap::Traceless,
ampCap::ManageAnonURL,
ampCap::APIu,
@ -404,6 +465,7 @@ function amp_env_check() {
ampCap::AddURL,
ampCap::EditURL,
ampCap::DeleteURL,
ampCap::ShareURL,
ampCap::APIu,
ampCap::ViewStats,
),
@ -436,26 +498,16 @@ function amp_env_check() {
$amp_role_assignment = $amp_role_assignment_lower;
unset($amp_role_assignment_lower);
// allow manipulation of env by other plugins
// be mindfull of extending ampCap and ampRoles classes if needed
$a = $amp_anon_capabilities;
$b = $amp_role_capabilities;
$c = $amp_role_assignment;
$d = $amp_admin_ipranges;
$e = $amp_allowed_plugin_pages;
yourls_apply_filter( 'amp_env_check', $a, $b, $c, $d, $e );
return true;
}
// Activation: add the user column to the URL table if not added
yourls_add_action( 'activated_authMgrPlus/plugin.php', 'amp_activated' );
yourls_add_action('activated_plugin', 'amp_activated');
function amp_activated() {
global $ydb;
$table = YOURLS_DB_TABLE_URL;
$sql = "DESCRIBE `$table`";
$sql = "DESCRIBE `".$table."`";
$results = $ydb->fetchObjects($sql);
$activated = false;
@ -466,10 +518,10 @@ function amp_activated() {
}
if(!$activated) {
if ($version) {
$sql = "ALTER TABLE `$table` ADD `user` VARCHAR(255) NULL";
$sql = "ALTER TABLE `".$table."` ADD `user` VARCHAR(255) NULL";
$insert = $ydb->fetchAffected($sql);
} else {
$ydb->query("ALTER TABLE `$table` ADD `user` VARCHAR(255) NULL");
$ydb->query("ALTER TABLE `".$table."` ADD `user` VARCHAR(255) NULL");
}
}
@ -485,6 +537,7 @@ function amp_current_capabilities() {
ampCap::AddURL,
ampCap::EditURL,
ampCap::DeleteURL,
ampCap::ShareURL,
ampCap::Traceless,
ampCap::ManageAnonURL,
ampCap::ManageUsrsURL,
@ -494,15 +547,14 @@ function amp_current_capabilities() {
ampCap::ViewStats,
ampCap::ViewAll,
);
// allow manipulation of this list ( be mindfull of extending the ampCap class if needed )
yourls_apply_filter( 'amp_current_capabilities', $all_capabilities);
foreach ( $all_capabilities as $cap ) {
if ( amp_have_capability( $cap ) ) {
$current_capabilities[] = $cap;
}
}
// allow manipulation of this list ( be mindfull of extending the ampCap class if needed )
$current_capabilities = yourls_apply_filter( 'amp_current_capabilities', $current_capabilities);
return $current_capabilities;
}
@ -531,10 +583,10 @@ function amp_manage_keyword( $keyword, $capability ) {
$return = false; // default is to deny access
if ( amp_is_valid_user() ) { // only authenticated users can manaage keywords
$owner = amp_keyword_owner($keyword);
$user = YOURLS_USER !== false ? YOURLS_USER : NULL;
$user = defined('YOURLS_USER') ? YOURLS_USER : NULL;
if ( amp_have_capability( ampCap::ManageUsrsURL ) // Admin?
|| ( $owner === NULL && amp_have_capability( ampCap::ManageAnonURL ) ) // Editor?
|| ( $owner === $user && amp_have_capability( $capability ) ) ); // Self Edit?
|| ( $owner === $user && amp_have_capability( $capability ) ) ) // Self Edit?
$return = true;
}
return $return;
@ -557,7 +609,7 @@ function amp_insert_link($actions) {
global $ydb;
$keyword = $actions[2];
$user = YOURLS_USER !== false ? YOURLS_USER : NULL;
$user = defined('YOURLS_USER') ? YOURLS_USER : NULL;
$table = YOURLS_DB_TABLE_URL;
// Insert $keyword against $username
@ -591,4 +643,48 @@ function amp_is_valid_user() {
return $valid;
}
yourls_add_action( 'html_footer', 'amp_format_table_javascript' );
function amp_format_table_javascript() {
echo <<<JS
<script>
if($("body").hasClass("index")) {
document.querySelector("#main_table tfoot th").colSpan = 7;
document.querySelector("#nourl_found td").colSpan = 7;
}
</script>
JS;
}
function array_insert($array, $position, $insert_array) {
$first_array = array_splice($array, 0, $position);
$array = array_merge($first_array, $insert_array, $array);
return $array;
}
yourls_add_filter('table_head_cells', 'amp_username_table_head');
function amp_username_table_head( $cells ) {
$user_head = array( 'username' => 'Username' );
$cells = array_insert($cells, 5, $user_head);
return $cells;
}
yourls_add_filter('table_add_row_cell_array', 'amp_add_user_row');
function amp_add_user_row( $cells, $keyword ) {
$username = amp_keyword_owner($keyword);
$user_cell = array(
'username' => array(
'template' => '%username%',
'username' => $username,
)
);
$cells = array_insert($cells, 5, $user_cell);
return $cells;
}
?>