Make ready for OIDC
lighter weight user validation new ampCap::traceless refactoring/beautifying dropped support for YOURLS < 1.7.3
This commit is contained in:
parent
1a18864830
commit
4f727346c7
17
README.md
17
README.md
@ -7,16 +7,19 @@ Features
|
|||||||
--------
|
--------
|
||||||
- Easily assign users to roles
|
- Easily assign users to roles
|
||||||
- Easily fine tune role permissions
|
- Easily fine tune role permissions
|
||||||
- IP based Authentication (optional)
|
- IPv4 based Authentication (optional)
|
||||||
- All plugin pages, including main management page, hidden to non-admins by default. Easy to unblock pages.
|
- 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)
|
- 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
|
- Fine(r) tuned API access
|
||||||
- PHP 7 compatible
|
- PHP 7 compatible
|
||||||
|
- No tracking of admins or editors by default
|
||||||
|
|
||||||
Requirements
|
Requirements
|
||||||
------------
|
------------
|
||||||
- YOURLS 1.7.2 (1.7.3 ready).
|
- YOURLS 1.7.3
|
||||||
- If they are isntalled, uninstall nicwaller's `authmgr` and/or Ian Barber's `Seperate Users` plugins.
|
- Incompatable Plugins:
|
||||||
|
- nicwaller's [`authmgr`](https://github.com/nicwaller/yourls-authmgr-plugin)
|
||||||
|
- Ian Barber's [`Seperate Users`](https://github.com/ianbarber/Yourls-Separate-Users)
|
||||||
|
|
||||||
Installation
|
Installation
|
||||||
------------
|
------------
|
||||||
@ -31,9 +34,9 @@ The default roles are set up as follows:
|
|||||||
|
|
||||||
Role | Capabilities
|
Role | Capabilities
|
||||||
--------------|---------------------------------------------------------------------------------------------------
|
--------------|---------------------------------------------------------------------------------------------------
|
||||||
Administrator | Can manage plugins, no limits
|
Administrator | Can manage plugins, no limits, not tracked on any
|
||||||
Editor | Can add (+API), access own and all others', edit & delete own & anon URL's
|
Editor | Can add (+API), access own and all others', edit & delete own & anon URL's, not tracked on any
|
||||||
Contributor | Can add (+API), access own and anon's, and edit & delete own URLs
|
Contributor | Can add (+API), access own and anon's, and edit & delete own URLs, not tracked on own
|
||||||
Anonymous | Can add and access (see stats, etc) anon links (If public)
|
Anonymous | Can add and access (see stats, etc) anon links (If public)
|
||||||
|
|
||||||
Configuration
|
Configuration
|
||||||
@ -68,7 +71,7 @@ $amp_allowed_plugin_pages = array(
|
|||||||
'another_plugin_slug'
|
'another_plugin_slug'
|
||||||
);
|
);
|
||||||
```
|
```
|
||||||
Explore the code to see how to set `$amp_role_capabilities` and `$amp_anon_capabilities`. These are set to defaults in the `authMgrPlus_env_check()` function.
|
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.
|
||||||
|
|
||||||
#### NOTE:
|
#### 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[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.
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
Plugin Name: Auth Manager Plus
|
Plugin Name: Auth Manager Plus
|
||||||
Plugin URI: https://github.com/joshp23/YOURLS-AuthMgrPlus
|
Plugin URI: https://github.com/joshp23/YOURLS-AuthMgrPlus
|
||||||
Description: Role Based Access Controlls with seperated user data for authenticated users
|
Description: Role Based Access Controlls with seperated user data for authenticated users
|
||||||
Version: 1.0.6
|
Version: 2.0.0
|
||||||
Author: Josh Panter, nicwaller, Ian Barber <ian.barber@gmail.com>
|
Author: Josh Panter, nicwaller, Ian Barber <ian.barber@gmail.com>
|
||||||
Author URI: https://unfettered.net
|
Author URI: https://unfettered.net
|
||||||
*/
|
*/
|
||||||
@ -24,6 +24,7 @@ class ampCap {
|
|||||||
const AddURL = 'AddURL';
|
const AddURL = 'AddURL';
|
||||||
const DeleteURL = 'DeleteURL';
|
const DeleteURL = 'DeleteURL';
|
||||||
const EditURL = 'EditURL';
|
const EditURL = 'EditURL';
|
||||||
|
const Traceless = 'Traceless';
|
||||||
const ManageAnonURL = 'ManageAnonURL';
|
const ManageAnonURL = 'ManageAnonURL';
|
||||||
const ManageUsrsURL = 'ManageUsrsURL';
|
const ManageUsrsURL = 'ManageUsrsURL';
|
||||||
const ManagePlugins = 'ManagePlugins';
|
const ManagePlugins = 'ManagePlugins';
|
||||||
@ -52,8 +53,10 @@ function amp_intercept_api() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
yourls_add_action( 'auth_successful', function() {
|
||||||
|
if( yourls_is_admin() ) amp_intercept_admin();
|
||||||
|
} );
|
||||||
|
|
||||||
yourls_add_action( 'auth_successful', 'amp_intercept_admin' );
|
|
||||||
/**
|
/**
|
||||||
* YOURLS processes most actions in the admin page. It would be ideal
|
* YOURLS processes most actions in the admin page. It would be ideal
|
||||||
* to add a unique hook for each action, but unfortunately we need to
|
* to add a unique hook for each action, but unfortunately we need to
|
||||||
@ -147,12 +150,12 @@ function amp_intercept_admin() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Cosmetic filter: removes disallowed plugins from link list
|
* Cosmetic filter: removes disallowed plugins from link list
|
||||||
*/
|
*/
|
||||||
if( yourls_is_admin() ) {
|
|
||||||
yourls_add_filter( 'admin_sublinks', 'amp_admin_sublinks' );
|
yourls_add_filter( 'admin_sublinks', 'amp_admin_sublinks' );
|
||||||
}
|
|
||||||
function amp_admin_sublinks( $links ) {
|
function amp_admin_sublinks( $links ) {
|
||||||
|
|
||||||
global $amp_allowed_plugin_pages;
|
global $amp_allowed_plugin_pages;
|
||||||
@ -171,10 +174,10 @@ function amp_admin_sublinks( $links ) {
|
|||||||
* Cosmetic filter: displays currently available roles
|
* Cosmetic filter: displays currently available roles
|
||||||
* by hovering mouse over the username in logout link.
|
* by hovering mouse over the username in logout link.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
yourls_add_filter( 'logout_link', 'amp_html_append_roles' );
|
yourls_add_filter( 'logout_link', 'amp_html_append_roles' );
|
||||||
function amp_html_append_roles( $original ) {
|
function amp_html_append_roles( $original ) {
|
||||||
$authenticated = yourls_is_valid_user();
|
if ( amp_is_valid_user() ) {
|
||||||
if ( $authenticated === true ) {
|
|
||||||
$listcaps = implode(', ', amp_current_capabilities());
|
$listcaps = implode(', ', amp_current_capabilities());
|
||||||
return '<div title="'.$listcaps.'">'.$original.'</div>';
|
return '<div title="'.$listcaps.'">'.$original.'</div>';
|
||||||
} else {
|
} else {
|
||||||
@ -217,11 +220,9 @@ function amp_have_capability( $capability ) {
|
|||||||
|
|
||||||
// Check user-role based auth
|
// Check user-role based auth
|
||||||
if( !$return ) {
|
if( !$return ) {
|
||||||
// Only users have roles.
|
// Only users have roles
|
||||||
$authenticated = yourls_is_valid_user();
|
if ( !amp_is_valid_user() ) //XXX
|
||||||
if ( $authenticated !== true )
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// List capabilities of particular user role
|
// List capabilities of particular user role
|
||||||
$user = YOURLS_USER !== false ? YOURLS_USER : NULL;
|
$user = YOURLS_USER !== false ? YOURLS_USER : NULL;
|
||||||
$user_caps = array();
|
$user_caps = array();
|
||||||
@ -281,12 +282,8 @@ function amp_admin_list_where($where) {
|
|||||||
return $where; // Allow admin/editor users to see the lot.
|
return $where; // Allow admin/editor users to see the lot.
|
||||||
|
|
||||||
$user = YOURLS_USER !== false ? YOURLS_USER : NULL;
|
$user = YOURLS_USER !== false ? YOURLS_USER : NULL;
|
||||||
if (version_compare(YOURLS_VERSION, '1.7.3') >= 0) {
|
|
||||||
$where['sql'] = $where['sql'] . " AND (`user` = :user OR `user` IS NULL) ";
|
$where['sql'] = $where['sql'] . " AND (`user` = :user OR `user` IS NULL) ";
|
||||||
$where['binds']['user'] = $user;
|
$where['binds']['user'] = $user;
|
||||||
}
|
|
||||||
else
|
|
||||||
$where = $where . " AND (`user` = $user OR `user` IS NULL) ";
|
|
||||||
|
|
||||||
return $where;
|
return $where;
|
||||||
}
|
}
|
||||||
@ -313,9 +310,7 @@ function amp_pre_yourls_infos( $keyword ) {
|
|||||||
|
|
||||||
if( yourls_is_private() && !amp_access_keyword($keyword) ) {
|
if( yourls_is_private() && !amp_access_keyword($keyword) ) {
|
||||||
|
|
||||||
$authenticated = yourls_is_valid_user();
|
if ( !amp_is_valid_user() )
|
||||||
|
|
||||||
if ( $authenticated === true )
|
|
||||||
yourls_redirect( yourls_admin_url( '?access=denied' ), 302 );
|
yourls_redirect( yourls_admin_url( '?access=denied' ), 302 );
|
||||||
else
|
else
|
||||||
yourls_redirect( YOURLS_SITE, 302 );
|
yourls_redirect( YOURLS_SITE, 302 );
|
||||||
@ -333,21 +328,29 @@ function amp_get_db_stats( $return, $where ) {
|
|||||||
global $ydb;
|
global $ydb;
|
||||||
$table_url = YOURLS_DB_TABLE_URL;
|
$table_url = YOURLS_DB_TABLE_URL;
|
||||||
$user = YOURLS_USER !== false ? YOURLS_USER : NULL;
|
$user = YOURLS_USER !== false ? YOURLS_USER : NULL;
|
||||||
if (version_compare(YOURLS_VERSION, '1.7.3') >= 0) {
|
|
||||||
$where['sql'] = $where['sql'] . " AND (`user` = :user OR `user` IS NULL) ";
|
$where['sql'] = $where['sql'] . " AND (`user` = :user OR `user` IS NULL) ";
|
||||||
$where['binds']['user'] = $user;
|
$where['binds']['user'] = $user;
|
||||||
|
|
||||||
$sql = "SELECT COUNT(keyword) as count, SUM(clicks) as sum FROM `$table_url` WHERE 1=1 " . $where['sql'];
|
$sql = "SELECT COUNT(keyword) as count, SUM(clicks) as sum FROM `$table_url` WHERE 1=1 " . $where['sql'];
|
||||||
$binds = $where['binds'];
|
$binds = $where['binds'];
|
||||||
|
|
||||||
$totals = $ydb->fetchObject($sql, $binds);
|
$totals = $ydb->fetchObject($sql, $binds);
|
||||||
} else {
|
|
||||||
$where = $where . " AND (`user` = $user OR `user` IS NULL) ";
|
|
||||||
$totals = $ydb->get_results("SELECT COUNT(keyword) as count, SUM(clicks) as sum FROM `$table_url` WHERE 1=1 " . $where );
|
|
||||||
}
|
|
||||||
$return = array( 'total_links' => $totals->count, 'total_clicks' => $totals->sum );
|
$return = array( 'total_links' => $totals->count, 'total_clicks' => $totals->sum );
|
||||||
|
|
||||||
return $return;
|
return $return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fine tune track-me-not
|
||||||
|
yourls_add_action('redirect_shorturl', 'amp_tracking');
|
||||||
|
function amp_tracking( $u, $k ) {
|
||||||
|
if( amp_is_valid_user() && ( amp_keyword_owner($k) || amp_have_capability( ampCap::Traceless ) ) ) {
|
||||||
|
// No logging
|
||||||
|
yourls_add_filter( 'shunt_update_clicks', function( $u, $k ) { return true; } );
|
||||||
|
yourls_add_filter( 'shunt_log_redirect', function( $u, $k ) { return true; } );
|
||||||
|
}
|
||||||
|
}
|
||||||
/********************* HOUSEKEEPING ************************/
|
/********************* HOUSEKEEPING ************************/
|
||||||
// Validate environment setup
|
// Validate environment setup
|
||||||
function amp_env_check() {
|
function amp_env_check() {
|
||||||
@ -368,6 +371,7 @@ function amp_env_check() {
|
|||||||
ampCap::AddURL,
|
ampCap::AddURL,
|
||||||
ampCap::EditURL,
|
ampCap::EditURL,
|
||||||
ampCap::DeleteURL,
|
ampCap::DeleteURL,
|
||||||
|
ampCap::Traceless,
|
||||||
ampCap::ManageAnonURL,
|
ampCap::ManageAnonURL,
|
||||||
ampCap::ManageUsrsURL,
|
ampCap::ManageUsrsURL,
|
||||||
ampCap::ManagePlugins,
|
ampCap::ManagePlugins,
|
||||||
@ -381,6 +385,7 @@ function amp_env_check() {
|
|||||||
ampCap::AddURL,
|
ampCap::AddURL,
|
||||||
ampCap::EditURL,
|
ampCap::EditURL,
|
||||||
ampCap::DeleteURL,
|
ampCap::DeleteURL,
|
||||||
|
ampCap::Traceless,
|
||||||
ampCap::ManageAnonURL,
|
ampCap::ManageAnonURL,
|
||||||
ampCap::APIu,
|
ampCap::APIu,
|
||||||
ampCap::ViewStats,
|
ampCap::ViewStats,
|
||||||
@ -442,14 +447,8 @@ function amp_activated() {
|
|||||||
global $ydb;
|
global $ydb;
|
||||||
|
|
||||||
$table = YOURLS_DB_TABLE_URL;
|
$table = YOURLS_DB_TABLE_URL;
|
||||||
$version = version_compare(YOURLS_VERSION, '1.7.3') >= 0;
|
|
||||||
|
|
||||||
if ($version) {
|
|
||||||
$sql = "DESCRIBE `$table`";
|
$sql = "DESCRIBE `$table`";
|
||||||
$results = $ydb->fetchObjects($sql);
|
$results = $ydb->fetchObjects($sql);
|
||||||
} else {
|
|
||||||
$results = $ydb->get_results("DESCRIBE $table");
|
|
||||||
}
|
|
||||||
|
|
||||||
$activated = false;
|
$activated = false;
|
||||||
foreach($results as $r) {
|
foreach($results as $r) {
|
||||||
@ -478,6 +477,7 @@ function amp_current_capabilities() {
|
|||||||
ampCap::AddURL,
|
ampCap::AddURL,
|
||||||
ampCap::EditURL,
|
ampCap::EditURL,
|
||||||
ampCap::DeleteURL,
|
ampCap::DeleteURL,
|
||||||
|
ampCap::Traceless,
|
||||||
ampCap::ManageAnonURL,
|
ampCap::ManageAnonURL,
|
||||||
ampCap::ManageUsrsURL,
|
ampCap::ManageUsrsURL,
|
||||||
ampCap::ManagePlugins,
|
ampCap::ManagePlugins,
|
||||||
@ -511,51 +511,33 @@ function amp_cidr_match($ip, $range) {
|
|||||||
|
|
||||||
// Check user access to a keyword ( can they see it )
|
// Check user access to a keyword ( can they see it )
|
||||||
function amp_access_keyword( $keyword ) {
|
function amp_access_keyword( $keyword ) {
|
||||||
global $ydb;
|
|
||||||
|
|
||||||
if ( amp_have_capability( ampCap::ViewAll ) )
|
$users = array( YOURLS_USER !== false ? YOURLS_USER : NULL , NULL );
|
||||||
|
$owner = amp_keyword_owner( $keyword );
|
||||||
|
if ( amp_have_capability( ampCap::ViewAll ) || in_array( $owner , $users ) )
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
$table = YOURLS_DB_TABLE_URL;
|
|
||||||
$user = YOURLS_USER !== false ? YOURLS_USER : NULL;
|
|
||||||
if (version_compare(YOURLS_VERSION, '1.7.3') >= 0) {
|
|
||||||
$binds = array( 'keyword' => $keyword, 'user' => $user);
|
|
||||||
$sql = "SELECT 1 FROM `$table` WHERE (`user` IS NULL OR `user` = :user) AND `keyword` = :keyword";
|
|
||||||
$result = $ydb->fetchAffected($sql, $binds);
|
|
||||||
} else
|
|
||||||
$result = $ydb->query("SELECT 1 FROM `$table` WHERE (`user` IS NULL OR `user` = $user) AND `keyword` = $keyword");
|
|
||||||
|
|
||||||
return $result > 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check user rights to a keyword ( can manage it )
|
// Check user rights to a keyword ( can manage it )
|
||||||
function amp_manage_keyword( $keyword, $capability ) {
|
function amp_manage_keyword( $keyword, $capability ) {
|
||||||
// only authenticated users can manaage keywords
|
// only authenticated users can manaage keywords
|
||||||
$authenticated = yourls_is_valid_user();
|
if ( !amp_is_valid_user() )
|
||||||
if ( $authenticated !== true )
|
|
||||||
return false;
|
return false;
|
||||||
// Admin?
|
// Admin?
|
||||||
if ( amp_have_capability( ampCap::ManageUsrsURL ) )
|
if ( amp_have_capability( ampCap::ManageUsrsURL ) )
|
||||||
return true;
|
return true;
|
||||||
// Editor?
|
// Editor?
|
||||||
$owner = amp_keyword_owner($keyword);
|
$owner = amp_keyword_owner($keyword);
|
||||||
if ( $owner === null ) {
|
if ( $owner === null && amp_have_capability( ampCap::ManageAnonURL ) )
|
||||||
if ( amp_have_capability( ampCap::ManageAnonURL ) ) {
|
|
||||||
return true;
|
return true;
|
||||||
} else {
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
}
|
|
||||||
// Self Edit?
|
// Self Edit?
|
||||||
$user = YOURLS_USER !== false ? YOURLS_USER : NULL;
|
$user = YOURLS_USER !== false ? YOURLS_USER : NULL;
|
||||||
if ( $owner === $user ) {
|
if ( $owner === $user && amp_have_capability( $capability ) )
|
||||||
if ( amp_have_capability( $capability ) ) {
|
|
||||||
return true;
|
return true;
|
||||||
} else {
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -563,14 +545,9 @@ function amp_manage_keyword( $keyword, $capability ) {
|
|||||||
function amp_keyword_owner( $keyword ) {
|
function amp_keyword_owner( $keyword ) {
|
||||||
global $ydb;
|
global $ydb;
|
||||||
$table = YOURLS_DB_TABLE_URL;
|
$table = YOURLS_DB_TABLE_URL;
|
||||||
|
|
||||||
if (version_compare(YOURLS_VERSION, '1.7.3') >= 0) {
|
|
||||||
$binds = array( 'keyword' => $keyword );
|
$binds = array( 'keyword' => $keyword );
|
||||||
$sql = "SELECT * FROM `$table` WHERE `keyword` = :keyword";
|
$sql = "SELECT * FROM `$table` WHERE `keyword` = :keyword";
|
||||||
$result = $ydb->fetchOne($sql, $binds);
|
$result = $ydb->fetchOne($sql, $binds);
|
||||||
} else
|
|
||||||
$result = $ydb->query("SELECT 1 FROM `$table` WHERE `keyword` = $keyword");
|
|
||||||
|
|
||||||
return $result['user'];
|
return $result['user'];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -584,13 +561,34 @@ function amp_insert_link($actions) {
|
|||||||
$table = YOURLS_DB_TABLE_URL;
|
$table = YOURLS_DB_TABLE_URL;
|
||||||
|
|
||||||
// Insert $keyword against $username
|
// Insert $keyword against $username
|
||||||
if (version_compare(YOURLS_VERSION, '1.7.3') >= 0) {
|
|
||||||
$binds = array( 'user' => $user,
|
$binds = array( 'user' => $user,
|
||||||
'keyword' => $keyword);
|
'keyword' => $keyword);
|
||||||
$sql = "UPDATE `$table` SET `user` = :user WHERE `keyword` = :keyword";
|
$sql = "UPDATE `$table` SET `user` = :user WHERE `keyword` = :keyword";
|
||||||
$result = $ydb->fetchAffected($sql, $binds);
|
$result = $ydb->fetchAffected($sql, $binds);
|
||||||
} else {
|
|
||||||
$result = $ydb->query("UPDATE `$table` SET `user` = $user WHERE `keyword` = $keyword");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Quick user validation without triggering hooks
|
||||||
|
function amp_is_valid_user() {
|
||||||
|
|
||||||
|
$valid = defined( 'YOURLS_USER' ) ? true : false;
|
||||||
|
|
||||||
|
if ( !$valid ) {
|
||||||
|
|
||||||
|
if ( yourls_is_API()
|
||||||
|
&& isset( $_REQUEST['timestamp'] ) && !empty($_REQUEST['timestamp'] )
|
||||||
|
&& isset( $_REQUEST['signature'] ) && !empty($_REQUEST['signature'] ) )
|
||||||
|
$valid = yourls_check_signature_timestamp();
|
||||||
|
elseif ( yourls_is_API()
|
||||||
|
&& !isset( $_REQUEST['timestamp'] )
|
||||||
|
&& isset( $_REQUEST['signature'] ) && !empty( $_REQUEST['signature'] ) )
|
||||||
|
$valid = yourls_check_signature();
|
||||||
|
elseif ( isset( $_REQUEST['username'] ) && isset( $_REQUEST['password'] )
|
||||||
|
&& !empty( $_REQUEST['username'] ) && !empty( $_REQUEST['password'] ) )
|
||||||
|
$valid = yourls_check_username_password();
|
||||||
|
elseif ( !yourls_is_API() && isset( $_COOKIE[ yourls_cookie_name() ] ) )
|
||||||
|
$valid = yourls_check_auth_cookie();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $valid;
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
|
Loading…
Reference in New Issue
Block a user