The proper way to skip the dashboard for non-master users in a User Frosting site - userfrosting

I want any user who isn't the master user to be redirected to a separate page at /profiles.
I've achieved this by editing the admin sprinkle, adding this simple statement to the pageDashboard function in AdminController.php:
if(!$currentUser->isMaster()){
header("Location: /profiles");
exit;
}
I want to move this to my own sprinkle, but I'm not clear on how best to do this. Would I create my own controller that extends AdminController, and just replace the function? Or is there a neater way of doing it? What I have now works but obviously isn't future-proof as this file will be overwritten in future updates.

You can change where the users are redirected after login using the determineRedirectOnLogin service. See : https://learn.userfrosting.com/services/default-services#determineredirectonlogin. In your sprinkle ServicesProvider, simply overwrite the default service with something similar:
$container['determineRedirectOnLogin'] = function ($c) {
return function ($response) use ($c)
{
if (!$c->currentUser->isMaster()) {
return $response->withHeader('UF-Redirect', '/dashboard');
} else {
return $response->withHeader('UF-Redirect', '/profiles');
}
};
};
You can then use the permission system to remove access to the dashboard for the non root users if you wish so.
Side note, like you pointed out, you shouldn't edit any core sprinkles and move that code to your own sprinkle.

Related

How to render a cms page with default theme AND variables from controllers in OctoberCMS?

