I am trying to integrate Quickblox into my app, my user IDs are matching Quickblox user IDs, so when I'm on a some user's page, I know his ID and I need to retrieve this user from Quickblox database, set him as an opponent and initialize Chat with this opponent. Unfortunately, I can not retrieve this through QBUsers userWithID call (recieving errors in delegate). Could you, please, privide a simple example of retrieving user by ID and setting him as opponent. Thank you!
Here is a solution:
1) Connect your user to QuickBlox user. QuickBlox user has externalUserID field, so set your system user id to this field
QBUUser *user = [QBUUser user];
user.login = #"iostest3355";
user.password = #"iostest3355";
user.externalUserID = 46732; // you system user id
[QBUsers signUp:user delegate:self];
2) Next, you have your system user id, you need to retrieve QuickBlox user
[QBUsers userWithExternalID:46732 delegate:self];
- (void)completedWithResult:(Result *)result{
if(result.success && [result isKindOfClass:QBUUserResult.class]){
QBUUserResult *res = (QBUUserResult *)result;
int qbUserID = res.user.ID;
}
}
3) Use qbUserID to chatting
Related
How can I get the list of Twilio members of a channel, on my Laravel backend? I am using Programmable Chat API of Twilio. I tried using ChannelInstance members method or property, but I am not getting the list of members correctly. Is there a way to do this, from inside Laravel? I need it to be consumed by the iOS app on the other side (iOS app being the client). Ios app asks from Laravel the list of users that the user has chatted to, so I first get all channels:
$params = $request->all();
$username = $params["username"];
$unl = strlen($username);
$twilio = new Client($this->sid, $this->authToken);
// Get all user's channels
$ucs = $twilio->chat->v2->services($this->serviceId)
->users($username)
->userChannels
->read(50);
// Try to find members of each channel
foreach ($ucs as $uc) {
$channel = $twilio->chat->v2->services($this->serviceId)
->channels($uc->channelSid)
->fetch();
print_r($channel->toArray());
}
in the print_r - ed array, I have uniqueName and friendlyName, which are concatenated two participants of the channel. But I would prefer to just have two objects, or two strings that would tell me which are the members participants of that channel. Is there a way to do this?
Twilio developer evangelist here.
In this case you're just reading the information about the channel. Instead, you should fetch the members from the channel.
foreach ($ucs as $uc) {
$channel_members = $twilio->chat->v2->services($this->serviceId)
->channels($uc->channelSid)
->members
->read([], 20);
print_r($channel_members);
}
To get members, I needed to do this:
$ucs = $twilio->chat->v2->services($this->serviceId)
->users($username)
->userChannels
->read(50);
foreach ($ucs as $uc) {
$channel_members = $twilio->chat->v2->services($this->serviceId)
->channels($uc->channelSid)
->members
->read([], 20);
foreach ($channel_members as $record) {
print($record->sid . "\n");
}
}
I want to provide two pieces of functionality to an MVC 5 (OWIN) website for the Authentication Cookies:-
Show cookie expiration for each user
Force a login, even if a cookie is not expired
Once a user is logged in, the cookie and its contained claims are on their browser.
I've managed to get the cookie information, although it does this on every visit to the server.
As far as forcing a login is concerned, I either have to update the cookie (not possible if the user isn't interacting with the site) or look for a user by name on each login.
My answer is below - if anyone has a better one, please let me know
In the OWIN start-up class I added a custom identity validation method. An administrator can set a field in the Identity Database to force a login next time around. A downside is a hit on the database each time a user visits a web page.
If a user must login this time, Forced Login flag is cleared, the user logged off and redirected to the Home page which then goes to the login page (and redirect back to the Home page after login).
This code also retrieves the cookie information for display in the list of users that an administrator can view.
private static Task MyCustomValidateIdentity(CookieValidateIdentityContext context)
{
var db = ApplicationDbContext.Create();
var userName = context.Identity.GetUserName();
var user = (from u in db.Users where u.UserName == userName select u).FirstOrDefault();
if (user != null)
{
if (user.ForceLoginNextTime)
{
user.ForceLoginNextTime = false;
db.SaveChanges();
context.OwinContext.Authentication.SignOut(context.Options.AuthenticationType);
context.Response.Redirect("/Home");
}
}
var i = (from u in __userInfo where u.userName == userName select u).FirstOrDefault();
if (i == null)
{
i = new UserInfo();
__userInfo.Add(i);
}
i.userName = userName;
i.CookieIssuedUtc = context.Properties.IssuedUtc;
i.CookieExpiresUtc = context.Properties.ExpiresUtc;
i.CookieIsPersistent = context.Properties.IsPersistent;
return Task.FromResult(0);
}
I have an Objective-C application (https://github.com/NBICreator/NBICreator) with a privileged helper tool.
I have a few different privileged tasks the helper will need to perform during one build, and I want to have the user authenticate only once to perform those tasks.
The authorization works, but I can't seem to reuse the session in the helper. The user always have to authenticate for every step, even if I supply the exact same right to the Security Server and use the same AuthenticationRef.
I have read the docs and tested the pre-authentication methods in the main app first, and tried printing out (and retaining the auth session in the helper as well). But nothing I've tried have yet to work successfully.
I need som help figuring out why the Security Server feel the need to reauthenticate.
The code on GitHub in the Master Branch is current, and what I'm trying and testing by changing things back and forth. With that code, the user have to authenticate each time I call a helper function, even if I use the same authentication right.
This is what the right looks like in the authorization database:
class = rule;
created = "470329367.933364";
"default-prompt" = {
"" = "NBICreator is trying to start an Imagr workflow.";
};
identifier = "com.github.NBICreator";
modified = "470329367.933364";
requirement = "identifier \"com.github.NBICreator\" and anchor apple generic and certificate leaf[subject.CN] = \"Mac Developer: Erik Berglund (BXUF2UUW7E)\" and certificate 1[field.1.2.840.113635.100.6.2.1] /* exists */";
rule = (
"authenticate-admin"
);
version = 0;
This is where I define the right: https://github.com/NBICreator/NBICreator/blob/master/NBICreator/Helper/NBCHelperAuthorization.m#L36-L43
NSStringFromSelector(#selector(authorizeWorkflowImagr:withReply:)) : #{
kCommandKeyAuthRightName : #"com.github.NBICreator.workflowImagr",
kCommandKeyAuthRightDefault : #kAuthorizationRuleAuthenticateAsAdmin,
kCommandKeyAuthRightDesc : NSLocalizedString(
#"NBICreator is trying to start an Imagr workflow.",
#"prompt shown when user is required to authorize to add a user"
)
},
And this is where I check if the user is authenticated:
https://github.com/NBICreator/NBICreator/blob/master/NBICreator/Helper/NBCHelperAuthorization.m#L222-L253
+ (NSError *)checkAuthorization:(NSData *)authData command:(SEL)command authRef:(AuthorizationRef)authRef {
#pragma unused(authData)
NSError * error;
OSStatus err = 0;
AuthorizationItem oneRight = { NULL, 0, NULL, 0 };
AuthorizationRights rights = { 1, &oneRight };
oneRight.name = [#"com.github.NBICreator.workflowImagr" UTF8String];
err = AuthorizationCopyRights(
authRef,
&rights,
NULL,
kAuthorizationFlagExtendRights | kAuthorizationFlagInteractionAllowed,
NULL
);
if ( err != errAuthorizationSuccess ) {
NSString *message = CFBridgingRelease(SecCopyErrorMessageString(err, NULL));
error = [NSError errorWithDomain:[[NSProcessInfo processInfo] processName] code:err userInfo:#{ NSLocalizedDescriptionKey : message }];
}
return error;
}
As you can see there, I'm testing by setting a hardcoded right name to try and resue that right to the Security Server.
I'm stumped right now, and can't seem to find a way forward. Hoping someone here might know where to look.
I found the answer in how I set up the right in the rights database.
I was using the default code from the Apple example EvenBetterAuthorizationExample for creating and using the rights. But that only points to this documentation for the different rights to use.
None of those were helping me with authenticatin once and the having the helper be authenticated the next time I request authentication for the same right.
After some digging and looking into the actual rules in the authorization database I found a way to copy the rule that AuthenticateWithPrivileges uses, that works by authenticating for 5 minutes until requiring re-authentication.
So, I changed my code for creating my custom right from this:
NSStringFromSelector(#selector(addUsersToVolumeAtPath:userShortName:userPassword:authorization:withReply:)) : #{
kCommandKeyAuthRightName : NBCAuthorizationRightAddUsers,
kCommandKeyAuthRightDefault : #kAuthorizationRuleAuthenticateAsAdmin,
kCommandKeyAuthRightDesc : NSLocalizedString(
#"NBICreator is trying to add a user.",
#"prompt shown when user is required to authorize to add a user"
)
},
To this:
NSStringFromSelector(#selector(addUsersToVolumeAtPath:userShortName:userPassword:authorization:withReply:)) : #{
kCommandKeyAuthRightName : NBCAuthorizationRightAddUsers,
kCommandKeyAuthRightDefault : #{
#"class": #"user",
#"group": #"admin",
#"timeout": #(300),
#"version": #(1),
},
kCommandKeyAuthRightDesc : NSLocalizedString(
#"NBICreator is trying to add a user.",
#"prompt shown when user is required to authorize to add a user"
)
},
So, instead of using #kAuthorizationRuleAuthenticateAsAdmin as the RightDefault, i passed in this dict:
#{
#"class": #"user",
#"group": #"admin",
#"timeout": #(300),
#"version": #(1),
},
After that, my helper can request authorization from the user, and then I can reuse that session for the same right during 5 minutes without asking the user again.
I am making a social app using Objective-C and Parse. I am trying to write cloud code to increment likes (which is part of the secured User class) upon a button click. This is what I have as of now:
Cloud Code
Parse.Cloud.define("incrementLikes", function(request, response) {
Parse.Cloud.useMasterKey();
var user = new Parse.Object("User");
user.userName = request.params.userName;
user.increment("profilePictureLikes");
});
profilePictureLikes is the name of the database row within the User class that is a number.
Objective-C
- (void)incrementLikes {
[PFCloud callFunctionInBackground:#"incrementLikes" withParameters:#{#"userName": self.user.username}];
}
self.user is the PFUser whose profile is being viewed.
This code generates the following error, and does not increment the likes:
[Error]: success/error was not called (Code: 141, Version: 1.6.2)
Well, the error is because you aren't calling the response handler in the cloud code but you have a number of other issues:
Not calling the response handler
Creating a new user instead of querying to find the existing user
Passing the user name instead of the user object id (see here)
Not saving the user after updating it
I would like to increment a counter for a given currentUser's key.
I'm using the incrementKey method, however, the following code is not working*:
[currentUser incrementKey:#"likes" byAmount:[NSNumber numberWithInt:1]];
[currentUser saveInBackground];
It doesn't raise an error, but it doesn't update the database either.
Supposing that current User is a PFUser instance, if it is not the current logged user [PFUser currentUser], probably you should have the right ACL on that user row.
Try to set the current ACL field for that user for read and write, eg:
// set user acl
PFACL* userACL = [PFACL ACLWithUser:currentUser];
[userACL setPublicReadAccess:YES];
[userACL setPublicWriteAccess:YES];
[currentUser setACL:userACL];
[currentUser saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
// check if any save error occurs
}];
Honestly, i suggest to don't use the above approach for security reason, especially on the User table. Instead you could try to make a custom function Cloud code side, using the Parse.Cloud.useMasterKey() and so increment the user with something like
.
..
...
Parse.Cloud.useMasterKey();
...
// retrieve the user with passed user object id from client
var userId =request.params.myUserId;
var user = new Parse.User();
user.set("objectId", userId);
user.fetch().then(function(concreteUser){
concreteUser.increment("likes", 1);
concreteUser.save().then(function(incrementedUser){
response.success();
},function(saveError){
response.error(saveError);
});
},function(error){
response.error(error);
});
Hope it helps