I'm writing a Symfony 3.0 application and I have the following situation:
The system provides different login and register pages (one for each subsite)
A user can have the same username to login on different subsites but accounts are managed separately.
My idea was to save the subsite domain's unique name in the username field with # notation, example:
User a.ndrew can access both domain1 and domain2 with the same username but the system stores 2 different accounts with usernames a.ndrew#domain1 and a.ndrew#domain2.
I handle this automatically by overwriting RegistrationController actions and it works fine during registration but now i'm trying to automatically push "#domain" data in the username at login with no luck. I'm overwriting loginAction but I don't understand how to push data in the username.
EDIT (tnx #malcom)
Here is my loginAction called companyUserLoginAction it simply checks if companyName exists and redirect to FOS loginAction, I'd like to be able to add #companyName at the end of the username provided by user in the login form but I don't understand where this information is handled by the controller:
`
/**
* #Route("/{companyName}/login")
*/
public function companyUserLoginAction(Request $request, $companyName)
{
$em = $this->getDoctrine()->getManager();
$company = $em->getRepository('CompanyBundle:Company')->findOneBy(array('name' => $companyName));
if ($company == null)
{
throw new NotFoundHttpException();
}
return $this->loginAction($request);
}
/**
*Default FOS loginAction
*/
public function loginAction(Request $request)
{
/** #var $session \Symfony\Component\HttpFoundation\Session\Session */
$session = $request->getSession();
if (class_exists('\Symfony\Component\Security\Core\Security')) {
$authErrorKey = Security::AUTHENTICATION_ERROR;
$lastUsernameKey = Security::LAST_USERNAME;
} else {
// BC for SF < 2.6
$authErrorKey = SecurityContextInterface::AUTHENTICATION_ERROR;
$lastUsernameKey = SecurityContextInterface::LAST_USERNAME;
}
// get the error if any (works with forward and redirect -- see below)
if ($request->attributes->has($authErrorKey)) {
$error = $request->attributes->get($authErrorKey);
} elseif (null !== $session && $session->has($authErrorKey)) {
$error = $session->get($authErrorKey);
$session->remove($authErrorKey);
} else {
$error = null;
}
if (!$error instanceof AuthenticationException) {
$error = null; // The value does not come from the security component.
}
// last username entered by the user
$lastUsername = (null === $session) ? '' : $session->get($lastUsernameKey);
if ($this->has('security.csrf.token_manager')) {
$csrfToken = $this->get('security.csrf.token_manager')->getToken('authenticate')->getValue();
} else {
// BC for SF < 2.4
$csrfToken = $this->has('form.csrf_provider')
? $this->get('form.csrf_provider')->generateCsrfToken('authenticate')
: null;
}
return $this->renderLogin(array(
'last_username' => $lastUsername,
'error' => $error,
'csrf_token' => $csrfToken,
));
}
}
`
In fuelphp project, I have a normal backend for users who are registered. In frontend I have a login from where only the university user can login to backend(superadmin also can't login from frontend).
My problem here is if I open both backend, frontend and then on refresh of backend or frontend user is logged out of backend.
I have maintained backend login as default fuelphp login(admin.php).
code :
public function action_login() {
// Already logged in
Auth::check() and Response::redirect('admin');
$val = Validation::forge();
if (Input::method() == 'POST') {
$val->add('email', 'Email or Username')
->add_rule('required');
$val->add('password', 'Password')
->add_rule('required');
if ($val->run()) {
$auth = Auth::instance();
// check the credentials. This assumes that you have the previous table created
if (Auth::check() or $auth->login(Input::post('email'), Input::post('password'))) {
// credentials ok, go right in
if (Config::get('auth.driver', 'Simpleauth') == 'Ormauth') {
$current_user = Model\Auth_User::find_by_username(Auth::get_screen_name());
} else {
$current_user = Model_User::find_by_username(Auth::get_screen_name());
}
Session::set_flash('success', e('Welcome, ' . $current_user->fullname));
Response::redirect('admin');
} else {
$this->template->set_global('login_error', 'Login failed.');
}
}
}
$this->template->title = 'Login';
$this->template->content = View::forge('admin/login', array('val' => $val), f
alse);
}
Also I have maintained frontend login as follows in different controller(welcome.php)
public function action_login_university() {
$val = Validation::forge();
if (Input::method() == 'POST') {
$auth = Auth::instance();
// check the credentials. This assumes that you have the previous table created
//if (Auth::check() and $auth->login(Input::post('email'), Input::post('password'))) {
if ($auth->login(Input::post('email'), Input::post('password'))) {
// credentials ok, go right in
if (Config::get('auth.driver', 'Simpleauth') == 'Ormauth') {
$current_user = Model\Auth_User::find_by_username(Auth::get_screen_name());
} else {
$current_user = Model_User::find_by_username(Auth::get_screen_name());
}
$group_id = $current_user->group_id;
$data['uname'] = Input::post('email');
$data['psword'] = Input::post('password');
$data['gid'] = $group_id;
if($current_user->group_id == '8') {
$data['msg'] = 'success';
$data['url'] = Input::post('admin_url');
} else {
$data['msg'] = 'error';
$data['url'] = Input::post('current_url');
}
} else {
$data['msg'] = 'error';
$data['url'] = Input::post('current_url');
}
echo json_encode($data);
die;
}
}
I have done the login via ajax in frontend.
Any help/suggestions are welcome.Thanks in advance.
The easier way to do this is to create base controllers for each type of user.
For instance call it Controller_Users and Controller_Admin. These can extend another controller such as Contoller_Template and so on.
In your Controllers for Users in your before() method. Make sure they have access. I like using groups for this. If they belong to group Users, then do nothing. If them do not, send them to an error page.
Now in all of the controllers for Users entend Controller_Users.
Something like:
<?php
/**
* The Users Controller.
*
* A controller to do user authentication for the Users section.
*
* #version 1.0.0
* #package Controllers\Users
* #extends Controller_Base
*/
class Controller_Users extends Controller_Base
{
/**
* #var string $template The template to use for this controller
*/
public $template = 'template_users';
public function before() {
parent::before();
$auth = \Auth::instance();
if ($auth->check()) {
$group_id = $auth->get_groups();
if (!$group_id) {
\Session::set('error_msg', 'You do not have access to this application.');
\Response::redirect(\Uri::generate('errors'));
} else {
if ($this->current_user->status === 'DISABLED') {
\Session::set('error_msg', 'Your user account has been disabled.');
\Response::redirect(\Uri::generate('errors'));
}
}
} else {
\Session::set('redirect_url', \Uri::current());
\Response::redirect(\Uri::generate('login/'));
}
}
}
I am new to cakePHP and am just starting to use it for my new job.
I have created an edit_company action in my Orders Controller. I updated the acos table to allow this action. Now the problem is, I can't access any sort of 'edit' action. It says "You are not authorized to access that location" whenever I try to acccess any action that writes or updates database. edit,edit_products,edit_shipping, etc...
The view action works just fine.
This was not happening before.
Heres a bit of the code:
class OrdersController extends AppController{
public $uses = array('Order');
public $hideActions = array('campaign','customer','shipping','review_order','place_order','products','payment','confirmation','cancel','edit_status','edit_order_type','edit_products','edit_tax','add_product','cancel_shipping_label','track_label','view_label','reprint_label','edit_shipping','create_shipping_label');
public $components = array('Payflow','Printer');
public $actionMap = array(
'create' => array('add','create','campaign','customer','shipping','review_order','place_order','payment','products'),
'read'=> array('index', 'view', 'display','confirmation','track_label','search'),
'update' => array('edit','cancel','edit_status','edit_order_type','edit_products','edit_company','edit_tax','add_product','cancel_shipping_label','reprint_label','edit_shipping','create_shipping_label'),
'delete' => array('delete','back_orders_by_state')
);
public function beforeFilter(){
parent::beforeFilter();
$this->Auth->allow('permissions','gen_acos');
}
public function permissions(){
$this->Acl->allow('Admin','Controllers/Orders');
$this->Acl->allow("Sales","Controllers/Orders",'read');
$this->Acl->allow("Sales","Controllers/Orders",'create');
$this->Acl->allow("Sales","Controllers/Orders",'update');
$this->Acl->deny("Shipping","Controllers/Orders",'update');
$this->Session->setFlash("Permissions Updated.");
$this->redirect("/orders/");
}
public function edit_shipping($id){
$sm_conditions = array();
if(!$this->Acl->check(array('User' => array('UserID' => $this->Auth->user("UserID"))), 'Controllers/Orders','delete')){
$sm_conditions['Restricted'] = 1;
}
$shipping_method_ids = $this->Order->ShippingMethod->find("list",array("conditions"=>$sm_conditions,"fields"=>array("ShippingMethodID","ShippingMethodName")));
$order = $this->Order->read(null,$id);
$this->set("order",$order);
$this->set("shipping_method_ids",$shipping_method_ids);
if($this->request->is('put')){
if($this->Order->save($this->data,null,array("ShippingAddress","ShippingMethodID"))){
$this->Session->setFlash("Order Shipping Updated.");
$this->Order->Note->create();
$this->Order->Note->save(
array("Note"=>array('OrderID'=>$id,"UserID"=>$this->Auth->user("UserID"),"NoteBody"=>"Order Shipping Information updated.","CreatedDate"=>date("Y-m-d H:i:s")))
);
$this->redirect("/orders/view/$id");
}
}else{
$this->request->data = $order;
}
}
public function create_shipping_label($id){
$order = $this->Order->read(null,$id);
$this->set("order",$order);
if($this->request->is('put')){
$this->Order->save(array(
"Order"=>array(
"OrderID"=>$id,
"LabelPrinted"=>false,
"OrderStatusID"=>2,
"Notes"=>(!empty($this->data['Order']['Notes']))?$this->data['Order']['Notes']:null
)
));
$this->Session->setFlash("A new shipping label will be created momentarily.");
$this->Order->Note->create();
$this->Order->Note->save(
array("Note"=>array('OrderID'=>$id,"UserID"=>$this->Auth->user("UserID"),"NoteBody"=>"New shipping label will be created. ".((!empty($this->data['Order']['Notes']))?$this->data['Order']['Notes']:null),"CreatedDate"=>date("Y-m-d H:i:s")))
);
$this->redirect("view/".$id);
}else{
$this->request->data = $order;
}
}
public function cancel($id){
$order = $this->Order->read(null,$id);
if($this->request->is('post')){
//Check if note given
$this->Order->Note->data = $this->data;
if($this->Order->Note->validates()){
//Delete from Call table
$this->loadModel("Call");
$this->Call->deleteAll(array('Call.OrderID'=>$id));
//Add a note
$user_id = $this->Auth->user("UserID");
$this->Order->Note->create();
$this->Order->Note->save(
array("Note"=>array('OrderID'=>$id,"UserID"=>$user_id,"NoteBody"=>"Order Canceled. ","CreatedDate"=>date("Y-m-d H:i:s")))
);
$this->Order->Note->create();
$this->Order->Note->save(
array("Note"=>array('OrderID'=>$id,"UserID"=>$user_id,"NoteBody"=>"Reason For Cancellation: ".$this->data['Note']['NoteBody'],"CreatedDate"=>date("Y-m-d H:i:s")))
);
//Create a refund request if payment type is in TxType (1,2,3,7,11,9)
$txTypes = array(1,2,3,7,11,9);
$paid = 0;
foreach($txTypes as $txType){
$payments = Set::extract("/Payment[TransactionTypeID=$txType]/PaymentAmount",$order);
$paid += array_sum($payments);
}
if($paid>0){
$this->Order->refund($id,$paid);
}
//Change Status to Cancel (4) & LabelPrinted = 0
$this->Order->save(array("Order"=>array("OrderID"=>$id,"LabelPrinted"=>0,"OrderStatusID"=>4)));
//Update the total price
$this->Order->updateOrderTotal($id);
$this->Session->setFlash("Order was successfully canceled.");
$this->redirect("/orders/view/".$id);
}
}
$this->set("order",$order);
}
public function edit_products($id){
$order = $this->Order->read(null,$id);
$this->set("order",$order);
if($this->request->is("post")){
$error = false;
while($error==false && ($oe=array_shift($this->request->data['OrderEntry']))){
if(!$this->Order->OrderEntry->save(array("OrderEntry"=>$oe))){
$error = true;
}
}
if($error==false){
$this->Session->setFlash("Products Updated.");
$this->Order->updateOrderTotal($id);
$this->redirect("/orders/view/$id");
}
}
}
public function edit_company () {
}
public function edit ($id=null) {
$order = $this->Order->read(null,$id);
$this->set("order",$order);
if($this->request->is("post")){
$error = false;
while($error==false && ($oe=array_shift($this->request->data['OrderEntry']))){
if(!$this->Order->OrderEntry->save(array("OrderEntry"=>$oe))){
$error = true;
}
}
if($error==false){
$this->Session->setFlash("Products Updated.");
$this->Order->updateOrderTotal($id);
$this->redirect("/orders/view/$id");
}
}
}
Could anyone help me with this problem?
Thanks!
You are only giving non authenticaded users permission to access two actions:
public function beforeFilter(){
parent::beforeFilter();
$this->Auth->allow('permissions','gen_acos');
}
Add the new actions or log the user in before accesing the actions:
Giving permission to not authenticated users to your new actions:
public function beforeFilter(){
parent::beforeFilter();
$this->Auth->allow('permissions','gen_acos','edit_products','edit','cancel','create_shipping_label','edit_shipping');
}
If you don't want to grant access to non authenticated users to these actions login before trying to access them.
You can check more about Auth here
Also check this example that is part of the Blog Tutorial
I need to validate duplicate email in magento on edit and add action. Basically on edit if i changed email id if that is available in database then i need to got message duplicate email.... if I add then i also want to validate duplicate email in magento.
my save function in admin
public function saveAction()
{
if ($this->getRequest()->getPost())
{
try {
$postData = $this->getRequest()->getPost();
$currentTimestamp = time();
$postData['updated_at']= $currentTimestamp;
$postData['seller_other_sale_sites'] = implode(',',$postData['seller_other_sale_sites']);
$sellerModel = Mage::getModel('seller/seller');
if( $this->getRequest()->getParam('id') <= 0 )
$sellerModel->setCreatedTime(
Mage::getSingleton('core/date')
->gmtDate()
);
$sellerModel
->addData($postData)
->setUpdateTime(
Mage::getSingleton('core/date')
->gmtDate())
->setId($this->getRequest()->getParam('id'))
->save();
Mage::getSingleton('adminhtml/session')
->addSuccess('successfully saved');
Mage::getSingleton('adminhtml/session')
->settestData(false);
$this->_redirect('*/*/');
return;
} catch (Exception $e){
Mage::getSingleton('adminhtml/session')
->addError($e->getMessage());
Mage::getSingleton('adminhtml/session')
->settestData($this->getRequest()
->getPost()
);
$this->_redirect('*/*/edit',
array('id' => $this->getRequest()
->getParam('id')));
return;
}
}
$this->_redirect('*/*/');
}
I need to validate that on save function
Create a function in helper class that takes $email as parameter
public function customerExists($email, $websiteId = null)
{
$customer = Mage::getModel('customer/customer');
$customer->setWebsiteId($websiteId);
$customer->loadByEmail($email);
if ($customer->getId()) {
return $customer;
}
return false;
}
Before you perform save operation, use the helper function this way.
Mage::helper('modulename')->customerExists($email, $websiteId);
If a customer is already there it will return the customer object and if it doesn't, it will return false. So you can write remaining code/throw exception/ set error message accordingly.
from Mage_Customer_Model_Resource_Customer this code checks for unique email _beforeSave before save (unless updating an existing customer in which case it checks for duplicates on just that customer).
This is within the Mage system, but doesn't use any models.
$adapter = $this->_getWriteAdapter();
$bind = array('email' => $customer->getEmail());
$select = $adapter->select()
->from($this->getEntityTable(), array($this->getEntityIdField()))
->where('email = :email');
if ($customer->getSharingConfig()->isWebsiteScope()) {
$bind['website_id'] = (int)$customer->getWebsiteId();
$select->where('website_id = :website_id');
}
if ($customer->getId()) {
$bind['entity_id'] = (int)$customer->getId();
$select->where('entity_id != :entity_id');
}
$result = $adapter->fetchOne($select, $bind);
if ($result) {
throw Mage::exception(
'Mage_Customer', Mage::helper('customer')->__('This customer email already exists'),
Mage_Customer_Model_Customer::EXCEPTION_EMAIL_EXISTS
);
}
I have the following app flow:
Add role action:
public function addroleAction($role) {
$securityContext = $this->get('security.context');
$em = $this->getDoctrine()->getManager();
$user = $this->get('security.context')->getToken()->getUser();
$userId = $user->getId();
$userObj = $em->getRepository('ProjectEntityBundle:User')->find($userId);
switch ($role) {
case 6://student
$userObj->addRole('ROLE_STUDENT');
$em->flush();
$securityContext->getToken()->setUser($userObj);
break;
}
return $this->redirect($this->generateUrl('check_role'));
}
Check role action:
public function checkroleAction() {
$securityContext = $this->get('security.context');
if ($securityContext->isGranted('ROLE_STUDENT')) {
return $this->redirect($this->generateUrl('student_profile'));
} else {
return $this->render('ProjectEduBundle:User:selectrole.html.twig');
}
}
The first action adds role to the database and redirect is made to checkroleAction.
The if condition is not met(returns false).
I guess this happens because security context is not refreshed after the database operation of adding role is done.
How do I solve this issue?
You can set the user on the token again...
$this->get('security.context')->getToken()->setUser($userObject);
Add that at the end of your addroleAction()