Error creating SalesForce users LICENSE_LIMIT_EXCEEDED:License Limit Exceeded - api

I want to create 5-6 SalesForce users programmatically in one go by using SOAP API. I am using Partner API and I have a Developer edition sandbox. I am retrieving users information from a database table and then by using API I want to create these 5-6 users at once. I can create one user however after creating another user it is throwing error LICENSE_LIMIT_EXCEEDED:License Limit Exceeded.
This is snapshot of my code which retrieves users information from database and then creates a user programmatically:
SObject user = new SObject();
user.setType("User");
while (rs.next()) {
user.setField("Alias", rs.getString("Alias"));
user.setField("Email", rs.getString("Email"));
user.setField("EmailEncodingKey", rs.getString("EmailEncodingKey"));
user.setField("LanguageLocaleKey", "En_US");
user.setField("LastName", rs.getString("LastName"));
user.setField("LocaleSidKey", rs.getString("LocaleSidKey"));
user.setField("TimeZoneSidKey", "America/Los_Angeles");
user.setField("Username", rs.getString("Username"));
user.setField("UserPermissionsCallCenterAutoLogin", "false");
user.setField("UserPermissionsMarketingUser", "false");
user.setField("UserPermissionsOfflineUser", "false");
user.setField("ProfileId", connection.getUserInfo().getProfileId());
SaveResult[] results = connection.create(new SObject[] { user });
System.out.println("Created user: " + results[0].getId());
if (results[0].isSuccess())
out.println("Created user: " + results[0].getId());
else
out.println("Error: " + results[0].getErrors()[0].getStatusCode() +
":" + results[0].getErrors()[0].getMessage());
}
QueryResult queryResults = connection
.query("SELECT Id, Name from User "
+ "ORDER BY CreatedDate DESC LIMIT 5");
if (queryResults.getSize() > 0) {
for (SObject s : queryResults.getRecords()) {
out.println("Id: " + s.getField("Id") + " - Name: "
+ s.getField("Name"));
}
}
Here I can create one user however after creating one user it is throwing error LICENSE_LIMIT_EXCEEDED:License Limit Exceeded.
These are the number of licenses available:
I can see that licenses remaining for SalesForce is 0. However, I just want to create some users that don't necessarily have to be SalesForce users. It can be any type of users which just should be able to login to my org. When I am trying to create some different type of users such as 'Chatter Free' which has 5000 licences by using user.setField("UserType", "CsnOnly") it is giving error INVALID_FIELD_FOR_INSERT_UPDATE:Unable to create/update fields: UserType
These are users in my SalesForce:
How to solve this problem? I just want to create some users from database which can then login to SalesForce. Its not necessary that they should be administrators. They can have minimum privileges but they should be able to login to SalesForce.

