Strongloop REST API: change password - rest

I would like to implement a simple "change password" so that an authorised user can do so.
Experimenting with the explorer, I managed to write an ACL for the user model (my extension of the default User) that allow a user to change its data:
{
"principalType": "ROLE",
"principalId": "$owner",
"accessType": "WRITE",
"permission": "ALLOW"
}
However, when I try from explorer the endpoint PUT /users/{id} with new credentials, it fails silently, i.e., it returns ok, but perform no password change:
REQUEST:
http://localhost:3000/api/users/6?access_token=6CVOuMZCLB8deH7e5t8xJtzDlWjU98WUCRCSGO6zdjW0bhSR6Z20vddl7dIWepF8
DATA:
{
"credentials":
{"email":"pepito#example.com", "password": "ppito"}
}
(User 6 is already authenticated).
RESPONSE:
{
"realm": null,
"username": "pepito",
"credentials": {
"email": "pepito#example.com",
"password": "ppito"
},
"challenges": null,
"email": "pepito#example.com",
"emailVerified": true,
"verificationToken": "2a9c25fa6e858db5894f98cd3f0be3694041f148781896cb5775ff30da1f367c7843ac4b60013fd47c34c6f1a862a5cabb77cf2807c101da7f2acfcdd8853ec7",
"status": null,
"created": null,
"lastUpdated": null,
"id": 6
}
However, the password remain unchanged (tried with logout/login from the explorer).
Could you help me?

Dealing with password is different game. In order to change the password use the following code:
var AccessToken = Customer.app.models.AccessToken;
AccessToken.findById(access_token, function (err, token) {
if (err) cb(err);
else {
Customer.findById(token.userId, function (err, user) {
if (err) {
cb(err);
}
if (user == null || user == undefined) cb(new Error('user is undefined'));
user.updateAttribute('password', password, function (err, user) {
if (err) {
cb(err);
}
cb(null, 'success');
});
});
}
})
updateAttribute is what allows you to make the updates.
I've never been able to change password from swagger.

Related

Microsoft Graph API and SharePoint files permissions

I try with no success to give read or write access to an existing user (Office 365) on a Sharepoint drive folder.
With Graph Explorer the URL is like :
https://graph.microsoft.com/v1.0/sites/{site id}/drive/items/{folder id}/permissions
I can get actual permissions with GET method, but with POST method and this body I've got Invalid Request :
{
"grantedToV2": {
"user": {
"id": "xxxxxxx",
"displayName": "xxx xxx"
}
},
"roles": [
"read"
]
}
I tried with the powershell SDK and the New-MgDriveItemPermission too with no success.
Any help is welcome !
In order to add permissions to an you will have to make a POST request to the below endpoint:
https://graph.microsoft.com/v1.0/sites/{site-id}/drive/items/{folder-id}/invite
With the body containing all the info about the invitation request as the below example:
{
"requireSignIn": false,
"sendInvitation": false,
"roles": [ "read | write"],
"recipients": [
{
"email": "{email of the user}"
}
],
"message": "string"
}
If your request is succesful the response you will get back will be of the below format:
Status: 200
{
"#odata.context": "https://graph.microsoft.com/v1.0/$metadata#Collection(permission)",
"value": [
{
"#odata.type": "#microsoft.graph.permission",
"id": "<some id>",
"roles": [
"write"
],
"grantedTo": {
"user": {
"email": "<user>#<tenant>.onmicrosoft.com",
"id": "<some id>",
"displayName": "<user's display name>"
}
}
}
]
}
Below I will share with you the code snippet I got from Graph Explorer after creating a succesful request:
GraphServiceClient graphClient = new GraphServiceClient( authProvider );
var recipients = new List<DriveRecipient>()
{
new DriveRecipient
{
Email = "<user>#<tenant>.onmicrosoft.com"
}
};
var message = "Here's the file that we're collaborating on.";
var requireSignIn = true;
var sendInvitation = true;
var roles = new List<String>()
{
"write"
};
await graphClient.Sites["root"].Drive.Items["<folder-id>"]
.Invite(recipients,requireSignIn,roles,sendInvitation,message,null,null,null)
.Request()
.PostAsync();
Notes
You can find documentation about the endpoint here.
If you try to add permissions to a Folder that inherits its permission model from the document library, you should watch out because in some cases if the user is not a member of the site groups, MS Graph might invoke unique permissions on the folder.

