php - Cakephp 3 - How to retrieve current logged user in a 'Table' class during validation process? -


i'am using cakephp3 website , have inject custom validation logic based on current user id when i'am creating or modifying entity.

the basic case "is user allow change field new value" ? if' not, want raise validation error (or unauthorized exception).

in cakephp, i'am understanding, of application , businness rules must placed on models or 'modelstable'of orm. but, in classes, authcomponent or current session not available.

i don't want call manually method on entity controller each time need check. use validator, :

$validator->add('protected_data', 'valid', [             'rule' => 'canchangeprotecteddata',             'message' => __('you're not able change data !'),             'provider' => 'table',         ]); 

method on modeltable :

public function canchangeprotecteddata($value, array $context) {     \cake\log\log::debug("canchangeprotecteddata");     // find logged user, @ new value, check if authorized that, return true/false     return false; } 

i cakephp < 3, authcomponent have static method 'authcomponent::user()' not available anymore. so, how can in cakephp 3 ?

thank response.

edit - adding more details

so here more details. in case of rest api. have edit function of entity. "article" entity.

this article has owner foreign key on column named "user_id" (nothing special here). users organized in groups leader on group. leaders of groups can change article's owner "basics" users can't (but can edit own articles). admin users can edit everything. edit method must available authenticated user, changing "user_id" of entity must allowed , checked depending case (if i'am admin yes, if i'am leader yes if new id 1 of group , if i'am basic user no).

i can check on controller if want rule checked everywhere in code article modified (in method "edit" of articlescontroller). me model seems place put no?

authentication vs authorisation

  • authentication means identifying user credentials, of time boils down "is user logged in".
  • authorisation means check if user allowed specific action

so don't mix these two.

you don't want validation want application rules

taken book:

validation vs. application rules

the cakephp orm unique in uses two-layered approach validation.

the first layer validation. validation rules intended operate in stateless way. best leveraged ensure shape, data types , format of data correct.

the second layer application rules. application rules best leveraged check stateful properties of entities. example, validation rules ensure email address valid, while application rule ensure email address unique.

what want implement complex application logic , more simple validation, best way implement application rule.

i'm taking code snippet 1 of articles explains similar case. had check limitation of languages (translations) can associated model. can read whole article here http://florian-kraemer.net/2016/08/complex-application-rules-in-cakephp3/

<?php namespace app\model\rule;  use cake\datasource\entityinterface; use cake\orm\tableregistry; use runtimeexception;  class profilelanguagelimitrule {     /**     * performs check     *     * @link http://php.net/manual/en/language.oop5.magic.php     * @param \cake\datasource\entityinterface $entity entity.     * @param array $options options.     * @return bool     */    public function __invoke(entityinterface $entity, array $options) {       if (!isset($entity->profile_constraint->amount_of_languages)) {          if (!isset($entity->profile_constraint_id)) {             throw new runtimeexception('profile constraint id missing!');          }          $languagelimit = $this->_getconstraintfromdb($entity);       } else {          $languagelimit = $entity->profile_constraint->amount_of_languages;       }        // unlimited languages represented -1       if ($languagelimit === -1) {          return true;       }        // -1 here because language_id of profiles table counts 1 language       // it's -1 of constraint value       $count = count($entity->languages);       return $count <= ($languagelimit - 1);    }     /**     * gets limitation profileconstraints table object.     *     * @param \cake\datasource\entityinterface $entity entity.     * @return int     */    protected function _getconstraintfromdb(entityinterface $entity) {       $constraintstable = tableregistry::get('profileconstraints');       $constraint = $constraintstable->find()          ->where([             'id' => $entity['profile_constraint_id']          ])          ->select([             'amount_of_languages'          ])          ->firstorfail();        return $constraint->amount_of_languages;    }  } 

i think pretty self-explaining. make sure entities user_id field not accessible "public". before saving data, after patching add it:

$entity->set('user_id', $this->auth->user('id')); 

if alter above snippet , change profile_constraint_id user_id or whatever else have there should job you.

what want row / field level based authorisation

guess can use acl that, i've never ever had need field based acl yet. can't give input on that, (cake2) , still (cake3) possible. cake3 acl stuff moved to plugin. technically possible check against anything, db fields, rows, anything.

you write behavior uses model.beforemarshal event , checks if user_id (or role, or whatever) present , not empty , run check on fields want given user id or user role using acl.

you use this method permissionstable::check() or can write more dedicated method checks on multiple objects (fields) @ same time. said, you'll spend time figure best way out using acl if go it.

ux , yet cheap solution

first not show fields @ user not allowed change or enter inputs. if need show them, fine, disable form input or show text. use regular set of validation rules requires field empty (or not present) or empty list of fields based on users role. if don't show fields user have temper form , fail csrf check (if used).


Comments

Popular posts from this blog

c - Bitwise operation with (signed) enum value -

xslt - Unnest parent nodes by child node -

YouTubePlayerFragment cannot be cast to android.support.v4.app.Fragment -