Skip to content
This repository was archived by the owner on May 19, 2025. It is now read-only.

Commit 4f72734

Browse files
committed
Make ready for OIDC
lighter weight user validation new ampCap::traceless refactoring/beautifying dropped support for YOURLS < 1.7.3
1 parent 1a18864 commit 4f72734

File tree

2 files changed

+89
-88
lines changed

2 files changed

+89
-88
lines changed

README.md

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,19 @@ Features
77
--------
88
- Easily assign users to roles
99
- Easily fine tune role permissions
10-
- IP based Authentication (optional)
10+
- IPv4 based Authentication (optional)
1111
- All plugin pages, including main management page, hidden to non-admins by default. Easy to unblock pages.
1212
- Plenty of hooks to filter Roles, Role Capabilities, and _any_ of the default data environemnt (such as plugin page visibility)
1313
- Fine(r) tuned API access
1414
- PHP 7 compatible
15+
- No tracking of admins or editors by default
1516

1617
Requirements
1718
------------
18-
- YOURLS 1.7.2 (1.7.3 ready).
19-
- If they are isntalled, uninstall nicwaller's `authmgr` and/or Ian Barber's `Seperate Users` plugins.
19+
- YOURLS 1.7.3
20+
- Incompatable Plugins:
21+
- nicwaller's [`authmgr`](https://github.com/nicwaller/yourls-authmgr-plugin)
22+
- Ian Barber's [`Seperate Users`](https://github.com/ianbarber/Yourls-Separate-Users)
2023

2124
Installation
2225
------------
@@ -31,9 +34,9 @@ The default roles are set up as follows:
3134

3235
Role | Capabilities
3336
--------------|---------------------------------------------------------------------------------------------------
34-
Administrator | Can manage plugins, no limits
35-
Editor | Can add (+API), access own and all others', edit & delete own & anon URL's
36-
Contributor | Can add (+API), access own and anon's, and edit & delete own URLs
37+
Administrator | Can manage plugins, no limits, not tracked on any
38+
Editor | Can add (+API), access own and all others', edit & delete own & anon URL's, not tracked on any
39+
Contributor | Can add (+API), access own and anon's, and edit & delete own URLs, not tracked on own
3740
Anonymous | Can add and access (see stats, etc) anon links (If public)
3841

