1*0579c2f8SAndreas Gohr<?php 2*0579c2f8SAndreas Gohr 3*0579c2f8SAndreas Gohr/** 4*0579c2f8SAndreas Gohr * Tests for the ACL enforcement of media_restore(). 5*0579c2f8SAndreas Gohr * 6*0579c2f8SAndreas Gohr * The restore target is a request parameter independent of the namespace the 7*0579c2f8SAndreas Gohr * media manager derived its authorization from, so media_restore() must 8*0579c2f8SAndreas Gohr * authorize the target media id itself rather than trusting the passed value. 9*0579c2f8SAndreas Gohr */ 10*0579c2f8SAndreas Gohrclass media_restore_test extends DokuWikiTest { 11*0579c2f8SAndreas Gohr 12*0579c2f8SAndreas Gohr public function setUp(): void { 13*0579c2f8SAndreas Gohr parent::setUp(); 14*0579c2f8SAndreas Gohr 15*0579c2f8SAndreas Gohr global $conf, $AUTH_ACL, $USERINFO; 16*0579c2f8SAndreas Gohr 17*0579c2f8SAndreas Gohr $conf['useacl'] = 1; 18*0579c2f8SAndreas Gohr $conf['mediarevisions'] = 1; 19*0579c2f8SAndreas Gohr $_SERVER['REMOTE_USER'] = 'john'; 20*0579c2f8SAndreas Gohr $USERINFO['grps'] = ['user']; 21*0579c2f8SAndreas Gohr 22*0579c2f8SAndreas Gohr // upload allowed in public:*, but denied in the child public:private:* 23*0579c2f8SAndreas Gohr $AUTH_ACL = [ 24*0579c2f8SAndreas Gohr '* @ALL 0', 25*0579c2f8SAndreas Gohr 'public:* @user 8', // AUTH_UPLOAD 26*0579c2f8SAndreas Gohr 'public:private:* @user 0', // AUTH_NONE 27*0579c2f8SAndreas Gohr ]; 28*0579c2f8SAndreas Gohr } 29*0579c2f8SAndreas Gohr 30*0579c2f8SAndreas Gohr /** 31*0579c2f8SAndreas Gohr * Create a current media file and one old revision of it. 32*0579c2f8SAndreas Gohr * 33*0579c2f8SAndreas Gohr * @param string $id media id 34*0579c2f8SAndreas Gohr * @param int $rev revision timestamp 35*0579c2f8SAndreas Gohr * @param string $current content of the current file 36*0579c2f8SAndreas Gohr * @param string $old content of the stored revision 37*0579c2f8SAndreas Gohr */ 38*0579c2f8SAndreas Gohr protected function seedRevision($id, $rev, $current, $old) { 39*0579c2f8SAndreas Gohr $cur = mediaFN($id); 40*0579c2f8SAndreas Gohr io_makeFileDir($cur); 41*0579c2f8SAndreas Gohr file_put_contents($cur, $current); 42*0579c2f8SAndreas Gohr 43*0579c2f8SAndreas Gohr $att = mediaFN($id, $rev); 44*0579c2f8SAndreas Gohr io_makeFileDir($att); 45*0579c2f8SAndreas Gohr file_put_contents($att, $old); 46*0579c2f8SAndreas Gohr } 47*0579c2f8SAndreas Gohr 48*0579c2f8SAndreas Gohr /** 49*0579c2f8SAndreas Gohr * Restoring a revision of a media file in an ACL-denied namespace must be 50*0579c2f8SAndreas Gohr * rejected, even when the request is otherwise valid. 51*0579c2f8SAndreas Gohr */ 52*0579c2f8SAndreas Gohr public function test_restore_rejects_denied_namespace() { 53*0579c2f8SAndreas Gohr $id = 'public:private:secret.png'; 54*0579c2f8SAndreas Gohr $rev = 1000000000; 55*0579c2f8SAndreas Gohr $this->seedRevision($id, $rev, 'CURRENT', 'OLD'); 56*0579c2f8SAndreas Gohr 57*0579c2f8SAndreas Gohr $res = media_restore($id, $rev); 58*0579c2f8SAndreas Gohr 59*0579c2f8SAndreas Gohr $this->assertFalse($res); 60*0579c2f8SAndreas Gohr $this->assertSame('CURRENT', file_get_contents(mediaFN($id)), 'protected file must be untouched'); 61*0579c2f8SAndreas Gohr } 62*0579c2f8SAndreas Gohr 63*0579c2f8SAndreas Gohr /** 64*0579c2f8SAndreas Gohr * Restoring a revision in a permitted namespace must overwrite the current 65*0579c2f8SAndreas Gohr * file with the stored revision. 66*0579c2f8SAndreas Gohr */ 67*0579c2f8SAndreas Gohr public function test_restore_allows_permitted_namespace() { 68*0579c2f8SAndreas Gohr $id = 'public:target.png'; 69*0579c2f8SAndreas Gohr $rev = 1000000000; 70*0579c2f8SAndreas Gohr $this->seedRevision($id, $rev, 'CURRENT', 'OLD'); 71*0579c2f8SAndreas Gohr 72*0579c2f8SAndreas Gohr $res = media_restore($id, $rev); 73*0579c2f8SAndreas Gohr 74*0579c2f8SAndreas Gohr $this->assertSame($id, $res); 75*0579c2f8SAndreas Gohr $this->assertSame('OLD', file_get_contents(mediaFN($id)), 'current file must hold the restored revision'); 76*0579c2f8SAndreas Gohr } 77*0579c2f8SAndreas Gohr} 78