Salesforce APEX get users User License - salesforce

So I am trying to get the current users User License eg. System Administrator or User etc... I have look through here and used other methods however these don't seem to work for me. I was wondering where I could make a start towards this?
The error I get is:
Comparison arguments must be compatible types: Schema.SObjectField, String
From using the following code:
public String getOpps() {
if(Profile.UserLicense.Name === 'Community Customer') {
oppCheck = true;
} else {
oppCheck = false;
}
***loop*** {
code here
}
} else {
more code here
}
return 'nil';
}

These are the license types, I got them from the API guide here thanks to this post.
Standard: user license. This user type also includes Salesforce Platform and Salesforce Platform One user licenses. Label is Standard.
PowerPartner: PRM user whose access is limited because he or she is a partner and typically accesses the application through a partner
portal. Label is Partner.
CSPLitePortal: user whose access is limited because he or she is an organization's customer and accesses the application through
aCustomer Portal. Label is High Volume Portal.
CustomerSuccess: user whose access is limited because he or she is an organization's customer and accesses the application through a
Customer Portal. Label is Customer Portal User.
PowerCustomerSuccess: user whose access is limited because he or she is an organization's customer and accesses the application through
a Customer Portal. Label is Customer Portal Manager. Users with this
license type can view and edit data they directly own or data owned by
or shared with users below them in the Customer Portal role hierarchy.
CsnOnly: user whose access to the application is limited to Chatter. This user type includes Chatter Free and Chatter moderator
users. Label is Chatter Free.
Also, you might have some luck trying:
Profile p = [Select Name from Profile where Id =: userinfo.getProfileid()];
String pname = p.name;
if(pname == 'Community Customer') {
oppCheck = true;
} else {
oppCheck = false;
}

Related

Exception in Site.createExternalUser in Apex RESTclass: Site.ExternalUserCreateException: [That operation is only allowed from within an active site.]

I have a Non-Salesforce Auth System which holds usernames and passwords for a few thousand users. I am willing to migrate these users to Salesforce and give access to these users to my Experience Cloud site. I am developing an apex REST Resource which will take username and password as arguments and create a user with that username and password with a community profile. I am planning to call this API from my Non-Salesforce system and migrate all these users. I am using Site.createExternalUser method in this API. I am getting the exception
Site.ExternalUserCreateException: [That operation is only allowed from within an active site.]
The reason I am using Site.createExternalUser is because I don't want to send the welcome email/reset password email to my users since they already have signed up successfully long ago.
I am open to any alternatives for achiving this.
Below is my code:
#RestResource(urlMapping='/createUser/*')
global with sharing class createUserRestResource {
#HttpPost
global static String doPost(){
Contact con=new Contact();
con.Firstname="First";
con.LastName= "Last";
con.Email="first.last#example.com";
con.AccountId='/Add an account Id here./';
insert con;
usr.Username= "usernameFromRequest#example.com";
usr.Alias= "alias123";
usr.Email= "first.last#example.com";
usr.FirstName= "First";
usr.IsActive= true;
usr.LastName= "Last";
usr.ProfileId='/Community User Profile Id/';
usr.EmailEncodingKey= 'ISO-8859-1';
usr.TimeZoneSidKey= 'America/Los_Angeles';
usr.LocaleSidKey= 'en_US';
usr.LanguageLocaleKey= 'en_US';
usr.ContactId = con.Id;
String userId = Site.createExternalUser(usr, con.AccountId, 'Password#1234', false);
return userId;
}
}
You can suppress sending emails out in whole org (Setup -> Deliverability) or in the Community config there will be way to not send welcome emails (your community -> Workspaces -> Administration -> Emails).
Without running on actual Site I don't think you can pull it off in one go. In theory it's simple, insert contact, then insert user. In practice depends which fields you set on the user. If it's Partner community you might be setting UserRoleId too and that's forbidden. See MIXED DML error. In Customer community you might be safe... until you decide to assign them some permission sets too.
You might need 2 separate endpoints, 1 to create contact, 1 to make user out of it. Or save the contact and then offload user creation to #future/Queueable/something else like that.

Active Directory - Cross Domains

