updating User using webvimark in yii2 - php

I am using webvimark module in Yii2. I have created a My Account page, where a user can update his/her information. I am unable to update user updated info, although I am able to fetch user info and display in a form on my-account page.
Below is my updated webvimark User class:
/**
* This is the model class for table "user".
*
* #property string $name
* #property string $country
* #property string $card_number
* #property string $payment_type
* #property string $expiring_month
* #property string $expiring_year
* #property string $expiry_date
* #property string $csc
* #property string $card_address
* #property string $city
* #property string $state
* #property string $zip_code
* #property string $user_type
* #property string $fax
* #property string $address
* #property string $phone
* #property string $user_type
* #property string $company_name
* #property integer $id
* #property string $username
* #property string $email
* #property integer $email_confirmed
* #property string $auth_key
* #property string $password_hash
* #property string $confirmation_token
* #property string $bind_to_ip
* #property string $registration_ip
* #property integer $status
* #property integer $superadmin
* #property integer $created_at
* #property integer $updated_at
*/
class User extends UserIdentity
{
const STATUS_ACTIVE = 1;
const STATUS_INACTIVE = 0;
const STATUS_BANNED = -1;
/**
* #var string
*/
public $gridRoleSearch;
/**
* #var string
*/
public $password;
/**
* #var string
*/
public $repeat_password;
/**
* Store result in singleton to prevent multiple db requests with multiple calls
*
* #param bool $fromSingleton
*
* #return static
*/
public static function getCurrentUser($fromSingleton = true)
{
if ( !$fromSingleton )
{
return static::findOne(Yii::$app->user->id);
}
$user = Singleton::getData('__currentUser');
if ( !$user )
{
$user = static::findOne(Yii::$app->user->id);
Singleton::setData('__currentUser', $user);
}
return $user;
}
/**
* Assign role to user
*
* #param int $userId
* #param string $roleName
*
* #return bool
*/
public static function assignRole($userId, $roleName)
{
try
{
Yii::$app->db->createCommand()
->insert(Yii::$app->getModule('user-management')->auth_assignment_table, [
'user_id' => $userId,
'item_name' => $roleName,
'created_at' => time(),
])->execute();
AuthHelper::invalidatePermissions();
return true;
}
catch (\Exception $e)
{
return false;
}
}
/**
* Revoke role from user
*
* #param int $userId
* #param string $roleName
*
* #return bool
*/
public static function revokeRole($userId, $roleName)
{
$result = Yii::$app->db->createCommand()
->delete(Yii::$app->getModule('user-management')->auth_assignment_table, ['user_id' => $userId, 'item_name' => $roleName])
->execute() > 0;
if ( $result )
{
AuthHelper::invalidatePermissions();
}
return $result;
}
/**
* #param string|array $roles
* #param bool $superAdminAllowed
*
* #return bool
*/
public static function hasRole($roles, $superAdminAllowed = true)
{
if ( $superAdminAllowed AND Yii::$app->user->isSuperadmin )
{
return true;
}
$roles = (array)$roles;
AuthHelper::ensurePermissionsUpToDate();
return array_intersect($roles, Yii::$app->session->get(AuthHelper::SESSION_PREFIX_ROLES,[])) !== [];
}
/**
* #param string $permission
* #param bool $superAdminAllowed
*
* #return bool
*/
public static function hasPermission($permission, $superAdminAllowed = true)
{
if ( $superAdminAllowed AND Yii::$app->user->isSuperadmin )
{
return true;
}
AuthHelper::ensurePermissionsUpToDate();
return in_array($permission, Yii::$app->session->get(AuthHelper::SESSION_PREFIX_PERMISSIONS,[]));
}
/**
* Useful for Menu widget
*
* <example>
* ...
* [ 'label'=>'Some label', 'url'=>['/site/index'], 'visible'=>User::canRoute(['/site/index']) ]
* ...
* </example>
*
* #param string|array $route
* #param bool $superAdminAllowed
*
* #return bool
*/
public static function canRoute($route, $superAdminAllowed = true)
{
if ( $superAdminAllowed AND Yii::$app->user->isSuperadmin )
{
return true;
}
$baseRoute = AuthHelper::unifyRoute($route);
if ( Route::isFreeAccess($baseRoute) )
{
return true;
}
AuthHelper::ensurePermissionsUpToDate();
return Route::isRouteAllowed($baseRoute, Yii::$app->session->get(AuthHelper::SESSION_PREFIX_ROUTES,[]));
}
/**
* getStatusList
* #return array
*/
public static function getStatusList()
{
return array(
self::STATUS_ACTIVE => UserManagementModule::t('back', 'Active'),
self::STATUS_INACTIVE => UserManagementModule::t('back', 'Inactive'),
self::STATUS_BANNED => UserManagementModule::t('back', 'Banned'),
);
}
/**
* getStatusValue
*
* #param string $val
*
* #return string
*/
public static function getStatusValue($val)
{
$ar = self::getStatusList();
return isset( $ar[$val] ) ? $ar[$val] : $val;
}
/**
* #inheritdoc
*/
public static function tableName()
{
return Yii::$app->getModule('user-management')->user_table;
}
/**
* #inheritdoc
*/
public function behaviors()
{
return [
TimestampBehavior::className(),
];
}
/**
* #inheritdoc
*/
public function rules()
{
return [
['username', 'required'],
[['name','phone','user_type'], 'required'],
['username', 'unique'],
['username', 'trim'],
[['company_name', 'name', 'phone','fax','address','payment_type','card_number','expiry_date','csc','card_address','country','city','state','zip_code'], 'trim'],
[['status', 'email_confirmed'], 'integer'],
['email', 'email'],
['email', 'validateEmailConfirmedUnique'],
['bind_to_ip', 'validateBindToIp'],
['bind_to_ip', 'trim'],
['bind_to_ip', 'string', 'max' => 255],
['password', 'required', 'on'=>['newUser', 'changePassword']],
['password', 'string', 'max' => 255, 'on'=>['newUser', 'changePassword']],
['password', 'trim', 'on'=>['newUser', 'changePassword']],
['repeat_password', 'required', 'on'=>['newUser', 'changePassword']],
['repeat_password', 'compare', 'compareAttribute'=>'password'],
];
}
/**
* Check that there is no such confirmed E-mail in the system
*/
public function validateEmailConfirmedUnique()
{
if ( $this->email )
{
$exists = User::findOne([
'email' => $this->email,
'email_confirmed' => 1,
]);
if ( $exists AND $exists->id != $this->id )
{
$this->addError('email', UserManagementModule::t('front', 'This E-mail already exists'));
}
}
}
/**
* Validate bind_to_ip attr to be in correct format
*/
public function validateBindToIp()
{
if ( $this->bind_to_ip )
{
$ips = explode(',', $this->bind_to_ip);
foreach ($ips as $ip)
{
if ( !filter_var(trim($ip), FILTER_VALIDATE_IP) )
{
$this->addError('bind_to_ip', UserManagementModule::t('back', "Wrong format. Enter valid IPs separated by comma"));
}
}
}
}
/**
* #return array
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'username' => UserManagementModule::t('back', 'Login'),
'superadmin' => UserManagementModule::t('back', 'Superadmin'),
'confirmation_token' => 'Confirmation Token',
'registration_ip' => UserManagementModule::t('back', 'Registration IP'),
'bind_to_ip' => UserManagementModule::t('back', 'Bind to IP'),
'status' => UserManagementModule::t('back', 'Status'),
'gridRoleSearch' => UserManagementModule::t('back', 'Roles'),
'created_at' => UserManagementModule::t('back', 'Created'),
'updated_at' => UserManagementModule::t('back', 'Updated'),
'password' => UserManagementModule::t('back', 'Password'),
'repeat_password' => UserManagementModule::t('back', 'Repeat password'),
'email_confirmed' => UserManagementModule::t('back', 'E-mail confirmed'),
'email' => 'E-mail',
//'user_type' => 'E-mail',
];
}
/**
* #return \yii\db\ActiveQuery
*/
public function getRoles()
{
return $this->hasMany(Role::className(), ['name' => 'item_name'])
->viaTable(Yii::$app->getModule('user-management')->auth_assignment_table, ['user_id'=>'id']);
}
/**
* Make sure user will not deactivate himself and superadmin could not demote himself
* Also don't let non-superadmin edit superadmin
*
* #inheritdoc
*/
public function beforeSave($insert)
{
if ( $insert )
{
if ( php_sapi_name() != 'cli' )
{
$this->registration_ip = LittleBigHelper::getRealIp();
}
$this->generateAuthKey();
}
else
{
// Console doesn't have Yii::$app->user, so we skip it for console
if ( php_sapi_name() != 'cli' )
{
if ( Yii::$app->user->id == $this->id )
{
// Make sure user will not deactivate himself
$this->status = static::STATUS_ACTIVE;
// Superadmin could not demote himself
if ( Yii::$app->user->isSuperadmin AND $this->superadmin != 1 )
{
$this->superadmin = 1;
}
}
// Don't let non-superadmin edit superadmin
if ( isset($this->oldAttributes['superadmin']) && !Yii::$app->user->isSuperadmin && $this->oldAttributes['superadmin'] == 1 )
{
return false;
}
}
}
// If password has been set, than create password hash
if ( $this->password )
{
$this->setPassword($this->password);
}
return parent::beforeSave($insert);
}
/**
* Don't let delete yourself and don't let non-superadmin delete superadmin
*
* #inheritdoc
*/
public function beforeDelete()
{
// Console doesn't have Yii::$app->user, so we skip it for console
if ( php_sapi_name() != 'cli' )
{
// Don't let delete yourself
if ( Yii::$app->user->id == $this->id )
{
return false;
}
// Don't let non-superadmin delete superadmin
if ( !Yii::$app->user->isSuperadmin AND $this->superadmin == 1 )
{
return false;
}
}
return parent::beforeDelete();
}
}
and the AuthController class because I have created my view file (my-account.php inside auth folder of webvimark). My AuthController action function is as under:
public function actionMyAccount()
{
$model = new User();
if ( Yii::$app->user->isGuest )
{
return $this->goHome();
}
//if ( Yii::$app->request->post() AND $model->validate())
if ( Yii::$app->request->post())
{
if($model->load(Yii::$app->request->post()) )
{
$model->save();
Yii::$app->session->setFlash('message', "Account has been updated!");
}
}
else
{
$model = User::getCurrentUser();
}
return $this->render('my-account', ['model' => $model,]);
}

