controllers in web frameworks ? [ruby, Grails, etc..] How do they work? - ruby

So the thing that I want to do is direct the login page to the admin page(e.g: "admin.gsp") if username "admin" is entered and password "pass" is entered. or direct it to the user page if username "user" and password "pass" is entered
However I do not understand how exactly controller works.
So when you redirect the page to a specific controller and specific method, how do you make it redirect it to a specific page. What code do you implement inside that method ?
to explain my question better. Below we have the code for controller User, with an if else statement depending on what the user typed in the login boxes.
package file_download
class UserController {
def index() {
//code that directs the page to username page, let's call it or user.gsp
}
def login = {
if(params.username == "admin" && params.password == "pass")
{
session.user = "admin"
redirect(controller:"admin",action:"admin")
}
else if(params.username == "user" && params.password == "pass")
{
session.user="user"
redirect(controller:"user",action:"index")
}
else
{
flash.message = "login failed"
}
redirect(controller:"user",action:"login")
}
def logout = {
session.user = null
redirect(action: 'index')
}
}
now here, we have the admin controller, with the action index, that should have a code implemented to direct the page to... admin.gsp, or admin.html, watever the admin page is called
package file_download
class AdminController {
def index() {
//code that takes us to admin page let's call it admin.gsp
}
}
How do we exactly do that ?
I need a little bit of an explanation on controllers.
Thank you. Please ask if you need more clarification on the question as I will edit it.

