1

I replaced the standard REST actionUpdate with one that only allows updates to the password:

class UserController extends ActiveController
{
    // ...
    public function actions()
    {
        $actions = parent::actions();
        unset($actions['update']);
        return $actions;
    }

    // ...
    public function actionUpdate($id)
    {
        if (! Yii::$app->request->isPut) {
            throw new MethodNotAllowedHttpException('Please use PUT');
        }

        /** @var User $user */
        $user = User::findIdentity($id);

        if (Yii::$app->request->post('password') !== null) {
            $user->setPassword(Yii::$app->request->post('password'));
        }

        return $user->save();
    }

    // ...
}

[Edit] Here is the User model:

<?php
namespace app\models\user;
use Yii;
use yii\base\NotSupportedException;
use yii\web\IdentityInterface;

class User extends \yii\db\ActiveRecord
             implements IdentityInterface
{

    public static function tableName()
    {
        return 'Users';
    }

    public function rules()
    {
        return [
            [['username', 'password_hash', 'email'], 'required'],
            [['role', 'status'], 'integer'],
            [['username', 'email', 'last_login'], 'string', 'max' => 255],
            [['username'], 'unique'],
            [['email'], 'email'],
            [['auth_key'], 'string', 'max' => 32],
            [['password'], 'safe'],
        ];
    }

    public function beforeSave($insert)
    {
        $return = parent::beforeSave($insert);
        if ($this->isNewRecord)
            $this->auth_key = Yii::$app->security->generateRandomKey($length = 255);
        return $return;
    }

    public function getId()
    {
        return $this->id;
    }

    public static function findIdentity($id)
    {
        return static::findOne($id);
    }

    public function getAuthKey()
    {
        return $this->auth_key;
    }

    public function validateAuthKey($authKey)
    {
        return $this->getAuthKey() === $authKey;
    }

    public function getPassword()
    {
        return $this->password_hash;
    }

    public function setPassword($password)
    {
        $this->password_hash = Yii::$app->security->generatePasswordHash($password);
    }


    public static function findIdentityByAccessToken($token, $type = null)
    {
        throw new NotSupportedException('You can only login by username/password pair for now.');
    }

    public function validatePassword($password)
    {
        return Yii::$app->security->validatePassword($password, $this->password_hash);
    }
}

[/Edit]

Testing with Postman and Codeception, [Response] = true and [Status] = 200. Both expected. However, the update does not take.

The [Request] =

PUT http://localhost:8888/api/v1/users/1 {"password":"anotherpassword"}

...which is correct. When I print_r the

Yii::$app->request->post()

in actionUpdate, it returns an empty array. Model rules lists 'password' as safe.

Any ideas?

Mahalo, Joe

10
  • can u please post your User model? Commented Jul 31, 2015 at 9:41
  • Try to use PATCH HTTP method instead of PUT. I also had problem with PUT request empty payload when testing with Codeception. Commented Jul 31, 2015 at 15:14
  • @balaji Posted user model. Commented Jul 31, 2015 at 18:31
  • Did you change the lines: if (! Yii::$app->request->isPut) { throw new MethodNotAllowedHttpException('Please use PUT'); } to if (! Yii::$app->request->isPatch) { throw new MethodNotAllowedHttpException('Please use PATCH'); } in the actionUpdate() function? Commented Jul 31, 2015 at 18:39
  • @matej PATCH also passes an empty array in post(). Commented Jul 31, 2015 at 18:43

1 Answer 1

1

Here is what finally worked for me in case others are interested. For Postman, I put the Json parameters in the request body (instead of as parameters).

In Codeception, I got my clue here. I had to

$I->haveHttpHeader('Content-Type','application/json');

before $I->sendPUT(...).

Hope this helps the next person...

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.