Azure mobile services scripts - javascript

I am very new to using server scripts, and I am sure this is a very simple answer but I have not found what I am looking for anywhere yet. I am using azure mobile services to retrieve and input user information, and want to prevent a user from seeing other users id numbers.
to read the data, the program makes the following http request
"GET http://Servicename.net/tables/TableName?$top=1&$orderby=__createdAt%20desc&$filter=id+eq+'"+id+"' HTTP/1.1"
the id is determined by the account the user is currently on, but I do not want the user to be able to remove the id, making a request such as the following and retrieving the entire table along with the other users id
"GET http://Servicename.net/tables/TableName HTTP/1.1"
What I would like to do is use server side scripts, specifically the read operation script, to make sure the request has a id associated with it, and only the data with that specific id is returned.
I have tried the following:
function read(query, user, request) {
if(request.parameter.id != null){
request.execute();
}
}
This does not work, so my question is how do I retrieve the id number from the http request and use it within the script? I hope my question was clear, and any help is greatly appreciated!

I would refer you to my series on Azure Mobile Apps: https://shellmonger.com/30-days-of-azure-mobile-apps-the-table-of-contents/
In particular, look at Day 6 - Personal Tables. This shows how to restrict the data being returned to the user by the authenticated user ID.

If you want to retrieve the user id in the table operations in Mobile Service. You can use the second the argument user, which is always a user object that represents the user that submitted the request.
And you can find a code snippet to explain the usage at https://azure.microsoft.com/en-us/documentation/articles/mobile-services-how-to-use-server-scripts/#table-scripts:
function insert(item, user, request) {
if (item.userId !== user.userId) {
request.respond(statusCodes.FORBIDDEN,
'You may only insert records with your userId.');
} else {
request.execute();
}
}
Please refer to Work with a JavaScript backend mobile service for more info about Mobile Services in Node.js.
Additionally, now we have suggested to use Mobile Apps instead of Mobile Services. You can refer to https://azure.microsoft.com/en-us/documentation/articles/app-service-mobile-value-prop-migration-from-mobile-services/ for details.

Related

What is the safest and most effective approach when you need to pass data to another component through navigation in Angular8?

