You are viewing limited content. For full access, please sign in.

Question

Question

User fields in Forms

asked on July 26, 2016

I guess this is more of a suggestion/idea than question, but someone might know a work around. I wish we had a field in Forms that could use active directory to pull names. That way we can avoid misspelling and updating a drop down list. I'm trying to create an "assigned to" field and I would love if it was similar to how we select an assignee for an user task in Forms

0 0

Answer

SELECTED ANSWER
replied on July 28, 2016

While I didn't actually use AD, I used a view that pulls info from the cf-users table in the Forms database. It seems to be storing all the users in Forms System Security. For my purposes, this is a better list than AD because only employees with Forms licenses are displayed:

 

SELECT        username, user_type, displayname
FROM            dbo.cf_users
WHERE        (username LIKE 'OurDomain%') AND (user_type = '1')

 

3 0

Replies

replied on July 26, 2016 Show version history

For posterity's sake, if you dare to try configuring a linked server like Eric described above, below is how you can do it using MSSQL and SQL Management Studio. Familiarity with SQL helps, and familiarity with the structure of Active Directory you wish to query is required. Tools like ADExplorer from SysInternals can help with that.

Step One: Create a Linked Server

  1. In SQL Management Studio, connect to the SQL server. In the Object Explorer, expand the "Server Objects" node and right-click on "Linked Servers" to add a new one. You will get the "New Linked Server" dialog.
  2. Give the Linked Server a name. In the attached example 1-LinkedServerGeneral.png, I named mine "ADQUERY".
  3. For "Provider", select "OLE DB Provider for Microsoft Directory Services".
  4. For "Product Name", enter "Active Directory Services 2.5".
  5. For "Data Source", enter "adsdatasource".
  6. Go to the Security page in the left pane. By default connections will not be made with any security context, which in most cases will cause errors when trying to make the query. If using Windows authentication with an account that has rights to query AD, you can choose "Be made using the login's current security context". (2-LinkedServerSecurity.png) To be safe, you can specify a security context and provide the credentials to use to query AD.
  7. Click OK and you've got yourself a linked server!

Step Two: Structure of Query for this Linked Server

You can use SQL-style queries to query this new linked server:

SELECT * FROM OpenQuery(
	<LinkedServerName>,
	'SELECT <ADAttribute1>, <ADAttribute2>, ..., <ADAttributeN>
	FROM ''LDAP://<domain>.<ext>/<BaseDistinguishedName>''
	WHERE objectClass = ''User''
	')

There are a lot of variables to play with here:

  • <LinkedServerName>: the name of the linked server from Step One above.
  • <ADAttribute#>: attributes in Active Directory; for example displayName, cn, sn, mail, memberOf, etc.
    • A good reference for user attributes in Active Directory is available online here.
    • Note that you must specify attributes here for the results to be meaningful; if you try to use wildcard (*) the results will not be useful values, but instead LDAP:// URIs for the returned users.
  • <domain>.<ext>: the domain of Active Directory you are querying
  • <BaseDistinguishedName>: the distinguished name of the "maximum" organizational unit you will be querying; at minimum this will probably include "DC=<domain>,DC=<ext>"

Here's an example:

SELECT * FROM OpenQuery(
	ADQUERY,
	'SELECT displayName, mail
	FROM ''LDAP://mydomain.com/OU=Users,DC=mydomain,DC=com''
	WHERE objectClass = ''User''
	')

This returns SQL results in two columns: 'displayName' and 'mail'.

You can actually extend the query to include more WHERE and ORDER BY just like in SQL, using attribute names as though they were SQL column names. A useful example for the use case in this thread could be as follows:

SELECT * FROM OpenQuery(
	ADQUERY,
	'SELECT displayName, mail
	FROM ''LDAP://mydomain.com/OU=Users,DC=mydomain,DC=com''
	WHERE objectClass = ''User''
	AND memberOf = ''CN=Sample Group,OU=My Group,OU=Users,DC=mydomain,DC=com''
	ORDER BY displayName
	')

This example returns all users from my fictitious Active Directory setup who are part of a group "Sample Group", ordered by their display names. Note the additional "memberOf" clause. The value is the distinguished name of the Windows group. How to find this? You'll have to get familiar with Active Directory. The tool I use is ADExplorer from SysInternals, mentioned previously.

One final note, for those following along in SQL Management Studio, is that when the query results are returned, the columns will be in the reverse order as specified in the query. So for example, if running the above query, the 'mail' column will be shown first, then the 'displayName' column.

Now to prepare this for use with Forms.

Step Three: Write a Stored Procedure to Query Active Directory

SQL-savvy folks can come up with queries that will take in parameters, etc. For now, here's code that will create a stored procedure that will run the Active Directory query from before:

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE sp_adquery
AS
BEGIN
	SET NOCOUNT ON;
	-- here's the query from before
	SELECT * FROM OpenQuery(
		ADQUERY,
		'SELECT displayName, mail
		FROM ''LDAP://mydomain.com/OU=Users,DC=mydomain,DC=com''
		WHERE objectClass = ''User''
		AND memberOf = ''CN=Sample Group,OU=My Group,OU=Users,DC=mydomain,DC=com''
		ORDER BY displayName
		')
END
GO

In SQL Management Studio's Object Explorer, expand the Databases node, navigating to the database used as an external data source in Forms, then expand the Programmability node. Right-click on "Stored Procedures" to create a new one. Replace the code in the query tab with the code above.

Now if you set up the external data source in Forms and configure a lookup rule (nothing fancy here, just treat it like any other stored procedure), you should be able to set up something like 3-LookupRulesConfig.png. Then when viewing the form you should be able to get the results of the stored procedure querying Active Directory.

For an extra step, one could create a "dictionary" of Windows groups and their distinguished names, then use that as an intermediate step to pass a parameter to the stored procedure so one could select a Windows group by its display name in one field, that then populates another with a list of users in that group.

Apologies for the wall of content, and I hope this helps!

1-LinkedServerGeneral.png
2-LinkedServerSecurity.png
3-LookupRulesConfig.png
3 0
replied on July 27, 2016

This is interesting LOL!...I know when to take a step back and reexamine my "Laserfiche Life Choices"laugh This is definitely for the future ME!

0 0
SELECTED ANSWER
replied on July 28, 2016

While I didn't actually use AD, I used a view that pulls info from the cf-users table in the Forms database. It seems to be storing all the users in Forms System Security. For my purposes, this is a better list than AD because only employees with Forms licenses are displayed:

 

SELECT        username, user_type, displayname
FROM            dbo.cf_users
WHERE        (username LIKE 'OurDomain%') AND (user_type = '1')

 

3 0
replied on July 28, 2016 Show version history

That's very clean, for purposes of choosing a user involved in the process. The WHERE part of the query can be modified to even include non-domain accounts with Forms logins. I recommend making this the marked answer.

The context for when I discovered how to set up the linked server stuff in my post was for a drop-down list that needed to be able to include people from our organization who were not necessarily part of the Forms process, so for that case in particular this would not have worked.

1 0
replied on July 28, 2016 Show version history

I will look into this...This seems like something my IT department might be able to fix up for me.

Glad I started this suggestion...Laserfiche community always has a great idea/workaround!

0 0
replied on January 18, 2017 Show version history

@████████ i'm still having trouble with configuring this the way it was mentioned above by Sheila. I am having trouble with the WHERE part. So following the model you came up with...How exactly would I fill out my javascript? Is "where" the actual field on the form

0 0
replied on January 19, 2017

This isn't in the javascript. It's the SQL used for the view that I created in the database.

I'm not a DBA, so you DBA's out there may cringe at this :)

In your database, right click on Views and select New View.

Close the box that asks you to select a table.

The bottom pane shows the current SQL, which is simply

FROM

WHERE

Change it to

SELECT        username, user_type, displayname
FROM            dbo.cf_users
WHERE        (username LIKE 'OurDomain%') AND (user_type = '1')

replacing "OurDomain" with your domain name.

Select File > Save and give the view a name. Save it and now you have a view that can be used for doing a database lookup. You don't need the username comparison above if your domain name isn't part of the username stored. Our is, and the comparison weeds out some of the usernames that don't belong to the staff.

Once you have the view created, you go into the form where you want a list of usernames and configure it on the Lookup Rules tab.

I hope that helps!

1 0
replied on January 14, 2018

A slightly cleaner alternative approach to the same idea had later been posted here.

0 0
replied on July 26, 2016

I've done this before.  You need to create a "Linked Server" in your Laserfiche SQL Server to the AD Server.  Once this is configured, then you can design a View that can suit your needs.

I can't be much help as far as the actual configuration details are concerned.  I usually have a DBA help configure this.

Hope this helps!

2 0
replied on July 26, 2016

Hmmmm...I think this is out of my reach as a normal user. wink

I am not gonna even attempt to tackle this hornets nest. Hopefully they can come up with an easier way in the future. 

0 0
replied on July 26, 2016

I replied with a similar solution to James but for some reason my reply didn't upload until after James had replied and his looks much better so I've deleted mine.  :o)   However the reason I set it up for myself, in addition to getting the username, email, and department, was in order to configure Form routing to an AD user's manager, retrieving the manager's name from AD.  Problem with that is that querying AD for the SQL table will bring the manager's name back in "CN=..." format so you need to add another column to the table in SQL, and run an additional query to provide the name in "Firstname Lastname" format.  

(Note that this process is limited to a maximum of 1,000 entries.)

I don't have DBA skills so didn't take the Stored Procedure route, just manually created the table with column headings matching the attributes I'm pulling from AD, set up the linked server then set up a SQL query that I run on schedule to pull the required data from AD and overwrite the data in the table (trying to work out how to update the data rather than overwrite it got way too hard for my limited skills).

Here's the initial query where the linked server name is "ADSI" and I'm retrieving all User accounts from AD that have email addresses:

USE [ExternalTables]
GO

DELETE FROM [dbo].[AD_Staff]
      WHERE mail is not null
GO

INSERT INTO AD_Staff(samAccountName, [First Name],[Last Name],displayName,mail,department,manager)
SELECT samAccountName, givenName [First Name],sn [Last Name],displayName,mail,department,manager FROM OPENQUERY(ADSI,'SELECT samAccountName,givenName,sn,displayName,mail,department,manager FROM ''LDAP://DC=DEMO,DC=LOCAL'' WHERE objectClass=''Person'' AND objectClass = ''User'' ORDER BY samAccountName') WHERE mail IS NOT NULL

Below that I've added following lines to format the manager's name:

Update AD_Staff
Set [ManagerName] = REPLACE(SUBSTRING([manager],4,CHARINDEX(',OU=', [manager])-4), '.','')
where manager is not null

And finally, I've saved the query as "D:\SQL_Queries\SyncAD.sql" and configured the following command in Task Scheduler to run the process on schedule:

sqlcmd -S servername -U user -P password -i path_to_query

... with sample data it looks like:  

sqlcmd -S .\SQLEXPRESS -U Scheduler -P password -i d:\SQL_Queries\SyncAD.sql

 

Not as refined as James's solution, but workable.  smiley

1 0
replied on July 26, 2016

Hi Chynna,

I had to do this to pull through the user's Manager's name from AD in order to route a form for approval, so now have a table in SQL with the AD info I need in my forms.  Eric's suggestion to set up a Linked Server in SQL is correct.  I'm not a DBA and don't have much in the way of SQL skills so I've cobbled together solutions I've found online to create the process below and it works really well, with the SQL table being updated - overwritten because the "update" process got way too complicated for me :o) - with the data from AD on a set schedule.  It's not as complicated as it looks, but if you're reluctant to give it a go maybe there's someone who can help you implement it, hence posting it just in case:

(Note: the process below is limited to a maximum of 1,000 records from AD)

First, you have to create a linked server in SQL Management Studio - in this example, called "ADSI" (it can be called whatever you want) in the domain "demo.local".  This can be done through the SQL Mgt Studio GUI via "Server Objects - Linked Servers - New Linked Server" or by running the following query (in SQL Mgt Studio):

 

EXEC master.dbo.sp_addlinkedserver @server = N'ADSI', 

@srvproduct=N'Active Directory Services', @provider=N'ADsDSOObject', 

@datasrc=N'demo.local' 

GO

 

The above only needs to be run once in order to set up the linked server.  Note that the query will set security to "Be made using the login's current security context".  To schedule the updates per the query below you will need to change this to "Be made using the security context" (via the GUI, right-click on the newly created linked server "ADSI", select Properties, and then the Security tab) and enter suitable credentials.

With a table that I created manually beforehand (in this example: "AD_Staff" in database "ExternalTables" with column headings that match the attributes I'm importing from AD), here's the query to update the table from AD, noting that I'm only working with users who have email addresses in AD:

USE [ExternalTables]

GO

 

DELETE FROM [dbo].[AD_Staff]

      WHERE mail is not null

GO

 

INSERT INTO AD_Staff(samAccountName, [First Name],[Last Name],displayName,mail,department,manager)

SELECT samAccountName, givenName [First Name],sn [Last Name],displayName,mail,department,manager FROM OPENQUERY(ADSI,'SELECT samAccountName,givenName,sn,displayName,mail,department,manager FROM ''LDAP://DC=DEMO,DC=LOCAL'' WHERE objectClass=''Person'' AND objectClass = ''User'' ORDER BY samAccountName') WHERE mail IS NOT NULL

 

If you're wanting to use the manager routing functionality, the "manager" name will come through in "CN=....." format which needs to be modified.  To provide a standard display name ("Firstname Lastname") for the manager's name, add an additional column to the table, "ManagerName", and add the following at the end of the above query:

 

Update AD_Staff

Set [ManagerName] = REPLACE(SUBSTRING([manager],4,CHARINDEX(',OU=', [manager])-4), '.','')

where manager is not null

 

To schedule the query, save it locally e.g. "d:\SQL_Queries\SyncAD.sql" and ensure there is a SQL user account with rights to the database - in the example below I'm using a database user in SQL called "Scheduler", with a password of "password".  Here's the base command, followed by an example of what it might look like:

sqlcmd -S servername -U user -P password -i path_to_query

e.g.

sqlcmd -S .\SQLEXPRESS -U Scheduler -P password -i d:\SQL_Queries\SyncAD.sql

 

Test the above command in a command prompt first, then when happy that the command runs as required, insert it into a batch file and call it via Task Scheduler if you want to schedule it to run regularly.

Again, I'm not a proper developer so others might have a better way of achieving this.

Cheers,

Mike

replied on July 28, 2016

I like the solutions you've come up with for accessing information in AD, and I'm sure we'll use those in the future. There are times when we'll want to show all names in the company and not just those in Forms.

0 0
You are not allowed to follow up in this post.

Sign in to reply to this post.