My role on the developer side. I have an application that I am trying check to see if a user has access to a share. In the application, I check the groups on that share. Then I check all the groups the user is in.
In one case, I not able to see the Local group that the users is in both code or the AD in windows
For example:
Domain A\User1 > Domain A\Global Group > Do not see: Domain B\Local Group
But when I look from Domain B I see:
Share > Domain B\Local Group > Domain A\Global Group > Do not see Domain A\User1
Is there some security setting that is not set correctly since I dont see in the windows tool or code.
Update
I have tried the following code. I am still unable to to see Domain B\Local Group.
string account = "{User**Or**Group}";
string domain = "{Domain}";
string dn = ADHelper.GetDistinguishedName(domain, account);
using (var forest = Forest.GetCurrentForest())
{
foreach (Domain domainName in forest.Domains)
{
Console.WriteLine(string.Format("Domain: {0}", domainName.Name));
Console.WriteLine("========================================================");
GetAllGroups(dn, domainName.Name);
domainName.Dispose();
}
}
void GetAllGroups(string dn, string domain)
{
DirectorySearcher ds = new DirectorySearcher(string.Format("GC://{0}", domain));
ds.Filter = String.Format("(&(distinguishedName={0}))", dn);
SearchResult sr = ds.FindOne();
if (sr == null)
return;
DirectoryEntry Diruser = sr.GetDirectoryEntry();
Diruser.RefreshCache(new string[] { "tokenGroups" });
for (int i = 0; i < Diruser.Properties["tokenGroups"].Count; i++)
{
SecurityIdentifier sid = new SecurityIdentifier((byte[])Diruser.Properties["tokenGroups"][i], 0);
try
{
NTAccount nt = (NTAccount)sid.Translate(typeof(NTAccount));
Console.WriteLine(nt.Value + "\t" + domain);
}
catch { }
}
}
In order to retrieve all groups user belongs to you have to query one Global Catalog in each domain of the entire forest for the user's membership (user's tokenGroups attribute will return you nested groups as well), then remove duplicated groups.
Be aware that Active Directory cannot return more than 5K values of a single attribute in one query.
If a user belongs to more than 10K groups, then AD will return you only first 5K. You have to use technique called range retrieval to query for membership in that case.
Also, there may be some external trusted domains that you also have to handle.
Other solution is to use GetEffectiveRightsFromAcl function to calculate effective user permissions for the specified share.
The solution is described here
Note that you will need to pass SE_OBJECT_TYPE.SE_LMSHARE as and object type to the function.

I am facing License Limit Exceeded Exception when trying to insert a new user through apex controller class

