GraphClientService throws exception when calling 'Any' - azure-active-directory

Given a GUID, I need to know if a user exists in azure active directory.
If I pass the Id of an exisitng user everything is Ok.
If I pass the id for which no user account exists, I get the following exeption:
ServiceException: Code: Request_ResourceNotFound Message: Resource
'02803255-b96e-438a-9123-123' does not exist or one of its queried
reference-property objects are not present.
I know this record doen not exist, as this is what I'm testing, I want false to be returned somehow.
Surely I do not have to catch the exception?
//Simple code:
public bool CheckUserExists(string userId) {
bool exists = false;
//purposefully set this to a string that does not match any user.
userId = "02803255-b96e-438a-9123-123";
var user = _graphServiceClient
.Users
.Request()
.Filter("Id eq '" + userId + "'")
.GetAsync();
//exception thrown on next line.
if (user.Result.Count == 1) {
exists = true;
}

Please try checking if user count is less than or equals 0 condition , instead if count equals 1.
var users = await graphClient.Users.Request().GetAsync();
var exists=true;
try {
var user = _graphServiceClient
.Users
.Request()
.Filter("Id eq '" + userId + "'")
.GetAsync();
if (user.Count <= 0) {
exists = false;
break;
}
}
catch (ServiceException ex) {
exists = false;
}
return exists;
or try with
if (user.Count !=null && user.Count>=0)
Reference:
verify if user account exists in azure active directory -SO
reference
Microsoft.Azure.ActiveDirectory.GraphClient/User

Related

Unable to Assign Role with member.roles.add (id)

I'm trying to make an assignrole command which takes userID and roleID as arguments.
content = message.content.slice(message.content.indexOf(' ')+1)
args = content.split(', ');
const userID = args[0]
const roleID = args[1]
const desiredUser = message.guild.members.cache.get(userID)
const desiredRole = message.guild.roles.cache.get(roleID)
if (desiredUser != undefined){
if (desiredRole != undefined){
usern = desiredUser.user.username
desiredUser.roles.add(roleID).catch(console.error);
message.channel.send(usern + " has been assigned the "+ desiredRole.name +" role")
console.log("added role")
} else {
message.channel.send("role with ID " + roleID + " does not exist")
}
} else {
message.channel.send("user with ID " + userID + " does not exist")
}
The function succeeds at "getting" the correct user and role, and successfully sends the "USER has been assigned the ROLENAME role" message. However, the role itself isn't actually added to the user!
My console throws a DiscordAPIError: Missing Permissions error, but I don't know how to interpret it. The error does not quit the bot, however.
How do I add the role to the user?
It is likely that you are missing the MANAGE_ROLES permission as it is, like the name would suggest, required to manage rules.
https://discord.com/developers/docs/topics/permissions
Here are other possibilities that may be causing the error:
I found these here
It is trying to execute an action on a guild member with a role higher than or equal to your bots highest role.
It is trying to modify or assign a role that is higher than or equal to its highest role.
It is trying to execute a forbidden action on the server owner.

Salesforce APEX method not bulkified

I have written an APEX Class that sends an email when a client is released. There is a method that I thought I had bulkified but I was told it does not. This is because this method calls another function which actually does the actual email creation and that is not bulkified. Can someone guide me as to how the SOQL queries can be taken out of the method?
global class LM_ChangeAccountRT {
private static final Profile sysAdmin = [select id from profile where name='System Administrator'];
#AuraEnabled
public static String resendEmails(List<String> accountIdList) {
String response = null;
try {
//Only send emails if user is either an ARMS Administor or System Administrator
if (System.label.ARMS_Administrator_Profile_Id == userinfo.getProfileId() ||
sysAdmin.Id == userinfo.getProfileId()) {
List<Account> accList = [SELECT Id,Client_Released__c, RecordTypeId,Client_Number__c, Client_Released__c, Email_Sent__c FROM Account WHERE Id IN:accountIdList];
for(Account acc: accList){
if (acc.Client_Number__c != null && acc.Client_Released__c && acc.Email_Sent__c == true) {
sendpdfgenerationEmails(acc); //this is the method thats not bulkified.
acc.Email_Sent__c = false;
response = 'Email Sent';
}else {
response= 'Access Denied';
}
}
update accList;
}
}catch(Exception e) {
System.debug(e.getMessage());
response = 'Error sending emails';
}
return response;
}
public static void sendpdfgenerationEmails(Account acc){
system.debug('start of confirmation card and pdf generation');
//Logic to find which VF template is used to send an email.
list<EmailTemplate> templateId = new list<EmailTemplate>();
string temppartner;
String partner_opt_in_attachment;
boolean sendFCAmail;
List<Dealership_PDF_Generation__c> custsettingdata = Dealership_PDF_Generation__c.getall().values();
System.debug('custom setting size = ' + custsettingdata.size());
// Fetch State
if(acc.Dealership_State__c!=null && acc.Dealership_Partner__c!=null)
{
for(Dealership_PDF_Generation__c tempcustsetting :custsettingdata)
{
if(acc.Dealership_Partner__c == tempcustsetting.Dealership_Partner__c && acc.Dealership_State__c==tempcustsetting.State__c && tempcustsetting.State__c=='WA' && acc.Dealership_State__c=='WA'){
//For WA State
// temppartner= '%' + tempcustsetting.TEMPLATE_Unique_name__c + '%';
temppartner= tempcustsetting.TEMPLATE_Unique_name__c;
if(acc.Dealership_Spiff_Payment__c == '% premium'){
partner_opt_in_attachment=tempcustsetting.opt_in_form_premium__c;
}else{
partner_opt_in_attachment=tempcustsetting.opt_in_form_nonpremium__c;
}
}
else if(acc.Dealership_Partner__c == tempcustsetting.Dealership_Partner__c && acc.Dealership_State__c==tempcustsetting.State__c && tempcustsetting.State__c=='TX' && acc.Dealership_State__c=='TX'){
//For TX State
//temppartner= '%' + tempcustsetting.TEMPLATE_Unique_name__c + '%';
temppartner= tempcustsetting.TEMPLATE_Unique_name__c;
if(acc.Dealership_Spiff_Payment__c == '% premium'){
partner_opt_in_attachment=tempcustsetting.opt_in_form_premium__c;
}else{
partner_opt_in_attachment=tempcustsetting.opt_in_form_nonpremium__c;
}
}
else if(acc.Dealership_Partner__c == tempcustsetting.Dealership_Partner__c && acc.Dealership_State__c!=tempcustsetting.State__c && tempcustsetting.State__c!='TX' && acc.Dealership_State__c!='TX' && acc.Dealership_State__c!='WA' &&tempcustsetting.State__c!='WA' ){
//For Non TX State
//temppartner= '%' + tempcustsetting.TEMPLATE_Unique_name__c + '%';
temppartner= tempcustsetting.TEMPLATE_Unique_name__c;
if(acc.Dealership_Spiff_Payment__c == '% premium'){
partner_opt_in_attachment=tempcustsetting.opt_in_form_premium__c;
}else{
partner_opt_in_attachment=tempcustsetting.opt_in_form_nonpremium__c;
}
system.debug('grabbed template: ' + temppartner);
}
if(acc.Dealership_Partner__c != null && temppartner!=null ){
templateId.add([Select id,DeveloperName from EmailTemplate where DeveloperName = :temppartner]); //This will probably cause governor limit issues. First problem
}
if (partner_opt_in_attachment != null) {
StaticResource sr = [Select s.Name, s.Id, s.Body From StaticResource s where s.Name =: partner_opt_in_attachment]; //'static_resource' is the name of the static resource PDF. This is another SOQL query that will cause problems
Blob tempBlob = sr.Body;
Messaging.EmailFileAttachment efa = new Messaging.EmailFileAttachment();
efa.setBody(tempBlob);
efa.setFileName('Opt-in.pdf');
List<Messaging.EmailFileAttachment> attachments = new List<Messaging.EmailFileAttachment>();
attachments.add(efa);
// add attachment to each email
for (Messaging.SingleEmailMessage email : emails) {
email.setFileAttachments(attachments);
}
}
system.debug('email sent: ' + emails.size());
Messaging.sendEmail(emails);
}
}
}
The reason why I am trying to bulkify this is because I have written a APEX scheduler that calls the resendemails method everyday at 7am to check which records need to have an email sent. I am afraid that if there are more than a 100 clients then it will cause problems and not send the emails. Any suggestions on how I can optimize the sendpdfemailgeenration() method?
Thank you
Yes, you are right - your's resendEmails() method is not bulkified.
Firstly, let me explain you why is that:
SOQL to get Accounts
Loop 1 on List of Account records
Call sendpdfgenerationEmails() method
Retrieve list of Dealership_PDF_Generation__c records
Loop 2 on List of Dealership_PDF_Generation__c records
SOQL to get StaticResources - Very bad! It's inside double loop!
Call Messaging.sendEmail() method - Very bad! It's inside double loop!
Update on List of Account records
You need to remember that:
1. You should never do SOQLs in loops! - Limit 100 SOQLs per transaction
2. You should never call Messaging.sendEmail() in loops! - Limit 10 calls per transaction
Now let me guide you how to refactor this method:
#AuraEnabled
public static String resendEmails(List<String> accountIdList) {
// 1. SOQL for List of Account records
// 2. Retrieve list of Dealership_PDF_Generation__c records
// 3. SOQL for List of StaticResources for all Names from Dealership_PDF_Generation__c records
// 4. Declaration of new List variable for Messaging.SingleEmailMessage objects
// 5. Loop 1 on List of Account records
// 6. Call new "prepareEmailsForAccount()" method, which prepares and returns list of Messaging.SingleEmailMessage objects
// 7. Add returned Messaging.SingleEmailMessage objects to list from point 4
// 8. End of loop 1
// 9. Call "Messaging.sendEmail()" method with list from point 4
// 10. Update on List of Account records
}
With this you will avoid SOQLs and calling Messaging.sendEmail() method in loops.

Google Drive API - File have childrens or not

I get files from google drive, like that. The result of Folders. ok,
I have List result, so I want to find if result(i) have children with application/vnd.google-apps.folder mime type or not.
in the other words, method which checks: if current folder contains children folder returns true. owherwise returns false;
I use it in google App engine.
how can I do that?
public void getAllFiles(String id, Drive service) throws IOException{
String query="'"+id + "'"+ " in parents and trashed=false and mimeType=application/vnd.google-apps.folder'";
FileList files = service.files().list().setQ(query).execute();
List<File> result = new ArrayList<File>();
Files.List request = service.files().list();
do {
result.addAll(files.getItems());
request.setPageToken(files.getNextPageToken());
} while (request.getPageToken() != null && request.getPageToken().length() > 0);
}
I do not want to create additional requests (new children request to each node) to see if it have children or not. something like that:
for (File file : result) {
query = "'" + file.getId() + "'" + " in parents and trashed=false and mimeType='application/vnd.google-apps.folder'";
FileList fileChild = service.files().list().setQ(query).execute();
List<File> res = new ArrayList<File>();
Files.List req = service.files().list();
do {
res.addAll(fileChild.getItems());
req.setPageToken(fileChild.getNextPageToken());
} while (req.getPageToken() != null && req.getPageToken().length() > 0);
RemoteFolder remFolder = new RemoteFolder();
remFolder.setFile(file);
if(res.size()>0){
remFolder.setChildrenable(true);
log.info("folder named "+file.getTitle() + " have children folders count: "+ res.size());
}
folderList.add(remFolder);
}
I want to optimize my code.
You have to make another request for each node. If you want to avoid too many calls use memcached.

Using Parse, how do I set a column unique or at least check if it exists first?

I have a table of 'words', and what I want to do is, if a user uses that word, insert it into the table. But, if it already exists, update the count on that word.
I don't see a way to actually set columns as unique..
That said, how do I avoid the race condition:
t1 - user1 checks if 'Love' is used. NO
t2 - user2 checks if 'Love' is used. NO
t3 - user1 adds 'Love'
t4 - user2 adds 'Love'
I do not want this to be in the database twice. Anyway to accomplish this in Parse?
To avoid race conditions, you should make the column/field unique. Do that in the database that you use with with Parse (if you use mongoDB with your parse server, then here's a link for mongoDB for example - https://docs.mongodb.com/manual/core/index-unique/). Then in CloudCode - try to create a new word object and store it. If the word already exists, the store will fail and then you can use a query to find the existing word and increment instead.
You can use the 'exists' query to check for objects which have the key set:
var Word = Parse.Object.extend("words");
var query = new Parse.Query(Word);
query.exists("Love");
query.find({
success: function(results) {
if(results.length === 0){
// Insert a new word object with the 'Love' key set to 1
var newWord = new Word();
newWord.set('Love', 1);
newWord.save(null, {
success: function(newWord) {
alert('New object created with objectId: ' + newWord.id);
},
error: function(newWord, error) {
alert('Failed to create new object, with error code: ' + error.description);
}
});
} else {
// Get the existing word object and increment its 'Love' key by 1
var existingWord = results[0];
var currCount = existingWord.get('Love');
existingWord.set('Love', currCount + 1);
existingWord.save(null, {
success: function(existingWord) {
alert('Existing object saved with objectId: ' + newWord.id);
},
error: function(existingWord, error) {
alert('Failed to save existing object, with error code: ' + error.description);
}
});
}
},
error: function(error) {
alert("Error: " + error.code + " " + error.message);
}
});
With regard to preventing race conditions, you could handle this with Parse Cloud Code. You could have a Cloud Function which handles the input of the data and it should handle the requests sequentially.

Audit of what records a given user can see in SalesForce.com

I am trying to determine a way to audit which records a given user can see by;
Object Type
Record Type
Count of records
Ideally would also be able to see which fields for each object/record type the user can see.
We will need to repeat this often and for different users and in different orgs, so would like to avoid manually determining this.
My first thought was to create an app using the partner WSDL, but would like to ask if there are any easier approaches or perhaps existing solutions.
Thanks all
I think that you can follow the documentation to solve it, using a query similar to this one:
SELECT RecordId
FROM UserRecordAccess
WHERE UserId = [single ID]
AND RecordId = [single ID] //or Record IN [list of IDs]
AND HasReadAccess = true
The following query returns the records for which a queried user has
read access to.
In addition, you should add limit 1 and get from record metadata the object type,record type, and so on.
I ended up using the below (C# using the Partner WSDL) to get an idea of what kinds of objects the user had visibility into.
Just a quick'n'dirty utility for my own use (read - not prod code);
var service = new SforceService();
var result = service.login("UserName", "Password");
service.Url = result.serverUrl;
service.SessionHeaderValue = new SessionHeader { sessionId = result.sessionId };
var queryResult = service.describeGlobal();
int total = queryResult.sobjects.Count();
int batcheSize = 100;
var batches = Math.Ceiling(total / (double)batcheSize);
using (var output = new StreamWriter(#"C:\test\sfdcAccess.txt", false))
{
for (int batch = 0; batch < batches; batch++)
{
var toQuery =
queryResult.sobjects.Skip(batch * batcheSize).Take(batcheSize).Select(x => x.name).ToArray();
var batchResult = service.describeSObjects(toQuery);
foreach (var x in batchResult)
{
if (!x.queryable)
{
Console.WriteLine("{0} is not queryable", x.name);
continue;
}
var test = service.query(string.Format("SELECT Id FROM {0} limit 100", x.name));
if(test == null || test.records == null)
{
Console.WriteLine("{0}:null records", x.name);
continue;
}
foreach (var record in test.records)
{
output.WriteLine("{0}\t{1}",x.name, record.Id);
}
Console.WriteLine("{0}:\t{1} records(0)", x.name, test.size);
}
}
output.Flush();
}

Resources