In a developer org, you won't be able to have more than two active users with Salesforce licenses. In order to create a user with a Chatter Free license, you should only need to assign them the profile of Chatter Free User - it will automatically set their license correctly based on the profile assigned to them (the UserType field is not editable).
Edit: to obtain the Chatter Free User's profile Id without hardcoding it (as it may change from org to org), you'll have to query it. I modified your code to include this query, as well as reworked it so that only a single callout to PartnerConnection.create is made (just a suggestion, as it will save overhead on your SOAP callouts):
QueryResult profileQuery = connection.query("select Id from Profile where Name = 'Chatter Free User' limit 1");
SObject chatterFreeProfile;
if ( profileQuery.getSize() > 0 ) {
chatterFreeProfile = profileQuery.getRecords()[0];
}
ArrayList<SObject> users = new ArrayList<SObject>();
while (rs.next()) {
SObject user = new SObject();
user.setType("User");
user.setField("Alias", rs.getString("Alias"));
user.setField("Email", rs.getString("Email"));
user.setField("EmailEncodingKey", rs.getString("EmailEncodingKey"));
user.setField("LanguageLocaleKey", "En_US");
user.setField("LastName", rs.getString("LastName"));
user.setField("LocaleSidKey", rs.getString("LocaleSidKey"));
user.setField("TimeZoneSidKey", "America/Los_Angeles");
user.setField("Username", rs.getString("Username"));
user.setField("UserPermissionsCallCenterAutoLogin", "false");
user.setField("UserPermissionsMarketingUser", "false");
user.setField("UserPermissionsOfflineUser", "false");
if ( chatterFreeProfile != null )
user.setField("ProfileId", chatterFreeProfile.getField("Id"));
else
user.setField("ProfileId", connection.getUserInfo().getProfileId());
users.add(user);
}
if ( users.size() > 0 ) {
SaveResult[] results = connection.create(users.toArray(new SObject[users.size()]));
for ( int i = 0; i < saveResults.length; i++ ) {
if (results[i].isSuccess())
out.println("Created user: " + results[i].getId());
else
out.println("Error: " + results[i].getErrors()[0].getStatusCode() + ":" + results[i].getErrors()[0].getMessage());
}
}
QueryResult queryResults = connection.query("SELECT Id, Name from User ORDER BY CreatedDate DESC LIMIT 5");
if ( queryResults.getSize() > 0 ) {
for ( SObject s : queryResults.getRecords() ) {
out.println("Id: " + s.getField("Id") + " - Name: " + s.getField("Name"));
}
}

You need to set ProfileId to a Profile associated with an available License Type, in your case to a Profile on the Chatter Free, Salesforce Platform, or one of your other available license types. Each Profile is tied to a particular UserLicense record, for example:
'SFDC' : Full Salesforce license
'CSN_User' : Chatter Free license
'AUL' : Salesforce Platform license
(To see more, do a Query All on the UserLicense object).
So you'll need to query for Profile records on available license types, and then associate this to your new users, e.g.
QueryResult profileQuery = connection.query(
"SELECT Id FROM Profile "
+ "WHERE UserLicense.Name = 'Chatter Free' LIMIT 1"
);
SObject chatterFreeProfile;
if ( profileQuery.getSize() > 0 ) {
chatterFreeProfile = profileQuery.getRecords()[0];
user.setField("ProfileId", chatterFreeProfile.getField("Id"));
}

Related

Fetch users liked Instagram-images after API update 2016

Hey!
After Instagram updated its API on the 1. june 2016 we are not able to get out JavaScript Instagram implementation to work. We inspected the client-setup and noticed that it has been put in Sandbox mode. When trying to resubmit then none of the valid user cases did fit, and we understood that they had removed our rights to fetch other peoples content through the account without getting permission from each individual owner.
As far as i understood, the new parameter "scope" needs to be set to "public_content" and this requires the users permission.
So at the moment the solution below only fetches the users own pictures that is self-liked. Before we also got other peoples images that the user had liked.
So, do anyone know how to fetch liked content of an account post 1. june 2016?
Does getting a Instagram Business account help you for displaying other peoples content?
Here is the code example with an additional filter on the hashtags.
If anyone got a better idea of how to filter on hashtags and liked content at the same time please let me know :)
$.fn.instagramFeedInit = function()
{
if(!$('#instagram-content').length)
{
return;
}
var container = $('#instagram-content');
var tag = container.data('hashtag');
var image_display_count = container.data('image-count');
var access_token = [INSERT_TOKEN_OR_SOUTH_PARK_REFERENCE_HERE];
$.ajax({
type:'GET',
url: 'https://api.instagram.com/v1/users/self/media/liked?access_token=' + access_token + '&callback=callback&count=99999',
jsonp: 'callback',
dataType: 'jsonp',
success: function(response) {
var container = $('#instagram-content');
var i = 0;
// Loops through images
$(response.data).each(function(i, el){
// Check that it has correct tag
if(jQuery.inArray(tag, el.tags) !== -1)
{
var imageTitle = el.caption.text;
var image = el.images.low_resolution.url;
var refImage = el.images.standard_resolution.url;
if (el.type === 'video') {
var videoLink = el.videos.standard_resolution.url;
container.append('<a class="lightbox instagramimage mfp-iframe" title="' + imageTitle + '" href="' + videoLink + '" ><img src="' + image + '"></a>');
}
else {
container.append('<a class="lightbox instagramimage" title="' + imageTitle + '" href="' + refImage + '" ><img src="' + image + '" class="img-responsive"></a>');
}
i++;
// If we have reached maximum display images
if(i == image_display_count) return false;
}
});
}
});
};
Be aware that if you are in Sandbox mode, only post from authorized Sandboxed users will appear in any api requests. Regardless of whether you have the public_access scope.
Note: you need to add scope=public_access to your authorization URL now. It's no longer included by default
E.g A and B are both sandbox users C is not.
A likes a post from C.
The liked media endpoint for A will not include the post from C. He is invisible to your sandbox app
A then goes an likes a post from B
The liked media endpoint for A will now include the post from B as he is visible to your sandbox app