Could be you must declare the field you don't validate by the safe attribute
[['company_name', 'name', 'phone','fax','address','payment_type',
'card_number','expiry_date','csc','card_address','country',
'city','state','zip_code'], 'safe'],
or could be is a validation problem
try using (just for debug) save(false)
//if ( Yii::$app->request->post() AND $model->validate())
if ( Yii::$app->request->post())
{
if($model->load(Yii::$app->request->post()) )
{
$model->save(false);
Yii::$app->session->setFlash('message', "Account has been updated!");
} else {
var_dump('model not loaded');
}
}
if in this way the values are saved in db the is a validation rule problem .
You can get the validation error this way
if ($model->validate()) {
// all inputs are valid
} else {
// validation failed: $errors is an array containing error messages
$errors = $model->errors;
var_dump($errors);
}

Related

Code Igniter 4 Restful API only default controller, routes not work

I try to create restful api using Code Igniter 4 on Apache2. If I open http://<my-ip:port>, it shows welcome message. Then I created Account.php controller to get account list from database.
<?php namespace App\Controllers;
use CodeIgniter\RESTful\ResourceController;
use CodeIgniter\API\ResponseTrait;
use App\Models\AccountModel;
class Account extends ResourceController
{
use ResponseTrait;
public function index()
{
$model = new AccountModel();
$data = $model->findAll();
return $this->respond($data, 200);
}
public function show($id = null)
{
$model = new AccountModel();
$data = $model->getWhere(['account_id' => $id])->getResult();
if($data){
return $this->respond($data);
}else{
return $this->failNotFound('No Data Found with id '.$id);
}
}
}
AccountModel.php
<?php namespace App\Models;
use CodeIgniter\Model;
class AccountModel extends Model
{
protected $table = 'account';
protected $primaryKey = 'id';
protected $allowedFields = ['account_id','name'];
}
I set Cors and Filters.
and this is my routes
<?php
namespace Config;
$routes = Services::routes();
if (file_exists(SYSTEMPATH . 'Config/Routes.php')) {
require SYSTEMPATH . 'Config/Routes.php';
}
$routes->setDefaultNamespace('App\Controllers');
$routes->setDefaultController('Home');
$routes->setDefaultMethod('index');
$routes->setTranslateURIDashes(false);
$routes->set404Override();
$routes->setAutoRoute(true);
//$routes->get('/','Home::index');
$routes->resource('account');
if (file_exists(APPPATH . 'Config/' . ENVIRONMENT . '/Routes.php')) {
require APPPATH . 'Config/' . ENVIRONMENT . '/Routes.php';
}
http://my-ip:port shows welcome message. But if I open http://<my-ip:port/account> using postman I got error
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>404 Not Found</title>
</head><body>
<h1>Not Found</h1>
<p>The requested URL was not found on this server.</p>
<hr>
<address>Apache/2.4.46 (Ubuntu) Server at <my-ip> Port 80</address>
</body></html>
and I set Account as a default controller $routes->setDefaultController('Account'); I got list of account if I open http://<my-ip:port>. Do I miss some set up? I want to get account list if I open http://<my-ip:port/account> and others.
Is it works if tried http://<my-ip:port/index.php/account? if yes, you have to config your apache to hide index.php from URL.
visit following link for more infos. => more infos
look at my code best way using restful ctl ci4
first routs
<?php
/*
* Core Auth routes file.
*/
$routes->group('api', ['namespace' => 'Modules\Auth\Controllers'], function ($routes) {
$routes->resource('group', ['filter' => 'authJwt']);
$routes->resource('permission', ['filter' => 'authJwt']);
$routes->resource('groupPermission', ['filter' => 'authJwt']);
$routes->resource('userPermission', ['filter' => 'authJwt']);
$routes->group('auth', function ($routes) {
$routes->post('signin-jwt', 'Auth::signInJwt', ['filter' => 'isSignIn']);
$routes->post('signin', 'Auth::signIn', ['filter' => 'isSignIn']);
$routes->get('signout', 'Auth::signOut', ['filter' => 'authJwt']);
$routes->get('is-signin', 'Auth::isSignIn',['filter' => 'authJwt']);
$routes->post('signup', 'Auth::signUp', ['filter' => 'isSignIn']);
$routes->post('forgot', 'Auth::forgot', ['filter' => 'isSignIn']);
$routes->post('reset-password-email', 'Auth::resetPasswordViaEmail', ['filter' => 'isSignIn']);
$routes->post('reset-password-sms', 'Auth::resetPasswordViaSms', ['filter' => 'isSignIn']);
$routes->post('activate-account-email', 'Auth::activateAccountViaEmail', ['filter' => 'isSignIn']);
$routes->post('send-activate-email', 'Auth::sendActivateCodeViaEmail', ['filter' => 'isSignIn']);
$routes->post('activate-account-sms', 'Auth::activateAccountViaSms', ['filter' => 'isSignIn']);
$routes->post('send-activate-sms', 'Auth::sendActivateCodeViaSms', ['filter' => 'isSignIn']);
});
});
sencond api ctl
<?php
namespace Modules\Shared\Controllers;
/**
* Class BaseController
*
* BaseController provides a convenient place for loading components
* and performing functions that are needed by all your controllers.
* Extend this class in any new controllers:
* class Home extends BaseController
*
* For security be sure to declare any new methods as protected or private.
*
* #package CodeIgniter
*/
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use CodeIgniter\RESTful\ResourceController;
use Modules\Auth\Config\Services;
use Myth\Auth\AuthTrait;
use Psr\Log\LoggerInterface;
use Modules\Shared\Interfaces\UrlAggregationInterface;
use Modules\Shared\Libraries\UrlAggregation;
class ApiController extends ResourceController
{
use AuthTrait;
protected $format = "";
public object $userObject;
public UrlAggregationInterface $urlAggregation;
/**
* An array of helpers to be loaded automatically upon
* class instantiation. These helpers will be available
* to all other controllers that extend BaseController.
*
* #var array
*/
protected $helpers = [
'cookie',
'url',
'from',
'filesystem',
'text',
'shared'
];
/**
* Constructor.
*
* #param RequestInterface $request
* #param ResponseInterface $response
* #param LoggerInterface $logger
*/
/**
* #var string
* Holds the session instance
*/
protected $session;
public function __construct()
{
$this->userObject = (object)[];
}
public function initController(RequestInterface $request, ResponseInterface $response, LoggerInterface $logger)
{
// Do Not Edit This Line
parent::initController($request, $response, $logger);
$this->urlAggregation = new UrlAggregation($request);
$requestWithUser = Services::requestWithUser();
$this->userObject = $requestWithUser->getUser();
}
}
thrid ctl
<?php namespace Modules\Auth\Controllers;
use Modules\Auth\Config\Services;
use Modules\Auth\Entities\GroupEntity;
use CodeIgniter\HTTP\ResponseInterface;
use Modules\Shared\Controllers\ApiController;
class Group extends ApiController
{
/**
* index function
* #method : GET
*/
public function index()
{
$groupEntity = new GroupEntity();
$this->urlAggregation->dataMap($groupEntity->getDataMap());
$groupService = Services::groupService();
$findAllData = $groupService->index($this->urlAggregation);
return $this->respond([
'data' => $findAllData['data'],
'pager' => $findAllData['pager']
], ResponseInterface::HTTP_OK, lang('Shared.api.receive'));
}
/**
* show function
* #method : GET with params ID
*/
public function show($id = null)
{
$groupService = Services::groupService();
$findOneData = $groupService->show($id);
return $this->respond([
'data' => $findOneData['data'],
'pager' => $findOneData['pager']
], ResponseInterface::HTTP_OK, lang('Shared.api.receive'));
}
public function create()
{
$rules = [
'name' => 'required|min_length[3]|max_length[255]|is_unique[auth_groups.name]',
'description' => 'required|min_length[3]|max_length[255]',
];
if (!$this->validate($rules)) {
return $this->respond([
'error' => $this->validator->getErrors(),
], ResponseInterface::HTTP_NOT_ACCEPTABLE, lang('Shared.api.validation'));
}
$groupEntity = new GroupEntity((array)$this->request->getVar());
$groupService = Services::groupService();
$groupService->create($groupEntity);
return $this->respond([
'data' => ''
], ResponseInterface::HTTP_CREATED, lang('Shared.api.save'));
}
/**
* update function
* #method : PUT or PATCH
*/
public function update($id = null)
{
//get request from Vue Js
//get request from Vue Js
$json = $this->request->getJSON();
if (!isset($id)) {
$id = $json->id;
}
$rules = [
'name' => 'if_exist|required|min_length[3]|max_length[255]',
'description' => 'required|min_length[3]|max_length[255]',
];
if (!$this->validate($rules)) {
return $this->respond([
'error' => $this->validator->getErrors(),
], ResponseInterface::HTTP_NOT_ACCEPTABLE, lang('Shared.api.validation'));
}
$groupEntity = new GroupEntity((array)$this->request->getVar());
$groupService = Services::groupService();
$groupService->update($id, $groupEntity);
return $this->respond([
], ResponseInterface::HTTP_OK, lang('Shared.api.update'));
}
/**
* edit function
* #method : DELETE with params ID
*/
public function delete($id = null)
{
$groupService = Services::groupService();
$groupService->delete($id);
return $this->respond([
], ResponseInterface::HTTP_OK, lang('Shared.api.remove'));
}
}
entitiy
forth service
<?php namespace Modules\Auth\Config;
use CodeIgniter\HTTP\UserAgent;
use Config\App;
use Config\Services as AppServices;
use Config\Services as BaseService;
use Modules\Auth\Libraries\RequestWithUser;
use Modules\Auth\Services\AuthService;
use Modules\Auth\Services\GroupsPermissionService;
use Modules\Auth\Services\PermissionService;
use Modules\Auth\Services\RoleRouteService;
use Modules\Auth\Services\GroupService;
use Modules\Auth\Services\UsersPermissionService;
class Services extends BaseService
{
//--------------------------------------------------------------------
/**
* The Request class models an HTTP request.
*
* #param App|null $config
* #param boolean $getShared
*
* #return RequestWithUser
*/
public static function requestWithUser(App $config = null, bool $getShared = true)
{
if ($getShared) {
return static::getSharedInstance('requestWithUser', $config);
}
$config = $config ?? config('App');;
return new RequestWithUser(
$config,
AppServices::uri(),
'php://input',
new UserAgent()
);
}
//--------------------------------------------------------------------
public static function roleRoute($getShared = true)
{
if ($getShared) {
return static::getSharedInstance('roleRoute');
}
return new RoleRouteService();
}
//--------------------------------------------------------------------
public static function authService($getShared = false)
{
if (!$getShared) {
return new AuthService();
}
return static::getSharedInstance('authService');
}
//--------------------------------------------------------------------
public static function groupService($getShared = false)
{
if (!$getShared) {
return new GroupService();
}
return static::getSharedInstance('groupService');
}
//--------------------------------------------------------------------
public static function permissionService($getShared = false)
{
if (!$getShared) {
return new PermissionService();
}
return static::getSharedInstance('permissionService');
}
//--------------------------------------------------------------------
public static function groupsPermissionService($getShared = false)
{
if (!$getShared) {
return new GroupsPermissionService();
}
return static::getSharedInstance('groupsPermissionService');
}
//--------------------------------------------------------------------
public static function userPermissionService($getShared = false)
{
if (!$getShared) {
return new UsersPermissionService();
}
return static::getSharedInstance('usersPermissionService');
}
//--------------------------------------------------------------------
}
<?php namespace Modules\Auth\Entities;
use \CodeIgniter\Entity;
use CodeIgniter\I18n\Time;
class GroupEntity extends Entity
{
protected $id;
protected $name;
protected $description;
//check type of data
// protected $casts = ['
// is_flag' => 'boolean'];
protected $attributes = [
'id' => null,
'name' => null,
'description' => null,
];
protected $datamap = [
];
protected $dates = [];
protected $casts = [];
protected $permissions = [];
protected $roles = [];
}
model
<?php namespace Myth\Auth\Authorization;
use CodeIgniter\Model;
use Modules\Auth\Entities\GroupEntity;
use Modules\Shared\Models\Aggregation;
class GroupModel extends Aggregation
{
protected $table = 'auth_groups';
protected $primaryKey = 'id';
protected $returnType = GroupEntity::class;
protected $allowedFields = [
'name', 'description'
];
protected $useTimestamps = false;
protected $validationRules = [
'name' => 'required|max_length[255]|is_unique[auth_groups.name,name,{name}]',
'description' => 'max_length[255]',
];
protected $validationMessages = [];
protected $skipValidation = false;
//--------------------------------------------------------------------
// Users
//--------------------------------------------------------------------
/**
* Adds a single user to a single group.
*
* #param int $userId
* #param int $groupId
*
* #return bool
*/
public function addUserToGroup(int $userId, int $groupId)
{
cache()->delete("{$groupId}_users");
cache()->delete("{$userId}_groups");
cache()->delete("{$userId}_permissions");
$data = [
'user_id' => (int) $userId,
'group_id' => (int) $groupId
];
return (bool) $this->db->table('auth_groups_users')->insert($data);
}
/**
* Removes a single user from a single group.
*
* #param int $userId
* #param int|string $groupId
*
* #return bool
*/
public function removeUserFromGroup(int $userId, $groupId)
{
cache()->delete("{$groupId}_users");
cache()->delete("{$userId}_groups");
cache()->delete("{$userId}_permissions");
return $this->db->table('auth_groups_users')
->where([
'user_id' => $userId,
'group_id' => (int) $groupId
])->delete();
}
/**
* Removes a single user from all groups.
*
* #param int $userId
*
* #return bool
*/
public function removeUserFromAllGroups(int $userId)
{
cache()->delete("{$userId}_groups");
cache()->delete("{$userId}_permissions");
return $this->db->table('auth_groups_users')
->where('user_id', (int)$userId)
->delete();
}
/**
* Returns an array of all groups that a user is a member of.
*
* #param int $userId
*
* #return array
*/
public function getGroupsForUser(int $userId)
{
if (null === $found = cache("{$userId}_groups"))
{
$found = $this->builder()
->select('auth_groups_users.*, auth_groups.name, auth_groups.description')
->join('auth_groups_users', 'auth_groups_users.group_id = auth_groups.id', 'left')
->where('user_id', $userId)
->get()->getResultArray();
cache()->save("{$userId}_groups", $found, 300);
}
return $found;
}
/**
* Returns an array of all users that are members of a group.
*
* #param int $groupId
*
* #return array
*/
public function getUsersForGroup(int $groupId)
{
if (null === $found = cache("{$groupId}_users"))
{
$found = $this->builder()
->select('auth_groups_users.*, users.*')
->join('auth_groups_users', 'auth_groups_users.group_id = auth_groups.id', 'left')
->join('users', 'auth_groups_users.user_id = users.id', 'left')
->where('auth_groups.id', $groupId)
->get()->getResultArray();
cache()->save("{$groupId}_users", $found, 300);
}
return $found;
}
//--------------------------------------------------------------------
// Permissions
//--------------------------------------------------------------------
/**
* Gets all permissions for a group in a way that can be
* easily used to check against:
*
* [
* id => name,
* id => name
* ]
*
* #param int $groupId
*
* #return array
*/
public function getPermissionsForGroup(int $groupId): array
{
$permissionModel = model(PermissionModel::class);
$fromGroup = $permissionModel
->select('auth_permissions.*')
->join('auth_groups_permissions', 'auth_groups_permissions.permission_id = auth_permissions.id', 'inner')
->where('group_id', $groupId)
->findAll();
$found = [];
foreach ($fromGroup as $permission)
{
$found[$permission['id']] = $permission;
}
return $found;
}
/**
* Add a single permission to a single group, by IDs.
*
* #param int $permissionId
* #param int $groupId
*
* #return mixed
*/
public function addPermissionToGroup(int $permissionId, int $groupId)
{
$data = [
'permission_id' => (int)$permissionId,
'group_id' => (int)$groupId
];
return $this->db->table('auth_groups_permissions')->insert($data);
}
//--------------------------------------------------------------------
/**
* Removes a single permission from a single group.
*
* #param int $permissionId
* #param int $groupId
*
* #return mixed
*/
public function removePermissionFromGroup(int $permissionId, int $groupId)
{
return $this->db->table('auth_groups_permissions')
->where([
'permission_id' => $permissionId,
'group_id' => $groupId
])->delete();
}
//--------------------------------------------------------------------
/**
* Removes a single permission from all groups.
*
* #param int $permissionId
*
* #return mixed
*/
public function removePermissionFromAllGroups(int $permissionId)
{
return $this->db->table('auth_groups_permissions')
->where('permission_id', $permissionId)
->delete();
}
}

