Last active
August 29, 2015 14:24
-
-
Save bummzack/2a6c5a3109a4ada75b1c to your computer and use it in GitHub Desktop.
Extension for member based API access (SilverStripe RESTfulAPI)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Extension that adds permissions for object owners | |
* | |
* The desired permissions have to be set as extension parameters. | |
* Allowed permission values are: | |
* - view | |
* - edit | |
* - delete | |
* | |
* 'create' cannot be set as permission, since this extensions needs | |
* to have an owner present (eg, the object has to be created first). | |
* | |
* Example for yml config | |
* MyDataObject: | |
* extensions: | |
* - OwnerCanExtension('view', 'edit') | |
* | |
* @author bummzack | |
*/ | |
class OwnerCanExtension extends DataExtension | |
{ | |
private static $has_one = array( | |
'DataOwner' => 'Member' | |
); | |
private static $class_perms = array(); | |
private static $perms = array( | |
'view', 'edit', 'delete' | |
); | |
// Cache the class arguments for later access | |
public static function add_to_class($class, $extensionClass, $args = null) { | |
if($args && is_array($args)){ | |
$key = $class . '_' . $extensionClass; | |
foreach($args as $arg){ | |
if(in_array($arg, self::$perms)){ | |
self::$class_perms[$key][] = $arg; | |
} | |
} | |
} | |
} | |
/** | |
* Restful API onAfterSerialize hook. | |
* Remove dataOwner ID from the serialized output | |
* @param $data | |
*/ | |
public function onAfterSerialize(&$data){ | |
unset($data['dataOwner']); | |
} | |
/** | |
* Restful API onAfterDeserialize hook. | |
* Don't allow setting of the DataOwner via REST API | |
* @param $data | |
*/ | |
public function onAfterDeserialize(&$data){ | |
unset($data['DataOwner']); | |
} | |
/** | |
* Upon writing, set the owner to the current member (if not already set) | |
*/ | |
public function onBeforeWrite() { | |
if(!$this->owner->DataOwnerID){ | |
$this->owner->DataOwnerID = Member::currentUserID(); | |
} | |
} | |
public function canView($member){ | |
return $this->checkAccess($member, 'view'); | |
} | |
public function canEdit($member){ | |
return $this->checkAccess($member, 'edit'); | |
} | |
public function canDelete($member){ | |
return $this->checkAccess($member, 'delete'); | |
} | |
protected function checkAccess($member, $perm) | |
{ | |
$key = $this->ownerBaseClass . '_' . $this->class; | |
// check if the extension should check the given permission, if not, don't influence the outcome | |
if(!in_array($perm, self::$class_perms[$key])){ | |
return null; | |
} | |
$ownerID = $this->owner->DataOwnerID; | |
// check if there's no owner of this object | |
if(!$ownerID){ | |
if($this->owner->exists()){ | |
// when the object is persisted, require elevated permissions! | |
return Permission::check('ADMIN', 'any', $member); | |
} else { | |
// if the object isn't written yet, don't influence the outcome | |
return null; | |
} | |
} | |
$memberId = 0; | |
if($member instanceof Member && $member->ID){ | |
$memberId = $member->ID; | |
} else if(is_numeric($member)){ | |
$memberId = $member; | |
} else { | |
$memberId = Member::currentUserID(); | |
} | |
if(!$memberId){ | |
// we can't determine ownership, so don't influence the outcome | |
return null; | |
} | |
return $memberId == $ownerID; | |
} | |
public function validate(ValidationResult $validationResult){ | |
$ownerID = $this->owner->DataOwnerID; | |
if($ownerID && $this->owner->DataOwnerID != Member::currentUserID()){ | |
$validationResult->error('Only owner is allowed to write'); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment