Version 1.0.0!
- Merge Old AuthMgr + Seperate Users plugins - Most issues in ques for both plugins have been squashed +/- 5 yrs of bugs. - Plenty of hooks for filtering data an integration - Many features of old plugins realized
This commit is contained in:
parent
3109dbcad4
commit
0f1f3db520
53
README.md
53
README.md
@ -1,15 +1,22 @@
|
|||||||
yourls-authmgr-plugin
|
YOURLS-AuthMgrPlus
|
||||||
=====================
|
=====================
|
||||||
|
|
||||||
This plugin adds role-based access controls (RBAC) to YOURLS. By assigning users to roles like "Editor" and "Contributor" you can limit the changes they are permitted to make.
|
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.
|
||||||
|
|
||||||
With access controls enabled, you can safely delegate access to the admin pages.
|
Features
|
||||||
|
--------
|
||||||
|
- Easily assign users to roles
|
||||||
|
- Easily fine tune role permissions
|
||||||
|
- IP based Authentication (optional)
|
||||||
|
- 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
|
||||||
|
|
||||||
Installation
|
Installation
|
||||||
------------
|
------------
|
||||||
1. Download the [latest release](https://github.com/nicwaller/yourls-authmgr-plugin/tags) of yourls-authmgr-plugin.
|
1. Download the [latest release](https://github.com/joshp23/YOURLS-AuthMgrPlus) of ythis plugin.
|
||||||
1. Copy the plugin folder into your `user/plugins` folder for YOURLS.
|
1. Copy the `authMgrPlus` folder into your `user/plugins` folder for YOURLS.
|
||||||
1. Set up the parameters for authmgr (details below)
|
1. Set up some parameters for authMgrPlus (details below)
|
||||||
1. Activate the plugin with the plugin manager in the YOURLS admin interface.
|
1. Activate the plugin with the plugin manager in the YOURLS admin interface.
|
||||||
|
|
||||||
Default Roles
|
Default Roles
|
||||||
@ -17,17 +24,18 @@ Default Roles
|
|||||||
The default roles are set up as follows:
|
The default roles are set up as follows:
|
||||||
|
|
||||||
Role | Capabilities
|
Role | Capabilities
|
||||||
--------------|-------------------------------------------------
|
--------------|---------------------------------------------------------------------------------------------------
|
||||||
Administrator | No Limits
|
Administrator | Can manage plugins, no limits
|
||||||
Editor | Cannot manage plugins
|
Editor | Can add (+API), access own and all others', edit & delete own & anon URL's
|
||||||
Contributor | Cannot manage plugins, edit URLs, or delete URLs
|
Contributor | Can add (+API), access own and anon's, and edit & delete own URLs
|
||||||
|
Anonymous | Can add and access (see stats, etc) anon links (If public)
|
||||||
|
|
||||||
Configuration
|
Configuration
|
||||||
-------------
|
-------------
|
||||||
Add role assignments to your `user/config.php` file.
|
Add role assignments to your `user/config.php` file.
|
||||||
|
|
||||||
```
|
```
|
||||||
$authmgr_role_assignment = array(
|
$authMgrPlus_role_assignment = array(
|
||||||
'administrator' => array(
|
'administrator' => array(
|
||||||
'your_username',
|
'your_username',
|
||||||
),
|
),
|
||||||
@ -43,31 +51,24 @@ $authmgr_role_assignment = array(
|
|||||||
You can also designate a range of IP addresses that will automatically be granted all capabilities. By default, all accesses from IPv4 localhost (127.0.0.0/8) are granted full access.
|
You can also designate a range of IP addresses that will automatically be granted all capabilities. By default, all accesses from IPv4 localhost (127.0.0.0/8) are granted full access.
|
||||||
|
|
||||||
```
|
```
|
||||||
$authmgr_admin_ipranges = array(
|
$authMgrPlus_admin_ipranges = array(
|
||||||
'127.0.0.0/8',
|
'127.0.0.0/8',
|
||||||
);
|
);
|
||||||
```
|
```
|
||||||
Plugin management and plugin pages are available to admins only by default. Individual pages can be exposed to non-admin roles like so:
|
Plugin management and plugin pages are available to admins only by default. Individual pages can be exposed to non-admin roles like so:
|
||||||
```
|
```
|
||||||
$authmgr_allowed_plugin_pages = array(
|
$authMgrPlus_allowed_plugin_pages = array(
|
||||||
'sample_page',
|
'sample_page',
|
||||||
'another_plugin_slug'
|
'another_plugin_slug'
|
||||||
);
|
);
|
||||||
```
|
```
|
||||||
|
Explore the code to see how to set `$authMgrPlus_role_capabilities` and `$authMgrPlus_anon_capabilities`. These are set to defaults in the `authMgrPlus_env_check()` function.
|
||||||
|
|
||||||
|
#### 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.
|
||||||
|
|
||||||
License
|
License
|
||||||
-------
|
-------
|
||||||
|
Copyright 2018 Joshua Panter
|
||||||
Copyright 2013 Nicholas Waller (code@nicwaller.com)
|
Copyright 2013 Nicholas Waller (code@nicwaller.com)
|
||||||
|
Copyright 2011 Ian Barber
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
586
authMgrPlus/plugin.php
Normal file
586
authMgrPlus/plugin.php
Normal file
@ -0,0 +1,586 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
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: 1.0.0
|
||||||
|
Author: Josh Panter, nicwaller, Ian Barber <ian.barber@gmail.com>
|
||||||
|
Author URI: https://unfettered.net
|
||||||
|
*/
|
||||||
|
|
||||||
|
// No direct call
|
||||||
|
if( !defined( 'YOURLS_ABSPATH' ) ) die();
|
||||||
|
|
||||||
|
/****************** SET UP CONSTANTS ******************/
|
||||||
|
|
||||||
|
class AuthMgrPlusRoles { const Administrator = 'Administrator';
|
||||||
|
const Editor = 'Editor';
|
||||||
|
const Contributor = 'Contributor';
|
||||||
|
}
|
||||||
|
|
||||||
|
class AuthMgrPlusCapability {
|
||||||
|
const ShowAdmin = 'ShowAdmin';
|
||||||
|
const AddURL = 'AddURL';
|
||||||
|
const DeleteURL = 'DeleteURL';
|
||||||
|
const EditURL = 'EditURL';
|
||||||
|
const ManageAnonURL = 'ManageAnonURL';
|
||||||
|
const ManageUsrsURL = 'ManageUsrsURL';
|
||||||
|
const ManagePlugins = 'ManagePlugins';
|
||||||
|
const API = 'API';
|
||||||
|
const APIu = 'APIu';
|
||||||
|
const ViewStats = 'ViewStats';
|
||||||
|
const ViewAll = 'ViewAll';
|
||||||
|
}
|
||||||
|
|
||||||
|
/********** Add hooks to intercept functionality in CORE **********/
|
||||||
|
|
||||||
|
yourls_add_action( 'load_template_infos', 'authMgrPlus_intercept_stats' );
|
||||||
|
function authMgrPlus_intercept_stats() {
|
||||||
|
if ( 'YOURLS_PRIVATE_INFOS' === true ) {
|
||||||
|
authMgrPlus_require_capability( AuthMgrPlusCapability::ViewStats );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
yourls_add_action( 'api', 'authMgrPlus_intercept_api' );
|
||||||
|
function authMgrPlus_intercept_api() {
|
||||||
|
if ( 'YOURLS_PRIVATE_API' === true ) {
|
||||||
|
if ( isset( $_REQUEST['shorturl'] ) || isset( $_REQUEST['stats'] ) ) {
|
||||||
|
authMgrPlus_require_capability( AuthMgrPlusCapability::APIu );
|
||||||
|
} else {
|
||||||
|
authMgrPlus_require_capability( AuthMgrPlusCapability::API );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
yourls_add_action( 'auth_successful', 'authMgrPlus_intercept_admin' );
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
* hook the admin page load itself, and try to figure out what action
|
||||||
|
* is intended.
|
||||||
|
*
|
||||||
|
* TODO: look for these hooks
|
||||||
|
*
|
||||||
|
* At this point, reasonably assume that the current request is for
|
||||||
|
* a rendering of the admin page.
|
||||||
|
*/
|
||||||
|
function authMgrPlus_intercept_admin() {
|
||||||
|
authMgrPlus_require_capability( authMgrPlusCapability::ShowAdmin );
|
||||||
|
|
||||||
|
// we use this GET param to send up a feedback notice to user
|
||||||
|
if ( isset( $_GET['access'] ) && $_GET['access']=='denied' ) {
|
||||||
|
yourls_add_notice('Access Denied');
|
||||||
|
}
|
||||||
|
|
||||||
|
$action_capability_map = array(
|
||||||
|
'add' => AuthMgrPlusCapability::AddURL,
|
||||||
|
'delete' => AuthMgrPlusCapability::DeleteURL,
|
||||||
|
'edit_display' => AuthMgrPlusCapability::EditURL,
|
||||||
|
'edit_save' => AuthMgrPlusCapability::EditURL,
|
||||||
|
'activate' => AuthMgrPlusCapability::ManagePlugins,
|
||||||
|
'deactivate' => AuthMgrPlusCapability::ManagePlugins,
|
||||||
|
);
|
||||||
|
// allow manipulation of this list ( be mindfull of extending Authmp Capability class if needed )
|
||||||
|
yourls_apply_filter( 'authMgrPlus_action_capability_map', $action_capability_map);
|
||||||
|
|
||||||
|
// 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( 'AuthMgrPlus_restricted_ajax_actions', $restricted_actions );
|
||||||
|
|
||||||
|
$action_keyword = $_REQUEST['action'];
|
||||||
|
$cap_needed = $action_capability_map[$action_keyword];
|
||||||
|
|
||||||
|
// Check the action against those boundaries
|
||||||
|
if ( in_array( $action_keyword, $restricted_actions) ) {
|
||||||
|
$keyword = $_REQUEST['keyword'];
|
||||||
|
$do = authMgrPlus_manage_keyword( $keyword, $cap_needed );
|
||||||
|
} else {
|
||||||
|
$do = authMgrPlus_have_capability( $cap_needed );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( $do !== true ) {
|
||||||
|
$err = array();
|
||||||
|
$err['status'] = 'fail';
|
||||||
|
$err['code'] = 'error:authorization';
|
||||||
|
$err['message'] = 'Access Denied';
|
||||||
|
$err['errorCode'] = '403';
|
||||||
|
echo json_encode( $err );
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Intercept requests for plugin management
|
||||||
|
if( isset( $_SERVER['REQUEST_URI'] ) && preg_match('/\/admin\/plugins\.php.*/', $_SERVER['REQUEST_URI'] ) ) {
|
||||||
|
// Is this a plugin page request?
|
||||||
|
if ( isset( $_REQUEST['page'] ) ) {
|
||||||
|
// Is this an allowed plugin?
|
||||||
|
global $authMgrPlus_allowed_plugin_pages;
|
||||||
|
if ( authMgrPlus_have_capability( authMgrPlusCapability::ManagePlugins ) !== true) {
|
||||||
|
$r = $_REQUEST['page'];
|
||||||
|
if(!in_array($r, $authMgrPlus_allowed_plugin_pages ) ) {
|
||||||
|
yourls_redirect( yourls_admin_url( '?access=denied' ), 302 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Should this user touch plugins?
|
||||||
|
if ( authMgrPlus_have_capability( AuthMgrPlusCapability::ManagePlugins ) !== true) {
|
||||||
|
yourls_redirect( yourls_admin_url( '?access=denied' ), 302 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// intercept requests for global plugin management actions
|
||||||
|
if (isset( $_REQUEST['plugin'] ) ) {
|
||||||
|
$action_keyword = $_REQUEST['action'];
|
||||||
|
$cap_needed = $action_capability_map[$action_keyword];
|
||||||
|
if ( $cap_needed !== NULL && authMgrPlus_have_capability( $cap_needed ) !== true) {
|
||||||
|
yourls_redirect( yourls_admin_url( '?access=denied' ), 302 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Cosmetic filter: removes disallowed plugins from link list
|
||||||
|
*/
|
||||||
|
if( yourls_is_admin() ) {
|
||||||
|
yourls_add_filter( 'admin_sublinks', 'authMgrPlus_admin_sublinks' );
|
||||||
|
}
|
||||||
|
function authMgrPlus_admin_sublinks( $links ) {
|
||||||
|
|
||||||
|
global $authMgrPlus_allowed_plugin_pages;
|
||||||
|
|
||||||
|
if ( authMgrPlus_have_capability( AuthMgrPlusCapability::ManagePlugins ) !== true) {
|
||||||
|
foreach( $links['plugins'] as $link => $ar ) {
|
||||||
|
if(!in_array($link, $authMgrPlus_allowed_plugin_pages) )
|
||||||
|
unset($links['plugins'][$link]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sort($links['plugins']);
|
||||||
|
return $links;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Cosmetic filter: displays currently available roles
|
||||||
|
* by hovering mouse over the username in logout link.
|
||||||
|
*/
|
||||||
|
yourls_add_filter( 'logout_link', 'authMgrPlus_html_append_roles' );
|
||||||
|
function authMgrPlus_html_append_roles( $original ) {
|
||||||
|
$authenticated = yourls_is_valid_user();
|
||||||
|
if ( $authenticated === true ) {
|
||||||
|
$listcaps = implode(', ', authMgrPlus_current_capabilities());
|
||||||
|
return '<div title="'.$listcaps.'">'.$original.'</div>';
|
||||||
|
} else {
|
||||||
|
return $original;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************** CAPABILITY TESTING ****************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If capability is not permitted in current context, then abort.
|
||||||
|
* This is the most basic way to intercept unauthorized usage.
|
||||||
|
*/
|
||||||
|
// TODO: API responses!
|
||||||
|
function authMgrPlus_require_capability( $capability ) {
|
||||||
|
if ( !authMgrPlus_have_capability( $capability ) ) {
|
||||||
|
// If the user can't view admin interface, return a plain error.
|
||||||
|
if ( !authMgrPlus_have_capability( AuthMgrPlusCapability::ShowAdmin ) ) {
|
||||||
|
// header("HTTP/1.0 403 Forbidden");
|
||||||
|
die('Require permissions to show admin interface.');
|
||||||
|
}
|
||||||
|
// Otherwise, render errors in admin interface
|
||||||
|
yourls_redirect( yourls_admin_url( '?access=denied' ), 302 );
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Heart of system - Can the user do "X"?
|
||||||
|
function authMgrPlus_have_capability( $capability ) {
|
||||||
|
|
||||||
|
global $authMgrPlus_anon_capabilities;
|
||||||
|
global $authMgrPlus_role_capabilities;
|
||||||
|
global $authMgrPlus_admin_ipranges;
|
||||||
|
|
||||||
|
// Make sure the environment has been setup
|
||||||
|
authMgrPlus_env_check();
|
||||||
|
|
||||||
|
// Check anon capabilities
|
||||||
|
$return = in_array( $capability, $authMgrPlus_anon_capabilities );
|
||||||
|
|
||||||
|
// Check user-role based auth
|
||||||
|
if( !$return ) {
|
||||||
|
// Only users have roles.
|
||||||
|
$authenticated = yourls_is_valid_user();
|
||||||
|
if ( $authenticated !== true )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// List capabilities of particular user role
|
||||||
|
$user_caps = array();
|
||||||
|
foreach ( $authMgrPlus_role_capabilities as $rolename => $rolecaps ) {
|
||||||
|
if ( authMgrPlus_user_has_role( YOURLS_USER, $rolename ) ) {
|
||||||
|
$user_caps = array_merge( $user_caps, $rolecaps );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$user_caps = array_unique( $user_caps );
|
||||||
|
// Is the requested capability in this list?
|
||||||
|
$return = in_array( $capability, $user_caps );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is user connecting from an admin designated IP?
|
||||||
|
if( !$return ) {
|
||||||
|
// the array of ranges: '127.0.0.0/8' will always be admin
|
||||||
|
foreach ($authMgrPlus_admin_ipranges as $range) {
|
||||||
|
$return = authMgrPlus_cidr_match( $_SERVER['REMOTE_ADDR'], $range );
|
||||||
|
if( $return )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine whether a specific user has a role.
|
||||||
|
function authMgrPlus_user_has_role( $username, $rolename ) {
|
||||||
|
|
||||||
|
global $authMgrPlus_role_assignment;
|
||||||
|
|
||||||
|
// if no role assignments are created, grant everything FIXME: Make 'admin'
|
||||||
|
// so the site still works even if stuff is configured wrong
|
||||||
|
if ( empty( $authMgrPlus_role_assignment ) )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// do this the case-insensitive way
|
||||||
|
// the entire array was made lowercase in environment check
|
||||||
|
$username = strtolower($username);
|
||||||
|
$rolename = strtolower($rolename);
|
||||||
|
|
||||||
|
// if the role doesn't exist, give up now.
|
||||||
|
if ( !in_array( $rolename, array_keys( $authMgrPlus_role_assignment ) ) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
$users_in_role = $authMgrPlus_role_assignment[$rolename];
|
||||||
|
return in_array( $username, $users_in_role );
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************* KEYWORD OWNERSHIP ************************/
|
||||||
|
|
||||||
|
// Filter out restricted access to keyword data in...
|
||||||
|
// Admin list
|
||||||
|
yourls_add_filter( 'admin_list_where', 'authMgrPlus_admin_list_where' );
|
||||||
|
function authMgrPlus_admin_list_where($where) {
|
||||||
|
|
||||||
|
if ( authMgrPlus_have_capability( AuthMgrPlusCapability::ViewAll ) )
|
||||||
|
return $where; // Allow admin/editor users to see the lot.
|
||||||
|
|
||||||
|
$user = YOURLS_USER;
|
||||||
|
if (version_compare(YOURLS_VERSION, '1.7.3') >= 0) {
|
||||||
|
$where['sql'] = $where['sql'] . " AND (`user` = :user OR `user` IS NULL) ";
|
||||||
|
$where['binds']['user'] = $user;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
$where = $where . " AND (`user` = $user OR `user` IS NULL) ";
|
||||||
|
|
||||||
|
return $where;
|
||||||
|
}
|
||||||
|
// API stats
|
||||||
|
yourls_add_filter( 'api_url_stats', 'authMgrPlus_api_url_stats' );
|
||||||
|
function authMgrPlus_api_url_stats( $return, $shorturl ) {
|
||||||
|
$keyword = str_replace( YOURLS_SITE . '/' , '', $shorturl ); // accept either 'http://ozh.in/abc' or 'abc'
|
||||||
|
$keyword = yourls_sanitize_string( $keyword );
|
||||||
|
$keyword = addslashes($keyword);
|
||||||
|
|
||||||
|
if(authMgrPlus_access_keyword($keyword))
|
||||||
|
return $return;
|
||||||
|
else
|
||||||
|
return array('simple' => "URL is owned by another user", 'message' => 'URL is owned by another user', 'errorCode' => 403);
|
||||||
|
}
|
||||||
|
// Info pages
|
||||||
|
yourls_add_action( 'pre_yourls_infos', 'authMgrPlus_pre_yourls_infos' );
|
||||||
|
function authMgrPlus_pre_yourls_infos( $keyword ) {
|
||||||
|
if( !authMgrPlus_access_keyword($keyword) ) {
|
||||||
|
$authenticated = yourls_is_valid_user();
|
||||||
|
if ( $authenticated === true )
|
||||||
|
yourls_redirect( yourls_admin_url( '?access=denied' ), 302 );
|
||||||
|
else
|
||||||
|
yourls_redirect( YOURLS_SITE, 302 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DB stats
|
||||||
|
yourls_add_filter( 'get_db_stats', 'authMgrPlus_get_db_stats' );
|
||||||
|
function authMgrPlus_get_db_stats( $return, $where ) {
|
||||||
|
|
||||||
|
if ( authMgrPlus_have_capability( AuthMgrPlusCapability::ViewAll ) )
|
||||||
|
return $return; // Allow admin/editor users to see the lot.
|
||||||
|
|
||||||
|
// or... filter results
|
||||||
|
global $ydb;
|
||||||
|
$table_url = YOURLS_DB_TABLE_URL;
|
||||||
|
$user = YOURLS_USER;
|
||||||
|
if (version_compare(YOURLS_VERSION, '1.7.3') >= 0) {
|
||||||
|
$where['sql'] = $where['sql'] . " AND (`user` = :user OR `user` IS NULL) ";
|
||||||
|
$where['binds']['user'] = $user;
|
||||||
|
$sql = "SELECT COUNT(keyword) as count, SUM(clicks) as sum FROM `$table_url` WHERE 1=1 " . $where['sql'];
|
||||||
|
$binds = $where['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 $return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************* HOUSEKEEPING ************************/
|
||||||
|
// Validate environment setup
|
||||||
|
function authMgrPlus_env_check() {
|
||||||
|
global $authMgrPlus_anon_capabilities;
|
||||||
|
global $authMgrPlus_role_capabilities;
|
||||||
|
global $authMgrPlus_role_assignment;
|
||||||
|
global $authMgrPlus_admin_ipranges;
|
||||||
|
global $authMgrPlus_allowed_plugin_pages;
|
||||||
|
|
||||||
|
if ( !isset( $authMgrPlus_anon_capabilities) ) {
|
||||||
|
$authMgrPlus_anon_capabilities = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !isset( $authMgrPlus_role_capabilities) ) {
|
||||||
|
$authMgrPlus_role_capabilities = array(
|
||||||
|
AuthMgrPlusRoles::Administrator => array(
|
||||||
|
AuthMgrPlusCapability::ShowAdmin,
|
||||||
|
AuthMgrPlusCapability::AddURL,
|
||||||
|
AuthMgrPlusCapability::EditURL,
|
||||||
|
AuthMgrPlusCapability::DeleteURL,
|
||||||
|
AuthMgrPlusCapability::ManageAnonURL,
|
||||||
|
AuthMgrPlusCapability::ManageUsrsURL,
|
||||||
|
AuthMgrPlusCapability::ManagePlugins,
|
||||||
|
AuthMgrPlusCapability::API,
|
||||||
|
AuthMgrPlusCapability::APIu,
|
||||||
|
AuthMgrPlusCapability::ViewStats,
|
||||||
|
AuthMgrPlusCapability::ViewAll,
|
||||||
|
),
|
||||||
|
AuthMgrPlusRoles::Editor => array(
|
||||||
|
AuthMgrPlusCapability::ShowAdmin,
|
||||||
|
AuthMgrPlusCapability::AddURL,
|
||||||
|
AuthMgrPlusCapability::EditURL,
|
||||||
|
AuthMgrPlusCapability::DeleteURL,
|
||||||
|
AuthMgrPlusCapability::ManageAnonURL,
|
||||||
|
AuthMgrPlusCapability::APIu,
|
||||||
|
AuthMgrPlusCapability::ViewStats,
|
||||||
|
AuthMgrPlusCapability::ViewAll,
|
||||||
|
),
|
||||||
|
AuthMgrPlusRoles::Contributor => array(
|
||||||
|
AuthMgrPlusCapability::ShowAdmin,
|
||||||
|
AuthMgrPlusCapability::AddURL,
|
||||||
|
AuthMgrPlusCapability::EditURL,
|
||||||
|
AuthMgrPlusCapability::DeleteURL,
|
||||||
|
AuthMgrPlusCapability::APIu,
|
||||||
|
AuthMgrPlusCapability::ViewStats,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !isset( $authMgrPlus_role_assignment ) ) {
|
||||||
|
$authMgrPlus_role_assignment = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !isset( $authMgrPlus_admin_ipranges ) ) {
|
||||||
|
$authMgrPlus_admin_ipranges = array(
|
||||||
|
'127.0.0.0/8',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !isset( $authMgrPlus_allowed_plugin_pages ) ) {
|
||||||
|
$authMgrPlus_allowed_plugin_pages = array(
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// convert role assignment table to lower case if it hasn't been done already
|
||||||
|
// this makes searches much easier!
|
||||||
|
$authMgrPlus_role_assignment_lower = array();
|
||||||
|
foreach ( $authMgrPlus_role_assignment as $key => $value ) {
|
||||||
|
$t_key = strtolower( $key );
|
||||||
|
$t_value = array_map('strtolower', $value);
|
||||||
|
$authMgrPlus_role_assignment_lower[$t_key] = $t_value;
|
||||||
|
}
|
||||||
|
$authMgrPlus_role_assignment = $authMgrPlus_role_assignment_lower;
|
||||||
|
unset($authMgrPlus_role_assignment_lower);
|
||||||
|
|
||||||
|
// allow manipulation of env by other plugins
|
||||||
|
// be mindfull of extending AuthMgrPlusCapability and AuthMgrPlusRoles classes if needed
|
||||||
|
$a = $authMgrPlus_anon_capabilities;
|
||||||
|
$b = $authMgrPlus_role_capabilities;
|
||||||
|
$c = $authMgrPlus_role_assignment;
|
||||||
|
$d = $authMgrPlus_admin_ipranges;
|
||||||
|
$e = $authMgrPlus_allowed_plugin_pages;
|
||||||
|
|
||||||
|
yourls_apply_filter( 'authMgrPlus_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', 'authMgrPlus_activated' );
|
||||||
|
function authMgrPlus_activated() {
|
||||||
|
global $ydb;
|
||||||
|
|
||||||
|
$table = YOURLS_DB_TABLE_URL;
|
||||||
|
$version = version_compare(YOURLS_VERSION, '1.7.3') >= 0;
|
||||||
|
|
||||||
|
if ($version) {
|
||||||
|
$sql = "DESCRIBE `$table`";
|
||||||
|
$results = $ydb->fetchObjects($sql);
|
||||||
|
} else {
|
||||||
|
$results = $ydb->get_results("DESCRIBE $table");
|
||||||
|
}
|
||||||
|
|
||||||
|
$activated = false;
|
||||||
|
foreach($results as $r) {
|
||||||
|
if($r->Field == 'user') {
|
||||||
|
$activated = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!$activated) {
|
||||||
|
if ($version) {
|
||||||
|
$sql = "ALTER TABLE `$table` ADD `user` VARCHAR(255) NULL)";
|
||||||
|
$insert = $ydb->fetchAffected($sql);
|
||||||
|
} else {
|
||||||
|
$ydb->query("ALTER TABLE `$table` ADD `user` VARCHAR(255) NULL");
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/***************** HELPER FUNCTIONS ********************/
|
||||||
|
|
||||||
|
// List currently available capabilities
|
||||||
|
function authMgrPlus_current_capabilities() {
|
||||||
|
$current_capabilities = array();
|
||||||
|
$all_capabilities = array(
|
||||||
|
AuthMgrPlusCapability::ShowAdmin,
|
||||||
|
AuthMgrPlusCapability::AddURL,
|
||||||
|
AuthMgrPlusCapability::EditURL,
|
||||||
|
AuthMgrPlusCapability::DeleteURL,
|
||||||
|
AuthMgrPlusCapability::ManageAnonURL,
|
||||||
|
AuthMgrPlusCapability::ManageUsrsURL,
|
||||||
|
AuthMgrPlusCapability::ManagePlugins,
|
||||||
|
AuthMgrPlusCapability::API,
|
||||||
|
AuthMgrPlusCapability::APIu,
|
||||||
|
AuthMgrPlusCapability::ViewStats,
|
||||||
|
AuthMgrPlusCapability::ViewAll,
|
||||||
|
);
|
||||||
|
// allow manipulation of this list ( be mindfull of extending the AuthMgrPlusCapability class if needed )
|
||||||
|
yourls_apply_filter( 'authMgrPlus_current_capabilities', $all_capabilities);
|
||||||
|
|
||||||
|
foreach ( $all_capabilities as $cap ) {
|
||||||
|
if ( authMgrPlus_have_capability( $cap ) ) {
|
||||||
|
$current_capabilities[] = $cap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $current_capabilities;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for IP in a range
|
||||||
|
// from: http://stackoverflow.com/questions/594112/matching-an-ip-to-a-cidr-mask-in-php5
|
||||||
|
function authMgrPlus_cidr_match($ip, $range) {
|
||||||
|
list ($subnet, $bits) = explode('/', $range);
|
||||||
|
$ip = ip2long($ip);
|
||||||
|
$subnet = ip2long($subnet);
|
||||||
|
$mask = -1 << (32 - $bits);
|
||||||
|
$subnet &= $mask; # nb: in case the supplied subnet wasn't correctly aligned
|
||||||
|
return ($ip & $mask) == $subnet;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check user access to a keyword ( can they see it )
|
||||||
|
function authMgrPlus_access_keyword( $keyword ) {
|
||||||
|
global $ydb;
|
||||||
|
|
||||||
|
if ( authMgrPlus_have_capability( AuthMgrPlusCapability::ViewAll ) )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
$table = YOURLS_DB_TABLE_URL;
|
||||||
|
$user = null;
|
||||||
|
if(defined('YOURLS_USER'))
|
||||||
|
$user = YOURLS_USER;
|
||||||
|
|
||||||
|
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 )
|
||||||
|
function authMgrPlus_manage_keyword( $keyword, $capability ) {
|
||||||
|
// only authenticated users can manaage keywords
|
||||||
|
$authenticated = yourls_is_valid_user();
|
||||||
|
if ( $authenticated !== true )
|
||||||
|
return false;
|
||||||
|
// Admin?
|
||||||
|
if ( authMgrPlus_have_capability( AuthMgrPlusCapability::ManageUsrsURL ) )
|
||||||
|
return true;
|
||||||
|
// Editor?
|
||||||
|
$owner = authMgrPlus_keyword_owner();
|
||||||
|
if ( $owner === null ) {
|
||||||
|
if ( authMgrPlus_have_capability( AuthMgrPlusCapability::ManageAnonURL ) ) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Self Edit?
|
||||||
|
$user = YOURLS_USER;
|
||||||
|
if ( $owner === $user ) {
|
||||||
|
if ( authMgrPlus_have_capability( $capability ) ) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Check keyword ownership
|
||||||
|
function authMgrPlus_keyword_owner( $keyword ) {
|
||||||
|
global $ydb;
|
||||||
|
$table = YOURLS_DB_TABLE_URL;
|
||||||
|
|
||||||
|
if (version_compare(YOURLS_VERSION, '1.7.3') >= 0) {
|
||||||
|
$binds = array( 'keyword' => $keyword );
|
||||||
|
$sql = "SELECT * FROM `$table` WHERE `keyword` = :keyword";
|
||||||
|
$result = $ydb->fetchOne($sql, $binds);
|
||||||
|
} else
|
||||||
|
$result = $ydb->query("SELECT 1 FROM `$table` WHERE `keyword` = $keyword");
|
||||||
|
|
||||||
|
return $result['user'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Record user info on keyword creation
|
||||||
|
yourls_add_action( 'insert_link', 'authMgrPlus_insert_link' );
|
||||||
|
function authMgrPlus_insert_link($actions) {
|
||||||
|
global $ydb;
|
||||||
|
|
||||||
|
$keyword = $actions[2];
|
||||||
|
$user = YOURLS_USER;
|
||||||
|
$table = YOURLS_DB_TABLE_URL;
|
||||||
|
|
||||||
|
// Insert $keyword against $username
|
||||||
|
if (version_compare(YOURLS_VERSION, '1.7.3') >= 0) {
|
||||||
|
$binds = array( 'user' => $user,
|
||||||
|
'keyword' => $keyword);
|
||||||
|
$sql = "UPDATE `$table` SET `user` = :user WHERE `keyword` = :keyword";
|
||||||
|
$result = $ydb->fetchAffected($sql, $binds);
|
||||||
|
} else {
|
||||||
|
$result = $ydb->query("UPDATE `$table` SET `user` = $user WHERE `keyword` = $keyword");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
@ -1,369 +0,0 @@
|
|||||||
<?php
|
|
||||||
/*
|
|
||||||
Plugin Name: Authorization Manager
|
|
||||||
Plugin URI: https://github.com/nicwaller/yourls-authmgr-plugin
|
|
||||||
Description: Restrict classes of users to specific functions
|
|
||||||
Version: 0.11.1
|
|
||||||
Author: nicwaller
|
|
||||||
Author URI: https://github.com/nicwaller
|
|
||||||
*/
|
|
||||||
|
|
||||||
// No direct call
|
|
||||||
if( !defined( 'YOURLS_ABSPATH' ) ) die();
|
|
||||||
|
|
||||||
/****************** SET UP CONSTANTS ******************/
|
|
||||||
|
|
||||||
class AuthmgrRoles {
|
|
||||||
const Administrator = 'Administrator';
|
|
||||||
const Editor = 'Editor';
|
|
||||||
const Contributor = 'Contributor';
|
|
||||||
}
|
|
||||||
|
|
||||||
class AuthmgrCapability {
|
|
||||||
const ShowAdmin = 'ShowAdmin';
|
|
||||||
const AddURL = 'AddURL';
|
|
||||||
const DeleteURL = 'DeleteURL';
|
|
||||||
const EditURL = 'EditURL';
|
|
||||||
const ManagePlugins = 'ManagePlugins';
|
|
||||||
const API = 'API';
|
|
||||||
const APIu = 'APIu';
|
|
||||||
const ViewStats = 'ViewStats';
|
|
||||||
}
|
|
||||||
|
|
||||||
/********** Add hooks to intercept functionality in CORE **********/
|
|
||||||
|
|
||||||
yourls_add_action( 'load_template_infos', 'authmgr_intercept_stats' );
|
|
||||||
function authmgr_intercept_stats() {
|
|
||||||
if ( 'YOURLS_PRIVATE_INFOS' === true ) {
|
|
||||||
authmgr_require_capability( AuthmgrCapability::ViewStats );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
yourls_add_action( 'api', 'authmgr_intercept_api' );
|
|
||||||
function authmgr_intercept_api() {
|
|
||||||
if ( 'YOURLS_PRIVATE_API' === true ) {
|
|
||||||
if ( isset( $_REQUEST['shorturl'] ) ) {
|
|
||||||
authmgr_require_capability( AuthmgrCapability::APIu );
|
|
||||||
} else {
|
|
||||||
authmgr_require_capability( AuthmgrCapability::API );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
yourls_add_action( 'auth_successful', 'authmgr_intercept_admin' );
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
* hook the admin page load itself, and try to figure out what action
|
|
||||||
* is intended.
|
|
||||||
*
|
|
||||||
* TODO: look for these hooks
|
|
||||||
*
|
|
||||||
* At this point, reasonably assume that the current request is for
|
|
||||||
* a rendering of the admin page.
|
|
||||||
*/
|
|
||||||
function authmgr_intercept_admin() {
|
|
||||||
authmgr_require_capability( AuthmgrCapability::ShowAdmin );
|
|
||||||
|
|
||||||
// we use this GET param to send up a feedback notice to user
|
|
||||||
if ( isset( $_GET['access'] ) && $_GET['access']=='denied' ) {
|
|
||||||
yourls_add_notice('Access Denied');
|
|
||||||
}
|
|
||||||
|
|
||||||
$action_capability_map = array(
|
|
||||||
'add' => AuthmgrCapability::AddURL,
|
|
||||||
'delete' => AuthmgrCapability::DeleteURL,
|
|
||||||
'edit_display' => AuthmgrCapability::EditURL,
|
|
||||||
'edit_save' => AuthmgrCapability::EditURL,
|
|
||||||
'activate' => AuthmgrCapability::ManagePlugins,
|
|
||||||
'deactivate' => AuthmgrCapability::ManagePlugins,
|
|
||||||
);
|
|
||||||
// allow manipulation of this list ( be mindfull of extending Authmgr Capability class if needed )
|
|
||||||
yourls_apply_filter( 'authmgr_action_capability_map', $action_capability_map);
|
|
||||||
|
|
||||||
// Intercept requests for plugin management
|
|
||||||
if( isset( $_SERVER['REQUEST_URI'] ) && preg_match('/\/admin\/plugins\.php.*/', $_SERVER['REQUEST_URI'] ) ) {
|
|
||||||
// Is this a plugin page request?
|
|
||||||
if ( isset( $_REQUEST['page'] ) ) {
|
|
||||||
// Is this an allowed plugin?
|
|
||||||
global $authmgr_allowed_plugin_pages;
|
|
||||||
if ( authmgr_have_capability( AuthmgrCapability::ManagePlugins ) !== true) {
|
|
||||||
$r = $_REQUEST['page'];
|
|
||||||
if(!in_array($r, $authmgr_allowed_plugin_pages ) ) {
|
|
||||||
yourls_redirect( yourls_admin_url( '?access=denied' ), 302 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Should this user touch plugins?
|
|
||||||
if ( authmgr_have_capability( AuthmgrCapability::ManagePlugins ) !== true) {
|
|
||||||
yourls_redirect( yourls_admin_url( '?access=denied' ), 302 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// intercept requests for global plugin management actions
|
|
||||||
if (isset( $_REQUEST['plugin'] ) ) {
|
|
||||||
$action_keyword = $_REQUEST['action'];
|
|
||||||
$cap_needed = $action_capability_map[$action_keyword];
|
|
||||||
if ( $cap_needed !== NULL && authmgr_have_capability( $cap_needed ) !== true) {
|
|
||||||
yourls_redirect( yourls_admin_url( '?access=denied' ), 302 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Key actions like Add/Edit/Delete are AJAX requests
|
|
||||||
if ( yourls_is_Ajax() ) {
|
|
||||||
$action_keyword = $_REQUEST['action'];
|
|
||||||
$cap_needed = $action_capability_map[$action_keyword];
|
|
||||||
if ( authmgr_have_capability( $cap_needed ) !== true) {
|
|
||||||
$err = array();
|
|
||||||
$err['status'] = 'fail';
|
|
||||||
$err['code'] = 'error:authorization';
|
|
||||||
$err['message'] = 'Access Denied';
|
|
||||||
$err['errorCode'] = '403';
|
|
||||||
echo json_encode( $err );
|
|
||||||
die();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* Cosmetic filter: removes disallowed plugins from link list
|
|
||||||
*/
|
|
||||||
if( yourls_is_admin() ) {
|
|
||||||
yourls_add_filter( 'admin_sublinks', 'authmgr_admin_sublinks' );
|
|
||||||
}
|
|
||||||
function authmgr_admin_sublinks( $links ) {
|
|
||||||
|
|
||||||
global $authmgr_allowed_plugin_pages;
|
|
||||||
|
|
||||||
if ( authmgr_have_capability( AuthmgrCapability::ManagePlugins ) !== true) {
|
|
||||||
foreach( $links['plugins'] as $link => $ar ) {
|
|
||||||
if(!in_array($link, $authmgr_allowed_plugin_pages) )
|
|
||||||
unset($links['plugins'][$link]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sort($links['plugins']);
|
|
||||||
return $links;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Cosmetic filter: displays currently available roles
|
|
||||||
* by hovering mouse over the username in logout link.
|
|
||||||
*/
|
|
||||||
yourls_add_filter( 'logout_link', 'authmgr_html_append_roles' );
|
|
||||||
function authmgr_html_append_roles( $original ) {
|
|
||||||
$authenticated = yourls_is_valid_user();
|
|
||||||
if ( $authenticated === true ) {
|
|
||||||
$listcaps = implode(', ', authmgr_current_capabilities());
|
|
||||||
return '<div title="'.$listcaps.'">'.$original.'</div>';
|
|
||||||
} else {
|
|
||||||
return $original;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**************** CAPABILITY TESTING ****************/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If capability is not permitted in current context, then abort.
|
|
||||||
* This is the most basic way to intercept unauthorized usage.
|
|
||||||
*/
|
|
||||||
// TODO: API responses!
|
|
||||||
function authmgr_require_capability( $capability ) {
|
|
||||||
if ( !authmgr_have_capability( $capability ) ) {
|
|
||||||
// If the user can't view admin interface, return a plain error.
|
|
||||||
if ( !authmgr_have_capability( AuthmgrCapability::ShowAdmin ) ) {
|
|
||||||
header("HTTP/1.0 403 Forbidden");
|
|
||||||
die('Require permissions to show admin interface.');
|
|
||||||
}
|
|
||||||
// Otherwise, render errors in admin interface
|
|
||||||
yourls_redirect( yourls_admin_url( '?access=denied' ), 302 );
|
|
||||||
die();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Heart of system
|
|
||||||
function authmgr_have_capability( $capability ) {
|
|
||||||
|
|
||||||
global $authmgr_anon_capabilities;
|
|
||||||
global $authmgr_role_capabilities;
|
|
||||||
global $authmgr_admin_ipranges;
|
|
||||||
|
|
||||||
// Make sure the environment has been setup
|
|
||||||
authmgr_env_check();
|
|
||||||
|
|
||||||
// Check anon capabilities
|
|
||||||
$return = in_array( $capability, $authmgr_anon_capabilities );
|
|
||||||
|
|
||||||
// Check user-role based auth
|
|
||||||
if( !$return ) {
|
|
||||||
// Only users have roles.
|
|
||||||
$authenticated = yourls_is_valid_user();
|
|
||||||
if ( $authenticated !== true )
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// List capabilities of particular user role
|
|
||||||
$user_caps = array();
|
|
||||||
foreach ( $authmgr_role_capabilities as $rolename => $rolecaps ) {
|
|
||||||
if ( authmgr_user_has_role( YOURLS_USER, $rolename ) ) {
|
|
||||||
$user_caps = array_merge( $user_caps, $rolecaps );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$user_caps = array_unique( $user_caps );
|
|
||||||
// Is the requested capability in this list?
|
|
||||||
$return = in_array( $capability, $user_caps );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Is user connecting from an admin designated IP?
|
|
||||||
if( !$return ) {
|
|
||||||
// the array of ranges: '127.0.0.0/8' will always be admin
|
|
||||||
foreach ($authmgr_admin_ipranges as $range) {
|
|
||||||
$return = authmgr_cidr_match( $_SERVER['REMOTE_ADDR'], $range );
|
|
||||||
if( $return )
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Determine whether a specific user has a role.
|
|
||||||
function authmgr_user_has_role( $username, $rolename ) {
|
|
||||||
|
|
||||||
global $authmgr_role_assignment;
|
|
||||||
|
|
||||||
// if no role assignments are created, grant everything FIXME: Make 'admin'
|
|
||||||
// so the site still works even if stuff is configured wrong
|
|
||||||
if ( empty( $authmgr_role_assignment ) )
|
|
||||||
return true;
|
|
||||||
|
|
||||||
// do this the case-insensitive way
|
|
||||||
// the entire array was made lowercase in environment check
|
|
||||||
$username = strtolower($username);
|
|
||||||
$rolename = strtolower($rolename);
|
|
||||||
|
|
||||||
// if the role doesn't exist, give up now.
|
|
||||||
if ( !in_array( $rolename, array_keys( $authmgr_role_assignment ) ) )
|
|
||||||
return false;
|
|
||||||
|
|
||||||
$users_in_role = $authmgr_role_assignment[$rolename];
|
|
||||||
return in_array( $username, $users_in_role );
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************* VALIDATE CONFIGURATION ************************/
|
|
||||||
|
|
||||||
function authmgr_env_check() {
|
|
||||||
global $authmgr_anon_capabilities;
|
|
||||||
global $authmgr_role_capabilities;
|
|
||||||
global $authmgr_role_assignment;
|
|
||||||
global $authmgr_admin_ipranges;
|
|
||||||
global $authmgr_allowed_plugin_pages;
|
|
||||||
|
|
||||||
if ( !isset( $authmgr_anon_capabilities) ) {
|
|
||||||
$authmgr_anon_capabilities = array();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( !isset( $authmgr_role_capabilities) ) {
|
|
||||||
$authmgr_role_capabilities = array(
|
|
||||||
AuthmgrRoles::Administrator => array(
|
|
||||||
AuthmgrCapability::ShowAdmin,
|
|
||||||
AuthmgrCapability::AddURL,
|
|
||||||
AuthmgrCapability::DeleteURL,
|
|
||||||
AuthmgrCapability::EditURL,
|
|
||||||
AuthmgrCapability::ManagePlugins,
|
|
||||||
AuthmgrCapability::API,
|
|
||||||
AuthmgrCapability::APIu,
|
|
||||||
AuthmgrCapability::ViewStats,
|
|
||||||
),
|
|
||||||
AuthmgrRoles::Editor => array(
|
|
||||||
AuthmgrCapability::ShowAdmin,
|
|
||||||
AuthmgrCapability::AddURL,
|
|
||||||
AuthmgrCapability::EditURL,
|
|
||||||
AuthmgrCapability::DeleteURL,
|
|
||||||
AuthmgrCapability::APIu,
|
|
||||||
AuthmgrCapability::ViewStats,
|
|
||||||
),
|
|
||||||
AuthmgrRoles::Contributor => array(
|
|
||||||
AuthmgrCapability::ShowAdmin,
|
|
||||||
AuthmgrCapability::AddURL,
|
|
||||||
AuthmgrCapability::APIu,
|
|
||||||
AuthmgrCapability::ViewStats,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( !isset( $authmgr_role_assignment ) ) {
|
|
||||||
$authmgr_role_assignment = array();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( !isset( $authmgr_admin_ipranges ) ) {
|
|
||||||
$authmgr_admin_ipranges = array(
|
|
||||||
'127.0.0.0/8',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( !isset( $authmgr_allowed_plugin_pages ) ) {
|
|
||||||
$authmgr_allowed_plugin_pages = array(
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// convert role assignment table to lower case if it hasn't been done already
|
|
||||||
// this makes searches much easier!
|
|
||||||
$authmgr_role_assignment_lower = array();
|
|
||||||
foreach ( $authmgr_role_assignment as $key => $value ) {
|
|
||||||
$t_key = strtolower( $key );
|
|
||||||
$t_value = array_map('strtolower', $value);
|
|
||||||
$authmgr_role_assignment_lower[$t_key] = $t_value;
|
|
||||||
}
|
|
||||||
$authmgr_role_assignment = $authmgr_role_assignment_lower;
|
|
||||||
unset($authmgr_role_assignment_lower);
|
|
||||||
|
|
||||||
// allow manipulation of env by other plugins
|
|
||||||
// be mindfull of extending AuthmgrCapability and AuthmgrRoles classes if needed
|
|
||||||
$a = $authmgr_anon_capabilities;
|
|
||||||
$b = $authmgr_role_capabilities;
|
|
||||||
$c = $authmgr_role_assignment;
|
|
||||||
$d = $authmgr_admin_ipranges;
|
|
||||||
$e = $authmgr_allowed_plugin_pages;
|
|
||||||
|
|
||||||
yourls_apply_filter( 'authmgr_env_check', $a, $b, $c, $d, $e );
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/***************** HELPER FUNCTIONS ********************/
|
|
||||||
|
|
||||||
// List currently available capabilities
|
|
||||||
function authmgr_current_capabilities() {
|
|
||||||
$current_capabilities = array();
|
|
||||||
$all_capabilities = array(
|
|
||||||
AuthmgrCapability::ShowAdmin,
|
|
||||||
AuthmgrCapability::AddURL,
|
|
||||||
AuthmgrCapability::DeleteURL,
|
|
||||||
AuthmgrCapability::EditURL,
|
|
||||||
AuthmgrCapability::ManagePlugins,
|
|
||||||
AuthmgrCapability::API,
|
|
||||||
AuthmgrCapability::APIu,
|
|
||||||
AuthmgrCapability::ViewStats,
|
|
||||||
);
|
|
||||||
// allow manipulation of this list ( be mindfull of extending the AuthmgrCapability class if needed )
|
|
||||||
yourls_apply_filter( 'authmgr_current_capabilities', $all_capabilities);
|
|
||||||
|
|
||||||
foreach ( $all_capabilities as $cap ) {
|
|
||||||
if ( authmgr_have_capability( $cap ) ) {
|
|
||||||
$current_capabilities[] = $cap;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $current_capabilities;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for IP in a range
|
|
||||||
// from: http://stackoverflow.com/questions/594112/matching-an-ip-to-a-cidr-mask-in-php5
|
|
||||||
function authmgr_cidr_match($ip, $range) {
|
|
||||||
list ($subnet, $bits) = explode('/', $range);
|
|
||||||
$ip = ip2long($ip);
|
|
||||||
$subnet = ip2long($subnet);
|
|
||||||
$mask = -1 << (32 - $bits);
|
|
||||||
$subnet &= $mask; # nb: in case the supplied subnet wasn't correctly aligned
|
|
||||||
return ($ip & $mask) == $subnet;
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user