I am trying to implement a login method using OpenID, and the $_SESSION var's are posting correctly - and through those I am simply trying to register users in MySQL. For some reason, when passing through the 'login' action in my controller ::
public function actionLogin()
{
if (!Yii::$app->user->isGuest) {
return $this->goHome();
}
include ('../views/user-record/steamauth/userInfo.php');
$steamid = $_SESSION['steam_steamid'];
$username = $_SESSION['steam_personaname'];
$profileurl = $_SESSION['steam_profileurl'];
$avatar = $_SESSION['steam_avatar'];
$avatarmedium = $_SESSION['steam_avatarmedium'];
$avatarfull = $_SESSION['steam_avatarfull'];
$user = UserRecord::findBySteamId($steamid);
if ($user === null)
{
$user = new UserRecord();
$user->steamid = $steamid;
$user->username = $username;
$user->profileurl = $profileurl;
$user->avatar = $avatar;
$user->avatarmedium = $avatarmedium;
$user->avatarfull = $avatarfull;
$user->verified = 0;
$user->banned = 0;
$user->save();
}
Yii::$app->user->login($user, 604800);
return $this->redirect(Yii::$app->user->returnUrl);
}
EDIT: Here is the UserRecord class, forgot to add it in.
<?php
namespace app\models;
class UserRecord extends \yii\db\ActiveRecord implements \yii\web\IdentityInterface
{
public $id;
public $steamid;
public $username;
public $profileurl;
public $avatar;
public $avatarmedium;
public $avatarfull;
public $verified;
public $banned;
public $rank;
public $authKey;
// public $password;
// public $accessToken;
public static function tableName()
{
return 'users';
}
public function getAuthKey()
{
return $this->authKey;
}
public function getId()
{
return $this->id;
}
public function validateAuthKey($authKey)
{
return $this->authKey === $authKey;
}
public static function findIdentity($id)
{
return self::findOne($id);
}
public function validateSteamID($steamid)
{
return $this->steamid === $steamid;
}
public static function findIdentityByAccessToken($token, $type = null)
{
throw new \yii\base\NotSupportedException;
}
public static function findBySteamId($steamid)
{
return self::findOne(['steamid' => $steamid]);
}
}
The result is simply a posted row, with none of the data entered.
Any help would be greatly appreciated, thank you.
If you have redefine the same columns name using public vars these override the vars for activeRecord and then are saved only empty value ..
if this you must remove the (redifined) public vars in your model
otherwise if you have no rules then
Try adding safe at the attribute in you model rules
public function rules()
{
return [
[['steamid', 'username', 'profileurl', 'avatar', 'avatarmedium',
'avatarfull', 'verified', 'banned', 'rank', 'authKey',], 'safe'],
];
}
Declaring 'public' variables made the save() ignore the data being posted. Thanks.
Related
So i created a controller for authentication with 2 methods (token() / native)_). Im using fractal transformer to return response. The token method works fine for me, but the loginAndroid() returns
"Call to a member function createData() on null" error.
Any help? Thank you.
class AuthController extends RestController
{
protected $transformer = UserTransformers::Class;
public function __construct()
{
$this->middleware('auth:api', ['except' => ['login', 'loginAndroid']]);
}
public function login(Request $request)
{
$credentials = $request->only(['username', 'password']);
if (!$token = auth()->attempt($credentials)) {
return response()->json(['error' => 'Unauthorized'], 401);
}
return $this->respondWithToken($token);
}
public function loginAndroid(Request $request)
{
$credentials = $request->only(['username', 'password']);
if (Auth::attempt($credentials)) {
//$user = Auth::user()->with(['employees']);
$userdata = User::with(['employees', 'employees.role', 'employees.branch'])->find(Auth::id());
//$success['token'] = $user->createToken('MyApp')->accessToken;
//return response()->json($userdata, 200);
//return $userdata;
$response = $this->generateItem($userdata);
return $this->sendResponse($response, 201);
} else {
return response()->json('gagal', 401);
}
}
}
this is my restcontroller
abstract class RestController extends Controller
{
protected $manager;
protected $transformer;
public function __construct()
{
$this->manager = new Manager();
}
protected function generateItem($model, $transformer = null)
{
if (!is_null($transformer)) {
return new Item($model, new $transformer);
}
return new Item($model, new $this->transformer);
}
protected function generateCollection($model, $transformer = null)
{
if (!is_null($transformer)) {
return new Collection($model, new $transformer);
}
return new Collection($model, new $this->transformer);
}
protected function sendResponse(ResourceInterface $data, $status = 200)
{
return response()->json(
$this->manager->createData($data)->toArray(),
$status
);
}
protected function sendNotFoundResponse($status)
{
return response()->json($status, 404);
}
protected function sendIseResponse($status)
{
return response()->json($status, 500);
}
}
It looks like your sendResponse() method depends on $this->manager. However, $this->manager gets set in RestController::__construct() and you've overridden the __construct() method in your AuthController::__construct(). So, in order to have $this->manager available, you should call the parent constructor from your AuthController, like this:
class AuthController extends RestController
{
protected $transformer = UserTransformers::Class;
public function __construct()
{
parent::__construct(); // call the parent constructor where
// $this->manager gets initialized
$this->middleware('auth:api', ['except' => ['login', 'loginAndroid']]);
}
... etc
I need to associate some models with at least two other models in an app that I'm developing, but I can't do the association in the controllers.
Here's the code.
UserModel
public function prices() {
return $this->hasMany(PriceClass::class);
}
PriceModel
public function user() {
return $this->belogsTo(ClassOfTheUser::class);
}
public function price_lines() {
return $this->hasMany(PriceLinesClass::class);
}
AreaModel
public function price_lines() {
return $this->hasMany(PriceLineClass::class);
}
PriceLinesModel
public function area() {
return $this->belongsTo(AreaClass::class);
}
public function price() {
return $this->belongsTo(PriceClass::class);
}
How may I do the creation of the Price, if I can't do something like:
public function store(Request $request) {
if ($request->ajax()) {
$user = UserClass::findOfFail($request->input("user_id"));
$user->prices()->save(new PriceClass());
$price = $user->prices()->lastest()->first();
foreach($request->input("price_lines") as $price_line) {
$area = AreaClass::findOrFail($price_line["area_id"]);
$area->price_lines()->save(new PriceLineClass());
$price_line_instance = $area->price_lines()->lastest()->first();
$price->price_lines()->save($price_line_instance);
}
}
}
I'm trying to do:
when user authorized go to home page
when user not authorized go to Login page
but now when I put (correct) user email and password that always refresh login page and doesn't log in into system.
User(ActiveRecord)
class User extends ActiveRecord implements IdentityInterface
{
public function setPassword($user_password)
{
$this->password = sha1($user_password);
}
public function validatePassword($user_password)
{
return $this->user_password === sha1($user_password);
}
public static function findIdentity($id)
{
return self::findOne($id);
}
public static function findIdentityByAccessToken($token, $type = null)
{
}
public function getId()
{
return $this->user_id;
}
public function getAuthKey()
{
}
public function validateAuthKey($authKey)
{
}
}
Login Model:
class Login extends Model
{
public $user_email;
public $user_password;
public function rules()
{
return [
[['user_email', 'user_password'],'required'],
['user_email','email'],
['user_password','validatePassword']
];
}
public function validatePassword($attribute,$params)
{
if(!$this->hasErrors())
{
$user = $this->getUser();
if(!$user || !$user->validatePassword($this->user_password))
{
$this->addError($attribute, 'Пароль или пользователь введенны не верно');
}
}
}
public function getUser()
{
return User::findOne(['user_email'=>$this->user_email]);
}
}
?>
SiteController(only login function)
public function actionLogin()
{
if(!Yii::$app->user->isGuest)
{
return $this->goHome();
}
else {
$login_model = new Login();
return $this->render('login',['login_model'=>$login_model]);
}
}
Putting username and password is not enough you should also perform a login
public function actionLogin()
{
if(!Yii::$app->user->isGuest)
{
return $this->goHome();
}
if ($model->load(Yii::$app->getRequest()->post())) {
// you should perform login
\Yii::$app->getUser()->login($model->user, $this->rememberMe ? $model->module->rememberFor : 0);
return $this->goBack();
}
else {
$login_model = new Login();
return $this->render('login',['login_model'=>$login_model]);
}
}
So I've got three models, "Incomplete", "User", and "Collaboration". They are related with foreign keys as such:
Collaboration->incomplete_id
incomplete_id->Incomplete
Incomplete->user_id
user_id->User
If I want to get the email of a user for a Collaboration model I have the following code
User::find(Incomplete::find($collab->incomplete_id)->user_id)->email);
I feel like this is wrong as I'm not joining any tables but I don't want to break out of mvc and call straight up SQL from the controller. Basically I'm curious how I could do this correctly.
Collaboration Model
class Collaboration extends Eloquent{
//Set the database to connect to as form d
protected $connection = 'formd';
//Set the table for the model to incomplets
protected $table = 'collaborations';
//Set the fillable columns
protected $fillable = array('incompid', 'link', 'shareFlag');
private $rules = array(
'link'=>'required|unique:collaborations|size:56',
'incompid'=>'required|integer'
);
private $errors;
public function validate($data)
{
// make a new validator object
$v = Validator::make($data, $this->rules);
// check for failure
if ($v->fails())
{
// set errors and return false
$this->errors = $v->errors();
return false;
}
// validation pass
return true;
}
public function errors()
{
return $this->errors;
}
public function getId(){
return $this->getKey();
}
public function incomplete(){
return $this->hasOne('Incomplete');
}
}
Incomplete Model
class Incomplete extends Eloquent{
//Set the database to connect to as form d
protected $connection = 'formd';
//Set the table for the model to incomplets
protected $table = 'incompletes';
//Set the fillable columns
protected $fillable = array('name', 'data', 'userid');
private $rules = array(
'name' => 'required|min:3',
'data' => 'required'
);
private $errors;
public function validate($data)
{
// make a new validator object
$v = Validator::make($data, $this->rules);
// check for failure
if ($v->fails())
{
// set errors and return false
$this->errors = $v->errors();
return false;
}
// validation pass
return true;
}
public function errors()
{
return $this->errors;
}
public function getId(){
return $this->getKey();
}
public function getData(){
return $this->data;
}
public function getName(){
return $this->name;
}
public function user(){
return $this->hasOne('User');
}
}
You can use Eloquents relations:
http://laravel.com/docs/eloquent#relationships
class Collaboration extends Eloquent {
public function incomplete()
{
return $this->hasOne('Incomplete', 'incomplete_id', 'id');
}
}
You can then get the data from the incomplete record by doing:
$collab->incomplete->user_id
In this case, use a relation on your models:
class Collaboration extends Eloquent {
public function incomplete()
{
return $this->belongsTo('Incomplete', 'incomplete_id');
}}
And
class Incomplete extends Eloquent {
public function user()
{
return $this->belongsTo('User', 'user_id');
}}
Then, do this:
Collaboration::find($id)->incomplete()->user()->email;
first of all you'll have to update parts of your model class
Class Collaboration extends Eloquent{
protected function incomplete(){
return $this->belongsTo('Incomplete');
}
}
Class Incomplete extends Eloquent{
protected function collaboration(){
return $this->hasOne('Collaboration');
}
protected function user(){
return $this->belongsTo('User');
}
}
Class User extends Eloquent(){
protected function incomplete(){
return $this->hasOne('Incomplete');
}
}
Then inorder to get what your want, here is the query
Collaboration::find($id)->incomplete()->user()->email;
I am trying to open a login form on my site. I have written code but some how it's not working.
The problem is that the login form does not return any error or mesage, it only redirects me to the login page.
Also, for some reason the checklogin function is not working.
controller/main:
public function actionLogin()
{
$model = new LoginForm;
$this->render('login',array('model'=>$model));
}
model/LoginForm:
class LoginForm extends CFormModel
{
public $email;
public $password;
private $_identity;
public function rules()
{
return array(
array('email, password', 'required', 'message' => 'error'),
array('email', 'email', 'allowEmpty' => false, 'checkMX' => true, 'message' => 'error'),
array('password', 'authenticate')
);
}
public function authenticate($attribute,$params)
{
$this->_identity = Account::model()->checkLogin($this->email, $this->password);
if(!$this->_identity)
$this->addError('password', 'error');
}
}
model/account:
public static function model()
{
return parent::model(__CLASS__);
}
public function tableName()
{
return 'table';
}
public function primaryKey()
{
return 'id';
}
public function checkLogin($email, md5($password))
{
$user = $this->findByAttributes(array('email' => $email, 'password' => $password));
if($user===null)
{
return false;
}
return false;
views/main/login:
<?php $form=$this->beginWidget('CActiveForm', array('action' => Yii::app()->createUrl('login'))); ?>
<table>
<tr><?php echo $form->errorSummary($model); ?></tr>
<tr> <?php echo $form->emailField($model,'email'); ?></tr>
<tr><?php echo $form->passwordField($model,'password'); ?></tr>
<tr><?php echo CHtml::submitButton('Login'); ?></tr>
</table>
<?php $this->endWidget(); ?>
To implement your authentication you must follow the steps below:
First in your action:
public function actionLogin() {
$model = new LoginForm();
if (isset($_POST['LoginForm'])) {
if (CActiveForm::validate($model) && $model->validate() && $model->login()) {
// Authentication DONE
} else {
//TRY TO GET ERRORS
}
}
}
In your model add the login function:
public function login() {
/*
* if identity property had no value, here we initialize
* identity property
*/
if ($this->identity === null) {
$this->identity = new UserIdentity($this->username, $this->password);
//authenticating
$this->identity->authenticate();
} else {
/*
* if error code was NONE, it means user has been successfully
* authenticated.
*/
if ($this->identity->errorCode === UserIdentity::ERROR_NONE) {
Yii::app()->user->login($this->identity);
return true;
}
}
}
and in your model's authentication method:
public function authenticate() {
//if validation was done and we had no error while validating
if (!$this->hasErrors()) {
//new instance of identity class
$this->identity = new UserIdentity($this->username, $this->password);
if (!$this->identity->authenticate()) {
$this->addError('password', Yii::t('app', 'Invalid Username or Password'));
}
}
}
Then you need to add UserIdentity Class (Put this class in your components directory)
class UserIdentity extends CUserIdentity {
private $_id;
private $_username;
public function authenticate() {
$record = Account::model()->findByAttributes(array(
'username' => $this->username
));
if ($record === null) {
//adds error to user
$this->errorCode = self::ERROR_USERNAME_INVALID;
//authentication failed
return false;
} else if (!CPasswordHelper::verifyPassword($this->password, $record->password)) {
$this->errorCode = self::ERROR_PASSWORD_INVALID;
return false;
} else {
/*
* no error
* user information[username and password are valid]
*/
$this->errorCode = self::ERROR_NONE;
//user's id whitch will be accessible through Yii::app()->user->id
$this->_id = $record->id;
//user's username whitch will be accessible through Yii::app()->user->name
$this->_username = $record->username;
//success
return true;
}
}
/**
* Overriding CUserIdentity's getId() method
* #access public
* #return integer user id
*/
public function getId() {
return $this->_id;
}
/**
* Overriding CUserIdentity's getName() method
* #access public
* #return string username
*/
public function getName() {
return $this->_username;
}
Change checklogin function as given below and try again to fix this.
public function checkLogin($email, md5($password))
{
$user = $this->model()->findByAttributes(array('email' => $email, 'password' => $password));
if($user===null)
{
return false;
}
return false;
}
If you are trying to implement the login functionality separately, then you are missing the whole logic to register the user's auth details using the Yii::app()->login()dependent on the CUserIdentity class.
Master this link -> http://www.yiiframework.com/doc/guide/1.1/en/topics.auth and proceed for post authentication.