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

Question

Question

Feature Request - Forms Security on FIelds

asked on April 7, 2017

Not sure this is possible, maybe with javascript. But I wish we could set security on Form fields. Now with Teams we are all contributing but I would like to have on certain people with rights to change a field. 

Like we are working on Project Ticket Request Form. Well the Project Manager should be the only one with the ability to change the projected date and complete the project, but we want everyone to have the ability to add action items to the ticket and also keep track of the project. 

Security on the Forms just makes everything a lot more cleaner.

0 0

Replies

replied on July 9, 2018

Hey @████████ - it's been a while!

It it a lot more complicated that you would think.  

Lucky for you - I've already been working on a similar process.  I send these weekly emails to staff members who have been sitting on forms without completing them, and I want to automate the process, so I'd been researching how that part of the database works, and I've nearly got my process complete.

So here's a query that you can use, that basically mimics what you see in the "Monitor" page in LFForms. 

When testing, you may see more results returned than when you review the "Monitor" page, because in the case of a form assigned to multiple users, it'll have a separate line item in the query results for each user.  In the case of a form assigned to a team, but it hasn't been claimed by a team member (it's showing "available") the query will return whichever user(s) is/are assigned as the "manager" for the team.

You'll notice that part of the WHERE statement is commented out (the part that limits the search to processes that have been open for a certain amount of time - showing 15 days currently) - I left that out so it is easier to compare to your "monitor" page.

USE [LFForms]
GO

SELECT 
  subquery.[Process Name], 
  subquery.[Instance name], 
  subquery.[Started by], 
  subquery.[Last updated], 
  subquery.[Assigned to], 
  subquery.[Assigned to (username)], 
  subquery.[Assigned to (email)], 
  subquery.[Current step], 
  subquery.[Step start date], 
  subquery.[Start date], 
  subquery.[Instance ID]  
FROM ( 
  SELECT  
    instance.bp_name AS [Process Name], 
    instance.title AS [Instance name], 
    CASE  
      WHEN start_user_snapshot.displayname LIKE '%WORKFLOW%' THEN 'Workflow' 
      ELSE start_user_snapshot.displayname
    END AS [Started by], 
    instance.lastacted_date AS [Last updated], 
    CASE 
      WHEN bp_worker_resume.status = 5 THEN assigned_user_snapshot.displayname 
      WHEN bp_worker_resume.status = 2 THEN assigned_user_snapshot.displayname 
      WHEN assigned_user_team_snapshot.displayname IS NULL THEN teams.name 
      WHEN bp_worker_resume.status = 1 THEN assigned_user_team_snapshot.displayname 
    END AS [Assigned to], 
    CASE 
      WHEN bp_worker_resume.status = 5 THEN assigned_user_snapshot.username 
      WHEN bp_worker_resume.status = 2 THEN assigned_user_snapshot.username 
      WHEN assigned_user_team_snapshot.displayname IS NULL THEN team_users.username 
      WHEN bp_worker_resume.status = 1 THEN assigned_user_team_snapshot.username 
    END AS [Assigned to (username)], 
    CASE 
      WHEN bp_worker_resume.status = 5 THEN assigned_user_snapshot.email 
      WHEN bp_worker_resume.status = 2 THEN assigned_user_snapshot.email 
      WHEN assigned_user_team_snapshot.displayname IS NULL THEN team_users.email 
      WHEN bp_worker_resume.status = 1 THEN assigned_user_team_snapshot.email 
    END AS [Assigned to (email)], 
    bp_worker_resume.step_name AS [Current step], 
    bp_worker_resume.assign_date AS [Step start date], 
    instance.start_date AS [Start date], 
    instance.bp_instance_id AS [Instance ID] 
  FROM cf_bp_main_instances AS instance 
    LEFT JOIN cf_user_snapshot AS start_user_snapshot ON start_user_snapshot.id = instance.user_snapshot_id 
    LEFT JOIN cf_bp_worker_instances AS bp_worker ON bp_worker.bp_instance_id = instance.bp_instance_id 
    LEFT JOIN cf_bp_worker_instnc_to_resume AS bp_worker_resume ON bp_worker_resume.worker_instance_id = bp_worker.instance_id 
    LEFT JOIN cf_bp_worker_instance_history AS bp_worker_history ON bp_worker_history.instance_id = bp_worker.instance_id AND bp_worker_history.status = 'assigned' AND bp_worker_resume.owner_snapshot_id IS NULL 
    LEFT JOIN cf_user_snapshot AS assigned_user_snapshot ON assigned_user_snapshot.id = bp_worker_resume.owner_snapshot_id 
    LEFT JOIN cf_user_snapshot AS assigned_user_team_snapshot ON assigned_user_team_snapshot.id = bp_worker_history.target_snapshot_id 
    LEFT JOIN teams AS teams ON teams.id = bp_worker_resume.team_id AND bp_worker_resume.owner_snapshot_id IS NULL 
    LEFT JOIN team_members AS team_members ON team_members.team_id = teams.id AND team_members.member_rights = 3 
    LEFT JOIN cf_users AS team_users ON team_users.user_id = team_members.user_id 
  WHERE instance.status = 1 
    AND (bp_worker_resume.status = 5 OR bp_worker_resume.status = 1 OR bp_worker_resume.status = 2) 
    AND bp_worker_resume.assign_date IS NOT NULL 
    --AND instance.start_date <= DATEADD(DAY, -15, GETDATE()) 
  ) AS subquery 
GROUP BY subquery.[Process Name], subquery.[Instance name], subquery.[Started by], subquery.[Last updated], subquery.[Assigned to], subquery.[Assigned to (username)], subquery.[Assigned to (email)], subquery.[Current step], subquery.[Step start date], subquery.[Start date], subquery.[Instance ID] 
ORDER BY subquery.[Start date] 

 

3 0
replied on April 7, 2017

I do this with Javascript.  I have a hidden field that gets the user's name and then a lookup from a database table that I use for HR forms, it includes a lot of data on each employee, include a permission level (which is just Regular, Manager, or Human Resources).  Then I use Javascript to tweak the desired fields based on the permission level.  It does mean I have to track the permission outside of forms itself, but it works.

In theory, you could do the same thing using the actual Forms database and get the users permissions that way, but I've never tried to do that.

2 0
replied on April 7, 2017

Of course you can always have alternate versions of the form for the different permissions and then route them differently in your process diagram, but I don't like having more versions of a form than is necessary.

0 0
replied on April 7, 2017 Show version history

It actually wasn't that hard to figure out how the Forms teams and roles are stored in the database (they're very logically stored)...

