Spring LDAP - Remove user from group - spring-ldap

I want to know what's the best way to remove a user from a group (without removing the user itself) using Spring LDAP 1.3.1. (The Spring LDAP version is important here because I can't upgrade right now and I'm NOT using the ODM).
I've tried this, but it doesn't work. The memberOf attribute is removed for the user, but the user entry remains in the group.
public void disable(User user) {
Name dn = buildDn(user.getUsername());
Attribute attr = new BasicAttribute("memberOf");
ModificationItem item = new ModificationItem(DirContext.REMOVE_ATTRIBUTE, attr);
ldapTemplate.modifyAttributes(dn, new ModificationItem[] { item });
}
Any help would be very appreciated.

If you want to remove user from group you have to also delete him from members attribute of this group.

Related

Discord.js - Command to Remove All Users Containing Role

I know that you can remove certain roles from users, and remove all roles from a user, but I was thinking of doing the reverse. I looked at this guide, which provides a way to retrieve all of the people who have a specific role. It seems like you could manipulate the collection/map to go through each member and remove the role. However, I cannot seem to achieve this.
I've hard-coded the one specific role that I am targeting as well as the message that should trigger the command.
Current code that I've been trying out (only seems to be working if there's just one person assigned the role):
if (msg.startsWith('!new round')) {
//check for everyone and remove the role
//roleID is just the roleID number string; I've stated it outside the if loop, for other command use cases as well
let membersWithRole = message.guild.roles.cache.get(roleID).members;
console.log(membersWithRole);
for (let member of membersWithRole) {
let mem = member[1]
mem.roles.remove(role).catch(console.error);
message.reply("Everyone with the jail role is now back in the game!");
}
}
Bottom line: Given a collection of the list of "guild" members that have the specified role (provided in the guide), could I iterate through a list* in order to remove the role from each member?
*I haven't found said list containing the members, but it's probably the objects themselves, so the whole collection
you need to learn documentation of discord.js
and yes you can do it by looping through all members.
if(msg.startsWith('!new round')){
console.log('command used by '+msg.author);
let role =msg.guild.roles.cache.get(roleId);
role.members.each(member=>{
member.roles.remove(role);
});
console.log('removed role from all members');
}
and also if you want to remove role from all members, so why you are not just deleting the role?
delete role:
msg.guild.roles.cache.get(roleId).delete();

editing roles with edit_role discord.py

I have the following line in my script:
await client.edit_role(server='547874634978789398', role='' ,colour=0x008000)
However I do not understand what parameter discord.py is expecting for role=. Can anyone point me in the right direction to better understand this parameter?
First, you should use Server class not server's id. There is get_server() function that returns Server object with the given server's id.
server = client.get_server('547874634978789398')
Then, you can access to all roles belonging to the server by server.roles. It is list of Role object. So if you have a name of role and want to edit one's role into that, try it.
for role in server.roles:
if role.name == 'role_name':
# What you want to do.
await client.edit_role(server=server, role=role, colour=0x0080000)
break
Also there is server.role_hierarchy property which returns roles in order of the hierarchy. It contains same elements with server.roles but it is the sorted version.
role = discord.utils.get(ctx.guild.roles, name="Name")
# This will get the role you want to edit
await role.edit(color=0x008000, reason="The reason")
# This will edit the role with the desired color
For more information on this please see the docs: discord.Role.edit | discord.utils.get

Kentico 10 - How do I update the username of an existing user?