I have created a visualforce page for creating new user and through the controller class I am trying to insert the newly created user.
I am working on a developer org and has three licenses available for - Salesforce Platform - User License.
I have created 4 users with this license in my org and only one of them is active.
Still I am facing the License Limit Exceeded Exception while I am trying to insert a new user with this license.
Can anyone please suggest a solution for this issue?
The code I am using is -
newUser = new User();
newUser.email = ApexPages.currentPage().getParameters().get('email');
String[] name = ApexPages.currentPage().getParameters().get('name').split(' ',2);
newUser.firstName = name[0];
newUser.lastName = name[1];
newUser.userName = newUser.email;
UserRole usrRole = [select id, name from UserRole where name = 'Customer'];
Profile prof = [select id, name from Profile where name = 'Customer Portal'];
newUser.UserRoleId = usrRole.id;
newUser.ProfileId = prof.id;
newUser.isActive = true;
try
{
insert newUser;
alertMsg = 'Successfully Created New User';
}
catch(System.DMLException e)
{
alertMsg = e.getMessage();
}
The screen shot of my company information is -
Option 1:
In the developer console, run this anonymous apex code snippet to get a count of active and inactive users:
system.debug([select isactive, count(Id) from User group by isactive]);
The outcome of the above SQL should be 3 inactive users and 1 active (as per your problem statement).
Option 2:
Make sure your controller class is not bulk inserting users beyond the # of open licenses.
Option 3:
Make sure your code is not trying to create user(s) using a profile that is tied to a license type that is all used up.
In addition to setting the profile, you also need to set the UserType (aka license type), otherwise it defaults to the Salesforce license, for which you have no spares, you need to add
something like newUser.userType = 'Platform' (you'll need to use describeSObject or a schema viewer tool to find the exact picklist value to use)

Two active directory forests, find corresponding exchange active directory object / mailbox

the company I work for has 2 Active Directory forests. One forest is called us where I log on in the morning with my profile (us\maflorin) and another forest is called (mail.us) which is dedicated to Exchange.
I have created an asp.net application that runs on SharePoint and gets the SPContext.Current.Web.CurrentUser.LoginName which is the us domain login name. (us\maflorin for example for me). I would like to get from the us credentials the corresponding object on the Exchange forest in order to write changes to the global address list (GAL) for user that opened the page after a line manager approval process.
I wrote the following working code to get the Exchange object, but it uses two ldap queries to find the object:
private Dictionary<string,AdRecod> FindExchangeAdProperties(string samAccountName,string description)
{
Dictionary<string,AdRecod> properties = null;
if (!string.IsNullOrEmpty(samAccountName))
{
properties = GetUserProperties(#"(&(objectCategory=person)(mailNickname=" +
samAccountName + "))");
if (properties != null) return properties;
}
if ((description == "") || (description == "0"))
throw new Exception("No matching Description, couldn't find correct Exchange AD object");
properties = GetUserProperties(#"(&(objectCategory=person)(description=" +
description + "))");
return properties;
}
Is it possible to get the exchange object with a single ldap query directly from the us samAccountName?
The mailNickname attribute on the exchange forest does not always match the sAMAccountName on the us forest. If it does not match, I use the second ldap query to see if a record is return by querying on the description field. The description field is many times the same for both forests but sometimes an administrator changed it.
Is it possible to find the corresponding Exchange Active Directory object for the us domain credentials more easily? How does Outlook find from the us credentials the corresponding mailbox / Ad object ? I was looking at the AD schema with adsiedit but could not find a clear field that is used to link the two forest objects together.
Furthermore I was looking into the Autodiscover service of the exchange web services managed api (mailbox dn attribute) but you need to pass into the GetUserSettings method an SMTP address and this field is not populated on the us domain.
Many thanks,
Mathias
I was able to find an answer to this question with a better approach than the one above which depends on the company's naming convention.
On the exchange forest I run a LDAP query with the DirectorySearcher class to obtain the attribute msExchMasterAccountSid.
The following code then provides the correct sam on the forest we use to logon:
var sid = directoryEntry.Properties["msExchMasterAccountSid"].Value as byte[];
// no mailbox
if (sid == null) continue;
var sidString = new SecurityIdentifier(sid, 0).ToString();
var samAccountName = "";
using (var context = new PrincipalContext(ContextType.Domain, "US"))
{
var principal = UserPrincipal.FindByIdentity(context, IdentityType.Sid, sidString);
if (principal == null) continue;
samAccountName = principal.SamAccountName;
}

app on GAE | Restricted Google account authentications | listed google accounts not all |

I am quite new to this Google app engine. I am learning things every day.
I am have a forum on google app engine.
But I want is to be having private or restricted parts.
Some features should be locked for certain google account users, which are in some sort of access control list.
I plain words I can say, only those user who are in list of access can see the forum rest will be redirect to the "contact to admin" page.
As I am new I wanna know that is it something possible.
if yes, how can I achieve it ?
Thanks,
Alok
If you are using the built-in Users API, you can check users.is_current_user_admin() as an access control mechanism. Administrators can be managed via the dashboard.
If you need more granular, application-specific authorization logic, generally you would create a User model in the datastore that references the built-in UserProperty and also holds a list of roles or whatever else you need to check authorization.
To follow up Drew's reply, I use a similar system in my app, so my server code has something like the following class definition (simplified here for clarity)
class myUser(db.Model):
user = db.UserProperty(required=True)
rights = db.StringProperty(required=True, choices=set(["public", "private"]))
created = db.DateTimeProperty(auto_now_add=True)
lastaccess = db.DateTimeProperty(auto_now=True)
and then I have code like this where I handle queries
def checkUserRights(user):
q = db.GqlQuery("SELECT * from myUser WHERE user = :1", user)
u = q.get()
if not u:
# create a new 'public access' user if we haven't seen this person before
u = myUser(user=user, rights="public")
# always update the user record after the source is fetched (updates the lastaccess field)
db.put( u )
return u.rights
rights = checkUser(users.get_current_user())
if isPrivateArea and rights == "private":
....
This way I create a user for EVERY visitor, and then I have an admin interface to change the rights of selected users - you may decide, for example, to not create a record for every visitor
def checkUserRights(user):
q = db.GqlQuery("SELECT * from myUser WHERE user = :1", user)
u = q.get()
if not u:
# grant default public rights to anyone...
return "public"
# always update the user record after the source is fetched (updates the lastaccess field)
db.put( u )
return u.rights
This is, of course, on a page where the app.yaml specifies "login: required"

Resources