I’m new to Laravel and OctoberCMS, there is a lot of documentation on both but because I don’t have much of an understanding of either I would really appreciate some help. It's also quite confusing trying to understand both at the same time, especially as there is way more documentation about laravel than October.
Currently, I wish to extend a plugin (Link to their extending plugin documentation). I need to use the session (username or email) from the rainlab user plugin (Link to their Git) and insert it into another plugin.
I'm upgrading the other plugin that currently relies on users entering their name via a form and replacing this with their username or email address once logged in.
My Layout contains the user plugin session:
{% component 'session' %}
The user plugin session works fine on the rest of my pages but I have gotten a 'value not found' error with my previous attempts using it with the plugin.
I know I need to either link the plugins or create a new one, and retrieve the username (or email) from the users database and insert it into another table, just can’t quite work out how to do this. To make matters worse I don’t have experience with MVC either!
Added this function (from an example I found) to the second plugin's Plugin.php page:
Plugin.php
public function boot()
{
Event::listen('rainlab.user.register', function($user) {
// Code to register $user->email to mailing list
});
}
But I got 'Undefined' error.
I've also tried adding a Routes.php file as I thought there may be an issue with middleware.
Routes.php
Route::get('/test', function () {
dd(
Auth::getUser(),
BackendAuth::getUser()
);
})->middleware('web');
Received this error:
"Call to undefined method RainLab\User\Facades\Auth::getUser()"
I’ve been banging my head against the wall for a week now and any tips or explanations would be greatly received. If you require any other bits of code please let me know. I haven't added any more bits of code as I know those pieces didn't work (being going around in circles and it would be a bit erratic and not much use) and I don't want to spam code on this page. I've shown the bits above to try and explain some previous thought processes. Also, it's the start of my project and not much code has changed from the generic code available to you from the OctoberCMS and User Plugin Gits.
I believe an explanation and some help here would benefit a lot of people, I can see I’m not the only one to have issues, partly down to the changes in the latest version of laravel.
Any thoughts and explanations would be much appreciated.
UPDATE:
To make it clearer where I need my session to appear I've included the code below. $name needs to be replaced by a new variable like email or username (from session).
components\Chat.php
$name = 'anonymous';
if ($n = Input::get('name')) {
$name = strip_tags($n);
}
$message = new Message(['text'=>$text, 'user_id'=>$user_id, 'name'=>$name]);
$message->save();
return $this->getMessagesOutput($message->id, [$message]);
}
It will be really Easy if you are adding session in layout {% component 'session' %}
now on entire page you can use {{ user.email }} directly in twig to get user email
if you need to use using PHP you can use Auth facade
this code must me in component which are included in page which is using that layout or in its life-cycle methods
// Returns the signed in user
$user = Auth::getUser();
echo $user->email;
you can not directly use route because route is separate from page execution so Auth will not work there.
"I need to use the session (username or email) from the rainlab user plugin (Link to their Git) and insert it into another plugin."
just create new component which have this code and include it in page.
can you share details what you need to do and how you are doing to get details and on which time you need to use that details so i can answer it precisely.
UPDATE
// by default name
$name = 'anonymous';
$user_id = 0; // if user is not logged in
// if user is logged in then use session
if($sessionUser = \Auth::getUser()) {
// if user didn't set name then you can assign some default value here or email
$name = $sessionUser->name != '' ? $sessionUser->name : $sessionUser->email;
$user_id = $sessionUser->id;
}
// not needed but if user want to edit its name then we use that one
if ($n = Input::get('name')) {
$name = strip_tags($n);
}
$message = new Message(['text'=>$text, 'user_id'=>$user_id, 'name'=>$name]);
$message->save();
return $this->getMessagesOutput($message->id, [$message]);
Related
I am currently doing a website wherein the login URLs are varying and displays the data according to the assigned projects to them.
For example, user A can only access www.example.com/projects/proj1. This is the homepage for user A and if he logs in he uses www.example.com/projects/proj1/login
While user B can only access www.example.com/projects/proj2. This is the homepage for user B and if he logs in he uses www.example.com/projects/proj2/login
Please note that proj1 and proj2 are varying depending on the database. So I have to check first that these projects are already registered in the database.
I am thinking of having a route like this.
For web.php
Route::get('/projects/{project_name}', 'PageHandler\CustomPageController#projects');
Route::get('/projects/{project_name}/login', 'PageHandler\CustomPageController#login');
Route::put('/projects/{project_name}/auth/{user}', 'PageHandler\TestUserPageController#auth');
Then my customepagecontroller.php looks like this
class CustomPageController extends Controller
{
public function projects(string $projectName)
{
if (auth()->user() == null)
return redirect('/projects'. '/' . $projectName . '/login');
}
public function login(string $projectName)
{
return view('login')->with('projectName', $projectName);
}
public function auth(Request $request, string $projectName)
{
$username = $request->username;
//How to set $username as logged in?
// rest of the code to show the home page after authentication
}
}
login.blade.php basically just looks like a form submitting username and password and calling auth of CustomPageController with a string parameter for the URL
So my question is how can I set $username as logged in already using the Auth of Laravel? Or should I create my custom Authentication Controllers?
Now, this is the only approach I have in mind for me to enable the logging in of users to varying URLs. Please let me know if you have better approach.
Thank you!
If you only want to limit the project the users can access, I do not see a need to use 2 different login URLs (please correct me if there is a reason why you want different URLs for that), instead, you simply find which project the user belongs to from the database.
For authentication, Laravel allows you to implement authentication in a very easy way, you can refer to the documentation. Using Laravel's authentication would be easier and safer than writing your own one, and even if the default functionalities it provides may not be exactly the same as those you would want to achieve, you can still add your own things, which is still a lot easier than implementing it from scratch.
As for setting a user as logged in with Laravel's authentication services, you can use Auth::login($user);. Here, $user must be an implementation of the Illuminate\Contracts\Auth\Authenticatable contract. You can refer to this part of the documentation for more details.
I'm using the Ion_auth for CodeIgniter in my project auth library. I'm trying to make a similar function as is_admin() for other user types (there are three user types other than the admin) to check whether the logging in user is of one of those three types so I can redirect them to their respective pages. Ion_auth is using an event called is_admin but I can't understand where this is happening in the Ion_auth_model.php and how it checks whether the logged in user is admin. So how can I make other functions/events similar to this one?
I know I can just do something like query the database and check the user group but I want to do the way Ion_auth has done. That way I can also satisfy myself by actually understanding the stock code.
I am just looking at source code on github.
As lots of auth libraries store, information you are looking for in session and library itself checks session variables.
your function you are looking for is on line 447 in file application/libraries/Ion_auth.php
public function is_admin($id=false)
{
$this->ion_auth_model->trigger_events('is_admin');
$admin_group = $this->config->item('admin_group', 'ion_auth');
return $this->in_group($admin_group, $id);
}
In order to create your own I suggest you to reverse engeneer model (ion_auth_model.php)
But! Ion already has a workaround for you, this method is what you are looking for
in_group()
$group = 'gangstas';
if (!$this->ion_auth->in_group($group))
{
$this->session->set_flashdata('message', 'You must be a gangsta to view this page');
redirect('welcome/index');
}
source
The function is_admin() refers to the admin group defined in the file /application/config/ion_auth.php: $config['admin_group'] = 'admin'; // Default administrators group, use name.
The admin_group name itself is stored in the ion_auth database field groups.name.
I am currently building a web app which has two models, Donor and Donation Models respectively. It has multiple user roles. When the staff user first registers a donor, I want him to be redirected to another form which allows him to fill in the Donation details(the donor is registered once the first donation is successful).
Firs of all, should I create a donation controller, from which I would redirect the user using:
return $this->redirect(array('controller'=>'donations','action'=>'add'));
For the above to work, it requires me to save the newly registered donor's id in a session like so :
$this->Session->write('id', $this->Donor->id);
So the user is redirected to 'donations/add' in the url, and this works fine.. However I think this has some flaws. I was wandering whether I should create another action inside the Donor controller called 'add_donation', which will have its respective 'View'. The idea is to be able to form a url of the sort : 'donors/add_donation/4' (4 being the donor_id ! )
This URL follows this construct: 'controller/action/id'
If anyone could shed some light on best practices, or describe any caveats to my solution(the former, using session etc.) , please do help a brother out! Ill be deeply indebted to you! Thanks in advance!
After you saved the data you can do this in the DonorsController:
$this->redirect(array(
'controller' => 'donations',
'action' => 'add',
$this->Donor->getLastInsertId()
));
There is no need to return a redirect, it's useless because you get redirected. Notice that we pass the last inserted record id as get param in the redirect. The redirect method of the controller calls by default _stop() which calls exit().
CakePHP3: There is a discussion about changing that default behavior in 3.0. Looks like in CakePHP 3.0 the redirect() won't exit() by default any more.
DonationsController:
public function add($donorId = null) {
// Get the donor to display it if you like to
if ($this->request->is('post')) {
$this->request->data['Donation']['donor_id'] = $donorId;
// Save code here
}
}
I would not use the session here, specially not by saving it to a totally meaningless and generic value named "id". If at all I would use always meaningful names and namespaces, for example Donor.lastInsertId as session key.
It's not always clear where to put things if they're related but the rule of thumb goes that things should go into the domain they belong to, which is pretty clear in this case IMHO.
Edit:
Leaving this edit here just if someone else needs it - it does not comply with the usage scenario of the asker.
If you have the user logged in at this stage, modify the add function to check if the userId passed is the same as the one logged in:
DonationsController:
public function add($donorId = null) {
// Get the donor to display it if you like to
if ($this->request->is('post')) {
if ($this->Auth->user('id') != $donorId) {
throw new InvalidArgumentException();
}
$this->request->data['Donation']['donor_id'] = $donorId;
// Save code here
}
}
You can use also the same controller using more models with uses.
Or you can also to ask to another controller with Ajax and morover to get response with Json.
I have a CakePHP 1.3 application that has a login system, which works well. It uses a DB with a users table, which existed before creating this app.
I'm using Auth in my AppController. The login function looks like
function login() {}
and it's located in the users_controller.
Everything works fine, as I said, but I have problems trying to add a new functionality. I would like to, during the login process, detect if a user has introduced a specific combination of login/password (let's say admin/adminpwd). If so, the login should be succesful AND he would be taken to an admin area (/admin/index). Otherwise, the login process should work as usual.
Once in this admin area (controlled by an admin_controller), this user should be able to perform some actions exclusive to him, no to the rest of users (even if they type on the browser /admin/action).
I've read about ACL, and probably it would help with this, but it seems too complicated for what I really need. Is there any simple way to do this? I guess I should modify the login function, but I don't really know how exactly, and if there's anything else I should change... any ideas?
Yeah, ACL is pretty complicated (and powerful). But in your case, I'd suggest create a 'group' field in users table to distinguish the role of the user. So you can have more admins later if you want. It's more flexible than hard-code a certain login credential in your users_controller.
There are several things you need to do to:
Tell the Auth component to transfer control to you after the user logins, so you can determine their group and redirect them accordingly.
Check if a user in a group is accessing some other group's action: If you don't, a regular user just need to be logged in, and they can type in admin url (if they know about it) and they can do everything an admin can. This check will probably be done in before_something_() in app_controller or tap into Auth somewhere.
I don't remember all the details, but you can get everything you need in the Cake Cookbook. Good luck!
Let's just see some code...
class UsersController extends AppController {
// we're moving the variable to AppController!
public function login() {
$usrInfo = $this->Auth->user();
if (isset($usrInfo) {
// this index name might not be right. I'm going off memory please check this!
if (in_array($usrInfo['username'], $this->adminUsers)) {
// do your code here for admin users.
// could be a redirect or just changing the layout used
} else {
// is a user that is logged in but not in our admin list
}
}
}
To test if the user is logged in you would need to do something like the following:
class AppController extends Controller {
protected $adminUsers = array('joe_blow_uname', 'jane_blow_uname');
public function beforeFilter() {
$routing = Configure::read('Routing.admin');
$usrInfo = $this->Auth->user();
if (isset($this->params[$routing]) && isset($usrInfo)) {
if (!in_array($usrInfo['username'], $this->adminUsers)) {
// do code here for non-admin users using /admin prefix
}
}
}
}
Let me know if this doesn't help.
Or worse breaks something...
Edit:
This is really not the best way to do this obviously. ACL or setting up some kind of group in your database would probably be better. BUT, it is a relatively quick-n-dirty way that, for a small site, should work fine.
i'm starting a project adn i'm using symfony, my first time with symfony, really great actually, i already install the sfDoctrineGuardPlugin and everything is ok untill now, why?, because frontend users can login in the backend and vice versa, i dont't want that, so, i start to google, i found Symfony sfDoctrineGuardPlugin custom login query here in SO, but i don't know where i should place the function so, i haven't tested it.
As i don't want frontend users can login in the backend, i think i can use credentials, can i?? but, symfony check for users credentials after they are logged, and i don't want tha neither, so, how can i achieve this?, maybe if i could have namespaces in the session, i can check if an admin in the backend namespace and also for frontend users, so they never get fixed, i think.
I don't know really know if sfDoctrineGuardPlugin have some configuration that can manage this situation, exist such a config??
Also, in my backend, i will like to have a page to manage the frontend users, and other for backend users, because frontend users will have a profile and addresses, think this is much easier, but i don't know where to start.
need some help over here
thanks
After a few days coding, i was able to do it exactly as i wanted, i'm going to share my solution:
I started with an example i found here in SO, you can read the post here:
Symfony sfDoctrineGuardPlugin custom login query
it gave me an idea and i executed it, so, i create \lib\Util.class.php, with to functions, one for query backend users and another for frontend users
static public function retrieveCustomer($username, $isActive = true)
{
$query = Doctrine_Core::getTable('sfGuardUser')->createQuery('u')
->leftJoin('u.Groups g')
->leftJoin('g.Permissions p')
->where('u.username = ?', $username)
->addWhere('u.is_active = ?', $isActive)
->addWhere('g.name = ?', 'customers');
return $query->fetchOne();
}
static public function retrieveAdmin($username, $isActive = true)
{
$query = Doctrine_Core::getTable('sfGuardUser')->createQuery('u')
->leftJoin('u.Groups g')
->leftJoin('g.Permissions p')
->where('u.username = ?', $username)
->addWhere('u.is_active = ?', $isActive)
->whereIn('g.name', array('administrators','operators'));
return $query->fetchOne();
}
Now, in the app.yml of each app, i override the default query of the plugin
#Example for apps/backend/config/app.yml
all:
sf_guard_plugin:
retrieve_by_username_callable: Util::retrieveAdmin
untill now all was good, but i started to face another problem, so i open a new thread:
Overwriting isAuthenticated() in symfony and there i got the final step for my solution, that was setting differents session name for each app, so, in the factories.yml of each app:
#apps\backend\config\factories.yml
storage:
class: sfSessionStorage
param:
session_name: backend
and now all is set, frontend users can not log in in backend app and vice versa.
feel free to comment
The most common approach is through credentials, my backend applications security.yml looks like:
all:
is_secure: on
credentials: [login_backend]