I'm wondering how I can render a view, or display a page with my default theme in OctoberCMS, via a route that executes a function in a controller.
If I have the following route:
Route::get('bransje', [
'uses' => 'Ekstremedia\Cityportal\CPController#bransje'
]);
And in my controller CPController ive tried several things, like I used to with Laravel:
public function bransje() {
$stuff = Stuff::with('info');
return View::make('cms::bransje')->with('stuff',$stuff);
}
But I cannot seem to get it to work, and I've tried to search the web, but it's hard to find answers. I have found a workaround, and that is to make a plugin component, then I can include that component and do:
public function onRun()
{
$this->eventen = $this->page['stuff'] = $this->stuff();
}
protected function stuff()
{
return ...
}
Is there any way so I can make pages without using the Cms, and that are wrapped in my default theme? I've tried
return View::make('my-theme-name::page');
and a lot of variants but no luck.
I know I can also do a:
==
public function onRun()
{
}
in the start of my page in the cms, but I'm not sure how to call a function from my plugin controller via there.
You can bypass frontend routing by using routes.php file in your plugin.
Full example in this video turotial.
If this answer can still be useful (Worked for October v434).
I have almost the same scenerio.
What I want to achieve is a type of routing like facebook page and profile.
facebook.com/myprofile is the same url structure as facebook.com/mypage
First I create a page in the CMS for each scenario (say catchpage.htm)
Then a created a catchall route at the buttom of routes.php in my plugin that will also not disturb the internal working of octobercms.
if (!Request::is('combine/*') && !Request::is('backend/*') && !Request::is('backend')) {
// Last fail over for looking up slug from the database
Route::get('{slug}/{slug2?}', function ($slug, $slug2 = null) {
//Pretend this are our routes and we can check them against the database
$routes = ["bola", "sade", "bisi", "ade", "tayo"];
if(in_array($slug, $routes)) {
$cmsController = new Cms\Classes\Controller;
return $cmsController->render("/catchpage", ['slug' => $slug]);
}
// Some fallback to 404
return Response::make(View::make('cms::404'), 404);
});
}
The if Request::is check is a list of all the resource that october uses under the hood, please dont remove the combine as it is the combiner route. Remove it and the style and script will not render. Also the backend is the url to the backend, make sure to supply the backend and the backend/*.
Finally don't forget to return Response::make(View::make('cms::404'), 404); if the resource is useless.
You may put all these in a controller though.
If anyone has a better workaround, please let us know.

Laravel 5.4, allow the user to only favourite something once so it does not get added to their list twice?

I have a working favourite system in my application, that allows the users' to favourite a charity and these favourites are displayed to them on another page.
The only problem is that the user is able to favourite the same charity multiple times, how could I limit this to just once and then maybe tell the user that they already have favourited this?
On your user object create a method public function hasFavourite($item)
This will call something like this
return $this->favourites()->where('key', $item->key)->count() !== 0;
in your controller you can now check if the user has a favourite
...
if (! $user->hasFavourite($item)) {
session()->flash(...);
return back();
}
... continue as usual

Better way to load views Codeigniter3

So let's say i have a controller named pages.
with this function.
function __construct(){
parent::__construct();
$this->auth['result'] = $this->is_logged_in();
}
The above code, calls for the extended function 'MY_Controller' which has a function called is_logged_in() and will simply fetch session data.
My first question would be, am i doing this authentication correct? or am i simply under-using it?
Anyways, my main question is regarding loading views.
Say i have many views, some views are accessed only by TYPE A user that has an access level different to that of TYPE B user.
Say both accounts are created differently, like in some online websites where there are users and shopowners that registered to advertise their shop irl, or for example, online travel. One account is user(normal/travelers) and one account is hotelowner(owns a hotel irl). So both will have overlapping views and some dedicated views for them.
How do i go about it when loading views?
Say in my controller i got functions,
public function view_home(){
}
public function view_userprofile(){
}
public function vieW_hotelprofile(){
}
You get my idea from above, i have separate functions for loading different views. But my question is that, how do i go about making it into one big function?
like for example,
public function view($page ='home' ){
}
the view function would be like a terminal for different accounts to access the views.
This would be simpler if i don't have to check access_levels. My first idea is to make a very long IF(){}ELSEIF(){} statement for example.
if($this->auth['result'] = 1 ){
load view here.
}
is this acceptable? also, how would i go about it efficiently? and regarding the authentication, this part i'm really confused if i'm using it the right way or not.
Also if i ever do a very long if statement, what values would i check? like i know you have to check the access level for certain views but do i also check the username logged in and match it to the database if it's accesslevel is the same?
You can try using switch case
public function loadView()
{
switch($this->auth['result']){
case 1:
$view= "home";
break;
case 2:
$view= "userprofile";
break;
case 3:
$view= "hotelprofile";
break;
default:
$view= "Welcome";
break;
}
$this->load->view($view);
}

Laravel 5.2 4 rolle

I need help how to make laravel 5.2 authenticate with 4 rolls?
guest
registered
support
admin
I make something but every time I get
ERR_TOO_MANY_REDIRECTS.
Route::group(['middleware' => ['web','isAdmin']], function () {
Route::get('/', function(){
return view('admin');
});
});
Route::group(['middleware' => ['web','isSupport']], function () {
Route::get('/support', function(){
return view('support');
});
});
Middleware
public function handle($request, Closure $next)
{
if (Auth::user()->role == '3') {
return $next($request);
}
if(Auth::guest()){
redirect('login');
}else
return redirect('/');
}
}
If I assume, you add isAdmin middleware to path /. isAdmin middleware is checking that user have a proper role (role with id === 3). If not, then redirect to /.
So only user with role 3 can access to path / but system still try redirect to this path. Infinite loop.
Yes, #grzegorz has the correct answer already posted on here I believe. But I will try to explain it clearly.
So in your route for the root of your application ('/') you tell Laravel to process middleware to authenticate users. This in and of itself is not unusual. The middleware runs a function to see if a user basically has level 3 authority and if they do then you return the request url (which is also '/' and the process continues in an infinite loop, because they are sent to the '/' url, then it processes and returns the same url again, causing it to process middleware again, going forever. This is why you are getting an error saying that there are too many redirects, because it redirects a whole bunch of times with no end in sight and eventually Laravel stops it for you and returns an error.
How to fix this problem?
Easy, you have a good start already. But what I would do is that when you check to see if a user has auth level 3 and they do, then simply return true. There is no need to return the requesting url, because this is middleware, so its running when someone requests a URL. So the purpose of your middleware would be to return true meaning "don't do anything, just continue". Then if the user does not have authority level 3, then you would want to redirect them away from this page. Do an actual redirect though (as opposed to returning a url string like you are now). So you would want to do something like this:
return redirect()->route('login');
You could also add some flash data to this with an error message to display to the user something telling them that they do not have access to this route.
Last note:
It would be strange to only allow high level authority users to be the only ones that can access a homepage. Maybe this is what you want, but it seems weird so I wanted to mention it in case it is unintended. What I wonder you are doing is maybe trying to display different information on the homepage depending if someone is logged in or not. if this is the case, then you don't want to use middleware, you want to move this to the controller and then conditionally add html for logged in users or something like that.

laravel 4.2. user permissions and hiding link source

I am a total newbie with Laravel and learning it now for a week. I have some basic questions that I can't find an answer to. Next week I will start with developing CRM system and I need some info from experienced developers who could tell me is the approach I am attending to make a good one.
I will need some authentication system, like 4 groups of users (Admin, Basic, Manager, Office) where Manager and Admin will add the Basic users. There will be few view and features and every groups will have defined access to each view and feature. Since few days I am searching for packages, watching the tutorials and learning. I found an interesting package for which I think it could help me with this user-group-permission things.The package is Sentry. Could this help me with my requirements?
What is the case when for example I have a user in group Basic and he deletes for example some comment with the button. On the left side down in the browser the user can see the link to this comment when he hovers the link. For example www.test.com/comments/345/delete where the id is 345. What if user types that with another id, that means he can delete another comment. I found some suggestions on how to solve this, to make it with jQuery and javascript so the link wouldn't be shown and POST would be made with for example with AJAX. But since I am a newbie, I am thinking how much time would this take and is this a good approach at all? Could package Sentry from 1. question help me with the permission on what route each group can access?
Any help or advice would be appreciated.
Sentry does what you want, yes. Here's a question with some answers explaining the permissions part.
The visible link part can be avoided by doing a POST request instead of a GET request.
When you open your form, you add a method attribute.
Form::open(array('url' => 'foo/bar', 'method' => 'post'))
A GET request will put the parameters in the URL, hence the visible ID. Using a POST request will put the parameters in the headers, thus hiding it from the URL.
An example could be deleting a comment. A GET request could look like this:
http://www.example.com/comments/delete/1
And the parameters would be defined in your method signature:
public function getDelete ($id) {
Comment::find($id)->delete();
}
Where the POST equivalent would be
http://www.example.com/comments/delete
And the parameters would be defined in your Input class, you would get them using the get method
public function postDelete() {
Comment::find(Input::get('id'))->delete();
}
1) The best package to help you with that is Sentry indeed.
2) To make sure an user can delete only his comments you can do something like this (but there are more solutions either you do it with Ajax or not):
public function destroy($id) {
$user = Sentry::getUser();
$comment = Comment::find($id);
if($comment) {
if($comment->user_id != $user->id) {
return Response::back(); // optional message: Permission denied!
}
$comment->delete();
return Response::back(); // optional with message: Deleted!
}
return Response::back(); // optional message: Comment not found!
}
You can use Sentry in this case to get the logged in user and check for user id. I think you should let user delete their own comments always but if you need special roles (Admins for example) to be able to delete any comment, or special permission comments.delete (For some Managers) - you can use Sentry as well:
public function destroy($id) {
$user = Sentry::getUser();
$comment = Comment::find($id);
if($comment) {
if($comment->user_id != $user->id && !$user->hasRole('Admin') && !$user->hasPermission('comments.delete'))) {
return Response::back(); // optional message: Permission denied!
}
$comment->delete();
return Response::back(); // optional with message: Deleted!
}
return Response::back(); // optional message: Comment not found!
}
A nicer way of making the DELETE thru a Form request check this:
Laravel RESTfull deleting

Resources