I think you are having wrong assumptions. In Grails (I don't know rails) when you go to the login page, let's say
/app/user/login
then, at FIRST the controller method is being called (def login()), so your logic shouldn't go there, it should actually do nothing and by convention it will end up rendering login.gsp. Next, your user fills in his username/pass and submits form, there goes the second request let's say to
/app/user/auhtenticate
and here's where your logic should go and the redirects will work as you expect
So basically - controller method is called first and (unless you specify gsp to be rendered or do a redirect) after the method is executed, the gsp view is being rendered

I know nothing of rails, however in grails what you are looking for is render.
Render:( http://grails.github.io/grails-doc/latest/ref/Controllers/render.html )
so the code would look something like this
def index() {
render view: "/directory/inside/views/admin" model: [thing1: "Thing One"]
}

Related

How to give access to views to specific user in laravel?

I have a Category Controller which checks if user is logged in
class CategoryController extends Controller
{
public function __construct() {
$this->middleware('auth');
}
...
My category routes are :
//Category Controller
Route::get('admin/category/{category}/edit', ['uses'=>'categoryController#edit','as'=>'admin.category.edit']);
Route::put('admin/category/{category}', ['uses'=>'categoryController#update','as'=>'admin.category.update']);
Route::get('admin/category/{category}', ['uses'=>'categoryController#show','as'=>'admin.category.show']);
Route::delete('admin/category/{category}', ['uses'=>'categoryController#destroy','as'=>'admin.category.destroy']);
Route::get('admin/category/create', ['uses'=>'categoryController#create','as'=>'admin.category.create']);
Route::get('admin/category', ['uses'=>'categoryController#index','as'=>'admin.category.index']);
Route::post('admin/category', ['uses'=>'categoryController#store','as'=>'admin.category.store']);
Is there a way to give access to these views to only specific user?
For example if user email is admin123#gmail.com then he is allowed to go to those view.
I know I can check like this
if(Auth::user()->email == 'admin123#gmail.com')
{
dd('admin Logged in');
}
But this is possible if i go to individual view and put all my content in the if statement.
Is there way to handle this in controller.
Thanks.
You can use the middlewares for these kinds of work.
From the docs
Middleware provide a convenient mechanism for filtering HTTP requests entering your application. For example, Laravel includes a middleware that verifies the user of your application is authenticated. If the user is not authenticated, the middleware will redirect the user to the login screen. However, if the user is authenticated, the middleware will allow the request to proceed further into the application.
You should restrict users by route groups. Use middleware for that.
However, if you have complicated logic, sometimes you may want to check if user is admin in controller, model and other classes. In this case you can create global helper isAdmin() and use it for simple checks. Examples:
if (isAdmin()) {
// Do something
}
{{ isAdmin() ? 'active' : '' }}
A better way to define user role is like 0 for admin, 1 for user, 2 for member.
Then you can check the user role like:
if(Auth::check())
{
if(Auth::User()->user_type == 0)
{
return view('admin_dashboard');
}
else if(Auth::User()->user_type == 1)
{
return view('user_dashboard');
}
else if(Auth::User()->user_type == 2)
{
return view('member_dashboard');
}
}

How to redirect to the method of a controller after user doing authentication on codeigniter?

I am using the Default Controller to make the user authentication. What I am trying to do is whatever is the page the user request news/add or news/index or themes/all or maps/view, if he is not logged in, he or she will be directed to the log in page and then redirected to the page he wanted to go, not always the same page.
You can your the
CodeIgniter User Agent Library and Session Library to store and use the referring url. The user agent library is basicly accessing the $_SERVER['HTTP_REFERER'] value.
NOTE: from the php.net website:
Not all user agents will set this, and some provide the ability to modify HTTP_REFERER as a feature. In short, it cannot really be trusted.
so this is not a foolproof method.
if ($this->agent->is_referral()) {
$this->session->set_userdata('prev_url', $this->agent->referrer());
}
// later, when login is successful
$prev_url = $this->session->userdata('prev_url');
if( $prev_url ) {
redirect($prev_url);
}
one way is to do it in the constructor of your controller. that way they are redirected before going to the news/add etc.
so for example you create a model called "sentry" and a "getUser()" method to check the browser cookie to see if the user is authorized. if they are not authorized have it return false. if they are authorized have it return $user so then you have it available for your other methods.
function __construct() {
parent::__construct();
$this->load->model( 'sentry' );
if ( ! $this->user = $this->sentry->_getUser() )
{ redirect( '/login/', 'refresh' ); }
}
so then for example you could have $this->user->name etc etc available to any method in the controller. And $this->user will also automatically be available in all the view files of this controller.
I do this by extending my controller and I check in constructor if person is logged in or not, if person is logged in I save to the session current URL, and redirect person to the login page (if same constructor is applied (controller one) I make exception to not save current URL to the session) after logging in I call redirect function to the session variable.
How to extend your controller is done here http://philsturgeon.co.uk/blog/2010/02/CodeIgniter-Base-Classes-Keeping-it-DRY
note that when your controller is extended you use $this->data['variable_sent_to_view'] and you can omit second parameter of $this->load->view()
here is some example code assuming you know how your login controller works
<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
class MY_Controller extends CI_Controller {
function __construct() {
parent::__construct();
$this->output->enable_profiler(FALSE);
if ($refer = $this->session->flashdata('refer')) {
$this->data['refer_page'] = $refer; // $this->data['refer_page'] is variable that you are interested in
unset($refer);
} else {
$this->data['refer_page'] = base_url(); //default refer_page
}
//check if user is NOT logged in
if (!$logged_in) {
$this->_setRefer(); //this is private function
}
// else dont care about it
}
private function _setRefer() {
$invalid_method = array('search', 'login'); // if method is 'search' or 'login' url will not save in session (it will stay same as was before)
$valid_refer = TRUE;
if (in_array($this->router->method, $invalid_method)) {
$valid_refer = FALSE;
}
if (!(count($_POST) > 0) && $valid_refer === TRUE && !$this->input->is_ajax_request()) {
$this->session->set_flashdata('refer', current_url());
} else {
$this->session->set_flashdata('refer', $this->data['refer_page']);
}
}
}
now in after succesful login redirect to $this->data['refer_page'], but note that login controller must by extended by MY_Controller.
this script also takes care about what happens if user made mistake and inserted wrong password (page will reload but "old" url stays)

Keep Tank Auth on every page in CodeIgniter

My question is a little hard to explain, but I'll try..
Basically, in the tank_auth example script there is this code to redirect the user if they are not already logged on;
if (!$this->tank_auth->is_logged_in()) {
redirect('/auth/login/');
} else {
$data['user_id'] = $this->tank_auth->get_user_id();
$data['username'] = $this->tank_auth->get_username();
$this->load->view('welcome', $data);
}
Which is great if you have a login page and the user starts at the beginning each time. (And I'm comfortable doing it that way)
But I want the user to be able to jump in to website at (almost) any controller and have a login bar come up across the top. When logging in, it should not redirect them to another page. They should end up on the same page they tried to visit.
For example, my user might load straight away example.com/food/burgers. I'd like a blank page to come up, but just with a login bar across the top. Then when they log in, they end up back on the 'burgers' page but this time there is also a list of burgers and the bar accross the top that tells them they are logged in, with the option to log-off.
So how do I do this? Do I need to call the auth/login method from every controller? Do I do it as an "include"? No idea.
Firstly you will want to create a base controller that all your controllers will extend from. You would check for authentication in this base controller. If they aren't logged in, then save the entry point uri in a cookie and redirect to the login page.
// application/core/My_Controller.php
class MY_Controller extends CI_Controller
{
public function __construct()
{
parent::__construct();
$this->load->library('session');
$this->load->model('tank_auth');
if (!$this->tank_auth->is_logged_in()) {
// save the visitors entry point and redirect to login
$this->session->set_userdata('redirect', $this->uri->uri_string());
redirect('auth/login');
}
}
}
Your main controllers will extend MY_Controller and don't need to worry about authentication.
class Welcome extends MY_Controller
{
public function index()
{
$data['user_id'] = $this->tank_auth->get_user_id();
$data['username'] = $this->tank_auth->get_username();
$this->load->view('welcome', $data);
}
}
Your authentication controller wouldn't extend MY_Controller otherwise it will get stuck in a redirect loop.
class Auth extends CI_Controller
{
public function login()
{
$this->load->library('session');
if (auth_success) {
// redirect the user back to the entry point or the welcome controller
if ($uri = $this->session->userdata('redirect')) {
redirect($uri);
} else {
redirect('welcome');
}
}
// handle authentication failure
}
}
Instead of using sessions to store the redirect uri, you could also pass it along as a GET parameter.

Spring Security redirect back to refer URL after login and logout

I am using Spring Security for authentication. The login and logout buttons are placed on the page layout, which is used by all pages. I have a BookController which needs a parameter for the create action (e.g., an image id):
class BookController {
#Secured("ROLE_USER")
def create() {
def someImage = params.imageId
...
}
#Secured("ROLE_USER")
def show() {
...
}
...
}
My LoginController is:
class LoginController {
...
def auth() {
...
redirect uri: SpringSecurityUtils.securityConfig.successHandler.defaultTargetUrl
}
...
}
This will redirect the user to the base URL after login was successful. I want to have the user always be redirected to the refer URL, which is the URL before he was successfully logged in.
For example:
The user is not logged in. He is at home/index and want to access book/create, which is only available for logged-in users. In this case, Spring Security will redirect the user to login/auth and (after he is successfully logged in) to / (which is the base URL).
I want to have the redirect go to the URL the user has been trying to access, which in this case is book/create. This should also be the case for any other action. If a not-logged-in user on home/index tries to access book/show/32333, he will be redirected to login/auth, and, after he successfully logs in, back to book/show/32333.
How can I implement that?
I had the following solution:
HttpSession session = request.getSession(false)
def referUrl
def referParamsMap
def referParams = "?"
if(session != null) {
SavedRequest savedRequest = new HttpSessionRequestCache().getRequest(request, response)
if(savedRequest != null) {
referUrl = savedRequest.getRedirectUrl()
referParamsMap = savedRequest.getParameterMap()
referParamsMap.each { referParams += "${it.key}=${it.value[0]}&" }
}
}
println "referUrl "+referUrl+referParams
if(referUrl != null)
redirect url: referUrl+referParams
else
redirect uri: SpringSecurityUtils.securityConfig.successHandler.defaultTargetUrl
The only problem is, that if a not logged in user is on a page and loggs in (by clicking on a login link at the layout GSP) he will alway be redirected to the defaultTargetUrl not to the page he has been before.
Is there a way to get the correct url in this case?

CakePHP 2 AJAX redirections

I'm using AJAX in my web-app stuffs like search but if the user has been logged out, the ajax function return nothing because the redirection (from the action 'search' to the action 'login') has not been handled correctly.
Is it possible to redeclare the method 'redirect' in AppController to render the right action when a redirect hapend in an AJAX call ?
Thank you,
Sébastien
I think your best bet would be to setup you ajax to call to respond correctly to an invalid response. As it seems to be an important part of your app I would pass a 'loggedin' variable with every ajax request, so the client can tell as soon as the user has been logged out.
Update
In the case you want to keep a user logged in, you simply have to put the logged in/cookie check in something like your AppController::beforeFilter() that gets run with every request. for example:
public function beforeFilter() {
if($this->Auth->user() {
// USer is logged in, it's all gravy
} else {
// User is not logged in, try to log them in
$userData = $this->Cookie->read('User');
if(!empty($userData)) {
// Function that grabs info from cookie and logs in user
}
}
}
This way there will be no redirect as the user will be logged in as long as they have a cookie.
Another approach would be to allow everyone access to the Ajax function:
public function beforeFilter() {
$this->Auth->allow(array('my_ajax_method'));
}
And then check the user is authenticated in the method itself:
public function my_ajax_method() {
if (!$this->Auth->user()) {
//user not authenticated
$result = "requires auth";
}
else {
// use is authenticated
// do stuff
$result = 'result of stuff';
}
$this->set(compact('result'));
}
You will need to check the result of the ajax call in your javascript and act accordingly.

Resources