Jul 28, 2009 at 4:43 PM
Edited Jul 28, 2009 at 4:44 PM
|
We just started looking into N2 CMS this week and so far I am very impressed with the implementation. One of the things that we're interested in would be some sort of Active Directory integration where we could do the following:
- Use network name and password to log in to the editor interface
- Allow users to edit only certain sections of the site based on AD groups
- Possibly have some sort of workflow notification so editors know when something should be approved to publish
Do you have any suggestions for how to go about implementing this? If I do end up writing code to make this work I would be interested in contributing it back to the source code.
Thanks!
|
|
|
|
N2 uses the standard .NET Membership API to authenticate users & manage groups, so you should just be able to wire in the built-in AD providers using the web.config file & the security stuff should work as normal.
There's an N2Contrib project on googlecode (http://code.google.com/p/n2contrib/) that includes a Workflow component. It might help you but I've never looked into it beyond reading the site..
Steve
2009/7/28 sddaniels <notifications@codeplex.com>
From: sddaniels
We just started looking into N2 CMS this week and so far I am very impressed with the implementation. One of the things that we're interested in would be some sort of Active Directory integration where we could do the following:
- Use network name and password to log in to the editor interface
- Restrict users to certain sections of the site based on AD groups
- Possibly have some sort of workflow notification so editors know when something should be approved to publish
Do you have any suggestions for how to go about implementing this? If I do end up writing code to make this work I would be interested in contributing it back to the source code.
Thanks!
|
|
|
|
Thanks for the help, Steve. I was able to use the built in MembershipADProvider, and I wrote a custom role provider that interfaced with the AD groups I wanted to use. The other options for role provider seemed like to much trouble (required an AzMan store).
I do have another question though: When the signed in person has permission as a Writer, they're not supposed to be able to publish articles, right? This seems to be the case for the edit page, but when I went to the previous versions page I was able to
publish any version as a Writer. Is this something that I can fix somehow or is this a bug?
|
|
|
|
Hi,
perhaps you can share your code on the custom role provider?
A userfull piece of code I think...
Thanks!
Martijn
|
|
Jul 31, 2009 at 9:45 PM
Edited Jul 31, 2009 at 9:51 PM
|
No guarantees, of course, but here you go:
Config Section
<roleManager enabled="true" defaultProvider="CustomActiveDirectoryProvider">
<providers>
<clear/>
<add name="CustomActiveDirectoryProvider"
type="CustomRoleProvider"
groups="Writers=Group 1;Editors=Group 2;Administrators=Group 3"
activeDirectoryPath="LDAP://yourserver.com/DC=YOURSERVER,DC=COM"/>
</providers>
</roleManager>
Code
Imports System.Collections.Generic
Imports System.DirectoryServices
Public Class CustomRoleProvider
Inherits RoleProvider
Private groupsByRole As Dictionary(Of String, String) ' key = role name, value = AD group name
Private rolesByGroup As Dictionary(Of String, String) ' key = AD group name, value = role name
Private adPath As String
Public Overrides Sub Initialize(ByVal name As String, ByVal config As System.Collections.Specialized.NameValueCollection)
If config Is Nothing Then
Throw New ArgumentNullException("config")
End If
MyBase.Initialize(name, config)
adPath = config("activeDirectoryPath")
' store all roles and their corresponding active directory groups
Dim rolesArr() As String = config("groups").Split(";"c)
groupsByRole = New Dictionary(Of String, String)
rolesByGroup = New Dictionary(Of String, String)
For Each roleEntry As String In rolesArr
Dim roleEntryArr() As String = roleEntry.Split("="c)
groupsByRole.Add(roleEntryArr(0), roleEntryArr(1))
rolesByGroup.Add(roleEntryArr(1), roleEntryArr(0))
Next
End Sub
Public Overrides Sub AddUsersToRoles(ByVal usernames() As String, ByVal roleNames() As String)
Throw New NotSupportedException()
End Sub
Public Overrides Property ApplicationName() As String
Get
Throw New NotSupportedException()
End Get
Set
Throw new NotSupportedException()
End Set
End Property
Public Overrides Sub CreateRole(ByVal roleName As String)
Throw New NotSupportedException()
End Sub
Public Overrides Function DeleteRole(ByVal roleName As String, ByVal throwOnPopulatedRole As Boolean) As Boolean
Throw New NotSupportedException()
End Function
Public Overrides Function FindUsersInRole(ByVal roleName As String, ByVal usernameToMatch As String) As String()
Throw New NotSupportedException()
End Function
Public Overrides Function GetAllRoles() As String()
Dim allRoles(groupsByRole.Count) As String
Dim i As Integer = 0
For Each pair As KeyValuePair(Of String, String) In groupsByRole
allRoles(i) = pair.Key
i += 1
Next
Return allRoles
End Function
Public Overrides Function GetRolesForUser(ByVal username As String) As String()
Dim userRoles As New List(Of String)
Dim domain As New DirectoryEntry(Me.adPath)
Dim searcher As New DirectorySearcher(domain)
' find user in AD
searcher.Filter = "sAMAccountName=" & username
Dim result As SearchResult = searcher.FindOne()
For Each groupDN As String In result.Properties("memberOf")
' strip the group name out of the distinguished name
Dim groupArr() As String = groupDN.Split(","c)
Dim groupName As New StringBuilder(groupArr(0))
groupName.Replace("CN=", "")
' look up group name in our list of roles
Dim roleToAdd As String = ""
rolesByGroup.TryGetValue(groupName.ToString(), roleToAdd)
If Not roleToAdd = String.Empty Then
userRoles.Add(roleToAdd)
End If
Next
Return userRoles.ToArray()
End Function
Public Overrides Function GetUsersInRole(ByVal roleName As String) As String()
Dim users As New List(Of String)
Dim domain As New DirectoryEntry(Me.adPath)
Dim searcher As New DirectorySearcher(domain)
' find group in AD
searcher.Filter = "cn=" & groupsByRole(roleName)
Dim result As SearchResult = searcher.FindOne()
' build search filter to get AD nodes of all users found in previous query
Dim filter As New StringBuilder("(!")
For Each userDN As String In result.Properties("member")
filter.Append("(distinguishedName=" & userDN & ")")
Next
filter.Append(")")
' get all users for role
searcher.Filter = filter.ToString()
Dim results As SearchResultCollection = searcher.FindAll()
For Each result In results
users.Add(getValue(result, "sAMAccountName"))
Next
Return users.ToArray()
End Function
Public Overrides Function IsUserInRole(ByVal username As String, ByVal roleName As String) As Boolean
Dim domain As New DirectoryEntry(Me.adPath)
Dim searcher As New DirectorySearcher(domain)
' find user in AD
searcher.Filter = "sAMAccountName=" & username
Dim result As SearchResult = searcher.FindOne()
For Each groupDN As String In result.Properties("memberOf")
' strip the group name out of the distinguished name
Dim groupArr() As String = groupDN.Split(","c)
Dim groupName As New StringBuilder(groupArr(0))
groupName.Replace("CN=", "")
' look up group name in our list of roles
Dim role As String = ""
rolesByGroup.TryGetValue(groupName.ToString(), role)
If Not role = String.Empty Then
If role.Equals(roleName) Then
Return True
End If
End If
Next
' still here, so we didn't find the role
Return False
End Function
Public Overrides Sub RemoveUsersFromRoles(ByVal usernames() As String, ByVal roleNames() As String)
Throw New NotSupportedException()
End Sub
Public Overrides Function RoleExists(ByVal roleName As String) As Boolean
If roleName Is Nothing Then
Throw New ArgumentNullException()
Else If rolename = String.Empty Then
Throw New ArgumentException()
End If
Return groupsByRole.ContainsKey(roleName)
End Function
Private Function getValue(result As SearchResult, propertyName As String) As String
Dim vColl As ResultPropertyValueCollection = result.Properties(propertyname)
If vColl.Count > 0 Then
Return vColl(0).ToString()
Else
Return ""
End If
End Function
End Class
|
|
|
|
Hmm, sounds like a bug. I don't think I have permission to turn this case into a work item, but if you're able to dig into the source and fix the issue then I'll be happy to apply a patch to the source if you post it up here.
I'm looking at a busy couple of weeks so wont be able to look at this myself for a while (maybe Libardo will re-appear from his holidays at some point and be able to take a look)
S
2009/7/31 sddaniels <notifications@codeplex.com>
From: sddaniels
Thanks for the help, Steve. I was able to use the built in MembershipADProvider, and I wrote a custom role provider that interfaced with the AD groups I wanted to use. The other options for role provider seemed like to much trouble (required an AzMan store).
I do have another question though: When the signed in person has permission as a Writer, they're not supposed to be able to publish articles, right? This seems to be the case for the edit page, but when I went to the previous versions page I was able to
publish any version as a Writer. Is this something that I can fix somehow or is this a bug?
|
|
Coordinator
Aug 5, 2009 at 9:45 AM
|
This discussion has been copied to a work item. Click
here to go to the work item and continue the discussion.
|
|
|
|
Thanks Libardo! Judging by the work item it looks like you've already fixed the bug. Any idea when this will come out in a release? Unfortunately we're still using VS 2005 at work so I don't think I can compile it myself from source.
|
|
|
|
I am also trying to get AD working with my N2CMS site...... with no luck. Should I be able to log into /N2/login.aspx with my domain name by following the above method?? Thanks.
|
|
Coordinator
Apr 21, 2011 at 8:48 PM
|
Have you tried the msdn documentation?
http://technet.microsoft.com/en-us/library/cc733010(WS.10).aspx
I could log in using basic authentication.
|
|