3942
Configuration
@@ -68,7 +71,7 @@ $amp_allowed_plugin_pages = array(
6871
'another_plugin_slug'
6972
);
7073
```
71-
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.
74+
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.
7275

7376
#### NOTE:
7477
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.

authMgrPlus/plugin.php

Lines changed: 79 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
Plugin Name: Auth Manager Plus
44
Plugin URI: https://github.com/joshp23/YOURLS-AuthMgrPlus
55
Description: Role Based Access Controlls with seperated user data for authenticated users
6-
Version: 1.0.6
6+
Version: 2.0.0
77
Author: Josh Panter, nicwaller, Ian Barber <[email protected]>
88
Author URI: https://unfettered.net
99
*/
@@ -24,6 +24,7 @@ class ampCap {
2424
const AddURL = 'AddURL';
2525
const DeleteURL = 'DeleteURL';
2626
const EditURL = 'EditURL';
27+
const Traceless = 'Traceless';
2728
const ManageAnonURL = 'ManageAnonURL';
2829
const ManageUsrsURL = 'ManageUsrsURL';
2930
const ManagePlugins = 'ManagePlugins';
@@ -52,8 +53,10 @@ function amp_intercept_api() {
5253
}
5354
}
5455
}
56+
yourls_add_action( 'auth_successful', function() {
57+
if( yourls_is_admin() ) amp_intercept_admin();
58+
} );
5559

56-
yourls_add_action( 'auth_successful', 'amp_intercept_admin' );
5760
/**
5861
* YOURLS processes most actions in the admin page. It would be ideal
5962
* to add a unique hook for each action, but unfortunately we need to
@@ -147,12 +150,12 @@ function amp_intercept_admin() {
147150
}
148151
}
149152
}
153+
150154
/*
151155
* Cosmetic filter: removes disallowed plugins from link list
152156
*/
153-
if( yourls_is_admin() ) {
154-
yourls_add_filter( 'admin_sublinks', 'amp_admin_sublinks' );
155-
}
157+
158+
yourls_add_filter( 'admin_sublinks', 'amp_admin_sublinks' );
156159
function amp_admin_sublinks( $links ) {
157160

158161
global $amp_allowed_plugin_pages;
@@ -171,10 +174,10 @@ function amp_admin_sublinks( $links ) {
171174
* Cosmetic filter: displays currently available roles
172175
* by hovering mouse over the username in logout link.
173176
*/
177+
174178
yourls_add_filter( 'logout_link', 'amp_html_append_roles' );
175179
function amp_html_append_roles( $original ) {
176-
$authenticated = yourls_is_valid_user();
177-
if ( $authenticated === true ) {
180+
if ( amp_is_valid_user() ) {
178181
$listcaps = implode(', ', amp_current_capabilities());
179182
return '<div title="'.$listcaps.'">'.$original.'</div>';
180183
} else {
@@ -217,11 +220,9 @@ function amp_have_capability( $capability ) {
217220

218221
// Check user-role based auth
219222
if( !$return ) {
220-
// Only users have roles.
221-
$authenticated = yourls_is_valid_user();
222-
if ( $authenticated !== true )
223+
// Only users have roles
224+
if ( !amp_is_valid_user() ) //XXX
223225
return false;
224-
225226
// List capabilities of particular user role
226227
$user = YOURLS_USER !== false ? YOURLS_USER : NULL;
227228
$user_caps = array();
@@ -281,12 +282,8 @@ function amp_admin_list_where($where) {
281282
return $where; // Allow admin/editor users to see the lot.
282283

283284
$user = YOURLS_USER !== false ? YOURLS_USER : NULL;
284-
if (version_compare(YOURLS_VERSION, '1.7.3') >= 0) {
285-
$where['sql'] = $where['sql'] . " AND (`user` = :user OR `user` IS NULL) ";
286-
$where['binds']['user'] = $user;
287-
}
288-
else
289-
$where = $where . " AND (`user` = $user OR `user` IS NULL) ";
285+
$where['sql'] = $where['sql'] . " AND (`user` = :user OR `user` IS NULL) ";
286+
$where['binds']['user'] = $user;
290287

291288
return $where;
292289
}
@@ -313,9 +310,7 @@ function amp_pre_yourls_infos( $keyword ) {
313310

314311
if( yourls_is_private() && !amp_access_keyword($keyword) ) {
315312

316-
$authenticated = yourls_is_valid_user();
317-
318-
if ( $authenticated === true )
313+
if ( !amp_is_valid_user() )
319314
yourls_redirect( yourls_admin_url( '?access=denied' ), 302 );
320315
else
321316
yourls_redirect( YOURLS_SITE, 302 );
@@ -333,21 +328,29 @@ function amp_get_db_stats( $return, $where ) {
333328
global $ydb;
334329
$table_url = YOURLS_DB_TABLE_URL;
335330
$user = YOURLS_USER !== false ? YOURLS_USER : NULL;
336-
if (version_compare(YOURLS_VERSION, '1.7.3') >= 0) {
337-
$where['sql'] = $where['sql'] . " AND (`user` = :user OR `user` IS NULL) ";
338-
$where['binds']['user'] = $user;
339-
$sql = "SELECT COUNT(keyword) as count, SUM(clicks) as sum FROM `$table_url` WHERE 1=1 " . $where['sql'];
340-
$binds = $where['binds'];
341-
$totals = $ydb->fetchObject($sql, $binds);
342-
} else {
343-
$where = $where . " AND (`user` = $user OR `user` IS NULL) ";
344-
$totals = $ydb->get_results("SELECT COUNT(keyword) as count, SUM(clicks) as sum FROM `$table_url` WHERE 1=1 " . $where );
345-
}
331+
332+
$where['sql'] = $where['sql'] . " AND (`user` = :user OR `user` IS NULL) ";
333+
$where['binds']['user'] = $user;
334+
335+
$sql = "SELECT COUNT(keyword) as count, SUM(clicks) as sum FROM `$table_url` WHERE 1=1 " . $where['sql'];
336+
$binds = $where['binds'];
337+
338+
$totals = $ydb->fetchObject($sql, $binds);
339+
346340
$return = array( 'total_links' => $totals->count, 'total_clicks' => $totals->sum );
347341

348342
return $return;
349343
}
350344

345+
// Fine tune track-me-not
346+
yourls_add_action('redirect_shorturl', 'amp_tracking');
347+
function amp_tracking( $u, $k ) {
348+
if( amp_is_valid_user() && ( amp_keyword_owner($k) || amp_have_capability( ampCap::Traceless ) ) ) {
349+
// No logging
350+
yourls_add_filter( 'shunt_update_clicks', function( $u, $k ) { return true; } );
351+
yourls_add_filter( 'shunt_log_redirect', function( $u, $k ) { return true; } );
352+
}
353+
}
351354
/********************* HOUSEKEEPING ************************/
352355
// Validate environment setup
353356
function amp_env_check() {
@@ -368,6 +371,7 @@ function amp_env_check() {
368371
ampCap::AddURL,
369372
ampCap::EditURL,
370373
ampCap::DeleteURL,
374+
ampCap::Traceless,
371375
ampCap::ManageAnonURL,
372376
ampCap::ManageUsrsURL,
373377
ampCap::ManagePlugins,
@@ -381,6 +385,7 @@ function amp_env_check() {
381385
ampCap::AddURL,
382386
ampCap::EditURL,
383387
ampCap::DeleteURL,
388+
ampCap::Traceless,
384389
ampCap::ManageAnonURL,
385390
ampCap::APIu,
386391
ampCap::ViewStats,
@@ -442,14 +447,8 @@ function amp_activated() {
442447
global $ydb;
443448

444449
$table = YOURLS_DB_TABLE_URL;
445-
$version = version_compare(YOURLS_VERSION, '1.7.3') >= 0;
446-
447-
if ($version) {
448-
$sql = "DESCRIBE `$table`";
449-
$results = $ydb->fetchObjects($sql);
450-
} else {
451-
$results = $ydb->get_results("DESCRIBE $table");
452-
}
450+
$sql = "DESCRIBE `$table`";
451+
$results = $ydb->fetchObjects($sql);
453452

454453
$activated = false;
455454
foreach($results as $r) {
@@ -478,6 +477,7 @@ function amp_current_capabilities() {
478477
ampCap::AddURL,
479478
ampCap::EditURL,
480479
ampCap::DeleteURL,
480+
ampCap::Traceless,
481481
ampCap::ManageAnonURL,
482482
ampCap::ManageUsrsURL,
483483
ampCap::ManagePlugins,
@@ -511,66 +511,43 @@ function amp_cidr_match($ip, $range) {
511511

512512
// Check user access to a keyword ( can they see it )
513513
function amp_access_keyword( $keyword ) {
514-
global $ydb;
515514

516-
if ( amp_have_capability( ampCap::ViewAll ) )
515+
$users = array( YOURLS_USER !== false ? YOURLS_USER : NULL , NULL );
516+
$owner = amp_keyword_owner( $keyword );
517+
if ( amp_have_capability( ampCap::ViewAll ) || in_array( $owner , $users ) )
517518
return true;
518-
519-
$table = YOURLS_DB_TABLE_URL;
520-
$user = YOURLS_USER !== false ? YOURLS_USER : NULL;
521-
if (version_compare(YOURLS_VERSION, '1.7.3') >= 0) {
522-
$binds = array( 'keyword' => $keyword, 'user' => $user);
523-
$sql = "SELECT 1 FROM `$table` WHERE (`user` IS NULL OR `user` = :user) AND `keyword` = :keyword";
524-
$result = $ydb->fetchAffected($sql, $binds);
525-
} else
526-
$result = $ydb->query("SELECT 1 FROM `$table` WHERE (`user` IS NULL OR `user` = $user) AND `keyword` = $keyword");
527-
528-
return $result > 0;
529519
}
530520

531521
// Check user rights to a keyword ( can manage it )
532522
function amp_manage_keyword( $keyword, $capability ) {
533523
// only authenticated users can manaage keywords
534-
$authenticated = yourls_is_valid_user();
535-
if ( $authenticated !== true )
524+
if ( !amp_is_valid_user() )
536525
return false;
537526
// Admin?
538527
if ( amp_have_capability( ampCap::ManageUsrsURL ) )
539528
return true;
540529
// Editor?
541530
$owner = amp_keyword_owner($keyword);
542-
if ( $owner === null ) {
543-
if ( amp_have_capability( ampCap::ManageAnonURL ) ) {
544-
return true;
545-
} else {
546-
return false;
547-
}
548-
}
531+
if ( $owner === null && amp_have_capability( ampCap::ManageAnonURL ) )
532+
return true;
533+
else
534+
return false;
549535
// Self Edit?
550536
$user = YOURLS_USER !== false ? YOURLS_USER : NULL;
551-
if ( $owner === $user ) {
552-
if ( amp_have_capability( $capability ) ) {
537+
if ( $owner === $user && amp_have_capability( $capability ) )
553538
return true;
554-
} else {
539+
else
555540
return false;
556-
}
557-
}
558-
559541
return false;
560542
}
561543

562544
// Check keyword ownership
563545
function amp_keyword_owner( $keyword ) {
564546
global $ydb;
565547
$table = YOURLS_DB_TABLE_URL;
566-
567-
if (version_compare(YOURLS_VERSION, '1.7.3') >= 0) {
568-
$binds = array( 'keyword' => $keyword );
569-
$sql = "SELECT * FROM `$table` WHERE `keyword` = :keyword";
570-
$result = $ydb->fetchOne($sql, $binds);
571-
} else
572-
$result = $ydb->query("SELECT 1 FROM `$table` WHERE `keyword` = $keyword");
573-
548+
$binds = array( 'keyword' => $keyword );
549+
$sql = "SELECT * FROM `$table` WHERE `keyword` = :keyword";
550+
$result = $ydb->fetchOne($sql, $binds);
574551
return $result['user'];
575552
}
576553

@@ -584,13 +561,34 @@ function amp_insert_link($actions) {
584561
$table = YOURLS_DB_TABLE_URL;
585562

586563
// Insert $keyword against $username
587-
if (version_compare(YOURLS_VERSION, '1.7.3') >= 0) {
588-
$binds = array( 'user' => $user,
589-
'keyword' => $keyword);
590-
$sql = "UPDATE `$table` SET `user` = :user WHERE `keyword` = :keyword";
591-
$result = $ydb->fetchAffected($sql, $binds);
592-
} else {
593-
$result = $ydb->query("UPDATE `$table` SET `user` = $user WHERE `keyword` = $keyword");
564+
$binds = array( 'user' => $user,
565+
'keyword' => $keyword);
566+
$sql = "UPDATE `$table` SET `user` = :user WHERE `keyword` = :keyword";
567+
$result = $ydb->fetchAffected($sql, $binds);
568+
}
569+
570+
// Quick user validation without triggering hooks
571+
function amp_is_valid_user() {
572+
573+
$valid = defined( 'YOURLS_USER' ) ? true : false;
574+
575+
if ( !$valid ) {
576+
577+
if ( yourls_is_API()
578+
&& isset( $_REQUEST['timestamp'] ) && !empty($_REQUEST['timestamp'] )
579+
&& isset( $_REQUEST['signature'] ) && !empty($_REQUEST['signature'] ) )
580+
$valid = yourls_check_signature_timestamp();
581+
elseif ( yourls_is_API()
582+
&& !isset( $_REQUEST['timestamp'] )
583+
&& isset( $_REQUEST['signature'] ) && !empty( $_REQUEST['signature'] ) )
584+
$valid = yourls_check_signature();
585+
elseif ( isset( $_REQUEST['username'] ) && isset( $_REQUEST['password'] )
586+
&& !empty( $_REQUEST['username'] ) && !empty( $_REQUEST['password'] ) )
587+
$valid = yourls_check_username_password();
588+
elseif ( !yourls_is_API() && isset( $_COOKIE[ yourls_cookie_name() ] ) )
589+
$valid = yourls_check_auth_cookie();
594590
}
591+
592+
return $valid;
595593
}
596594
?>

0 commit comments

Comments
 (0)