User Authorization not working for Mean.JS - javascript

I’m using mean.js to let registered users access content. It’s sort of working. I can change isAllowed to !isAllowed to let people see the content. The problem is that content is not authorized when the user logs in. The articles example works fine. But when I create my own section, logged in users can’t access pages!
So basically if I log in, I get message: 'User is not authorized' if I try going to localhost:3000/requestoffwork
If I log in and change isAllowed to !isAllowed, I can access it
'use strict';
/**
* Module dependencies.
*/
var acl = require('acl');
// Using the memory backend
acl = new acl(new acl.memoryBackend());
/**
* Invoke Articles Permissions
*/
exports.invokeRolesPolicies = function () {
acl.allow([{
roles: ['admin'],
allows: [{
resources: '/api/articles',
permissions: '*'
}, {
resources: '/api/articles/:articleId',
permissions: '*'
}]
}, {
roles: ['user'],
allows: [{
resources: '/requestoffwork',
permissions: '*'
}, {
resources: '/api/articles/:articleId',
permissions: ['get']
}]
}, {
roles: ['guest'],
allows: [{
resources: '/api/articles',
permissions: ['get']
}, {
resources: '/api/articles/:articleId',
permissions: ['get']
}]
}]);
};
/**
* Check If Articles Policy Allows
*/
exports.isAllowed = function (req, res, next) {
var roles = (req.user) ? req.user.roles : ['guest'];
// If an article is being processed and the current user created it then allow any manipulation
if (req.article && req.user && req.article.user.id === req.user.id) {
return next();
}
// Check for user roles
acl.areAnyRolesAllowed(roles, req.route.path, req.method.toLowerCase(), function (err, isAllowed) {
if (err) {
// An authorization error occurred.
return res.status(500).send('Unexpected authorization error');
} else {
if (isAllowed) {
// Access granted! Invoke next middleware
return next();
} else {
return res.status(403).json({
message: 'User is not authorized'
});
}
}
});
};
This is the route
app.route('/requestoffwork').all(managementPolicy.isAllowed)
.get(management.list)
.post(management.submit);
And here's the data for the user
{"_id":"5788fe46587a1c0b07a04078","displayName":"","provider":"local","__v":0,"created":"2016-07-15T15:16:22.625Z","roles":["user"],"profileImageURL":"modules/users/client/img/profile/default.png","email":"email#gmail.com","lastName":"","firstName":”"}

Did you add the permissions to the client side routes ass well ?
In modules/youModule/client/config/youModule.client.routes.js add this:
function routeConfig($stateProvider) {
$stateProvider
.state('yourState', {
abstract: true,
url: '/requestoffwork',
template: '<ui-view/>',
data: {
roles: ['user'], //here you must specify the roles as well
pageTitle: 'requestoffwork'
}
})
}
Hope this helps.

Related

How to add permissions to a new API with STRAPI (not from dashboard)

I need to do a new api in order to send an email with sendgrid. I followed the official doc and other examples so I did:
config/plugins
module.exports = ({ env }) => ({
email: {
provider: 'sendgrid',
providerOptions: {
apiKey: env('SENDGRID_API_KEY'),
},
settings: {
defaultFrom: 'juliasedefdjian#strapi.io',
defaultReplyTo: 'juliasedefdjian#strapi.io',
},
},
});
then I did a new folder named email in api folder
api/email/config/routes.json
{
"routes": [
{
"method": "POST",
"path": "/email",
"handler": "email.index",
"config": {
"policies": []
}
}
]
}
finally under api/email/controllers/email.js
const { default: createStrapi } = require('strapi');
module.exports = {
index: async (ctx) => {
//build email with data from ctx.request.body
await createStrapi.plugins['email'].services.email.send({
to: 'email#email.com',
from: 'email#email.com',
replyTo: 'email#email.com',
subject: 'test',
text: 'test',
});
ctx.send('Email sent!');
},
};
The real problem is that /email api returns me a 403 even if I did this from the dashboard:
I have done many APIs with strapi but I have never sent emails with it.
Is there a way to add permissions from the code? I have to say that if I use GET method it works, but I need to do it with a POST method, which doesn't. Did I miss something?

How to create a middleware for check role in Nuxtjs

I'm trying to create a middleware for check role of my users.
// middleware/is-admin.js
export default function (context) {
let user = context.store.getters['auth/user']
if ( user.role !== 'admin' ) {
return context.redirect('/errors/403')
}
}
In my .vue file, I'm putting this on:
middleware: [ 'is-admin' ]
It works.
Now, I'd like to check if the user also has another role. So, I create a new middleware:
// middleware/is-consultant.js
export default function (context) {
let user = context.store.getters['auth/user']
if ( user.role !== 'consultant' ) {
return context.redirect('/errors/403')
}
}
And in my .vue file:
middleware: [ 'is-admin', 'is-consultant' ]
Unfortunately, when I do that, if I visit the route with an administrator role, it does not work anymore.
Can you tell me how I can create a middleware that checks multiple roles with Nuxt.js?
Thank you!
The idea is that every page has its authority level. Then in middleware you can compare your current user authority level with the current page authority level, and if it's lower redirect the user. It's very elegant solution that was proposed by Nuxt.js creator. GitHub issue.
<template>
<h1>Only an admin can see this page</h1>
</template>
<script>
export default {
middleware: 'auth',
meta: {
auth: { authority: 2 }
}
}
</script>
Then in your middleware/auth.js:
export default ({ store, route, redirect }) => {
// Check if user is connected first
if (!store.getters['user/user'].isAuthenticated) return redirect('/login')
// Get authorizations for matched routes (with children routes too)
const authorizationLevels = route.meta.map((meta) => {
if (meta.auth && typeof meta.auth.authority !== 'undefined')
return meta.auth.authority
return 0
})
// Get highest authorization level
const highestAuthority = Math.max.apply(null, authorizationLevels)
if (store.getters['user/user'].details.general.authority < highestAuthority) {
return error({
statusCode: 401,
message: 'Du måste vara admin för att besöka denna sidan.'
})
}
}
You can use this feature in Nuxt
export default function ({ $auth, redirect }) {
if (!$auth.hasScope('admin')) {
return redirect('/')
}
}
The scope can be anything you want e.g Consultant, Editor etc.
Check the documentation
Updated
Since you are using Laravel
You can have a role column in your user table
e.g
$table->enum('role', ['subscriber', 'admin', 'editor', 'consultant', 'writer'])->default('subscriber');
Then create a API resource, check the documentation for more
To create a user resource, run this artisan
php artisan make:resource UserResource
Then in your resource, you can have something like this
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->email,
'phone' => $this->phone,
'gender' => $this->gender,
'country' => $this->country,
'avatar' => $this->avatar,
'role' => $this->role,
];
}
Then you can import it to your controller like this
use App\Http\Resources\UserResource;
You can get the resource like this
$userdata = new UserResource(User::find(auth()->user()->id));
return response()->json(array(
'user' => $userdata,
));
In Nuxt
To do authentication in Nuxt
Install nuxt auth and axios
Using YARN : yarn add #nuxtjs/auth #nuxtjs/axios
Or using NPM: npm install #nuxtjs/auth #nuxtjs/axios
Then register them in your nuxtconfig.js
modules: [
'#nuxtjs/axios',
'#nuxtjs/auth',
],
In your nuxtconfig.js, add this also
axios: {
baseURL: 'http://127.0.0.1:8000/api'
},
auth: {
strategies: {
local: {
endpoints: {
login: { url: '/login', method: 'post', propertyName: 'access_token' },
logout: { url: '/logout', method: 'post' },
user: { url: '/user', method: 'get', propertyName: false }
},
tokenRequired: true,
tokenType: 'Bearer',
globalToken: true
// autoFetchUser: true
}
}
}
The URL been the endpoints
Check Documentation for more
To restrict certain pages in Nuxt to Specific User.
> Create a middlweare e.g isadmin.js
Then add this
export default function ({ $auth, redirect }) {
if (!$auth.hasScope('admin')) {
return redirect('/')
}
}
Then go to the Page, add the middleware
export default {
middleware: 'isadmin'

request.auth.session.set(user_info) not working HapiJS

This is my strategy, which is defined on a server.register(). I'm basing my work off a tutorial and it is literally copied from it but it doesn't work.
server.auth.strategy('standard', 'cookie', {
password: 'somecrazycookiesecretthatcantbeguesseswouldgohere', // cookie secret
cookie: 'app-cookie', // Cookie name
isSecure: false, // required for non-https applications
redirectTo: '/login',
ttl: 24 * 60 * 60 * 1000 // Set session to 1 day
});
server.auth.default({
strategy: 'standard',
mode: 'required',
scope: ['admin']
});
This is my login route where the error occurs:
server.route({
method: 'POST',
path: '/login',
config: {
auth: false,
validate: {
payload: {
email: Joi.string().email().required(),
password: Joi.string().min(2).max(200).required()
}
},
handler: function (request, reply) {
getValidatedUser(request.payload.email, request.payload.password)
.then(function (user) {
if (user) {
//ERROR OCCURS HERE: IT SAYS SESSION IS UNDEFINED
request.auth.session.set(user);
return reply('Login Successful!');
} else {
return reply(Boom.unauthorized('Bad email or password'));
}
});
// .catch(function (err) {
// return reply(Boom.badImplementation());
// });
}
}
});
I've tried so many things but this part is crucial for this work and I can't find anyone with the same problem. Help please!
hapi-auth-cookie has changed the way cookies are set and cleared. As of version 5.0.0, use request.cookieAuth.set() and request.cookieAuth.clear(). You are probably using a more recent version of the plugin than is used in the package.json of the tutorial.
source:
https://github.com/hapijs/hapi-auth-cookie/commit/d233b2a3e4d0f03ef53b91b7929b8dbadbff624c

accessing github user data in meteor oauth

I am trying to authenticate a user with github, then pass their avatar_url to the client. Simplified structure looks as follows.
server/
publications.js
client/
users/
login.js
main.js
In my client/users/login.js file, I try to get the permission to the user Object which contains the avatar url
Accounts.ui.config({
requestPermissions: {
github: ['user']
}
});
Then in my server/publications.js, I try to publish the data related to the avatar url.
Meteor.publish('userData', function() {
if(this.userId) {
return Meteor.users.find(
{ _id: this.userId }, {
fields: {
'services.github.id': 1,
'services.github.user.avatar_url': 1
}
})
} else {
this.ready();
}
});
However I never get the data related to the github user when I get my user object. How can I get access to the user with OAuth?
Please have a look at this sample code, do you capture the Github profile data onCreateUser?
EDIT: this is server side code, e.g. server/accounts.js
Accounts.onCreateUser(function (options, user) {
var accessToken = user.services.github.accessToken,
result,
profile;
result = Meteor.http.get("https://api.github.com/user", {
params: {
access_token: accessToken
}
});
if (result.error)
throw result.error;
profile = _.pick(result.data,
"login",
"name",
"avatar_url",
"url",
"company",
"blog",
"location",
"email",
"bio",
"html_url");
user.profile = profile;
return user;
});
Code found here

How to reference associated models in a one-to-many relationship with Sails 0.10.x

I'm using Sails.js version 0.10.x, and am just starting to try out it's associactions stuff.
In my scenario I have a User who has many Documents.
so in /api/models/User.js I have:
module.exports = {
// snipped out bcrypt stuff etc
attributes: {
email: {
type: 'string',
unique: true,
index: true,
required: true
},
documents: {
collection: 'document',
via: 'owner'
},
}
};
and in /api/models/Document.js I have:
module.exports = {
attributes: {
name: 'string',
owner: {
model: 'user'
}
}
};
In my DocumentController I have the following:
fileData = {
name: file.name,
owner: req.user
}
Document.create(fileData).exec(function(err, savedFile){
if (err) {
next(err);
} else {
results.push({
id: savedFile.id,
url: '/files/' + savedFile.name,
document: savedFile
});
next();
}
});
Looking in my local mongo database via the command line I can see that the documents have the owner field set as follows "owner" : ObjectId("xxxxxxxxxxxxxxxxxxxxxxxx") which is as expected.
However when I inspect the req.user object later in the DocumentController via sails.log.debug("user has documemts", req.user.documents); I see
debug: user has documents [ add: [Function: add], remove: [Function: remove] ]
And not an array of Document objects.
In my resulting slim template
if req.user.documents.length > 0
ul
for doc in req.user.documents
li= doc.toString()
else
p No Documents!
I always get "No Documents!"
I seem to be missing something obvious but I'm not sure what that is.
I worked this out by wading through the Waterline source code.
Firstly, as I hoped, both sides of the association are affected by the creation of the Document instance, and I simply needed to reload my user.
Within the controller this is as simple as User.findOne(req.user.id).populateAll().exec(...)
I also modified my passport service helper as follows
function findById(id, fn) {
User.findOne(id).populateAll().exec(function (err, user) {
if (err) return fn(null, null);
return fn(null, user);
});
}
function findByEmail(email, fn) {
User.findOne({email: email}).populateAll().exec(function (err, user) {
if (err) return fn(null, null);
return fn(null, user);
});
}
Now the user, and its associations, are loaded properly per request.
I had to dig through the source to find the populateAll() method as it's not actually documented anywhere I could find. I could also have used populate('documents') instead but I am about to add other associations to the User so need populateAll() to load all the relevant associations.
Waterline associations docs
Waterline /lib/waterline/query/deferred.js#populateAll

Categories