Parse cloud code issue accessing pointers in request - objective-c

I am having an issue accessing some objects in cloud code.
I am trying to send a push to array of users everytime a message object is save on parse. Here is the beginning of my code :
// To send push whenever a message is sent
Parse.Cloud.afterSave("Message", function(request) {
// Our "Comment" class has a "text" key with the body of the comment itself
var messageText = request.object.get('text');
var messageUserFirstName = request.object.get('user').get('firstName');
var usersId = [];
var conversation = request.object.get('conversation').get('group1').get('users');
In my Message table, I have a pointer to the class Conversation, which has also a pointer to a class Group, which contains an array of Users pointers. It seems I cannot access this array with the following line:
var conversation = request.object.get('conversation').get('group1').get('users');
Am I doing something wrong?
Thanks.

Your 'user', 'conversation', and 'group1' objects will all need to be fetched before you can access their data.

Related

Azure service bus Message deserialize broken in core conversion

So, I've created a new Azure Functions project v3 and am porting over a subset of functions from v1 that was running on 4.6.2, while retiring the rest as obsolete. Unfortunately in the change from BrokeredMessage to Message due to changing from Microsoft.ServiceBus.Messaging to Microsoft.Azure.ServiceBus the following deserialization method is now failing with:
There was an error deserializing the object of type stream. The input source is not correctly formatted.
The problem is right there in the error, but Im not sure what the correct new approach is, its a bit unclear.
Serialize
public static Message CreateBrokeredMessage(object messageObject)
{
var message = new Message(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(messageObject)))
{
ContentType = "application/json",
Label = messageObject.GetType().Name
};
return message;
}
Deserialize
public static T ParseBrokeredMessage<T>(Message msg)
{
var body = msg.GetBody<Stream>();
var jsonContent = new StreamReader(body, true).ReadToEnd();
T updateMessage = JsonConvert.DeserializeObject<T>(jsonContent);
return updateMessage;
}
Object
var fileuploadmessage = new PlanFileUploadMessage()
{
PlanId = file.Plan_Id.Value,
UploadedAt = uploadTimeStamp,
UploadedBy = uploadUser,
FileHash = uploadedFileName,
FileName = file.Name,
BusinessUnitName = businessUnitName,
UploadedFileId = uploadedFile.Id
};
```
Message.GetBody<T>() is an extension method for messages sent using the legacy Service Bus SDK (WindowsAzure.ServiceBus package) where BrokeredMessage was populated with anything other than Stream. If your sender sends an array of bytes as you've showed, you should access it using Message.Body property.
In case your message is sent as a BrokeredMessage, the receiving code will need to select either of the methods based on some information to indicate how the message was originally sent.

Getting data from the body in the authorization middleware

I have a similar question as enter link description here: if I want to update an object (sent in the body of a PUT) which contains an id, how can I obtain this id in the middleware without sending this Id in the route data?
Example: Given the object:
myObject= new MyObject
{
id = 1,
string "blah blah blah"
}
a user who has update rights on MyObject with id = 3 and who has NO UPDATE RIGHTS on MyObject with id = 1 uses Postman to send a PUT with the route /api/values/3 and the body myObject. The authorization middleware will be fooled with the id = 3 and will let the user modify the wrong object.
Of course I could add in the updateMethod a check (if (myObjectId != myObject.id) ...) or I could remove the id from the MyObject, but both solutions seem too much effort for such an edge case. The most straightforward way would be to be able to validate the actual data in the middleware.
Any way to do it? Is there a better approach I have not considered? thanks!
I want to update an object (sent in the body of a PUT) which contains an id, how can I obtain this id in the middleware without sending this Id in the route data?
Achieve the above requirement in middleware/authorization filter, reading the posting data MyObject from request body is easy, but it does not support us write the modified MyObject data back to request body.
If possible, you can try to achieve it in action filter, like below.
public void OnActionExecuting(ActionExecutingContext context)
{
if (context.HttpContext.Request.Path.StartsWithSegments(new Microsoft.AspNetCore.Http.PathString("/api/values")))
{
var user = context.HttpContext.User;
//code logic here
//check if request from client contains id in route data
var routeData = context.HttpContext.Request.RouteValues;
//update value of MyObject Id property based on your requirement
object myObject;
if (context.ActionArguments.TryGetValue("myObject", out myObject))
{
MyObject _myobject = myObject as MyObject;
_myobject.Id = 3;
}
}
}

Mongoose: Why to convert a received data toObject

I was learning mongoose, and I am trying to figure out.
Why toObject() was needed to convert the data received into Object, when it was already in object form it seems
Here is the code:
UserSchema.methods.toJSON = function() {
var user = this;
var userObject = user.toObject();
return _.pick(userObject, ['_id', 'email']);
};
I cannot understand why toObject() was used to extract the meaningful properties from the object.
Thanks
toObject is a mongoose document method Document.prototype.toObject() which:
Converts this document into a plain javascript object, ready for storage in MongoDB.
You can more about it here
The reason it is called there is because a plain JS object is required in order to do the lodash _.pick which would create a new object with only _id and email properties.

Update Document with external object

i have a database containing Song objects. The song class has > 30 properties.
My Music Tagging application is doing changes on a song on the file system.
It then does a lookup in the database using the filename.
Now i have a Song object, which i created in my Tagging application by reading the physical file and i have a Song object, which i have just retrieved from the database and which i want to update.
I thought i just could grab the ID from the database object, replace the database object with my local song object, set the saved id and store it.
But Raven claims that i am replacing the object with a different object.
Do i really need to copy every single property over, like this?
dbSong.Artist = songfromFilesystem.Artist;
dbSong.Album = songfromFileSystem.Album;
Or are there other possibilities.
thanks,
Helmut
Edit:
I was a bit too positive. The suggestion below works only in a test program.
When doing it in my original code i get following exception:
Attempted to associate a different object with id 'TrackDatas/3452'
This is produced by following code:
try
{
originalFileName = Util.EscapeDatabaseQuery(originalFileName);
// Lookup the track in the database
var dbTracks = _session.Advanced.DocumentQuery<TrackData, DefaultSearchIndex>().WhereEquals("Query", originalFileName).ToList();
if (dbTracks.Count > 0)
{
track.Id = dbTracks[0].Id;
_session.Store(track);
_session.SaveChanges();
}
}
catch (Exception ex)
{
log.Error("UpdateTrack: Error updating track in database {0}: {1}", ex.Message, ex.InnerException);
}
I am first looking up a song in the database and get a TrackData object in dbTracks.
The track object is also of type TrackData and i just put the ID from the object just retrieved and try to store it, which gives the above error.
I would think that the above message tells me that the objects are of different types, which they aren't.
The same error happens, if i use AutoMapper.
any idea?
You can do what you're trying: replace an existing object using just the ID. If it's not working, you might be doing something else wrong. (In which case, please show us your code.)
When it comes to updating existing objects in Raven, there are a few options:
Option 1: Just save the object using the same ID as an existing object:
var song = ... // load it from the file system or whatever
song.Id = "Songs/5"; // Set it to an existing song ID
DbSession.Store(song); // Overwrites the existing song
Option 2: Manually update the properties of the existing object.
var song = ...;
var existingSong = DbSession.Load<Song>("Songs/5");
existingSong.Artist = song.Artist;
existingSong.Album = song.Album;
Option 3: Dynamically update the existing object:
var song = ...;
var existingSong = DbSession.Load<Song>("Songs/5");
existingSong.CopyFrom(song);
Where you've got some code like this:
// Inside Song.cs
public virtual void CopyFrom(Song other)
{
var props = typeof(Song)
.GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance)
.Where(p => p.CanWrite);
foreach (var prop in props)
{
var source = prop.GetValue(other);
prop.SetValue(this, source);
}
}
If you find yourself having to do this often, use a library like AutoMapper.
Automapper can automatically copy one object to another with a single line of code.
Now that you've posted some code, I see 2 things:
First, is there a reason you're using the Advanced.DocumentQuery syntax?
// This is advanced query syntax. Is there a reason you're using it?
var dbTracks = _session.Advanced.DocumentQuery<TrackData, DefaultSearchIndex>().WhereEquals("Query", originalFileName).ToList();
Here's how I'd write your code using standard LINQ syntax:
var escapedFileName = Util.EscapeDatabaseQuery(originalFileName);
// Find the ID of the existing track in the database.
var existingTrackId = _session.Query<TrackData, DefaultSearchIndex>()
.Where(t => t.Query == escapedFileName)
.Select(t => t.Id);
if (existingTrackId != null)
{
track.Id = existingTrackId;
_session.Store(track);
_session.SaveChanges();
}
Finally, #2: what is track? Was it loaded via session.Load or session.Query? If so, that's not going to work, and it's causing your problem. If track is loaded from the database, you'll need to create a new object and save that:
var escapedFileName = Util.EscapeDatabaseQuery(originalFileName);
// Find the ID of the existing track in the database.
var existingTrackId = _session.Query<TrackData, DefaultSearchIndex>()
.Where(t => t.Query == escapedFileName)
.Select(t => t.Id);
if (existingTrackId != null)
{
var newTrack = new Track(...);
newTrack.Id = existingTrackId;
_session.Store(newTrack);
_session.SaveChanges();
}
This means you already have a different object in the session with the same id. The fix for me was to use a new session.

How to get an object from a _ref

I apologize if this is a stupid/newb question, but when a Rally query result is returned with a _ref (using the Javascript SDK 1.32), is there a way to directly get the object associated with the _ref?
I see that I can use getRefFromTypeAndObjectId to get the type and the object ID, and then query on that type and object ID to get the object, however I wondered if there was something like getObjectFromRef or some other such way to more directly get back the object associated with the reference.
Excellent question. The getRallyObject method on RallyDataSource should do what you need.
var ref = '/defect/12345.js';
rallyDataSource.getRallyObject(ref, function(result) {
//got it
var name = result.Name;
}, function(response) {
//oh noes... errors
var errors = response.Errors;
});
In SDK 2.0 you use the load method of a data model to read a specific object. Check out this example: http://developer.help.rallydev.com/apps/2.0p5/doc/#!/guide/appsdk_20_data_models