Eroro: Call to a member function validatePassword() on a non-object

I'm trying to install Humbhub, and I'm pretty much new to Yii framework, and I've got the error below on my login page;
Error: Call to a member function validatePassword() on a non-object
Here is my accountlogin.php source code;
<?php
namespace humhub\modules\user\models\forms;
use Yii;
use yii\base\Model;
use humhub\modules\user\models\User;
use humhub\modules\user\libs\Ldap;
use humhub\models\Setting;
use yii\db\Expression;
/**
* LoginForm is the model behind the login form.
*/
class AccountLogin extends Model
{
/**
* #var string user's username or email address
*/
public $username;
public $password;
public $rememberMe = true;
private $_user = false;
/**
* #return array the validation rules.
*/
public function rules()
{
return [
[['username', 'password'], 'required'],
['rememberMe', 'boolean'],
['password', 'validatePassword'],
['username', 'validateUser'],
];
}
/**
* Validates the password.
* This method serves as the inline validation for password.
*
* #param string $attribute the attribute currently being validated
* #param array $params the additional name-value pairs given in the rule
*/
public function validatePassword($attribute, $params)
{
if (!$this->hasErrors()) {
$user = $user = $this->getUser();
if ($user !== null) {
if ($user->auth_mode === User::AUTH_MODE_LOCAL && $user->currentPassword->validatePassword($this->password)) {
return;
} elseif ($user->auth_mode === User::AUTH_MODE_LDAP && Ldap::isAvailable() && Ldap::getInstance()->authenticate($user->username, $this->$password)) {
return;
}
}
$this->addError($attribute, 'Incorrect username or password.');
}
}
public function validateUser($attribute, $params)
{
if (!$this->hasErrors()) {
$user = $this->getUser();
if ($user !== null) {
if ($user->status == User::STATUS_DISABLED) {
$this->addError($attribute, 'Your account is disabled!');
}
if ($user->status == User::STATUS_NEED_APPROVAL) {
$this->addError($attribute, 'Your account is not approved yet!');
}
}
}
}
/**
* Logs in a user using the provided username and password.
* #return boolean whether the user is logged in successfully
*/
public function login()
{
if ($this->validate() && Yii::$app->user->login($this->getUser(), $this->rememberMe ? 3600 * 24 * 30 : 0)) {
$this->_user->last_login = new Expression('NOW()');
$this->_user->save();
return true;
} else {
return false;
}
}
/**
* Finds user by [[username]]
*
* #return User|null
*/
public function getUser()
{
if ($this->_user === false) {
$this->_user = User::find()->where(['username' => $this->username])->orWhere(['email' => $this->username])->one();
// Could not found user -> lookup in LDAP
if ($this->_user === null && Ldap::isAvailable() && Setting::Get('enabled', 'authentication_ldap')) {
// Try load/create LDAP user
$usernameDn = Ldap::getInstance()->ldap->getCanonicalAccountName($this->username, \Zend\Ldap\Ldap::ACCTNAME_FORM_DN);
Ldap::getInstance()->handleLdapUser(Ldap::getInstance()->ldap->getNode($usernameDn));
// Check if user is availble now
$this->_user = User::find()->where(['username' => $this->username])->orWhere(['email' => $this->username])->one();
}
}
return $this->_user;
}
}
I've tried changing $user = $this->getUser();to $user = new User(); and the error were gone, but then my login credentials were not properly validated and I get the error wrong username or emailon the login form,
What is the possible solution? any material to study ? any consideration is highly appreciated...
Update:
User model source code:
<?php
/**
* #link https://www.humhub.org/
* #copyright Copyright (c) 2015 HumHub GmbH & Co. KG
* #license https://www.humhub.com/licences
*/
namespace humhub\modules\user\models;
use Yii;
use yii\base\Exception;
use humhub\modules\content\components\ContentContainerActiveRecord;
use humhub\modules\user\models\GroupAdmin;
use humhub\modules\user\components\ActiveQueryUser;
/**
* This is the model class for table "user".
*
* #property integer $id
* #property string $guid
* #property integer $wall_id
* #property integer $group_id
* #property integer $status
* #property integer $super_admin
* #property string $username
* #property string $email
* #property string $auth_mode
* #property string $tags
* #property string $language
* #property string $time_zone
* #property string $last_activity_email
* #property string $created_at
* #property integer $created_by
* #property string $updated_at
* #property integer $updated_by
* #property string $last_login
* #property integer $visibility
*/
class User extends ContentContainerActiveRecord implements \yii\web \IdentityInterface, \humhub\modules\search\interfaces\Searchable
{
/**
* Authentication Modes
*/
const AUTH_MODE_LDAP = "ldap";
const AUTH_MODE_LOCAL = "local";
/**
* User Status Flags
*/
const STATUS_DISABLED = 0;
const STATUS_ENABLED = 1;
const STATUS_NEED_APPROVAL = 2;
/**
* E-Mail Settings (Value Stored in UserSetting)
*/
const RECEIVE_EMAIL_NEVER = 0;
const RECEIVE_EMAIL_DAILY_SUMMARY = 1;
const RECEIVE_EMAIL_WHEN_OFFLINE = 2;
const RECEIVE_EMAIL_ALWAYS = 3;
/**
* Visibility Modes
*/
const VISIBILITY_REGISTERED_ONLY = 1; // Only for registered members
const VISIBILITY_ALL = 2; // Visible for all (also guests)
/**
* #inheritdoc
*/
public static function tableName()
{
return 'user';
}
/**
* #inheritdoc
*/
public function rules()
{
return [
[['username', 'email'], 'required'],
[['wall_id', 'group_id', 'status', 'super_admin', 'created_by', 'updated_by', 'visibility'], 'integer'],
[['tags'], 'string'],
[['last_activity_email', 'created_at', 'updated_at', 'last_login'], 'safe'],
[['guid'], 'string', 'max' => 45],
[['username'], 'string', 'max' => 25, 'min' => Yii::$app->params['user']['minUsernameLength']],
[['time_zone'], 'in', 'range' => \DateTimeZone::listIdentifiers()],
[['email'], 'string', 'max' => 100],
[['auth_mode'], 'string', 'max' => 10],
[['language'], 'string', 'max' => 5],
[['email'], 'unique'],
[['username'], 'unique'],
[['guid'], 'unique'],
[['wall_id'], 'unique']
];
}
public function __get($name)
{
/**
* Ensure there is always a related Profile Model also when it's
* not really exists yet.
*/
if ($name == 'profile') {
$profile = parent::__get('profile');
if (!$this->isRelationPopulated('profile') || $profile === null) {
$profile = new Profile();
$profile->user_id = $this->id;
$this->populateRelation('profile', $profile);
}
return $profile;
}
return parent::__get($name);
}
public function scenarios()
{
$scenarios = parent::scenarios();
$scenarios['login'] = ['username', 'password'];
$scenarios['editAdmin'] = ['username', 'email', 'group_id', 'super_admin', 'auth_mode', 'status'];
$scenarios['registration'] = ['username', 'email', 'group_id'];
return $scenarios;
}
/**
* #inheritdoc
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'guid' => 'Guid',
'wall_id' => 'Wall ID',
'group_id' => 'Group ID',
'status' => 'Status',
'super_admin' => 'Super Admin',
'username' => 'Username',
'email' => 'Email',
'auth_mode' => 'Auth Mode',
'tags' => 'Tags',
'language' => 'Language',
'last_activity_email' => 'Last Activity Email',
'created_at' => 'Created At',
'created_by' => 'Created By',
'updated_at' => 'Updated At',
'updated_by' => 'Updated By',
'last_login' => 'Last Login',
'visibility' => 'Visibility',
];
}
public function behaviors()
{
return array(
\humhub\components\behaviors\GUID::className(),
\humhub\modules\user\behaviors\UserSetting::className(),
\humhub\modules\user\behaviors\Followable::className(),
\humhub\modules\user\behaviors\UserModelModules::className()
);
}
public static function findIdentity($id)
{
return static::findOne($id);
}
public static function findIdentityByAccessToken($token, $type = null)
{
return static::findOne(['guid' => $token]);
}
/**
* #inheritdoc
*
* #return ActiveQueryContent
*/
public static function find()
{
return Yii::createObject(ActiveQueryUser::className(), [get_called_class()]);
}
public function getId()
{
return $this->id;
}
public function getAuthKey()
{
return $this->guid;
}
public function validateAuthKey($authKey)
{
return $this->getAuthKey() === $authKey;
}
public function getCurrentPassword()
{
return $this->hasOne(Password::className(), ['user_id' => 'id'])->orderBy('created_at DESC');
}
public function getProfile()
{
return $this->hasOne(Profile::className(), ['user_id' => 'id']);
}
public function getGroup()
{
return $this->hasOne(Group::className(), ['id' => 'group_id']);
}
/**
* Before Delete of a User
*
*/
public function beforeDelete()
{
// We don't allow deletion of users who owns a space - validate that
foreach (\humhub\modules\space\models\Membership::GetUserSpaces($this->id) as $space) {
if ($space->isSpaceOwner($this->id)) {
throw new Exception("Tried to delete a user which is owner of a space!");
}
}
// Disable all enabled modules
foreach ($this->getAvailableModules() as $moduleId => $module) {
if ($this->isModuleEnabled($moduleId)) {
$this->disableModule($moduleId);
}
}
// Delete profile image
$this->getProfileImage()->delete();
// Remove from search index
Yii::$app->search->delete($this);
// Cleanup related tables
Invite::deleteAll(['user_originator_id' => $this->id]);
Follow::deleteAll(['user_id' => $this->id]);
Follow::deleteAll(['object_model' => $this->className(), 'object_id' => $this->id]);
Password::deleteAll(['user_id' => $this->id]);
Profile::deleteAll(['user_id' => $this->id]);
GroupAdmin::deleteAll(['user_id' => $this->id]);
Session::deleteAll(['user_id' => $this->id]);
Setting::deleteAll(['user_id' => $this->id]);
return parent::beforeDelete();
}
/**
* Before Save Addons
*
* #return type
*/
public function beforeSave($insert)
{
if ($insert) {
if ($this->auth_mode == "") {
$this->auth_mode = self::AUTH_MODE_LOCAL;
}
if (\humhub\models\Setting::Get('allowGuestAccess', 'authentication_internal')) {
// Set users profile default visibility to all
if (\humhub\models\Setting::Get('defaultUserProfileVisibility', 'authentication_internal') == User::VISIBILITY_ALL) {
$this->visibility = User::VISIBILITY_ALL;
}
}
$this->last_activity_email = new \yii\db\Expression('NOW()');
// Set Status
if ($this->status == "") {
if (\humhub\models\Setting::Get('needApproval', 'authentication_internal')) {
$this->status = User::STATUS_NEED_APPROVAL;
} else {
$this->status = User::STATUS_ENABLED;
}
}
if ((\humhub\models\Setting::Get('defaultUserGroup', 'authentication_internal'))) {
$this->group_id = \humhub\models\Setting::Get('defaultUserGroup', 'authentication_internal');
}
}
if ($this->time_zone == "") {
$this->time_zone = \humhub\models\Setting::Get('timeZone');
}
if ($this->group_id == "") {
throw new \yii\base\Exception("Could not save user without group!");
}
return parent::beforeSave($insert);
}
/**
* After Save Addons
*
* #return type
*/
public function afterSave($insert, $changedAttributes)
{
if ($this->status == User::STATUS_ENABLED) {
Yii::$app->search->update($this);
} else {
Yii::$app->search->delete($this);
}
if ($insert) {
if ($this->status == User::STATUS_ENABLED) {
$this->setUpApproved();
} else {
$this->group->notifyAdminsForUserApproval($this);
}
$this->profile->user_id = $this->id;
}
if (Yii::$app->user->id == $this->id) {
Yii::$app->user->setIdentity($this);
}
return parent::afterSave($insert, $changedAttributes);
}
public function setUpApproved()
{
$userInvite = Invite::findOne(['email' => $this->email]);
if ($userInvite !== null) {
// User was invited to a space
if ($userInvite->source == Invite::SOURCE_INVITE) {
$space = \humhub\modules\space\models\Space::findOne(['id' => $userInvite->space_invite_id]);
if ($space != null) {
$space->addMember($this->id);
}
}
// Delete/Cleanup Invite Entry
$userInvite->delete();
}
// Auto Assign User to the Group Space
$group = Group::findOne(['id' => $this->group_id]);
if ($group != null && $group->space_id != "") {
$space = \humhub\modules\space\models\Space::findOne(['id' => $group->space_id]);
if ($space !== null) {
$space->addMember($this->id);
}
}
// Auto Add User to the default spaces
foreach (\humhub\modules\space\models\Space::findAll(['auto_add_new_members' => 1]) as $space) {
$space->addMember($this->id);
}
// Create new wall record for this user
$wall = new \humhub\modules\content\models\Wall;
$wall->object_model = $this->className();
$wall->object_id = $this->id;
$wall->save();
$this->wall_id = $wall->id;
$this->update(false, ['wall_id']);
}
/**
* Returns users display name
*
* #return string
*/
public function getDisplayName()
{
$name = '';
$format = \humhub\models\Setting::Get('displayNameFormat');
if ($this->profile !== null && $format == '{profile.firstname} {profile.lastname}')
$name = $this->profile->firstname . " " . $this->profile->lastname;
// Return always username as fallback
if ($name == '' || $name == ' ')
return $this->username;
return $name;
}
/**
* Checks if this records belongs to the current user
*
* #return boolean is current User
*/
public function isCurrentUser()
{
if (Yii::$app->user->id == $this->id) {
return true;
}
return false;
}
public function canAccessPrivateContent(User $user = null)
{
return ($this->isCurrentUser());
}
public function getWallOut()
{
return \humhub\modules\user\widgets\UserWall::widget(['user' => $this]);
}
/**
* Returns an array with assigned Tags
*/
public function getTags()
{
// split tags string into individual tags
return preg_split("/[;,#]+/", $this->tags);
}
/**
* Checks if given userId can write to this users wall
*
* #param type $userId
* #return type
*/
public function canWrite($userId = "")
{
if ($userId == "")
$userId = Yii::$app->user->id;
if ($userId == $this->id)
return true;
return false;
}
/**
* Returns an array of informations used by search subsystem.
* Function is defined in interface ISearchable
*
* #return Array
*/
public function getSearchAttributes()
{
$attributes = array(
'email' => $this->email,
'username' => $this->username,
'tags' => $this->tags,
'firstname' => $this->profile->firstname,
'lastname' => $this->profile->lastname,
'title' => $this->profile->title,
);
if (!$this->profile->isNewRecord) {
foreach ($this->profile->getProfileFields() as $profileField) {
$attributes['profile_' . $profileField->internal_name] = $profileField->getUserValue($this, true);
}
}
return $attributes;
}
public function createUrl($route = null, $params = array(), $scheme = false)
{
if ($route === null) {
$route = '/user/profile';
}
array_unshift($params, $route);
if (!isset($params['uguid'])) {
$params['uguid'] = $this->guid;
}
return \yii\helpers\Url::toRoute($params, $scheme);
}
/**
*
* #return type
*/
public function getSpaces()
{
// TODO: SHOW ONLY REAL MEMBERSHIPS
return $this->hasMany(\humhub\modules\space\models\Space::className(), ['id' => 'space_id'])
->viaTable('space_membership', ['user_id' => 'id']);
}
/**
* #return type
*/
public function getHttpSessions()
{
return $this->hasMany(\humhub\modules\user\models\Session::className(), ['user_id' => 'id']);
}
/**
* Checks if the user can create a space
*
* #return boolean
*/
public function canCreateSpace()
{
return ($this->canCreatePrivateSpace() || $this->canCreatePublicSpace());
}
/**
* User can approve other users
*
* #return boolean
*/
public function canApproveUsers()
{
if ($this->super_admin == 1) {
return true;
}
if (GroupAdmin::find()->where(['user_id' => $this->id])->count() != 0) {
return true;
}
return false;
}
/**
* Checks if the user can create public spaces
*
* #return boolean
*/
public function canCreatePublicSpace()
{
if ($this->super_admin) {
return true;
} elseif ($this->group !== null && $this->group->can_create_public_spaces == 1) {
return true;
}
return false;
}
/**
* Checks if user can create private spaces
*
* #return boolean
*/
public function canCreatePrivateSpace()
{
if ($this->super_admin) {
return true;
} elseif ($this->group !== null && $this->group->can_create_private_spaces == 1) {
return true;
}
return false;
}
}
Update: config.php in user's module
<?php
use humhub\modules\search\engine\Search;
use humhub\modules\user\Events;
use humhub\commands\IntegrityController;
use humhub\modules\content\components\ContentAddonActiveRecord;
use humhub\modules\content\components\ContentActiveRecord;
use humhub\commands\CronController;
return [
'id' => 'user',
'class' => \humhub\modules\user\Module::className(),
'isCoreModule' => true,
'urlManagerRules' => [
['class' => 'humhub\modules\user\components\UrlRule']
],
'events' => [
['class' => Search::className(), 'event' => Search::EVENT_ON_REBUILD, 'callback' => array(Events::className(), 'onSearchRebuild')],
['class' => ContentActiveRecord::className(), 'event' => ContentActiveRecord::EVENT_BEFORE_DELETE, 'callback' => array(Events::className(), 'onContentDelete')],
['class' => ContentAddonActiveRecord::className(), 'event' => ContentAddonActiveRecord::EVENT_BEFORE_DELETE, 'callback' => array(Events::className(), 'onContentDelete')],
['class' => IntegrityController::className(), 'event' => IntegrityController::EVENT_ON_RUN, 'callback' => array(Events::className(), 'onIntegrityCheck')],
['class' => CronController::className(), 'event' => CronController::EVENT_ON_HOURLY_RUN, 'callback' => [Events::className(), 'onHourlyCron']],
]
];
?>

