Skip to main content

This site requires you to update your browser. Your browsing experience maybe affected by not having the most up to date version.

We've moved the forum!

Please use forum.silverstripe.org for any new questions (announcement).
The forum archive will stick around, but will be read only.

You can also use our Slack channel or StackOverflow to ask for help.
Check out our community overview for more options to contribute.

General Questions /

General questions about getting started with SilverStripe that don't fit in any of the categories above.

Moderators: martimiz, Sean, Ed, biapar, Willr, Ingo, swaiba

User should access only 1 DataObject


Go to End


6 Posts   2524 Views

Avatar
huberd

Community Member, 8 Posts

26 February 2015 at 5:56am

Hi everyone,

lets say I have a page where my customers profiles are shown. Now I want to give them access to the backend where they can edit their own profile - and they should not see any of the other CMS features or other customers.

I created a new user 'testcustomer' - he's only allowed to visit the Customer-Admin section, now i want SilverStripe to direct him automatically to his DataObject. So he wouldn't even be able to edit or see other Customer-Objects or visit e.g. Pages, Files, Security...

I never handled permissions in SilverStripe so what's the best approach for this problem?

Avatar
Nightjar

Community Member, 28 Posts

26 February 2015 at 6:10am

There are a few ways to approach it I guess.
But basically you must implement can* on your model.

can()
canView()
canEdit()
canCreate()
etc.

http://api.silverstripe.org/3.1/class-DataObject.html#_canView

You could also make this managable via the CMS by creating a permission you can assign to users (although you're probably after a built in one, or simply checking Member::current_user() (from memory, check that with the api site linked above).

http://doc.silverstripe.org/en/developer_guides/security/permissions/

Avatar
huberd

Community Member, 8 Posts

26 February 2015 at 6:33am

Thanks, I'll try :)

Avatar
huberd

Community Member, 8 Posts

3 March 2015 at 2:52am

FYI, this is what i got so far:
I'm still at cleaning up the code but it works ;)

I created a new rule for cms members to only allow access to the Betrieb (customer) - Admin and assets.

My base-DataObject "Betrieb" (customer) implements PermissionProvider:

function canView($member = false) {
		//Allow view on frontend for everyone
		if (strpos('/'.Director::get_current_page()->Link(),'admin/') == false) return true;

		//Get current member
		if(!$member) $member = Member::currentUser();
		
		//Allow view if member has assigned Betrieb or member is admin
		$ret = false;
		if($member) $ret = $member->Betrieb()->ID == $this->ID;
		if(!$ret) return Permission::check('ADMIN');
		
		return $ret;
	}
	function canEdit($member = false) {
		//Get current member
		if(!$member) $member = Member::currentUser();
		
		//Allow edit if member has assigned Betrieb or member is admin
		$ret = false;
		if($member) $ret = $member->Betrieb()->ID == $this->ID;
		if(!$ret) return Permission::check('ADMIN');
		return $ret;
	}

Extension to Member-Class:

class CustomMemberExtension extends DataExtension{
	...
	private static $has_one = array("Betrieb"=>"Betrieb"); 
	...
	//create Betrieb-Object on new member creation
	function onBeforeWrite() {
	    parent::onBeforeWrite();
		$this->owner->customTest = $this->owner->Betrieb()->ID;
		if(!$this->owner->Betrieb()->ID){
		    $betrieb = new Betrieb();
		    $betrieb->write();
		    $betrieb->Ansprechperson = $this->owner->FirstName . ' ' . $this->owner->Surname;
		    $betrieb->write();
		    $this->owner->BetriebID = $betrieb->ID;		
		}
	}
}

CustomLeftAndMain
Redirects to the assigned Betrieb-Object of a member (always, so he won't be able to navigate to the model admin)

class CustomLeftAndMain extends LeftAndMainExtension {

	public function init() {
        
		CMSMenu::remove_menu_item('Help');
		
		//Check if not admin and member is logged in
		if(!Permission::check('ADMIN') && $member = Member::currentUser()) {
			//Remove Admin-Links
			CMSMenu::remove_menu_item('BetriebAdmin');
			CMSMenu::remove_menu_item('AssetAdmin');
			
			//Redirect to members Betrieb-Object
			$betrieb = $member->owner->Betrieb();
			if(strpos($_SERVER["REQUEST_URI"], 'field/Betrieb/item') == false){
				Controller::curr()->redirect(Director::baseURL().'admin/betriebe/Betrieb/EditForm/field/Betrieb/item/'.$betrieb->ID.'/edit');
			}
			
			//Add custom admin-link to LeftAndMain
			$id = 'LinkToBetrieb';
			$title = $member->getTitle();
			// the link you want to item to go to
			$link = '/admin/betriebe/Betrieb/EditForm/field/Betrieb/item/'.$betrieb->ID.'/edit';
			$priority = 10;
			$attributes = array();

			CMSMenu::add_link($id, $title, $link, $priority, $attributes);
		}
    }
}

I also tried redirecting with a custom MemberLoginForm but it was replaced with the CustomLeftAndMain above:

class GoHomeLoginForm extends MemberLoginForm {
    public function dologin($data) {
        parent::dologin($data);
        if(Controller::curr()->redirectedTo() and Member::currentUserID() ) {
		
            $this->controller->response->removeHeader('Location');
	    $betrieb = Member::currentUser()->owner->Betrieb();
            Controller::curr()->redirect(Director::baseURL().'admin/betriebe/Betrieb/EditForm/field/Betrieb/item/'.$betrieb->ID.'/edit');
        }
    }
}

I guess that's all for now, but I'm still trying to improve that code...

Thanks Nightjar for your help ;)

Avatar
dhensby

Community Member, 253 Posts

3 March 2015 at 3:04am

It seems to me that allowing general users access to the CMS to only edit their profile is going to be a lot more work (and quite a confusing change of interface) than just providing them with a front end form for making edits to their profile.

You should probably look at pursuing a form on the front end site instead.

Avatar
huberd

Community Member, 8 Posts

3 March 2015 at 4:24am

I agree, this would be pretty nice - getting some responses from my customers first...

The problem is, they are not editing one HTML Field, there are standard fields (name, address...), images, a slideshow, prices and a lot more fields...

I'll continue this week with the backend solution, because it needs to be online quite soon :/