Google API for getting maximum number of licenses in a Google Apps domain

I have a Google Apps Script function used for setting up accounts for new employees in our Google Apps domain.
The first thing it does is makes calls to the Google Admin Settings API and retrieves the currentNumberOfUsers and maximumNumberOfUsers, so it can see if there are available seats (otherwise a subsequent step where the user is created using the Admin SDK Directory API would fail).
It's been working fine until recently when our domain had to migrate from Postini to Google Vault for email archiving.
Before the migration, when creating a Google Apps user using the Admin SDK Directory API, it would increment the currentNumberOfUsers by 1 and the new user account user would automatically have access to all Google Apps services.
Now after the migration, when creating a Google Apps user, they aren't automatically assigned a "license," so I modified my script to use the Enterprise License Manager API and now it assigns a "Google-Apps-For-Business" license. That works fine.
However, the currentNumberOfUsers is now different from the number of assigned licenses, and "Google-Apps-For-Business" is only one of several different types of licenses available.
I can get the current number of assigned "Google-Apps-For-Business" licenses by running this:
var currentXml = AdminLicenseManager.LicenseAssignments.listForProductAndSku('Google-Apps', 'Google-Apps-For-Business', 'domain.com', {maxResults: 1000});
var current = currentXml.items.toString().match(/\/sku\/Google-Apps-For-Business\/user\//g).length;
But the number that produces is different from currentNumberOfUsers.
All I really need to do now is get the maximum number of owned "Google-Apps-For-Business" licenses so the new employee setup script can determine whether there are any available.
I checked the API Reference documentation for the following APIs but...
Enterprise License Manager API → Doesn't have a method for getting the maximum or available number of licenses.
Google Admin Settings API → Doesn't deal with licenses, only "users."
Admin SDK Directory API User resource → Doesn't deal with licenses.
Google Apps Reseller API → This API seems to have what I need, but it's only for Reseller accounts.
I know I can program my new employee setup script to just have a try/catch seeing if it would be able to create the user and assign the license, and end the script execution gracefully if it can't, but that doesn't seem efficient.
Also, part of the old script was that if there were less than X seats available, it would email me a heads-up to order more. I can program a loop that attempts to repeatedly create dummy users and assign them licenses and count the number of times it can do that before it fails, then delete all the dummy users, but, once again, that's not efficient at all.
Any ideas?
Update 3/11/2020: Since the Admin Settings API had shut down a few years ago I've been using the Enterprise License Manager API to get the current number of used licenses, like this:
function getCurrentNumberOfUsedGoogleLicenses(skuId) {
var success = false, error = null, count = 0;
var adminEmail = 'admin#domain.com';
var gSuiteDomain = adminEmail.split('#')[1];
// for more information on the domain-wide delegation:
// https://developers.google.com/identity/protocols/OAuth2ServiceAccount#delegatingauthority
// the getDomainWideDelegationService() function uses this:
// https://github.com/gsuitedevs/apps-script-oauth2
var service = getDomainWideDelegationService('EnterpriseLicenseManager: ', 'https://www.googleapis.com/auth/apps.licensing', adminEmail);
if (skuId == 'Google-Apps-Unlimited') var productId = 'Google-Apps';
else return { success: success, error: "Unsupported skuId", count: count };
var requestBody = {};
requestBody.headers = {'Authorization': 'Bearer ' + service.getAccessToken()};
requestBody.method = "GET";
requestBody.muteHttpExceptions = false;
var data, pageToken, pageTokenString;
var maxAttempts = 5;
var currentAttempts = 0;
var pauseBetweenAttemptsSeconds = 3;
loopThroughPages:
do {
if (typeof pageToken === 'undefined') pageTokenString = "";
else pageTokenString = "&pageToken=" + encodeURIComponent(pageToken);
var url = 'https://www.googleapis.com/apps/licensing/v1/product/' + productId + '/sku/' + skuId + '/users?maxResults=1000&customerId=' + gSuiteDomain + pageTokenString;
try {
currentAttempts++;
var response = UrlFetchApp.fetch(url, requestBody);
var result = JSON.parse(response.getContentText());
if (result.items) {
var licenseAssignments = result.items;
var licenseAssignmentsString = '';
for (var i = 0; i < licenseAssignments.length; i++) {
licenseAssignmentsString += JSON.stringify(licenseAssignments[i]);
}
if (skuId == 'Google-Apps-Unlimited') count += licenseAssignmentsString.match(/\/sku\/Google-Apps-Unlimited\/user\//g).length;
currentAttempts = 0; // reset currentAttempts before the next page
}
} catch(e) {
error = "Error: " + e.message;
if (currentAttempts >= maxAttempts) {
error = 'Exceeded ' + maxAttempts + ' attempts to get license count: ' + error;
break loopThroughPages;
}
} // end of try catch
if (result) pageToken = result.nextPageToken;
} while (pageToken);
if (!error) success = true;
return { success: success, error: error, count: count };
}
However, there still does not appear to be a way to get the maximum number available to the domain using this API.
Use CustomerUsageReports.
jay0lee is kind enough to provide the GAM source code in Python. I crudely modified the doGetCustomerInfo() function into Apps Script thusly:
function getNumberOfLicenses() {
var tryDate = new Date();
var dateString = tryDate.getFullYear().toString() + "-" + (tryDate.getMonth() + 1).toString() + "-" + tryDate.getDate().toString();
while (true) {
try {
var response = AdminReports.CustomerUsageReports.get(dateString,{parameters : "accounts:gsuite_basic_total_licenses,accounts:gsuite_basic_used_licenses"});
break;
} catch(e) {
//Logger.log(e.warnings.toString());
tryDate.setDate(tryDate.getDate()-1);
dateString = tryDate.getFullYear().toString() + "-" + (tryDate.getMonth() + 1).toString() + "-" + tryDate.getDate().toString();
continue;
}
};
var availLicenseCount = response.usageReports[0].parameters[0].intValue;
var usedLicenseCount = response.usageReports[0].parameters[1].intValue;
Logger.log("Available licenses:" + availLicenseCount.toString());
Logger.log("Used licenses:" + usedLicenseCount.toString());
return availLicenseCount;
}
I would recommend exploring GAM which is a tool that gives command line access to the administration functions of your domain.

Obj C - I can't find the user location via the Facebook Graph API

I'm building a iOS app with a Facebook login via the Facebook Graph API. So far the login works perfectly and I receive the users profile. I'm trying to display the location (place of residence, not his current location) of the user but can't seem to find it in the user data I get when the user is logging in.
This is the JSON I receive:
{
email = "";
"favorite_athletes" = (
{
id = 308994352528078;
name = "Belgian Falcon F16 Racing Team";
}
);
"first_name" = Bastiaan;
gender = male;
id = 10153090459134040;
"last_name" = Andriessen;
link = "https://www.facebook.com/app_scoped_user_id/10153090459134040/";
locale = "en_US";
name = "Bastiaan Andriessen";
timezone = 1;
"updated_time" = "2014-11-28T13:10:46+0000";
verified = 1;
}
The Facebook Docs says it does send the location with the profile but I as you can see I don't find it in the JSON:
https://developers.facebook.com/docs/reference/ios/current/protocol/FBGraphUser/
Does someone know how I could solve this?

Getting list of nodes for user

I have many 'nt:folder' Nodes created and upon each folder creation, permissions has been granted to different set of users.
Now I need to get list of nodes based on user(with read and write) persmissions.
Using jackrabbit 2.6.0
Partial snippet of user creation and privieges assignement:
User creation
UserManager userManager = ((JackrabbitSession) session).getUserManager();
org.apache.jackrabbit.api.security.user.User user =
(org.apache.jackrabbit.api.security.user.User)userManager.getAuthorizable(userName);
Add entry
javax.jcr.security.Privilege[] privileges = new
javax.jcr.security.Privilege[] {
accessControlManager.privilegeFromName(javax.jcr.security.Privilege.JCR_WRITE)
};
Temporary folder access
Map<String, Value> restrictions = new HashMap<String, Value>();
restrictions.put("rep:nodePath",
valueFactory.createValue(userDbInstance.getUserFilePath(),
PropertyType.PATH)); restrictions.put("rep:glob",
valueFactory.createValue("*"));
accessControlList.addEntry(userPrincipal, privileges, true /*allow or deny */, restrictions);
Adding Node
public Node addNode(String parent, String name, ETNodeTypes type) throws JCRServiceException {
checkSession();
try {
name = Text.escapeIllegalJcrChars(name);
logger.debug("Adding Node: " + parent + " type: " + type + " name(escaped):" + name);
Node node = session.getNode(parent).addNode(name, type.getName());
node.addMixin("rep:AccessControllable");
logger.debug("Node added: " + node.getPath());
return node;
} catch (RepositoryException e) {
e.printStackTrace();
throw new JCRServiceException(e,e.getMessage(),"Unable to create");
}
}
Thanks.
I recently posted on answering a similar question: Using JCR-SQL2 for querying ACLs in a Jackrabbit repository.
This was my example query:
select resource.*, ace.*
from [nt:hierarchyNode] as resource
inner join [rep:ACL] as acl
ON ISCHILDNODE(acl, resource)
inner join [rep:ACE] as ace
ON ISCHILDNODE(ace, acl)
where ace.[rep:principalName] = 'username'

How to email SalesForce users temporary password by using API?

I am using SOAP Partner API and I have a Developer edition. I am creating users by using API. And upon creation of users I want to email these users temporary password which they can use to login to SalesForce.
This is my code:
SaveResult[] results = connection.create(new SObject[] { user });
if (results[0].isSuccess())
{
out.println("Created user: " + results[0].getId());
//connection.setPassword(results[0].getId(), "password");
ResetPasswordResult rpr = connection.resetPassword(results[0].getId());
String result = rpr.getPassword();
System.out.println("The temporary password for user ID " + results[0].getId()
+ " is " + result);
}
else
{
out.println("Error: " + results[0].getErrors()[0].getStatusCode() +
":" + results[0].getErrors()[0].getMessage());
}
This is the output I am getting in console:
The temporary password for user ID 005E0000000MwkZIAS is ucQD2PADs
However, the user is NOT receiving any password. :-(
Thanks,
Wap Rau
If you build & pass an EmailHeader in your soap request you can control what types of emails will get sent from your request.
It looks like you're using WSC, so you can add this call before calling resetPassword, which will enabled emails being sent to users. This should then send the standard reset password email.
connection.setEmailHeader(false, false, true);
use this class to send out an email. include the pwd variable in the string you want to send the user. there's an example that spells everything out
http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_classes_email_outbound.htm