Using a kentico 10 website with claims based authentication. We have the facility to update their email address in the external system. So what I want to do is update the user's email address and username by looking up based on the external userid from our sso platform.
var existingUser = UserInfoProvider.GetUsers().Where("ExternalGuid", QueryOperator.Equals, userId).FirstOrDefault();
if (existingUser.IsInSite(SiteContext.CurrentSiteName))
UserInfoProvider.RemoveUserFromSite(existingUser.UserName, SiteContext.CurrentSiteName);
loggingInUser = UserInfoProvider.GetUserInfo(existingUser.UserID);
loggingInUser.UserName = e.UserName;
UserInfoProvider.SetUserInfo(loggingInUser);
I'm getting the error:
The user with code name 'ac.aa#test.com' already exists.
This is happening on that SetUserInfo line. So I'm thinking there must be another way to update the username properly.
You need to do a few things:
Check if the user exists already:
UserInfo ui = UserInfoProvider.GetUserInfo(newUserName);
if (ui != null)
{
// user exists with new username so don't continue
}
Check if the username can be used as a username (no spaces, special characters, etc):
if (!ValidationHelper.IsUserName(newUserName))
{
// username cannot be used as a username
}
Check if the username is reserved or not:
if (UserInfoProvider.NameIsReserved(siteName, newUserName))
{
// reserved username so cannot use it
}
I'm willing to bet the username is reserved or not valid which is why it is not saving. The assignment you have done should work without issue.
It also looks like you're performing this update in a global handler so this could cause problems with a few things. So you may have to perform that username update later on or simply write a record to a custom table and then update it from there based on the event of creating those records in the custom table.
So I'd debug through your code and verify it is working properly by removing it from the global event handler, if it works, then it's an issue with having too many things happen at one time.
Try using SetValue(string columnName, value) method, I just tested this one and it worked fine:
UserInfo updateUser = UserInfoProvider.GetUserInfo("NewUser");
if (updateUser != null)
{
// Updates the user's properties
updateUser.SetValue("UserName", "NewUserName");
// Saves the changes to the database
UserInfoProvider.SetUserInfo(updateUser);
}
For some properties/columns, which are acting like "read only", you need to use the SetValue method like it was a custom field (API examples)

Indexing Sitecore Item security and restricting returned search results

