How to limit users to use Panel creating specific kind of content?

Hey guys,
Here’s the deal - I want users to register and submit content to my website. I’ve already done a custom role, and some user registration flow (page with template with sign up form in it, specific controller which uses $site->users()->create(..) method; is there any better way?).
I’ve got some specific blueprints and now I want those users to be able to create JUST that specific kind of pages. I’ve played with the permissions and I’ve already set some rules, like:

'panel.page.create' => function() {
	if ($this->state() === 'ui') {
		return true;
	}

	if ($this->target->template() != 'custom' || $this->target->blueprint() != 'custom') {
		return 'Please select "Custom" from the Template section!';
	}

	return true;
}

It kind of works, but first - the users sees all kinds of templates available, and second - he creates page in the site directory. I think a good way to solve this would be to check the user role (using $this->user()->role() in Panel), and then somehow redirect this person to /panel/pages/some-custom-page/ADD. This way I can make the blueprints work in my favor so that the user will be able to only select specific templates (some-custom-page is a custom page with custom blueprint allowing only what I want)

The reason I don’t want to do a front-end submission is that I’ll have a pretty complex blueprint with over 20 fields, and I don’t want to deal with all the image uploads, tag selections and stuff.

Any ideas?

What is probably the easiest way is to limit page read rights to the parent and children where users are supposed to add their content. Secondly, you could redirect to that specific panel page after login/registration using panel()->redirect().

Ookay, I got it working this way:

'panel.page.read' => function() {
	// user should see only the "parent" page he can add children to
	if ($this->target()->page()->template() == 'projects')
		return true;

	if ($this->target()->page()->template() == 'project') {
		// user can only see and edit his own projects
		if ($this->target()->page()->user() == $this->user()->username())
			return true;
	}

	return false; // if it's something else or others' projects - disable
},
'panel.page.create' => function() {
	if ($this->state() === 'ui') // create page only inside projects page
		return $this->target()->page()->template() == 'projects';

	if ($this->target()->blueprint() != 'project')
		return 'Please select "Project" from the Template section!';

	return true;
},
'panel.page.update' => function() {
	return $this->target()->page->blueprint() == 'project';
}

Everything works properly so far - user can see the “parent” page called “Projects”. He can only add pages inside with specific template and he can see and edit only them, which suits me perfectly fine.

My problem here is that the project has some fields in the blueprints that I want to be disabled for that user. For example “approved”. I’ve added disabled property (which couldn’t find anywhere in docs), but this disables the field for both the user and the admin.

How can I disable fields depending on user role?

And another question of mine (maybe add new post) would be - how can I intercept page creation and add specific value in the blueprint - I’m having an user field inside each project (so I can easily connect project with user) and I want to fill it with the current user?

Thanks!

At the moment, there are no permission options on the field level. I haven’t tested this, but one idea is to create a custom field that is either disabled or not based on user role.

You can’t add anything in the blueprint unless you start parsing them, which does not sound like a good idea. Do you mean you want to add a value to the content file on page creation? That is possible via a panel.page.create hook. But an easier way would be to use a read-only field with a default value.

fields:
  created_by:
    label: Page created by
    type: user
    readonly: true

I did it with a hook already! :slight_smile: Sorry, it seems I’m asking a question and then finding a solution later on.

I’ll try with my own custom field, I’ll just have to look for an old one to base it upon (don’t want to invent the wheel, I just need to write the role checking feature). I guess it would be nice in future if we can simply use:

fields:
  name:
    type: text
    role: admin

just to ensure this field is visible/editable only if user has admin role. I think it would be helpful.

And yes, you are right, I didn’t explain it properly - I want to add values, not properties in the blueprint, sorry, my mistake. Is any difference between readonly and disabled? And is there a place in the docs where I can find all options of a field?

Both options exist in the base field, disabled and readonly. If the field is set to readonly the value (in this case the current user) is saved in the text file. If set to disabled, nothing is saved in the text file.

Most options should be explained here: https://getkirby.com/docs/panel/blueprints/form-fields

Here’s a list of the basic ones:

  • label
  • icon
  • type
  • placeholder
  • help
  • readonly
  • disabled
  • required
  • validate
  • width
  • default
  • translate (multi-lang installations)

Special fields may have additional options that you can find in the corresponding panel field documentation.