I have a base class which is inherited by all the controllers. I am having a function in the base class which determines the logged in users role using Auth. Once the users role is determine a variable $LoggedIn_role is set.
This method is correctly called on the initial page load, but later i am issuing ajax calls to check whether the user is still logged in, at that time the Auth::logged_in() always returning 0.
The kohana version i am using is 3.3
Can any one please suggest what is the best approach to circumvent this issue. Thanks.
To login -
if ($ValidObj->check()) {
if (Auth::instance()->login($_POST['email'], $_POST['password'],FALSE)) {
$this->DoPostLoginJobs();
} else {
$this->ManageError(Controller_Application::MsgWrongUserCredentials);
}
} else {
$this->Form_Errors = $ValidObj->errors('');
}
To Logout -
public function action_logout() {
$loggedout = Auth::instance()->logout();
if ($loggedout)
HTTP::redirect ('/home/'); // redirects to the home page.
}
Inside the controller_Application . The base class of all the controllers
public function DetermineUserRole() {
$this->LoggedIn_Role = Controller_Application::None;
try {
if (Auth::instance()->logged_in('freelancer')) {
$this->LoggedIn_Role = Controller_Application::Freelancer;
$this->LoggedIn_Id = Auth::instance()->get_user()->pk();
} else if (Auth::instance()->logged_in('employer')) {
$this->LoggedIn_Role = Controller_Application::Employer;
$this->LoggedIn_Id = Auth::instance()->get_user()->pk();
}
} catch (Gettrix_Exception $exc) {
$this->ManageError(Controller_Application::RedirectNonRecoverableError);
}
public function before() {
if ($this->request->is_ajax()) {
$this->auto_render = false;
}
$this->DetermineUserRole();
if($this->auto_render==TRUE){
parent::before();
$this->template->content = '';
$this->template->styles = array();
$this->template->scripts = array();
View::set_global('site_name', 'TheWebTeam');
View::bind_global('Form_Errors', $this->Form_Errors);
View::bind_global('LoggedIn_Role', $this->LoggedIn_Role);
View::bind_global('LoggedIn_Id', $this->LoggedIn_Id);
View::bind_global('InvitedEmail', $this->InvitedEmail);
View::bind_global('InvitedUniqueID', $this->InvitedUniqueID);
View::bind_global('scripts', $this->template->scripts);
View::bind_global('styles', $this->template->styles);
}
//This is inside the Home page controller, where it lists all the jobs for the logged in user.
public function action_joblist()
{
echo Auth::instance()->logged_in() . //The state holds to the initial state, doesn't //change when the user is logged out or logged in.
}
Please note that action_joblist() is called via AJAX/Jquery call.
The issue is fixed by following the instructions given in the link : http://forum.kohanaframework.org/discussion/9619/session-timeout-corruption-problems/p1
Related
So I've built a small conditional to evaluate which button is pressed in my form (as there are 2). This works fine and fires off the correct method and writes the appropriate data to the DB, however my redirect is not working. It saves() to the DB and then simply stays on the page designated as the POST route.
I suspect the problem has something to do with my conditional and the use of $this.
Here is my check_submit method:
public function check_submit()
{
if(!is_null(Input::get('add_to_invoice'))){
$this->invoice_add_item();
} elseif(!is_null(Input::get('complete_invoice'))) {
$this->invoice_complete();
}
}
Here is one of the 2 methods which I am currently testing:
public function invoice_add_item()
{
$input = Request::all();
$invoice_items = new Expense;
$invoice_items->item_id = $input['item_id'];
$invoice_items->category_id = $input['category'];
$invoice_items->price = $input['price'];
$invoice_items->store_id = $input['store'];
if(Input::has('business_expense'))
{
$invoice_items->business_expense = 1;
}
else{
$invoice_items->business_expense = 0;
}
$invoice_items->save();
return redirect('/');
}
Perhaps there is a better way of handling this in my routes(web) file, but I'm not sure how to go about this.
You should add the return to the check_submit() method. Something like
public function check_submit()
{
if(!is_null(Input::get('add_to_invoice'))){
return $this->invoice_add_item();
} elseif(!is_null(Input::get('complete_invoice'))) {
return $this->invoice_complete();
}
}
Better yet, you should probably return a boolean on invoice_add_item() and based on that, redirect the user to the correct place (or with some session flash variable with an error message)
How can I create a PHP function or class that checks if a user who is a half-admin (set from a MySQL database) has some rights such as creating a new page, editing, or deleting?
I need a function that checks the user permissions and then display the code like this:
if ($he_can_create_page){
//continue the script.....
}else{
//don`t continue
}
In present I use sessions like this:
If($_SESSION['user_type']=='Admin'||$_SESSION['user_type']=='premium'){
//do stuff
}else if()......... {
// ..............
}
but they become too many if statements, and I want a cleaner code :)
interface User {
public function canCreatePage();
public function canDeletePage();
public function canEditPage();
....
}
class Admin implements User {
public function canCreatePage(){
return true;
}
public function canEditPage(){
return true;
}
...
}
class Editor implements User {
public function canCreatePage() {
return false;
}
public function canEditPage(){
return true;
}
...
}
then from what you get in the data base
if ($row['user_type'] == 'Admin') {
$user = new Admin();
} else if $row['user_type'] == 'Editor') {
$user = new Editor();
} ....
in all your pages :
if ($user->canCreatePage()){
//continue the script.....
}else{
//don`t continue
}
If you want to store your user in session the first time you get it from the dataBase
$_SESSION['user'] = serialize($user);
in the next page
$user = unserialize($_SESSION['user']);
Or you can also just store the id of the user in session and get it back from de
DB on every page.
Create a generic function an put it in a file which is common for all files something like this
function pageCreatePermission() {
if($_SESSION['user_type']=='Admin'||$_SESSION['user_type']=='premium'){
return true;
} else {
return false;
}
then use this function something like this in your file
if (pageCreatePermission()) {
//do your stuff
} else {
//show error you want
}
Add columns in your users table like:
| canEdit | canDelete | canCreate |
with flags 1/0. 1 for true, 0 for false.
select the fields and make checks i.e.:
if($row['canEdit'] = 1) {
//continue (return true)
}
else {
//stop (return false)
}
You can make it a function with params, so you will give the param to the function i.e. $canDelete (which is your $row data) and it checks only that permission
function userPermissions($type)
if($type=1) {
return true;
}
else {
return false;
}
$canCreate = $row['canCreate'];
if(userPermissions($canCreate)) { ...
The answer is to use an access control system. There are many different types. The most used (in web development) are ACL (Access control list) and RBAC (Role based access control). The rules can be filled from database or hardcoded.
To give you an idea of how they work look at the examples from Zend Framework: ACL and RBAC.
In Zend Framework the ACL is not very different from a RBAC because it also has roles. But normally an ACL is user based and not role based. If you like you can integrate the ACL/RBAC from Zend or other frameworks into your own project.
Read about how yii do it: yii RBAC
When a user is logged in, I would like them to be able to visit http://website.com/user and be taken to http://website.com/1/johndoe, where 1 is their user ID, and johndoe is their user name.
I'm trying to use _remap() to catch all attempts at http://website.com/user/, so even incomplete URIs like http://website.com/user/1 or http://website.com/user/1/joh are redirected to http://website.com/user/1/johndoe.
Here's what I've tried:
class User extends CI_Controller {
function index($uID, $user) {
echo $uID;
echo $user;
}
function _remap() {
$uID = 3;
$user = 'johndoe';
//redirect('user/'.$uID.'/'.$user); // Updates URI, but redirect loop
//$this->index($uID, $user); Works, but doesn't update the URI
}
}
I could of course detect the method first, and do something like this:
function _remap($method = '') {
if ($method != 'view') {
$uID = 3;
$user = 'johndoe';
redirect('user/view/'.$uID.'/'.$user);
}
}
function view($uID, $user) {
echo $uID;
echo $user;
}
But then I think the URI would look like http://website.com/user/view/1/johndoe, and I'd rather view was excluded. How should I go about this problem?
If you have a _remap() method - it will always be called, so redirecting to user/anything will still call _remap() on the next request, so not only do you need to catch the router method and its parameters - you must do it if you want to use _remap() in a way that makes any sense:
public function _remap($method, $args)
{
if ($method === 'user' && (empty($args) OR ! ctype_digit($args[0])))
{
// determine and handle the user ID and name here
}
else
{
return call_user_func_array(array($this, $method), $args));
}
}
The solution I use is:
$route['user/(:num)/:any'] = 'user/view/$1';
$route['user/(:num)'] = 'user/view/$1';
Really, the username should only be for SEO purposes and in which case, should not be passed to the action. You will of course be able to access the username from the UserID when you look up the user anyway, so I feel it's redundant.
The above will match
/user/1/jdoe
/user/1
but will only pass 1 to your user/view action.
Edit: With your comment in mind:
$route['user/(:num)/(:any)'] = 'user/view/$1/$2';
$route['user/(:num)'] = 'user/view/$1';
function view($UserID, $UserName = null) {
// Load the model and get the user.
$this->model->load('user_model');
$User = $this->user_model->GetByUserID($UserID);
// If the user does not exist, 404!
if (empty($User)) {
show_404();
return;
}
// If the UserName does not exist, or is wrong,
// redirect to the correct page.
if($UserName === null || strtolower($User->UserName) != strtolower($UserName)) {
redirect("user/$UserID/{$User->UserName}");
return;
}
}
The above will accept the username as the parameter, however if it is not supplied or if it is not correct, it will redirect to the correct url and continue.
Hopefully this solves your problem?
i am using opencart in one project,
every thing is working fine but i am unable to find an option to stop view of home page until LOGIN.
actually this is project requirement, no one can see home until LOGIN.
is there way to do this with OPEN CART ?
Thanks
this is untested, but should point you in the right direction:
(OpenCart 1.4.9.x)
Save this to:
catalog/controller/common/check_login.php
<?php
class ControllerCommonCheckLogin extends Controller {
public function index() {
if (!$this->customer->isLogged()) {
// Require to be logged in
$ignore = array(
'account', 'payment'
);
$match = false;
if (isset($this->request->get['route'])) {
foreach ($ignore as $i) {
if (strpos($this->request->get['route'], $i) !== false) {
$match = true;
break;
}
}
}
// Show site if logged in as admin
$this->load->library('user');
$this->registry->set('user', new User($this->registry));
if (!$this->user->isLogged() && !$match) {
return $this->forward('account/login');
}
}
}
}
?>
Edit /index.php
Find:
// Maintenance Mode
$controller->addPreAction(new Action('common/maintenance/check'));
Add After:
// Login Check
$controller->addPreAction(new Action('common/check_login'));
Essentially use the same logic as the maintenence check... The big difference is it looks for the word 'account' in the string... If it finds it it allows the page to be displayed, if not it redirects to the login page...
Use the word "account" instead of "login" in case they need to register... All of the account pages already check for loggin so there is no worry there...
Again, untested so you may need to tweak one or two things - but it should/may work by dropping in the code
check_login.php for opencart 1.5.3
<?php
class ControllerCommonCheckLogin extends Controller {
public function index() {
// Require to be logged in
if (!$this->customer->isLogged()) {
// Require to be logged in
$ignore = array(
'account','payment'
);
$match = false;
if (isset($this->request->get['route'])) {
foreach ($ignore as $i) {
if (strpos($this->request->get['route'], $i) !== false) {
$match = true;
break;
}
}
}
// Show site if logged in as admin
$this->load->library('user');
$this->user = new User($this->registry);
if (!$this->user->isLogged() && !$match) {
$this->redirect($this->url->link('account/login'));
}
}
}
}
?>
There is nothing built-in that I know of, but you can do it yourself. Based on your answers to #CarpeNoctumDC's questions you may have to do some digging, but this should get you started:
system/library/customer.php
public function isLogged() { ... }
catalog/controller/common/home.php
if (!$this->customer->isLogged()) {
// login page
exit;
}
The right way to go about this is to open
/catalog/controller/common/home.php
find public function index() { at the top of the code, and after it put
if(!$this->customer->isLogged()) {
$this->session->data['redirect'] = $this->url->link('common/home');
$this->url->redirect('account/login', '', 'SSL');
}
In case you're unsure how to do this properly, just take a look at the first few lines after public function index() { in
/catalog/controller/account/account.php
setting your code in the home controller to common/home in place of account/account
I have users' table users, where I store information like post_count and so on. I want to have ~50 badges and it is going to be even more than that in future.
So, I want to have a page where member of website could go and take the badge, not automatically give him it like in SO. And after he clicks a button called smth like "Take 'Made 10 posts' badge" the system checks if he has posted 10 posts and doesn't have this badge already, and if it's ok, give him the badge and insert into the new table the badge's id and user_id that member couldn't take it twice.
But I have so many badges, so do I really need to put so many if's to check for all badges? What would be your suggestion on this? How can I make it more optimal if it's even possible?
Thank you.
optimal would be IMHO the the following:
have an object for the user with functions that return user specific attributes/metrics that you initialise with the proper user id (you probably wanna make this a singleton/static for some elements...):
<?
class User {
public function initUser($id) {
/* initialise the user. maby load all metrics now, or if they
are intensive on demand when the functions are called.
you can cache them in a class variable*/
}
public function getPostCount() {
// return number of posts
}
public function getRegisterDate() {
// return register date
}
public function getNumberOfLogins() {
// return the number of logins the user has made over time
}
}
?>
have a badge object that is initialised with an id/key and loads dependencies from your database:
<?
class Badge {
protected $dependencies = array();
public function initBadge($id) {
$this->loadDependencies($id);
}
protected function loadDependencies() {
// load data from mysql and store it into dependencies like so:
$dependencies = array(array(
'value' => 300,
'type' => 'PostCount',
'compare => 'greater',
),...);
$this->dependencies = $dependencies;
}
public function getDependencies() {
return $this->dependencies;
}
}
?>
then you could have a class that controls the awarding of batches (you can also do it inside user...)
and checks dependencies and prints failed dependencies etc...
<?
class BadgeAwarder {
protected $badge = null;
protected $user = null;
public function awardBadge($userid,$badge) {
if(is_null($this->badge)) {
$this->badge = new Badge; // or something else for strange freaky badges, passed by $badge
}
$this->badge->initBadge($badge);
if(is_null($this->user)) {
$this->user = new User;
$this->user->initUser($userid);
}
$allowed = $this->checkDependencies();
if($allowed === true) {
// grant badge, print congratulations
} else if(is_array($failed)) {
// sorry, you failed tu full fill thef ollowing dependencies: print_r($failed);
} else {
echo "error?";
}
}
protected function checkDependencies() {
$failed = array();
foreach($this->badge->getDependencies() as $depdency) {
$value = call_user_func(array($this->badge, 'get'.$depdency['type']));
if(!$this->compare($value,$depdency['value'],$dependency['compare'])) {
$failed[] = $dependency;
}
}
if(count($failed) > 0) {
return $failed;
} else {
return true;
}
}
protected function compare($val1,$val2,$operator) {
if($operator == 'greater') {
return ($val1 > $val2);
}
}
}
?>
you can extend to this class if you have very custom batches that require weird calculations.
hope i brought you on the right track.
untested andp robably full of syntax errors.
welcome to the world of object oriented programming. still wanna do this?
Maybe throw the information into a table and check against that? If it's based on the number of posts, have fields for badge_name and post_count and check that way?