Yii2 user model with relational tables

I'm new to Yii and I have problem with its User and login system .
I should use 3 tables for login check but when I use custom query I face
"Argument 1 passed to yii\web\User::login() must implement interface yii\web\IdentityInterface, ActiveQuery given"
my tables are like :
user : user_id, name, family, birthday, ...
email : email_user_fk, email_addr, email_active, email_cdt
passwd : passwd_user_fk, passwd_hashed, passwd_active, passwd_cdt
and my query is like :
SELECT
user.user_id, email.email_addr, email.email_active,
passwd.passwd_hashed, passwd_passwd_active , ...
FROM user
JOIN email ON user.user_id = email.email_user_fk
JOIN passwd ON user.user_id = passwd.passwd_user_fk
WHERE
email.email_addr = :email
Is there any Idea ,Please ??
class User extends ActiveRecord implements IdentityInterface
{
const STATUS_DELETED = 0;
const STATUS_ACTIVE = 10;
/**
* #inheritdoc
*/
public static function tableName()
{
return 'user';
}
public static function primaryKey(){
return 'user_id';
}
/**
* #inheritdoc
*/
public function behaviors()
{
return [
TimestampBehavior::className(),
];
}
/**
* #inheritdoc
*/
public static function find
Identity($id)
{
return static::findOne(['id' => $id, 'status' => self::STATUS_ACTIVE]);
}
/**
* #inheritdoc
*/
public static function findIdentityByAccessToken($token, $type = null)
{
throw new NotSupportedException('"findIdentityByAccessToken" is not implemented.');
}
/**
* Finds user by username
*
* #param string $username
* #return static|null
*/
public static function findByUsername($username)
{
return static::findOne(['email' => $username]);
}
public static function findByEmail($email)
{
return User::find()
->joinWith(['emails'])
->where("email.email_address = 'me#mail.com' ")
->one();
}
public static function findByMobile($email)
{
return User::find()
->joinWith(['mobiles'])
->where("mobile.mobile_address = '0931515124' ")
->one();
}
/**
* Finds user by password reset token
*
* #param string $token password reset token
* #return static|null
*/
public static function findByPasswordResetToken($token)
{
if (!static::isPasswordResetTokenValid($token)) {
return null;
}
return static::findOne([
'password_reset_token' => $token,
'status' => self::STATUS_ACTIVE,
]);
}
/**
* Finds out if password reset token is valid
*
* #param string $token password reset token
* #return boolean
*/
public static function isPasswordResetTokenValid($token)
{
if (empty($token)) {
return false;
}
$expire = Yii::$app->params['user.passwordResetTokenExpire'];
$parts = explode('_', $token);
$timestamp = (int) end($parts);
return $timestamp + $expire >= time();
}
/**
* #inheritdoc
*/
public function getId()
{
return $this->getPrimaryKey();
}
/**
* #inheritdoc
*/
public function getAuthKey()
{
return $this->auth_key;
}
/**
* #inheritdoc
*/
public function validateAuthKey($authKey)
{
return $this->getAuthKey() === $authKey;
}
/**
* Validates password
*
* #param string $password password to validate
* #return boolean if password provided is valid for current user
*/
public function validatePassword($password)
{
return Yii::$app->security->validatePassword($password, $this->password_hash);
}
/**
* Generates password hash from password and sets it to the model
*
* #param string $password
*/
public function setPassword($password)
{
$this->password_hash = Yii::$app->security->generatePasswordHash($password);
}
/**
* Generates "remember me" authentication key
*/
public function generateAuthKey()
{
$this->auth_key = Yii::$app->security->generateRandomString();
}
/**
* Generates new password reset token
*/
public function generatePasswordResetToken()
{
$this->password_reset_token = Yii::$app->security->generateRandomString() . '_' . time();
}
/**
* Removes password reset token
*/
public function removePasswordResetToken()
{
$this->password_reset_token = null;
}
public function rules()
{
return [
[['user_name', 'user_family', 'user_birthday'], 'required'],
[['user_gender', 'city_id_fk', 'user_status'], 'integer'],
[['user_birthday', 'user_cdt'], 'safe'],
[['user_name'], 'string', 'max' => 32],
[['user_family'], 'string', 'max' => 48],
[['user_tel', 'user_postcode'], 'string', 'max' => 12],
[['user_address'], 'string', 'max' => 128],
[['user_profile_image', 'user_cover_image'], 'string', 'max' => 256]
];
}
/**
* #return \yii\db\ActiveQuery
*/
public function getEmails()
{
return $this->hasMany(Email::className(), ['email_user_id_fk' => 'user_id']);
}
/**
* #return \yii\db\ActiveQuery
*/
public function getMobiles()
{
return $this->hasMany(Mobile::className(), ['mobile_user_id_fk' => 'user_id']);
}
/**
* #return \yii\db\ActiveQuery
*/
public function getPasswds()
{
return $this->hasMany(Passwd::className(), ['passwd_user_id_fk' => 'user_id']);
}
}
What this error is showing is that when you execute Yii::$app->user->login() at some point you must pass a User object that implements identity interface as a parameter (and it seems you are passing another type of object).
What this method does is allow you to save the information from the user after logging. First the user provides a username, then it has to retrieve info for this username from the database and instatiate a user object with this info. This is the object that you have to pass to the Yii::$app->user->login() function.
Read about the User class here.
and find a good sample here.

