I have to populate my autocomplete PeopleEditor-like control based on brililant ASPTokenInput with all people from my AD domain. Reflecting PeopleEditor shows a real mess in their Active Directory search engine and all potentially helpful classes are internal.
My test method works fine, but I need to get ALL users from AD(not sharepoint site ones) to populate my list:
public string GetUsers(string filter)
{
var spWeb = SPContext.Current.Web;
SPUserCollection allusers = spWeb.AllUsers;
List<SPUser> users = allusers.Cast<SPUser>().ToList();
var query = from spUser in users.Select(usr => new {id = usr.ID, name = usr.Name})
.Where(p => p.name.IndexOf(filter, StringComparison.InvariantCultureIgnoreCase) >= 0)
select new {id = spUser.id.ToString(), spUser.name};
return new JavaScriptSerializer().Serialize(query);
}
How can I query active directory like this? Is it possible to retrieve all AD connection settings from sharepoint itself? I need just id and user name to fill my dropdownlist Converting this to SPUserCollection is another big deal.
It would be great to use some built-in SP methods like this:
[SubsetCallableExcludeMember(SubsetCallableExcludeMemberType.UnsupportedSPType)]
public static IList<SPPrincipalInfo> SearchWindowsPrincipals(SPWebApplication webApp, string input, SPPrincipalType scopes, int maxCount, out bool reachMaxCount)
Solution was simple, the only thing I needed was SharePoint Group search implementation (If specified in Field Editor Control). SP has a nice built-in method, so I use it.
/// <summary>
/// Provides searching for AD or SharePoint group if specified in field setting
/// </summary>
public static class ActiveDirectorySearchProvider
{
public static IList<SPPrincipalInfo> Search(string filter, string selectionGroup, string principalType)
{
var site = SPContext.Current.Site.WebApplication;
bool reachmaxcount;
var scope = SPUtils.GetSpPrincipalType(principalType);
if (!String.IsNullOrEmpty(selectionGroup)) //search for users in SPGroup if present
{
var rawSPGroupList = SPUtility.GetPrincipalsInGroup(SPContext.Current.Web, selectionGroup, 100,
out reachmaxcount).ToList();
string lowerFilter = filter.ToLowerInvariant();
var filteredGroupList =
rawSPGroupList.Where(
pInfo =>
pInfo.LoginName.Substring(pInfo.LoginName.IndexOf('\\') + 1).StartsWith(lowerFilter) ||
pInfo.DisplayName.ToLowerInvariant().StartsWith(lowerFilter) ||
pInfo.DisplayName.ToLowerInvariant().Substring(pInfo.DisplayName.IndexOf(' ') + 1).StartsWith(
lowerFilter)).ToList();
return filteredGroupList;
}
return SPUtility.SearchWindowsPrincipals(site, filter, scope, 100, out reachmaxcount); //Search in AD instead
}
I can think of two options here.
You can use System.DirectoryServices and query all users from your Active Directory in your c# code.
You can setup User Profile Sync so that your SharePoint user DB is upto date.
Related
I want to Get the Active Directory names in sharepoint in a list.
To got Know that SharePoint 2013 Has some Hidden URL which Shows Current Active Directory User I wan to get it into List.
http://{YourSharepointUrl}/_catalogs/users/simple.aspx
Now I want to have list of all the names Displayed on my sharepoint
I am using the code:
private static void GetAllSiteUsers()
{
// Starting with ClientContext, the constructor requires a URL to the server running SharePoint.
var sharepointContext = new ClientContext("http://yoursharepointurl/");
}
Now I am Getting error it says about assembly reference doesn't exist.So I checked on google and added up this ddl and add the using Microsoft.SharePoint.Client; reference also.Still Not working.
Please Let me Know what needed to be done Guys
Purpose Of Making Program:To have all the AD Users and Make a work Group so that I can Assign them some right in such a way when assigned grp open something some other URL in iframe shows. and if some one else than other URL in iframe is shown to him.
Thanks IN Advance Guys.
You are in Server side (Farms solution), so don't use : ClientContext, this is for Client application, not server.
You just have to get the : User Information List
You could try somthing like :
using(SPSite site = new SPSite("URLsiteCollection")){
using(SPWeb web = site.rootWeb){
SPList userList = web.SiteUserInfoList;
SPListItemCollection allUsers = userList.Items;
foreach(SPListItem userItem in allUsers){
string userEmail = Convert.Tostring(userItem["EMail"]);
string userName = userItem.Title;
....
}
}
}
To get all information about active directory user or group you can use
PrincipalContext pContext = new PrincipalContext (ContextType.Domain, YOUR_DOMAIN);
//For User
UserPrincipal userPrincipal = new UserPrincipal (pContext);
PrincipalSearcher userSearch = new PrincipalSearcher (userPrincipal);
//For Group
GroupPrincipal grpPrincipal = new GroupPrincipal (pContext);
PrincipalSearcher grpSearch = new PrincipalSearcher (grpPrincipal);
foreach (UserPrincipal result in userSearch.FindAll())
{
if (result.SamAccountName!= null)
// Your code
}
foreach (GroupPrincipal result in grpSearch.FindAll())
{
if (result != null)
{
// Your code
}
Assembly
System.DirectoryServices.AccountManagement
Namespace
using System.DirectoryServices.AccountManagement;
I'm building a custom workflow where all users that are members of a specific role will receive email notifications depending on certain state changes. I've begun fleshing out e-mail templates via Sitecore items with replaceable tokens, but I'm struggling to find a way to allow the setting of the recipient role in Sitecore. I'd like to avoid having users enter a string representation of the role, so a droplink would be ideal if there were a way to populate it with the various roles defined in sitecore. Bonus points if I can filter the roles that populate the droplink.
I'm aware that users/roles/domains aren't defined as items in the content tree, so how exactly does one go about configuring this droplink?
Sitecore 6.5.
I'm not sure if there is a module for this already made, but you can use this technique: http://newguid.net/sitecore/2013/coded-field-datasources-in-sitecore/
It explains how you can use a class as data source. So you could create a class that lists all user roles.
You might want to take a look at http://sitecorejunkie.com/2012/12/28/have-a-field-day-with-custom-sitecore-fields/ which presents a multilist to allow you to select a list of users.
Also take a look at the Workflow Escaltor Module form which you can borrow the AccountSelector control which allows you to select either individual person or roles.
This is the module I previously used to do this exact thing. The following code gets all the unique email addresses of users and only for those users that have read access to the item (it was a multisite implementation, the roles were restricted to each site but the workflow was shared).
protected override List<string> GetRecipientList(WorkflowPipelineArgs args, Item workflowItem)
{
Field recipientsField = workflowItem.Fields["To"];
Error.Assert((recipientsField != null || !string.IsNullOrEmpty(recipientsField.Value)), "The 'To' field is not specified in the mail action item: " + workflowItem.Paths.FullPath);
List<string> recepients = GetEmailsForUsersAndRoles(recipientsField, args);
if (recepients.Count == 0)
Log.Info("There are no users with valid email addresses to notify for item submission: " + workflowItem.Paths.FullPath);
return recepients;
}
//Returns unique email addresses of users that correspond to the selected list of users/roles
private List<string> GetEmailsForUsersAndRoles(Field field, WorkflowPipelineArgs args)
{
List<string> emails = new List<string>();
List<User> allUsers = new List<User>();
AccountSelectorField accountSelectorField = new AccountSelectorField(field);
List<Account> selectedRoles = accountSelectorField.GetSelectedAccountsByType(AccountType.Role);
List<Account> selectedUsers = accountSelectorField.GetSelectedAccountsByType(AccountType.User);
foreach (var role in selectedRoles)
{
var users = RolesInRolesManager.GetUsersInRole(Role.FromName(role.Name), true).ToList();
if (users.Any())
allUsers.AddRange(users);
}
selectedUsers.ForEach(i => allUsers.Add(Sitecore.Security.Accounts.User.FromName(i.Name, false)));
foreach (var user in allUsers)
{
if (user == null || !args.DataItem.Security.CanRead(user)) continue; //move on if user does not have access to item
if (!emails.Contains(user.Profile.Email.ToLower()))
{
if(user.Profile.Email != null && !string.IsNullOrEmpty(user.Profile.Email.Trim()))
emails.Add(user.Profile.Email.ToLower());
else
Log.Error("No email address setup for user: " + user.Name);
}
}
return emails;
}
I have a code in which I have to check if a user is a part of a certain group (lets say "GroupA").
I have the user details stored in the Sharepoint variable SPUser. Now I need to check if this user is a part of GroupA and then take some action.
How can I achieve this?
Source : How to check if a user exists in a group
you can use following extension method, like this:
public static bool InGroup(this SPUser User, string GroupName)
{
return User.Groups.Cast<SPGroup>().Any(g => g.Name.ToLower() == GroupName.ToLower());
}
Then call it like this:
bool inGroup = spuser.InGroup("GroupName");
If you want to check the current user then another approach can be like this:
From: Check user already exist in specified SharePoint Group
SPWeb web = SPContext.Current.Web;
SPGroupCollection webGroups = web.Groups;
foreach (SPGroup group in webGroups)
{
//Checking the group
if (group.ContainsCurrentUser)
{
// perform action
}
else
{
//perform action
}
}
For More Reference:
Tell if user exists in SharePoint Group through web service
As you may know, MOSS 2007 offers functionality to synchronize Active Directory properties to SharePoint UserProfile Properties. You can map AD properties to userProfile properties in
Shared Services > User Profile and Properties > View Profile properties (all the way at the bottom).
I'm currently investigating the possibility to synchronize modifications on userProfiles back to AD.
I'm new to SharePoint and struggling my way through its API's, but what I dug up so far, is that you can iterate to UserProfile changes and find out timestamps, old values, new values, etc.
string siteUrl = #"http://[siteUrl]/";
Microsoft.SharePoint.SPSite spsite = new Microsoft.SharePoint.SPSite(url);
Microsoft.Office.Server.ServerContext serverContext = Microsoft.Office.Server.ServerContext.GetContext(spsite);
Microsoft.Office.Server.UserProfiles.UserProfileManager userProfileMgr = new Microsoft.Office.Server.UserProfiles.UserProfileManager(serverContext);
var collection = userProfileMgr.GetChanges();
List<ProfilePropertyChange> changes = new List<ProfilePropertyChange>();
foreach (Microsoft.Office.Server.UserProfiles.UserProfileChange change in collection)
{
if (change.ObjectType == Microsoft.Office.Server.UserProfiles.ObjectTypes.SingleValueProperty)
{
var singleValue = change as Microsoft.Office.Server.UserProfiles.UserProfileSingleValueChange;
string oldValue = singleValue.OldValue;
string newValue = singleValue.NewValue;
var profileProperty = singleValue.ProfileProperty;
DateTime modificationDate = singleValue.EventTime;
...
}
}
However, what I'm currently unable to discover, is programmatic access to the so called "Mapped Attribute" (the original property name in AD).
Can anybody point me to the SharePoint API that will reveale this information for me?
Many thanks
Steve Curran was kind enough to address my question on the MSDN forum:
http://social.msdn.microsoft.com/Forums/en-US/sharepointdevelopment/thread/019c1e60-babb-4942-90e1-d33e924c7c73
Using the PropertyMapCollection you
may be able to look up the mapped AD
attribute given the Userprofile name.
DataSource ds = upcm.GetDataSource();
PropertyMapCollection pmc =
ds.PropertyMapping;
http://msdn.microsoft.com/en-us/library/microsoft.office.server.userprofiles.propertymapcollection%28office.12%29.aspx
I have a document library in my SharePoint page and there are 10 documents in it.
If User A is logged in I want him to only see 5 of those documents in that document library.
How can I create some custom document library for this to work?
I have MOSS installed.
Thanks in advance!
You could configure different permissions on each document in the document library. Just select the "Manage Permissions" option on each item and break the permission inheritance from the document library level. Just note that having too many documents with item level permissions can create a maintenance nightmare for you. Another option could be to create two document libraries with different permissions.
Write an ItemEventReceiver that breaks the permissions based on a field in the library, i.e. a column that holds the different roles .
We have done this by creating a list that holds all roles coupled to sharepoint groups.
i.e.
Administrator -> Owners of website (SPGroup), Company Administrators (SPGroup)
Managers -> Managers (SPGroup)
then in our content type we have a lookup column to this list.
Here's the code for the ItemEventReceiver:
public override void ItemUpdated(SPItemEventProperties properties)
{
lock (_lock)
{
try
{
using (SPSite site = new SPSite(properties.SiteId,
properties.ListItem.ParentList.ParentWeb.Site.SystemAccount.UserToken))
using (SPWeb web = site.OpenWeb(properties.RelativeWebUrl))
{
web.AllowUnsafeUpdates = true;
var item = web.Lists[properties.ListId].GetItemById(properties.ListItemId);
var roles = item["Roles"] as SPFieldLookupValueCollection;
var rolesList = web.Site.RootWeb.Lists["Company Roles"];
var groupsToAdd = new List<SPFieldUserValue>();
if (item.HasUniqueRoleAssignments)
{
item.ResetRoleInheritance();
item = item.ParentList.GetItemById(item.ID);
}
if (roles != null && roles.Count > 0)
{
// Iterate over the roles and see if there is a group associated
foreach (var role in roles)
{
var roleItem = rolesList.GetItemById(rol.LookupId);
if (roleItem != null)
{
// This is the SPgroup field in the rolesList
var groups = roleItem["Groups"] as SPFieldUserValueCollection;
if (groups != null)
{
groupsToAdd.AddRange(from g in groups
where g.User == null
select g);
}
}
}
if (groupsToAdd.Count > 0)
{
item.BreakRoleInheritance(false);
foreach (var value in groupsToAdd)
{
var group = web.Groups[value.LookupValue];
var assignment = web.RoleAssignments.GetAssignmentByPrincipal(group);
item.RoleAssignments.Add(assignment);
}
}
}
DisableEventFiring();
item.SystemUpdate(false);
EnableEventFiring();
}
}
catch (Exception ex)
{
//LOG ERROR
}
}
}
If the coding doesn't work for you, and you'd rather not set permissions on each file, then there is a third option. We use folders with permissions set on them.
e.g.
Create a folder called "Managers", break permissions, and set rights to only the managers.
Create another folder called "Employee 1", break permissions, and set Contribute rights to the Employee and the Employe's manager.
Place the files in the appropriate folders and it will inherit rights from the folder.
This way, managers can see the manager files, and all files of their employees. Users can only see their own files.
Similar logic can be done for Headquarters, Region 1, Region 2, etc ... and creating different Groups for each region and then assigning the group to the folder's permissions.
Note, there's always concern in using this design on maintaining all the permissions and on performance, but we've been doing similar things for 750+ user populations and thousand of docs and it's been working fine for us so far.