Parse - Delete another user as super admin from iOS app - ios

I use back4app for my app, I would like to delete another user (not authorised user on this device).
The app throws this:
[Error]: User cannot be deleted unless they have been authenticated. (Code: 206, Version: 1.19.1)
which make sense to me if I am not a super admin of the product. But in case I have super admin rights I would like to remove a user from the system completely.
Is there any solution for this purpose? I've tried to find some function from Parse.Cloud code.
The idea was to create cloud code and execute it form the iOS device by calling smth like this:
PFCloud.callFunctionInBackground("deleteUserAsSuperAdmin",
withParameters: user id param here)
{ success, error) -> Void in
}
I have not found such a solution and for me it's a bit difficult to write such code in a right way using cloud code, for sure if this is an option.

You will have to create a cloud code function for that, and use useMasterKey option to delete the user. Something like:
Parse.Cloud.define('deleteUser', async ({ user, params: { userIdToDelete } }) => {
if (user) {
const query = new Parse.Query(Parse.Role);
query.equalTo('name', 'admin');
query.equalTo('users', user);
const count = await query.count({ useMasterKey: true });
if (count === 1) {
const userToDelete = new Parse.User();
userToDelete = userIdToDelete;
return userToDelete.destroy({ useMasterKey: true });
}
}
throw new Error('Not an admin');
});

Related

How can I access a Teams user's email address?

I'm trying to build a Microsoft Teams integration for an app, but I'm having some trouble getting a user's email address.
I used the Microsoft Teams extension for VS Code to scaffold a basic app. I'm using the BotFramework v4 (NodeJS) on my server. I'm able to receive requests from Teams and respond to them as well.
To get an user's email address, I am using the TeamsInfo.getMember(context, id) method, where the id is obtained from context.activity.from object. Unfortunately, calling this method results in a RestError: Unknown with a status code of 400.
I'm not sure what I'm missing here. My app is registered with the Azure Active Directory and has the User.Read.All permission. Am I missing something here?
Any help would be appreciated!
For some context, I'm trying to build a Messaging Extension Action Command.
Code:
import {
TurnContext,
TeamsActivityHandler,
CardFactory,
MessagingExtensionAction,
TeamsInfo,
} from 'botbuilder';
export default class TeamsMessagingExtensionsActionBot extends TeamsActivityHandler {
constructor() {
super();
}
// #ts-ignore
handleTeamsMessagingExtensionSubmitAction(
context: TurnContext,
action: MessagingExtensionAction,
) {
switch (action.commandId) {
case 'someCommand':
return handleCommand(context, action);
default:
throw new Error('NotImplemented');
}
}
}
async function handleCommand(
context: TurnContext,
action: MessagingExtensionAction,
) {
const card = CardFactory.heroCard(
'Some Command',
'We have received your command!',
);
const user = await TeamsInfo.getMember(context, context.activity.from.id);
console.log('User:', user);
const attachment = {
contentType: card.contentType,
content: card.content,
preview: card,
};
return {
composeExtension: {
type: 'result',
attachmentLayout: 'list',
attachments: [attachment],
},
};
}
This is the error I get when calling TeamsInfo.getMember(): JSON

Getting email id value null as response during apple-authentication

I'm implementing apple-authentication in react native using expo-apple-authentication package.
Below is the code which I'm calling on button's onPress.
async handleSocialLogin() {
const { mutate, BB, onSuccess, navigation } = this.props;
try {
const result = await AppleAuthentication.signInAsync({
requestedScopes: [
AppleAuthentication.AppleAuthenticationScope.FULL_NAME,
AppleAuthentication.AppleAuthenticationScope.EMAIL,
],
});
Alert.alert(JSON.stringify(result))
// signed in
} catch (e) {
Alert.alert(e)
if (e.code === 'ERR_CANCELED') {
// handle that the user canceled the sign-in flow
} else {
// handle other errors
}
}
}
It should return me authentication-token, Full_Name and Email which I requested in scope but It is giving me null for Full_Name and Email.
As per the documentation:
requestedScopes (AppleAuthenticationScope[]) (optional) - Array of user information scopes to which your app is requesting access. Note that the user can choose to deny your app access to any scope at the time of logging in. You will still need to handle null values for any scopes you request. Additionally, note that the requested scopes will only be provided to you the first time each user signs into your app; in subsequent requests they will be null.
You have probably already logged in once and didn't catch the logs. Subsequent log in will result in this data being null

Atomic update of Realtime Database from Google Cloud Functions