I have several roles defined, each with different restrictions to content and media items and I would like to restrict the search results that are returned based on the access rights of the currently logged in user, rather than displaying the result and the user then presented with an "Access Denied" page. Some content will obviously be accessible to extranet\anonymous so they should be returned for all users regardless.
The security follows the standard Sitecore practices so Role inheritance (roles within roles) will be used, so it will need to take this into account also.
I couldn't see anything in the Advanced Database Crawler module that would help and I've looked through the Sitecore Search and Indexing Guide (version 6.6 and version 7) but couldn't find any information about indexing the security applied to items. The following articles have some suggestions:
How can I set up a Lucene index in Sitecore that handles security correctly?
This feels "dirty" and has the potential for performance issues, particularly when there are a large number of items returned. Also, (see in the comments) the issue with paging results.
Security (aka Permissions) and Lucene - How ? Should it be done?
The above looks more realistic, and would filter out the results based on indexed security roles, there would obviously be a need to expand the roles to handle roles within roles. My concern here would be that we would need to handle denied permissions, when we specifically need to deny/restrict access for certain roles to content items (I know this is not recommended practice, but there is a very specific need to always deny).
I'm at the planning stage at the moment so with the release of Sitecore 7 today there is also the possibility to use the updated Lucene libraries and/or SOLR if that makes life easier - assuming of course that some of the modules like WebForms for Marketers and Email Campaign Manager are updated before too long.
What are the solutions that people are using for returning search results taking into account security? Any alternatives than the linked questions above? Maybe something in Sitecore 7 that I can leverage, the updated Lucene libraries or SOLR?
I'd prefer to keep this all "out of the box" Sitecore and not use other third party search products if at all possible.
A slight alternative to the suggestion from Klaus:
In Sitecore.ContentSeach.config you'll find a pipeline called contentSearch.getGlobalSearchFilters
Processors added to this pipeline will be applied to any query, so if we drop in one that applies a filter based on roles we're good.
ComputedField
To start, we want a computed field added to our index configuration:
<fields hint="raw:AddComputedIndexField">
<field fieldName="read_roles" returnType="stringCollection">Sitecore.ContentSearch.ComputedFields.ReadItemRoles,Sitecore.ContentSearch</field>
</fields>
NOTE the stored type is a collection of strings. We'll use it to index all the names of roles that can read an item.
Implementation
We have a base abstract class to handle the extraction of item security details
public abstract class ItemPermissions: IComputedIndexField
{
public string FieldName { get; set; }
public string ReturnType { get; set; }
public object ComputeFieldValue(IIndexable indexable)
{
var indexableItem = indexable as SitecoreIndexableItem;
if (indexableItem == null) return null;
var security = indexableItem.Item.Security;
return GetPermissibles(security);
}
protected abstract object GetPermissibles(ItemSecurity security);
}
We implement the above with the abstracted method
public class ReadItemRoles : ItemPermissions
{
protected override object GetPermissibles(ItemSecurity security)
{
var roles = RolesInRolesManager.GetAllRoles();
return roles.Where(security.CanRead).Select(r => r.Name);
}
}
NOTE There's obviously a performance impact here, this will reduce your indexing speed.
To reduce the impact, only add the the computed field to the index configuration for the index that contains secured content. E.g. If your web content is only accessed by the anonymous user it will add no benefit.
Pipeline
Add the entry in to the config
<contentSearch.getGlobalSearchFilters>
<processor type="Sitecore.ContentSearch.Pipelines.GetGlobalFilters.ApplyGlobalReadRolesFilter, Sitecore.ContentSearch" />
</contentSearch.getGlobalSearchFilters>
Implementation
Implement the pipeline filter to check the roles of the context user
public class ApplyGlobalReadRolesFilter : GetGlobalFiltersProcessor
{
public override void Process(GetGlobalFiltersArgs args)
{
var query = (IQueryable<SitecoreUISearchResultItem>)args.Query;
var userRoles = Context.User.Roles.Select(r => r.Name.Replace(#"\", #"\\"));
var predicate = PredicateBuilder.True<SitecoreUISearchResultItem>();
predicate = userRoles.Aggregate(predicate, (current, role) => current.Or(i => i["read_roles"].Contains(role)));
if(predicate.Body.NodeType != ExpressionType.Constant)
args.Query = query.Filter(predicate);
}
}
Summary
Create a ComputedField that returns a list of all valid roles for a given access right
Apply a pipeline processor to contentSearch.getGlobalSearchFilters to add a query filter to each search request.
Use the PredicateBuilder class to ensure the role names are OR'ed together
The big benefit here is that you take the hit at index time and the handling of item restriction is handled through a search query as normal. No need to worry about the facet numbers or search counts being incorrect.
You can restrict the roles you are checking to compute the field and you can vary the application of the pipeline filter. You can even take out the pipeline filter and just update your queries to filter when you require it.
NOTE The biggest problem with this set up is the requirement to re-index your content when security restrictions change. Should you be applying security restrictions to users themselves, you'll have to include additional computed fields.
Edit 02/06/2013
I was just tinkering with this in a project and realised that it was AND'ing the roles in the query. If a user had multiple roles assigned then both roles would have to have declared rights to the item. I've updated the pipeline processor to use the PredicateBuilder class to OR the roles. A check is also added to ensure the predicate is not a constant, this ensures the query is updated only if we have a filter to apply.
After some more searching around, the Linq to Sitecore article pointed me to the following lines of code:
var index = SearchManager.GetIndex("sitecore_master_index");
var context = index.CreateSearchContext(SearchSecurityOptions.EnableSecurityCheck))
Digging through Sitecore.ContentSearch.dll and Sitecore.ContentSearch.LuceneProvider.dll in dotPeek decompiler and the mention of the indexing.filterIndex.outbound pipeline in the Sitecore 7 Search document I found the following code:
Sitecore.ContentSearch.LuceneProvider.LuceneSearchReults
public IEnumerable<SearchHit<TElement>> GetSearchHits()
{
for (int idx = this.startIndex; idx <= this.endIndex; ++idx)
{
Document doc = this.context.Searcher.IndexReader.Document(this.searchHits.ScoreDocs[idx].Doc, (FieldSelector) this.fieldSelector);
if (!this.context.SecurityOptions.HasFlag((Enum) SearchSecurityOptions.DisableSecurityCheck))
{
string secToken = doc.GetField("_uniqueid").StringValue;
string dataSource = doc.GetField("_datasource").StringValue;
if (!string.IsNullOrEmpty(secToken))
{
bool isExcluded = OutboundIndexFilterPipeline.CheckItemSecurity(new OutboundIndexFilterArgs(secToken, dataSource));
if (!isExcluded)
yield return new SearchHit<TElement>(this.searchHits.ScoreDocs[idx].Score, this.configuration.IndexDocumentPropertyMapper.MapToType<TElement>(doc, this.selectMethod, this.virtualFieldProcessors, this.context.SecurityOptions));
}
}
else
yield return new SearchHit<TElement>(this.searchHits.ScoreDocs[idx].Score, this.configuration.IndexDocumentPropertyMapper.MapToType<TElement>(doc, this.selectMethod, this.virtualFieldProcessors, this.context.SecurityOptions));
}
}
Sitecore.ContentSearch.Pipelines.IndexingFilters
public class ApplyOutboundSecurityFilter : OutboundIndexFilterProcessor
{
public override void Process(OutboundIndexFilterArgs args)
{
if (args.IndexableUniqueId == null || !(args.IndexableDataSource == "Sitecore"))
return;
ItemUri uri = new ItemUri(args.IndexableUniqueId);
if (args.AccessRight != AccessRight.ItemRead || Database.GetItem(uri) != null)
return;
args.IsExcluded = true;
}
}
So it looks like Sitecore 7 gives us the ability to filter the the search results using the security rights of the context user straight out of the box, albeit using a very similar method of checking the item read permissions that Mark Cassidy suggested. Which is good news, since if this is a requirement for Sitecore 6 implementations then we can easily update the Advanced Database Crawler to do the same thing.
I'm still not convinced on the performance of this though, given that Sitecore 7 comes with Item Buckets and the possibility of storing millions of items. It should be possible to create several indexes though, and only EnableSecurityCheck on indexes with security enabled content, but then we need to think about combining the results from several indexes for "global search" results and also take into acccount Boosting which will mean re-ordering the combined results.
well - your considerations seems quite on target.
The easy implementation is to check the item through the database lookup - but paging, facetting and other statistics will fail in that.
The approach we do is to index security tokens for roles - having an inclusion field for allow and an exclusion field for deny rights. You then need to build a query for this - and expand all roles in roles for the query.
There are two issues you might be facing.
One is very complex OR queries for all roles in roles memberships. Might be less then well-performing.
The other is indexing congestion - as you will need to index major parts of the contentitems when security and permissions change as then are inherited.
The alternative is to use join queries - but normally that would be bad performing.
Sitecore developers made a silly mistake, it will never work, because of that statement:
if ((args.IndexableUniqueId != null) && (args.IndexableDataSource == "Sitecore"))
as args.IndexableDataSource will always be equal to "sitecore" not "Sitecore".
I'm currently upgrading big project to latest 7.2 Update and found out that silly mistake, oh Sitecore Devs usual mistakes :)

How do you get the value for an attribute when it's not your primary entity

I am trying to write a plugin that will trigger when an account is created. If there is a originating lead I want to fetch the company name in the lead and put it in the account name field. What I'm not sure how to do is to obtain the information out of the lead entity.
I have the following code (I'll keep updating this)...
Entity member = service.Retrieve("lead",
((EntityReference)account["originatingleadid"]).Id, new ColumnSet(true));
if (member.Attributes.Contains("companyname"))
{
companyName = member.Attributes["companyname"].ToString();
}
if (context.PostEntityImages.Contains("AccountPostImage") &&
context.PostEntityImages["AccountPostImage"] is Entity)
{
accountPostImage = (Entity)context.PostEntityImages["AccountPostImage"];
companyName = "This is a test";
if (companyName != String.Empty)
{
accountPostImage.Attributes["name"] = companyName;
service.Update(account);
}
}
I'm not going to spoil the fun for you just yet but the general idea is to:
Catch the message of Create.
Extract the guid from your Entity (that's your created account).
Obtain the guid from its EntityReference (that's your lead).
Read the appropriate field from it.
Update the name field in your account.
Store the information.
Which of the steps is giving you issues? :)
As always, I recommend using query expressions before fetchXML. YMMV
Is lead connected to the account? Just use the IOrganizationService.Retrieve Method
To retrieve the correct lead (assuming you have the lead id from the account entity)..
Create the organizationService in the execute method of your plugin.
http://msdn.microsoft.com/en-us/library/gg334504.aspx
Also here is a nice example to write the plugin:
http://mscrmkb.blogspot.co.il/2010/11/develop-your-first-plugin-in-crm-2011.html?m=1

Resources