How does on assign Admin status to a user in the Admin UI?
I have read the guide on authentication and the one on access control, but I don't understand the difference between "owner" and "admin" in KeystoneJS. When you create a User, how do you assign that User admin rights? How do you need to set up the User list to permit that? What is an "owner" then?
KeystoneJs access control is declarative, you have full control and keystone does not make any assumptions on this.
Admin: in simple words you might be thinking is Admin means that user can access Admin-UI app. but the Admin UI app is also restricted using some access control method.
By default all have access to admin ui, you can restrict that by using isAccessAllowed property in the Admin UI app constructor option.
from above link example:
new AdminUIApp({
/*...config */
isAccessAllowed: ({ authentication: { item: user, listKey: list } }) => !!user && !!user.isAdmin,
}),
in above this list item is usually from "User" list as defined in Auth Strategy
const authStrategy = keystone.createAuthStrategy({
type: PasswordAuthStrategy,
list: 'User',
config: {
identityField: 'username', // default: 'email'
secretField: 'password', // default: 'password'
},
});
...
module.exports = {
keystone: new Keystone(),
apps: [
new GraphQLApp(),
new AdminUIApp({
adminPath: '/admin',
authStrategy,
isAccessAllowed: ({ authentication: { item: user, listKey: list } }) => !!user && !!user.isAdmin,
}),
],
};
Owner: there is no owner defined by keystone, all you do is to create ownership entitlement based on declaration like for blog post, an Author is owner, based on this distinction you can allow certain action by post author like editing and submitting for approval.
all this goes into access control api, when you create access control definition, they evaluate the function and decide if that action is allowed. You can see full example of how this works in https://github.com/MadeByMike/keystone-access-control-demo and more advanced one in their test suit here - https://github.com/keystonejs/keystone/blob/master/test-projects/access-control/index.js
Related
I currently have a service authentication up and running (using jwt to auth).
I'm working on a quiz service that force user to create some required information and force them to take a quiz to understand how to use our tool.
Because lacking of Frontend exp, I'm wondering how this quiz service will integrate with the auth service
Right now, for Backend side during auth service I will give them back the permission in the token if I call the function to check if the user pass the test & have a profile created. Otherwise I give them back the token with permission = []
But for the Frontend side, what is the solution to re-direct use to Quiz page (after sign-in and what about user that already log-in before)
check this documentation programatic navigation
once authenticated redirect the user back using [vue2 code]
this.$router.push({name:'Quiz',params:{id:this.$route.query.next})
In the authentication page you may pass the quiz link as next query parameter eg
example.com/login?next=< quizID >
Navigation guard documentation
You can use route guards to redirect unauthenticated users to the login page, do remember to pass the quiz id as a query parameter.
your guard will be similar to this
router.beforeEach((to, from, next) => {
if (to.name === 'Quiz' && !isAuthenticated) next({ name: 'Login', query: { next: to.params.quizID }})
else next()
})
This was assuming you have set your routes has a route named Quiz and takes :id and a route named login, similar to this.
{
path: '/quiz/:id',
name: 'Quiz',
.....
},
{
path: '/login',
name: 'Login',
......
},
Alternatively, you could have set up a dialog box on the quiz page that handles authication.
Is it possible to hide slash command in discord.js v13.1.0 ?
I tried to add some permission but nothing that i found worked like the
" command.permissions.add({ "permission array" }) "
If there is a way to do it it would be amazing
I saw that the support saw that issue but do you have any idea about when they would add this feature ?
I just used the discord interface. Here's what I did:
(1) Right click your server
(2) Go to Server Settings -> Integrations
(3) Scroll down to Bots and Apps and click Manage next to your bot
(4) Click Add Roles or Members, or click Channels depending on if you want to restrict to specific roles, users, or channels
(5) Once you add them, click the X to restrict their access to the command. Now they won't be able to see it anymore.
Important Note: Make sure to view the server as a non-admin role or switch accounts to a non-admin user to test the new permissions. Otherwise, it won't work. To view as another role, go to Server Settings -> Roles, then select a non-admin role, scroll to the bottom and select View Server As Role.
According to discordjs guide, you need to use ApplicationCommandPermissionsManager#set() or ApplicationCommandPermissionsManager#add():
using set()
const fullPermissions = [
{
id: '123456789012345678',
permissions: [{
id: '224617799434108928',
type: 'USER',
permission: false,
}],
},
{
id: '876543210987654321',
permissions: [{
id: '464464090157416448',
type: 'ROLE',
permission: true,
}],
},
];
await client.guilds.cache.get('123456789012345678')?.commands.permissions.set({ fullPermissions });
using add()
if (!client.application?.owner) await client.application?.fetch();
const command = await client.guilds.cache.get('123456789012345678')?.commands.fetch('876543210987654321');
const permissions = [
{
id: '224617799434108928',
type: 'USER',
permission: false,
},
];
await command.permissions.add({ permissions });
In Vue, when I want to restrict some pages for some users, in router I define a permission in meta, like this:
routes: [
{
path: 'transport',
name: 'transport',
component: Transport,
meta: { permission: "edit_transport" }
},
]
When user logins I have its JWT where I can find what permission he/she has and in route.beforeEach, I check if user has this permission, he/she can visit a page.
router.beforeEach((to, from, next) => {
let token = window.localStorage.getItem('user_token');
if(to.meta.permission == 'edit_transport') {
//if user's token has edit_tranport permission let him visit the page
}
})
But, now I have this permissions In database, there is a table where admin defines permission for page:
id permision page
_____________________________________
1 edit_transport transport
2 write_post create_post
This means, for example user needs edit_transport permission to visit transport page.
My solution is: first I have to take all this permissions from database and save them in vuex store, and then access this store data in route.beforeEach and check what permission page needs and then check if user has this permission
router.beforeEach((to, from, next) => {
let token = window.localStorage.getItem('user_token');
let pagepermission = store.permissions[to.name]
if (token.has(pagepermission)) {
// let user visit the page
} else {
// redirect
}
})
So, is it a good way or is there any other way better then this?
This is a good check to do on the client side, if you are also protecting routes / endpoints on the back end I think that would be the most well rounded solution.
I'm not sure what you're using on the backend but if its Node, you could use something like Passport to manage roles - as a middleware to routes and endpoints.
Basically I have a login/register landing page of my app. After a user logs in or registers I don't want them to be able to access this route anymore. I'm not sure how to achieve this with Hapi.js. The login page doesn't use any auth strategies so it has no idea if a user is logged in or not.
The approach I normally use for this is not disabling the route per se, but redirecting logged-in users away from the login route.
As you point out correctly your login route currently doesn't know whether a user is logged in if it has no auth strategy configured. The solution is to add an auth strategy to the login route, but using the try mode. This means the handler will be executed regardless of whether auth was successful. The trick is that you can then check if the user is authenticated (by inspecting the value of request.auth.isAuthenticated) or not and react accordingly.
So your route might look like this:
server.route({
config: {
auth: {
strategy: 'session',
mode: 'try'
}
},
method: 'GET',
path: '/login',
handler: function (request, reply) {
if (request.auth.isAuthenticated) {
return reply.redirect('/'); // user is logged-in send 'em away
}
return reply.view('login'); // do the login thing
}
});
Another approach with the same result is to set your auth strategy on try mode as the default for all routes:
server.auth.strategy('session', 'cookie', 'try', {
password: 'password-that-is-longer-than-32-chars',
isSecure: true
});
Notice that third argument try. With this approach you don't need to add any auth config to the route itself because it will try this strategy by default. According to the server.auth.strategy docs:
mode - if true, the scheme is automatically assigned as a required strategy to any route without an auth config. Can only be assigned to a single server strategy. Value must be true (which is the same as 'required') or a valid authentication mode ('required', 'optional', 'try'). Defaults to false.
There's some more info about modes in the Authentication tutorial on the hapi site.
I am logging in the system successfully but
I want that the user whose role is 'Administrator' can only go to all the routes and user having role as 'Manager' can go to 'Home' and 'GetDocumentDetails' else the other login users will be restricted to home page and the guest to Login page.
My route and filter files are as follows:
Routes:
Route::post('/login', function()
{
$user = array(
'username' => Input::get('username'),
'password' => Input::get('password'));
// verify user credentials
if (Auth::attempt($user,true))
{
$role= Auth::user()->userrole;
return Redirect::route('home');
}
}
// Route for getting document details using get method
Route::get('GetDocumentDetailsById',array('as'=>'GetDocumentDetailsById','uses'=>'DocumentController#GetDocumentDetailsById'));
// Route for guest user
Route::filter('guest', function()
{
if (Auth::check())
return Redirect::route('home')->with('flash_notice', 'You are already logged in!');
// Redirect Log-in user to his home page
});
Filters:
/* Filter to redirect guest user to login page */
Route::filter('auth', function()
{
$role=Auth::user();
if (Auth::guest()) return Redirect::guest('login');
});
Route::filter('auth.basic', function()
{
return Auth::basic('username');
});
Route::filter('guest', function()
{
if (Auth::check()) return Redirect::to('/');
});
I would recommend using Zizaco's Entrust and Confide packages for this purpose, as they greatly simplify this task.
Follow the tutorials on these pages after installing both packages, and then you can limit access to certain routes just by defining Route Permission filters or regular Route filters. No need for any additional logic in controller actions.
These Route Permission filters can easily be defined like this:
// Any route under admin is only accessible by users with role Admin.
// Redirect happens if user doesn't have this role.
Entrust::routeNeedsRole('admin*', 'Admin', Redirect::to('/'));
A Route filter based on permissions would look like this:
Route::filter('myFilter', function()
{
if (!Entrust::can('get_document_details') )
{
return Redirect::to('/');
}
});
This filter could then be applied to any route. See the Entrust documentation for more examples and features. Entrust is really versatile.