I´m currently developing an application based on user authentication where each user can register a student-campus as a teacher and currently, I'm on a feature where I have two routes:
Route 1: It has a Datagrid where I'm listing all of the student campuses that I've already created and each row has an edit button that navigates to "Route 2" and the purpose of that is to edit the already created student campus.
Route 2: It has a form with all the necessary fields to create a student-campus.
As you can see I need to pass the student-campus ID to fetch data in the ngOnInit to fill the fields and be able to edit the above-mentioned, so I have several options in consideration:
Option 1: Pass ID in the URL.
this.router.navigate(['planteles/registrar', idPlantel]);
https://myapplication/planteles/registrar/1
Option 2: Pass ID in the URL with queryParams.
this.router.navigate(['planteles/registrar'], { queryParams: { ID: idPlantel } });
https://myapplication/planteles/registrar?ID=1
Option 3: Pass ID in the state object of navigation extras.
this.router.navigate(['planteles/registrar'], { state: { id: idPlantel } });
Option 4: Shared service and BehaviorSubject to subscribe to data.
I owe you the code
I'm able to use any of these but I have a problem with each one of them.
I can't use Option 1 and Option 2 because the ID cannot be changed by the teacher because that gives him the possibility to fetch the student-campus data of another teacher and edit it, so it isn't safe.
The problem with option 3 and option 4 is when I refresh the page the state is lost.
Currently, I have a workaround with option 3 which is to redirect the user to the previous page if the state is undefined but I don't like that solution. I'd like to persist data if the user reloads the page without using LocalStorage.
Thanks in advance, all help or contribution is well appreciated.
Option 1 is the correct option here (and the way you will find most sites in the real world are implemented... including this one we're on now). The problem is your approach to web security, and what you need to fix is your backend. You're approaching web security as though front end security is real, it's not. Web security exists on your backend. Users should not be able to fetch or view or manipulate data that does not belong to them, and this must be enforced by your backend.
A high level example of how this might work: some secure authentication token should be granted when the user logs in, then this authentication token should be attached to each request. The API then uses this token to check which user is making the request and ensures they have the proper permissions. If they do not (as in the case of the user editing their URL param to some ID they do not have permissions for) or if there is no token, the API should return a 401 or 403 response and the front end should handle it appropriately (ie sending them back to list, or showing an error page, whatever you decide)... how to issue this token, make it secure, and make use of it is an entirely separate topic beyond the scope of this answer.
In any of the options, I could open my dev tools, and view any API requests being made, and change the ID's and use that to view or manipulate other people's data without any effort at all. So options 3 / 4 are barely more "safe" than 1 or 2. As none of these are safe without properly implemented backend security.
Front end "security" exists only as user experience. Me and you are both using the same URL to view this page, but we see different options and buttons, like you can edit or delete your post and accept answers, while I can't, but I can edit or delete my answer etc. This isn't for true security purposes, SO's servers enforce who can and can't take what actions. It's just showing me and you the UI that reflects our different permissions, ie, its all just UX.
There's another way too, which is defined in Angular docs itself.
NavigationExtras
Example:
let navigationExtras: NavigationExtras = {
queryParams: {
"firstname": "Nic",
"lastname": "Raboy"
}
};
this.router.navigate(["page2"], navigationExtras);

Using mod_scorm_insert_scorm_tracks

I'm interfacing my App with Moodle and I'm successfully calling mod_scorm_get_scorm_sco_tracks and mod_scorm_get_scorm_attempt_count via Ajax (XMLHttpRequest) for a given user (userid).
Now I want my App to push some SCORM tracks back to Moodle.
So I'm trying to use mod_scorm_insert_scorm_tracks but with no success.
The problem is that this method does not take an userid parameter, so I don't understand how to use it (and if I try to add userid to input params I get an invalid parameter exception).
I had kind of success (no error message) by sending this:
scoid=206&attempt=2&tracks[0][element]=cmi.completion_status&tracks[0][value]=completed&tracks[1][element]=cmi.interactions.0.id&tracks[1][value]=multiplechoice_page_1_1&tracks[2][element]=cmi.interactions.0.learner_response&tracks[2][value]=White&tracks[3][element]=cmi.interactions.0.result&tracks[3][value]=correct&tracks[4][element]=cmi.interactions.0.description&tracks[4][value]=Which%20color%20was%20Garibaldi's%20white%20horse%3F&tracks[5][element]=cmi.interactions.1.id&tracks[5][value]=hotobject_page_2_1&tracks[6][element]=cmi.interactions.1.learner_response&tracks[6][value]=butterfly&tracks[7][element]=cmi.interactions.1.result&tracks[7][value]=incorrect&tracks[8][element]=cmi.interactions.1.description&tracks[8][value]=Where%20is%20the%20fish%3F&tracks[9][element]=cmi.score.max&tracks[9][value]=2&tracks[10][element]=cmi.score.raw&tracks[10][value]=1&tracks[11][element]=cmi.score.scaled&tracks[11][value]=0.5&tracks[12][element]=cmi.session_time&tracks[12][value]=PT0H0M15S&tracks[13][element]=timemodified&tracks[13][value]=1480947821&tracks[14][element]=userid&tracks[14][value]=26&tracks[15][element]=scoid&tracks[15][value]=206&wstoken=69f2471506c4c49ff47cd0de0c4c9f01&wsfunction=mod_scorm_insert_scorm_tracks&moodlewsrestformat=json
However, since I cannot specify the user those data belongs to, my user's attempts does not update (as predictable).
This is the response from Moodle:
{"trackids":[44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59],"warnings":[]}
I've tried inserting the userid info into traks (tracks[14][element]=userid&tracks[14][value]=26) but still no luck.
So, the questions are:
Which user are those tracks inserted to considering that I'm calling it from an external app, so there's no logged in user in Moodle?
How can I specify that those tracks are for a give userid?
the user identity comes from the HTTP Context of a full login into Moodle: you can't provide SCORM tracking info on behalf of any user but the actual logged-in user.
More at:
https://github.com/moodle/moodle/blob/d33c67bc4744f901bf389607cfbbb683ef1c7d80/mod/scorm/classes/external.php#L451
https://github.com/moodle/moodle/blob/0b8e0c374f89ca20e5b9e7c9370761810811edc6/lib/externallib.php#L481
HTH,
Matteo

Automating posts from "company" for the Facebook page of said "company"

I put company in between quotations because my question relates to our Rugby team page but in Facebook it acts like a company page.
I am currently rebuilding my teams website (BBRFC Celtic) and I am going to add a user login system which will have coaches and admin staff with different levels of authority.
Sometimes due to weather conditions, events, or other things a training time may be changed or a match canceled or other various events. When these happen we normally send emails through a mailing list or sms or post on Facebook by hand.
What I want to have is a little bot of some kind that runs behind the scenes of the server and when coaches or admins change something it allows them to make an automated post to Facebook.
Something like after changing a trainings time it asking Would you like this to be posted to the facebook page and groups?.
I have been unsuccessful in finding out how I would go about writing the code for this. Our webpage will use php but maybe this can be done with javascript?
Do I need to get a key to post something as if I were the page?
How about to the different groups we have?
Any pointers would be helpful since I am totally stuck not really programmatically but more conceptually, I do not know if this is even possible.
I will explain the steps you need to accomplish your goal for a website. Note that the documentation also explains the case of a mobile application and others. I used the facebook API before, however, not to manage groups/pages, hence, this post will only point you in the right direction. I will explain how to post a message as being the admin of the page, not sure if you meant facebook pages or groups.
First, the user need to log in with facebook. This can be done using Javascript and the facebook API. Their documentation provides a very detailed explanation with code examples etc. Note that i will explain for the case of Javascript, however, this could be done in php, ...
Once the user is logged in, you can retrieve all kind of information about the user, his pages, etc. I would suggest to retrieve the pages the user is managing, then check if your "company" is part of this list (note that you will need the manage_pages permission). If this is the case, the user can post a message in name of the page.
/* Retrieve pages the user is managing */
FB.api(
"/me/accounts",
function (response) {
if (response && !response.error) {
/* handle the result */
}
}
);
Now response is an object containing multiple fields (see the official documentation).
Now, if the user is an administrator of your page, you can post a message as a Page.
/* Post a message as a Page, use your page id */
FB.api(
"/{page-id}/feed",
"POST",
{
"message": "The match has been delayed to ..."
},
function (response) {
if (response && !response.error) {
/* handle the result */
}
}
);
If successful, the ID of the post will be returned as part of a JSON response (see doc)

SignalR Content Specific Notifications

I am using SignalR for notifications in my web site but i couldn't find a way to send notifications according to the page/content.
Let me explain in details.
Assume that, there is a page for showing a record from database (for example a blog post).
So there is only one page for showing posts as it should be.
And every post has a like counter which i want to update via signalr notifications, if another user clicks like button. Until here, it is very easy to accomplish.
This page contains a javascript code block like below
var notify = $.connection.notificationHub;
notify.client.updatePostLikeCount = function (likeCount) {
$("#likeCount").text(likeCount);
};
And this function triggered from server-side like below (it is in another class instead of Hub class)
var context = GlobalHost.ConnectionManager.GetHubContext<NotificationHub>();
context.Clients.User(user.Id).updatePostLikeCount(likeCount);
But a user might open more than one post; so if a notification is sent from server-side all opened tabs receive this notification and update its counter.
I looked for .Caller method but it is not available in IHubContext interface which GetHubContext() returns and couldn't find another way.
To summarize, i want to send notifications to users who had opened the post which user liked.
EDIT: After sending question i got an idea. Continue sending notification as being and filtering according to the content at client side. It is not very good but i think it will work with charms.

JS SDK - Posting to a page wall

I am using the JavaScript SDK. I have an application that has publishing permissions and after certain actions are taken a post will be made to the logged in users wall like so:
FB.getLoginStatus(function (response) {
//we are authorized
if (response.status == "connected") {
var name = "Post name";
var body = "Post body";
var caption = "The caption";
var description = "The description";
var link = "http://www.facebook.com/mypage";
FB.api('/me/feed', 'post', { message:body,caption:caption,link:link,name:name,description:description}, function (response) {
console.log(response);
});
}
});
What I would like to able to do is post to a specific Facebook Page after a post is successfully made to the users page. Is there a way to securely pre-authorize an application to do that? Is this possible with the JavaScript SDK, or at all? I did some looking around and havn't found a definite answer. I'm looking at the FB documentation but find it to be a bit spotty in places. Could anyone tell me if this is possible? Any help or advice would be very much appreciated, thanks much!
Edit: my mistake, I should have supplied more info. Here is what I am trying to do:
var body = "The body";
var caption = "The caption";
FB.api("mypageid/feed", "post", { message: body, caption: caption }, function (response) {
console.log(response);
});
I am getting the error "this api call requires a valid app_id" however my page id is valid. When I call FB.init() I am passing my app id and it works for the first post to the logged in users feed.
Edit:
I have made the change the Igy suggested. Now I am getting the error:""(#200) The user has not granted the application the permission to automatically publish feed stories""
Now, as I said I am trying to post to a Facebook page. I have logged into the account that owns the page and I have gone to the app and clicked allow for the following permissions:
email,user_photos,publish_stream
When I am logged in with the account that owns the page and check my status:
FB.getLoginStatus(function (response) {
console.log(response);
});
I get "connected". Am I doing this incorrectly? Do I have to do more than just authorize with the account that owns the page? Is there a way to set allow permissions for a page? I did a little digging but couldn't find an answer.
Edit :
Ok, now what is happening is IF I am logged into the account that owns the page the post will be made to the page. If I am logged in with another account I get an id back as a response to the API call but it doesn't seem to be a valid object id. For instance I just got this back:
id: 499973616681852_507724422573438
if I go to http://graph.facebook.com/499973616681852_507724422573438
I get an "unsupported get request" graph api exception, which suggest that id returned is not valid. I feel like I am close here but I am missing something. Any advice would be appreciated, thanks again to all who responded.
edit: removed the link to the page,that was left in unintentionally.
It's good practice to try getting it to work in the graph explorer first. Note that on the top right you can select which application to run under. I just made a post to your page using /PAGE_ID/feed and it worked fine. You'll need the publish_stream permission. If you can get it to work in the graph explorer you'll know it's possible to get it to work in the JS SDK and you've just made some sort of syntax error.
Also note there is an open high priority bug report on some calls to the graph returning "unsupported get request". So even though the id you are getting back is invalid, check the page itself to see if the posts are appearing.
I also noticed that the user itself is getting the same error. Try https://graph.facebook.com/507724422573438. Is this a test user for your app? Might be worth trying this as a real user if so.
Since you want to post to the page as the page itself, you'll need to authenticate as a page and then use that access token when making graph api calls. I am not sure if you'll be able to then use this access token for any user, or only users that are allowed to manage the page. It would be best for you to use the graph explorer to do some experiments to find out.

Categories