Yii 2.0 login from database not working

Right i am working on yii 2.0 trying to amend the login system. It works when the users are just a hand coded array. Instead i want to make this work from a database.
I will show you what the initial Model looks like:
<?php
namespace app\models;
class User extends \yii\base\Object implements \yii\web\IdentityInterface
{
public $id;
public $username;
public $password;
public $authKey;
public $accessToken;
private static $users = [
'100' => [
'id' => '100',
'username' => 'admin',
'password' => 'admin',
'authKey' => 'test100key',
'accessToken' => '100-token',
],
'101' => [
'id' => '101',
'username' => 'demo',
'password' => 'demo',
'authKey' => 'test101key',
'accessToken' => '101-token',
],
];
/**
* #inheritdoc
*/
public static function findIdentity($id)
{
return isset(self::$users[$id]) ? new static(self::$users[$id]) : null;
}
/**
* #inheritdoc
*/
public static function findIdentityByAccessToken($token, $type = null)
{
foreach (self::$users as $user) {
if ($user['accessToken'] === $token) {
return new static($user);
}
}
return null;
}
/**
* Finds user by username
*
* #param string $username
* #return static|null
*/
public static function findByUsername($username)
{
foreach (self::$users as $user) {
if (strcasecmp($user['username'], $username) === 0) {
return new static($user);
}
}
return null;
}
/**
* #inheritdoc
*/
public function getId()
{
return $this->id;
}
/**
* #inheritdoc
*/
public function getAuthKey()
{
return $this->authKey;
}
/**
* #inheritdoc
*/
public function validateAuthKey($authKey)
{
return $this->authKey === $authKey;
}
/**
* Validates password
*
* #param string $password password to validate
* #return boolean if password provided is valid for current user
*/
public function validatePassword($password)
{
return $this->password === $password;
}
}
okay so as you can see it is working on the hand coded array called $users. So i have made a table called "Users" and made the columns id username password authkey and accessToken.
Hoping that it would do the same thing with a database table, however i am getting an error when i try to log in. This is my new code
<?php
namespace app\models;
/**
* This is the model class for table "Cases".
*
* #property integer $id
* #property string $username
* #property string $password
* #property string $authkey
* #property string $accessToken
*/
class User extends \yii\db\ActiveRecord
{
/**
* #inheritdoc
*/
public static function tableName()
{
return 'users';
}
public function rules()
{
return [
[['id','username','password','authkey','accessToken'], 'required'],
[['id'], 'integer'],
];
}
/**
* #inheritdoc
*/
public function attributeLabels()
{
return [
'id' => 'id',
'username' => 'username',
'password' => 'password',
'authkey' => 'authkey',
'accessToken' => 'accessToken',
];
}
/**
* #inheritdoc
*/
public static function findIdentity($id)
{
return isset(self::$users[$id]) ? new static(self::$users[$id]) : null;
}
/**
* #inheritdoc
*/
public static function findIdentityByAccessToken($token, $type = null)
{
foreach (self::$users as $user) {
if ($user['accessToken'] === $token) {
return new static($user);
}
}
return null;
}
/**
* Finds user by username
*
* #param string $username
* #return static|null
*/
public static function findByUsername($username)
{
foreach (self::$Users as $user) {
if (strcasecmp($user['username'], $username) === 0) {
return new static($user);
}
}
return null;
}
/**
* #inheritdoc
*/
public function getId()
{
return $this->id;
}
/**
* #inheritdoc
*/
public function getAuthKey()
{
return $this->authKey;
}
/**
* #inheritdoc
*/
public function validateAuthKey($authKey)
{
return $this->authKey === $authKey;
}
/**
* Validates password
*
* #param string $password password to validate
* #return boolean if password provided is valid for current user
*/
public function validatePassword($password)
{
return $this->password === $password;
}
}
The error message i am getting when i try to log in is "Access to undeclared static property: app\models\User::$Users".
If you need to see my LoginForm Model and Controller action i will post them underneath here.
public function actionLogin()
{
if (!\Yii::$app->user->isGuest) {
return $this->goHome();
}
$model = new LoginForm();
if ($model->load(Yii::$app->request->post()) && $model->login()) {
return $this->goBack();
} else {
return $this->render('login', [
'model' => $model,
]);
}
}
and LoginForm model is:
<?php
namespace app\models;
use Yii;
use yii\base\Model;
/**
* LoginForm is the model behind the login form.
*/
class LoginForm extends Model
{
public $username;
public $password;
public $rememberMe = true;
private $_user = false;
/**
* #return array the validation rules.
*/
public function rules()
{
return [
// username and password are both required
[['username', 'password'], 'required'],
// rememberMe must be a boolean value
['rememberMe', 'boolean'],
// password is validated by validatePassword()
['password', 'validatePassword'],
];
}
/**
* Validates the password.
* This method serves as the inline validation for password.
*
* #param string $attribute the attribute currently being validated
* #param array $params the additional name-value pairs given in the rule
*/
public function validatePassword($attribute, $params)
{
if (!$this->hasErrors()) {
$user = $this->getUser();
if (!$user || !$user->validatePassword($this->password)) {
$this->addError($attribute, 'Incorrect username or password.');
}
}
}
/**
* Logs in a user using the provided username and password.
* #return boolean whether the user is logged in successfully
*/
public function login()
{
if ($this->validate()) {
return Yii::$app->user->login($this->getUser(), $this->rememberMe ? 3600*24*30 : 0);
} else {
return false;
}
}
/**
* Finds user by [[username]]
*
* #return User|null
*/
public function getUser()
{
if ($this->_user === false) {
$this->_user = User::findByUsername($this->username);
}
return $this->_user;
}
}
Can any one advise what i should do , once again the error i get is:
Access to undeclared static property: app\models\User::$Users
and this error corresponds to this section of code
foreach (self::$Users as $user) {
if (strcasecmp($user['username'], $username) === 0) {
return new static($user);
}
}
In your new User class change this methods:
public static function findIdentity($id)
{
return static::findOne(['id' => $id, 'status' => self::STATUS_ACTIVE]);
}
/**
* #inheritdoc
*/
public static function findIdentityByAccessToken($token, $type = null)
{
throw new NotSupportedException('"findIdentityByAccessToken" is not implemented.');
}
/**
* Finds user by username
*
* #param string $username
* #return static|null
*/
public static function findByUsername($username)
{
return static::findOne(['username' => $username, 'status' => self::STATUS_ACTIVE]);
}
See more in Yii2 Advanced template - https://github.com/yiisoft/yii2-app-advanced/blob/master/common/models/User.php#L61
Or take this class(from Yii2 Advanced template) in your app.
Use one Object for User Model instead your three different objects.
class User extends ActiveRecord implements IdentityInterface
{
const LOGIN_SCENARIO = 'login';
const CREATE_SCENARIO = 'create';
const UPDATE_SCENARIO = 'update';
/**
* Table name
*
* #return string
*/
public static function tableName()
{
return 'user';
}
/**
* Primary key
*/
public static function primaryKey()
{
return ['id'];
}
/**
* Set attribute labels
*
* #return array
*/
public function attributeLabels()
{
return [
'login' => Yii::t('app', 'Login'),
'password' => Yii::t('app', 'Password')
];
}
/**
* Rules
*
* #return array
*/
public function rules()
{
return [
[
[
'login',
'password'
],
'required',
'on' => self::LOGIN_SCENARIO
],
[
'password',
'validatePassword',
'on' => self::LOGIN_SCENARIO
],
[
[
'role',
'login',
'confirm',
'password',
],
'required',
'on' => self::CREATE_SCENARIO
],
[
[
'role',
'login',
],
'required',
'on' => self::UPDATE_SCENARIO
],
[
[
'name',
'status',
'password',
'create_dt',
'update_dt'
],
'safe',
],
];
}
/**
* Password validation
*/
public function validatePassword($attribute)
{
// Validate pass
}
/**
* #param null $id
*
* #return bool|mixed
*/
public function saveUser($id = null)
{
/** #var self $user */
$user = $this->findIdentity($id) ? $this->findIdentity($id) : $this;
$user->setScenario($this->scenario);
// Make Save
}
/**
* #param $id
*
* #throws \Exception
*/
public function deleteUser($id)
{
/** #var self $user */
if($user = $this->findIdentity($id)) {
// Make Delete
}
}
/**
* Finds an identity by the given ID.
*
* #param string|integer $id the ID to be looked for
*
* #return IdentityInterface the identity object that matches the given ID.
* Null should be returned if such an identity cannot be found
* or the identity is not in an active state (disabled, deleted, etc.)
*/
public static function findIdentity($id)
{
return static::findOne($id);
}
/**
* Returns an ID that can uniquely identify a user identity.
* #return string|integer an ID that uniquely identifies a user identity.
*/
public function getId()
{
return $this->getPrimaryKey();
}
}
And one User Model working with users, with different scenarios, can create, delete, make login etc.
And at html, for login form, put code like this:
<?php $model = new namespace\User() ?>
<?php $form = ActiveForm::begin(); ?>
<?= $form->field($model, 'login') ?>
<?= $form->field($model, 'password')->passwordInput() ?>
And for login, in controller, put code like this:
/**
* Login action
*
* #return mixed
*/
public function actionLogin()
{
$user = new namespace\User();
$user->setScenario(namespace\User::LOGIN_SCENARIO);
$user->load(Yii::$app->request->post());
if($user->validate()) {
// Make Login
return true;
}
return false;
}