SELECT u.username, 
  u.email, 
  u.displayname, 
  t.name AS team_name, 
  tr.name AS role_name 
FROM cf_users AS u 
  LEFT JOIN team_members AS tm ON tm.user_id = u.user_id 
  LEFT JOIN teams AS t ON t.id = tm.team_id 
  LEFT JOIN team_member_team_role_mapping AS trm ON trm.team_member_id = tm.id 
  LEFT JOIN team_roles AS tr ON tr.id = trm.team_role_id 
WHERE tm.join_date IS NOT NULL 
  AND tm.leave_date IS NULL 
  AND t.is_deleted = 'False' 

 

1 0
replied on April 7, 2017

Okay, I just tested this and it worked!

I added this Stored Procedure to the LFForms database: 

-- ================================================
-- Template generated from Template Explorer using:
-- Create Procedure (New Menu).SQL
--
-- Use the Specify Values for Template Parameters 
-- command (Ctrl-Shift-M) to fill in the parameter 
-- values below.
--
-- This block of comments will not be included in
-- the definition of the procedure.
-- ================================================
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author:		Matthew Tingey
-- Create date: April 7, 2017
-- Description:	Checks if the entered user is a part of the entered team and role
-- =============================================
CREATE PROCEDURE GetUserPermission 
	-- Add the parameters for the stored procedure here
	@username varchar(100), 
	@teamname varchar(100),
	@rolename varchar(100)
AS
BEGIN
	-- SET NOCOUNT ON added to prevent extra result sets from
	-- interfering with SELECT statements.
	SET NOCOUNT ON;

    -- Insert statements for procedure here
	SELECT 'True' AS result 
    FROM cf_users AS u 
      LEFT JOIN team_members AS tm ON tm.user_id = u.user_id 
      LEFT JOIN teams AS t ON t.id = tm.team_id 
      LEFT JOIN team_member_team_role_mapping AS trm ON trm.team_member_id = tm.id 
      LEFT JOIN team_roles AS tr ON tr.id = trm.team_role_id 
    WHERE tm.join_date IS NOT NULL 
      AND tm.leave_date IS NULL 
      AND t.is_deleted = 'False' 
	  AND u.username = @username 
	  AND t.name = @teamname
	  AND tr.name = @rolename