I use Google Cloud Functions to create an API endpoint for my users to interact with the Realtime Database.
The problem I have is that I'm not sure how the code works. I have a helper function doSomething that I need to call only once, but I have a suspicion that there are cases where it can be called twice or possibly more (when multiple users call the API at the same time and the update operation hasn't been processed by the DB yet). Is it possible? Does it mean I need to use a transaction method? Thank you!
DB structure
{
somePath: {
someSubPath: null
}
}
Google Cloud Functions code
const functions = require('firebase-functions')
const admin = require('firebase-admin')
const cors = require('cors')({origin: true});
admin.initializeApp(functions.config().firebase)
// API ENDPOINT
exports.test = functions.https.onRequest((req, res) => {
cors(req, res, () => {
admin.database().ref('/somePath/someSubPath').once('value')
.then(snapshot => {
const value = snapshot.val()
if (value) return res.status(400).send({ message: 'doSomethingAlreadyCalled' })
doSomething()
const updates = { '/somePath/someSubPath': true }
return admin.database().ref().update(updates)
.then(() => res.status(200).send({ message: 'OK' }))
})
.catch(error => res.status(400).send({ message: 'updateError' }))
})
})
// HELPERS
const doSomething = () => {
// needs to be called only once
}
I believe you were downvoted due to the above pseudocode not making complete sense and there being no log or output of what your code is actually doing in your question. Not having a complete picture makes it hard for us to help you.
Just Going from your structure in the question, your actual code could be calling twice due to function hoisting. Whenever I have this issue, I’ll go back to the api documentation and try to restructure my code from rereading.
HTH

parse swift add new user to existing role

Can some one just confirm that in order to add a user to a existing role the role needs to have public read & write access ?
as this seems to be the only way i can get it to work?
Code to create the Role (Working Fine)
let roleACL = PFACL()
roleACL.setPublicReadAccess(true)
//roleACL.setPublicWriteAccess(true)
let role = PFRole(name: "ClubName", acl:roleACL)
role.saveInBackground()
Code to add user to said Role (Works If write access set to public)
let QueryRole = PFRole.query()
QueryRole!.whereKey("name", equalTo: "ClubName")
QueryRole!.getFirstObjectInBackgroundWithBlock({ (roleObject: PFObject?, error: NSError?) -> Void in
if error == nil
{
let roleToAddUser = roleObject as! PFRole
roleToAddUser.users.addObject(user)
roleToAddUser.saveInBackground()
//print(roleObject)
}
else
{
print(error)
//print(roleObject)
}
})
the above code works but as i said only when the public write access to the role has been set true.
this is driving me crazy now
also IF the role is meant to have the public write access doesn't that make it vulnerable to someone changing the role?
if the role shouldn't have public write access then can someone point me in the right direction to get the above code working without setting the role with public write access.
the error i get if there is no public write access on the role is: object not found for update (Code: 101, Version: 1.8.1)
Why not perform all the work in cloud code instead, that will get you around the issue of read/write issue. Here is what I am doing.
Important to note: The code below would not work when the cloud code JDK was set to 'latest', I had to set it to JDK 1.5 and then redepled my cloud code.
Parse.Cloud.afterSave(Parse.User, function(request) {
Parse.Cloud.useMasterKey();
var user = request.object;
if (user.existed()) {
//console.log('object exits');
response.success();
// console.log('********return after save');
return;
}
// set ACL so that it is not public anymore
var acl = new Parse.ACL(user);
acl.setPublicReadAccess(false);
acl.setPublicWriteAccess(false);
user.setACL(acl);
user.save();
//add user to role
var query = new Parse.Query(Parse.Role);
query.equalTo("name", "signedmember");
query.first().then(function(object) {
if (object) {
object.relation("users").add(request.user);
object.save(null, {
success: function(saveObject) {
object.relation("users").add(request.user);
object.save(null, {
success: function(saveObject) {
// The object was saved successfully.
console.log('assigned user to role');
},
error: function(saveObject, error) {
// The save failed.
console.error("Failed creating role with error: " + error.code + ":"+ error.message);
}
});
},
});
}
});
});

Returning multiple Parse classes in one PFQuery?

I currently have my parse classes set up as follows
User - objectid, usename, password, location
Profile - birthday, weight, height, et....
Settings - user app preferences such as "Show my location"
Both profile and settings have a pointer to the user objectid called "user"
Is there anyway I can call a query knowing the Users.objectid that returns both Profile and Settings?
I have played around with includes key and matches query but only get back empty results.
If it isn't possible is there a way to execute a function once both queries have completed? (using getFirstObjectInBackgroundWithBlock)
Any help would greatly be appreciated.
No, but you could hide the combination in a function....
function profileAndSettingsForUser(user) {
var profiles;
var profileQuery = new Parse.Query("Profile");
profileQuery.equalTo("user", user);
return profileQuery.find().then(function(result) {
profiles = result;
settingsQuery = new Parse.Query("Settings");
settingsQuery.equalTo("user", user);
return settingsQuery.find();
}).then(function(settings) {
return profiles.concat(settings);
});
};
You could even locate that function in the cloud, so to hide the combination from the client.
Parse.Cloud.define("profileAndSettingsForUser", function(request, response) {
// we could pass a userId in params, then start by querying for that user
// or, if we know its always the current user who's calling for his own profile and settings...
var user = request.user;
profileAndSettingsForUser(user).then(function(profileAndSettings) {
response.success(profileAndSettings);
}, function(error) {
response.error(error);
});
});

Resources