Skip to content
Snippets Groups Projects
Commit f21dad39 authored by Andreas Gohr's avatar Andreas Gohr
Browse files

all actions should have a class now

Lots of FIXMEs and the routing isn't integrated, yet
parent 64ab5140
No related branches found
No related tags found
No related merge requests found
Showing
with 731 additions and 54 deletions
<?php
use dokuwiki\Action\AbstractAclAction;
use dokuwiki\Action\AbstractUserAction;
use dokuwiki\Action\Exception\ActionAclRequiredException;
use dokuwiki\Action\Exception\ActionDisabledException;
use dokuwiki\Action\Exception\ActionUserRequiredException;
class action_general extends DokuWikiTest {
public function dataProvider() {
return array(
array('Login', AUTH_NONE, array('exists' => true, 'ismanager' => false)),
array('Logout', AUTH_NONE, array('exists' => true, 'ismanager' => false)),
array('Search', AUTH_NONE, array('exists' => true, 'ismanager' => false)),
array('Recent', AUTH_NONE, array('exists' => true, 'ismanager' => false)),
array('Profile', AUTH_NONE, array('exists' => true, 'ismanager' => false)),
array('Profiledel', AUTH_NONE, array('exists' => true, 'ismanager' => false)),
array('Index', AUTH_NONE, array('exists' => true, 'ismanager' => false)),
array('Sitemap', AUTH_NONE, array('exists' => true, 'ismanager' => false)),
array('Denied', AUTH_NONE, array('exists' => true, 'ismanager' => false)),
array('Register', AUTH_NONE, array('exists' => true, 'ismanager' => false)),
array('Resendpwd', AUTH_NONE, array('exists' => true, 'ismanager' => false)),
array('Revert', AUTH_ADMIN, array('exists' => true, 'ismanager' => false)),
array('Revert', AUTH_EDIT, array('exists' => true, 'ismanager' => true)),
array('Admin', AUTH_ADMIN, array('exists' => true, 'ismanager' => false)),
array('Admin', AUTH_READ, array('exists' => true, 'ismanager' => true)), // let in, check later again
array('Check', AUTH_READ, array('exists' => true, 'ismanager' => false)), // sensible?
array('Diff', AUTH_READ, array('exists' => true, 'ismanager' => false)),
array('Show', AUTH_READ, array('exists' => true, 'ismanager' => false)),
array('Subscribe', AUTH_READ, array('exists' => true, 'ismanager' => false)),
array('Locked', AUTH_READ, array('exists' => true, 'ismanager' => false)),
array('Source', AUTH_READ, array('exists' => true, 'ismanager' => false)),
array('Export', AUTH_READ, array('exists' => true, 'ismanager' => false)),
array('Media', AUTH_READ, array('exists' => true, 'ismanager' => false)),
array('Draftdel', AUTH_EDIT, array('exists' => true, 'ismanager' => false)),
// aliases
array('Cancel', AUTH_NONE, array('exists' => true, 'ismanager' => false)),
array('Recover', AUTH_NONE, array('exists' => true, 'ismanager' => false)),
// EDITING existing page
array('Save', AUTH_EDIT, array('exists' => true, 'ismanager' => false)),
array('Conflict', AUTH_EDIT, array('exists' => true, 'ismanager' => false)),
array('Draft', AUTH_EDIT, array('exists' => true, 'ismanager' => false)),
//the edit function will check again and do a source show
//when no AUTH_EDIT available:
array('Edit', AUTH_READ, array('exists' => true, 'ismanager' => false)),
array('Preview', AUTH_READ, array('exists' => true, 'ismanager' => false)),
// EDITING new page
array('Save', AUTH_CREATE, array('exists' => false, 'ismanager' => false)),
array('Conflict', AUTH_CREATE, array('exists' => false, 'ismanager' => false)),
array('Draft', AUTH_CREATE, array('exists' => false, 'ismanager' => false)),
array('Edit', AUTH_CREATE, array('exists' => false, 'ismanager' => false)),
array('Preview', AUTH_CREATE, array('exists' => false, 'ismanager' => false)),
);
}
/**
* @dataProvider dataProvider
* @param $name
* @param $expected
* @param $info
*/
public function testMinimumPermissions($name, $expected, $info) {
global $INFO;
$INFO = $info;
$classname = 'dokuwiki\\Action\\' . $name;
/** @var \dokuwiki\Action\AbstractAction $class */
$class = new $classname();
$this->assertSame($expected, $class->minimumPermission());
}
/**
* All actions should handle the disableactions setting
*
* @dataProvider dataProvider
* @param $name
*/
public function testBaseClassActionOkPermission($name) {
$classname = 'dokuwiki\\Action\\' . $name;
/** @var \dokuwiki\Action\AbstractAction $class */
$class = new $classname();
global $conf;
$conf['useacl'] = 1;
$conf['subscribers'] = 1;
$conf['disableactions'] = '';
try {
$class->checkPermissions();
} catch(\Exception $e) {
$this->assertNotSame(ActionDisabledException::class, get_class($e));
}
$conf['disableactions'] = $class->getActionName();
try {
$class->checkPermissions();
} catch(\Exception $e) {
$this->assertSame(ActionDisabledException::class, get_class($e));
}
}
/**
* Actions inheriting from AbstractAclAction should have an ACL enabled check
*
* @dataProvider dataProvider
* @param $name
*/
public function testBaseClassAclPermission($name) {
$classname = 'dokuwiki\\Action\\' . $name;
/** @var \dokuwiki\Action\AbstractAction $class */
$class = new $classname();
if(!is_a($class, AbstractAclAction::class)) return;
global $conf;
$conf['useacl'] = 1;
$conf['subscribers'] = 1;
try {
$class->checkPermissions();
} catch(\Exception $e) {
$this->assertNotSame(ActionAclRequiredException::class, get_class($e));
}
$conf['useacl'] = 0;
try {
$class->checkPermissions();
} catch(\Exception $e) {
$this->assertSame(ActionAclRequiredException::class, get_class($e));
}
}
/**
* Actions inheriting from AbstractUserAction should have user check
*
* @dataProvider dataProvider
* @param $name
*/
public function testBaseClassUserPermission($name) {
$classname = 'dokuwiki\\Action\\' . $name;
/** @var \dokuwiki\Action\AbstractAction $class */
$class = new $classname();
if(!is_a($class, AbstractUserAction::class)) return;
global $conf;
$conf['useacl'] = 1;
$conf['subscribers'] = 1;
$_SERVER['REMOTE_USER'] = 'test';
try {
$class->checkPermissions();
} catch(\Exception $e) {
$this->assertNotSame(ActionUserRequiredException::class, get_class($e));
}
unset($_SERVER['REMOTE_USER']);
try {
$class->checkPermissions();
} catch(\Exception $e) {
$this->assertSame(ActionUserRequiredException::class, get_class($e));
}
}
}
<?php
class action_minimumPermissions extends DokuWikiTest {
public function dataProvider() {
return array (
array('Login', AUTH_NONE, array('exists' => true, 'ismanager' => false)),
array('Logout', AUTH_NONE, array('exists' => true, 'ismanager' => false)),
array('Search', AUTH_NONE, array('exists' => true, 'ismanager' => false)),
array('Recent', AUTH_NONE, array('exists' => true, 'ismanager' => false)),
//array('Profile', AUTH_NONE, array('exists' => true, 'ismanager' => false)),
//array('Profile_delete', AUTH_NONE, array('exists' => true, 'ismanager' => false)),
//array('Index', AUTH_NONE, array('exists' => true, 'ismanager' => false)),
array('Sitemap', AUTH_NONE, array('exists' => true, 'ismanager' => false)),
array('Denied', AUTH_NONE, array('exists' => true, 'ismanager' => false)),
array('Check', AUTH_READ, array('exists' => true, 'ismanager' => false)),
array('Diff', AUTH_READ, array('exists' => true, 'ismanager' => false)),
array('Show', AUTH_READ, array('exists' => true, 'ismanager' => false)),
array('Subscribe', AUTH_READ, array('exists' => true, 'ismanager' => false)),
/*
array('', AUTH_NONE, array('exists' => true, 'ismanager' => false)),
*/
);
}
/**
* @dataProvider dataProvider
* @param $name
* @param $expected
* @param $info
*/
public function testMinimumPermissions($name, $expected, $info) {
global $INFO;
$INFO = $info;
$classname = 'dokuwiki\\Action\\'.$name;
/** @var \dokuwiki\Action\AbstractAction $class */
$class = new $classname();
$this->assertSame($expected, $class->minimumPermission());
}
}
......@@ -4,6 +4,7 @@ namespace dokuwiki\Action;
use dokuwiki\Action\Exception\ActionDisabledException;
use dokuwiki\Action\Exception\ActionException;
use dokuwiki\Action\Exception\FatalException;
abstract class AbstractAction {
......@@ -54,8 +55,17 @@ abstract class AbstractAction {
/**
* Output whatever content is wanted within tpl_content();
*
* @fixme we may want to return a Ui class here
*/
public function tplContent() {
echo 'No content for this action';
throw new FatalException('No content for Action ' . $this->actionname);
}
/**
* @return string
*/
public function getActionName() {
return $this->actionname;
}
}
<?php
namespace dokuwiki\Action;
use dokuwiki\Action\Exception\ActionAclRequiredException;
use dokuwiki\Action\Exception\ActionException;
abstract class AbstractAliasAction extends AbstractAction {
/** @inheritdoc */
function minimumPermission() {
return AUTH_NONE;
}
}
......@@ -4,7 +4,7 @@ namespace dokuwiki\Action;
use dokuwiki\Action\Exception\ActionAclRequiredException;
use dokuwiki\Action\Exception\ActionException;
use dokuwiki\Action\Exception\ActionNoUserException;
use dokuwiki\Action\Exception\ActionUserRequiredException;
abstract class AbstractUserAction extends AbstractAclAction {
......@@ -13,7 +13,7 @@ abstract class AbstractUserAction extends AbstractAclAction {
parent::checkPermissions();
global $INPUT;
if(!$INPUT->server->str('REMOTE_USER')) {
throw new ActionNoUserException();
throw new ActionUserRequiredException();
}
}
......
<?php
/**
* Created by IntelliJ IDEA.
* User: andi
* Date: 2/11/17
* Time: 11:33 AM
*/
namespace dokuwiki\Action;
use dokuwiki\Action\Exception\ActionException;
class Admin extends AbstractUserAction {
/** @inheritdoc */
function minimumPermission() {
global $INFO;
if($INFO['ismanager']) {
return AUTH_READ; // let in check later
} else {
return AUTH_ADMIN;
}
}
public function checkPermissions() {
parent::checkPermissions();
global $INFO;
if(!$INFO['ismanager']) {
throw new ActionException('denied');
}
}
public function preProcess() {
global $INPUT;
global $INFO;
// retrieve admin plugin name from $_REQUEST['page']
if (($page = $INPUT->str('page', '', true)) != '') {
/** @var $plugin \DokuWiki_Admin_Plugin */
if ($plugin = plugin_getRequestAdminPlugin()){ // FIXME this method does also permission checking
if($plugin->forAdminOnly() && !$INFO['isadmin'] ) {
throw new ActionException('denied');
}
$plugin->handle();
}
}
}
public function tplContent() {
tpl_admin();
}
}
<?php
/**
* Created by IntelliJ IDEA.
* User: andi
* Date: 2/11/17
* Time: 10:13 AM
*/
namespace dokuwiki\Action;
use dokuwiki\Action\Exception\ActionAbort;
class Cancel extends AbstractAliasAction {
public function preProcess() {
throw new ActionAbort();
}
}
<?php
/**
* Created by IntelliJ IDEA.
* User: andi
* Date: 2/11/17
* Time: 11:52 AM
*/
namespace dokuwiki\Action;
class Conflict extends AbstractAction {
/** @inheritdoc */
function minimumPermission() {
global $INFO;
if($INFO['exists']) {
return AUTH_EDIT;
} else {
return AUTH_CREATE;
}
}
public function tplContent() {
global $PRE;
global $TEXT;
global $SUF;
global $SUM;
html_conflict(con($PRE, $TEXT, $SUF), $SUM);
html_diff(con($PRE, $TEXT, $SUF), false);
}
}
<?php
/**
* Created by IntelliJ IDEA.
* User: andi
* Date: 2/11/17
* Time: 11:55 AM
*/
namespace dokuwiki\Action;
class Draft extends AbstractAction {
/** @inheritdoc */
function minimumPermission() {
global $INFO;
if($INFO['exists']) {
return AUTH_EDIT;
} else {
return AUTH_CREATE;
}
}
// FIXME any permission checks needed?
public function tplContent() {
html_draft();
}
}
<?php
/**
* Created by IntelliJ IDEA.
* User: andi
* Date: 2/11/17
* Time: 10:13 AM
*/
namespace dokuwiki\Action;
use dokuwiki\Action\Exception\ActionAbort;
class Draftdel extends AbstractUserAction {
/** @inheritdoc */
function minimumPermission() {
return AUTH_EDIT;
}
public function preProcess() {
act_draftdel('fixme'); // FIXME replace this utility function
throw new ActionAbort();
}
}
<?php
/**
* Created by IntelliJ IDEA.
* User: andi
* Date: 2/11/17
* Time: 10:42 AM
*/
namespace dokuwiki\Action;
use dokuwiki\Action\Exception\ActionAbort;
class Edit extends AbstractAction {
/** @inheritdoc */
function minimumPermission() {
global $INFO;
if($INFO['exists']) {
return AUTH_READ; // we check again below
} else {
return AUTH_CREATE;
}
}
public function checkPermissions() {
parent::checkPermissions();
global $INFO;
// no edit permission? view source
if($INFO['exists'] && !$INFO['writable']) {
throw new ActionAbort('source');
}
}
public function preProcess() {
global $ID;
global $INFO;
global $TEXT;
global $RANGE;
global $PRE;
global $SUF;
global $REV;
global $SUM;
global $lang;
global $DATE;
if (!isset($TEXT)) {
if ($INFO['exists']) {
if ($RANGE) {
list($PRE,$TEXT,$SUF) = rawWikiSlices($RANGE,$ID,$REV);
} else {
$TEXT = rawWiki($ID,$REV);
}
} else {
$TEXT = pageTemplate($ID);
}
}
//set summary default
if(!$SUM){
if($REV){
$SUM = sprintf($lang['restored'], dformat($REV));
}elseif(!$INFO['exists']){
$SUM = $lang['created'];
}
}
// Use the date of the newest revision, not of the revision we edit
// This is used for conflict detection
if(!$DATE) $DATE = @filemtime(wikiFN($ID));
//check if locked by anyone - if not lock for my self
$lockedby = checklock($ID);
if($lockedby) {
throw new ActionAbort('locked');
};
lock($ID);
}
public function tplContent() {
html_edit();
}
}
......@@ -2,6 +2,6 @@
namespace dokuwiki\Action\Exception;
class ActionNoUserException extends ActionException {
class ActionUserRequiredException extends ActionException {
}
<?php
/**
* Created by IntelliJ IDEA.
* User: andi
* Date: 2/11/17
* Time: 11:10 AM
*/
namespace dokuwiki\Action;
use dokuwiki\Action\Exception\ActionAbort;
class Export extends AbstractAction {
/** @inheritdoc */
function minimumPermission() {
return AUTH_READ;
}
// FIXME proper mode should be checked
/**
* Export a wiki page for various formats
*
* Triggers ACTION_EXPORT_POSTPROCESS
*
* Event data:
* data['id'] -- page id
* data['mode'] -- requested export mode
* data['headers'] -- export headers
* data['output'] -- export output
*
* @author Andreas Gohr <andi@splitbrain.org>
* @author Michael Klier <chi@chimeric.de>
*/
public function preProcess() {
global $ID;
global $REV;
global $conf;
global $lang;
$pre = '';
$post = '';
$headers = array();
// search engines: never cache exported docs! (Google only currently)
$headers['X-Robots-Tag'] = 'noindex';
$mode = substr('FIXME', 7); // FIXME how to pass the proper mode?
switch($mode) {
case 'raw':
$headers['Content-Type'] = 'text/plain; charset=utf-8';
$headers['Content-Disposition'] = 'attachment; filename=' . noNS($ID) . '.txt';
$output = rawWiki($ID, $REV);
break;
case 'xhtml':
$pre .= '<!DOCTYPE html>' . DOKU_LF;
$pre .= '<html lang="' . $conf['lang'] . '" dir="' . $lang['direction'] . '">' . DOKU_LF;
$pre .= '<head>' . DOKU_LF;
$pre .= ' <meta charset="utf-8" />' . DOKU_LF; // FIXME improve wrapper
$pre .= ' <title>' . $ID . '</title>' . DOKU_LF;
// get metaheaders
ob_start();
tpl_metaheaders();
$pre .= ob_get_clean();
$pre .= '</head>' . DOKU_LF;
$pre .= '<body>' . DOKU_LF;
$pre .= '<div class="dokuwiki export">' . DOKU_LF;
// get toc
$pre .= tpl_toc(true);
$headers['Content-Type'] = 'text/html; charset=utf-8';
$output = p_wiki_xhtml($ID, $REV, false);
$post .= '</div>' . DOKU_LF;
$post .= '</body>' . DOKU_LF;
$post .= '</html>' . DOKU_LF;
break;
case 'xhtmlbody':
$headers['Content-Type'] = 'text/html; charset=utf-8';
$output = p_wiki_xhtml($ID, $REV, false);
break;
default:
$output = p_cached_output(wikiFN($ID, $REV), $mode, $ID);
$headers = p_get_metadata($ID, "format $mode");
break;
}
// prepare event data
$data = array();
$data['id'] = $ID;
$data['mode'] = $mode;
$data['headers'] = $headers;
$data['output'] =& $output;
trigger_event('ACTION_EXPORT_POSTPROCESS', $data);
if(!empty($data['output'])) {
if(is_array($data['headers'])) foreach($data['headers'] as $key => $val) {
header("$key: $val");
}
print $pre . $data['output'] . $post;
exit;
}
throw new ActionAbort();
}
}
<?php
/**
* Created by IntelliJ IDEA.
* User: andi
* Date: 2/11/17
* Time: 11:31 AM
*/
namespace dokuwiki\Action;
class Index extends AbstractAction {
/** @inheritdoc */
function minimumPermission() {
return AUTH_NONE;
}
public function tplContent() {
global $IDX;
html_index($IDX);
}
}
<?php
/**
* Created by IntelliJ IDEA.
* User: andi
* Date: 2/11/17
* Time: 11:43 AM
*/
namespace dokuwiki\Action;
class Locked extends AbstractAction {
/** @inheritdoc */
function minimumPermission() {
return AUTH_READ;
}
public function tplContent() {
html_locked();
}
}
......@@ -9,7 +9,7 @@
namespace dokuwiki\Action;
use dokuwiki\Action\Exception\ActionException;
use dokuwiki\Action\Exception\ActionNoUserException;
use dokuwiki\Action\Exception\ActionUserRequiredException;
class Logout extends AbstractAclAction {
......@@ -23,7 +23,7 @@ class Logout extends AbstractAclAction {
global $INPUT;
parent::checkPermissions();
if(!$INPUT->server->has('REMOTE_USER')) {
throw new ActionNoUserException('login');
throw new ActionUserRequiredException('login');
}
}
......
<?php
/**
* Created by IntelliJ IDEA.
* User: andi
* Date: 2/11/17
* Time: 11:49 AM
*/
namespace dokuwiki\Action;
class Media extends AbstractAction {
/** @inheritdoc */
function minimumPermission() {
return AUTH_READ;
}
public function tplContent() {
tpl_media();
}
}
<?php
/**
* Created by IntelliJ IDEA.
* User: andi
* Date: 2/11/17
* Time: 10:26 AM
*/
namespace dokuwiki\Action;
class Preview extends Edit {
public function preProcess() {
header('X-XSS-Protection: 0'); // FIXME is it okay to send it right away here?
act_draftsave('fixme'); // reimplement thisutility function and take of duplicate code in ajax.php
parent::preProcess();
}
public function tplContent() {
global $TEXT;
html_edit();
html_show($TEXT);
}
}
<?php
/**
* Created by IntelliJ IDEA.
* User: andi
* Date: 2/11/17
* Time: 9:47 AM
*/
namespace dokuwiki\Action;
use dokuwiki\Action\Exception\ActionAbort;
class Profile extends AbstractUserAction {
/** @inheritdoc */
function minimumPermission() {
return AUTH_NONE;
}
public function preProcess() {
global $lang;
if(updateprofile()) {
msg($lang['profchanged'], 1);
throw new ActionAbort('show');
}
}
public function tplContent() {
html_updateprofile();
}
}
<?php
/**
* Created by IntelliJ IDEA.
* User: andi
* Date: 2/11/17
* Time: 9:47 AM
*/
namespace dokuwiki\Action;
use dokuwiki\Action\Exception\ActionAbort;
/**
* Class Profiledel
* @package dokuwiki\Action
* @fixme rename profile_delete action to profiledel
*/
class Profiledel extends AbstractUserAction {
/** @inheritdoc */
function minimumPermission() {
return AUTH_NONE;
}
public function preProcess() {
global $lang;
if(auth_deleteprofile()){
msg($lang['profdeleted'],1);
throw new ActionAbort('show');
} else {
throw new ActionAbort('profile');
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment