I m calling logout api in yii2 framework using logout action
url :http://localhost/mobile/public/api/v1/logout
Code:
public function actionLogout()
{
$user_t = Yii::$app->user->logout();
return $this->apiItem(array(),'Logout Successfully');
}
but after calling logout api
when after this i calling view profile api it returns user data
public function actionViewprofile()
{
$user = Yii::$app->user->identity;
$profile_fetch = [
'firstname' => $user['member_fname'],
'lastname' => $user['member_lname'],
'gender' => $user['member_gender'],
'dateofbirth' => $user['member_dob']
];
return $this->apiItem($profile_fetch);
}
where apitem is a function for json parameter format
/**
* Api Item response
*/
public function apiItem($data, $message = false,$flag = false )
{
Yii::$app->response->statusCode = 200;
return [
'statusCode' => 200,
'message' => $message ? $message : 'Data retrieval successful',
'data' => $data,
'flag' => $flag
];
}
Clear the token from DB and clear the user session
$userID = Yii::$app->session->get('userID');
$userModel = User::find()->where(['id'=>$userID])->one();
if(!empty($userModel))
{
$userModel->token=NULL;
$userModel->save(false);
}
Yii::app()->user->logout(false);
Related
I'm trying to perform unit test for Laravel socialite function. There are 2 functions for redirect and callback.
There is one problem that I couldn't test successful was the callback function.
Here is how I test the redirect function
AuthController.php
/**
* #return mixed
*/
public function loginWithGoogle () {
return Socialite::driver('google')
->scopes([
'https://www.googleapis.com/auth/userinfo.email'
])
->with([
'access_type' => 'offline',
'prompt' => 'consent select_account'
])
->redirect();
}
AuthTest.php
public function testGoogleLoginForwardRequest()
{
$response = $this->getJson('/oauths/forward/google');
$response->assertStatus(302);
}
For the callback function
AuthController.php
/**
* #return RedirectResponse
*/
public function loginRedirectFromGoogle (): RedirectResponse
{
$user = Socialite::driver('google')->stateless()->user();
$acUser = User::where('email', $user->getEmail())->first();
if(empty($acUser)){
return redirect('/oauth/login?'.http_build_query([
'force_external_oauth_response' => 'true',
'external_oauth_response_error' => 'User account not register'
]));
}
Auth::login($acUser);
OAuthProvider::updateOrCreate(
[
'provider_name' => 'google',
'provider_id' => $user->id,
'user_id' => $acUser->id
],
[
'encrypted_token' => Crypt::encryptString($user->token),
'encrypted_refreshed_token' => Crypt::encryptString($user->refreshToken),
'expires_at' => time() + $user->expiresIn // time and expiresIn are all in seconds
]
);
return redirect('/oauth/login?'.http_build_query([
'force_external_oauth_response' => 'true',
'external_oauth_response_error' => ''
]));
}
AuthTest.php
public function testGoogleLoginRedirectRequest()
{
Mockery::getConfiguration()->allowMockingNonExistentMethods(false);
$abstractUser = Mockery::mock('Laravel\Socialite\Two\User');
$abstractUser
->shouldReceive('getId')
->andReturn(rand())
->shouldReceive('getName')
->andReturn($this->faker->name())
->shouldReceive('getEmail')
->andReturn($this->faker->name() . '#gmail.com')
->shouldReceive('getAvatar')
->andReturn('https://en.gravatar.com/userimage');
Socialite::shouldReceive('driver')->with('google')->andReturn($abstractUser);
$response = $this->getJson('/oauths/forward/google');
$response->assertStatus(302);
}
For this function it returns error the following
Mockery\Exception\BadMethodCallException: Method Mockery_0_Laravel_Socialite_Two_User::scopes() does not exist on this mock object in C:\xampp\htdocs\ac-dev\achievement-console\vendor\mockery\mockery\library\Mockery\Loader\EvalLoader.php(34) : eval()'d code:928
For the callback function, I followed this example How to Test Laravel Socialite
I am getting error from IE when I redirect to "dashboard" controller after settings session values in "login" function ( return redirect()->to(base_url('dashboard'));). I have this working on Chrome, Firefox, Edge, and Opera.
I am using public $sessionDriver = 'CodeIgniter\Session\Handlers\DatabaseHandler'; for session storage. this works well with other borwsers.
<?php
namespace App\Controllers;
use App\Controllers\BaseController;
use App\Models\UserModel;
class User extends BaseController
{
public function login()
{
$data = [];
if ($this->request->getMethod() == 'post') {
$rules = [
'email' => 'required|min_length[6]|max_length[50]|valid_email',
'password' => 'required|min_length[8]|max_length[255]|validateUser[email,password]',
];
$errors = [
'password' => [
'validateUser' => "Email or Password don't match",
],
];
if (!$this->validate($rules, $errors)) {
return view('login', [
"validation" => $this->validator,
]);
} else {
$model = new UserModel();
$user = $model->where('email', $this->request->getVar('email'))
->first();
// Stroing session values
$this->setUserSession($user);
// Redirecting to dashboard after login
return redirect()->to(base_url('dashboard'));
}
}
return view('login');
}
private function setUserSession($user)
{
$data = [
'id' => $user['id'],
'name' => $user['name'],
'phone_no' => $user['phone_no'],
'email' => $user['email'],
'isLoggedIn' => true,
];
session()->set($data);
return true;
}
public function register()
{
$data = [];
if ($this->request->getMethod() == 'post') {
//let's do the validation here
$rules = [
'name' => 'required|min_length[3]|max_length[20]',
'phone_no' => 'required|min_length[9]|max_length[20]',
'email' => 'required|min_length[6]|max_length[50]|valid_email|is_unique[tbl_users.email]',
'password' => 'required|min_length[8]|max_length[255]',
'password_confirm' => 'matches[password]',
];
if (!$this->validate($rules)) {
return view('register', [
"validation" => $this->validator,
]);
} else {
$model = new UserModel();
$newData = [
'name' => $this->request->getVar('name'),
'phone_no' => $this->request->getVar('phone_no'),
'email' => $this->request->getVar('email'),
'password' => $this->request->getVar('password'),
];
$model->save($newData);
$session = session();
$session->setFlashdata('success', 'Successful Registration');
return redirect()->to(base_url('login'));
}
}
return view('register');
}
public function profile()
{
$data = [];
$model = new UserModel();
$data['user'] = $model->where('id', session()->get('id'))->first();
return view('profile', $data);
}
public function logout()
{
session()->destroy();
return redirect()->to('login');
}
}
CodeIgniter4 has its "user agent class" this should help you to be able to validate if you are using IE, I share the documentation and I hope it helps you.
You can validate using that class and redirect with another method.
https://codeigniter.com/user_guide/libraries/user_agent.html
I'm trying to pass token_id and user_id from controller to middleware.
I have some hard time with that.
This is the code that I'm trying to run.
class UserController extends Controller
{
protected $user_id;
protected $token_id;
public function __construct()
{
$user_id = $this->user_id;
$token_id = $this->token_id;
$together = $user_id . ':' . $token_id;
$this->middleware('check.auth:' . $together);
}
public function setLogin(Request $request)
{
$credentials = request(['email', 'password']);
if (!Auth::attempt($credentials)){
Secure::checkFailedAuth($request->email, $request->password);
return response()->json(['response' => false, 'status' => 400, 'message' => 'Provided details are not correct!'], 400);
}
$user = Auth::user();
$tokenResult = $user->createToken($user->name);
$token = $tokenResult->token;
$token->save();
$this->user_id = Auth::id();
$this->token_id = $tokenResult->token->token_id;
return response()->json(['result' => true, 'status' => 200, 'message' => 'Login Successful', 'data' => Auth::user(), 'token' => $tokenResult->accessToken ], 200);
}
When I run that I have no errors, but there is null on both user_id and token_id.
Any ideas why?
I'm building an online courses website, where students can buy a course via PayPal. The payment process is working successfully, But I'm confused on where or how to store course and user data after PayPal Payment Approval.
I have a users table, courses table and pivot table: course_students where I store the id of the course and the id of the student:
-------------
course_students
--------------
student_id course_id
1 2
----------
This is PayPalService Class:
class PayPalService
{
use ConsumesExternalServices;
protected $baseUri;
protected $clientId;
protected $clientSecret;
public function __construct()
{
$this->baseUri = config('services.paypal.base_uri');
$this->clientId = config('services.paypal.client_id');
$this->clientSecret = config('services.paypal.client_secret');
}
public function resolveAuthorization(&$queryParams, &$formParams, &$headers)
{
$headers['Authorization'] = $this->resolveAccessToken();
}
public function decodeResponse($response)
{
return json_decode($response);
}
public function resolveAccessToken()
{
$credentials = base64_encode("{$this->clientId}:{$this->clientSecret}");
return "Basic {$credentials}";
}
public function handlePayment(Request $request)
{
$order = $this->createOrder($request->value, $request->currency);
$orderLinks = collect($order->links);
$approve = $orderLinks->where('rel', 'approve')->first();
session()->put('approvalId', $order->id);
return redirect($approve->href);
}
public function handleApproval()
{
if (session()->has('approvalId')) {
$approvalId = session()->get('approvalId');
$payment = $this->capturePayment($approvalId);
$name = $payment->payer->name->given_name;
$payment = $payment->purchase_units[0]->payments->captures[0]->amount;
$amount = $payment->value;
$currency = $payment->currency_code;
return redirect()
->route('success')
->with('payment', "Thanks, {$name}. We received your {$amount}{$currency} payment.");
}
// $errorMessage = 'We cannot capture the payment. Try again, please';
return redirect()
->route('paymentform')
->with('error','We cannot capture the payment. Try again, please');
}
public function createOrder($value, $currency)
{
return $this->makeRequest(
'POST',
'/v2/checkout/orders',
[],
[
'intent' => 'CAPTURE',
'purchase_units' => [
0 => [
'amount' => [
'currency_code' =>strtoupper($currency),
'value' => round($value * $factor = $this->resolveFactor($currency)) / $factor,
]
]
],
'application_context' => [
'brand_name' => config('app.name'),
'shipping_preference' => 'NO_SHIPPING',
'user_action' => 'PAY_NOW',
'return_url' => route('approval'),
'cancel_url' => route('cancelled'),
]
],
[],
$isJsonRequest = true,
);
}
public function capturePayment($approvalId)
{
return $this->makeRequest(
'POST',
"/v2/checkout/orders/{$approvalId}/capture",
[],
[],
[
'Content-Type' => 'application/json'
],
);
}
public function resolveFactor($currency)
{
$zeroDecimalCurrencies = ['JPY'];
if (in_array(strtoupper($currency), $zeroDecimalCurrencies)) {
return 1;
}
return 100;
}
}
PaymentController:
public function paymentForm($course_uuid)
{
$currencies = Currency::all();
$platforms = PaymentPlatform::get();
$course = Course::where('uuid', $course_uuid)->where('status',1)->where('availability',1)->first();
return view('public.payment.paypalform', compact('currencies','platforms','course'));
}
/**
* implment Payemnt process
*
* #param Request $request
*/
public function pay(Request $request)
{
// dd($request->all());
$rules = [
'value' => ['required', 'numeric', 'min:5'],
'currency' => ['required', 'exists:currencies,iso'],
'payment_platform' => ['required', 'exists:payment_platforms,id'],
];
$request->validate($rules);
$paymentPlatform = $this->paymentPlatformResolver
->resolveService($request->payment_platform);
session()->put('paymentPlatformId', $request->payment_platform);
return $paymentPlatform->handlePayment($request);
}
protected function approval()
{
if (session()->has('paymentPlatformId')) {
$paymentPlatform = $this->paymentPlatformResolver
->resolveService(session()->get('paymentPlatformId'));
return $paymentPlatform->handleApproval();
}else{
return redirect()
->route('courses.levels')
->withErrors('We cannot retrieve your payment platform. Try again, please.');
}
}
protected function canceled()
{
return redirect()
->route('courses.levels')
->withErrors('You cancelled the payment.');
}
In your payment controller you can save you the course information in session. After payment when user will redirect, save the information to your desired database table..
//save course info or other info
session()->put('courseInfo', [your data]);
your controller function:
/**
* implment Payemnt process
*
* #param Request $request
*/
public function pay(Request $request)
{
// dd($request->all());
$rules = [
'value' => ['required', 'numeric', 'min:5'],
'currency' => ['required', 'exists:currencies,iso'],
'payment_platform' => ['required', 'exists:payment_platforms,id'],
];
$request->validate($rules);
$paymentPlatform = $this->paymentPlatformResolver
->resolveService($request->payment_platform);
session()->put('paymentPlatformId', $request->payment_platform);
//save course info or other info
session()->put('courseInfo', [your data]);
return $paymentPlatform->handlePayment($request);
}
you another function: approval() call another function $paymentPlatform->handleApproval(); inside of it after payment done.
Go to handleApproval() function and hopefully you will find there user account creation codes. Now get the session value session()->get('courseInfo') and save in your desired table.
Hey guys i have read and studied the kohana orm and auth modules. so i want to implement am admin section to my website. i get the error above and i have googled but can't seem to find the answer. am using Kohana 3.3.4
so a created a controller called admin:
<?php defined('SYSPATH') or die('No direct script access!');
class Controller_Admin extends Controller_Dev
{
public $template = 'login_template';
public function action_index()
{
if (Auth::instance()->logged_in()) {
$this->redirect->body('admin/dashboard', 302);
}
$this->redirect('admin/login');
}
//lets login user
public function action_login()
{
$view = new View('admin_login');
$this->template->title = "Log in";
if ($_POST) {
$user = ORM::factory('user');
$status = $user->login($_POST);
if ($status) {
$this->redirect('admin/dashboard', 302);
}
else {
$errors = $_POST->errors('admin/login');
}
}
// Display the login form
$this->template->content = $view;
}
//lets logout user
public function action_logout()
{
Auth::instance()->logout();
$this->redirect('admin/login', 302);
}
//lets register new users
public function action_register()
{
$view = View::factory('admin_register')
->set('values', $_POST)
->bind('errors', $errors);
$this->template->title = "Registration Page";
if ($_POST)
{
$user = ORM::factory('User');
// The ORM::values() method is a shortcut to assign many values at once
/* $external_values = array(
// The unhashed password is needed for comparing to the password_confirm field
'password' => Arr::get($_POST, 'password'),
// Add all external values
) + Arr::get($_POST, '_external', array());
$extra = Validation::factory($external_values)
->rule('confirm_password', 'matches', array(':validation', ':field', 'password')); */
try
{
//$test = $extra; //Arr::get($_POST, 'password');
//$view->test = $test;
$data = $this->request->post();
$user->register($data);
// Redirect the user to his page
$this->redirect('admin/login');
}
catch (ORM_Validation_Exception $e)
{
$errors = $e->errors('models');
}
}
$this->template->content = $view;
}
and i created a model called user to help me validate the new user account before save it to the database:
<?php defined('SYSPATH') or die('No direct access allowed.');
class Model_User extends Model_Auth_User {
//public $_table_name = 'users';
protected $_has_many = array(
'user_tokens' => array('model' => 'user_token'),
'roles' => array('model' => 'role', 'through', 'roles_users'),
// for facbook, google+, twitter and yahoo indentities
'user_identity' => array(),
);
protected $_ignored_columns = array('confirm_password');
public function rules()
{
return array(
'username' => array(
array('not_empty'),
array('min_length', array(':value', 4)),
array('max_length', array(':value', 32)),
array(array($this, 'username_available')),
),
'password' => array(
'not_empty' => NULL,
'min_length' => array(5),
'max_length' => array(42),
),
'password_confirm' => array(
'matches' => array('password'),
),
'email' => array(
'not_empty' => NULL,
'min_length' => array(4),
'max_length' => array(127),
'email' => NULL,
),
);
}
public function filters()
{
return array(
'password' => array(
array(array($this, 'hash_password')),
),
);
}
public function username_available($username)
{
// There are simpler ways to do this, but I will use ORM for the sake of the example
//return ORM::factory('Member', array('username' => $username))->loaded();
// Check if the username already exists in the database
return ! DB::select(array(DB::expr('COUNT(username)'), 'total'))
->from('users')
->where('username', '=', $username)
->execute()
->get('total');
}
public function hash_password($password)
{
// Do something to hash the password
}
public function register($array)
{
$this->values($array);
$this->save();
// Create a new user record in the database
// Save the new user id to a cookie
cookie::set('user', $id);
return $id;
}
}
When i visit the admin registration page. it fails displaying an error which says:
ErrorException [ Warning ]: call_user_func_array() expects parameter 1 to be a valid callback, no array or string given
so please help me out because i think i might be missing something. Thanks in advance guys. Am using Kohana 3.3.4
I had the same error recently. You need to change line:
array(array($this, 'username_available')),
to line (for username):
array(array($this, 'unique'), array('username', ':value')),
as stated in https://kohanaframework.org/3.3/guide-api/Model_Auth_User#rules
I hope this helps you.