Compare commits
24 Commits
Author | SHA1 | Date |
---|---|---|
Mario Voigt | a936333a97 | |
Josh Panter | ff31aff5c2 | |
Josh Panter | 475417ff91 | |
Josh Panter | 87560573c6 | |
Josh Panter | 63d91b01fd | |
rizlas | 16e7899a63 | |
Filippo Lazzarini | e3cb3401c1 | |
Josh Panter | d7d5d00b78 | |
Josh Panter | 6d84f6e0e2 | |
Josh Panter | 37c769d44b | |
Josh Panter | 0277e6b114 | |
Marcos de Oliveira | 9512298328 | |
joshp | 338e0299f1 | |
joshp | 727c9d8c35 | |
joshp | abd6231fc7 | |
joshp | 33e1402ce4 | |
joshp | 93b4a263c3 | |
joshp | 09ab9fd0e6 | |
joshp | 5d37ab7c4d | |
Josh Panter | e89f6c4770 | |
Ulrich | 110fc6e680 | |
ueickmann | 3262c12253 | |
joshp | 65e50a60f4 | |
joshp | da0d928b3c |
19
README.md
19
README.md
|
@ -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,19 +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:
|
||||
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
|
||||
-------
|
||||
|
|
|
@ -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.2.1
|
||||
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.
|
||||
|
@ -233,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 );
|
||||
|
@ -254,15 +294,27 @@ function amp_have_capability( $capability ) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
if( !$return ) {
|
||||
if ( isset( $amp_default_role ) && in_array ($amp_default_role, array_keys( $amp_role_capabilities ) ) ) {
|
||||
$default_caps = $amp_role_capabilities [ $amp_default_role ];
|
||||
$return = in_array( $capability, $default_caps );
|
||||
}
|
||||
}
|
||||
|
||||
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 ) {
|
||||
|
||||
|
@ -296,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;
|
||||
|
||||
|
@ -342,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;
|
||||
|
@ -386,6 +438,7 @@ function amp_env_check() {
|
|||
ampCap::AddURL,
|
||||
ampCap::EditURL,
|
||||
ampCap::DeleteURL,
|
||||
ampCap::ShareURL,
|
||||
ampCap::Traceless,
|
||||
ampCap::ManageAnonURL,
|
||||
ampCap::ManageUsrsURL,
|
||||
|
@ -400,6 +453,7 @@ function amp_env_check() {
|
|||
ampCap::AddURL,
|
||||
ampCap::EditURL,
|
||||
ampCap::DeleteURL,
|
||||
ampCap::ShareURL,
|
||||
ampCap::Traceless,
|
||||
ampCap::ManageAnonURL,
|
||||
ampCap::APIu,
|
||||
|
@ -411,6 +465,7 @@ function amp_env_check() {
|
|||
ampCap::AddURL,
|
||||
ampCap::EditURL,
|
||||
ampCap::DeleteURL,
|
||||
ampCap::ShareURL,
|
||||
ampCap::APIu,
|
||||
ampCap::ViewStats,
|
||||
),
|
||||
|
@ -443,21 +498,11 @@ 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;
|
||||
|
||||
|
@ -492,6 +537,7 @@ function amp_current_capabilities() {
|
|||
ampCap::AddURL,
|
||||
ampCap::EditURL,
|
||||
ampCap::DeleteURL,
|
||||
ampCap::ShareURL,
|
||||
ampCap::Traceless,
|
||||
ampCap::ManageAnonURL,
|
||||
ampCap::ManageUsrsURL,
|
||||
|
@ -501,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;
|
||||
}
|
||||
|
||||
|
@ -538,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;
|
||||
|
@ -564,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
|
||||
|
@ -598,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;
|
||||
}
|
||||
|
||||
?>
|
Loading…
Reference in New Issue