I am using Google Plus integration where I have to fetch circles of user.
I am passing the Url:https://www.googleapis.com/plus/v1/people/Your_User_Id/people/visible?key=APP_Key.
I am getting the response as:
{ error = { code = 403; errors = ( { domain = global; message = Forbidden; reason = forbidden; } ); message = Forbidden; }; }
What kind of permission do I need for This request?
You can only do this for the signed in user - so the "Your_User_Id" should always be "me". It's fine to pass the app key as well, but you must be making the call with an oAuth 2.0 token from a user who has signed in to your app. You can see all the details here: https://developers.google.com/+/mobile/ios/people#retrieve_a_collection_of_people
Basically you'd need to implement sign-in, if you haven't already, then you can use the plusService in the GPPSignIn sharedInstance:
GTLQueryPlus *query =
[GTLQueryPlus queryForPeopleListWithUserId:#"me"
collection:kGTLPlusCollectionVisible];
[[[GPPSignIn sharedInstance] plusService] executeQuery:query
completionHandler:^(GTLServiceTicket *ticket,
GTLPlusPeopleFeed *peopleFeed,
NSError *error) {
if (error) {
GTMLoggerError(#"Error: %#", error);
} else {
// Get an array of people from GTLPlusPeopleFeed
NSArray* peopleList = [peopleFeed.items retain];
}
}];
That is calling the URL that you're giving there.
Related
I want to mock the facebook login block, but test failed, the block wasn't invoked. Please help me solve the problem.
//Test
-(void)testFacebookLogin
{
id mockManager = OCMClassMock([FBSDKLoginManager class]);
OCMStub([[mockManager alloc]init]).andReturn(mockManager);
FBSDKLoginManagerLoginResult *res = [[FBSDKLoginManagerLoginResult alloc]initWithToken:nil isCancelled:YES grantedPermissions:nil declinedPermissions:nil];
NSError* err = [NSError errorWithDomain:#"This is an error" code:NSURLErrorNotConnectedToInternet userInfo:nil];
[[mockManager stub]logInWithReadPermissions:OCMOCK_ANY fromViewController:OCMOCK_ANY handler:[OCMArg invokeBlockWithArgs:res,err,nil]];
__block BOOL invoke;
[LoginHelper facebookLoginWithLoginResult:^(BOOL success, NSError *error, id result) {
invoke = YES;
}];
XCTAssertTrue(invoke);
}
//LoginHelper.m
+(void)facebookLoginWithLoginResult:(LoginResult)loginResult
{
UIViewController* currentRootViewController = AppDelegateHelperSingleton.globalDelegate.window.rootViewController;
FBSDKLoginManager* loginManager = [[FBSDKLoginManager alloc]init];
loginManager.loginBehavior = FBSDKLoginBehaviorNative;
NSArray* permissions = #[#"email",#"public_profile",#"user_birthday"];
//facebook login with read permisssions
[loginManager logInWithReadPermissions:permissions fromViewController:currentRootViewController handler:^(FBSDKLoginManagerLoginResult *result, NSError *error)
{
loginResult(result, error);
}];
}
OCMStub([[mockManager alloc]init]).andReturn(mockManager);
That's not going to work. The problem you face is that your production code has a dependency which it locks down:
FBSDKLoginManager* loginManager = [[FBSDKLoginManager alloc]init];
In order for your test code to supply a "test double" (something that stands in for the real thing), you need a way to inject it.
There are various approaches to Dependency Injection. You can make it an initializer argument. You can make it a property. If you want the FBSDKLoginManager to be short-lived, you can make it a method argument.
For more, see How to Use Dependency Injection to Make Your Code Testable
I am building an iphone app with a rails-backed server. I am using the devise gem. I am having trouble with user logins on the client-side (everything works on the web side, and even in the terminal with CURL).
On Xcode I can create a user and I can login. After logging in
(and recieving this in the log: "User logged in!")
I am then pushed to the indexViewController- and here I receive an error that the posts don't load. The reason is because on the post_controller.rb I have a
before_filter :authenticate_user!
preventing the posts from loading. The problem is, that the auth_token which was generated upon a successful login, is not being stored and passed along to the different views. So then, in the log I get:
'You need to sign in before continuing.'
As if the first part of what I just explained never happened..
In the indexViewController viewDidLoad method I have:
if (![[APIClient sharedClient] isAuthorized]) {
LoginViewController *loginViewController = [[LoginViewController alloc] init];
[self.navigationController pushViewController:loginViewController animated:YES];
}
isAuthorized is a BOOL in the APIClient that checks if userID>0
In the user model this is the code that creates a login session
+ (void)loginUser:(NSString *)signature
email:(NSString *)email
password:(NSString *)password
block:(void (^)(User *user))block
{
NSDictionary *parameters = #{ #"user": #{
// #"signature": signature,
#"email": email,
#"password": password
}
};
[[APIClient sharedClient] postPath:#"/users/sign_in" parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
User *user = [[User alloc] initWithDictionary:responseObject];
if (block) {
block(user);
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
if (block) {
block(nil);
}
}];
}
I am guessing it is here that I am missing some auth_token implementation? Since it is generated automatically by devise- I am not sure how to tell xcode to remember it. The auth_token is a string that has a column in the user table on the db. Should I add auth_token as param to the dictionary that holds the user's email and username? Or how do I get the token to persist?
Any ideas would be helpful.
Not being intimately familiar with AFNetworking this is a stab in the dark, but presumably you need to set the token for subsequent requests. Assuming APIClient is a wrapper you've added around AFHTTPClient, here's a quick idea of what that might look like after reviewing the code here - AFHTTPClient.
+ (void)loginUser:(NSString *)signature
email:(NSString *)email
password:(NSString *)password
block:(void (^)(User *user))block {
NSDictionary *parameters = #{ #"user": #{ #"email": email,
#"password": password } };
[[APIClient sharedClient] postPath:#"/users/sign_in"
parameters:parameters
success:^(AFHTTPRequestOperation *operation, id responseObject) {
User *user = [[User alloc] initWithDictionary:responseObject];
// retrieve and save auth token
NSString *token = [responseObject objectForKey:#"authToken"];
[[APIClient sharedClient] setAuthorizationHeaderWithToken:token];
if (block) {
block(user);
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
if (block) {
block(nil);
}
}];
}
Let me make this clear. I am NOT using the Facebook SDK. I'm using iOS SDK's Social.framework, and ACAccountStore to access Facebook accounts, and post with it/them.
I use the same code to post on Twitter. It works 100%. But for some reason regardless of what I do for Facebook integration, I get a "400" error when I try to post.
My method is:
ACAccountStore *account = [[ACAccountStore alloc] init];
ACAccountType *facebookAccountType = [account accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook];
// Specify App ID and permissions
NSDictionary *options = #{ ACFacebookAppIdKey: #"MY_APP_ID",ACFacebookPermissionsKey: #[#"publish_stream", #"publish_actions"],ACFacebookAudienceKey: ACFacebookAudienceFriends };
[account requestAccessToAccountsWithType:facebookAccountType options:options
completion:^(BOOL granted, NSError *error)
{
if (granted == YES)
{
NSDictionary *parameters = #{#"message": string999};
NSURL *feedURL = [NSURL URLWithString:#"https://graph.facebook.com/me/feed"];
SLRequest *feedRequest = [SLRequest
requestForServiceType:SLServiceTypeFacebook
requestMethod:SLRequestMethodPOST
URL:feedURL
parameters:parameters];
acct.accountType = facebookAccountType;
// Post the request
[feedRequest setAccount:acct];
// Block handler to manage the response
[feedRequest performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error)
{
if (granted && error == nil) {
} else {
NSLog(#"Facebook response, HTTP response: %i %#", [urlResponse statusCode], [error description]);
[self closeShareMenu];
}
}];
}
}
I don't know where I'm going wrong! It's so annoying! I've set up my app correctly in Facebook Developers and all! Please help -_-'
Following up to the chat session held between #fguchelaar and yours truly yesterday; I was able to ascertain the following solution for this issue.
Add the following in your iOS completion handler:
NSString *temp = [[NSString alloc] initWithData:data encoding: NSUTF8StringEncoding];
NSLog(temp);
//'data' is your 'responseData' (or another object name) that you declare in your completion handler.
This will allow you to see the exact cause of the issue printed to the Debug Console. Now depending on the issue presented, you'll need to grab a Facebook account from the Array of Accounts generated when you call this handler in the iPhone SDK. Not at any prior stage whatsoever, as the Access Token will likely expire and give you this '400' error.
In my case; the error printed was: error:{'400' A valid access token is required… which vastly annoyed me as my prior method to access and check the current Twitter account was working perfectly. And my theory was that it should work just as well for Facebook. Why should the access token be instantaneously revoked if I'm grabbing the account a split second before?
The way I solved my issue (depending on the reason for your error the answer can vary) was to use a for loop to check the newly created array of accounts, with the sole purpose of finding the account there with the same identifier string as the one I saved into NSData/NSKeyedArchiver.
for(ACAccount *a in arrayOfAccounts) {
if([a.identifier isEqualToString:storedAccount.identifier]) {
//set the account to be used
accountToBeUsed = a;
//don't forget to break the For loop once you have your result.
break;
} else {
//This else{} block is not strictly necessary, but here you could set an account if no account was found with a matching identifier.
}
}
For it to work, it's recommended to declare an ACAccount object in your View Controller's .h file, add a #property and #synthesize it, so it can be assigned within the for loop and used after the break; statement.
This effectively solved my whole issue with the '400' error. It was inexplicably frustrating for about six hours of my day, so I hope that my explanation helps anybody who happens to stumble across this issue, and my question here on Stack Overflow :)
Regards,
cocotutch
i want to store some data in "EverNote" through our app either (image or text or both).
I googled, i got some guidance like EverNote SDK and i got the EverNoteCounter Sample also(When i run this, when i click getCount button it shows an alert message "Could not authenticate").
I generated the developer token also.
But i unable to create the consumerKey,consumerSecret. And also i did not find how to store our data to evernote from our app.
I got some links like this one
but when i go through that link it says( HTTP method GET is not supported by this URL)
I able to authenticate with the EVERNOTE and i able to get the number of notebooks in that Account.
I am using sqllite in my app. i am using one folder for images. Sqllite have the images links info.
How to store the data.
I used the following code to authenticate and to get the count
- (IBAction)retrieveUserNameAndNoteCount:(id)sender
{
// Create local reference to shared session singleton
EvernoteSession *session = [EvernoteSession sharedSession];
[session authenticateWithViewController:self completionHandler:^(NSError *error) {
// Authentication response is handled in this block
if (error || !session.isAuthenticated) {
// Either we couldn't authenticate or something else went wrong - inform the user
if (error) {
NSLog(#"Error authenticating with Evernote service: %#", error);
}
if (!session.isAuthenticated) {
NSLog(#"User could not be authenticated.");
}
UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:#"Error"
message:#"Could not authenticate"
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil] autorelease];
[alert show];
} else {
// We're authenticated!
EvernoteUserStore *userStore = [EvernoteUserStore userStore];
// Retrieve the authenticated user as an EDAMUser instance
[userStore getUserWithSuccess:^(EDAMUser *user) {
// Set usernameField (UILabel) text value to username
[usernameField setText:[user username]];
// Retrieve total note count and display it
[self countAllNotesAndSetTextField];
} failure:^(NSError *error) {
NSLog(#"Error retrieving authenticated user: %#", error);
}];
}
}];
}
- (void)countAllNotesAndSetTextField
{
// Allow access to this variable within the block context below (using __block keyword)
__block int noteCount = 0;
EvernoteNoteStore *noteStore = [EvernoteNoteStore noteStore];
[noteStore listNotebooksWithSuccess:^(NSArray *notebooks) {
for (EDAMNotebook *notebook in notebooks) {
if ([notebook guid]) {
EDAMNoteFilter *filter = [[EDAMNoteFilter alloc] init];
[filter setNotebookGuid:[notebook guid]];
[noteStore findNoteCountsWithFilter:filter withTrash:NO success:^(EDAMNoteCollectionCounts *counts) {
if (counts) {
// Get note count for the current notebook and add it to the displayed total
NSNumber *notebookCount = (NSNumber *)[[counts notebookCounts] objectForKey:[notebook guid]];
noteCount = noteCount + [notebookCount intValue];
NSString *noteCountString = [NSString stringWithFormat:#"%d", noteCount];
[noteCountField setText:noteCountString];
}
} failure:^(NSError *error) {
NSLog(#"Error while retrieving note counts: %#", error);
}];
}
}
} failure:^(NSError *error) {
NSLog(#"Error while retrieving notebooks: %#", error);
}];
}
Please suggest me the links or give me the guidance
Thanks a lot in advance
Developer token is to be used when you only need to access your own account. To get a consumer key/secret, go here : http://dev.evernote.com/documentation/cloud/ .
If you are using iOS, https://github.com/evernote/evernote-sdk-ios has a sample app that you can use once you have a consumer key and secret.
In general, there is a lot of information on dev.evernote.com.
All SDKs are located at https://github.com/evernote
Getting started guide for iOS : http://blog.evernote.com/tech/2012/05/24/evernote-sdk-integration-ios/
Did you solved it? If not, i did the following to get it work:
download and include sdk
get consumerKey and secret (if you want to access notes too, then
instead of basic you should request for full access, http://dev.evernote.com/documentation/cloud/ top right corner)
Add the URLType entry in info.plist ("Modify your application's main
plist file" chapter https://github.com/evernote/evernote-sdk-ios)
Copy the session init code (filled with consumer key and secret, the hostname should be left unchanged) and implement the two application delegate specific code
An (on-screen) viewcontroller should be passed on authenticating the user to authenticateWithViewController method, f.e. the appdelegate's rootViewController
Study this pages to understand the model hierarchy used by Evernote:
http://dev.evernote.com/documentation/cloud/chapters/data_structure.php
http://dev.evernote.com/documentation/reference/Types.html
Image could be stored as EDAMResource (Resource) in the field data and text as EDAMNote (Note) in the field content. Both is handled by Evernote SDK's EvernoteNoteStore object.
I have a Facebook SSO working perfectly on my app, using last release of Facebook Objective-C SDK.
I need to ask an extra permission inside the app if user do "something". I don't need to ask that permission if user gave it to me before, so, I guess, in Facebook SDK there should be a method
-(BOOL) checkPermission:(NSString*) permission;
so I can use it like this:
if( [facebook checkPermission:#"email"] ) {
Is there a way to do this?
This question is a bit old but you can now check what permissions the active session has without making a graph request. Here is how it's done in the HelloFacebookSample :
if ([FBSession.activeSession.permissions indexOfObject:#"publish_actions"] == NSNotFound) {
// permission does not exist
} else {
// permission exists
}
Just replace "publish_actions" with "email".
SDK not providing direct method for checking specific permissions but you can check if user granted permission to your application by checking permissions connection of user object in Graph API
GET https://graph.facebook.com/me/permissions
Same can be achieved with FQL query on permissions table
SELECT email FROM permissions WHERE uid = me()
IMPORTANT: This seems to be true for an older version of the Facebook SDK (for example 3.9.0). In 3.15.0 it doesn't work this way anymore. You should use [session.permissions] as Raphaël Agneau says in his answer.
You have to use the following method, because [FBSession activeSession].permissions seems to return the permissions you requested, not the real ones.
[FBRequestConnection startWithGraphPath:#"/me/permissions"
completionHandler:^(FBRequestConnection *c, id result, NSError *error) {
if (!error) {
NSDictionary *permissions= [(NSArray *)[result data] objectAtIndex:0];
if (![permissions objectForKey:#"publish_actions"]) {
// Ok, continue with your logic
} else {
// Permission not found, maybe request it (see below)
}
} else {
// Treat error
}
}];
See here for more info:
https://developers.facebook.com/docs/facebook-login/ios/v2.0#permissions-checking
If the permission is not found you may want to request it this way:
[session requestNewPublishPermissions:PERMISSIONS_YOU_WANT
defaultAudience:FBSessionDefaultAudienceFriends
completionHandler:^(FBSession* session, NSError* error) {
// Try again the /me/permissions above
}];
Here's my code for FBSDK 4.2.0 for checking permissions. The string that's passed in is the name of the permission, e.g. "publish_actions"
- (void) checkForPermission:(NSString *)permission granted:(void (^)(void))sBlock denied:(void (^)(void))fBlock {
if ([FBSDKAccessToken currentAccessToken]) {
[[[FBSDKGraphRequest alloc] initWithGraphPath:#"me/permissions" parameters:nil] startWithCompletionHandler:^(FBSDKGraphRequestConnection *connection, id result, NSError *error) {
BOOL hasPermission = NO;
if (!error) {
NSArray *permissions = [result objectForKey:#"data"];
for (NSDictionary *dict in permissions) {
if ([[dict objectForKey:#"permission"] isEqualToString:permission]) {
if ([[dict objectForKey:#"status"] isEqualToString:#"granted"]) {
hasPermission = YES;
}
}
}
}
if (hasPermission) {
(sBlock) ? sBlock() : sBlock;
} else {
(fBlock) ? fBlock() : fBlock;
}
}];
} else {
(fBlock) ? fBlock() : fBlock;
}
}
For the SDK 4+ you have these 2 ways of getting the permissions:
[[FBSDKAccessToken currentAccessToken] hasGranted:#"user_photos"]
or
[[[FBSDKAccessToken currentAccessToken] permissions] containsObject:#"user_photos"]