How do I get more information after subscribing?

I don't know how to get more information after subscription.
The following returns an error:
paypal.Buttons({
createSubscription: function (data, actions) {
console.log(data)
return actions.subscription.create({
'plan_id': PP_PLAN_ID
})
},
onApprove: function (data, actions) {
console.log(data)
fetch(`https://api.sandbox.paypal.com/v1/billing/subscriptions/${data.subscriptionID}`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${data.facilitatorAccessToken}`
}
})
.then((r) => {
return r.json()
})
.then((r) => {
console.log(r)
})
}
}).render('#paypal-button-container')
Error response
{
"name": "NOT_AUTHORIZED",
"message": "Authorization failed due to insufficient permissions.",
"debug_id": "e0ba8b67ee540",
"details": [
{
"issue": "PERMISSION_DENIED",
"description": "You do not have permission to access or perform operations on this resource."
}
],
"links": [
{
"href": "https://developer.paypal.com/docs/api/v1/billing/subscriptions#NOT_AUTHORIZED",
"rel": "information_link",
"method": "GET"
}
]
}
I'm guessing some configuration is missing because of the permission error. Any pointers?
This is not a client-side operation, and a ClientID access token will not have permission.
You need to obtain the access token from a server, using a ClientID and Secret: https://developer.paypal.com/docs/api/overview/#get-an-access-token

how to fix ".... validation failed" using postman with express/bodyParser

I am making an API using express/bodyparser/MongoDB/postman, but whenever i send a POST request the Schema returns an error, how can i fix this issue?
I've tried different options in Postman, like checking if I had the right options and making sure its set to JSON.
How my requirements look:
const express = require("express");
const app = express();
const todoRoutes = require("./routes/todos");
const bodyParser = require("body-parser");
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
What my Schema looks like:
var todoSchema = new mongoose.Schema({
name: {
type: String,
required: "Use a string"
},
completed: {
type: Boolean,
default: false
},
created_date: {
type: Date,
default: Date.now
}
});
How my POST request looks:
router.post("/",function(req,res){
console.log(req.body);
db.Todo.create(req.body)
.then(function(newTodo){
res.json(newTodo);
})
.catch(function(err){
res.send(err);
});
});
The error which is returned by Postman:
{
"errors": {
"name": {
"message": "Use a string",
"name": "ValidatorError",
"properties": {
"message": "Use a string",
"type": "required",
"path": "name"
},
"kind": "required",
"path": "name"
}
},
"_message": "Todo validation failed",
"message": "Todo validation failed: name: Use a string",
"name": "ValidationError"
}
And the console.log of req.body when i give a key of name and a value of GoT :
'{\n "name" : "watch GoT"\n}': " }
The main odd thing which i see is that for some reason I get a strange log from req.body in the first place ( unusual ' and \n)
You need to go to the body tab in Postman and select xxx-w-form-urlencoded
To post a URL parameter's value, use req.params
router.post("/",function(req,res){
db.Todo.create({ name = req.params.name })
.then(function(newTodo){
res.json(newTodo);
})
.catch(function(err){
res.send(err);
});
});

Include Loopback relation in POST response

I have a working chat-room loopback project, which also utilises Socket.IO.
Once I create a Message (POST to Loopback REST API), I need the response the include the 'creator' relation.
This works fine when using GET, but I cannot include the relation to the POST response.
I'm sure it's a simple remote hook, but I'm stuck...
Any help is greatly appreciated!
"relations": {
"creator": {
"type": "belongsTo",
"model": "Person",
"foreignKey": "",
"options": {
"nestRemoting": true
}
},
"event": {
"type": "belongsTo",
"model": "Event",
"foreignKey": "",
"options": {
"nestRemoting": true
}
}
},
There are two options how you can do it with Loopback 2.x or 3.x (not sure about the Loopback 4.x).
Let's assume we have the following "Note" model:
{
"name": "Note",
"properties": {
"title": {
"type": "string",
"required": true
},
"content": {
"type": "string"
},
"userId": {
"type": "number"
}
},
"relations": {
"user": {
"type": "belongsTo",
"model": "User",
"foreignKey": "userId"
}
}
}
Now, to include "user" property (which is a belongsTo relation of Note) in the response when you create (POST) a Note you have two options.
Option #1 (Recommended): Create a custom remote method and hide the default method in your model's script file. In this case your note.js file should look something like:
module.exports = function (Note) {
// Hide the default 'create' remote method
Note.disableRemoteMethod('create', true);
// Add a custom 'customCreate' remote method
Note.remoteMethod('customCreate', {
description: 'Create a new instance of the model and persist it into the data source.',
accessType: 'WRITE',
accepts: [
{
arg: 'data',
type: 'object',
model: 'Note',
allowArray: true,
description: 'Model instance data',
http: { source: 'body' },
},
{ arg: 'options', type: 'object', http: 'optionsFromRequest' },
],
returns: { arg: 'data', type: 'Note', root: true },
http: { verb: 'post', path: '/' },
isStatic: true,
});
Note.customCreate = function (data, options, cb) {
Note.create(data, options, function(err, newObj) {
if (err) {
cb(err);
}
else {
// here we try to load the user value
newObj.user(function (err, user) {
if (user) {
// if we found a user we add it to __data, so it appears in the output (a bit hacky way)
newObj.__data.user = user;
}
cb(err, newObj);
});
}
});
};
};
I would recommend using this option because you achieve what you need with minimal changes in the default logic of the loopback model, i.e. all the default methods like create, upsert, etc. continue to have default behavior.
Option 2: Use 'after save' operation hook (be careful with this approach as it changes the way how create, upsert, upsertWithWhere and other default methods work)
In this case your note.js file should look something like:
module.exports = function (Note) {
Note.observe('after save', function (ctx, next) {
ctx.instance.user(function (err, user) {
ctx.instance.__data.user = user;
next();
});
});
};
The second option has less code, but as I mentioned before you should be very careful using it because it will change the behavior of default "create" method of the model. I.e. 'after save' action will be executed each time you call Model.create, Model.upsert, etc. It will also slow down these operation as you add additional select query in the 'after save' hook.

Add event to calendar on SharePoint through REST API

I'm trying to add a calendar event to a SharePoint Calendar through REST API but i can't seems to find the relevant resources to achieve this.
If i understand correctly, the calendar in SharePoint is a List of events object, as such I should be able to add the event via ListItem object?
Sorry if this sounds wrong as I'm not familiar with SharePoint structure.
Thanks
This is the example for OAuth token Authentication but REST part is anyway like this.
var dataObj = {
"Subject": "Birthday Party"
"Body": {
"ContentType": "Text",
"Content": "Birthday Party for Cathy",
},
"Start": {
"dateTime": "2016-07-03T09:00:00Z",
"timeZone": "Asia/Tokyo"
},
"End": {
"dateTime": "2016-07-04T11:00:00Z",
"timeZone": "Asia/Tokyo"
},
"Location": {
"DisplayName": "Conference Room 1"
},
"ShowAs": "Busy",
"Attendees": [
{
"EmailAddress": { "Name": "Alex Darrow", "Address": "darrow.alex#company.com" },
"Type": "Required"
}
]
};
var url = "https://graph.microsoft.com/v1.0/me/events/";
var data = JSON.stringify(dataObj);
$.ajax({
url: url,
type: "POST",
data: data,
beforeSend: function (XMLHttpRequest) {
XMLHttpRequest.setRequestHeader("Accept", "application/json;odata.metadata=full;odata.streaming=true");
XMLHttpRequest.setRequestHeader('Authorization', 'Bearer ' + accessToken);
XMLHttpRequest.setRequestHeader("content-type", "application/json;odata=verbose");
},
success: function (result, textStatus, jqXHR) {
//Success
},
error: function (data) {
//
}});