END
GO

 

Then I added LFForms as a data source for my forms process.

Then I added four single line fields to my form:

Then I set the fields to populate via the Stored Procedure:

And the end result is that the "User Had Role?" field is left blank if the three values don't match, or populates True if they do.

I'd probably want these all to be hidden fields, so I'd need some Javascript to auto-click the "auto-fill" button.  And then I'd need Javascript (or field rules) to dictate what happens when the "User Had Role?" field is True.

That was really fun to figure out!

2 0
replied on April 7, 2017

My only worry would be if future Forms updates ever broke (or deleted) the stored procedure...

0 0
replied on April 9, 2017

Forms updates won't delete the stored procedure that was not defined by Forms itself.

1 0
replied on July 9, 2018

You...are....marvelous!  This is fantastic, thank you!

 

I effectively combined this script you just posted with the idea from the one above from April 2017 and saved it as a stored procedure.  I then added a condition line:

 @instanceid varchar(100)

And added another line to the Where condition.  (In front of line 60 the commented area):

AND instance.bp_instance_id = @instanceid 

 

With both of those, I can have the fields populate with forms lookup rules with the username values, to send the reminder emails.

 

Thank you again!

1 0
replied on July 9, 2018

Thank you @████████ - I'm glad you think so wink  Do you mind informing my wife of my marvelousness? laughlaughlaugh

I'm just happy to help - I'm really glad it worked for you.  And I got my email process automated now too smiley

 

1 0
replied on July 10, 2018 Show version history

As a followup - this works in workflow too.  Simply use your query posted yesterday in a custom query.  I used the extra criteria to filter it based on instance.

AND instance.bp_instance_id = ?

The workflow itself is very simple:

2 0
replied on July 6, 2018 Show version history

@████████

 

I'm following a similar train of thought here and am exploring the Forms Database a bit.  Would you happen to know what table I'd be able to see what user(s) a task is currently assigned to?  

 

Essentially, since you can't assign a team to an email task, I'm trying the next best thing an am going to see if I can have workflow do a sql query and get the usernames of the people assigned to a particular step in a particular instance.  I'm sure it will be extremely static, with alot of steps, and be very clunky, but there isn't much I can do otherwise until the email task supports teams.

 

Edit: I'm betting it will probably won't be a clear naming of a the people.  Rather, it'll probably list their user_id values.  (End Edit)

 

If not, I'll post the question to the main feed of answers.  Thanks!

0 0
replied on October 15, 2018

@████████

 

Another question related to this -- I'm looking to use this with a process that is split by an inclusive gateway.  I should be able to use the Current Step variable in your stored procedure, but I'm not quite sure the best way to get the current step value passed to workflow with forms.  

 

I did a brief search on answers, but didn't find anything.  I figured I would ask if you had any ideas before spending longer searching and/or posting a direct question.

0 0
replied on October 15, 2018

Hey @████████- That current step should be the user task(s) that are currently assigned out.  I haven't tested this part out.  But if you go to your Workflow Properties and check the box to say it was "Started by Laserfiche Forms"  Then you get a bunch of new tokens (categorized under "Input Parameters").  There may be some tokens in there that apply to user tasks.  Although, you may not be able to find user tasks that are active, maybe just the last one that was submitted or something like that...

0 0
replied on October 15, 2018

You inclination is correct in that the "started by Laserfiche Forms" tokens only seem to show the step ID and submitter info from the last step of an actual submission.  I'm haven't been able to find anything related to the Current Step.

 

One workaround/idea is to use your stored procedure and the instance ID from forms to find "all" current step values.  Then, for each current step and instance ID, search for the users assigned to that step.  

 

It would would mean reworking the Business Process in forms to somehow repeat the workflow once per day, rather than having it run from each step like I do.  It also would mean having workflow send the email instead of forms.  But if there is no way to send the current step from forms to workflow, then it is the only way.

1 0
replied on October 15, 2018

I think you might be right @████████

 

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

Sign in to reply to this post.