403 Forbidden Error : JSON-RPC PHP

I tried to implement json-rpc server on local for some test.
But when I send some request, it returns the "Forbidden Error".
I made a clone from git (https://github.com/fguillot/JsonRPC), but for now I wanted to make sure something could be returned. So I used command line, instead of running program named Client.php.
example.php
<?php
require 'Server.php';
use JsonRPC\Server;
$server = new Server;
$server->register('addition', function ($a, $b) {
return $a + $b;
});
$server->register('random', function ($start, $end) {
return mt_rand($start, $end);
});
echo $server->execute();
?>
Server.php
<?php
namespace JsonRPC;
use Closure;
use BadFunctionCallException;
use Exception;
use InvalidArgumentException;
use LogicException;
use ReflectionFunction;
use ReflectionMethod;
class InvalidJsonRpcFormat extends Exception {};
class InvalidJsonFormat extends Exception {};
/**
* JsonRPC server class
*
* #package JsonRPC
* #author Frederic Guillot
* #license Unlicense http://unlicense.org/
*/
class Server
{
/**
* Data received from the client
*
* #access private
* #var string
*/
private $payload;
/**
* List of procedures
*
* #static
* #access private
* #var array
*/
private $callbacks = array();
/**
* List of classes
*
* #static
* #access private
* #var array
*/
private $classes = array();
/**
* Constructor
*
* #access public
* #param string $payload Client data
* #param array $callbacks Callbacks
* #param array $classes Classes
*/
public function __construct($payload = '', array $callbacks = array(), array $classes = array())
{
$this->payload = $payload;
$this->callbacks = $callbacks;
$this->classes = $classes;
}
/**
* IP based client restrictions
*
* Return an HTTP error 403 if the client is not allowed
*
* #access public
* #param array $hosts List of hosts
*/
public function allowHosts(array $hosts) {
if (! in_array($_SERVER['REMOTE_ADDR'], $hosts)) {
header('Content-Type: application/json');
header('HTTP/1.0 403 Forbidden');
echo '{"error": "Access Forbidden"}';
exit;
}
}
/**
* HTTP Basic authentication
*
* Return an HTTP error 401 if the client is not allowed
*
* #access public
* #param array $users Map of username/password
*/
public function authentication(array $users)
{
if (! isset($_SERVER['PHP_AUTH_USER']) ||
! isset($users[$_SERVER['PHP_AUTH_USER']]) ||
$users[$_SERVER['PHP_AUTH_USER']] !== $_SERVER['PHP_AUTH_PW']) {
header('WWW-Authenticate: Basic realm="JsonRPC"');
header('Content-Type: application/json');
header('HTTP/1.0 401 Unauthorized');
echo '{"error": "Authentication failed"}';
exit;
}
}
/**
* Register a new procedure
*
* #access public
* #param string $procedure Procedure name
* #param closure $callback Callback
*/
public function register($name, Closure $callback)
{
$this->callbacks[$name] = $callback;
}
/**
* Bind a procedure to a class
*
* #access public
* #param string $procedure Procedure name
* #param mixed $class Class name or instance
* #param string $method Procedure name
*/
public function bind($procedure, $class, $method)
{
$this->classes[$procedure] = array($class, $method);
}
/**
* Return the response to the client
*
* #access public
* #param array $data Data to send to the client
* #param array $payload Incoming data
* #return string
*/
public function getResponse(array $data, array $payload = array())
{
if (! array_key_exists('id', $payload)) {
return '';
}
$response = array(
'jsonrpc' => '2.0',
'id' => $payload['id']
);
$response = array_merge($response, $data);
#header('Content-Type: application/json');
return json_encode($response);
}
/**
* Parse the payload and test if the parsed JSON is ok
*
* #access public
*/
public function checkJsonFormat()
{
if (empty($this->payload)) {
$this->payload = file_get_contents('php://input');
}
if (is_string($this->payload)) {
$this->payload = json_decode($this->payload, true);
}
if (! is_array($this->payload)) {
throw new InvalidJsonFormat('Malformed payload');
}
}
/**
* Test if all required JSON-RPC parameters are here
*
* #access public
*/
public function checkRpcFormat()
{
if (! isset($this->payload['jsonrpc']) ||
! isset($this->payload['method']) ||
! is_string($this->payload['method']) ||
$this->payload['jsonrpc'] !== '2.0' ||
(isset($this->payload['params']) && ! is_array($this->payload['params']))) {
throw new InvalidJsonRpcFormat('Invalid JSON RPC payload');
}
}
/**
* Return true if we have a batch request
*
* #access public
* #return boolean
*/
private function isBatchRequest()
{
return array_keys($this->payload) === range(0, count($this->payload) - 1);
}
/**
* Handle batch request
*
* #access private
* #return string
*/
private function handleBatchRequest()
{
$responses = array();
foreach ($this->payload as $payload) {
if (! is_array($payload)) {
$responses[] = $this->getResponse(array(
'error' => array(
'code' => -32600,
'message' => 'Invalid Request'
)),
array('id' => null)
);
}
else {
$server = new Server($payload, $this->callbacks, $this->classes);
$response = $server->execute();
if ($response) {
$responses[] = $response;
}
}
}
return empty($responses) ? '' : '['.implode(',', $responses).']';
}
/**
* Parse incoming requests
*
* #access public
* #return string
*/
public function execute()
{
try {
$this->checkJsonFormat();
if ($this->isBatchRequest()){
return $this->handleBatchRequest();
}
$this->checkRpcFormat();
$result = $this->executeProcedure(
$this->payload['method'],
empty($this->payload['params']) ? array() : $this->payload['params']
);
return $this->getResponse(array('result' => $result), $this->payload);
}
catch (InvalidJsonFormat $e) {
return $this->getResponse(array(
'error' => array(
'code' => -32700,
'message' => 'Parse error'
)),
array('id' => null)
);
}
catch (InvalidJsonRpcFormat $e) {
return $this->getResponse(array(
'error' => array(
'code' => -32600,
'message' => 'Invalid Request'
)),
array('id' => null)
);
}
catch (BadFunctionCallException $e) {
return $this->getResponse(array(
'error' => array(
'code' => -32601,
'message' => 'Method not found'
)),
$this->payload
);
}
catch (InvalidArgumentException $e) {
return $this->getResponse(array(
'error' => array(
'code' => -32602,
'message' => 'Invalid params'
)),
$this->payload
);
}
}
/**
* Execute the procedure
*
* #access public
* #param string $procedure Procedure name
* #param array $params Procedure params
* #return mixed
*/
public function executeProcedure($procedure, array $params = array())
{
if (isset($this->callbacks[$procedure])) {
return $this->executeCallback($this->callbacks[$procedure], $params);
}
else if (isset($this->classes[$procedure])) {
return $this->executeMethod($this->classes[$procedure][0], $this->classes[$procedure][1], $params);
}
throw new BadFunctionCallException('Unable to find the procedure');
}
/**
* Execute a callback
*
* #access public
* #param Closure $callback Callback
* #param array $params Procedure params
* #return mixed
*/
public function executeCallback(Closure $callback, $params)
{
$reflection = new ReflectionFunction($callback);
$arguments = $this->getArguments(
$params,
$reflection->getParameters(),
$reflection->getNumberOfRequiredParameters(),
$reflection->getNumberOfParameters()
);
return $reflection->invokeArgs($arguments);
}
/**
* Execute a method
*
* #access public
* #param mixed $class Class name or instance
* #param string $method Method name
* #param array $params Procedure params
* #return mixed
*/
public function executeMethod($class, $method, $params)
{
$reflection = new ReflectionMethod($class, $method);
$arguments = $this->getArguments(
$params,
$reflection->getParameters(),
$reflection->getNumberOfRequiredParameters(),
$reflection->getNumberOfParameters()
);
return $reflection->invokeArgs(
is_string($class) ? new $class : $class,
$arguments
);
}
/**
* Get procedure arguments
*
* #access public
* #param array $request_params Incoming arguments
* #param array $method_params Procedure arguments
* #param integer $nb_required_params Number of required parameters
* #param integer $nb_max_params Maximum number of parameters
* #return array
*/
public function getArguments(array $request_params, array $method_params, $nb_required_params, $nb_max_params)
{
$nb_params = count($request_params);
if ($nb_params < $nb_required_params) {
throw new InvalidArgumentException('Wrong number of arguments');
}
if ($nb_params > $nb_max_params) {
throw new InvalidArgumentException('Too many arguments');
}
if ($this->isPositionalArguments($request_params, $method_params)) {
return $request_params;
}
return $this->getNamedArguments($request_params, $method_params);
}
/**
* Return true if we have positional parametes
*
* #access public
* #param array $request_params Incoming arguments
* #param array $method_params Procedure arguments
* #return bool
*/
public function isPositionalArguments(array $request_params, array $method_params)
{
return array_keys($request_params) === range(0, count($request_params) - 1);
}
/**
* Get named arguments
*
* #access public
* #param array $request_params Incoming arguments
* #param array $method_params Procedure arguments
* #return array
*/
public function getNamedArguments(array $request_params, array $method_params)
{
$params = array();
foreach ($method_params as $p) {
$name = $p->getName();
if (isset($request_params[$name])) {
$params[$name] = $request_params[$name];
}
else if ($p->isDefaultValueAvailable()) {
$params[$name] = $p->getDefaultValue();
}
else {
throw new InvalidArgumentException('Missing argument: '.$name);
}
}
return $params;
}
}
Commmand Line (I use macOS)
curl --data-binary '{"jsonrpc": "2.0","id":1, "method":"addition","params":[100,200] }' -H 'content-type: text/plain;' http://127.0.0.1/jsonrpcphp3/example.php
Return Value
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>403 Forbidden</title>
</head><body>
<h1>Forbidden</h1>
<p>You don't have permission to access /jsonrpcphp3/example.php
on this server.</p>
</body></html>

Categories