Development
- Agile
- Definition of Done
- Stand up
- Agile Trainings
- User Story Template
- Agile Discussion Jan 25 2021
- ADO Work Item Standardization
- Emails
- AccessLink
- Share
- EmailFiles
- EmailImportFailure
- EmailImportMaxFailure
- MfaAuthCode
- MfaQrCode
- NewDocumentRequest
- NewUser
- PasswordReset
- SmtpEmailSettingFailure
- SmtpEmailSettingMaxFailure
- Status
- TestEmail
- Form Fill
- PrizmDoc Resources
- File Request Recipient
- File Request - Form Fill Create
- UI Mockups
- Form Fill User Experience
- Integromat
- Mac Desktop Client
- OCR
- PostgreSQL
- Previewer
- PreviewerX (Apryse)
- RPC
- Rubex Reports
- Scripts
- Setup and Configurations
- Connecting to UtopiaNuget
- Steps to setup pg_partman
- How to run and Release Mobile
- SonarCloud and SonarLint Setup Steps
- How to Run WOPI Validator Tests on O365
- AWS DMS Setup
- Previewer Setup for Local Environment
- OCR Worker Local Setup
- Windows Services
- Setup/Configurations for Mac Mini
- Office Addins Terminal Services Environment
- Utopia Local DB Refresher
- Generating a DB Connection String
- How to Sign and Notarize a New Build for the Mac
- How to Renew a Certificate for Mac
- Local Testing
- Standards
- SIGNiX
- Technologies
- Utopia
- Windows File Encryption
- Open Source Software List
- First Time Setup - Utopia (Work in Progress)
- Utopia Articles of Permissions (2020)
- Utopia Architecture Notes (2020) Has Changed
- File OCR Worker debugging (2021)
- Utopia Bundle Installer build instruction
- Azure Active Directory SAML Configuration (2020)
- OneLogin SAML SSO Configuration
- Okta SAML SSO Configuration
- Entity Framework Code First
- Code First Training Video
- Entity Framework Optimizations
- Adding a new Email Type
- Utopia External Login Instructions and Options
- Test Against Production Read Replica
- How to run local Utopia over LAN/connect from outside network
- How to create a new user license type
- Concurrent Licenses
- Utopia Architecture
- Windows Desktop Client
- Utopia Windows Desktop Client Update Creation Process
- Update CefSharp to 64 bit (when we want to do it)
- Client Application Update Process
- Code Scanning
- How To Update CefSharp Version
- Archived
- Unit Testing
- Azure
- Postman
- Azure Dev Ops
- Offloaded Operations
Agile
Definition of Done
We consider a User Story or Defect to be complete when it has met the following criteria:
- Meets the Acceptance Criteria for the story
- Engineer has done their own testing and verified that everything is working as expected
- Smoke tests (ensure that it builds and runs) for Utopia project and any others as needed
- Tested by the team tester as applicable
- Pull-requested into a feature
- As part of the pull-request, the branch is reviewed by at least two other Engineers
- All tasks on the story are marked as completed
Stand up
3 Standup Questions (per story)
-
How far along are you?
-
Will you complete in time?
-
Who can help ? (How can we adjust the collaboration)
Agile Trainings
Agile-GettingStarted.pptx
Agile Training to go over the basics of Agility, covering:
- Agile Manifesto Values and Principles
- User Story Writing
- Requirements Hierarchy: Epics, Features, User Stories
- Estimation techniques
- High-level overview of Scrum and Kanban
ProductOwnerTraining.pptx
Product Owner Training
ScrumMasterTraining.pptx
Scrum Master Training
User Story Template
User Story
Write user story text description.
Note
User stories should be written according to the following pattern:
As a <type of user>
, I want <some goal>
so that <some reason>
.
Important: a user story should consider needs of particular type (most often role) of user.
User stories should follow INVEST principles:
- Independent. Reduced dependencies = easier to plan;
- Negotiable. Details added via collaboration;
- Valuable. Provides value to the customer;
- Estimable. Too big or too vague = not estimable;
- Small. Can be done in less than a week by the team;
- Testable. Good acceptance criteria.
Note: large (those which won't fit into a single sprint) user stories, also called epics, should be eventually split into smaller user stories (if it's possible at the moment).
Each user story will go through the following lifecycle before implementation begins:
- Writing a user story (anyone is allowed to write a user story, most often it'll be Product Owner);
- Discussion (all teams should take part in the final discussion):
- [Optional] Breaking an epic into smaller user stories;
- Splitting into sub-tasks (with tech specifics);
- Verification of acceptance criteria completeness;
- Update user story contents if needed;
- Mark as ready. Goes to the implementation pipeline when it's time.
Activity
Note
Activities (also known as themes) are common groups (usually features) that combine user stories together. As an example, "Account" activity may contain user stories describing registration, password recovery, profile updates, etc. Granularity of activities should be chosen in a way that doesn't lead to activities with too many user stories (in such cases these activities should be split into smaller ones).
When combined with user stories, activities present a good visualization of the backlog, called user story map.
Type
Epic or User story. Epics should only be used as a temporary stub for user story(ies). See definition of an epic above.
Status
Status of user story readiness in terms of the lifecycle. A user story should only be marked as ready when all sections were filled in and reviewed by team members.
An example:
- In icebox (new);
- In backlog (discussion in progress);
- Ready to go (discussed and verified);
- In progress, in testing, etc.
Components
Provide a list of affected components (e.g. back-end, front-end, etc.).
Sketches/wireframes/mockups
All graphical data goes here (with some captions if necessary).
An example:
Workflow
Describe the whole workflow from user's perspective, step by step, with all necessary details.
All stakeholders should be able to understand contents of this section, so no sophisticated technical details should be placed here.
An example:
- User opens web app link.
- User enters credentials.
- User logs in and sees the dashboard.
Acceptance Criteria
Describe details that are required to validate the software once it's implemented: UI elements behavior, validation logic, messages of all types (validation errors, hints, etc.).
An example:
- Security
- No other web pages except Sign In should be available for non-authenticated users.
- When a non-authenticated user opens a link leading to one of internal pages and then logs in, the app should redirect the user from Sign In to the page corresponding to the original link
- UI elements
- "Login" input field
- Required field
- Maximum 255 characters
- "Login" input field
Tech Notes
Describe all low level technical details here, like API specification, error handling conventions, timeout values, etc. May also contain some diagrams, (pseudo) code snippets, etc.
Links
Provide links to related epics/user stories, mockups, API specification, other high-level design documents, etc.
Agile Discussion Jan 25 2021
Named Roles:
Splitting of PO and Scrum Master
- Product Owner (PO) - similar to Product Manager, prioritize sprint work based off of the product manager. Remove blockers along with the scrum master and work with scrum master/PO from other teams
- Scrum Master - manages the logistics/ceremonies and coaching the team
- Quinn and Royce become the POs - need to find who will be SM on each team (Bryan and Abe)
- Meet with POs to discuss organization of backlog, aggregation of team boards, reorganize around features
Do a full split of the teams, not a large kanban of items.
Ceremonies in Order:
- Will be covered in training, SM will create and organize
Product Council:
- Discuss processes, backlog, prioritization
- Separate from current Stakeholder meeting
Release Cycle:
Faster releases - Goal of constant releases during the day
Action Items:
- Check with Abe and Bryan to become SMs - Royce & Quinn
- Training on SM/PO roles (Agile training - 3hr WED, SM/PO - 1.5-2hrs each FRI and then following WED 8:30am MST) - Bryce
- Product Council meeting - setup weekly meeting (Eventually include all process stakeholders: Marc, Brian, Jesse, Eric, Emily)
ADO Work Item Standardization
User Stories
Bugs
The primary difference between a bug and a user story is that the bug should include the Repro Steps
Emails
Guide on how to trigger each email.
AccessLink
How to trigger:
- Your user must have the Access Links user permission.
- Go to Admin Panel > Users and Groups > Users page
- Hover over the user row you want to grant an Access Link for
- Click the Create Access Link icon
- You'll be brought to the Create Instant Sign-In Link page where you can customize the access link settings.
- Once finished customizing, click Send.
Share
How to trigger:
- Your user must have the Sharing user permission.
- From the Home page, get to the node view (expand an account, a cabinet, and a drawer)
- Right click on a node, and select Share
EmailFiles
How to trigger:
- Your account must have the Email Files account feature
- Your user must have the Sharing user permission
- Open the left menu and click on Admin
- In the Admin panel, click on Settings
- Scroll to the Email Files section, and check the Allow Email of Files checkbox
- From the Home page, get to the node view (expand an account, a cabinet, and a drawer)
- Right click on a node, and select Email
- This will open the Email Dialogue
- Select who the email will be sent to and customize the Subject and Content
- Click send
EmailImportFailure
How to trigger:
- Account must have the Email Import account feature
- You'll need to set up an email import using an app password
- Once the setting is complete, change the app password in your email and this should trigger the failure
EmailImportMaxFailure
How to trigger:
- Allow your Email Import to fail for 4 days in a row.
MfaAuthCode
How to trigger:
- Under the Two Factor Authentication section, select the Enable Two Factor Authentication checkbox
- Select the Email Token option
- Save your changes
- Log out
- Enter your username and password and attempt to log in again. This will trigger the email to be sent with the code.
MfaQrCode
How to trigger:
- Under the Two Factor Authentication section, select the Enable Two Factor Authentication checkbox
- Select the Mobile Authenticator App option
- Save your changes
- Log out
- Enter your username and password and attempt to log in again. This will trigger the email to be sent with the QR code.
NewDocumentRequest
How to trigger:
- Your account must have the Document Requests account feature
- Your user must have the Document Requests user permission
- Open the left menu, hover over Document Requests, and select New Request
- Fill out the information on the New Request page
- Click Send Request
NewUser
How to trigger:
- You must have the User Management user permission
- Open the left menu and click on Admin
- Click Users and Groups
- From the Users page, click the Add User link
- Fill in the new user information and click Create
PasswordReset
How to trigger:
- From the login page, click the Forgot Password? link.
- Enter your email address/username and click Send Reset Link
SmtpEmailSettingFailure
How to trigger:
The only way I've been able to trigger this consistently is to
- Turn off Azure Storage Emulator
- And then follow the steps for sending an Email file
SmtpEmailSettingMaxFailure
How to trigger:
Status
How to trigger:
- I'm not sure of all the actions that trigger a Status email, but I know if you complete a Document Request, it will trigger this email.
TestEmail
How to trigger:
- Under the Email Settings section, click Add Email Setting
- Select your email provider
- Once your new email setting has been established, a test email will be sent.
Form Fill
PrizmDoc Resources
Sample Projects:
prizm-samples-mvc.zip
prizm-samples-webforms.zip
File Request Recipient
File Request - Form Fill Create
UI Mockups
Previewer
Adding a default Template Library to store Form Definitions
Designer View - Allow linking of profile items to Form fields
Templates - Allow Multi Select and Partial Template application
Database Model
Form Fill User Experience
Phase 1:
Add manual push using Form Template in the Profile Dialog of Right pane menu
Expose Anonymous File Requests and Share in Workflow
Add step in workflow to push profile using form fill
Add file request container type that uses a file and form fill template
Cleanup Accusoft UI, change button locations.
Change Name of Checklist for things filler needs to do
Phase 2:
Zonal OCR form template fields
Misc..
Change annotation Tool Order
Research:
Guided Form Fill
Auto-save Form Fill - Both Design and Playthrough
Need to allow filling it out partially and then resuming
User Stories:
User pushes metadata into document using Form Fill Template
User Creates Form Fill Template and asks different user to fill it out
User Fills out document and info is pulled into profile
Notes:
- Possibly accessible from templates admin and from a new screen in the right panel that's specifically for form fill templates
- Templates apply form fill templates as well?
- Tie a profile to a form fill template
- 3 modes in previewer - View, Designer, Fill Form
- Filling out form needs to save progress and needs to confirm completion
- Progress indicator during form fill needs to be more clear (especially with 0 fields filled)
- Next button to continue during form fill
- Good icon to indicate FormTemplates on NodeDetails panel, different from preview or design
- Icon on node in nodelist that indicates a document needs to be filled out
- Fill Form icon needs to disappear after complete is clicked
- New view of forms that aren't filled out
More Notes:
- Need for uploading form template files from inside of our system
- Make apply template selector a multi-select? Can then apply full template or individual form templates
- Easily applying a form template into a new location is a major factor
- Creating form fields: Profile boxes and allow editing of custom boxes
Form Fill Profiles:
- Items are divorced from Profiles if a node's profile is changed, they are still displayed underneath the current profile
- First selected Profile in the designer is set as the document's profile
- Add dropdown to specify profile for a document in the top right
- Add ability/checkbox to force the profile, even if required profile items aren't added or parent profile is different otherwise it is a "suggestion" if it can be applied
Previewer UI
- Keep black bar at top and bottom at all times if possible
- Drop down for selecting Profiles/Profile items
Templates
- Apply template selector will allow multi-select and partial application of templates
- Possible UI updates, apply template tree on left with selected node list on the right
- All selected template nodes will be applied at the top layer with all of their children
- Update sync changes logic to handle when the parent node does not exist
- Reuse the current apply template endpoint and do one at a time in order selected
- Investigate mass apply to take multiples as well
- Need to indicate
DB Model:
-
Store full JSON inside DbFormFillDefinitions
-
Add table that links profileItems to FieldIds and the FormFieldDefinition (Unique constraint on FormFieldDefinition, FieldId together?)
-
If they change definition with pending form fills, then notify before the save
-
If saved, then delete all pending
-
Designer does not need to autosave, only filling forms
File Requests:
-
Add option Request File, Request Multiple Files, or Request Form (Request Using Fillable Form, Form Fill Request)?
-
Remove default File Request Container
-
Enable editing in node selector
-
Allow uploading
-
After file request, open up form fill editor
-
Linking table between container and files for document?
-
Reuse template permissions to allow creating of form fill requests?
-
New linking table DbFileRequestFormFillContainer (FormFillDefinitionId, OriginatingFileInfoId)
-
File specific ones in it's own table DbFileRequestFileContainer
-
DbFileRequestCurrentFormFills (FormFillDefinitionId(Different from Originating), OriginatingFileInfoId, UserId(Who is filling out the form)) When complete form, then fill out form and insert into FileRequestContainer
-
Open Iframe to edit - In url access token, form fill id, fileinfoid, optional : fileRequestContainerId, optional : nodeId
-
Copied when someone comes in to fill it out if it's multiple, otherwise everyone fills out the same document
-
Once it's completed, then original node is copied and form is burned into document and stored,
-
To add profile, maybe hit our own api first and intercept the info
-
Min and max for "IsMultiple"?
-
Offer to reuse a definition when adding to a file request
-
Check for existing FormFillDefinitions
-
Need to add verbage to indicate Container (Or something better)*
-
Deliniate between template form request or from storage, node selector will allow uploads
-
After node selection, pop up with preview in designer mode
-
Form fill container, "Select File" until selected, then show change or edit form fill
-
If selected item has a FormFillDefinition, offer to copy or create new, then go to designer mode
-
In Form Fill Container, allow configuring of min/max, max allow nullable for infinite?
-
Messaging of when Form Fill is saved? It's an iframe, so we can't just get the JSON and the filerequest doesn't exist yet to allow us to save. For now plan on messaging with the iframe.
Notes for FormFill Request Creation
- Multiple form fills for the same container, UI needs some work possibly
- Regular buttons, not container
- "Files to Request" to "Documents to Request"
- Template vs Storage, popup
- Pass FormFillDefinition JSON between windows, can't be saved to db until request is complete
- Add edit button to FormFillContainer
- Allow fulfillment per user or all users
- Container: Requirements for completion header
- Maybe: Container uses tally
- Required Uses instead of min/max?
Ideas for Recipient playthrough
To Ask Jessie:
- Renaming of File Requests to Document Requests
Integromat
Getting Started
Setup
- Head to integromat.com
- Login
- Username: development@efilecabinet.com
- Password: Ask Trevor
eFileCabinet App
Click here to see our app.
An integromat app is composed of several components. The important ones are:
-
Base
- This is the parent structure that all modules and remote procedures inherits from, if you notice that every module is using a header or requiring some other piece of information, then place it here
-
Connections
- It is possible to create more than a single connection if a module requires something unique
- The active connection is the one where oauth2 does it's magic
- The current connection is setup in a way that it fetches the token and saves it inside of memory.
- To access this token, call
connection.accessToken
- To access this token, call
- The "Common Data" section at the bottom allows us to hold parameters that we need, but wish to keep private such as the base64 encoded access string
- This will need to be adjusted after we setup an integromat specific connection
- Currently it is set up to renew the connection when there is less than one minute remaining
- See:
"condition": "{{if(data.accessToken, data.expires < addMinutes(now, 1), true)}}"
- See:
- The "Parameters" tab is what indicates the user input. In this case, the user's username and password that will be used during authentication
-
Modules
- Modules are generally set up in a way to accomplish a single task, not single calls to our api
- The "Communication" tab is where it will make it's calls to our api, save and manipulate temporary data, and perform basic logic
- Any logic performed must follow the IML pattern see IML functions in the integromat documentation
- The "Static Parameters" tab allows for user input only and is rarely used
- To use parameters (static or mappable), simply call
parameter.ParameterName
- To use parameters (static or mappable), simply call
- The "Mappable Parameters" tab allows for user input in a more fluid way. It also allows for Remote Procedures (RPC) to be called, allowing a better user experience. This is what should generally always be used
- I've noticed that it is easier to start here during module creation as you'll probably need to use or create a RPC to use or fetch additional input
- To use parameters (static or mappable), simply call
parameter.ParameterName
-
Remote Procedures (RPC)
- Are sub modules that can are ran while the user is selecting parameters, before the module itself is ran
- They are used to fetch input needed to run the app's module
-
IML Functions
- IML is a feature that allows you to write your own JavaScript functions and execute them inside IML expressions to process data
- IML functions are disabled by default. Luckily for you, I've already contacted them to unlock it.
Remote Procedure Calls (RPCs)
What are they?
- Think of RPCs as sub modules that are called to help the main modules get the inputs they need
- They CAN NOT be called inside the module itself, instead, they are called inside of the "Mappable Parameters" tab
How do I use them?
- List Files
- Call this using
rpc://listFolders
- Call this using
- List Folders
- Call this using
rpc://listFiles
- Call this using
List Files
Communication
Each number in the following ordered list is referring to a block in code
- This block grabs the parent workspace id and initializes a counter so that the RPC will know where it currently is when it iterates in block 2. It also determines the last string in the path so that block 2 knows when it is done iterating
- This block iterates through each string in the path to get the nodeId by it's name
- It knows it is done when the
lastNamePath
is equal to itscurrentName
- This
"condition": "{{if(parameters.path !== '/', true, false)}}"
will prevent it from running when there is no path entered so as to save an API call
- It knows it is done when the
- This will show the user the next layer in the path
Notice
"response": {
"iterate": "{{body}}",
"output": {
"label": "{{item.name}}",
"value": "{{item.id}}",
"file": "{{if(item.systemType === 7, true, false)}}"
}
}
- Our API responds with an array instead of an object, as a result Integromat does not know how to output the data
- This means that we need to iterate through each element in the array and output the information we require
- This
"file": "{{if(item.systemType === 7, true, false)}}"
is what determines if a proper file has been selected. If it evaluates to false then the module cannot proceed and will run the RPC again until it returns true
List Folders
Communication
Each number in the following ordered list is referring to a block in code
- This block grabs the parent workspace id and initializes a counter so that the RPC will know where it currently is when it iterates in block 2. It also determines the last string in the path so that block 2 knows when it is done iterating
- This block iterates through each string in the path to get the nodeId by it's name
- It knows it is done when the
lastNamePath
is equal to itscurrentName
- This
"condition": "{{if(parameters.path !== '/', true, false)}}"
will prevent it from running when there is no path entered so as to save an API call
- It knows it is done when the
- This will show the user the next layer in the path
Notice
"response": {
"iterate": "{{filterFolders(body)}}",
"output": {
"label": "{{item.name}}",
"value": "{{item.id}}"
}
}
- Our API responds with an array instead of an object, as a result Integromat does not know how to output the data
- This means that we need to iterate through each element in the array and output the information we require
- An IML function is called on the body to filter out all file node objects from the body
Modules
As of 10/06/2020, we have 4 modules built:
Download a file
-
- From eFileCabinet to another source
- Uses connection "eFileCabinet oauth2"
Required Inputs Using Mappable Parameters
- File
- A way for the user to dig into the file structure to find a valid file. This uses the RPC List Files
Interface
Note that this tab is only used when you need to specify to other modules what your output will be
- Data
- This is the content of the data (file)that is going to be sent
- File Name
- This is the name of the data (file) that is going to be sent
- File Size
- This is the size of the data (file)that is going to be sent
Communication
Each number in the following ordered list is referring to a block in code
- This block grabs the parent workspace id and initializes a counter so that the module will know where it currently is when it iterates in block 2. It also determines the last string in the path so that block 2 knows when it is done iterating
- This block iterates through each string in the path to get the nodeId by it's name
- It knows it is done when the
lastNamePath
is equal to itscurrentName
- This
"condition": "{{if(parameters.path !== '/', true, false)}}"
will prevent it from running when there is no path entered so as to save an API call
- It knows it is done when the
- This block uses the pathId and the accessToken to makes a call to our API so that we can GET the file to download
Upload a file
- From another source to eFileCabinet
- Uses connection "eFileCabinet oauth2"
Required Inputs Using Mappable Parameters
- Directory
- This is where the user selects the Folder or Drawer that the file is to be saved in
- This uses RPC List Folders
- Notice that the name is called path, this is true because the value being return from the RPC is in format
abc/def/ghi
- File Name
- This will auto fill if the user "Source File" - (Other module input)
- Data
- The file that will be uploaded and should be auto filled when another module links to it
Communication
Each number in the following ordered list is referring to a block in code
- This block grabs the parent workspace id and initializes a counter so that the module will know where it currently is when it iterates in block 2. It also determines the last string in the path so that block 2 knows when it is done iterating
- This block iterates through each string in the path to get the nodeId by it's name
- It knows it is done when the
lastNamePath
is equal to itscurrentName
- This
"condition": "{{if(parameters.path !== '/', true, false)}}"
will prevent it from running when there is no path entered so as to save an API call
- It knows it is done when the
- This block processes the node that the user has input by selecting the last node. It then saves this id into a temp variable called "pathId"
- This block attempts to create the file in the requested parent node
- If there is an error (as seen in the response body), then it will take the suggestedName in the Batch Object name for block 3
- Conditional block: This block will only run if the suggested name received in block 2 does not equal the file name parameter received
- If this runs it will create the node with the suggested name
- Now that the node has been created it will begin the upload process. This block will FileUpload POST to retrieve the
uploadIdentifier
- With the
uploadIdentifier
retrieved, this block will start the data upload - Once the data has finished uploading, it will finalize by sending
"complete": true
Create a node
-
- Create a new Folder, Drawer, or Cabinet
- Uses connection "eFileCabinet oauth2"
Required Inputs Using Mappable Parameters
- Name
- The name of the new node
- Node
- A way for the user to select the parent Cabinet, Drawer, or Folder
- This uses a mappable for of input, where the user just clicks the node in question, starting with the workspace and working down until they've selected the parent node in question
- This uses the RPC List Folders
Communication
Each number in the following ordered list is referring to a block in code
- This block grabs the parent workspace id and initializes a counter so that the module will know where it currently is when it iterates in block 2. It also determines the last string in the path so that block 2 knows when it is done iterating
- This block iterates through each string in the path to get the nodeId by it's name
- It knows it is done when the
lastNamePath
is equal to itscurrentName
- This
"condition": "{{if(parameters.path !== '/', true, false)}}"
will prevent it from running when there is no path entered so as to save an API call
- It knows it is done when the
- This block uses the pathid found in block 2 to make a call to our API so that we can fetch the systemType. It then saves that in to temp variable "parentSystemType".
- This block starts by figuring the systemType of the new node, then it will POST the new node using the pathId, systemType, and name
- If the parent is a workspace, it will create a cabinet
- If the parent is a cabinet, it will create a drawer
- If the parent is a drawer, it will create a folder
- If the parent is a folder, it will create a folder
Rename a node
-
- Rename a File, Folder, Drawer, or Cabinet
- Uses connection "eFileCabinet oauth2"
Required Inputs Using Mappable Parameters
- This begins with a Select dropdown, where the user can select either a file or a folder
- File - calls RPC List Files
- Folder - calls RPC List Folders
- Name
- The name they want the new item to be called
Communication
Each number in the following ordered list is referring to a block in code
- This block grabs the parent workspace id and initializes a counter so that the module will know where it currently is when it iterates in block 2. It also determines the last string in the path so that block 2 knows when it is done iterating
- This block iterates through each string in the path to get the nodeId by it's name
- It knows it is done when the
lastNamePath
is equal to itscurrentName
- This
"condition": "{{if(parameters.path !== '/', true, false)}}"
will prevent it from running when there is no path entered so as to save an API call
- It knows it is done when the
- This block uses the pathId found in block 2 to update the node using PUT with the gathered name in the body
Mac Desktop Client
Mac Desktop Client
see README.md in source code
OCR
OCR Web Wrapper Image
To create the image of the web wrapper, you need to do 5 things:
- Spin up Windows Server base Image.
- Add IIS
- Ensure/Add .NET Framework extended/ ASP.NET in Windows Features
- Install Visual C++ 2010, 2012, 2013, 2015/2022
- Copy publish folder of the OCR Web Wrapper project
PostgreSQL
PostgreSQL Information
**Note: If you don't have the Utopia solution cloned to your local machine, follow these instructions
Installation and Setup
- In order to get a postgres db up and running on your local machine, you first need to install PostgreSQL.
- You can get the installer from the site or from this eFile quick link . Download v13.2 for Windows.
- During installation it will ask you for a password. Feel free to make this any password you like, but be sure to remember it, as you will need to use it to connect to PgAdmin.
- DO NOT just download PgAdmin 4. This will install the PgAdmin client, but you will not have a running PostgreSQL server on your local machine. If this applies to you, just follow the link above to actually install PostgreSQL and not just PgAdmin.
- After the installation is complete, the Pg Stack Builder will open asking if you want to install any other dev tools. You can just close it.
Connecting to your Server
- Once the installation has finished, open PgAdmin - you can find it by typing PgAdmin in your taskbar search.
- The installer should have automatically configured your local server and named it PostgreSQL 13. If you do see this server, right click on it and click properties.
- Once there, click connection and make sure the username is postgres.
- If it asks you for a password to view the server, type pass@word1
- If the password is not pass@word1 for your server, you will need to change it
- If you do not see a connected server, you can create your own connection to your local server by right clicking on Servers, then hovering over Create, and selecting server.
- In the name, you can call it PostgreSQL 13, though it doesn't really matter. On the connection tab, the host is localhost, the port is 5432, the username is postgres, and the password is pass@word1.
- Click save, and if you get any errors, it simply means that your postgres wasn't installed correctly and you can start over by following the link in the Installation and Setup section.
Creating your Database
- Open the Utopia solution. Make sure you've fetched the most recent changes for the branch you're on.
- Set the startup project as DBMigratorEF, make sure Azure Storage Emulator is running, and click run.
- If there are issues, it's probably because your server password is incorrect. If you can't change your password, you can actually just change your configuration data string using the utopia configuration tool to have the password of your PG server.
- Once that's done running, you can open PgAdmin and verify that inside the Schemas of your postgres database, you now have public and workflows. Yay, you have a configured database!
- Important: To make sure there are no conflicts with the old database, delete the UtopiaDB database. You should now only have the postgres database.
- Now open the root folder of the utopia source code and copy the contents of the DB Instance Settings Local.config.sql file. Paste the contents in a new query for PgAdmin in the postgres DB and click run.
- Once the query is done, your DB is configured and you can run the batch worker and reset your password.
- Celebrate! Your DB should be good to go!
Changing the postgres user's password
If you accidentally didn't set the postgres user's password to our standard pass@word1, then here are steps to help you fix it.
- Open Command Prompt and navigate to the PostgreSQL bin folder on your machine. Assuming you didn't change the default installation directory, the path should be C:\Program Files\PostgreSQL\13\bin
- Once there, you can use the psql command (another way to do this is to add that bin folder path to your environment PATH variable). Type the following command:
psql -U postgres
- You will be asked for the current password of the pstgress user. Enter it to continue.
- Type
alter user postgres with password 'pass@word1'
, and you can substitute pass@word1 with any password you happen to need. - The command
\q
exits you back to the regular command line. Yay, your postgres user password will now be what you want!
Distribute Foreign Keys
When it's time to distribute the foreign keys in postgres:
select 'alter table '||quote_ident(ns.nspname)||'.'||quote_ident(tb.relname)||
' drop constraint '||quote_ident(conname)||';'||chr(10)||
'alter table '||quote_ident(ns.nspname)||'.'||quote_ident(tb.relname)||
' add constraint '||quote_ident(conname)||' '||
pg_get_constraintdef(c.oid, true)||';' as ddl
from pg_constraint c
join pg_class tb on tb.oid = c.conrelid
join pg_namespace ns on ns.oid = tb.relnamespace
where ns.nspname in ('public') --<<< adjust the schema name(s) here
and c.contype = 'f'; (edited)
Pulled from: https://dba.stackexchange.com/questions/125578/recreate-all-foreign-keys-in-all-tables-as-deferrable-batch
Backup and Restore
See pgAdmin Backup and restore.pdf that Ty Toon created for RPC backups. Most of the steps should work for a local backup. See the differences below. The backup will be saved to the file path and name saved in the backup step.
The Key Difference:
- You'll see different binary path options, and the path should be something like: C:\Program Files\PostgreSQL\14\bin
- In the backup steps you'll see Data/Objects instead of Dump options
Previewer
Supported Previewer File Types
As of 5/31/2022 these are the supported Previewer file types. This list can be found in code in Utopia/wwwroot/Client/app/shared/sharedServices.js
"pdf",
"doc",
"dot",
"docx",
"docm",
"dotx",
"dotm",
"rtf",
"xls",
"xlt",
"xlsx",
"xlsm",
"xltx",
"xltm",
"ppt",
"pot",
"pps",
"pptx",
"pptm",
"potx",
"potm",
"ppsx",
"ppsm",
"odt",
"ott",
"fodt",
"ods",
"ots",
"fods",
"odp",
"otp",
"fodp",
"odf",
"odg",
"otg",
"fodg",
"dwg",
"dxf",
"dwf",
"dgn",
"html",
"htm",
"xhtml",
"xhtm",
"msg",
"eml",
"txt",
"csv",
"dcm",
"dicom",
"dcim",
"dicm",
"tif",
"tiff",
"jpg",
"jpeg",
"jp2",
"jpc",
"gif",
"png",
"psd",
"psb",
"bmp",
"dib",
"pct",
"pic",
"pict",
"wmf",
"emf",
"pcx",
"dcx",
"ras",
"pcd",
"tga",
"tpic",
"cal",
"cals",
"ico",
"cur",
"ncr",
"xwd",
"sgi",
"wbmp",
"sct",
"wpg",
"xbm",
"pbm",
"pgm",
"ppm",
"img",
"cut",
// Legacy support
"dbf",
"nef",
"svg",
"pdb",
"dif",
"pfb",
"xpm",
"fax",
"info",
"std",
"arw",
"sdc",
"sxw"
PreviewerX (Apryse)
All about PreviewerX
PreviewerX Overview - Architecture, Building, Running, Deploying
Base Project Architecture
General Info
apryse-webviewer - Repos (azure.com)
Main branch - previewerX/8.12-Main - this is our main branch because we can't use the actual Main. This is because we originally forked off of the Apryse Gihub project and we need to preserve their branches so we can more easily pull updates in the future if needed.
After cloning, you'll need to make sure you've checked out the previewerX/8.12-Main branch, since the default master branch won't have the Revver-specific changes and you won't be able to get very far through this installation guide.
There's 3 main pieces to PreviewerX and depending on the work you're doing it may change which ones you'll be interacting with the most.
Demo Project - /Demo
This project is not deployed anywhere, it is simply an internal project to speed up testing so you don't have to constantly move files into Utopia/Atlantis in order to see your changes. One nice thing about this project is that you can make changes in the PreviewerX project and with a quick reload, you'll see those changes come through.
If you want to run the demo project pointed at your local files, please see Previewer Setup for Local Environment. However, if you're only making changes to the PreviewerX code and not any interactions specifically with Utopia, you can also point the URLs in the form to staging which are provided as the default values.
PreviewerX - /PreviewerX
This is the main project where we try to put the majority of our code. It provided a wrapper for the Apryse Previewer objects and it provides the interface that Utopia (and eventually Atlantis) will see when you integrate your changes into Utopia.
ApryseUI - Root folder and /src
The other 2 projects are nested into this main project folder. This project is the UI code provided from Apryse and was originally forked from their repo in Github.
This is a dense project to initially dig into and we try to avoid making changes in this area, mostly because any changes we make in here will make it harder for us to stay up to date when Apryse releases new versions and will inevitably cause merge conflicts. The main reason you might find yourself making changes in here is because the internal state of the app is not visible or modifiable outside of their React app. Most of the time, that's okay, there's an interface to hook into the internal events, and that would be the preferable method. However, we've had to add a few modals directly into the previewer itself such as watermarks where we want to block interaction behind the scenes but need to provide a modal that's still within the bounds of the previewer itself.
Build and Run this bad boy
As mentioned there's 3 separate projects inside this repo, but we've added some convenience scripts to make building and launching as easy as possible.
We've all generally been using Node version 14+ and had no issues. If you have Node 11 (from the less cool and older previewer) it will cause issues during build time. You'll also need to have Python version 3.11 installed; if you have version 3.12 installed, you'll get lots of errors and you'll waste half your day troubleshooting and get super sad.
NOTE: All the following command and some more can be found in the root package.json file
- Open a terminal in the root folder
npm run install-all
- This will go into each project and run npm i for you
npm run download-webviewer
- This will install the correct version of the "Core" webviewer files, these are the super secret libraries that power the UI
- You MUST do this before running the next command, the build command takes these files and puts them where the demo project needs them in order to properly run
npm run build-all
- Congrats, everything should be built now! You have a couple options from here:
- To launch the demo project and test things out use
npm run demo
- To build the standalone file that is transferred to Utopia use
npm run build-standalone
- This will output a js file into the /PreviewerX/Standalone folder that can be copied over to the Utopia/wwwroot/scripts/previewer folder
- To launch the demo project and test things out use
Running WebViewer Locally
Local Webviewer Server with Local Utopia
Preface
This guide is assuming you already have previewerX building and running. If you leave the Web Server Url and 'Connecting to local Utopia and Webviewer' checkbox unchecked, PreviewerX will run client side only and will only preview PDF files properly. This is fine for most use cases, but if you need to work with annotations, redactions, or any page manipulation functions you'll need the Webviewer Server running.
Instructions
- If you don't have it already, download and install Docker Desktop
- Download the docker-compose.yml file, preferably somewhere you can find it
- Open a command prompt in that folder and run:
docker-compose up -d --force-recreate
- This will take a few seconds to spin up the first time, you can test if it's up by going to http://localhost:8090/demo?s
- Navigate to the Utopia project (The main project, not the base repo) from the repo base
- Find the .vs/Utopia/config/applicationhost.config file and open in an editor like notepad++
- Find the <sites> section and the <site name="Utopia"> section inside of it
- Add the additional binding
<binding protocol="https" bindingInformation="*:44334:host.docker.internal" />
the full Utopia Site section should look similar to this:
<site name="Utopia" id="2"> <application path="/" applicationPool="Utopia AppPool"> <virtualDirectory path="/" physicalPath="C:\src\Utopia\Utopia\Utopia" /> </application> <bindings> <binding protocol="http" bindingInformation="*:57584:localhost" /> <binding protocol="https" bindingInformation="*:44334:localhost" /> <binding protocol="https" bindingInformation="*:44334:host.docker.internal" /> </bindings> </site>
- You may need to restart Visual Studio if it was already running
- If you're testing in the PreviewerX Demo project, enter the following values into the form on the side:
Base Url -https://localhost:44334
Web Server Url -http://localhost:8090
Check the box for 'Connecting to local Utopia and Webviewer'
(Make sure there isn't whitespace at the end of the URL, but that would never happen to you, right?)
Congrats! Everything should be working locally now!
Technical Details
To add technical details in case there's any issues later on.. under the hood we were having issues running locally be the webviewer running in docker couldn't make a call out to Localhost on the host machine, so it was impossible to load the file. Fortunately, docker desktop adds a host.docker.internal dns entry under the hood that allows docker containers to reach the host machine. I'll be honest, I'm not sure if it's mapped to the loopback on the host somehow, or if it's the local IP. I assume the local IP. To get everything running locally, we're simply overriding the base URL of the loadDocument call to use the host.docker.internal address. However, that means we also need to add that as a viable binding in IISExpress, so we modify the binding in the applicationhost.config file. I'm looking to see if there's a way to just add this by default to Utopia, but for now, hopefully this isn't too painful.
Problems and Solutions
Sometimes Docker gets confuse and you get a "Error: (HTTP code 500) server error - Ports are not available: exposing port TCP 0.0.0.0:60001 -> 0.0.0.0:0: listen tcp 0.0.0.0:60001: bind: An attempt was made to access a socket in a way forbidden by its access permissions." from the loadbalancer docker image. Usually you'll notice this because previewerX can't connect to localhost:8090 even though everything is running. When this happens try this:
- Stop the Apryse Docker images
- Open an admin/elevated command prompt and run:
net stop winnat
- Restart the docker images or re-run
docker-compose up -d --force-recreate
from the folder with the docker-compose.yml file - Once everything is green, go back to the command prompt and run:
net start winnat
RPC
Control Center Design
URL to Powerpoint: https://1drv.ms/p/s!AgkwKyXrWS3Xhg0oRDG4giTo7jw3?e=8oA7mO
On Premise Design Plan - 2019
Server Application Update and Versioning - DSR
· There should be notifications when the update is available
· Online
o BatchWorker checks for the new version in the shared location and in the network
o BatchWorker downloads a package and stores it in the folder for the updates
§ File storage should be used for storing updates because it is shared between the components
o User should confirm the update
o Marks the DB that the Update is available and confirmed (BatchWorker)
§ the user should confirm the update start
o Each component will shut itself down and reinstall itself (including the CM)
o Once the update process is done the health status should be updated
o Alternatively, the admin console should trigger the update.
· Offline
o The update is downloaded manually
o The user puts the installer into the downloads folder
o The Admin Console accepts the update package and stores it
o ... the same as the online version
· Rollback
o There should be a history of updates and ability to go to any of it
o For now - manual process
· Downloads and puts into the permanent storage
· Indicate that the update is available.
· Each component will update itself on its own (maybe)
· Health dashboard is required
· Shared Updates location (centralized)
o Each component will have its own access to the centralized storage
· Getting older versions in the new installation - is it possible?
o New users should get the latest version for the 1st installation
o After the 1st installation we should store the installation package in the storage.
o Will require the support managers training
· Currently the Admin Console worker is supposed to be the updater but it conflicts with the admin console role. Can we move the Call Home and update functionality to Admin Console
o The Batch Worker downloads the files and mars the DB as ready for update
§ The BW will delete all intermediate updates so the user will not be able to install them. User will be able to install the newest version only.
o Admin Console will control the installation
· Will the updates be located in the central storage or on each machine separately (it will have to download them somehow)?
o All updates should be in the file storage which is accessible for all components
o We don't have to encrypt the updates files
o The key is stored in each component configuration string (please see above)
Database Update and Versioning
· Nice to have option: install the SQL express for the user and start it
· Change the Utopia to use migrations and code first at some point
o We will use code first and migrations.
------ Old Notes ------
Researches to be done:
· Research for feasibility: - done
o drag out event from the browser control (including Outlook)
o Important to have
· Research for options (BE):
o Install Shield installer and updater for Desktop when the pipe is small
· Research for solution of changing IP address (BE):
o Self-hosted ClickOnce installer and updater that checks for updates manually and provides a link to download
· Research if Mac updates the applications of the same name and different versions, especially, for non-store apps
· Research: can we implement Drag and Drop for the Windows taskbar icons (it works in Mac) - lowest priority
· Research: running indexer ( ElasticSearch ) on a laptop and its memory consumption
o Possibly it can be excluded for small accounts
· SQL Server Express: can we include it into the installation package?
· Multi-instance data migration for Desktop: migration and integration.
o Only for Casselle, possibly they will go to Cloud
· Research the encryption so that we can use the main key and recovery keys
· Proof of concept: self-updating service that starts the installer and then itself
· Research: if dotless can be used in the desktop version
Client UI
· Will be available for Mac (phase 2) and Windows (phase 1)
· Keep the existing functionality to support d&d, printing, scanning, watch folder, office addins, managing check-in/out
· Change the UI to Web completely (except settings and Addins UI)
o There is no big value in changing the Settings and Addins UI to Web
o The Store Window can be a value for attracting clients to the Utopia and change the name of scanned files
§ Should be enabled by a user setting
o Store dialog design is required
· Discussed Items:
o Switching modes: A button on the top of the form that hides everything and shows the browser window
o Implement dragging files on the SideKick taskbar icon so that we can avoid showing the Orb - (not many windows users use it) ?
o Remember the last selected mode: Maximized and Minimized
o Authentication:
§ Reuse the authentication screen from the SideKick
§ Do not use the Web Auth screen
§ Change the browser to refresh the authentication using the refresh tocken
§ Track the url or JS event for logging out - display the sign in screen from the SideKick
§ The SideKick sign in UI has a server name/IP address selector
§ There should be a mode selector for full-sized mode and limited mode. Prompt can be here as well.
o Disconnected mode for the web and limited view
o The front end side will be done by the EFC team
o For the future: Move the settings, addons etc. to the web part
o Configuration
§ Should include the OCR running schedule (currently it does not support the schedules) - admin console
§
Server Side
· Servers discoverability of the desktop can be postponed for phase 2
· Integration implementation (store dialog and population) - phase 2
· Requirements
o The Desktop 2.0 should be able to handle up to 1000 users
§ The requirement is fulfilled
o We don't need to care about the Load Balancing (it will be done by customers)
o We need to make sure the system components will be configurable and will be able to handle load balancers configuration
o Installation must consider that different components can be installed on different machines
§ Current Desktop configuration is 2-3 different machines: OCR, Server Services + Indexing service
o Instructions documentation should be provided
§ Should include the list of load balancers that will work
· Scaled components:
o Database
o Application server
o Batch Worker can be included into the installer
o Index server (ElasticSearch)
o OCR server
o Image server
o Admin Console (native or web-hosted)
· Non-functional requirements:
o Indexer limitation for memory consumption (to be defined)
o OCR server limitation for threads number, CPU usage
o Must be able to work offline completely
· Discussion
o Switching to self-hosted Web API
o OCR should be the separate installer because many of the customers will not have it
o Must work offline (including the licensing)
o There should be a provider that works on the local file system
§ The files should be encrypted individually
§ It should not take long
§ There should be a way to avoid windows file system number of files limitation
§ There will be no ability to map different locations for file storage
o Backdoor: need a research encryption best practices to have several keys that can unlock.
Licensing:
· Batch worker will need to call home periodically for the account updates (contains features and keys that will expire)
· Batch Worker will be a kind of the licensing server
· Batch Worker should be able to update itself
· The user should be able to update the application package by downloading it and applying.
· Application package can be downloaded independently from the update package
· The Account package will be provided annually
· Obfuscation is required
Installation and configuration
Requirements
· Installer should have a link to SQL Express.
· Updates should be optional. The update package should be downloaded for the account and should be downloadable separatelly.
· Will need an installation wizard
· We will need a configuration wizard that can be reused to set/edit configuration
· Dashboard (admin console) should be combined with the installation wizard
· Admin console should be a prerequisite for the installer in order to avoid multiple Admin Consoles installations.
· Will need to have several installation options
o Typical
§ Should be a single machine, should work on laptops and should be as simple as possible
§ Will still include the Admin console full functionality
o Custom
· We need an MSI for each individual component and all inclusive MSI that includes all individual components MSIs
· User is able to install the components without signing in and licensing
o Obfuscation is nice to have, can be phase 2
· Will need to provide ability to update the server when it is offline
o Using the installer
o Should prevent a component from running if it is not up to date
§ Can be done by a component
§ Will be done throug a heartbeat table for each component
§ The version should be tracked by the admin console
· Backup - ask JR and Jesse about it
o Should be done before each update
o Should have its own folder to store data
o Should not include the files
Admin Console
· Requirements
o Should include the admin email setup for notifications
o If the BatchWorker is not able to phone home then the user should be able to provide an account data package and the account data hash
o The user will be able to download the account data package from the EFC server
o Remote configuration
§ Provide the configuration string for a remote machine. Remote machine config wizard will be able to accept the string and configure the services by it.
§ Can be used in the installer as well
§ Updating configuration is a challenge: the user needs to know that each component configuration should be updated
§ If the component starts and there is no configuration it should start a configuration manager (if possible for a component)
o Includes the UI to check health and configure
o Each Utopia configuration item should be configurable except the SecureDrawer
§ Please see the UtopiaConfiguration class for details
o We can allow them to enter their own encryption string
§ In this case, there will be no way to restore if the key is lost
§ Generate a key for them
§ generate recovery keys for them (like 2FA in GitHub)
§ We need to have 2 options for encryptions keys: auto generated and provided manually
o It should be a separate component that can be installed on a different machine
o Should provide access to the older installers in case of the version downgrade
§ Sometimes customers downgrade but more often they just need an older version of a particular component
o If the service is not able to phone home it looks at the installation packages and sends an email to the admin about the account data packages expiration
o Should show all the components and their versions
o Running status of the components
§ Will work through the DB
o Will need to add some checks for cheating
Client application update
· We might switch the application to use the same installer (Install Shield or ClickOnce or anything else). It depends on the installers research.
· Current (ClickOnce)
o Locally hosted ClickOnce application (on the server which will get the updated ClickOnce installer once it is updated by itself)
o The challenge is to switch the client from Cloud to local server
Server Application Update and Versioning
· There should be notifications when the update is available
· Online
o BatchWorker checks for the new version in the shared location and in the network
o BatchWorker downloads a package and stores it in the folder for the updates
§ File storage should be used for storing updates because it is shared between the components
o User should confirm the update
o Marks the DB that the Update is available and confirmed (BatchWorker)
§ the user should confirm the update start
o Each component will shut itself down and reinstall itself (including the CM)
o Once the update process is done the health status should be updated
o Alternatively, the admin console should trigger the update.
· Offline
o The update is downloaded manually
o The user puts the installer into the downloads folder
o The Admin Console accepts the update package and stores it
o ... the same as the online version
· Rollback
o There should be a history of updates and ability to go to any of it
o For now - manual process
· Downloads and puts into the permanent storage
· Indicate that the update is available.
· Each component will update itself on its own (maybe)
· Health dashboard is required
· Shared Updates location (centralized)
o Each component will have its own access to the centralized storage
· Getting older versions in the new installation - is it possible?
o New users should get the latest version for the 1st installation
o After the 1st installation we should store the installation package in the storage.
o Will require the support managers training
· Currently the Admin Console worker is supposed to be the updater but it conflicts with the admin console role. Can we move the Call Home and update functionality to Admin Console
o The Batch Worker downloads the files and mars the DB as ready for update
§ The BW will delete all intermediate updates so the user will not be able to install them. User will be able to install the newest version only.
o Admin Console will control the installation
· Will the updates be located in the central storage or on each machine separately (it will have to download them somehow)?
o All updates should be in the file storage which is accessible for all components
o We don't have to encrypt the updates files
o The key is stored in each component configuration string
Database Update and Versioning
· Nice to have option: install the SQL express for the user and start it
· Change the Utopia to use migrations and code first at some point?
o We will use code first and migrations. DSR will work on WBS and estimate
o The available team can start working on it (possibly, DSR, after the Pandora and Pangea)
o We will need a training after it is done (if DSR does it)
Global Relay
Common RPC Errors
Error: Maximum number of retries (2) exceeded while executing database operations with 'UtopiaExecutionStrategy'. See inner exception for the most recent failure. The underlying provider failed on Open. 53300: sorry, too many clients already
Solution: By default the number of connections that a postgresql db can have is 100 and they are hitting that thresh hold. Increasing the max number of connections allowed should resolve this. this article details how to do this.
Other Details: We've seen this happen when using Pangea to export from RPC to windows.
-----------------------------------------------------------------------------------------------------------------------------------------------
Rubex Reports
Rubex Reports slick, resources, and videos
Scripts
Purged Account Migration From Backup Script
-- to install extension
CREATE EXTENSION postgres_fdw;
-- you need to create a reference to the backup server
CREATE SERVER backup_prod_server
FOREIGN DATA WRAPPER postgres_fdw
OPTIONS (host 'hostAddressHere', port '5432', dbname 'postgres');
-- you need to define the user credentials to access the backup db
CREATE USER MAPPING FOR currentDbUserNameHere
SERVER staging
OPTIONS (user 'usernameHere', password 'passwordHere');
-- and you need to define a reference to the external db schema(s) (you actually need to create a schema named backup_prod_db_public)
IMPORT FOREIGN SCHEMA public
FROM SERVER backup_prod_server
INTO backup_prod_db_public;
-- and you need to define a reference to the external db schema(s) (you actually need to create a schema named backup_prod_db_workflow)
IMPORT FOREIGN SCHEMA workflow
FROM SERVER backup_prod_server
INTO backup_prod_db_workflow;
INSERT INTO public."DbBrandings"
SELECT * FROM backup_prod_db_public."DbBrandings" where "Id" IN (SELECT "BrandingID" FROM backup_prod_db_public."DbAccounts" WHERE "Id" = {ACCOUNT_ID});
INSERT INTO public."DbAccounts"
SELECT * FROM backup_prod_db_public."DbAccounts" where "Id" = {ACCOUNT_ID};
INSERT INTO public."DbSamlConfigurations"
SELECT * FROM backup_prod_db_public."DbSamlConfigurations" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbSamlRoleAuthentications"
SELECT * FROM backup_prod_db_public."DbSamlRoleAuthentications" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbSamlResponses"
SELECT * FROM backup_prod_db_public."DbSamlResponses" where "AccountID" = {ACCOUNT_ID};
CREATE TEMP TABLE Temp_Email_Settings_Ids(Id integer);
INSERT INTO Temp_Email_Settings_Ids
SELECT "EmailSettingsID" from backup_prod_db_public."DbEmailSettingToAccounts" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbEmailSettings"
SELECT * FROM backup_prod_db_public."DbEmailSettings" where "Id" IN (SELECT "Id" FROM Temp_Email_Settings_Ids);
INSERT INTO public."DbEmailSettingToAccounts"
SELECT * FROM backup_prod_db_public."DbEmailSettingToAccounts" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbProfileItemHiddenCharacterConfigurations"
SELECT * FROM backup_prod_db_public."DbProfileItemHiddenCharacterConfigurations" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbProfileItemHiddenCharacterRanges"
SELECT * FROM backup_prod_db_public."DbProfileItemHiddenCharacterRanges" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbProfileItems"
SELECT * FROM backup_prod_db_public."DbProfileItems" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbProfiles"
SELECT * FROM backup_prod_db_public."DbProfiles" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbPresetValues"
SELECT * FROM backup_prod_db_public."DbPresetValues" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbProfileToProfileItems"
SELECT * FROM backup_prod_db_public."DbProfileToProfileItems" where "ProfileID" in (select "Id" from backup_prod_db_public."DbProfiles" where "AccountID" = {ACCOUNT_ID});
INSERT INTO public."DbFormFillDefinitions"
SELECT * FROM backup_prod_db_public."DbFormFillDefinitions" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbFormFillToProfileItems"
SELECT * FROM backup_prod_db_public."DbFormFillToProfileItems" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbFormFillPendings"
SELECT * FROM backup_prod_db_public."DbFormFillPendings" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbSecurityPolicies"
SELECT * FROM backup_prod_db_public."DbSecurityPolicies" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbSecurityPolicyIpAddresses"
SELECT * FROM backup_prod_db_public."DbSecurityPolicyIpAddresses" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbSecurityPolicyLoginTimes"
SELECT * FROM backup_prod_db_public."DbSecurityPolicyLoginTimes" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbSystemPermissions"
SELECT * FROM backup_prod_db_public."DbSystemPermissions" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbRoles"
SELECT * FROM backup_prod_db_public."DbRoles" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbRoleToAccountFeatures"
SELECT * FROM backup_prod_db_public."DbRoleToAccountFeatures" where "RoleID" in (select "Id" from backup_prod_db_public."DbRoles" where "AccountID" = {ACCOUNT_ID});
INSERT INTO public."DbUserRolePreferences"
SELECT * FROM backup_prod_db_public."DbUserRolePreferences" where "RoleID" in (select "Id" from backup_prod_db_public."DbRoles" where "AccountID" = {ACCOUNT_ID});
INSERT INTO public."DbUserSessions"
SELECT * FROM backup_prod_db_public."DbUserSessions" where "RoleID" in (select "Id" from backup_prod_db_public."DbRoles" where "AccountID" = {ACCOUNT_ID});
INSERT INTO public."DbUserSessionToDbRoles"
SELECT * FROM backup_prod_db_public."DbUserSessionToDbRoles" where "UserSessionID" in (select "Id" from "DbUserSessions" where backup_prod_db_public."RoleID" in (select "Id" from "DbRoles" where "AccountID" = {ACCOUNT_ID}));
INSERT INTO public."DbUserSessionToDbRoles"
SELECT * FROM backup_prod_db_public."DbUserSessionToDbRoles" where "RoleID" in (select "Id" from backup_prod_db_public."DbRoles" where "AccountID" = {ACCOUNT_ID});
INSERT INTO public."DbProfileValueRoles"
SELECT * FROM backup_prod_db_public."DbProfileValueRoles" where "RoleID" in (select "Id" from backup_prod_db_public."DbRoles" where "AccountID" = {ACCOUNT_ID});
INSERT INTO public."DbRoleRelationships"
SELECT * FROM backup_prod_db_public."DbRoleRelationships" where "ParentRoleID" in (select "Id" from backup_prod_db_public."DbRoles" where "AccountID" = {ACCOUNT_ID});
DELETE FROM public."DbRoleClosures" where "ParentID" in (select "Id" from backup_prod_db_public."DbRoles" where "AccountID" = {ACCOUNT_ID});
INSERT INTO public."DbRoleClosures"
SELECT * FROM backup_prod_db_public."DbRoleClosures" where "ParentID" in (select "Id" from backup_prod_db_public."DbRoles" where "AccountID" = {ACCOUNT_ID});
INSERT INTO public."DbNotifications"
SELECT * FROM backup_prod_db_public."DbNotifications" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbWorkflowStageInstanceToNotifications"
SELECT * FROM backup_prod_db_public."DbWorkflowStageInstanceToNotifications" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbAccountSettings"
SELECT * FROM backup_prod_db_public."DbAccountSettings" where "AccountID" = {ACCOUNT_ID};
CREATE TEMP TABLE Temp_Active_File_Infoes(NodeID bigint, FileInfoID bigint);
INSERT INTO Temp_Active_File_Infoes (nodeid, fileinfoid)
SELECT "Id", "FileInfoID" from backup_prod_db_public."DbNodes" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbNodes" ("Id", "AccountID", "CreatedByUserID", "ParentID", "Name", "SystemType", "FileInfoID", "ProfileID", "CreatedOn", "ModifiedOn", "DeletedOn", "PurgedOn")
SELECT backup_prod_db_public."DbNodes"."Id", backup_prod_db_public."DbNodes"."AccountID", backup_prod_db_public."DbNodes"."CreatedByUserID", backup_prod_db_public."DbNodes"."ParentID", backup_prod_db_public."DbNodes"."Name", backup_prod_db_public."DbNodes"."SystemType", NULL, backup_prod_db_public."DbNodes"."ProfileID", backup_prod_db_public."DbNodes"."CreatedOn", backup_prod_db_public."DbNodes"."ModifiedOn", backup_prod_db_public."DbNodes"."DeletedOn", backup_prod_db_public."DbNodes"."PurgedOn"
FROM backup_prod_db_public."DbNodes" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbNodeComments"
SELECT * FROM backup_prod_db_public."DbNodeComments" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbFileInfoes"
SELECT * FROM backup_prod_db_public."DbFileInfoes" where "AccountID" = {ACCOUNT_ID};
UPDATE public."DbNodes"
SET "FileInfoID" = Temp_Active_File_Infoes.fileinfoid
FROM Temp_Active_File_Infoes
WHERE public."DbNodes"."Id" = Temp_Active_File_Infoes.nodeid;
INSERT INTO public."DbNodeToFileInfoes"
SELECT * FROM backup_prod_db_public."DbNodeToFileInfoes" where "AccountID" = {ACCOUNT_ID};
DELETE FROM public."DbNodeClosures" WHERE "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbNodeClosures" ("ParentID", "ChildID", "Depth", "AccountID")
SELECT backup_prod_db_public."DbNodeClosures"."ParentID", backup_prod_db_public."DbNodeClosures"."ChildID", backup_prod_db_public."DbNodeClosures"."Depth", backup_prod_db_public."DbNodeClosures"."AccountID"
FROM backup_prod_db_public."DbNodeClosures" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbEmailQueueAttachmentNodes"
SELECT * FROM backup_prod_db_public."DbEmailQueueAttachmentNodes" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbPortfolioToNodes"
SELECT * FROM backup_prod_db_public."DbPortfolioToNodes"
where "AddedByUserID" IN (select "UserID" from backup_prod_db_public."DbRoles" where backup_prod_db_public."DbRoles"."AccountID" = {ACCOUNT_ID} and backup_prod_db_public."DbRoles"."UserID" is not null)
and isnumeric(backup_prod_db_public."DbPortfolioToNodes"."NodeID")
and EXISTS (SELECT * FROM backup_prod_db_public."DbNodes" WHERE "Id" = CAST(backup_prod_db_public."DbPortfolioToNodes"."NodeID" as bigint) AND "AccountID" = {ACCOUNT_ID});
INSERT INTO public."DbTemplateNodeChangeLogs"
SELECT * FROM backup_prod_db_public."DbTemplateNodeChangeLogs" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbESignatureTransactions"
SELECT * FROM backup_prod_db_public."DbESignatureTransactions" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbESignatureNodeAssociations"
SELECT * FROM backup_prod_db_public."DbESignatureNodeAssociations" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbESignatureSigners"
SELECT * FROM backup_prod_db_public."DbESignatureSigners" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbRetentionChangeReason"
SELECT * FROM backup_prod_db_public."DbRetentionChangeReason" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbRightSignatureDocuments"
SELECT * FROM backup_prod_db_public."DbRightSignatureDocuments" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbNodeAnnotations"
SELECT * FROM backup_prod_db_public."DbNodeAnnotations" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbUserImageStamps"
SELECT * FROM backup_prod_db_public."DbUserImageStamps" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbDocumentRequests"
SELECT * FROM backup_prod_db_public."DbDocumentRequests" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbDocumentRequestToNotifications"
SELECT * FROM backup_prod_db_public."DbDocumentRequestToNotifications" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbDocumentRequestRoles"
SELECT * FROM backup_prod_db_public."DbDocumentRequestRoles" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbDocumentRequestContainers"
SELECT * FROM backup_prod_db_public."DbDocumentRequestContainers" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbDocumentRequestAttachments"
SELECT * FROM backup_prod_db_public."DbDocumentRequestAttachments" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbDocumentRequestContainerNodes"
SELECT * FROM backup_prod_db_public."DbDocumentRequestContainerNodes" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbFileQueue"
SELECT * FROM backup_prod_db_public."DbFileQueue" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbNodeShares"
SELECT * FROM backup_prod_db_public."DbNodeShares" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbProfileValueNodes"
SELECT * FROM backup_prod_db_public."DbProfileValueNodes" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbPermissions"
SELECT * FROM backup_prod_db_public."DbPermissions" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbLegacyNodeMappings"
SELECT * FROM backup_prod_db_public."DbLegacyNodeMappings" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbTriggerMessageContent"
SELECT * FROM backup_prod_db_public."DbTriggerMessageContent" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbTriggers"
SELECT * FROM backup_prod_db_public."DbTriggers" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbTriggerToSearchCriteria"
SELECT * FROM backup_prod_db_public."DbTriggerToSearchCriteria" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbTriggerToApiCallouts"
SELECT * FROM backup_prod_db_public."DbTriggerToApiCallouts" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbTriggerInfoNodes"
SELECT * FROM backup_prod_db_public."DbTriggerInfoNodes" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbTriggerToNode"
SELECT * FROM backup_prod_db_public."DbTriggerToNode" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbTriggerToRoles"
SELECT * FROM backup_prod_db_public."DbTriggerToRoles" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbTriggerToWorkflow"
SELECT * FROM backup_prod_db_public."DbTriggerToWorkflow" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbTimeTriggers"
SELECT * FROM backup_prod_db_public."DbTimeTriggers" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbEventTriggers"
SELECT * FROM backup_prod_db_public."DbEventTriggers" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbEmailImportMappings"
SELECT * FROM backup_prod_db_public."DbEmailImportMappings" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbEmailQueue"
SELECT * FROM backup_prod_db_public."DbEmailQueue" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbEmailRecipients"
SELECT * FROM backup_prod_db_public."DbEmailRecipients" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbEmailQueueAttachmentNodes"
SELECT * FROM backup_prod_db_public."DbEmailQueueAttachmentNodes" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbAuditLogs"
SELECT * FROM backup_prod_db_public."DbAuditLogs" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbAuditLogsToRoles"
SELECT * FROM backup_prod_db_public."DbAuditLogsToRoles" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbAuditLogsToRoleDetails"
SELECT * FROM backup_prod_db_public."DbAuditLogsToRoleDetails" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbAuditLogsToNodes"
SELECT * FROM backup_prod_db_public."DbAuditLogsToNodes" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbAuditLogsToNodeDetails"
SELECT * FROM backup_prod_db_public."DbAuditLogsToNodeDetails" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbAccessLinks"
SELECT * FROM backup_prod_db_public."DbAccessLinks" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbAccessLinksToDocumentRequests"
SELECT * FROM backup_prod_db_public."DbAccessLinksToDocumentRequests" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbAccessLinksToNodeAndTriggers"
SELECT * FROM backup_prod_db_public."DbAccessLinksToNodeAndTriggers" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbAccountFeatureUsages"
SELECT * FROM backup_prod_db_public."DbAccountFeatureUsages" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbAccountFeatures"
SELECT * FROM backup_prod_db_public."DbAccountFeatures" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbCheckoutInfoes"
SELECT * FROM backup_prod_db_public."DbCheckoutInfoes" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbSfMappingDestinations"
SELECT * FROM backup_prod_db_public."DbSfMappingDestinations" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbSfMappings"
SELECT * FROM backup_prod_db_public."DbSfMappings" where "AccountID" = {ACCOUNT_ID};
INSERT INTO public."DbSfLinks"
SELECT * FROM backup_prod_db_public."DbSfLinks" where "AccountID" = {ACCOUNT_ID};
-- WORKFLOW TABLES
INSERT INTO workflow."DbWorkflows"
SELECT * FROM backup_prod_db_workflow."DbWorkflows" where "AccountId" = {ACCOUNT_ID};
INSERT INTO workflow."DbWorkflowAssets"
SELECT * FROM backup_prod_db_workflow."DbWorkflowAssets" where "WorkflowID" IN (SELECT "Id" FROM backup_prod_db_workflow."DbWorkflows" WHERE "AccountId" = {ACCOUNT_ID});
INSERT INTO workflow."DbWorkflowStages"
SELECT * FROM backup_prod_db_workflow."DbWorkflowStages" where "WorkflowID" IN (SELECT "Id" FROM backup_prod_db_workflow."DbWorkflows" WHERE "AccountId" = {ACCOUNT_ID});
INSERT INTO workflow."DbWorkflowsAvailableStates"
SELECT * FROM backup_prod_db_workflow."DbWorkflowsAvailableStates" where "WorkflowID" IN (SELECT "Id" FROM backup_prod_db_workflow."DbWorkflows" WHERE "AccountId" = {ACCOUNT_ID});
CREATE TEMP TABLE Temp_Current_Workflow_Stages(WorkflowInstanceID bigint, WorkflowStageInstanceID bigint);
INSERT INTO Temp_Current_Workflow_Stages (workflowinstanceid, workflowstageinstanceid)
SELECT "Id", "CurrentStageID" from backup_prod_db_workflow."DbWorkflowInstances" where "WorkflowID" IN (SELECT "Id" FROM backup_prod_db_workflow."DbWorkflows" WHERE "AccountId" = {ACCOUNT_ID});
INSERT INTO workflow."DbWorkflowInstances" ("Id", "Name", "Description", "IsActive", "StateID", "WorkflowID", "OwnerID", "CreatedDate", "LastModifiedDate", "CurrentStageID")
SELECT "Id", "Name", "Description", "IsActive", "StateID", "WorkflowID", "OwnerID", "CreatedDate", "LastModifiedDate", NULL
FROM backup_prod_db_workflow."DbWorkflowInstances" where "WorkflowID" IN (SELECT "Id" FROM backup_prod_db_workflow."DbWorkflows" WHERE "AccountId" = {ACCOUNT_ID});
INSERT INTO workflow."DbWorkflowStageInstances"
SELECT * FROM backup_prod_db_workflow."DbWorkflowStageInstances" where "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowInstances" WHERE "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflows" WHERE "AccountId" = {ACCOUNT_ID}));
UPDATE workflow."DbWorkflowInstances"
SET "CurrentStageID" = Temp_Current_Workflow_Stages.workflowstageinstanceid
FROM Temp_Current_Workflow_Stages
WHERE workflow."DbWorkflowInstances"."Id" = Temp_Current_Workflow_Stages.workflowinstanceid;
INSERT INTO workflow."DbAssetNodeReference"
SELECT * FROM backup_prod_db_workflow."DbAssetNodeReference" where "AssetID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowAssets" WHERE "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflows" WHERE "AccountId" = {ACCOUNT_ID}));
INSERT INTO workflow."DbWorkflowAssetsStages"
SELECT * FROM backup_prod_db_workflow."DbWorkflowAssetsStages" where "StageID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowStages" WHERE "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflows" WHERE "AccountId" = {ACCOUNT_ID}));
INSERT INTO workflow."DbWorkflowAssetInstances"
SELECT * FROM backup_prod_db_workflow."DbWorkflowAssetInstances" where "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowInstances" WHERE "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflows" WHERE "AccountId" = {ACCOUNT_ID}));
INSERT INTO workflow."DbAssetInstanceNodeReferences"
SELECT * FROM backup_prod_db_workflow."DbAssetInstanceNodeReferences" where "AssetInstanceID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowAssetInstances" WHERE "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowInstances" WHERE "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflows" WHERE "AccountId" = {ACCOUNT_ID})));
INSERT INTO workflow."DbProfileRoutingRules"
SELECT * FROM backup_prod_db_workflow."DbProfileRoutingRules" where "StageID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowStages" WHERE "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflows" WHERE "AccountId" = {ACCOUNT_ID}));
INSERT INTO workflow."DbWorkflowSteps"
SELECT * FROM backup_prod_db_workflow."DbWorkflowSteps" where "StageID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowStages" WHERE "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflows" WHERE "AccountId" = {ACCOUNT_ID}));
INSERT INTO workflow."DbStageApproveResults"
SELECT * FROM backup_prod_db_workflow."DbStageApproveResults" where "StageInstanceID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowStageInstances" WHERE "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowInstances" WHERE "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflows" WHERE "AccountId" = {ACCOUNT_ID})));
INSERT INTO workflow."DbWorkflowAssetsStagesInstances"
SELECT * FROM backup_prod_db_workflow."DbWorkflowAssetsStagesInstances" where "StageID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowStageInstances" WHERE "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowInstances" WHERE "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflows" WHERE "AccountId" = {ACCOUNT_ID})));
INSERT INTO workflow."DbWorkflowStepInstances"
SELECT * FROM backup_prod_db_workflow."DbWorkflowStepInstances" where "StageID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowStageInstances" WHERE "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowInstances" WHERE "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflows" WHERE "AccountId" = {ACCOUNT_ID})));
INSERT INTO workflow."DbWorkflowSetProfileInstanceItems"
SELECT * FROM backup_prod_db_workflow."DbWorkflowSetProfileInstanceItems" where "StepInstanceID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowStepInstances" WHERE "StageID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowStageInstances" WHERE "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowInstances" WHERE "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflows" WHERE "AccountId" = {ACCOUNT_ID}))));
INSERT INTO workflow."DbWorkflowSetProfileInstanceItemPresetValues"
SELECT * FROM backup_prod_db_workflow."DbWorkflowSetProfileInstanceItemPresetValues" where "StepProfileItemID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowSetProfileInstanceItems" WHERE "StepInstanceID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowStepInstances" WHERE "StageID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowStageInstances" WHERE "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowStageInstances" WHERE "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflows" WHERE "AccountId" = {ACCOUNT_ID})))));
INSERT INTO workflow."DbWorkflowSendMessageInstanceRecipients"
SELECT * FROM backup_prod_db_workflow."DbWorkflowSendMessageInstanceRecipients" where "StepInstanceID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowStepInstances" WHERE "StageID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowStageInstances" WHERE "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowInstances" WHERE "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflows" WHERE "AccountId" = {ACCOUNT_ID}))));
INSERT INTO workflow."DbWorkflowStepInstanceEmailUserGroups"
SELECT * FROM backup_prod_db_workflow."DbWorkflowStepInstanceEmailUserGroups" where "WorkflowAddTriggerStepInstanceID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowStepInstances" WHERE "StageID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowStageInstances" WHERE "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowInstances" WHERE "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflows" WHERE "AccountId" = {ACCOUNT_ID}))));
INSERT INTO workflow."DbWorkflowStepInstanceEmailUsers"
SELECT * FROM backup_prod_db_workflow."DbWorkflowStepInstanceEmailUsers" where "WorkflowAddTriggerStepInstanceID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowStepInstances" WHERE "StageID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowStageInstances" WHERE "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowInstances" WHERE "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflows" WHERE "AccountId" = {ACCOUNT_ID}))));
INSERT INTO workflow."DbWorkflowRequestFileExternalStepInstanceNewUserReferences"
SELECT * FROM backup_prod_db_workflow."DbWorkflowRequestFileExternalStepInstanceNewUserReferences" where "StepInstanceID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowStepInstances" WHERE "StageID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowStageInstances" WHERE "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowInstances" WHERE "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflows" WHERE "AccountId" = {ACCOUNT_ID}))));
INSERT INTO workflow."DbWorkflowRequestFileExternalStepInstanceRecipientGroups"
SELECT * FROM backup_prod_db_workflow."DbWorkflowRequestFileExternalStepInstanceRecipientGroups" where "WorkflowStepInstanceID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowStepInstances" WHERE "StageID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowStageInstances" WHERE "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowInstances" WHERE "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflows" WHERE "AccountId" = {ACCOUNT_ID}))));
INSERT INTO workflow."DbWorkflowRequestFileExternalStepInstanceRecipients"
SELECT * FROM backup_prod_db_workflow."DbWorkflowRequestFileExternalStepInstanceRecipients" where "WorkflowStepInstanceID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowStepInstances" WHERE "StageID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowStageInstances" WHERE "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowInstances" WHERE "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflows" WHERE "AccountId" = {ACCOUNT_ID}))));
INSERT INTO workflow."DbWorkflowStepInstanceDocumentRequestContainers"
SELECT * FROM backup_prod_db_workflow."DbWorkflowStepInstanceDocumentRequestContainers" where "StepInstanceID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowStepInstances" WHERE "StageID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowStageInstances" WHERE "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowInstances" WHERE "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflows" WHERE "AccountId" = {ACCOUNT_ID}))));
INSERT INTO workflow."DbWorkflowStepInstanceUserReferences"
SELECT * FROM backup_prod_db_workflow."DbWorkflowStepInstanceUserReferences" where "StepInstanceID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowStepInstances" WHERE "StageID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowStageInstances" WHERE "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowInstances" WHERE "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflows" WHERE "AccountId" = {ACCOUNT_ID}))));
INSERT INTO workflow."DbWorkflowStepInstanceGroupReferences"
SELECT * FROM backup_prod_db_workflow."DbWorkflowStepInstanceGroupReferences" where "StepInstanceID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowStepInstances" WHERE "StageID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowStageInstances" WHERE "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowInstances" WHERE "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflows" WHERE "AccountId" = {ACCOUNT_ID}))));
INSERT INTO workflow."DbWorkflowShareStepInstanceNewUserReferences"
SELECT * FROM backup_prod_db_workflow."DbWorkflowShareStepInstanceNewUserReferences" where "StepInstanceID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowStepInstances" WHERE "StageID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowStageInstances" WHERE "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowInstances" WHERE "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflows" WHERE "AccountId" = {ACCOUNT_ID}))));
INSERT INTO workflow."DbWorkflowStepInstanceUsers"
SELECT * FROM backup_prod_db_workflow."DbWorkflowStepInstanceUsers" where "WorkflowSetPermissionsStepInstanceID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowStepInstances" WHERE "StageID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowStageInstances" WHERE "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowInstances" WHERE "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflows" WHERE "AccountId" = {ACCOUNT_ID}))));
INSERT INTO workflow."DbWorkflowStepInstanceUserGroups"
SELECT * FROM backup_prod_db_workflow."DbWorkflowStepInstanceUserGroups" where "WorkflowSetPermissionsStepInstanceID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowStepInstances" WHERE "StageID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowStageInstances" WHERE "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowInstances" WHERE "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflows" WHERE "AccountId" = {ACCOUNT_ID}))));
INSERT INTO workflow."DbWorkflowInstanceHistoryRecords"
SELECT * FROM backup_prod_db_workflow."DbWorkflowInstanceHistoryRecords" where "WorkflowID" IN (SELECT "Id" FROM backup_prod_db_workflow."DbWorkflows" WHERE "AccountId" = {ACCOUNT_ID});
INSERT INTO workflow."DbWorkflowSetProfileItems"
SELECT * FROM backup_prod_db_workflow."DbWorkflowSetProfileItems" where "StepID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowSteps" WHERE "StageID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowStages" WHERE "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflows" WHERE "AccountId" = {ACCOUNT_ID})));
INSERT INTO workflow."DbWorkflowSetProfileItemPresetValues"
SELECT * FROM backup_prod_db_workflow."DbWorkflowSetProfileItemPresetValues" where "StepProfileItemID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowSetProfileItems" WHERE "StepID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowSteps" WHERE "StageID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowStages" WHERE "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflows" WHERE "AccountId" = {ACCOUNT_ID}))));
INSERT INTO workflow."DbWorkflowSendMessageRecipients"
SELECT * FROM backup_prod_db_workflow."DbWorkflowSendMessageRecipients" where "StepID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowSteps" WHERE "StageID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowStages" WHERE "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflows" WHERE "AccountId" = {ACCOUNT_ID})));
INSERT INTO workflow."DbWorkflowAddTriggerStepEmailUserGroups"
SELECT * FROM backup_prod_db_workflow."DbWorkflowAddTriggerStepEmailUserGroups" where "WorkflowStepID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowSteps" WHERE "StageID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowStages" WHERE "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflows" WHERE "AccountId" = {ACCOUNT_ID})));
INSERT INTO workflow."DbWorkflowAddTriggerStepEmailUsers"
SELECT * FROM backup_prod_db_workflow."DbWorkflowAddTriggerStepEmailUsers" where "WorkflowStepID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowSteps" WHERE "StageID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowStages" WHERE "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflows" WHERE "AccountId" = {ACCOUNT_ID})));
INSERT INTO workflow."DbWorkflowRequestFileExternalStepNewUserReferences"
SELECT * FROM backup_prod_db_workflow."DbWorkflowRequestFileExternalStepNewUserReferences" where "StepID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowSteps" WHERE "StageID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowStages" WHERE "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflows" WHERE "AccountId" = {ACCOUNT_ID})));
INSERT INTO workflow."DbWorkflowRequestFileExternalStepRecipientGroups"
SELECT * FROM backup_prod_db_workflow."DbWorkflowRequestFileExternalStepRecipientGroups" where "WorkflowStepID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowSteps" WHERE "StageID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowStages" WHERE "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflows" WHERE "AccountId" = {ACCOUNT_ID})));
INSERT INTO workflow."DbWorkflowRequestFileExternalStepRecipients"
SELECT * FROM backup_prod_db_workflow."DbWorkflowRequestFileExternalStepRecipients" where "WorkflowStepID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowSteps" WHERE "StageID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowStages" WHERE "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflows" WHERE "AccountId" = {ACCOUNT_ID})));
INSERT INTO workflow."DbWorkflowStepDocumentRequestContainers"
SELECT * FROM backup_prod_db_workflow."DbWorkflowStepDocumentRequestContainers" where "StepID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowSteps" WHERE "StageID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowStages" WHERE "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflows" WHERE "AccountId" = {ACCOUNT_ID})));
INSERT INTO workflow."DbWorkflowShareStepNewUserReferences"
SELECT * FROM backup_prod_db_workflow."DbWorkflowShareStepNewUserReferences" where "StepID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowSteps" WHERE "StageID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowStages" WHERE "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflows" WHERE "AccountId" = {ACCOUNT_ID})));
INSERT INTO workflow."DbWorkflowStepUserReferences"
SELECT * FROM backup_prod_db_workflow."DbWorkflowStepUserReferences" where "StepID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowSteps" WHERE "StageID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowStages" WHERE "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflows" WHERE "AccountId" = {ACCOUNT_ID})));
INSERT INTO workflow."DbWorkflowStepGroupReferences"
SELECT * FROM backup_prod_db_workflow."DbWorkflowStepGroupReferences" where "StepID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowSteps" WHERE "StageID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowStages" WHERE "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflows" WHERE "AccountId" = {ACCOUNT_ID})));
INSERT INTO workflow."DbWorkflowSetPermissionsStepUsers"
SELECT * FROM backup_prod_db_workflow."DbWorkflowSetPermissionsStepUsers" where "WorkflowStepID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowSteps" WHERE "StageID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowStages" WHERE "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflows" WHERE "AccountId" = {ACCOUNT_ID})));
INSERT INTO workflow."DbWorkflowSetPermissionsStepUserGroups"
SELECT * FROM backup_prod_db_workflow."DbWorkflowSetPermissionsStepUserGroups" where "WorkflowStepID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowSteps" WHERE "StageID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowStages" WHERE "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflows" WHERE "AccountId" = {ACCOUNT_ID})));
INSERT INTO workflow."DbWorkflowStageAssigneeGroups"
SELECT * FROM backup_prod_db_workflow."DbWorkflowStageAssigneeGroups" where "WorkflowStageID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowStages" WHERE "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflows" WHERE "AccountId" = {ACCOUNT_ID}));
INSERT INTO workflow."DbWorkflowStageAssignees"
SELECT * FROM backup_prod_db_workflow."DbWorkflowStageAssignees" where "WorkflowStageID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowStages" WHERE "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflows" WHERE "AccountId" = {ACCOUNT_ID}));
INSERT INTO workflow."DbWorkflowStageApproverGroups"
SELECT * FROM backup_prod_db_workflow."DbWorkflowStageApproverGroups" where "WorkflowStageID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowStages" WHERE "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflows" WHERE "AccountId" = {ACCOUNT_ID}));
INSERT INTO workflow."DbWorkflowStageApprovers"
SELECT * FROM backup_prod_db_workflow."DbWorkflowStageApprovers" where "WorkflowStageID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflowStages" WHERE "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflows" WHERE "AccountId" = {ACCOUNT_ID}));
INSERT INTO workflow."DbWorkflowStarterGroups"
SELECT * FROM backup_prod_db_workflow."DbWorkflowStarterGroups" where "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflows" WHERE "AccountId" = {ACCOUNT_ID});
INSERT INTO workflow."DbWorkflowStarters"
SELECT * FROM backup_prod_db_workflow."DbWorkflowStarters" where "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflows" WHERE "AccountId" = {ACCOUNT_ID});
INSERT INTO workflow."DbWorkflowOwnerGroups"
SELECT * FROM backup_prod_db_workflow."DbWorkflowOwnerGroups" where "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflows" WHERE "AccountId" = {ACCOUNT_ID});
INSERT INTO workflow."DbWorkflowOwners"
SELECT * FROM backup_prod_db_workflow."DbWorkflowOwners" where "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflows" WHERE "AccountId" = {ACCOUNT_ID});
INSERT INTO workflow."DbWorkflowWatcherGroups"
SELECT * FROM backup_prod_db_workflow."DbWorkflowWatcherGroups" where "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflows" WHERE "AccountId" = {ACCOUNT_ID});
INSERT INTO workflow."DbWorkflowWatchers"
SELECT * FROM backup_prod_db_workflow."DbWorkflowWatchers" where "WorkflowID" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflows" WHERE "AccountId" = {ACCOUNT_ID});
INSERT INTO workflow."DbWorkflowScheduleConfigurations"
SELECT * FROM backup_prod_db_workflow."DbWorkflowScheduleConfigurations" where "Id" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflows" WHERE "AccountId" = {ACCOUNT_ID});
INSERT INTO workflow."DbWorkflowNotificationConfigurations"
SELECT * FROM backup_prod_db_workflow."DbWorkflowNotificationConfigurations" where "Id" IN
(SELECT "Id" FROM backup_prod_db_workflow."DbWorkflows" WHERE "AccountId" = {ACCOUNT_ID});
INSERT INTO workflow."DbWorkflowJobsQueue"
SELECT * FROM backup_prod_db_workflow."DbWorkflowJobsQueue" where "AccountId" = {ACCOUNT_ID};
INSERT INTO workflow."DbWorkflowAccountEmailConfig"
SELECT * FROM backup_prod_db_workflow."DbWorkflowAccountEmailConfig" where "AccountId" = {ACCOUNT_ID};
Setup and Configurations
Connecting to UtopiaNuget
Link to UtopiaNuget: https://dev.azure.com/eFileCabinet/Utopia/_packaging?_a=feed&feed=UtopiaNuget (alternatively try this: https://pkgs.dev.azure.com/eFileCabinet/Utopia/_packaging/UtopiaNuget/nuget/v3/index.json)
First connect to feed by pressing the Connect to Feed button at the top. Click on the Visual Studio option. Follow steps.
(Once you've created the Nuget Package Source, try to build the project and see if it succeeds before moving trying the below stuff)
Once connected to feed then go ahead an find the nuget that is needed and click on it. Then copy the nuget command and go into visual studio and go to Tools-Nuget Package Manager-Package Manager Console. Then paste the nuget command into the console and run.
If issue of 401 comes up use link to resolve: https://blog.rsuter.com/how-to-use-a-private-vsts-nuget-package-feed-with-the-net-core-cli/#:~:text=If you have a.NET Core project which references,status code does not indicate success%3A 401 (Unauthorized) .
UtopiaNuget on Mac
If you're doing this on mac (sorry), then the process is slightly different. See this other wiki page.
Steps to setup pg_partman
Steps to setup partman
** Make sure you don't have the postgres service running on windows **
Use WSL Ubuntu :
- It may need some additional setup (enable virtualization, etc)
Install postgresql on ubuntu:
- Follow these steps
- make sure you update it to the latest version (currently 13)
Login and setup postgres and postgres user:
- Run the psql command from the postgres user account
sudo -u postgres psql postgres
- Set the password
\password postgres
- Enter a new password (pass@word1)
- Close psql
\q
Run the following commands:
`sudo apt install make`
`sudo apt install gcc`
`sudo apt install postgresql-server-dev-13` (if the version ever changes, change that number at the end)
Setting up partman:
- In your working folder run:
- git clone https://github.com/keithf4/pg_partman
- cd pg_partman
- make install
Commands that may come in handy:
`sudo service postgresql start` (starts postgres service)
`sudo service postgresql restart` (restarts postgres service)
`sudo service postgresql stop` (stops postgres service)
`explorer.exe .` ( Use this if you fancy an explorer view instead of a terminal one. Also allows you to edit the files without using vim)
To get PgAdmin working:
Inside of the pg_hba.conf file, change the local connection to
`host all all 0.0.0.0/0 md5`
Inside of postgres.conf change listen_addresses under CONNECTIONS AND AUTHENTICATION to
`listen_addresses = '*'`
Example docs to get partman setup:
Additional Info
https://github.com/pgpartman/pg_partman/blob/master/doc/pg_partman.md
Partition types that pg_partman supports
- Time based
- Integer based
Peformance with 1 billion entries
Saved in the SPIKE:
How to run and Release Mobile
Debugging the iOS app:
- Set efcMobileApp.iOS as the startup project
- Pair the Mac by clicking this icon:
- Make sure you are in Debug mode, not Release mode
- Click the down arrow on the start options, and pick the device you want to simulate - Remote Device will not work
- Happy testing!
Releasing the iOS app:
- In the efcMobileApp.iOS/Info.plist file, scroll down to Bundle version and bundle versions string (short) then add 1 to each value.
- Set efcMobileApp.iOS as the startup project
- Pair the Mac (see step 2 of Debugging the iOS app)
- Make sure you are in Release mode, not Debug mode
- Right click on efcMobileApp.iOS and click Archive...
- Wait for the Archive to finish - if there's a signing error:
a. Right click on efcMobileApp.iOS and click Properties.
b. Once there, click the iOS Bundle Signing tab and make sure the Signing Identity is: iPhone Distribution: eFileCabinet, Inc. and the Provisioning Profile is: eFileCabinet Online AppStore and try the Archive again.
c. If there's still an issue, the signing certificate may be out of date. Please get with dev management to get a new signing certificate. - Once the Archive has finished, use VNC Viewer to connect to the Mac Mini (if you need credentials, ask dev management)
- Open XCode
- On the top toolbar, click Windows and then click Organizers
- You should see Archives as a tab on the left, and in there you should see the archive you just created in Visual Studio
- Select the archive and click distribute app
- Follow the wizard, leaving all the defaults except the one asking about sending reports to Apple and XCode - uncheck that box
- Please step through next steps with a member of the Dev management.
- Login into https://developer.apple.com/ using login from Last pass: Mobile Dev Apple Account. (may need to be logged into the dev mac to get the authentication code on login)
- Go to the App Store Connect section and choose Apps:
- Then go to the TestFlight tab at the top. You will now see the most recent version displayed. It will take a while to process.
- Once done processing it will ask to complete some compliance information. Click on manage and then answer the questions as shown below (I had two different sets of questions I had to ask so both are listed below):
18. Once you hit start internal testing make sure your apple ID is added to the internal testings users list and download the testflight app on your apple device. Once app is up and running log in and accept the invite to the app.
19. You are not good to test the app.
Debugging the Android app:
- Set efcMobileApp.Droid as the startup project
- Make sure you are in Debug mode, not Release mode
- Run the emulator you have (you may need to install a new device)
- Make sure you have enabled Hyper-V and Windows Hypervisor Platform in windows features, and that you have enabled Virtulization (or SVM on AMD) in your bios (If you don't android emulation probably won't actually work). You will want to restart your computer when you do this. Also see this doc for further guidance.
- Wait for a long time - the Android emulator is very slow on startup
- Alternative: If you have an Android phone, plug it in and on step 3 select your phone on the run dropdown. That way debugging should be a lot faster.
Releasing the Android app:
- Release can not be done in Visual Studio 2022, Please use Visual Studio 2019
- Make sure you've followed the steps found here to make sure JDK 11 is installed and will work with VS 2019.
- Set efcMobileApp.Droid as the startup project
- Make sure you are in Release mode, not Debug mode
- Right click on efcMobileApp.Droid and click Archive...
- Once the Archive has completed, click Open Distribution (you can also click the 'Distribute' button, and wak through through the steps, at the end just make sure you upload to the lowest level track)
- If at any point you are asked for signing credentials, they are found in the Android Signature Key Info file in the root of the source code.
- If at any point you are asked for a keystore file, import the keystore file found in the root of the source code.
- Give the resulting apk file to dev management to upload to the play store.
SonarCloud and SonarLint Setup Steps
Link your ADO account to SonarCloud
- Go to the SonarCloud link and click "Log In" then "With Azure Devops" button
- Let one of the senior devs know so they can add you to the SonarCloud project
- Login again and make sure you can access the Utopia project in SonarCloud
Download and setup the SonarLint IDE tool
- Go to https://marketplace.visualstudio.com/items?itemName=SonarSource.SonarLintforVisualStudio2019 and download the extension.
- Restart VS if it was running. (Yes, you have to)
- Inside VS go to Team Explorer > SonarQube > connect
- You'll be prompted for a url and login for SonarCloud.
- Url is https://sonarcloud.io
- For username/password you'll need to generate an auth token. Go to SonarCloud, login, click on your profile pic > My Account. Now click the Security tab, enter a token name, and click Generate. I'd recommend saving this token into a password manager, you can only see it one time.
- Copy this token into the Username field back in the VS login prompt, no password is needed
- Select EFC Sonar Cloud Integration as the Project
- In the Team Explorer > SonarQube tab, right click on Utopia and select Bind (Or update if it's already been bound)
- It will take a minute, but all of the linter rules will be pulled down from the cloud and you should start seeing additional Warnings for security issues in the Error List tab on the bottom of the IDE (Error Code will start with an 'S')
How to Run WOPI Validator Tests on O365
The WOPI Validator Tool allows us to make sure our endpoints conform to the WOPI protocol so we can offer an Office 365 integration. This tool is run through Windows PowerShell, but in order to make it work, we need 4 things first:
- The WOPI source code on our machine
- A valid Rubex Authentication token
- The port that we can use to run the WOPI tool with
- The node id of the file we're running the WOPI too
Please note, number 4 is only needed if you're using a file endpoint from FilesController.cs in Utopia (wopi/files/{id}). There are other endpoints you can use, just be sure to update the powershell command accordingly. This is just an example using the file endpoint.
Source Code Setup (Utopia and WOPI)
- Clone the WOPI source code onto your machine in a place easily accessible to you. A good option is just your source folder where your other repositories are.
- Once the WOPI code is cloned, open the solution at the path: wopi-validator-core\WopiValidator.sln
- Build the project in Release mode. This will add the necessary files and directories to enable you to run the tool in PowerShell later.
- In Utopia, navigate to Utopia/Controllers/Wopi/WopiBaseController.cs - modify the ValidateRequestAsync method to always return true. We cannot run the proofkey portion of the test locally.
Rubex Authentication Token
- Run Utopia
- Go to the UtopiaDB and view the data in the DbUserSessions table.
- Copy the token under the AccessToken column header on your current session row (i.e. 07680FAC-90D8-419B-AF81-5C14BFA23F4F). This token is the valid Rubex Auth Token you need to run the WOPI tool. Copy it and paste it somewhere that will be easily accessible later.
- Alternatively, open up devtools networking tab in the Utopia window. Find an API call and copy the access token from the Authorization header
- Important: Keep your local Rubex session alive during the entire rest of this process or you will need to grab a new auth token!
Port to Use
- With the Utopia project still running, go to your taskbar and right click IIS Express.
- Under the header "View Sites", you should see Utopia. Hover over it to see the ports Rubex is using.
- There should be two ports, one that matches the port in the URL (i.e. localhost:54298) and one that's different (i.e. localhost:44313).
- The port you want to copy and save for later is the one that doesn't match the URL port when you look at the browser running your Utopia project. The port you want is probably 44313 or 44311 or the like.
- Keep track of it in the same place you saved your authentication token.
Node ID to Use
- Download one of the wopi test files found here . It doesn't matter which one you use, there are just a few in here to try out.
- Upload the file you chose to your localhost environment.
- Once the upload completes, go to the UtopiaDB again and view the data in the DbNodes table.
- Find the wopi test file you created and grab its Node ID from the Id column of the table (i.e. 294 or 11020). Keep track of it in the same place you saved your port and authentication token.
Putting it All Together
- Open PowerShell in the wopi-validator-core\src\WopiValidator\bin\Release\net6.0\ directory
- The first time you try to run a test with a new user, you must run the following test:
dotnet Microsoft.Office.WopiValidator.dll -t TOKEN -l 0 -w https://localhost:PORT/wopi/files/NODE_ID -g PutUserInfo
This will populate a string value on the user so that all subsequent tests will pass. If this is missing, you'll get error messages about missing the "UserInfo" property.
Substitute the TOKEN, PORT, and NODE_ID for your retrieved values. - If you want to run all of the WOPI Validations tests, run:
dotnet Microsoft.Office.WopiValidator.dll -t TOKEN -l 0 -w https://localhost:PORT/wopi/files/NODE_ID --ignore-skipped
Substitute the TOKEN, PORT, and NODE_ID for your retrieved values. - If you want to run a specific Test Case of the WOPI Validation tests, run:
dotnet Microsoft.Office.WopiValidator.dll -n NAME -w https://localhost:PORT/<YOUR ROUTE HERE> -t TOKEN -l 0
Substitute the TOKEN and PORT with your retrieved values and the YOUR ROUTE HERE needs to match up to the endpoint you are testing. The NAME is where you place the name of the test case you want to run.- For example: If you are testing name
containers.EnumerateAncestorsOnRoot
then you should match it to the endpoint/wopi/containers/NODE_ID/ancestry
where node isNODE_ID
is your retrieved value from above. - Test case and test group names are all found inside of TestCases.xml found in the same folder as that .dll
- For example: If you are testing name
- See the Additional Info section for more commands
Troubleshooting
- If at any time, all your test cases are getting skipped and you want to see why, be sure to remove the --ignore-skipped flag from your command and run it again. If you see that the reason for skipping the test cases is a 306 Unused error, that means your port is wrong. Make sure you're using one of the ports listed under Utopia in IIS Express, and make sure it's not the port your browser is using to connect to Rubex.
- If you are getting lots of Authorization exceptions while you're running your test cases, it simply means your Rubex Authentication token is no longer valid. Log out (if you're not already) and login again. Then follow the steps in the Rubex Authentication Token section of this document to get the new auth token. Replace the token in your command with this new one and run the test cases again.
- If you are seeing a message about missing the UserInfo property, see step 2 of "Putting it All Together"
Additional Info
Microsoft.Office.WopiValidator 1.0.0
Copyright (C) 2018 Microsoft
-w, --wopisrc Required. WopiSrc URL for a wopitest file
-t, --token Required. WOPI access token
-l, --token_ttl Required. WOPI access token ttl
-c, --config (Default: runConfig.xml) Path to XML file with test definitions
-g, --testgroup Run only the tests in the specified group (cannot be used with testname)
-n, --testname Run only the test specified (cannot be used with testgroup)
-e, --testcategory (Default: All) Run only the tests in the specified category
-s, --ignore-skipped Don't output any info about skipped tests.
--help Display this help screen.
--version Display version information.
AWS DMS Setup
How to setup AWS DMS:
This is assuming the PostgreSQL DB is already created
SETUP SCHEMA:
A. Get the sqlserver2pgsql.pl script from https://github.com/dalibo/sqlserver2pgsql/blob/master/INSTALL.md
- We will not be using Kettle
B. Install perl
C. In MSSQ Studio, right click on the database required to migrate and select Task -> Generate Scripts
- Under SQL Server Management Studio, Right click on the database you want to export
- Select Tasks/Generate Scripts
- Click "Next" on the welcome screen (if it hasn't already been deactivated)
- Select your database
- In the list of things you can export, just change "Script Indexes" from False to True, then "Next"
- Select Tables then "Next"
- Select the tables you want to export (or select all), then "Next"
- Script to file, choose a filename, then "Next"
- Select unicode encoding (who knows…, maybe someone has put accents in objects names, or in comments)
- You will receive a SQL script (in SQL Server syntax) with Db Structure (tables, indexes, constraints, stored procedures, etc)
D. In the terminal, go to where the sqlserver2pgsql.pl script is kept and run the following:~/sqlserver2pgsql.pl -f <THE NAME OF THE FILE DUMP THAT CAME FROM PART C> -b before.sql -a after.sql -u unsure.sql -keep_identifier_case -stringtype_unspecified
- The before script is what you should run before data migration
- There may be some errors that come up when the perl script reads the MSSQ Db SQL dump. Mostly it's just syntax that can be manipulated inside of the dump.
- If this comes up as an error it can be removed: 'ALTER TABLE [dbo].[DbNodeClosures] SET (LOCK_ESCALATION = DISABLE)'
- You will probably have errors with the create views, this is just a whitespace issue. Remove that and you'll be golden.
- It will probably ignore functions and procedures... Keep that in mind, it may not be important for procedures, and important for functions (although if you've already enabled cdc on tables, you can ignore those ignored functions)
- The after script is what you should run after data migration
- keep in mind that postgres has a max constraint name size of 63 characters, so currently these will need to be renamed manually. View the alterations.sql file to see what I did (I had 48 alterations to adjust)
- The unsure script is what you should run after data migration but needs review and will more than likely need quite a few edits
- Often it doesn't have views, functions, and other things
- View the 'updated-unsure.sql' file as an example as it is what was used for the test migration
E. Connect to the PostgreSQL DB and run the before script (this will build the tables, types, and columns)
- I recommend using pgAdmin4
- https://www.pgadmin.org/download/pgadmin-4-windows/
- If you get an error having it run (eternal loading screen) then go into the Registry Editor -> \HKEY_CLASSES_ROOT.js -> Change 'Content Type' to text/javascript
F. Migrate your data over as listed in the 'SETUP AND RUN AWS DMS' section
G. Make sure that everything is migrated over
H. Connect to the PostgreSQL DB and run the after and unsure scripts
- Do so after you've reviewed them to make sure they're accurate and the constraint names are 63 characters or less
I. Go play some Starcraft, you've earned it
SETUP AND RUN AWS DMS:
- Create your Replication Instance on AWS DMS
- Not needed anymore, can just use the one that's already built
- Make sure that the Replication Instance's IP address is allowed to enter the VPC security group of both the Source enpoint's DB and the Target endpoint's DB, if not, add it to both
- Create your endpoints (source and target)
- Test the connection with the Replication Instance before creating the endpoint (it will create even if the Replication instance can't connect to it)
- Do everything here on the MSSQ DB
- https://aws.amazon.com/premiumsupport/knowledge-center/dms-migrate-rds-sqlserver/
- I know that it sucks to need to enable CDC for each table sooo just run the AutoWriter program if the tables are different then what's there, make sure you replace the strings in the file
- I've noticed better results (in that the task would run without errors) by just keeping 'exec sys.sp_cdc_stop_job;' and not turning it back on, though keep in mind that you probably won't be able to get your logs, so turn it back on if you need those
- You may get a table that fails, that's fine as it's probably a table that MSSQ made and isn't in the DB
- Run these to get the tables if needed
For the dbo SCHEMA:
SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_SCHEMA='dbo'
For the workflow SCHEMA:
SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_SCHEMA='workflow'
- Create a DB migration task
- Task Identifier: Something unique
- Descriptive Amazon Resource Name (ARN): Skip this
- Replication instance: Choose the Replication Instance from step 1
- Select your Endpoints
- Migration Type - I recommend 'Migrate existing data and replicate ongoing changes'
- Editing mode: Wizard
- Target table preparation mode: Do Nothing
- Include LOB columns in replication: Full LOB mode
- Maximum LOB size (KB): I set it to 10,000 but you can set it to whatever is needed
- Enable validation: true
- Enable CloudWatch logs: true
- Advanced task settings
- Create control table in target using schema: dms
- Enable control table - enable all
- Table mappings
- Create two new selection rules and include SCHEMAs 'dbo' and 'workflow'
- Create one new transformation rule with Target -> Schema, Schema name -> 'dbo', Action -> 'Rename to', Value -> 'public'
- Migration task startup configuration: Automatically start
- Save n start it
Previewer Setup for Local Environment
Use Docker To get the Previewer Up and Running: For local use
Taken from Accusoft’s Try It link:
Accusoft: Try It!
- Make sure you have stopped Prizm and Prizm Application Services so the ports won’t conflict
- Download Docker Desktop (Windows): Docker Desktop
- Open up PowerShell and run this command:
docker pull accusoft/prizmdoc-viewer-eval:13.26
- Find our Solution Name and License Key in LastPass under Prizm License and replace YOUR_SOLUTION_NAME and YOUR_LICENSE_KEY in the command below of your choice
- Option 1 (Recommended)-
If you want to be able to restart the docker container use this (once this is run you only have to click stop or play in the Docker Desktop app):docker run -p 8888:8888 -p 3000:3000 -p 18681:18681 -e ACCEPT_EULA=YES -e LICENSE_SOLUTION_NAME=YOUR_SOLUTION_NAME -e LICENSE_KEY=YOUR_LICENSE_KEY --name prizmdoc-viewer-eval docker pull accusoft/prizmdoc-viewer-eval:13.26
- Once the PrizmDoc Server and PAS are running in PowerShell, and you can see the container named accusoft/prizmdoc-viewer-eval:latest in Docker Desktop you can close PowerShell. This will stop the container. Hit play in Docker Desktop to start it back up again.
- Option 2-
If you want the docker container to be removed when you stop it use this:
docker run --rm -p 8888:8888 -p 3000:3000 -p 18681:18681 -e ACCEPT_EULA=YES -e LICENSE_SOLUTION_NAME=YOUR_SOLUTION_NAME -e LICENSE_KEY=YOUR_LICENSE_KEY --name prizmdoc-viewer-eval accusoft/prizmdoc-viewer-eval:13.26
- It takes a few minutes for everything to start up, even though it says it's running in Docker. Confirm that everything is running with these checks:
-
Option 1- Check that the sample application is running
Sample Application -
Option 2- Check the server and service separately
- Check PrizmDoc Server
Health Check
Admin Status - Check PrizmDoc Application Services(PAS)
Health Check
Service Connection
- Check PrizmDoc Server
- Once the application loads or all the checks come back with OK you are ready to start using the PrizmDoc Previewer with the AccusoftPreviewer solution.
Note: To get updates, just click the delete icon in Docker Desktop and repeat the steps above.
For debugging the front end of the Previewer:
On your machine, make sure you have node.js, npm, and gulp installed.
- Node needs to be a specific version. Check if node is installed by running
node -v
- If you have node version 11.3.0, skip to the npm installation
- If you don't have node installed:
- Use this msi: https://nodejs.org/download/release/v11.3.0/node-v11.3.0-x86.msi
- Verify it installed correctly by running
node -v
- If you have a different version of node already installed, try installing nvm (node version manager) for Windows:
- Download the nvm-setup.zip at this site: https://github.com/coreybutler/nvm-windows/releases , unzip it and run the application
- Close out of your command line and reopen it (make sure to run it as an administrator)
- Check that it installed correctly by running
nvm -v
- Run
nvm install 11.3.0
to install the correct version of node - Run
nvm use 11.3.0
to switch to the correct version
- Make sure npm is installed by running
npm -v
- If you don't have it installed, just run
sudo apt install npm
ornpm install -g npm
- If there are errors installing npm, make sure you update first by running
sudo apt-get update
- If there are errors installing npm, make sure you update first by running
- If you don't have it installed, just run
- To install gulp, simply run the command
npm install -global gulp
Now you've got what you need. To run the previewer and debug it:
- Run Utopia and Utopia\UtopiaPreviewers\AccusoftPreviewer at the same time.
- In the source code, open the source code and go to the following directory: Utopia\UtopiaPreviewers\AccusoftPreviewer\AccusoftPreviewer\wwwroot\ViewerSources
- Open a powershell window in that directory and run the command ./builddev.bat
- In the Utopia window, open the dev tools and make sure the cache is disabled
- In the Utopia dev tools, you'll see a "Previewer" item in the tree view - if you expand it, you should see webpack://, which you can expand and find ./modules
- If you don't see ./modules then you'll need to right click the Previewer in the browser and select Reload Frame. Then repeat steps 4 and 5.
- In the ./modules directory, you'll see the client code for debugging.
- Go eat a donut. You deserve it. You're ready to debug with the Previewer!
Troubleshooting
- Make sure you have Azure Storage Emulator running.
- If running the ./builddev.bat script doesn't work, try running it again in PowerShell as an administrator
- If that still doesn't work, try running the AccusoftPreviewer project as an administrator in Visual Studio.
The Way of Pain - To get the Previewer up and running:
- Download and install the PrizmDoc Server and Client
- if the following steps dont't work to install the PrizmDoc Server and Client, see Quinn's comment
- https://v953w.app.goo.gl/ef1g
- For the user, the best thing to do is create a new system user and set a password to use for PrizmDoc. You CAN use your own user, but be aware -- if you change your password, PrizmDoc will not work until you update the password, see this link on how to update https://www.accusoft.com/faqs/is-it-possible-to-change-the-login-accounts-on-prizmdoc-services-in-windows/
- Also for user, if you created a new one, you may need to add the user to the Window's Administrators group.
- For the Server pick 'I have purchased a license' and then pick OEM. Then License info is the Development-Shared folder in Last Pass.
- Use the default URL for the client installer
- Other than the User/Password info, you should be able to just keep defaults on all options.
-
Restart your computer, yes... you have to.
-
Make sure the PrizmDoc server and client are running, (Demo isn't required to be running). These are services that need to be running called 'PrizmDoc' and 'PrizmApplicationServices'
-
Start the Utopia Project found Utopia\UtopiaPreviewers\AccusoftPreviewer - While this is running you can preview files in your local Utopia instance and the previewer project webpage will be a HTTP Error 403.14 - Forbidden type page.
Note: Azure storage needs to be running or the previewer will timeout while loading
Note: Make sure your port number is correct in the AccusoftPreviewer.csproj file. The line <IISExpressSSLPort>44318</IISExpressSSLPort> got changed to <IISExpressSSLPort>44300</IISExpressSSLPort>. VS automatically sets this in some fashion, so make sure your hitting the correct port, I also made the mistake of trying to line it up to port 50560 (not the 44300 or the correct one 44318) which didn't help finding the problem. To not have problems in the future you need to update the ssl port in 3 different files.
- C:\src\Utopia\UtopiaPreviewers\AccusoftPreviewer\AccusoftPreviewer\AccusoftPreviewer.csproj
- C:\src\Utopia\UtopiaPreviewers\AccusoftPreviewer\AccusoftPreviewer\AccusoftPreviewer.csproj.user
- C:\src\Utopia\UtopiaPreviewers\AccusoftPreviewer.vs\AccusoftPreviewer\config\applicationhost.config
OCR Worker Local Setup
Keep in mind that these are the instructions that were used during testing of the OnPremise/Master merge that happened
- Download Accusoft ImageGear (it is NOT a service)
- Install it with the evaluators license
- Inside of appsettings.json set "RunAsService" to false
- Inside of App.config set
<add key="AccusoftSolutionName" value="EFileCabinet" />
<add key="AccusoftSolutionKey" value="0x50DBF8B0,0x898D16D1,0x6BBB80AD,0xD99D98D8" />
to<add key="AccusoftSolutionName" value="" />
<add key="AccusoftSolutionKey" value="" />
- Inside of Program.cs inside of LoadWorkerConfiguration() comment out these two lines
AccusoftSolutionName = InstanceSettingsManager.Get<string>(InstanceSettingEnum.FileOCRWorkerAccusoftSolutionName),
AccusoftSolutionKey = InstanceSettingsManager.Get<string>(InstanceSettingEnum.FileOCRWorkerAccusoftSolutionKey),
- Test that all is well by performing an OCR
- You will probably get a GdPicture error, that is expected, just continue
Windows Services
Server Service:
First, we need to publish the Utopia Project.
After that we need to create the service by running the command (use Admin Command Prompt):SC CREATE "ServerService" binpath="C:\Projects\Efilecabinet\Utopia\Utopia\Utopia\bin\Release\netcoreapp3.1\publish\Utopia.exe"
The bin path it's the path of the publish project + "Utopia.exe".
Now the service it's created. We can open the Services app of windows and check it.
The logs go to this path or similar:
Useful commands:
Delete the service:
sc.exe delete "ServerService"
Stop the service:
sc stop "FileOCRService"
List of the service names and projects:
FileOCRService - File OCR worker
Index Service - File Indexing worker
Rubex Service - Utopia Batch Worker
Server - Utopia
All the projects use .net core worker sdk, except File OCR Worker that continues on .net framework. For this project, we need to use the exact same name on the creation of the service. And if an error like this one ("Login failed for user 'NT AUTHORITY\SYSTEM'. Reason: Failed to open the explicitly specified database 'UtopiaDB2'. [CLIENT: <local machine>]") occurs, we need to create the user 'NT AUTHORITY\SYSTEM' on the db with all permissions.
Checking Event Viewer windows app it's useful for debugging services that fail to start for example.
Setup/Configurations for Mac Mini
Connecting
*You will need to be at our office or on the VPN to do this
- Download VNC Viewer
- Make sure the Mac you're wanting to connect to is actually plugged in (check the ethernet cable) and turned on
- The two QA ones are by all the other QA testing machines (as of 10/25/2022)
- The Dev one is by McKay's space - in the Ops corner (as of 10/25/2022)
- Once it's open, add a new connection see credentials
- The dev mac currently is the only machine that has all the signing certificates for the Mac Desktop Client
- The dev mac is often turned off
- The QA mac 1 is much faster than any of the others, but doesn't have the signing certificates for the Desktop Client
- When setting up the QA mac within VNC, turn Encryption > Prefer Off
- Make sure no one from QA is using it
- The dev mac currently is the only machine that has all the signing certificates for the Mac Desktop Client
Credentials
DEV MAC
IP Address: 10.10.0.60
Login Info In Last Pass: Development Mac Mini
QA MAC 1
IP Address: 10.10.0.68
Login Info In Last Pass: QA Mac Mini 1
QA MAC 2 (not recommended)
IP Address: 10.10.0.67
Login Info In Last Pass: QA Mac Mini 2
Before you get started
You will need the following installed on your machine (Dev mac and QA mac 1 have these already):
- XCode
- Note: Be careful with updating xCode versions, as it is likely to break building in release mode for the mac desktop client
- Make sure you open XCode and check all the boxes to install the things needed
- Visual Studio for mac with:
- .NET
- .NET WebAssembly Build Tools
- macOS (Cocoa) - all versions listed
- Android
- iOS
- Our codebase
Version Control
IMPORTANT - the master branch for the Mac Desktop Client is different from windows. You're looking for origin/mac-master. Branch off of that unless instructed otherwise
Sometimes git through Visual Studio for mac is really dumb, especially with changing branches. The good news is that you can use git through terminal where needed.
- If using Visual Studio for Mac for version control, make sure that when you bring the branch into your local environment, that you also track the branch, this will prevent a few issues
Useful Git Commands
- Force change branches => git switch -f <branch-name>
- It tries rebasing on branch swap sometimes => git rebase --quit
NuGet
You will probably need to add our UtopiaNuget at some point to a project on mac. The process is slightly different than what is described in our other wiki page.
- Go to the NuGet packages in the solution and select Configure Sources
-
- Go in to ADO and select Personal Access Tokens
-
- Select + New Token
- Give it a name
- Change the expiration to be far in the future
- Give full access scope
- Click Create
- Save the token you are given and don't lose it
- You will not be given it again and will need to regenerate another one if you lose it, potentially breaking other connections
-
- Add a new package source
- Name it UtopiaNuget
- The location is https://pkgs.dev.azure.com/eFileCabinet/Utopia/_packaging/UtopiaNuget/nuget/v3/index.json
- The username is your ADO username
- The password is the token you generated in step 2
- Click Add Source
- Click OK
- At this point, if you select UtopiaNuget as the package source and are on the browse page, you should be able to see all of our packages we offer.
Troubleshooting
- If you finish all the steps successfully, and can see all the packages we offer, but restoring the packages still gives you a problem, then Visual Studio for mac messed up on adding a nuget reference to the global nuget file.
- The fix is to search for the hidden file NuGet.Config and add the reference to the new package source manually
-
-
(ignore the double reference)
-
- The fix is to search for the hidden file NuGet.Config and add the reference to the new package source manually
Mac Desktop Client
IMPORTANT - the master branch for mac is different from windows. You're looking for origin/mac-master. Branch off of that unless instructed otherwise
If you're feeling courageous and want to mess with getting the signing certificates working on a machine other than the dev mac machine, then the credentials are found in last pass and is named Mobile Dev Apple Account.
Helpful Tips
It may be beneficial to run a local instance of Utopia to connect to for the Desktop Client.
- See our page on how to do this
- It is only possible to do from the office since you're remoting into the mac for testing
Building in Debug Mode
*If you're building on a machine that doesn't have the signing certificates (any other than Dev Mac Machine), you will need to set signing to false in the project file.
To be able to build, you need to first have built two other projects on the machine:
- UtopiaAPIClient
- SharedLogic
It is very likely that you will need to update their references to UtopiaSharedClasses in NuGet. I recommend going into the UtopiaWindowsDesktopClient to update the packages and build them.
Building in Release Mode
*As of right now the signing certificates are only on the Dev Mac machine. I've tried putting it on the other mac, and they are there, but they require a password per use, which we don't have.
To build in release mode, it's as simple as putting it in release mode in visual studio, updating the version number in the Product.plist file, and running build. Once done, then go into the bin folder to get the dmg file
../UtopiaMacDesktopClient/RubexClient/bin/Release/RubexInstaller.dmg
Send this to QA to test your changes. If they sign off on it then you're good to have it replace the dmg file in Utopia. Make sure you update the version number in the json file in the Utopia project after updating the dmg file!
Note
There is a chance that building it won't sign it properly or build the dmg. I never had this problem, but if you do then you will need to follow these steps:
Monterey 12.0.1 has build issues when trying to build an installer from Visual Studios when running the release mode for Rubex Desktop Mac Application. Had to manually build the files. There is a Product.plist file in the obj/release folder that has a property called “os”, delete this entry and run the below commands (with the proper version).
productbuild --product /Users/dev/
appdmg /Users/dev/
iOS Mobile
*I haven't touched this much but we do have a helpful page already built. I don't know how up to date it may be.
Office Addins Terminal Services Environment
With Terminal Services, the Office Add-ins don't always show up, despite being installed for all users.
The batch script below imports the registry settings needed into HKEY_CURRENT_USER and can be run for each user to make the Office Add-ins show up. It is dependent on them installing it to the default path.
OfficeAddinRegistry.zip
Utopia Local DB Refresher
The Utopia local database refresher solution is located in the Utopia repo in the UtopiaLocalDatabaseRefresher folder.
- Check that all the requirements are met before running:
- Make sure you've stopped the Microsoft Azure Storage Emulator
- PG Admin already set up with the local Postgres instance for Utopia
- Docker needs to be installed. (Docker Desktop is available on the Company Portal)
- Get ElasticSearch Running in Docker (see ElasticSearch Doc)
- DbMigratorEF has been rebuilt in debug (Open the Utopia solution, switch to DbMigratorEF and rebuild in debug)
- Rebuild UtopiaBatchWorker in debug as well
- Open the UtopiaLocalDatabaseRefresher solution
- (Optional) Update the "TestUserName" and the "TestUserPassword" to the desired values in appSettings.json
- Ensure you have met the requirements
- Run the solution in debug
If things are broken and you need to do it manually:
-
Make sure the Azure Storage Emulator or Azurite is running
-
Make sure Elastic Search is running
-
In pgAdmin4 Drop Cascade schemas: public and workflow
-
Right click Schemas
-
Create a schema called “public”
-
In the Utopia solution switch “Set startup project” to DbMigratorEF and run in debug (in command prompt press enter unless need other options)
-
Switch back to Utopia project
-
Run DBInstanceSettingsLocalConfig.sql from Utopia repo
-
Open and run the UtopiaBatchWorker solution
Generating a DB Connection String
- Locate the ConfigurationDataCreator solution in the Utopia repo
- Start the solution
Create a new connection string
- Fill in the corresponding fields under Configuration Value
- It can be helpful to click Load Configuration From System to see the local values
- Most of this information can be found in LastPass or should be provided to you
- Note that all fields are required to create a new connection string
- Click Create Configuration Data String
- The new string will populate in the Configuration Data Output field
Pull information from a connection string
- Paste the encrypted connection string in the field Encrypted Value and click the Encrypt/Decrypt button
- The decrypted value will be populated in the Decrypted Value field
Encrypt a connection string from a JSON object
-
Paste the JSON object into the Decrypted Value field and click the Encrypt/Decrypt button
- The encrypted value will be populated in the Encrypted Value field
Populate configuration values from a connection string
- Paste the encrypted connection string into the Configuration Data Input field and click Load Configuration Data String
How to Sign and Notarize a New Build for the Mac
I recently learned how to sign and notarize our build for the Mac Mini and will be documenting both the one-time setup that I had to do, as well as the steps that must be taken with each new build. Many of these steps began as outlined in this blog, though with extensive changes along the way. If all you're looking for is how to make the next build for the Mac, please skip down to the "Notarize and Staple a Build" section.
Initial Setup
All of this setup has already occurred, and you probably won't ever need to do any of it again. These instructions are here just so that we can reproduce these actions if that is ever made necessary.
Update the Keychain certificates
In order to sign and notarize our build file, we're going to need to use two Keychain Certificates.
- Open the Keychain Access app, open the "All Items" tab
- Search for "J82X76G6Y8" (our "team identifier")
- Among the results you are looking for these two certificates
- Developer ID Application: eFilecabinet, Inc. (J82X76G6Y8)
- Developer ID Installer: eFilecabinet, Inc. (J82X76G6Y8)
- You need to verify that both of these are still current (not expired). You also need to make sure that there aren't any expired duplicates of these certificates. If there are, then right-click on the expired duplicates and delete them.
Configure Visual Studio to use the Hardened Runtime
For our application to be notarized, it is also necessary for it to be compiled using the Hardened Runtime.
- Right-click on the RubexClient project in the Solution side-panel of Visual Studio and select Properties. Then open the Build->Mac Signing view
- Check "Enable Hardened Runtime
- In the "Custom entitlements" field enter: Entitlements.plist
- Open the Entitlements.plist and add a necessary permission.
- If you are doing this in Visual Studio, click "Add new entry" and then enter the following in each column
- Property: com.apple.security.cs.allow-jit
- Type: Boolean
- Value: Yes
- If you are doing this in a text editor, inside of the <dict></dict> section add the following:
<key>com.apple.security.cs.allow-jit</key>
<true/>
- If you are doing this in Visual Studio, click "Add new entry" and then enter the following in each column
Configure Visual Studio to sign the .dmg build
Now Visual Studio needs to be configured to sign the package as part of the build process. For this you will need the name of the Installer certificate from the last step, as well as the identifier for our application (currently "com.efilecabinet.rubex").
- In the Visual Studio project find and open the spec.json file
- On the same level as the title, background, icon-size, contents, and window, add a new section as follows (with the current signing-identity and identifier as defined above):
"code-sign": {
"signing-identity": "Developer ID Application: eFilecabinet, Inc. (J82X76G6Y8)",
"identifier": "com.efilecabinet.rubex"
} - Next, right-click on the RubexClient project in the Solution side-panel of Visual Studio and select Properties. Then open the Build->Mac Signing view
- Check "Sign the application bundle" at the top
- For the "Identity" directly beneath that checkbox select "Developer ID: eFilecabinet, Inc. (J82X76G6Y8)"
- Check "Sign the installer package" at the bottom
- For the "Identity" directly beneath that checkbox select "Developer ID Installer: eFilecabinet, Inc. (J82X76G6Y8)"
- Now when you build the project, towards the end of the process you should see a line that says:
- [20/21] Signing image... [ OK ]
Generate Application-Specific Password for notarytool
Now that we have a signed build using the hardened runtime, we can configure our notarization tools. For this, we use the command-line utility "notarytool." First, though, we must authenticate the tool with an application-specific password. The current application-password is stored in LastPass, under the Notes section of the Mobile Dev Apple Account item. If you ever need to create a new password, then:
- Go to the Apple ID website
- Enter the sign-in credentials under the Mobile Dev Apple Account item in LastPass
- You will probably need to enter a second-factor code. For this you'll want to be signed into the Development Mac Mini so you can see the sign-in attempt alert, approve it, and get the 6-digit code to complete your sign in
- Under the Sign-in and Security section select App-Specific Passwords
- Press the + button, enter a memorable name, and press the Create button
- You will ONLY be able to see the password one time on the next screen, so be sure to save that somewhere for reference
Authorize notarytool
Now we can use this password to authorize the notarytool.
- In a terminal on the mac run:
xcrun notarytool store-credentials --apple-id "mobiledev@efilecabinet.net" --team-id "J82X76G6Y8"
Note the 10-digit team id at the end that we got from our certificates. Also, the Apple ID is the same one that we used to sign into the mobile dev account. - You will then be asked for a "Profile name." Choose something meaningful and write it down for future use. Our current profile name is "notary-credentials"
- You will then be asked for the password that goes with your account (mobiledev@efilecabinet.net). This does not mean the password that you used to sign into the Apple Id account. It means the Application-Specific Password that you generated at the end of the last section.
- It should process for a minute and then tell you that it has validated your credentials and saved them to Keychain. You will now be able to reference that Keychain item using the "Profile name" that you provided on step 2.
In the following section it refers to the keychain profile as "notary-credentials." Obviously, you would change that to whatever profile name you set in this section.
Notarize and Staple a Build
- Increment the "Bundle versions string" in the Info.plist of the Visual Studio project
- Ensure that your Visual Studio project is set to build for Release
- Select Build->Rebuild Solution
- Open a terminal and navigate to the build location: dev/UtopiaClientApplications/UtopiaMacDesktopClient/RubexClient/bin/Release/
- Notarize the built .dmg file with the following command:
xcrun notarytool submit RubexInstaller.dmg --keychain-profile "notary-credentials" --wait
It will run for a while, just wait for it to complete with a success message. - Now you need to "staple" that notarization to the .dmg file. You do that with this command:
xcrun stapler staple RubexInstaller.dmg - Finally, check that everything is correct by running this command
spctl --assess -vv --type install RubexInstaller.dmg
This should give a response message the .dmg file is "accepted," that the source is a "Notarized Developer ID," and the origin should be our developer id.
You may now give the signed and notarized RubexInstaller.dmg to QA for testing and then SecDevOps for release.
How to Renew a Certificate for Mac
To build and sign our Apple-product applications it is required for us to point the build towards valid certificates, which expire after a number of years. We will periodically need to renew these certificates. You can view the status of any certificates by opening Keychain Access. Any items that are already expired will have a red X by them, and every certificate's expiration date can be seen in a column to the right. To renew any expired/soon-to-be-expired certificates:
- Open Xcode.
- Don't open or create a project, just select Xcode->Settings from the top menu.
- Select Accounts from the top ribbon menu.
- Select the mobiledev@efilecabinet.net account (not mobiledev@efilecabinet.com). You may need to sign in again, using the credentials in LastPass.
- Select the "eFileCabinet, Inc." team.
- Click Manage Certificates.
- Click the + dropdown button in the bottom-left.
- Select the needed certificate type.
- You should now see the new certificate in the main list, and it should have the same name as the previous certificate in that category.
**Note: The next time that you try to build a project that relies on the new certificate you might get a popup requesting the "login" keychain password. This password should be the same one that you used to sign into the Dev account on the Mac machine (e.g. the password for the Development Mac Mini item in LastPass). Make sure to select "Allow Always" after entering the password so you won't have to do this again.
Go ahead and delete the old certificate once you verify that the new one is working for you. Having duplicates can make certain signing operations confused.
Local Testing
Test Utopia local changes in Atlantis local
-
Check that Utopia appsettings.json has:
"Environ": "Staging", "Region": "LocalToStage"
- In Utopia file SystemResourceController.cs search for AtlantisFrontendUrl = UtopiaSettings?.AtlantisFrontendUrl and change it to AtlantisFrontendUrl = "https://localhost:44437"
- Make sure you're opted into Atlantis or in Utopia go to the file UserService.cs, search for the method GetAtlantisOptInStatusAsync, and have it return true
- Check that Atlantis appsettings.json has:
"Environ": "Local"
Note: You will be using your local database. Don't change DbConnectionConfigurationData in Utopia appsettings.json.
Test Utopia local changes against local DB
-
Leave Utopia appsettings.json as:
"Environ": "Staging", "Region": "LocalToStage"
- Make sure you're opted out of Atlantis or in Utopia go to the file UserService.cs, search for the method GetAtlantisOptInStatusAsync, and have it return false
Test Utopia local changes against staging DB
-
Leave Utopia appsettings.json as:
"Environ": "Staging", "Region": "LocalToStage"
- Update DbConnectionConfigurationData to the staging connection string found in LastPass under "Utopia Staging DB AWS"
- Make sure you're opted out of Atlantis or in Utopia go to the file UserService.cs, search for the method GetAtlantisOptInStatusAsync, and have it return false
- If working remotely make sure you're on the VPN
Standards
Coding Standards
Coding Rules
- Thou shalt not commit to the master branch, pull requests only.
- Thou shalt not use magic values.
- Thou shalt not use static classes save for utilities.
- Thou shalt not write recursive methods without an exit case.
- Thou shalt spell things correctly.
- Thou shalt modularize all thine code.
- Thou shalt keep thine methods short.
- Thou shalt name thine variables with a descriptive name.
- Thou shalt name thine methods with a name that describes what the method does.
- Thou shalt think of the future while coding the present.
- Thou shalt make thy code self-documenting.
Please read: https://github.com/dotnet/corefx/blob/master/Documentation/coding-guidelines/coding-style.md
And: https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/
Javascript Styling Guidelines
- With dependency injections, (think AngularJS controllers) the expected pattern is to have the item name declared at the top and then use new lines after each dependency declaration.
Clean Code Article
Pull Request Checklist
General Items
- Code compiles
- Code has been developer-tested
- Code is tidy (indentation, line length, no commented-out code, no spelling mistakes, etc)
- Code adheres to the Coding Styles and Standards Guidelines (Found in the documentation folder)
- Exceptions have been used properly
- New functionality is appropriately logged as needed
- Unused using's have been removed
- Eliminated warnings
- Ensured NullReference Exceptions caught or handled appropriately
- Leftover stubs and test routines have been removed
- Hard-coded or development only things have been removed
- Considered performance and scalability
- Considered security, and potential exploits
- All resources (HTTP connections, DB connection, files, etc) properly released in all code exits (i.e. normal and exception)
- Corner cases and workarounds for known limitations of dependencies are well documented
- No new code is a repeat of existing functionality that can be safely reused
- Thread safety and possible deadlocks are considered and handled accordingly
- Method bodies are kept as close to 4 lines or less if possible
- Method names must be descriptive (reveal their intention aka what they do)
- Methods do one thing only
- Asynchronous Methods have the post-fix of "Async" appended to the end of their names.
Utopia Specific Checklist Items
- All code added to UtopiaSharedClasses is safe to expose to customers (No sensitive information)
- Libraries or projects that could become Libraries should be stored at the top level of the Utopia Repository
- Public API endpoints have documentation comments if needed
General
- .NET standard Coding Guidelines: https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/
- Clean Code Book with corresponding guidelines are found in the Utopia Repository under Documentation.
Code Reviewer's Checklist
- Types have been generalized where possible
- Parameterized types have been used appropriately
- Exceptions have been used appropriately
- Repetitive code has been factored out
- Frameworks have been used appropriately – methods have all been defined appropriately
- Classes have been designed to only have one purpose
- Views do not contain business logic
- Common errors have been checked for
- Potential threading issues have been eliminated where possible
- Any security concerns have been addressed
- Performance and Scalability was considered
- The functionality fits the current design/architecture
- The code does not use unjustifiable static methods/blocks
- The code complies to coding standards
- Logging used appropriately (proper logging level and details)
- Exception use is in compliance with proper methodology
- Code quality is excellent
Utopia Specific Checklist Items
- All code added to UtopiaSharedClasses is safe to expose to customers (No sensitive information)
- Libraries or projects that could become Libraries should be stored at the top level of the Utopia Repository
- Public API endpoints have documentation comments if needed
- Functionality should be exposed at the highest layer of the architecture as possible and only moved down when reuse becomes necessary. (i.e. CSV generation at the presentation layer, but could be moved into business logic if reuse becomes necessary)
ADA Compliance Checklist
This is not meant to be a comprehensive list but is hopefully a good starting place. Feel free to add.
To see the WCAG standards established by W3C go here
-
Form fields should have a visible label, not just a placeholder
-
Field formatting information should stay visible after beginning to edit
-
Test page text with Text Only setting up to 200%
-
Color contrast should meet WCAG standard
-
Don’t rely on color to convey meaning, provide another way for the information to be understood
-
All page content MUST be keyboard accessible
-
Confirm that the tabbing order makes sense for the user experience
- Ensure that the user won't get stuck in an infinite tabbing loop
-
Header tags should not be used for styling alone. They should add meaning to the page hierarchy. Add styling to get different text sizes and styling
-
Use provided HTML semantic tags whenever possible. This makes it much easier for screen readers
-
Avoid using small targets (i.e. be sure that the text associated with a checkbox selects that checkbox)
-
Not everyone can use drag and drop or similar components. Be sure to provide an alternative way to modify the information
-
Make sure all page actions are visible. (i.e. don’t rely on a mouse hover to show that an image is a carousel)
-
Page titles should go from specific to general information. They should help the user know what the page is about, not just what the website is.
-
Audio and visual content that conveys meaning must have a text alternative. This could be an alt tag description, closed captioning, a transcript, etc.
-
Media that has meaning that is already conveyed can have a blank alt tag
-
Look at content proximity, both for auditory content and visually. Related information should be close together. Those who need to zoom in may not be able to see a modal or submit button that is on another part of the page
-
Don’t use auto-advancing fields. They cause issues for accessibility
-
Use plain language and provide full versions of acronyms
For a more comprehensive checklist from WebAIM go here
SIGNiX
SIGNiX Documentation and API Links
Support Contacts at SIGNiX:
Heide Abbajay habbajay@signix.com - Support person
Hannah Detherow hdetherow@signix.com- role?
Joshua Curry jcurry@signix.com - VP of something, don’t want to bother unless no one responds.
API Docs:
Resend emails:
API Email Resend Ajax Call.docx
For In-Person signing, all you do is use a stripped-down GAL call and the TransactionRole changes based on the Signer’s position in the XML. Signer 1 = ‘1’, Signer 2 = ‘2’, etc.
<?xml version="1.0" encoding="utf-16"?><
<CustInfo>
<Sponsor>efilecabinet</
<Client>efilecabinet</Client>
<UserId>efilecabinet</UserId>
<Pswd>********</Pswd>
</CustInfo>
<Data>
<TransactionID>3e3750f5-a66e-
<TransactionRole>1</
<SkinID>Signix.Base</SkinID>
<Embedded>iframe</Embedded>
<ContainerOrigin>https://
</Data>
</GetAccessLinkRq>
Technologies
Http Client
you should use either long-lived clients and set PooledConnectionLifetime (.NET Core and .NET 5+) or short-lived clients created by IHttpClientFactory.
*see HttpClient guidelines for .NET - .NET | Microsoft Learn
How?
In the Startup
file (or Program.cs
file in cases, wherever you are doing dependency injection is where you want to do this), do
builer.Services.AddHttpClient();
This will allow you to dependency inject IHttpClientFactory
in other classes, which you can use to create short lived HttpClient
objects whose connections will be cleaned up immediately after disposal with the following code.
using HttpClient httpClient = HttpClientFactory.CreateClient();
Another way to do this is by dependency injecting a singeton HttpClient. I (Quinn) had trouble getting the IHttpClientFactory
to dependency inject in functions apps. I kept running into dependency issues with different nuget packages, but this approach worked great.
In your startup.cs add the following builder.Services.AddSingleton(() => new HttpClient(
new SocketsHttpHandler { PooledConnectionLifetime = TimeSpan.FromMinutes(2) }
));
Once you do this, you can add a HttpClient
as a parameter to any constructor of a class that is dependency injected.
The approach this way is different than the one above because you aren't creating short lived HttpClient
s, but instead, you have a singleton HttpClient
. This is fine because most functions are thread safe, but you won't want to dispose of the HttpClient
anywhere.
Why?
In the Atlantis Front-End we learned this the hard way. We were spinning up a new HttpClient
object every time a request was sent to Utopia or the Atlantis Back End (which happens for basically every request to the Atlantis Front End server). When we opted in all users to the new experience, we got a lot more traffic and starting seeing thousands of failed requests with the following error message:
An operation on a socket could not be performed because the system lacked sufficient buffer space or because a queue was full. (utopia.revverdocs.com:443) An operation on a socket could not be performed because the system lacked sufficient buffer space or because a queue was full.
After researching a bit, we learned that each HttpClient
object has it's own connection pool, and even when you dispose of the HttpClient
object, it's connection pool stays alive and keeps all connections in the pool alive for 2 minutes (this time is configurable though). While the connection is still alive, it blocks another connection from being created on the same port, and your server does have a limited number of ports, so if you have a bunch of connections blocking all your ports from being used, you start to get the error above because there are no ports available to send you web request out on.
Utopia
Windows File Encryption
Decryption
- download PSTools from: https://docs.microsoft.com/en-us/sysinternals/downloads/psexec
- This can be used to run commands as the SYSTEM user
- You need to do this to decrypt the database data files / elastic search data files
- Cmmand to decrypt folder and all contents as system user:
PsExec.exe -i -s cipher /d /s"fullPathToFolder"
(documentation for the cipher command can be found here
Open Source Software List
Correct as of 8/23/2021
Server-Side: ElasticSearch, Postgresql, iTextSharp - LGPL, MailKit, BouncyCastle, AutoMapper, DeviceId, dotLess.Core, FluentValidation, .Net 5, MimeTypes, NUglify, Chutzpah, Ninject, Serilog, Swashbuckle, SkiaSharp, OpenIddict, StackExchange.Redis, LigerShark.WebOptimizer
Client-Side: AngularJS, Angular-UI (various sub-libraries), Font-Awesome, Bootstrap, ngDialog, daterangepicker, Cytoscape, jasmine, jquery, less, lodash, moment.js, signalr, split.js
First Time Setup - Utopia (Work in Progress)
Step 1: Postgresql
- download and install the latest version of postgres from https://www.enterprisedb.com/downloads/postgres-postgresql-downloads
- use the password 'pass@word1' if you don't want to have to change config settings every time you work on the Utopia project
- pgAdmin should be installed with postgresql, and it is a useful to to have on hand to monitor and access you postgres db
- no need to install stack builder
After install is complete - Run the DbMigratorEF and update to latest migration
Apply the "DB InstanceSettings Local Config.sql" file to the local db - this is found in the top level folder inside the Utopia repo
Step 2: Install Elastic Search
ElasticSearch Installer In Rubex
ElasticSearch Direct Download
Step 3: Install Azure Storage Emulator
Step 4: Run the UtopiaBatchWorker to pull down local accounts
Utopia Articles of Permissions (2020)
Utopia Articles of Permissions
This file is to explain the over-arching permissions strategy
Node Permissions
-
Every node inherits it's permission set from it's parent by default.
-
a. A node's permission set consists of accumulating all permissions on and above the given node.
b. The permission set requires that the roles be unique. (One permission per role in the permission set collection)
c. In the case that more than one permission per role is found, (e.g. group has a permission on the cabinet and a different permission on the drawer) the closest permission is taken for evaluation.
-
Only member/personal roles can have the override/enforce permission.
-
The Override/Enforce permission, when checked on a member/personal role, results in all other permissions being ignored for evaluation.
a. If multiple permissions are found with override checked, the nearest permission is choosen for evaluation.
-
Pushdown is an action offered when a permission is added, updated, or removed.
a. When taken, it removes all permissions on descendants that have a matching role.
System Permissions
- These are permissions for a specific role to access certain system features. (e.g. workflow, manage users, recycle bin, etc.)
- A particular users' total system permission set consists of any system permissions assigned to their personal role, or any roles they are a member of.
Non-Inheritable (Only this item) Behavior
Expected behavior for various parent folder with inheritable permission and a sub folder w/ non-inheritance(Only this item) relationships.
Vocabulary:
Parent = Parent with inheritable permissions
Child = Child with NotInerhitable(Only this item) permission
RWD = Permissions (Read/Write/Delete)
Behaviors:
E = Edit/Rename Child
D = Delete Child
V = View Children of Child
C = Create folder or Upload File into Child
L = Delete children of Child
No Parent Permissions | Parent-R | Parent-RW | Parent-RWD | |
---|---|---|---|---|
Child-R | V | VC | VCL | |
Child-RW | E | EV | EVC | EVCL |
Child-RWD | ED | EDV | EDVC | EDVCL |
Utopia Architecture Notes (2020) Has Changed
Download link: Utopia Architecture Notes.docx
DataAccess Notes
- Contains DB entities
- Method Classes
- Used for uniform retrieval of data from the database that doesn't require knowledge of business rules
- Used by BusinessLogic to compous various, reusable IQueryables to get informationit needs for a given operation
- Used for updating in case of additional database specific work. i.e. When adding a DbNode, it sets the CreatedOn and ModifiedOn values prior to adding them to the DbContext
- The primary goals for the Method classes in DataAccess are to make Get, Add, Update, and Delete reusable and abstract so any change to the Database layer (i.e. going to NoSQL) will require far less work
- Contains common extension methods for any of the DB entities
- Contains any classes that are required to do optimized batch queries (i.e. Retrieving permissions by NodeID, although this could probably be converted to some form of IGrouping in the future)
BusinessLogic Notes
-
Contains all Business Logic
-
Split into three layers: BaseLogic, Logic, FacadeLogic
BaseLogic Layer
- Used for sharing reusable logic
- Getting permissions for nodes for NodeLogic operations
- Used for intercommunication between logics
- Think Validation operations
- These logics act as parent objects for their corresponding Logic layer counterparts. This allows logic that needs to be reused in both the Logic and Base Logic layers to be a part of that logic only.
- For example: A method in NodeBaseLogic is marked as private, enabling it's use by NodeLogic due to NodeLogic inheriting from NodeBaseLogic. This ensures that the method can only be used from these two classes.
- This layer is up for debate.
- We have also considered a Logic Components section that contains the reusable logic, as well as a Validation section that contains all the logic required for validation in a formal format (most cross-logic communication occurs due to validation requirements).
Logic Layer
- Primary layer containing most logic
- There is no cross-communication between the Logics
- Utilizes Base Logics for reusable logic
- Utilizes DataAccess Methods for DB interactions as much as possible
- Should avoid accessing the DbContext directly, where possible
FacadeLogic Layer
- Used primarily by External Node Providers
- A transparent layer to whatever wishes to support external Node Providers (Google Drive, OneDrive, etc.)
- Does no other logic than getting the correct provider for the given ID/Operation
- Bypassed by any operation that is not supported for external providers
- Currently everything except Node Operations, File Download Operations, and File Upload Operations bypasses this layer and goes directly to the Logic layer
- Used for sharing reusable logic
EventSystem Notes
- Lives in BusinessLogic
- Consists of 3 parts: Events, Listeners, EventManager
- Any call to the EventManager, regardless of location, will initialize the Manager and invoke all BusinessLogic level listeners. This allows for Audit Logging, EventTrigger Servicing, Notification Creation, and other "reactions" to system events to occur transparently
- Events are handled Asynchronously to allow original requests to process as quickly as possible while another thread handles all "reactions"
- Listeners can be hooked up from upper layers
- i.e. SignalR on the App Server
UtopiaSharedClass Notes
Security
File OCR Worker debugging (2021)
This is the instruction how to debug OCR worker.
a. If you no need to use FREngine
- In Program.cs comment row `FREngineOCRWorker.Initialize(Configuration);
- Put breakpoints
- Run File OCR Worker in Debug mode
b. If you need to use FREngine
- FREngine can't initialize correctly if you trying to run File OCR Worker in debug mode, so DO NOT PUT BREAKPOINTS AND DO NOT RUN IT IN DEBUG MODE. For debugging purposes you can print debug information in logs and analyze it.
Utopia Bundle Installer build instruction
- Build all components which should be included into installer
1a. If PrizmDoc should be included, PrizmInstaller project should be built as well. Do not forget to specify PrizmServer license key into the Strings resource of PrizmInstaller.
1b. If ElasticSearch should be included, UtopiaSearchServiceWrapper project should be built as well
NOTE: For build installer locally you need to make sure that each project that is going to be installed as a component, that in the appsettings.json both the "RunAsService" needs to be true and the ConnectionString needs to be updated/accurate to their DB (or Utopia)
- Open Utopia installer project and navigate to appsettings.json file
- Specify all components which should be included into installer in this configuration file. By default it contains configuration for including all Utopia componets, but it can be easily changed. If some component should be excluded from installer, it just should be removed from Components section in appsettings.json. This is the appsettings.json structure:
"BundleTargetDirectory": "[ProgramFilesFolder]eFileCabinet",- Default installation directory for bundle
"ProjectTargetDirectory": "%ProgramFiles%\\eFileCabinet", - Default installation directory for msi
"BundleName": "Utopia Bundle", - Bundle name
"BundleVersion": "1.0.0", - Bundle version
"ProjectName": "Utopia Solution", - Installer name (will be included into bundle)
"Components": [ - List of components
{
"Identifier": "ce279e3c-8c3e-469c-9454-6f4b9035eae8", - Unique component identifier (GUID), it is used by windows to detect if this component already installed.
"SourceDirectory": "..\\..\\pgsql", - Root directory with component's files
"ApplicationFolder": "eFileCabinetDatabaseService", - Target component directory in installation path
"ServiceName": "eFileCabinet Database Service", - Feature / Service name
"Required": true, - Required for installation
"IncludeIntoBundle" : true, - If true then msi will be included into the bundle
"AfterInstall": { - After install block
"DirectoryForCheck": "data", - If this directory DOESN'T exist, after install actions will be executed
"Actions": [ - After install actions
{
"File": "bin\\initdb.exe", - File to execute
"Arguments": "-D ../data -U postgres -A trust", - Execution arguments
"WaitForExit": true - Sync or async execution (in current example - sync),
"Local": true - if true then full installation path will be added to the file
}
]
},
"BeforeUninstall": { - Before Uninstall block
"Actions": [
{
"Local": false,
"File": "cmd.exe",
"Arguments": "/C \"net.exe stop ^\"eFileCabinet Database Service^\"\"",
"WaitForExit": true
},
{
"Local": false,
"File": "cmd.exe",
"Arguments": "/C \"sc.exe delete ^\"eFileCabinet Database Service^\"\"",
"WaitForExit": true
}
]
}
"DependsOn": [ - List of required for installation components. It WILL NOT be displayed in Feature select list
{
"SourceDirectory": "..\\..\\Prizm", - Root directory with component's files
"ApplicationFolder": "PrizmDoc", - Target component directory in installation
"AfterInstall": { - After install block
"DirectoryForCheck": "PrizmServer", - If this directory DOESN'T exist, after install actions will be executed
"Actions": [
{
"File": "PrizmInstaller.exe", - File to execute
"WaitForExit": false - Sync or async execution (in current example - async)
}
]
}
}
]
}
]
3a. If AccusoftPreviewer (PrizmDoc) should be included, do the following steps:
3a1. Put PrizmDoc Server Installer, PrizmDoc Client installer and PrizmInstaller.exe (result of 1a) into the one directory.
3a2. Rename PrizmDoc Server Installer from PrizmDocServer-<version>.exe to PrizmDocServer.exe and PrizmDoc Client installer from PrizmDocClient-<version>.exe to PrizmDocClient.exe
3b. If ElasticSearch should be included, do the following steps:
3b1. Download OpenJDK8 (https://github.com/AdoptOpenJDK/openjdk8-binaries/releases/download/jdk8u292-b10/OpenJDK8U-jdk_x64_windows_hotspot_8u292b10.zip ) and elasticsearch 6.* (https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.8.11.zip )
3b2. Unzip elasticsearch into the new folder
3b3. Unzip java into the folder from 3b2
3b4. Rename jdk8u292-b10 folder to java.
Result of 3b1 - 3b4 should be like on the screenshot below
4. Build project (It can takes more than 10 minutes). During the build installer with name <BundleName>.exe will be created. (This project can't be run, only build action is required)
Local build Issues
Missing assembly: System.Drawing
- The folder that this assembly sits in is mega hidden. The only way to access it is by entering the run tool (Windows + R) and then type
C:\Windows\assembly\GAC_MSIL
- Check this repository. You're looking for System, System.Core, System.Drawing, and System.Windows.Forms
- Add any missing folders from here
Azure Active Directory SAML Configuration (2020)
- In Azure search for "Enterprise applications"
- On "Enterprise applications" click "New application". Then click "Non-gallery application"
- Put whatever you want to the name field (I named it "TestSaml") and press "Add"
- On your app page select "Single sign-on" and then select "SAML"
- You should see SAML settings and configurations. You will need "Certificate" (base64), "Login URL (Azure)" and "Azure AD Identifier"
- Go to Rubex -> Hamburger menu -> Admin -> Settings -> Single Sign-On Settings -> Create Saml Configuration.
Name: Whatever you like
Issuer: Copy contents of "Azure AD Identifier"
Entity ID: Whatever valid URL you like
Saml Endpoint: "Login URL (Azure)"
Certificate: Load "Certificate" file
- Click Create/Update. You will need "Login URL (Rubex)"
THIS URL SHOULD BE HTTPS!!! Otherwise, it will not work with Azure
- Go back to Azure app settings.
Identifier (Entity ID): Put the same Entity ID as in Rubex
Reply URL: Copy "Login URL (Rubex)"
Save everything. You can also press the Test button to test auth from Identity Provider
- To add users to Active Directory search for "Users" in top search bar.
- To add groups to Active Directory search for "Groups" in top search bar. Set type as "Security" and add some users during creation.
- To add users to SAML application go back to the Enterprise application, select users and groups and add existing AD users
- To import groups select "Single Sign-on" -> "User attributes & claims"
- Then click "add a group claim", check "Customize the name...", Name: "groups" or something else. The namespace should be empty. Source attribute needs to be checked for different values, because ID returns... ID! Save everything
- Put the same name ("groups") to Rubex saml settings
OneLogin SAML SSO Configuration
- Create developers OneLogin Account.
- After the registration go to Applications page and push Add App button.
- In the search field print "SAML" and select SAML Test Connector (Advanced).
- Save application.
- Navigate to SSO tab. There are three URLs and certificate on this page. We need two of these URLs (Issuer URL and SAML 2.0 Endpoint (HTTP)) and certificate.
-
Open Rubex on another tab (or browser) and navigate to SAML configuration (Admin -> Settings -> Single Sign-On Settings).
-
Create new SAML configuration.
-
Fill Issuer field with value from OneLogin Issuer URL, Saml Endpoint with value from SAML 2.0 Endpoint (HTTP), Entity ID with any url. Aslo specify SAML Attribute Name for Groups (attribute where all user groups will be listed, usually Group) and upload OneLogin certificate downloaded on step 5
-
Save configuration and open it again. Save Login URL from the bottom of this page.
-
Back to OneLogin. Navigate to Configuration tab.
-
Fill Audience (EntityID) with the same URL like in Entity ID Rubex SAML Configuration, Recipient, ACS (Consumer) URL and Login URL with Login URL from Rubex SAML Configuration. Save configuration.
-
Navigate to Parameters tab and add Group attribute (Do not forget to select Include in SAML Assertion)
.
Push Save button. On the next window select default value for this attribute (It can be any user attribute (default or custom)) and save it again. -
Save all configuration again.
Okta SAML SSO Configuration
Setting up Okta
- Go to the Admin Dashboard and create an app integration.
- Select SAML 2.0
- Have the fields match as to what is shown in the below screenshots for the Configure SAML section
- Keep in mind that the Single-sign on URL will be dependent on the environment you're setting this up for, and the ID at the end will be dependent on your Revver SAML Config (once the config is created in Revver, edit it and the URL will contain the ID)
- The SAML Issuer Id needs to begin with http://www.okta.com/ but anything after that is up to you. It does need something and it needs to be unique, but it is something that you can make up if you'd like
- Once it's been configured and the app is up and running, you'll need to get the SAML signing certificate
Configuring SAML in Revver
- Configure the name
- The Issuer is the Issuer Id configured above
- You can find this in Okta by going to going to the Sign On tab => Scroll to the Settings section => Click More Details => Issuer
- The Entity ID will match the Audience Restriction area in Okta's app by going to General => SAML Settings => Audience Restriction
- Be careful when using the SAML Endpoint as Okta has some misleading areas to find this
- This can be found in Sign On => Settings => More Details => Sign on URL
- Leave the rest blank (or configure as needed)
- For the Signature, Choose File => Select the .cer file (formerly a .cert file) that was downloaded (see the above Setting Up Okta section)
- Click save
Here's an example Config:
Entity Framework Code First
Difference between code first and DB first
In code first approach we have
- entity to tables mapping in the C# code instead of .edmx XML file
- use a general connection string. We don't need to specify configuration files in the connection string
- We create all entities and mapping manually instead of code generation in DB first
- EF can update DB with using our mapping
Entities and mapping
We create entities as general C# objects. Most of them are the same as
Mapping will bind entities to the DB tables. We can apply mapping in two ways:
- Use code annotations attributes
- Use fluent API with DbModelBuilder
- We can combine these two approaches in the same context. (we apply this approach in the Utopia)
- Use separately classes with mapping for each entity. (This approach we used in workflows.)
mapping example:
Mapping by attributes
public partial class DbNode
{
[Key]
public long Id { get; set; }
[Required]
[StringLength(255)]
public string Name { get; set; }
Mapping by modelBuilder
public partial class UtopiaDB : DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// map foreign key.One to many
modelBuilder.Entity<DbNode>()
.HasMany(e => e.DbEmailQueueAttachmentNodes)
.WithRequired(e => e.DbNode)
.HasForeignKey(e => e.NodeID)
.WillCascadeOnDelete(false);
// map foreign key. many to many
modelBuilder.Entity<DbSearchCriteria>()
.HasMany(e => e.DbTriggers)
.WithMany(e => e.DbSearchCriterias)
.Map(m => m.ToTable("DbTriggerToSearchCriteria")
.MapLeftKey("SearchCriteriaId")
.MapRightKey("TriggerId"));
// map complex primary key
modelBuilder.Entity<DbTriggerInfoNodes>()
.HasKey(e => new {e.TriggerID, e.NodeInfoType});
}
}
Mapping by mapping class (used in WF)
public class DbWorkflowMap : EntityTypeConfiguration<Workflow>
{
public DbWorkflowMap(string tablePrefix)
{
ToTable(tablePrefix + "DbWorkflows");
HasKey(t => t.Id);
Property(t => t.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
HasMany(t => t.Owners).WithMany().Map(a => a.MapLeftKey("WorkflowID")
.MapRightKey("UserID")
.ToTable(tablePrefix + "DbWorkflowOwners"));
Migration
To update the DB structure we use migration.
- Migration is a C# class that contains updating instruction.
- EF can generate migrations automatically
How to change structure
- Add changes to entities and mapping if it needed
- Create a migration for this changes. To make it automatically create a migration, run this command in the Package Manager Console:
Add-Migration "MigrationNameHere" -ProjectName DataAccess -ConnectionString "data source=(localdb)\MSSQLLocalDB;initial catalog=UtopiaDB;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework" -ConnectionProviderName System.Data.SqlClient -ConfigurationTypeName UtopiaDBMigrationConfiguration
- After this command EF will generate C# class for this migration. Please check it
public partial class InitialMigration : DbMigration
{
public override void Up()
{
//Some instructions
}
public override void Down()
{
}
}
- To apply migration to the DB you can run next command:
Update DB to the last state
update-database -verbose -ProjectName DataAccess -ConnectionString "data source=(localdb)\MSSQLLocalDB;initial catalog=UtopiaDB;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework" -ConfigurationTypeName UtopiaDbMigrationConfiguration -ConnectionProviderName System.Data.SqlClient
Update/Downgrade db to a specific migration.
update-database -TargetMigration:<Insert migration name> -verbose -ProjectName DataAccess -ConnectionString "data source=(localdb)\MSSQLLocalDB;initial catalog=UtopiaDB;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework" -ConfigurationTypeName UtopiaDbMigrationConfiguration -ConnectionProviderName System.Data.SqlClient
Update for updating remote DB's/connections that require authentication:
update-database -verbose -ProjectName DataAccess -ConnectionString "data source={databaseserveraddress};User={databaseUsername};password={password};initial catalog={schemaName};integrated security=False;MultipleActiveResultSets=True;App=EntityFramework" -ConfigurationTypeName UtopiaDbMigrationConfiguration -ConnectionProviderName System.Data.SqlClient
- Applied migrations are stored in
__MigrationHistory
table
PostgreSQL process
There are several things that are different during PostgreSQL Code-First Migration process:
- Update DB to the last state
update-database -verbose -ProjectName DataAccess -ConnectionString "Host=localhost;Database=UtopiaDB;Integrated Security=False;Username=postgres;Password=pass@word1;Port=5432" -ConfigurationTypeName UtopiaDbMigrationConfiguration -ConnectionProviderName Npgsql
-
If Package Manager Console cannot update database, DbMigratorEF project can be used. Pay attention to constants and main method before running it, main methods are UpdateDatabase(config) and ScaffoldNewMigration(config)
-
During master merging into feature/OnPremiseMaster new migrations should be deleted and rescafolded. If "dbo" scheme appears after migration, that means one or more migrations are not deleted.
Code First Training Video
https://youtu.be/goRtW-1c_BY
Entity Framework Optimizations
Entity framework does not have great performance when dealing with large batches of data. We've compiled this list as a reference so that our batch operations can be efficient as possible.
Please Read these Articles
https://weblog.west-wind.com/posts/2014/dec/21/gotcha-entity-framework-gets-slow-in-long-iteration-loops
https://weblog.west-wind.com/posts/2013/Dec/22/Entity-Framework-and-slow-bulk-INSERTs
Disable Auto Detecting Changes
see https://docs.microsoft.com/en-us/ef/ef6/saving/change-tracking/auto-detect-changes
using (var context = new BloggingContext())
{
try
{
context.Configuration.AutoDetectChangesEnabled = false;
// Make many calls in a loop
foreach (var blog in aLotOfBlogs)
{
context.Blogs.Add(blog);
}
}
finally
{
// make sure you re enable AutoDetectChangesEnabled before calling SaveChanges
context.Configuration.AutoDetectChangesEnabled = true;
await context.SaveChangesAsync();
}
}
Bloated DbContext
With Entity Framework, you have a dbContext object that tracks all the entities you've read from the database and changes that have been made to them. If it starts to track too many entities you can start getting pretty slow performance.
There a several thanks that can be done to address this issue.
.AsNoTracking()
List<DbNodes> childNodes = UtopiaDB.DbNodes.Where(i => i.ParentID = 1).AsNoTracking().ToListAsync();
When you use .AsNoTracking() the entities that get returned will not be tracked by the dbContext. You should use this when you are querying data from the db that is read only.
Re-Create DbContext Object
The easiest way to get past a bloated dbContext is to create a new dbContext object.
This is difficult in our Utopia solution because create one dbContext object per session, so unless a new session is created, a new dbContext object cannot be created.
To address this we have added code to to detach all entities from the dbContext
UtopiaDB.DetachEntitiesFromUtopiaDB();
The intent behind this code was to have the same effect as creating a new DbContext object.
Smaller Batches
Typically we've seen better performance when we process things in smaller batches (500 items or less), call 'SaveChangesAsync()', then detach all entities from the DbContext object, and process another small batch.
Adding a new Email Type
Steps required to add a new email type
- Add the new email type to the EmailEnum in UtopiaSharedClasses
- Add the new email template inside of UtopiaSharedResources
You must add both an efilecabinet and a SecureDrawer version of name format:
xx_eFileCabinet.html
xx_SecureDrawer.html - Change VS property "Copy to Output Directory" to "Copy Always" on those html files
- The Hub must be published and any partners must have their own templates added
Utopia External Login Instructions and Options
Utopia External Login Instructions and Options
This file is to explain how to create an external login page and the options available
External Login Instructions
- Create an iframe with the src set to "~/#/extLogin/" (replace ~ with host site)
- Examples:
<iframe src='https://app.securedrawer.com/#/extLogin/'/> <iframe src='https://express.efilecabinet.net/#/extLogin/'/>
External Login Options and Notes
- Open a New Tab on Successful Login - this is done by setting the src to "~/#/extLoginNewTab/". a. This will authorize the user in a new tab and clear out their login details after success b. This will allow websites to embed a small login snippet and not a full page iframe. c. Minimum height and width of the iframe is: height="305px" width="250px"
- Redirect to Specific Logcation After Login - This is accomplished by appending the desired location to the src. a. Redirect Instructions: 1. Navigate to the desired redirect location inside the system. 2. Copy the segment of the URL that appears after the hash '#' 3. Append that segment to the end of the src URL "/#/home/state/data/node/490025/1375574/details/1375574" - a location in my account b. I now copy "/home/state/data/node/490025/1375574/details/1375574" c. and append it the src URL "https://~/#/home/state/data/node/490025/1375574/details/1375574 " d. Now anyone logging in through that iframe will be redirected to the navigated location automatically if they have access to it.
Test Against Production Read Replica
To follow our security policy YOU MUST HAVE TWO OTHER DEVELOPERS OBSERVING when you access production information
Be sure to step over the listed breakpoints to ensure we don't send notifications to users in production
Note: The snapshot of production is likely from a previous date. Ensure that your branches state will work with where production was at.
- If remote, connect to the VPN
- Delete the conf.json file from C:\ProgramData\EFC\Configuration
- Use the DbConnectionConfigurationData string from Prod DB Read Replica found in the Shared-Development section in LastPass to update the DbConnectionConfigurationData string in Utopia's appsettings.json.
- Add a breakpoint to step over
await ValidatePasswordAsync(password, dbUser);
in the method ValidateUsernameAndPasswordAsync in BusinessLogic/Services/AuthenticationService.cs - Add
loginRequirementsStatus.UserSettingMFARequirementMet = true;
below where the loginRequirementsStatus gets set in the method GetUserLoginRequirementsStatusAsync in BusinessLogic/Services/AuthenticationService.cs - And add a breakpoint to step over: PopulateUserSettingLoginRequirements, PopulateSecurityPolicyStatuses, await PopulateRolesFailingOtherRequirementsAsync, InvalidateGroupRolesWhereUserRoleIsFailing in the method GetUserLoginRequirementsStatusAsync in BusinessLogic/Services/AuthenticationService.cs
How to run local Utopia over LAN/connect from outside network
Why
At times it may be helpful to connect to your local instance of Utopia from other devices to be able to debug/test:
- Mobile device
- Apply garbage
- SalesForce
- Other integrations
To name a few. Also, it just feels cool.
How to setup Utopia over LAN
The key here is to set up IIS properly and then open whatever ports are needed on your firewall.
- Lets first get your local IP
- Run command prompt
- Type ipconfig
- Copy and save your IPv4 Address
-
- Inside of Visual Studios, click on the IIS Express dropdown arrow and select Utopia Debug Properties
- Scroll down until you see App URL. Replace localhost with the saved IPv4 Address
-
- Close the window
- Find the .vs hidden folder of the Utopia solution and then go into Utopia\Config and open applicationhost.config
- For me it's C:\src\Utopia\Utopia\.vs\Utopia\config\applicationhost.config
- Inside of applicationhost.config, find where it sets up it's bindings
- Usually around line 162
- Searching for binding and it should go straight to it
- Duplicate the two lines that bind the two ports to localhost. Replace localhost with your saved IPv4 Address on those duplicated lines.
- Next, open up the ports inside of your windows firewall
- You will need to open up port 44334 for both UDP and TCP
- Actually not sure if you need both but I did just in case
- In some instances you may need to open 57584 as well
- I had to to be able to connect from the company mac via the desktop client (it was yelling at the not trusted certificate)
- Allow the connection
- Have Domain, Private, and Public all checked
- Give it a meaningful name
-
- Actually not sure if you need both but I did just in case
- You will need to open up port 44334 for both UDP and TCP
- Close out Visual Studio completely
- Open Visual Studio as administrator
-
- Finally, open Utopia and run it with IIS Express
Note:
- If you get an error that looks like this
-
- Then you need to shut down Visual Studio completely and relaunch it as administrator
-
How to connect from outside network
This one is actually really simple. All you need to do is do some port forwarding. I'm not going to get into how to do this since each router is unique (basics is to log into the router and go to advanced).
Note:
- To connect, make sure the device you're connecting from is NOT on the local network
- You'll need your external IP
- Replace the internal IP with the external one on the connecting device
How to create a new user license type
- All changes are made in the Utopia solution in the Utopia git repository
- See this PR for the Compliance License for a previously implemented example
C#
- Add a value to the
UserLicenseEnum
enum - Add a value to
AllowedNodeTypesByUserLicenseType
dictionary (if applicable)
- Instantiate a new
UserLicense
in theUserLicenses
static method
- Add a value to the
AccountFeatureEnum
enum - Add a value to the
UserLicenseAccountFeatures
array. The licenses in the UI will display in this order. - Add a value to the
MeteredAccountFeatures
array (assuming that the license will be metered) - Add a value to these other arrays (if applicable)
UserLicenseAssignmentFallbackOrder
RoleLicensesWithConcurrentUserSupport
AdvancedOCRAccountFeatureTypes
MeteredOCRAccountFeatureTypes
UsageFeatureTypes
- Add a resource value for the title of the license
- The name must be
AccountFeatureEnum_{name-of-account-feature-enum}
, e.g.AccountFeatureEnum_ComplianceUserLicense
- The name must be
- In the
GetAccountReportAsync
method, update the assignment to theuserCountLookup
dictionary to also add the counts of the new license type
- In the
GetUsageAsync
method, add a line to set the count of the new license
- In the
GetUserLicenseCountLookupAsync
method, add a line to set the count of the new license
JavaScript
- In the
determineFeatureUsageMessage
function, add aswitch case
for the new license
- In the
getUserRoleOnAccount
function, add a block that returns a role for the new license if one exists
- In the
getPermissionPresets
function, add a block that sets the permission presets of the new license
- In the
isUserLicenseType
function, add the new license to theOR
clause - Add a function called
is{name-of-license-type}UserLicenseType
Concurrent Licenses
This feature is primarily used by Caselle
- The concurrent license count is actually based off the value added to the Full User License feature.
- For example, an account with 4 concurrent licenses will have the Concurrent License feature applied to the account with the value as null, and the Full User License feature with the value of 4.
- An account with the concurrent license feature can add more full users to the account than the feature value, but they will only be able to have 4 of those full users logged in at a time.
- Currently the account can only have the Full User License feature with the Concurrent License feature. If there comes a time that we'd like to allow different user types the code would need to be adjusted.
- A single user is allowed to log into multiple applications as one concurrent license user.
- The external applications that should be part of concurrent licensing need to have their application IDs added to the Azure configuration setting Utopia:Settings:ExternalClientApplicationIds
- If we ever decide to enforce concurrent licensing for the mobile app or other internal apps those will also need to be added in the code.
- The bulk of the logic for concurrent licensing is in AuthenticationService.cs. See the method GetRolesFailingConcurrentLicensingAsync.
Utopia Architecture
eFC Enterprise Architecture
Introduction
eFileCabinet has 3 Legacy platforms and 1 flagship platform that all legacy platforms are migrating to.
Reference: Utopia Architecture.pptx
Flagship
- Rubex (Codename Utopia)
Legacy Platforms
- eFileCabinet Desktop (Codename efc)
- Customers Self-host
- eFileCabinet Online (Codename Tandoori)
- Sass only
*No longer sold
- Sass only
- SecureDrawer (Codename SD)
- Sass only
*No longer sold separately
- Sass only
Supporting Systems
The following are systems utilized to support selling, supporting, and provisioning these platforms.
- Salesforce
- CRM for Sales and Support
- Used for sales and support of all platforms
- Zuora
- Used for billing customers
- Tightly integrated with Salesforce
- Hub (efc-maintained and operated)
- Used for provisioning accounts in all 4 platforms
- Used for serving Eulas to customers
- Used for controlling partner branding/labeling
- Marketplace
- Used for direct customer purchases
- Primarily used at Trade shows.
- Designed to provide a self-provisioning portal for customers.
Legacy Supporting Systems
The following are system previously used for selling, supporting, and provisioning
- Bontbok
- Utilized for controlling user access within the Hub, BontBok, and BontBok360 systems.
- Utilized to serve eFileCabinet Desktop with updates.
- Bontbok 360
- Serviced self-provisioning pages for customers
- Handled billing for eFileCabinet Online customers
Enterprise Architecture Diagram
Windows Desktop Client
Utopia Windows Desktop Client Update Creation Process
To Create an update to the Utopia Windows Desktop Client, you will do the following steps:
- Right-click the UtopiaWindowsDesktopClient project in Visual Studio and select Properties.
- Under the Application tab on the left side, click the "Assembly Information" button.
- Change both the Assembly version and the File version. (Yes, you must do both!)
- Click Ok, Save All.
- Select the UtopiaWindowsDesktopClientSetup and go to the properties window.
- Change the "Version" property to match the version set in Assembly Information.
- Save All, this will prompt you to automatically change the Product Code, Accept this. (We want it to change the Product Code. NEVER Change the Upgrade Code)
- To create a new exe:
- Clean and rebuild the solution in Debug
- Switch to Release mode
- Right click UtopiaWindowsDesktopClientSetup and Rebuild or Build
- Take the resulting "RubexInstaller.exe", found in UtopiaClientApplications\UtopiaWindowsDesktopClient\UtopiaWindowsDesktopClientSetup\Release within your local repo, and copy it to the Utopia Web Project's ClientApplicationInstallers/Windows folder. (Replacing the existing installer)
- Edit the WindowsClientVersion.json file in the given folder, change the Version property to the correct value.
Congratulations, You've updated the Windows Desktop Client!
- Note: You may also have to update the file versions in the other projects if they change. (i.e. UtopiaWindowsDesktopClientShared)
Update CefSharp to 64 bit (when we want to do it)
When updating the build of this application, you must change the version number in the Assembly Information of the UtopiaDesktopClientApplication AND the UtopiaWindowsDesktopClientSetup version.
Most of this should build and run out of the box. However, there are some CefSharp caveats,
first and foremost, CefSharp cares about x86 vs x64. Everything is currently targeting x86, but if and when the day comes that we do a x64 version, here are some of the changes needed (May want to consider making x86 and x64 versions with a shared project, same with installer):
- Change the targeting to x64 in the configuration manager.
- You may have to change the references in the UtopiaWindowsDesktopClient project to target the x64 versions of the cefsharp dlls (CefSharp, CefSharp.Core, CefSharp.Wpf)
- The following files directly referenced in the setup project will need to be pointed at the x64 versions:
a. CefSharp.BrowserSubprocess.Core.dll
b. CefSharp.BrowserSubprocess.exe
c. cef.pak
d. cef_100_percent.pak
e. cef_200_percent.pak
f. cef_extensions.pak
g. chrome_elf.dll
h. d3dcompiler_47.dll
i. icudtl.dat
j. libcef.dll
k. libEGL.dll
l. libGLESv2.dll
m. natives_blob.bin
n. snapshot_blob.bin
o. v8_context_snapshot.bin
- use their current reference paths as a starting location, then change with the corresponding x64 paths.
--------------- IF YOU UPDATE CEFSHARP-----------------
Update the above files to point at the new version's file paths.
Client Application Update Process
Code Scanning
Resources
- Code Scan Pipeline: https://dev.azure.com/eFileCabinet/Utopia/_apps/hub/ms.vss-ciworkflow.build-ci-hub?_a=edit-build-definition&id=132&view=Tab_Tasks
- Migrating from packages.config: https://learn.microsoft.com/en-us/nuget/consume-packages/migrate-packages-config-to-package-reference#migration-steps
Background
We wanted to do a code scan of the Revver Desktop App, but after some research and some trial and error, we found that this was going to be more difficult than anticipated.
In order to be able to used ADO advanced security to code scan, we needed to build the app in and ADO pipeline. There are two issues with this. 1) you can't build a .vsproj project (Visual Studio Installer Project) in ADO pipelines (well, we probably could if we we had our own build machines), and 2) our projects store nuget packages in a packages.config file and the ADO pipelines have issues restoring nuget packages when they are configured this way.
We attempted migrating from the packages.config to package references, and this was successful, however, it broke the installer project. We did spend several hours trying to see if we could reconfigure things in the installer project so that when you built the installer, things would work, but did not want to spend more effort trying to get this to work, so eventually gave up on this.
In the end, a pipeline was created (referenced at the top of this page), but it cannot currently be used with the master branch. In order to do a code scan you need to branch off of master, migrate the packages.config to package references, and run the pipeline on that branch. Keep in mind this will not scan the installers, just the build projects.
Doing a code scan
- Create a branch of master (or the branch you want to create a new update installer off of)
- Migrate from packages.config to package references
- you can use the reference at the top of this page for instructions on how to do this (but long story short, you right click the packages.config file and select Migrate packages.config to PackageReference...)
- Commit the changes to your branch and push it to ADO
- Run the 'Revver Windows Desktop App Code Scan' build pipeline on your branch
How can we automate this in the future?
I think the best way to do this would be to build the installer using wixsharp, rather than a visual studio installer project.
How To Update CefSharp Version
This update process may not work for future updates to CefSharp. The next version of CefSharp starts using some different libraries (chromiumembeddedframework instead of cef.redist.x86). Knowing these steps will likely still be important though because we will still likely need to update the setup / installer project
- Update the version of CefSharp.Wpf to the desired version
- Attempt to rebuild the UtopiaWindowsDesktopClient (Release | x86), you should get build errors in the output console indicating that it couldn't find files specific to the previous version of CefSharp.
- example error
- ERROR: Unable to find source file 'C:\src\UtopiaClientApplications\UtopiaWindowsDesktopClient\packages\cef.redist.x86.109.1.11\CEF\locales\ru.pak' for file 'ru.pak', located in '[TARGETDIR]\locales', the file may be absent or locked.
- You may also get build errors you need to resolve because CefSharp updates are not always backwards compatible.
- example error
- In the UtopiaWindowsDesktopClient project, double click the first file (af.pak currently) to open up a view that looks like the following screen shot
-
Delete all the files that are currently in the 'locales' folder.
- Right click the 'locales' folder on the left, and in the dropdown select 'Add' -> 'File', and add all the files from 'C:\src\UtopiaClientApplications\UtopiaWindowsDesktopClient\packages\cef.redist.x86.{UPDATED_TO_VERSION}\CEF\locales'
- Now select the 'Application Folder' folder on the left.
- Delete any files that start with the following paths (be vary careful when you do this so you don't accidentally delete a file you weren't supposed to)
- C:\src\UtopiaClientApplications\UtopiaWindowsDesktopClient\packages\CefSharp.Common.109.1.110\CefSharp\x86\
- 'C:\src\UtopiaClientApplications\UtopiaWindowsDesktopClient\packages\cef.redist.x86.109.1.11\CEF\
- you can reference the errors in the output console when building to see exactly what files it can't find and need to be deleted
- they may also be underlined in blue
- Right click 'Application Folder' on the left, and in the dropdown select 'Add' => 'File', and all the files from 'C:\src\UtopiaClientApplications\UtopiaWindowsDesktopClient\packages\cef.redist.x86.{UPDATED_TO_VERSION}\CEF' except for the following
- Right click 'Application Folder' on the left, and in the dropdown select 'Add' => 'File', and all the files from 'C:\src\UtopiaClientApplications\UtopiaWindowsDesktopClient\packages\CefSharp.Common.{UPDATED_TO_VERSION}\CefSharp\x86'
- You may want to make sure that you now don't have any duplicate files in 'Application Folder' or any files that you missed deleting that referenced the old CefSharp version.
- You should now be able to build the installers per ususal.
Archived
Azure Arc Citus Deployment
How to deploy Azure Arc
Basicly, this guide provides almost all things required for deployment arc in EKS. There are some tips about this cluster creation
-
Variables
TF_VAR_client_id: everywhere in description it is named as "Principal name" and if you will see the response of principal creation, it contains "name" field
But in fact in this variable you need to specify appId -
terraform apply
When I did that, this step was failed on deploying windows server VM with issue "file is locked". To avoid this you need to add an additional flag to the command. Result is:terraform apply --auto-approve --lock=false
How to create citus cluster and connect to it
- Connect via RDP to the machine with arc and open shell.
- Login to azdata:
azdata login --namespace $env:ARC_DC_NAME
2.1 It'll output a url with port number defined, this is what you'll use in step 4 for the Controller URL. - Create postgreSQL cluster:
azdata arc postgres server create -n postgres01 --workers 2
. - Open Azure Data Studio and expand the Connections pane and expand the Azure Arc Controllers are and Connect Controller.
4.1. If you receive an error: Could not connect to controller https://x.x.x.x:30080 . Microsoft Privacy statement and Azure Data CLI license terms have not been accepted. Execute the command: Azure Data CLI: Accept EULA to accept EULA to enable the features that requires Azure Data CLI. executeazdata login --namespace $env:ARC_DC_NAME --accept-eula ACCEPT_EULA
and restart Azure Data Studio - Expand Azure Arc Controllers -> [Your Arc Controller] and select [Your PostgreSQL cluster].
- Click on Reset Password button and specify new password for your cluster.
- You can connect to your cluster via PgAdmin or any other app
How to create distributed database
-
Create new database
-
Add citus extension
-
Add worker nodes
SELECT * from master_add_node('[worker_address]', 5432);
-
Execute InitialMigration.sql to create db schema on master node
- InitialMigration.sql can be found here
-
Execute
SELECT * FROM run_command_on_workers($cmd$ [content of InitialMigration.sql] $cmd$);
to create db schema on worker nodes. (Citus doesn't propagate CREATE command) -
Run the following command on the master node
SELECT * FROM run_command_on_workers($cmd$
CREATE SCHEMA IF NOT EXISTS "workflow";
CREATE SCHEMA IF NOT EXISTS "public";
CREATE EXTENSION IF NOT EXISTS "uuid-ossp" SCHEMA public
$cmd$);
- Run the following command on the master node
alter table public."DbAccessLinks" drop constraint "FK_DbAccounts";
alter table public."DbAccountFeatures" drop constraint "FK_DbAccounts";
alter table public."DbAccountSettings" drop constraint "FK_DbAccounts";
alter table public."DbAccountSettings" drop constraint "FK_DbEmailSettings";
alter table public."DbAccounts" drop constraint "FK_BrandingID";
alter table public."DbAuditLogs" drop constraint "FK_DbAccounts";
alter table public."DbAuditLogsToNodeDetails" drop constraint "FK_DbAccounts";
alter table public."DbAuditLogsToNodes" drop constraint "FK_DbAccounts";
alter table public."DbAuditLogsToRoleDetails" drop constraint "FK_DbAccounts";
alter table public."DbAuditLogsToRoles" drop constraint "FK_DbAccounts";
alter table public."DbDocumentRequests" drop constraint "FK_DbAccounts";
alter table public."DbESignatureTransactions" drop constraint "FK_DbAccount";
alter table public."DbEmailImportMappings" drop constraint "FK_AccountID";
alter table public."DbEmailImportMappings" drop constraint "FK_EmailSettingID";
alter table public."DbEmailQueue" drop constraint fk_accounts;
alter table public."DbEmailQueue" drop constraint fk_emailsettings;
alter table public."DbEmailSettingToAccounts" drop constraint fk_account;
alter table public."DbEmailSettingToAccounts" drop constraint fk_emailsetting;
alter table public."DbEmailSettingToUsers" drop constraint fk_emailsetting;
alter table public."DbEmailTemplateToPartner" drop constraint "FK_DbEmailTemplate";
alter table public."DbFileInfoes" drop constraint "FK_AccountID";
alter table public."DbFileQueue" drop constraint "FK_Account";
alter table public."DbNodeAnnotations" drop constraint fk_account;
alter table public."DbNodeClosures" drop constraint "fk_accountID";
alter table public."DbAccessLinksToDocumentRequests" drop constraint "FK_public.DbAccessLinksToDocumentRequests_public.DbAccessLinks_";
alter table public."DbAccessLinksToNodeAndTriggers" drop constraint "FK_public.DbAccessLinksToNodeAndTriggers_public.DbAccessLinks_A";
alter table public."DbAccessLinks" drop constraint "FK_public.DbAccessLinks_public.DbRoles_RoleID_AccountID";
alter table public."DbAccessLinksToDocumentRequests" drop constraint "FK_public.DbAccessLinksToDocumentRequests_public.DbDocumentRequ";
alter table public."DbAccountSettings" drop constraint "FK_public.DbAccountSettings_public.DbSecurityPolicies_DefaultGu";
alter table public."DbAccountSettings" drop constraint "FK_public.DbAccountSettings_public.DbSecurityPolicies_DefaultUs";
alter table public."DbEmailImportMappings" drop constraint "FK_public.DbEmailImportMappings_public.DbNodes_NodeID_AccountID";
alter table public."DbAccessLinksToNodeAndTriggers" drop constraint "FK_public.DbAccessLinksToNodeAndTriggers_public.DbNodes_NodeID_";
alter table public."DbAuditLogsToNodes" drop constraint "FK_public.DbAuditLogsToNodes_public.DbNodes_NodeID_AccountID";
alter table public."DbNodeShares" drop constraint fk_account;
alter table public."DbNodeToFileInfoes" drop constraint "FK_DbAccounts";
alter table public."DbNodes" drop constraint fk_account;
alter table public."DbNotifications" drop constraint "FK_DbAccounts";
alter table public."DbPartners" drop constraint "FK_BrandingID";
alter table public."DbPermissions" drop constraint fk_account;
alter table public."DbPortfolioToNodes" drop constraint "FK_DbPortfolios";
alter table public."DbPortfolioToUsers" drop constraint "FK_DbPortfolios";
alter table public."DbPresetValues" drop constraint "FK_Account";
alter table public."DbProfileItems" drop constraint fk_account;
alter table public."DbProfiles" drop constraint fk_account;
alter table public."DbRetentionChangeReason" drop constraint "FK_DbAccount";
alter table public."DbRoles" drop constraint "FK_DbAccounts";
alter table public."DbSamlConfigurations" drop constraint "FK_DbAccounts";
alter table public."DbSamlResponses" drop constraint "FK_DbAccounts";
alter table public."DbSearchCriteria" drop constraint "fk_parentUserSearchCriteria";
alter table public."DbSecurityPolicies" drop constraint "FK_DbAccounts";
alter table public."DbSfLinks" drop constraint "FK_DbAccounts";
alter table public."DbSfMappings" drop constraint "FK_DbAccounts";
alter table public."DbTriggerToSearchCriteria" drop constraint "FK_DbSearchCriteria";
alter table public."DbUserImageStamps" drop constraint "FK_DbAccounts";
alter table public."DbUserSearchToSearchCriteria" drop constraint "FK_DbSearchCriteria";
alter table public."DbUserSearchToSearchCriteria" drop constraint "FK_DbUserSearches";
alter table public."DbUserSettings" drop constraint "FK_DbEmailSettings";
alter table public."DbUserSettings" drop constraint "FK_DbPortfolios";
alter table public."DbUsers" drop constraint "FK_DbUserSettings";
alter table workflow."DbWorkflowInstanceHistoryRecords" drop constraint "FK_DbWorkflowInstanceHistoryRecordTypes_RecordTypeID";
alter table workflow."DbWorkflowSteps" drop constraint "FK_DbWorkflowStepTypes_TypeID";
alter table public."DbDocumentRequestContainers" drop constraint "DbFileRequestContainers_check";
alter table public."DbDocumentRequests" drop constraint "DbFileRequests_check";
alter table public."DbTimeTriggers" drop constraint "check_timeTrigger_preActionNotificationTimeSpanInDays";
alter table public."DbTimeTriggers" drop constraint "check_timeTrigger_timeSpanInSeconds";
alter table public."DbComponentStatusHistories" drop constraint "FK_public.DbComponentStatusHistories_public.DbComponentStatus_C";
alter table public."DbDocumentRequestAttachments" drop constraint "FK_public.DbDocumentRequestAttachments_public.DbNodes_Attachmen";
alter table public."DbDocumentRequestContainerNodes" drop constraint "FK_public.DbDocumentRequestContainerNodes_public.DbNodes_NodeID";
alter table public."DbDocumentRequests" drop constraint "FK_public.DbDocumentRequests_public.DbNodes_DestinationNodeID_A";
alter table public."DbEmailQueueAttachmentNodes" drop constraint "FK_public.DbEmailQueueAttachmentNodes_public.DbNodes_NodeID_Acc";
alter table public."DbESignatureNodeAssociations" drop constraint "FK_public.DbESignatureNodeAssociations_public.DbNodes_OriginalN";
alter table public."DbESignatureNodeAssociations" drop constraint "FK_public.DbESignatureNodeAssociations_public.DbNodes_SignedNod";
alter table public."DbESignatureTransactions" drop constraint "FK_public.DbESignatureTransactions_public.DbNodes_AuditTrailNod";
alter table public."DbESignatureTransactions" drop constraint "FK_public.DbESignatureTransactions_public.DbNodes_AuditTrailPar";
alter table public."DbESignatureTransactions" drop constraint "FK_public.DbESignatureTransactions_public.DbNodes_SignedDocumen";
alter table public."DbNodes" drop constraint "FK_public.DbNodes_public.DbFileInfoes_FileInfoID_AccountID";
alter table public."DbFileQueue" drop constraint "FK_public.DbFileQueue_public.DbNodes_NodeID_AccountID";
alter table public."DbLegacyNodeMappings" drop constraint "FK_public.DbLegacyNodeMappings_public.DbNodes_NodeId_AccountID";
alter table public."DbNodes" drop constraint "FK_public.DbNodes_public.DbNodes_ParentID_AccountID";
alter table public."DbNodeAnnotations" drop constraint "FK_public.DbNodeAnnotations_public.DbNodes_NodeID_AccountID";
alter table public."DbNodeClosures" drop constraint "FK_public.DbNodeClosures_public.DbNodes_ChildID_AccountID";
alter table public."DbRoleRelationships" drop constraint "Parent_Is_Group";
alter table public."DbAccessLinks" drop constraint "FK_public.DbAccessLinks_public.DbUsers_CreatedByUserID";
alter table public."DbAuditLogs" drop constraint "FK_public.DbAuditLogs_public.DbUsers_UserID";
alter table public."DbAuditLogs" drop constraint "FK_public.DbAuditLogs_public.DbUsers_GeneratedByUserID";
alter table public."DbDocumentRequests" drop constraint "FK_public.DbDocumentRequests_public.DbUsers_CreatedByUserID";
alter table public."DbEmailImportMappings" drop constraint "FK_public.DbEmailImportMappings_public.DbUsers_CreatedByUserID";
alter table public."DbESignatureTransactions" drop constraint "FK_public.DbESignatureTransactions_public.DbUsers_UserID";
alter table public."DbFileInfoes" drop constraint "FK_public.DbFileInfoes_public.DbUsers_CreatedByUserID";
alter table public."DbNodeComments" drop constraint "FK_public.DbNodeComments_public.DbUsers_LastModifiedByUserID";
alter table public."DbNodeComments" drop constraint "FK_public.DbNodeComments_public.DbUsers_CreatedByUserID";
alter table public."DbNodes" drop constraint "FK_public.DbNodes_public.DbUsers_CreatedByUserID";
alter table public."DbPortfolios" drop constraint "FK_public.DbPortfolios_public.DbUsers_OwnerUserID";
alter table public."DbPortfolioToNodes" drop constraint "FK_public.DbPortfolioToNodes_public.DbUsers_AddedByUserID";
alter table public."DbPortfolioToUsers" drop constraint "FK_public.DbPortfolioToUsers_public.DbUsers_UserID";
alter table public."DbResetPasswordRequests" drop constraint "FK_public.DbResetPasswordRequests_public.DbUsers_UserID";
alter table public."DbRightSignatureUsers" drop constraint "FK_public.DbRightSignatureUsers_public.DbUsers_UserID";
alter table public."DbRoles" drop constraint "FK_public.DbRoles_public.DbUsers_UserID";
alter table public."DbSamlConfigurations" drop constraint "FK_public.DbSamlConfigurations_public.DbUsers_CreatedByUserID";
alter table public."DbTriggers" drop constraint "FK_public.DbTriggers_public.DbUsers_CreatedByUserID";
alter table public."DbUserApplicationsMfa" drop constraint "FK_public.DbUserApplicationsMfa_public.DbUsers_UserID";
alter table public."DbUserExternalAuthentications" drop constraint "FK_public.DbUserExternalAuthentications_public.DbUsers_UserID";
alter table public."DbUserImageStamps" drop constraint "FK_public.DbUserImageStamps_public.DbUsers_UserID";
alter table public."DbUserPasswordHistories" drop constraint "FK_public.DbUserPasswordHistories_public.DbUsers_UserID";
alter table public."DbUserSearches" drop constraint "FK_public.DbUserSearches_public.DbUsers_UserID";
alter table public."DbUserSessions" drop constraint "FK_public.DbUserSessions_public.DbUsers_UserID";
alter table public."DbUserSessions" drop constraint "FK_public.DbUserSessions_public.DbUsers_GeneratedByUserID";
alter table public."DbEmailSettingToUsers" drop constraint "FK_public.DbEmailSettingToUsers_public.DbUsers_UserID";
alter table public."DbRightSignatureDocuments" drop constraint "FK_public.DbRightSignatureDocuments_public.DbRightSignatureUser";
alter table public."DbFormFillPendings" drop constraint "FK_public.DbFormFillPendings_public.DbUsers_UserID";
alter table workflow."DbWorkflowStepInstances" drop constraint "FK_workflow.DbWorkflowStepInstances_workflow.DbWorkflowSteps_Db";
alter table workflow."DbWorkflowInstances" drop constraint "FK_workflow.DbWorkflowInstances_workflow.DbWorkflowInstanceStat";
alter table workflow."DbStageApproveResults" drop constraint "FK_workflow.DbStageApproveResults_workflow.DbWorkflowStageInsta";
alter table workflow."DbWorkflowStepInstances" drop constraint "FK_workflow.DbWorkflowStepInstances_workflow.DbWorkflowAssetI1";
alter table workflow."DbWorkflowStepInstances" drop constraint "FK_workflow.DbWorkflowStepInstances_workflow.DbWorkflowAssetI2";
alter table workflow."DbWorkflowStepInstances" drop constraint "FK_workflow.DbWorkflowStepInstances_workflow.DbWorkflowAssetI3";
alter table workflow."DbWorkflowStepInstances" drop constraint "FK_workflow.DbWorkflowStepInstances_workflow.DbWorkflowAssetI4";
alter table workflow."DbWorkflowStepInstances" drop constraint "FK_workflow.DbWorkflowStepInstances_workflow.DbWorkflowAssetI5";
alter table workflow."DbWorkflowStepInstances" drop constraint "FK_workflow.DbWorkflowStepInstances_workflow.DbWorkflowAssetI6";
alter table workflow."DbWorkflowStepInstances" drop constraint "FK_workflow.DbWorkflowStepInstances_workflow.DbWorkflowAssetI7";
alter table workflow."DbWorkflowStepInstances" drop constraint "FK_workflow.DbWorkflowStepInstances_workflow.DbWorkflowAssetI8";
alter table workflow."DbWorkflowStepInstances" drop constraint "FK_workflow.DbWorkflowStepInstances_workflow.DbWorkflowAssetI9";
alter table workflow."DbWorkflowStepInstances" drop constraint "FK_workflow.DbWorkflowStepInstances_workflow.DbWorkflowAsset10";
alter table workflow."DbWorkflowStepInstances" drop constraint "FK_workflow.DbWorkflowStepInstances_workflow.DbWorkflowAsset11";
alter table workflow."DbWorkflowStepInstances" drop constraint "FK_workflow.DbWorkflowStepInstances_workflow.DbWorkflowAsset12";
alter table workflow."DbWorkflowStepInstances" drop constraint "FK_workflow.DbWorkflowStepInstances_workflow.DbWorkflowAsset14";
alter table workflow."DbWorkflowStepInstances" drop constraint "FK_workflow.DbWorkflowStepInstances_workflow.DbWorkflowAsset15";
alter table workflow."DbWorkflowStepInstances" drop constraint "FK_workflow.DbWorkflowStepInstances_workflow.DbWorkflowAsset16";
alter table workflow."DbWorkflowESignatureStepInstanceUserReferences" drop constraint "FK_workflow.DbWorkflowESignatureStepInstanceUserReferences_wor1";
alter table workflow."DbWorkflowStepInstances" drop constraint "FK_workflow.DbWorkflowStepInstances_workflow.DbWorkflowAsset17";
alter table workflow."DbWorkflowESignatureStepInstanceTemplateDocuments" drop constraint "FK_workflow.DbWorkflowESignatureStepInstanceTemplateDocuments_1";
alter table workflow."DbWorkflowStepInstances" drop constraint "FK_workflow.DbWorkflowStepInstances_workflow.DbWorkflowAsset18";
alter table workflow."DbWorkflowStepInstances" drop constraint "FK_workflow.DbWorkflowStepInstances_workflow.DbWorkflowAsset19";
alter table workflow."DbWorkflowStepInstances" drop constraint "FK_workflow.DbWorkflowStepInstances_workflow.DbWorkflowAsset20";
alter table workflow."DbWorkflowStepInstances" drop constraint "FK_workflow.DbWorkflowStepInstances_workflow.DbWorkflowAsset21";
alter table workflow."DbWorkflowStepInstances" drop constraint "FK_workflow.DbWorkflowStepInstances_workflow.DbWorkflowAsset22";
alter table workflow."DbWorkflowStepInstances" drop constraint "FK_workflow.DbWorkflowStepInstances_workflow.DbWorkflowAsset23";
alter table workflow."DbWorkflowStepInstances" drop constraint "FK_workflow.DbWorkflowStepInstances_workflow.DbWorkflowAsset24";
alter table workflow."DbWorkflowStepInstances" drop constraint "FK_workflow.DbWorkflowStepInstances_workflow.DbWorkflowAsset25";
alter table workflow."DbWorkflowStepInstances" drop constraint "FK_workflow.DbWorkflowStepInstances_workflow.DbWorkflowAsset26";
alter table workflow."DbWorkflowStepInstances" drop constraint "FK_workflow.DbWorkflowStepInstances_workflow.DbWorkflowAsset27";
alter table workflow."DbWorkflowStepInstances" drop constraint "FK_workflow.DbWorkflowStepInstances_workflow.DbWorkflowAsset28";
alter table workflow."DbWorkflowStepInstances" drop constraint "FK_workflow.DbWorkflowStepInstances_workflow.DbWorkflowAsset29";
alter table workflow."DbWorkflowStepInstanceDocumentRequestContainers" drop constraint "FK_workflow.DbWorkflowStepInstanceDocumentRequestContainers_wo1";
alter table workflow."DbAssetInstanceNodeReferences" drop constraint "FK_workflow.DbAssetInstanceNodeReferences_workflow.DbWorkflowAs";
alter table workflow."DbWorkflowAssetsStagesInstances" drop constraint "FK_workflow.DbWorkflowAssetsStagesInstances_workflow.DbWorkflo1";
alter table workflow."DbWorkflowStepInstanceEmailUserGroups" drop constraint "FK_workflow.DbWorkflowStepInstanceEmailUserGroups_workflow.DbWo";
alter table workflow."DbWorkflowStepInstanceEmailUsers" drop constraint "FK_workflow.DbWorkflowStepInstanceEmailUsers_workflow.DbWorkflo";
alter table workflow."DbWorkflowESignatureStepInstanceUserReferences" drop constraint "FK_workflow.DbWorkflowESignatureStepInstanceUserReferences_wor2";
alter table workflow."DbWorkflowESignatureStepInstanceTemplateDocuments" drop constraint "FK_workflow.DbWorkflowESignatureStepInstanceTemplateDocuments_2";
alter table workflow."DbWorkflowSendMessageInstanceRecipients" drop constraint "FK_workflow.DbWorkflowSendMessageInstanceRecipients_workflow.Db";
alter table workflow."DbWorkflowStepInstanceUserGroups" drop constraint "FK_workflow.DbWorkflowStepInstanceUserGroups_workflow.DbWorkflo";
alter table workflow."DbWorkflowStepInstanceUsers" drop constraint "FK_workflow.DbWorkflowStepInstanceUsers_workflow.DbWorkflowStep";
alter table workflow."DbWorkflowSetProfileInstanceItems" drop constraint "FK_workflow.DbWorkflowSetProfileInstanceItems_workflow.DbWorkfl";
alter table workflow."DbWorkflowShareStepInstanceNewUserReferences" drop constraint "FK_workflow.DbWorkflowShareStepInstanceNewUserReferences_workfl";
alter table workflow."DbWorkflowStepInstanceGroupReferences" drop constraint "FK_workflow.DbWorkflowStepInstanceGroupReferences_workflow.DbWo";
alter table workflow."DbWorkflowStepInstanceUserReferences" drop constraint "FK_workflow.DbWorkflowStepInstanceUserReferences_workflow.DbWor";
alter table workflow."DbWorkflowInstanceHistoryRecords" drop constraint "FK_workflow.DbWorkflowInstanceHistoryRecords_workflow.DbWorkfl1";
alter table workflow."DbWorkflowStepInstanceDocumentRequestContainers" drop constraint "FK_workflow.DbWorkflowStepInstanceDocumentRequestContainers_wo2";
alter table workflow."DbWorkflowRequestFileExternalStepInstanceRecipientGroups" drop constraint "FK_workflow.DbWorkflowRequestFileExternalStepInstanceRecipientG";
alter table workflow."DbWorkflowRequestFileExternalStepInstanceNewUserReferences" drop constraint "FK_workflow.DbWorkflowRequestFileExternalStepInstanceNewUserRef";
alter table workflow."DbWorkflowRequestFileExternalStepInstanceRecipients" drop constraint "FK_workflow.DbWorkflowRequestFileExternalStepInstanceRecipients";
alter table workflow."DbWorkflowStepDocumentRequestContainers" drop constraint "FK_workflow.DbWorkflowStepDocumentRequestContainers_workflow.D1";
alter table workflow."DbWorkflowRequestFileExternalStepRecipientGroups" drop constraint "FK_workflow.DbWorkflowRequestFileExternalStepRecipientGroups_wo";
alter table workflow."DbWorkflowRequestFileExternalStepNewUserReferences" drop constraint "FK_workflow.DbWorkflowRequestFileExternalStepNewUserReferences_";
alter table workflow."DbWorkflowRequestFileExternalStepRecipients" drop constraint "FK_workflow.DbWorkflowRequestFileExternalStepRecipients_workflo";
alter table workflow."DbWorkflowAddTriggerStepEmailUserGroups" drop constraint "FK_workflow.DbWorkflowAddTriggerStepEmailUserGroups_workflow.Db";
alter table workflow."DbWorkflowAddTriggerStepEmailUsers" drop constraint "FK_workflow.DbWorkflowAddTriggerStepEmailUsers_workflow.DbWorkf";
alter table workflow."DbWorkflowESignatureStepUserReferences" drop constraint "FK_workflow.DbWorkflowESignatureStepUserReferences_workflow.DbW";
alter table workflow."DbWorkflowESignatureStepTemplateDocuments" drop constraint "FK_workflow.DbWorkflowESignatureStepTemplateDocuments_workflow1";
alter table workflow."DbWorkflowSendMessageRecipients" drop constraint "FK_workflow.DbWorkflowSendMessageRecipients_workflow.DbWorkflow";
alter table workflow."DbWorkflowSetPermissionsStepUserGroups" drop constraint "FK_workflow.DbWorkflowSetPermissionsStepUserGroups_workflow.DbW";
alter table workflow."DbWorkflowSetPermissionsStepUsers" drop constraint "FK_workflow.DbWorkflowSetPermissionsStepUsers_workflow.DbWorkfl";
alter table public."DbNodeClosures" drop constraint "FK_public.DbNodeClosures_public.DbNodes_ParentID_AccountID";
alter table public."DbTriggers" drop constraint "FK_public.DbTriggers_public.DbAccounts_AccountID";
alter table public."DbEmailContent" drop constraint "FK_public.DbEmailContent_public.DbAccounts_AccountID";
alter table public."DbEventTriggers" drop constraint "FK_public.DbEventTriggers_public.DbAccounts_AccountID";
alter table public."DbTimeTriggers" drop constraint "FK_public.DbTimeTriggers_public.DbAccounts_AccountID";
alter table public."DbTriggerInfoNodes" drop constraint "FK_public.DbTriggerInfoNodes_public.DbAccounts_AccountID";
alter table public."DbTriggerToNode" drop constraint "FK_public.DbTriggerToNode_public.DbAccounts_AccountID";
alter table public."DbTriggerToWorkflow" drop constraint "FK_public.DbTriggerToWorkflow_public.DbAccounts_AccountID";
alter table public."DbTriggerToRoles" drop constraint "FK_public.DbTriggerToRoles_public.DbAccounts_AccountID";
alter table public."DbTriggerToSearchCriteria" drop constraint "FK_public.DbTriggerToSearchCriteria_public.DbAccounts_AccountID";
alter table public."DbProfileValueNodes" drop constraint "FK_public.DbProfileValueNodes_public.DbAccounts_AccountID";
alter table public."DbProfileToProfileItems" drop constraint "FK_public.DbProfileToProfileItems_public.DbAccounts_AccountID";
alter table public."DbProfileValueRoles" drop constraint "FK_public.DbProfileValueRoles_public.DbAccounts_AccountID";
alter table public."DbRoleRelationships" drop constraint "FK_public.DbRoleRelationships_public.DbAccounts_AccountID";
alter table public."DbRoleToAccountFeatures" drop constraint "FK_public.DbRoleToAccountFeatures_public.DbAccounts_AccountID";
alter table public."DbSystemPermissions" drop constraint "FK_public.DbSystemPermissions_public.DbAccounts_AccountID";
alter table public."DbEmailQueueAttachmentNodes" drop constraint "FK_public.DbEmailQueueAttachmentNodes_public.DbAccounts_Account";
alter table public."DbTemplateNodeChangeLogs" drop constraint "FK_public.DbTemplateNodeChangeLogs_public.DbAccounts_AccountID";
alter table public."DbTemplateNodeLinks" drop constraint "FK_public.DbTemplateNodeLinks_public.DbAccounts_AccountID";
alter table public."DbWorkflowStageInstanceToNotifications" drop constraint "FK_public.DbWorkflowStageInstanceToNotifications_public.DbAccou";
alter table public."DbRoleClosures" drop constraint "FK_public.DbRoleClosures_public.DbAccounts_AccountID";
alter table public."DbAccessLinksToNodeAndTriggers" drop constraint "FK_public.DbAccessLinksToNodeAndTriggers_public.DbAccounts_Acco";
alter table public."DbDocumentRequestRoles" drop constraint "FK_public.DbDocumentRequestRoles_public.DbAccounts_AccountID";
alter table public."DbNodeComments" drop constraint "FK_public.DbNodeComments_public.DbNodes_NodeID_AccountID";
alter table public."DbNodeShares" drop constraint "FK_public.DbNodeShares_public.DbNodes_AccountWorkspaceNodeID_Ac";
alter table public."DbNodeShares" drop constraint "FK_public.DbNodeShares_public.DbNodes_SharedWorkspaceNodeID_Acc";
alter table public."DbNodeToFileInfoes" drop constraint "FK_public.DbNodeToFileInfoes_public.DbNodes_NodeID_AccountID";
alter table public."DbPermissions" drop constraint "FK_public.DbPermissions_public.DbNodes_NodeID_AccountID";
alter table public."DbNodes" drop constraint "FK_public.DbNodes_public.DbProfiles_ProfileID_AccountID";
alter table public."DbProfileValueNodes" drop constraint "FK_public.DbProfileValueNodes_public.DbNodes_NodeID_AccountID";
alter table public."DbRightSignatureDocuments" drop constraint "FK_public.DbRightSignatureDocuments_public.DbNodes_NodeID_Accou";
alter table public."DbSfLinks" drop constraint "FK_public.DbSfLinks_public.DbNodes_NodeID_AccountID";
alter table public."DbSfMappings" drop constraint "FK_public.DbSfMappings_public.DbNodes_ParentNodeID_AccountID";
alter table public."DbTemplateNodeChangeLogs" drop constraint "FK_public.DbTemplateNodeChangeLogs_public.DbNodes_TemplateNodeI";
alter table public."DbTemplateNodeLinks" drop constraint "FK_public.DbTemplateNodeLinks_public.DbNodes_AppliedNodeID_Acco";
alter table public."DbTemplateNodeLinks" drop constraint "FK_public.DbTemplateNodeLinks_public.DbNodes_TemplateNodeID_Acc";
alter table public."DbTriggerInfoNodes" drop constraint "FK_public.DbTriggerInfoNodes_public.DbNodes_NodeID_AccountID";
alter table public."DbTriggerToNode" drop constraint "FK_public.DbTriggerToNode_public.DbNodes_NodeID_AccountID";
alter table public."DbUserImageStamps" drop constraint "FK_public.DbUserImageStamps_public.DbNodes_NodeID_AccountID";
alter table public."DbAccessLinksToNodeAndTriggers" drop constraint "FK_public.DbAccessLinksToNodeAndTriggers_public.DbTriggers_Trig";
alter table public."DbTriggers" drop constraint "FK_public.DbTriggers_public.DbEmailContent_EmailContentID_Accou";
alter table public."DbEventTriggers" drop constraint "FK_public.DbEventTriggers_public.DbTriggers_TriggerID_AccountID";
alter table public."DbTimeTriggers" drop constraint "FK_public.DbTimeTriggers_public.DbTriggers_TriggerID_AccountID";
alter table public."DbTriggerInfoNodes" drop constraint "FK_public.DbTriggerInfoNodes_public.DbTriggers_TriggerID_Accoun";
alter table public."DbTriggerToApiCallouts" drop constraint "FK_public.DbTriggerToApiCallouts_public.DbTriggers_TriggerID_Ac";
alter table public."DbTriggerToNode" drop constraint "FK_public.DbTriggerToNode_public.DbTriggers_TriggerID_AccountID";
alter table public."DbTriggerToRoles" drop constraint "FK_public.DbTriggerToRoles_public.DbTriggers_TriggerID_AccountI";
alter table public."DbTriggerToSearchCriteria" drop constraint "FK_public.DbTriggerToSearchCriteria_public.DbTriggers_TriggerID";
alter table public."DbTriggerToWorkflow" drop constraint "FK_public.DbTriggerToWorkflow_public.DbTriggers_TriggerID_Accou";
alter table public."DbWatermarkTriggerInfo" drop constraint "FK_public.DbWatermarkTriggerInfo_public.DbTriggers_TriggerID_Ac";
alter table public."DbTriggerToRoles" drop constraint "FK_public.DbTriggerToRoles_public.DbRoles_RoleID_AccountID";
alter table public."DbAuditLogsToRoles" drop constraint "FK_public.DbAuditLogsToRoles_public.DbRoles_RoleID_AccountID";
alter table public."DbDocumentRequestRoles" drop constraint "FK_public.DbDocumentRequestRoles_public.DbRoles_RecipientRoleID";
alter table public."DbESignatureSigners" drop constraint "FK_public.DbESignatureSigners_public.DbRoles_RoleID_AccountID";
alter table public."DbFileInfoes" drop constraint "FK_public.DbFileInfoes_public.DbRoles_CheckedOutByRoleID_Accoun";
alter table public."DbNodeShares" drop constraint "FK_public.DbNodeShares_public.DbRoles_RoleID_AccountID";
alter table public."DbNotifications" drop constraint "FK_public.DbNotifications_public.DbRoles_RecipientRoleID_Accoun";
alter table public."DbPermissions" drop constraint "FK_public.DbPermissions_public.DbRoles_RoleID_AccountID";
alter table public."DbRoles" drop constraint "FK_public.DbRoles_public.DbProfiles_ProfileID_AccountID";
alter table public."DbProfileValueRoles" drop constraint "FK_public.DbProfileValueRoles_public.DbRoles_RoleID_AccountID";
alter table public."DbRoleClosures" drop constraint "FK_public.DbRoleClosures_public.DbRoles_ChildID_AccountID";
alter table public."DbRoleClosures" drop constraint "FK_public.DbRoleClosures_public.DbRoles_ParentID_AccountID";
alter table public."DbRoles" drop constraint "FK_public.DbRoles_public.DbRoles_RoleManagerID_AccountID";
alter table public."DbRoleRelationships" drop constraint "FK_public.DbRoleRelationships_public.DbRoles_ParentRoleID_Accou";
alter table public."DbRoleRelationships" drop constraint "FK_public.DbRoleRelationships_public.DbRoles_ChildRoleID_Accoun";
alter table public."DbRoleToAccountFeatures" drop constraint "FK_public.DbRoleToAccountFeatures_public.DbRoles_RoleID_Account";
alter table public."DbSamlConfigurations" drop constraint "FK_public.DbSamlConfigurations_public.DbRoles_DefaultGroupID_Ac";
alter table public."DbRoles" drop constraint "FK_public.DbRoles_public.DbSecurityPolicies_SecurityPolicyID_Ac";
alter table public."DbRoles" drop constraint "FK_public.DbRoles_public.DbSystemPermissions_SystemPermissionID";
alter table public."DbUserRolePreferences" drop constraint "FK_public.DbUserRolePreferences_public.DbRoles_RoleID_AccountID";
alter table public."DbUserSessions" drop constraint "FK_public.DbUserSessions_public.DbRoles_RoleID_AccountID";
alter table public."DbUserSessionToDbRoles" drop constraint "FK_public.DbUserSessionToDbRoles_public.DbRoles_RoleID_AccountI";
alter table public."DbAuditLogsToRoles" drop constraint "FK_public.DbAuditLogsToRoles_public.DbAuditLogs_AuditLogID_Acco";
alter table public."DbAuditLogsToRoleDetails" drop constraint "FK_public.DbAuditLogsToRoleDetails_public.DbAuditLogsToRoles_Au";
alter table public."DbAuditLogsToNodes" drop constraint "FK_public.DbAuditLogsToNodes_public.DbAuditLogs_AuditLogID_Acco";
alter table public."DbAuditLogsToNodeDetails" drop constraint "FK_public.DbAuditLogsToNodeDetails_public.DbAuditLogsToNodes_Au";
alter table public."DbDocumentRequestAttachments" drop constraint "FK_public.DbDocumentRequestAttachments_public.DbDocumentRequest";
alter table public."DbDocumentRequestContainers" drop constraint "FK_public.DbDocumentRequestContainers_public.DbDocumentRequests";
alter table public."DbDocumentRequestRoles" drop constraint "FK_public.DbDocumentRequestRoles_public.DbDocumentRequests_Docu";
alter table public."DbDocumentRequestToNotifications" drop constraint "FK_public.DbDocumentRequestToNotifications_public.DbDocumentReq";
alter table public."DbDocumentRequestContainerNodes" drop constraint "FK_public.DbDocumentRequestContainerNodes_public.DbDocumentRequ";
alter table public."DbDocumentRequestContainers" drop constraint "FK_public.DbDocumentRequestContainers_public.DbFileInfoes_FileI";
alter table public."DbDocumentRequestContainers" drop constraint "FK_public.DbDocumentRequestContainers_public.DbFormFillDefiniti";
alter table public."DbFileQueue" drop constraint "FK_public.DbFileQueue_public.DbFileInfoes_FileInfoID_AccountID";
alter table public."DbFileInfoes" drop constraint "FK_public.DbFileInfoes_public.DbFormFillDefinitions_FormFillDef";
alter table public."DbFileInfoes" drop constraint "FK_public.DbFileInfoes_public.DbNodeComments_NodeCommentID_Acco";
alter table public."DbNodeToFileInfoes" drop constraint "FK_public.DbNodeToFileInfoes_public.DbFileInfoes_FileInfoID_Acc";
alter table public."DbFileInfoes" drop constraint "FK_public.DbFileInfoes_public.DbFileInfoes_GeneratedFromFileInf";
alter table public."DbFormFillPendings" drop constraint "FK_public.DbFormFillPendings_public.DbFormFillDefinitions_FormF";
alter table public."DbFormFillToProfileItems" drop constraint "FK_public.DbFormFillToProfileItems_public.DbFormFillDefinitions";
alter table public."DbFormFillDefinitions" drop constraint "FK_public.DbFormFillDefinitions_public.DbProfiles_ProfileID_Acc";
alter table public."DbFormFillPendings" drop constraint "FK_public.DbFormFillPendings_public.DbFileInfoes_AppliedNodeFil";
alter table public."DbFormFillToProfileItems" drop constraint "FK_public.DbFormFillToProfileItems_public.DbProfileItems_Profil";
alter table public."DbPresetValues" drop constraint "FK_public.DbPresetValues_public.DbProfileItems_ProfileItemID_Ac";
alter table public."DbProfileToProfileItems" drop constraint "FK_public.DbProfileToProfileItems_public.DbProfileItems_Profile";
alter table public."DbProfileValueNodes" drop constraint "FK_public.DbProfileValueNodes_public.DbProfileItems_ProfileItem";
alter table public."DbProfileValueRoles" drop constraint "FK_public.DbProfileValueRoles_public.DbProfileItems_ProfileItem";
alter table public."DbProfileValueNodes" drop constraint "FK_public.DbProfileValueNodes_public.DbPresetValues_PresetValue";
alter table public."DbProfileValueRoles" drop constraint "FK_public.DbProfileValueRoles_public.DbPresetValues_PresetValue";
alter table public."DbProfileValueNodes" drop constraint "FK_public.DbProfileValueNodes_public.DbProfiles_ProfileID_Accou";
alter table public."DbProfileToProfileItems" drop constraint "FK_public.DbProfileToProfileItems_public.DbProfiles_ProfileID_A";
alter table public."DbProfileValueRoles" drop constraint "FK_public.DbProfileValueRoles_public.DbProfiles_ProfileID_Accou";
alter table public."DbDocumentRequestToNotifications" drop constraint "FK_public.DbDocumentRequestToNotifications_public.DbNotificatio";
alter table public."DbWorkflowStageInstanceToNotifications" drop constraint "FK_public.DbWorkflowStageInstanceToNotifications_public.DbNotif";
alter table public."DbESignatureNodeAssociations" drop constraint "FK_public.DbESignatureNodeAssociations_public.DbESignatureTrans";
alter table public."DbESignatureSigners" drop constraint "FK_public.DbESignatureSigners_public.DbESignatureTransactions_T";
alter table public."DbESignatureTransactions" drop constraint "FK_public.DbESignatureTransactions_public.DbESignatureTransacti";
alter table public."DbSamlResponses" drop constraint "FK_public.DbSamlResponses_public.DbSamlConfigurations_Configura";
alter table public."DbPermissions" drop constraint "FK_public.DbPermissions_public.DbPermissions_ChildPermissionId_";
alter table public."DbSecurityPolicyIpAddresses" drop constraint "FK_public.DbSecurityPolicyIpAddresses_public.DbSecurityPolicies";
alter table public."DbSecurityPolicyLoginTimes" drop constraint "FK_public.DbSecurityPolicyLoginTimes_public.DbSecurityPolicies_";
alter table public."DbEmailQueueAttachmentNodes" drop constraint "FK_public.DbEmailQueueAttachmentNodes_public.DbEmailQueue_Email";
alter table public."DbEmailRecipients" drop constraint "FK_public.DbEmailRecipients_public.DbEmailQueue_EmailQueueID_Ac";
alter table public."DbSfLinks" drop constraint "FK_public.DbSfLinks_public.DbSfMappings_SfMappingID_AccountID";
alter table public."DbSfMappings" drop constraint "FK_public.DbSfMappings_public.DbPermissions_GroupPermissionID_A";
alter table public."DbSfMappings" drop constraint "FK_public.DbSfMappings_public.DbPermissions_UserPermissionID_Ac";
alter table public."DbEmailTemplateToPartner" drop constraint "FK_public.DbEmailTemplateToPartner_public.DbPartners_PartnerID";
alter table public."DbUserSessionToDbRoles" drop constraint "FK_public.DbUserSessionToDbRoles_public.DbUserSessions_UserSess";
alter table workflow."DbWorkflowSetProfileItems" drop constraint "FK_workflow.DbWorkflowSetProfileItems_workflow.DbWorkflowSteps_";
alter table workflow."DbWorkflowShareStepNewUserReferences" drop constraint "FK_workflow.DbWorkflowShareStepNewUserReferences_workflow.DbWor";
alter table workflow."DbWorkflowStepGroupReferences" drop constraint "FK_workflow.DbWorkflowStepGroupReferences_workflow.DbWorkflowSt";
alter table workflow."DbWorkflowStepUserReferences" drop constraint "FK_workflow.DbWorkflowStepUserReferences_workflow.DbWorkflowSte";
alter table workflow."DbWorkflowAssetsStages" drop constraint "FK_workflow.DbWorkflowAssetsStages_workflow.DbWorkflowStages_St";
alter table workflow."DbWorkflowStageInstances" drop constraint "FK_workflow.DbWorkflowStageInstances_workflow.DbWorkflowStages_";
alter table workflow."DbWorkflowStageApproverGroups" drop constraint "FK_workflow.DbWorkflowStageApproverGroups_workflow.DbWorkflowSt";
alter table workflow."DbWorkflowStageApprovers" drop constraint "FK_workflow.DbWorkflowStageApprovers_workflow.DbWorkflowStages_";
alter table workflow."DbWorkflowStageAssigneeGroups" drop constraint "FK_workflow.DbWorkflowStageAssigneeGroups_workflow.DbWorkflowSt";
alter table workflow."DbWorkflowStageAssignees" drop constraint "FK_workflow.DbWorkflowStageAssignees_workflow.DbWorkflowStages_";
alter table workflow."DbProfileRoutingRules" drop constraint "FK_workflow.DbProfileRoutingRules_workflow.DbWorkflowStages_Sta";
alter table workflow."DbWorkflowSteps" drop constraint "FK_workflow.DbWorkflowSteps_workflow.DbWorkflowStages_StageID";
alter table workflow."DbWorkflowSteps" drop constraint "FK_workflow.DbWorkflowSteps_workflow.DbWorkflowAssets_requestF1";
alter table workflow."DbWorkflowSteps" drop constraint "FK_workflow.DbWorkflowSteps_workflow.DbWorkflowAssets_requestF2";
alter table workflow."DbWorkflowStepDocumentRequestContainers" drop constraint "FK_workflow.DbWorkflowStepDocumentRequestContainers_workflow.D2";
alter table workflow."DbAssetNodeReference" drop constraint "FK_workflow.DbAssetNodeReference_workflow.DbWorkflowAssets_Asse";
alter table workflow."DbWorkflowAssetsStages" drop constraint "FK_workflow.DbWorkflowAssetsStages_workflow.DbWorkflowAssets_As";
alter table workflow."DbWorkflowStages" drop constraint "FK_workflow.DbWorkflowStages_workflow.DbWorkflowAssets_Approval";
alter table workflow."DbProfileRoutingRules" drop constraint "FK_workflow.DbProfileRoutingRules_workflow.DbWorkflowAssets_Ass";
alter table workflow."DbWorkflowSteps" drop constraint "FK_workflow.DbWorkflowSteps_workflow.DbWorkflowAssets_addTrigg1";
alter table workflow."DbWorkflowSteps" drop constraint "FK_workflow.DbWorkflowSteps_workflow.DbWorkflowAssets_addTrigg2";
alter table workflow."DbWorkflowSteps" drop constraint "FK_workflow.DbWorkflowSteps_workflow.DbWorkflowAssets_applyTemp";
alter table workflow."DbWorkflowSteps" drop constraint "FK_workflow.DbWorkflowSteps_workflow.DbWorkflowAssets_comment_T";
alter table workflow."DbWorkflowSteps" drop constraint "FK_workflow.DbWorkflowSteps_workflow.DbWorkflowAssets_copy_Dest";
alter table workflow."DbWorkflowSteps" drop constraint "FK_workflow.DbWorkflowSteps_workflow.DbWorkflowAssets_copy_Resu";
alter table workflow."DbWorkflowSteps" drop constraint "FK_workflow.DbWorkflowSteps_workflow.DbWorkflowAssets_copy_Sour";
alter table workflow."DbWorkflowSteps" drop constraint "FK_workflow.DbWorkflowSteps_workflow.DbWorkflowAssets_createLo1";
alter table workflow."DbWorkflowSteps" drop constraint "FK_workflow.DbWorkflowSteps_workflow.DbWorkflowAssets_createLo2";
alter table workflow."DbWorkflowSteps" drop constraint "FK_workflow.DbWorkflowSteps_workflow.DbWorkflowAssets_delete_Ta";
alter table workflow."DbWorkflowSteps" drop constraint "FK_workflow.DbWorkflowSteps_workflow.DbWorkflowAssets_esignatu1";
alter table workflow."DbWorkflowSteps" drop constraint "FK_workflow.DbWorkflowSteps_workflow.DbWorkflowAssets_esignatu2";
alter table workflow."DbWorkflowSteps" drop constraint "FK_workflow.DbWorkflowSteps_workflow.DbWorkflowAssets_esignatu3";
alter table workflow."DbWorkflowSteps" drop constraint "FK_workflow.DbWorkflowSteps_workflow.DbWorkflowAssets_esignatu4";
alter table workflow."DbWorkflowSteps" drop constraint "FK_workflow.DbWorkflowSteps_workflow.DbWorkflowAssets_esignatu5";
alter table workflow."DbWorkflowESignatureStepTemplateDocuments" drop constraint "FK_workflow.DbWorkflowESignatureStepTemplateDocuments_workflow2";
alter table workflow."DbWorkflowSteps" drop constraint "FK_workflow.DbWorkflowSteps_workflow.DbWorkflowAssets_move_Dest";
alter table workflow."DbWorkflowSteps" drop constraint "FK_workflow.DbWorkflowSteps_workflow.DbWorkflowAssets_move_Sour";
alter table workflow."DbWorkflowSteps" drop constraint "FK_workflow.DbWorkflowSteps_workflow.DbWorkflowAssets_rename_Ta";
alter table workflow."DbWorkflowSteps" drop constraint "FK_workflow.DbWorkflowSteps_workflow.DbWorkflowAssets_sendMessa";
alter table workflow."DbWorkflowSteps" drop constraint "FK_workflow.DbWorkflowSteps_workflow.DbWorkflowAssets_setPermis";
alter table workflow."DbWorkflowSteps" drop constraint "FK_workflow.DbWorkflowSteps_workflow.DbWorkflowAssets_setProfil";
alter table workflow."DbWorkflowSteps" drop constraint "FK_workflow.DbWorkflowSteps_workflow.DbWorkflowAssets_setReten1";
alter table workflow."DbWorkflowSteps" drop constraint "FK_workflow.DbWorkflowSteps_workflow.DbWorkflowAssets_setReten2";
alter table workflow."DbWorkflowSteps" drop constraint "FK_workflow.DbWorkflowSteps_workflow.DbWorkflowAssets_share_Sou";
alter table workflow."DbWorkflowSteps" drop constraint "FK_workflow.DbWorkflowSteps_workflow.DbWorkflowAssets_upload_Re";
alter table workflow."DbWorkflowSteps" drop constraint "FK_workflow.DbWorkflowSteps_workflow.DbWorkflowAssets_upload_So";
alter table workflow."DbWorkflowAssetInstances" drop constraint "FK_workflow.DbWorkflowAssetInstances_workflow.DbWorkflowAssets_";
alter table workflow."DbWorkflowAssets" drop constraint "FK_workflow.DbWorkflowAssets_workflow.DbWorkflows_WorkflowID";
alter table workflow."DbWorkflowInstanceHistoryRecords" drop constraint "FK_workflow.DbWorkflowInstanceHistoryRecords_workflow.DbWorkfl2";
alter table workflow."DbWorkflowInstances" drop constraint "FK_workflow.DbWorkflowInstances_workflow.DbWorkflows_WorkflowID";
alter table workflow."DbWorkflowsAvailableStates" drop constraint "FK_workflow.DbWorkflowsAvailableStates_workflow.DbWorkflows_Wor";
alter table workflow."DbWorkflowNotificationConfigurations" drop constraint "FK_workflow.DbWorkflowNotificationConfigurations_workflow.DbWor";
alter table workflow."DbWorkflowOwnerGroups" drop constraint "FK_workflow.DbWorkflowOwnerGroups_workflow.DbWorkflows_Workflow";
alter table workflow."DbWorkflowOwners" drop constraint "FK_workflow.DbWorkflowOwners_workflow.DbWorkflows_WorkflowID";
alter table workflow."DbWorkflowScheduleConfigurations" drop constraint "FK_workflow.DbWorkflowScheduleConfigurations_workflow.DbWorkflo";
alter table workflow."DbWorkflowStages" drop constraint "FK_workflow.DbWorkflowStages_workflow.DbWorkflows_WorkflowID";
alter table workflow."DbWorkflowStarterGroups" drop constraint "FK_workflow.DbWorkflowStarterGroups_workflow.DbWorkflows_Workfl";
alter table workflow."DbWorkflowStarters" drop constraint "FK_workflow.DbWorkflowStarters_workflow.DbWorkflows_WorkflowID";
alter table workflow."DbWorkflowWatcherGroups" drop constraint "FK_workflow.DbWorkflowWatcherGroups_workflow.DbWorkflows_Workfl";
alter table workflow."DbWorkflowWatchers" drop constraint "FK_workflow.DbWorkflowWatchers_workflow.DbWorkflows_WorkflowID";
alter table workflow."DbWorkflowsAvailableStates" drop constraint "FK_workflow.DbWorkflowsAvailableStates_workflow.DbWorkflowInsta";
alter table workflow."DbWorkflowStages" drop constraint "FK_workflow.DbWorkflowStages_workflow.DbWorkflowInstanceStates1";
alter table workflow."DbWorkflowStages" drop constraint "FK_workflow.DbWorkflowStages_workflow.DbWorkflowInstanceStates2";
alter table workflow."DbWorkflowStages" drop constraint "FK_workflow.DbWorkflowStages_workflow.DbWorkflowInstanceStates3";
alter table workflow."DbProfileRoutingRules" drop constraint "FK_workflow.DbProfileRoutingRules_workflow.DbWorkflowInstanceSt";
alter table workflow."DbWorkflowStages" drop constraint "FK_workflow.DbWorkflowStages_workflow.DbWorkflowInstanceStates4";
alter table workflow."DbWorkflowAssetInstances" drop constraint "FK_workflow.DbWorkflowAssetInstances_workflow.DbWorkflowInstanc";
alter table workflow."DbWorkflowInstanceHistoryRecords" drop constraint "FK_workflow.DbWorkflowInstanceHistoryRecords_workflow.DbWorkfl3";
alter table workflow."DbWorkflowStageInstances" drop constraint "FK_workflow.DbWorkflowStageInstances_workflow.DbWorkflowInstanc";
alter table workflow."DbWorkflowInstanceHistoryRecords" drop constraint "FK_workflow.DbWorkflowInstanceHistoryRecords_workflow.DbWorkfl4";
alter table workflow."DbWorkflowStepInstances" drop constraint "FK_workflow.DbWorkflowStepInstances_workflow.DbWorkflowStageIns";
alter table workflow."DbWorkflowInstances" drop constraint "FK_workflow.DbWorkflowInstances_workflow.DbWorkflowStageInstanc";
alter table workflow."DbWorkflowAssetsStagesInstances" drop constraint "FK_workflow.DbWorkflowAssetsStagesInstances_workflow.DbWorkflo2";
alter table workflow."DbWorkflowSetProfileInstanceItemPresetValues" drop constraint "FK_workflow.DbWorkflowSetProfileInstanceItemPresetValues_workfl";
alter table workflow."DbWorkflowSetProfileItemPresetValues" drop constraint "FK_workflow.DbWorkflowSetProfileItemPresetValues_workflow.DbWor";
alter table public."DbWorkflowStageInstanceToNotifications" drop constraint "FK_DbWorkflowStageInstanceToNotifications_DbWorkflowStageInstan";
alter table public."DbRoles" drop constraint "CK_RoleManagerID";
alter table public."DbDocumentRequestAttachments" drop constraint "FK_public.DbDocumentRequestAttachments_public.DbAccounts_Accoun";
alter table public."DbFormFillDefinitions" drop constraint "FK_public.DbFormFillDefinitions_public.DbAccounts_AccountID";
alter table public."DbDocumentRequestContainers" drop constraint "FK_public.DbDocumentRequestContainers_public.DbAccounts_Account";
alter table public."DbDocumentRequestContainerNodes" drop constraint "FK_public.DbDocumentRequestContainerNodes_public.DbAccounts_Acc";
alter table public."DbFormFillPendings" drop constraint "FK_public.DbFormFillPendings_public.DbAccounts_AccountID";
alter table public."DbFormFillToProfileItems" drop constraint "FK_public.DbFormFillToProfileItems_public.DbAccounts_AccountID";
alter table public."DbNodeComments" drop constraint "FK_public.DbNodeComments_public.DbAccounts_AccountID";
alter table public."DbESignatureSigners" drop constraint "FK_public.DbESignatureSigners_public.DbAccounts_AccountID";
alter table public."DbESignatureNodeAssociations" drop constraint "FK_public.DbESignatureNodeAssociations_public.DbAccounts_Accoun";
alter table public."DbSecurityPolicyIpAddresses" drop constraint "FK_public.DbSecurityPolicyIpAddresses_public.DbAccounts_Account";
alter table public."DbSecurityPolicyLoginTimes" drop constraint "FK_public.DbSecurityPolicyLoginTimes_public.DbAccounts_AccountI";
alter table public."DbUserRolePreferences" drop constraint "FK_public.DbUserRolePreferences_public.DbAccounts_AccountID";
alter table public."DbTriggerToApiCallouts" drop constraint "FK_public.DbTriggerToApiCallouts_public.DbAccounts_AccountID";
alter table public."DbWatermarkTriggerInfo" drop constraint "FK_public.DbWatermarkTriggerInfo_public.DbAccounts_AccountID";
alter table public."DbLegacyNodeMappings" drop constraint "FK_public.DbLegacyNodeMappings_public.DbAccounts_AccountID";
alter table public."DbAccessLinksToDocumentRequests" drop constraint "FK_public.DbAccessLinksToDocumentRequests_public.DbAccounts_Acc";
alter table public."DbDocumentRequestToNotifications" drop constraint "FK_public.DbDocumentRequestToNotifications_public.DbAccounts_Ac";
alter table public."DbPermissions" drop constraint ck_permission;
DROP TRIGGER tr_dbnode_insert ON "public"."DbNodes";
DROP TRIGGER tr_dbnode_update ON "public"."DbNodes";
DROP TRIGGER tr_dbroleclosures_insert ON "public"."DbRoleClosures";
DROP TRIGGER tr_dbrole_insert ON "public"."DbRoles";
DROP TRIGGER tr_dbrole_delete ON "public"."DbRoles";
DROP TRIGGER tr_dbrolerelationships_insert ON "public"."DbRoleRelationships";
DROP TRIGGER tr_dbrolerelationships_delete ON "public"."DbRoleRelationships";
DROP TRIGGER tr_dbrolerelationships_update ON "public"."DbRoleRelationships";
SELECT create_reference_table('"workflow"."DbAssetInstanceNodeReferences"');
SELECT create_reference_table('"workflow"."DbAssetNodeReference"');
SELECT create_reference_table('"workflow"."DbEventServiceInstancesInfo"');
SELECT create_reference_table('"workflow"."DbProfileRoutingRules"');
SELECT create_reference_table('"workflow"."DbStageApproveResults"');
SELECT create_reference_table('"workflow"."DbWorkflowAccountEmailConfig"');
SELECT create_reference_table('"workflow"."DbWorkflowAddTriggerStepEmailUserGroups"');
SELECT create_reference_table('"workflow"."DbWorkflowAddTriggerStepEmailUsers"');
SELECT create_reference_table('"workflow"."DbWorkflowAssetInstances"');
SELECT create_reference_table('"workflow"."DbWorkflowAssets"');
SELECT create_reference_table('"workflow"."DbWorkflowAssetsStages"');
SELECT create_reference_table('"workflow"."DbWorkflowAssetsStagesInstances"');
SELECT create_reference_table('"workflow"."DbWorkflowESignatureStepInstanceTemplateDocuments"');
SELECT create_reference_table('"workflow"."DbWorkflowESignatureStepInstanceUserReferences"');
SELECT create_reference_table('"workflow"."DbWorkflowESignatureStepTemplateDocuments"');
SELECT create_reference_table('"workflow"."DbWorkflowESignatureStepUserReferences"');
SELECT create_reference_table('"workflow"."DbWorkflowInstanceHistoryRecordTypes"');
SELECT create_reference_table('"workflow"."DbWorkflowInstanceHistoryRecords"');
SELECT create_reference_table('"workflow"."DbWorkflowInstanceStates"');
SELECT create_reference_table('"workflow"."DbWorkflowInstances"');
SELECT create_reference_table('"workflow"."DbWorkflowJobsQueue"');
SELECT create_reference_table('"workflow"."DbWorkflowNotificationConfigurations"');
SELECT create_reference_table('"workflow"."DbWorkflowOwnerGroups"');
SELECT create_reference_table('"workflow"."DbWorkflowOwners"');
SELECT create_reference_table('"workflow"."DbWorkflowRequestFileExternalStepInstanceNewUserReferences"');
SELECT create_reference_table('"workflow"."DbWorkflowRequestFileExternalStepInstanceRecipientGroups"');
SELECT create_reference_table('"workflow"."DbWorkflowRequestFileExternalStepInstanceRecipients"');
SELECT create_reference_table('"workflow"."DbWorkflowRequestFileExternalStepNewUserReferences"');
SELECT create_reference_table('"workflow"."DbWorkflowRequestFileExternalStepRecipientGroups"');
SELECT create_reference_table('"workflow"."DbWorkflowRequestFileExternalStepRecipients"');
SELECT create_reference_table('"workflow"."DbWorkflowScheduleConfigurations"');
SELECT create_reference_table('"workflow"."DbWorkflowSendMessageInstanceRecipients"');
SELECT create_reference_table('"workflow"."DbWorkflowSendMessageRecipients"');
SELECT create_reference_table('"workflow"."DbWorkflowSetPermissionsStepUserGroups"');
SELECT create_reference_table('"workflow"."DbWorkflowSetPermissionsStepUsers"');
SELECT create_reference_table('"workflow"."DbWorkflowSetProfileInstanceItemPresetValues"');
SELECT create_reference_table('"workflow"."DbWorkflowSetProfileInstanceItems"');
SELECT create_reference_table('"workflow"."DbWorkflowSetProfileItemPresetValues"');
SELECT create_reference_table('"workflow"."DbWorkflowSetProfileItems"');
SELECT create_reference_table('"workflow"."DbWorkflowShareStepInstanceNewUserReferences"');
SELECT create_reference_table('"workflow"."DbWorkflowShareStepNewUserReferences"');
SELECT create_reference_table('"workflow"."DbWorkflowStageApproverGroups"');
SELECT create_reference_table('"workflow"."DbWorkflowStageApprovers"');
SELECT create_reference_table('"workflow"."DbWorkflowStageAssigneeGroups"');
SELECT create_reference_table('"workflow"."DbWorkflowStageAssignees"');
SELECT create_reference_table('"workflow"."DbWorkflowStageInstances"');
SELECT create_reference_table('"workflow"."DbWorkflowStages"');
SELECT create_reference_table('"workflow"."DbWorkflowStarterGroups"');
SELECT create_reference_table('"workflow"."DbWorkflowStarters"');
SELECT create_reference_table('"workflow"."DbWorkflowStepDocumentRequestContainers"');
SELECT create_reference_table('"workflow"."DbWorkflowStepGroupReferences"');
SELECT create_reference_table('"workflow"."DbWorkflowStepInstanceDocumentRequestContainers"');
SELECT create_reference_table('"workflow"."DbWorkflowStepInstanceEmailUserGroups"');
SELECT create_reference_table('"workflow"."DbWorkflowStepInstanceEmailUsers"');
SELECT create_reference_table('"workflow"."DbWorkflowStepInstanceGroupReferences"');
SELECT create_reference_table('"workflow"."DbWorkflowStepInstanceUserGroups"');
SELECT create_reference_table('"workflow"."DbWorkflowStepInstanceUserReferences"');
SELECT create_reference_table('"workflow"."DbWorkflowStepInstanceUsers"');
SELECT create_reference_table('"workflow"."DbWorkflowStepInstances"');
SELECT create_reference_table('"workflow"."DbWorkflowStepTypes"');
SELECT create_reference_table('"workflow"."DbWorkflowStepUserReferences"');
SELECT create_reference_table('"workflow"."DbWorkflowSteps"');
SELECT create_reference_table('"workflow"."DbWorkflowWatcherGroups"');
SELECT create_reference_table('"workflow"."DbWorkflowWatchers"');
SELECT create_reference_table('"workflow"."DbWorkflows"');
SELECT create_reference_table('"workflow"."DbWorkflowsAvailableStates"');
SELECT create_reference_table('"public"."DbBrandings"');
SELECT create_reference_table('"public"."DbClientApplications"');
SELECT create_reference_table('"public"."DbComponentStatus"');
SELECT create_reference_table('"public"."DbComponentStatusHistories"');
SELECT create_reference_table('"public"."DbEmailSettingToUsers"');
SELECT create_reference_table('"public"."DbEmailSettings"');
SELECT create_reference_table('"public"."DbEmailTemplateToPartner"');
SELECT create_reference_table('"public"."DbEmailTemplates"');
SELECT create_reference_table('"public"."DbInstanceSettings"');
SELECT create_reference_table('"public"."DbPartners"');
SELECT create_reference_table('"public"."DbPortfolioToNodes"');
SELECT create_reference_table('"public"."DbPortfolioToUsers"');
SELECT create_reference_table('"public"."DbPortfolios"');
SELECT create_reference_table('"public"."DbResetPasswordRequests"');
SELECT create_reference_table('"public"."DbRightSignatureUsers"');
SELECT create_reference_table('"public"."DbSearchCriteria"');
SELECT create_reference_table('"public"."DbUserApplicationsMfa"');
SELECT create_reference_table('"public"."DbUserExternalAuthentications"');
SELECT create_reference_table('"public"."DbUserPasswordHistories"');
SELECT create_reference_table('"public"."DbUserSearchToSearchCriteria"');
SELECT create_reference_table('"public"."DbUserSearches"');
SELECT create_reference_table('"public"."DbUserSettings"');
SELECT create_reference_table('"public"."DbUsers"');
SELECT create_reference_table('"public"."DbUserSessions"');
SELECT create_distributed_table('"public"."DbNodeClosures"', 'AccountID');
SELECT create_distributed_table('"public"."DbAccountFeatures"', 'AccountID');
SELECT create_distributed_table('"public"."DbSecurityPolicies"', 'AccountID');
SELECT create_distributed_table('"public"."DbAuditLogsToNodeDetails"', 'AccountID');
SELECT create_distributed_table('"public"."DbAuditLogsToNodes"', 'AccountID');
SELECT create_distributed_table('"public"."DbAuditLogsToRoleDetails"', 'AccountID');
SELECT create_distributed_table('"public"."DbDocumentRequestAttachments"', 'AccountID');
SELECT create_distributed_table('"public"."DbEmailQueue"', 'AccountID');
SELECT create_distributed_table('"public"."DbEmailSettingToAccounts"', 'AccountID');
SELECT create_distributed_table('"public"."DbFileQueue"', 'AccountID');
SELECT create_distributed_table('"public"."DbNodeAnnotations"', 'AccountID');
SELECT create_distributed_table('"public"."DbNodeToFileInfoes"', 'AccountID');
SELECT create_distributed_table('"public"."DbProfiles"', 'AccountID');
SELECT create_distributed_table('"public"."DbPresetValues"', 'AccountID');
SELECT create_distributed_table('"public"."DbProfileItems"', 'AccountID');
SELECT create_distributed_table('"public"."DbProfileToProfileItems"', 'AccountID');
SELECT create_distributed_table('"public"."DbRetentionChangeReason"', 'AccountID');
SELECT create_distributed_table('"public"."DbSamlResponses"', 'AccountID');
SELECT create_distributed_table('"public"."DbSfLinks"', 'AccountID');
SELECT create_distributed_table('"public"."DbTriggerToNode"', 'AccountID');
SELECT create_distributed_table('"public"."DbAccountSettings"', 'AccountID');
SELECT create_distributed_table('"public"."DbProfileValueNodes"', 'AccountID');
SELECT create_distributed_table('"public"."DbAccessLinks"', 'AccountID');
SELECT create_distributed_table('"public"."DbDocumentRequests"', 'AccountID');
SELECT create_distributed_table('"public"."DbEmailImportMappings"', 'AccountID');
SELECT create_distributed_table('"public"."DbNodes"', 'AccountID');
SELECT create_distributed_table('"public"."DbAuditLogs"', 'AccountID');
SELECT create_distributed_table('"public"."DbAuditLogsToRoles"', 'AccountID');
SELECT create_distributed_table('"public"."DbDocumentRequestRoles"', 'AccountID');
SELECT create_distributed_table('"public"."DbESignatureTransactions"', 'AccountID');
SELECT create_distributed_table('"public"."DbNodeShares"', 'AccountID');
SELECT create_distributed_table('"public"."DbNotifications"', 'AccountID');
SELECT create_distributed_table('"public"."DbProfileValueRoles"', 'AccountID');
SELECT create_distributed_table('"public"."DbRoleToAccountFeatures"', 'AccountID');
SELECT create_distributed_table('"public"."DbSamlConfigurations"', 'AccountID');
SELECT create_distributed_table('"public"."DbTriggerToRoles"', 'AccountID');
SELECT create_distributed_table('"public"."DbUserRolePreferences"', 'AccountID');
SELECT create_distributed_table('"public"."DbUserImageStamps"', 'AccountID');
SELECT create_distributed_table('"public"."DbTemplateNodeLinks"', 'AccountID');
SELECT create_distributed_table('"public"."DbFileInfoes"', 'AccountID');
SELECT create_distributed_table('"public"."DbRoles"', 'AccountID');
SELECT create_distributed_table('"public"."DbSystemPermissions"', 'AccountID');
SELECT create_distributed_table('"public"."DbTriggers"', 'AccountID');
SELECT create_distributed_table('"public"."DbEmailContent"', 'AccountID');
SELECT create_distributed_table('"public"."DbEventTriggers"', 'AccountID');
SELECT create_distributed_table('"public"."DbWorkflowStageInstanceToNotifications"', 'AccountID');
SELECT create_distributed_table('"public"."DbRoleClosures"', 'AccountID');
SELECT create_distributed_table('"public"."DbRoleRelationships"', 'AccountID');
SELECT create_distributed_table('"public"."DbTimeTriggers"', 'AccountID');
SELECT create_distributed_table('"public"."DbTriggerInfoNodes"', 'AccountID');
SELECT create_distributed_table('"public"."DbTriggerToWorkflow"', 'AccountID');
SELECT create_distributed_table('"public"."DbEmailQueueAttachmentNodes"', 'AccountID');
SELECT create_distributed_table('"public"."DbTemplateNodeChangeLogs"', 'AccountID');
SELECT create_distributed_table('"public"."DbTriggerToSearchCriteria"', 'AccountID');
SELECT create_distributed_table('"public"."DbFormFillDefinitions"', 'AccountID');
SELECT create_distributed_table('"public"."DbAccessLinksToDocumentRequests"', 'AccountID');
SELECT create_distributed_table('"public"."DbAccessLinksToNodeAndTriggers"', 'AccountID');
SELECT create_distributed_table('"public"."DbESignatureSigners"', 'AccountID');
SELECT create_distributed_table('"public"."DbESignatureNodeAssociations"', 'AccountID');
SELECT create_distributed_table('"public"."DbFormFillPendings"', 'AccountID');
SELECT create_distributed_table('"public"."DbFormFillToProfileItems"', 'AccountID');
SELECT create_distributed_table('"public"."DbNodeComments"', 'AccountID');
SELECT create_distributed_table('"public"."DbSecurityPolicyIpAddresses"', 'AccountID');
SELECT create_distributed_table('"public"."DbSecurityPolicyLoginTimes"', 'AccountID');
SELECT create_distributed_table('"public"."DbTriggerToApiCallouts"', 'AccountID');
SELECT create_distributed_table('"public"."DbWatermarkTriggerInfo"', 'AccountID');
SELECT create_distributed_table('"public"."DbDocumentRequestContainerNodes"', 'AccountID');
SELECT create_distributed_table('"public"."DbDocumentRequestContainers"', 'AccountID');
SELECT create_distributed_table('"public"."DbLegacyNodeMappings"', 'AccountID');
SELECT create_distributed_table('"public"."DbDocumentRequestToNotifications"', 'AccountID');
SELECT create_distributed_table('"public"."DbSfMappings"', 'AccountID');
SELECT create_distributed_table('"public"."DbPermissions"', 'AccountID');
SELECT create_distributed_table('"public"."DbRightSignatureDocuments"', 'AccountID');
SELECT create_distributed_table('"public"."DbUserSessionToDbRoles"', 'AccountID');
SELECT create_distributed_table('"public"."DbEmailRecipients"', 'AccountID');
SELECT create_distributed_table('"DbAccounts"', 'Id');
alter table public."DbAccessLinks" add constraint "FK_DbAccounts" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbAccountFeatures" add constraint "FK_DbAccounts" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbAccountSettings" add constraint "FK_DbAccounts" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbAccountSettings" add constraint "FK_DbEmailSettings" FOREIGN KEY ("EmailSettingID") REFERENCES "DbEmailSettings"("Id");
alter table public."DbAccounts" add constraint "FK_BrandingID" FOREIGN KEY ("BrandingID") REFERENCES "DbBrandings"("Id");
alter table public."DbAuditLogs" add constraint "FK_DbAccounts" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbAuditLogsToNodeDetails" add constraint "FK_DbAccounts" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbAuditLogsToNodes" add constraint "FK_DbAccounts" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbAuditLogsToRoleDetails" add constraint "FK_DbAccounts" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbAuditLogsToRoles" add constraint "FK_DbAccounts" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbDocumentRequests" add constraint "FK_DbAccounts" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbESignatureTransactions" add constraint "FK_DbAccount" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbEmailImportMappings" add constraint "FK_AccountID" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbEmailImportMappings" add constraint "FK_EmailSettingID" FOREIGN KEY ("EmailSettingID") REFERENCES "DbEmailSettings"("Id");
alter table public."DbEmailQueue" add constraint fk_accounts FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbEmailQueue" add constraint fk_emailsettings FOREIGN KEY ("EmailSettingID") REFERENCES "DbEmailSettings"("Id");
alter table public."DbEmailSettingToAccounts" add constraint fk_account FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbEmailSettingToAccounts" add constraint fk_emailsetting FOREIGN KEY ("EmailSettingsID") REFERENCES "DbEmailSettings"("Id");
alter table public."DbEmailSettingToUsers" add constraint fk_emailsetting FOREIGN KEY ("EmailSettingsID") REFERENCES "DbEmailSettings"("Id");
alter table public."DbEmailTemplateToPartner" add constraint "FK_DbEmailTemplate" FOREIGN KEY ("EmailTemplateID") REFERENCES "DbEmailTemplates"("Id");
alter table public."DbFileInfoes" add constraint "FK_AccountID" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbFileQueue" add constraint "FK_Account" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbNodeAnnotations" add constraint fk_account FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbNodeClosures" add constraint "fk_accountID" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbAccessLinksToDocumentRequests" add constraint "FK_public.DbAccessLinksToDocumentRequests_public.DbAccessLinks_" FOREIGN KEY ("AccessLinkID", "AccountID") REFERENCES "DbAccessLinks"("Id", "AccountID");
alter table public."DbAccessLinksToNodeAndTriggers" add constraint "FK_public.DbAccessLinksToNodeAndTriggers_public.DbAccessLinks_A" FOREIGN KEY ("AccessLinkID", "AccountID") REFERENCES "DbAccessLinks"("Id", "AccountID");
alter table public."DbAccessLinks" add constraint "FK_public.DbAccessLinks_public.DbRoles_RoleID_AccountID" FOREIGN KEY ("RoleID", "AccountID") REFERENCES "DbRoles"("Id", "AccountID");
alter table public."DbAccessLinksToDocumentRequests" add constraint "FK_public.DbAccessLinksToDocumentRequests_public.DbDocumentRequ" FOREIGN KEY ("DocumentRequestID", "AccountID") REFERENCES "DbDocumentRequests"("Id", "AccountID") ON DELETE CASCADE;
alter table public."DbAccountSettings" add constraint "FK_public.DbAccountSettings_public.DbSecurityPolicies_DefaultGu" FOREIGN KEY ("DefaultGuestSecurityPolicyID", "AccountID") REFERENCES "DbSecurityPolicies"("Id", "AccountID");
alter table public."DbAccountSettings" add constraint "FK_public.DbAccountSettings_public.DbSecurityPolicies_DefaultUs" FOREIGN KEY ("DefaultUserSecurityPolicyID", "AccountID") REFERENCES "DbSecurityPolicies"("Id", "AccountID");
alter table public."DbEmailImportMappings" add constraint "FK_public.DbEmailImportMappings_public.DbNodes_NodeID_AccountID" FOREIGN KEY ("NodeID", "AccountID") REFERENCES "DbNodes"("Id", "AccountID");
alter table public."DbAccessLinksToNodeAndTriggers" add constraint "FK_public.DbAccessLinksToNodeAndTriggers_public.DbNodes_NodeID_" FOREIGN KEY ("NodeID", "AccountID") REFERENCES "DbNodes"("Id", "AccountID");
alter table public."DbAuditLogsToNodes" add constraint "FK_public.DbAuditLogsToNodes_public.DbNodes_NodeID_AccountID" FOREIGN KEY ("NodeID", "AccountID") REFERENCES "DbNodes"("Id", "AccountID");
alter table public."DbNodeShares" add constraint fk_account FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbNodeToFileInfoes" add constraint "FK_DbAccounts" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbNodes" add constraint fk_account FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbNotifications" add constraint "FK_DbAccounts" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbPartners" add constraint "FK_BrandingID" FOREIGN KEY ("BrandingID") REFERENCES "DbBrandings"("Id");
alter table public."DbPermissions" add constraint fk_account FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbPortfolioToNodes" add constraint "FK_DbPortfolios" FOREIGN KEY ("PortfolioID") REFERENCES "DbPortfolios"("Id");
alter table public."DbPortfolioToUsers" add constraint "FK_DbPortfolios" FOREIGN KEY ("PortfolioID") REFERENCES "DbPortfolios"("Id");
alter table public."DbPresetValues" add constraint "FK_Account" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbProfileItems" add constraint fk_account FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbProfiles" add constraint fk_account FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbRetentionChangeReason" add constraint "FK_DbAccount" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbRoles" add constraint "FK_DbAccounts" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbSamlConfigurations" add constraint "FK_DbAccounts" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbSamlResponses" add constraint "FK_DbAccounts" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbSearchCriteria" add constraint "fk_parentUserSearchCriteria" FOREIGN KEY ("ParentUserSearchCriteriaId") REFERENCES "DbSearchCriteria"("Id");
alter table public."DbSecurityPolicies" add constraint "FK_DbAccounts" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbSfLinks" add constraint "FK_DbAccounts" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbSfMappings" add constraint "FK_DbAccounts" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbTriggerToSearchCriteria" add constraint "FK_DbSearchCriteria" FOREIGN KEY ("SearchCriteriaID") REFERENCES "DbSearchCriteria"("Id");
alter table public."DbUserImageStamps" add constraint "FK_DbAccounts" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbUserSearchToSearchCriteria" add constraint "FK_DbSearchCriteria" FOREIGN KEY ("SearchCriteriaId") REFERENCES "DbSearchCriteria"("Id");
alter table public."DbUserSearchToSearchCriteria" add constraint "FK_DbUserSearches" FOREIGN KEY ("UserSearchId") REFERENCES "DbUserSearches"("Id");
alter table public."DbUserSettings" add constraint "FK_DbEmailSettings" FOREIGN KEY ("EmailSettingID") REFERENCES "DbEmailSettings"("Id");
alter table public."DbUserSettings" add constraint "FK_DbPortfolios" FOREIGN KEY ("DefaultPortfolioID") REFERENCES "DbPortfolios"("Id");
alter table public."DbUsers" add constraint "FK_DbUserSettings" FOREIGN KEY ("UserSettingsID") REFERENCES "DbUserSettings"("Id");
alter table workflow."DbWorkflowInstanceHistoryRecords" add constraint "FK_DbWorkflowInstanceHistoryRecordTypes_RecordTypeID" FOREIGN KEY ("RecordTypeID") REFERENCES workflow."DbWorkflowInstanceHistoryRecordTypes"("Id");
alter table workflow."DbWorkflowSteps" add constraint "FK_DbWorkflowStepTypes_TypeID" FOREIGN KEY ("TypeID") REFERENCES workflow."DbWorkflowStepTypes"("Id");
alter table public."DbDocumentRequestContainers" add constraint "DbFileRequestContainers_check" CHECK ("Rename" = false OR "Rename" = true AND "IsMultiple" = false);
alter table public."DbDocumentRequests" add constraint "DbFileRequests_check" CHECK ("IsTemplate" = true OR "IsTemplate" = false AND "DestinationNodeID" IS NOT NULL);
alter table public."DbTimeTriggers" add constraint "check_timeTrigger_preActionNotificationTimeSpanInDays" CHECK ("PreActionNotificationTimeSpanInDays" <= 365);
alter table public."DbTimeTriggers" add constraint "check_timeTrigger_timeSpanInSeconds" CHECK ("TimeSpanInSeconds"::numeric <= '220898664000'::numeric);
alter table public."DbComponentStatusHistories" add constraint "FK_public.DbComponentStatusHistories_public.DbComponentStatus_C" FOREIGN KEY ("ComponentStatusId") REFERENCES "DbComponentStatus"("Id") ON DELETE CASCADE;
alter table public."DbDocumentRequestAttachments" add constraint "FK_public.DbDocumentRequestAttachments_public.DbNodes_Attachmen" FOREIGN KEY ("AttachmentNodeID", "AccountID") REFERENCES "DbNodes"("Id", "AccountID");
alter table public."DbDocumentRequestContainerNodes" add constraint "FK_public.DbDocumentRequestContainerNodes_public.DbNodes_NodeID" FOREIGN KEY ("NodeID", "AccountID") REFERENCES "DbNodes"("Id", "AccountID");
alter table public."DbDocumentRequests" add constraint "FK_public.DbDocumentRequests_public.DbNodes_DestinationNodeID_A" FOREIGN KEY ("DestinationNodeID", "AccountID") REFERENCES "DbNodes"("Id", "AccountID");
alter table public."DbEmailQueueAttachmentNodes" add constraint "FK_public.DbEmailQueueAttachmentNodes_public.DbNodes_NodeID_Acc" FOREIGN KEY ("NodeID", "AccountID") REFERENCES "DbNodes"("Id", "AccountID");
alter table public."DbESignatureNodeAssociations" add constraint "FK_public.DbESignatureNodeAssociations_public.DbNodes_OriginalN" FOREIGN KEY ("OriginalNodeID", "AccountID") REFERENCES "DbNodes"("Id", "AccountID");
alter table public."DbESignatureNodeAssociations" add constraint "FK_public.DbESignatureNodeAssociations_public.DbNodes_SignedNod" FOREIGN KEY ("SignedNodeID", "AccountID") REFERENCES "DbNodes"("Id", "AccountID");
alter table public."DbESignatureTransactions" add constraint "FK_public.DbESignatureTransactions_public.DbNodes_AuditTrailNod" FOREIGN KEY ("AuditTrailNodeID", "AccountID") REFERENCES "DbNodes"("Id", "AccountID");
alter table public."DbESignatureTransactions" add constraint "FK_public.DbESignatureTransactions_public.DbNodes_AuditTrailPar" FOREIGN KEY ("AuditTrailParentNodeID", "AccountID") REFERENCES "DbNodes"("Id", "AccountID");
alter table public."DbESignatureTransactions" add constraint "FK_public.DbESignatureTransactions_public.DbNodes_SignedDocumen" FOREIGN KEY ("SignedDocumentParentNodeID", "AccountID") REFERENCES "DbNodes"("Id", "AccountID");
alter table public."DbNodes" add constraint "FK_public.DbNodes_public.DbFileInfoes_FileInfoID_AccountID" FOREIGN KEY ("FileInfoID", "AccountID") REFERENCES "DbFileInfoes"("Id", "AccountID");
alter table public."DbFileQueue" add constraint "FK_public.DbFileQueue_public.DbNodes_NodeID_AccountID" FOREIGN KEY ("NodeID", "AccountID") REFERENCES "DbNodes"("Id", "AccountID");
alter table public."DbLegacyNodeMappings" add constraint "FK_public.DbLegacyNodeMappings_public.DbNodes_NodeId_AccountID" FOREIGN KEY ("NodeId", "AccountID") REFERENCES "DbNodes"("Id", "AccountID");
alter table public."DbNodes" add constraint "FK_public.DbNodes_public.DbNodes_ParentID_AccountID" FOREIGN KEY ("ParentID", "AccountID") REFERENCES "DbNodes"("Id", "AccountID");
alter table public."DbNodeAnnotations" add constraint "FK_public.DbNodeAnnotations_public.DbNodes_NodeID_AccountID" FOREIGN KEY ("NodeID", "AccountID") REFERENCES "DbNodes"("Id", "AccountID");
alter table public."DbNodeClosures" add constraint "FK_public.DbNodeClosures_public.DbNodes_ChildID_AccountID" FOREIGN KEY ("ChildID", "AccountID") REFERENCES "DbNodes"("Id", "AccountID");
alter table public."DbRoleRelationships" add constraint "Parent_Is_Group" CHECK ("func_RoleIsGroup"("ParentRoleID") = true);
alter table public."DbAccessLinks" add constraint "FK_public.DbAccessLinks_public.DbUsers_CreatedByUserID" FOREIGN KEY ("CreatedByUserID") REFERENCES "DbUsers"("Id");
alter table public."DbAuditLogs" add constraint "FK_public.DbAuditLogs_public.DbUsers_UserID" FOREIGN KEY ("UserID") REFERENCES "DbUsers"("Id");
alter table public."DbAuditLogs" add constraint "FK_public.DbAuditLogs_public.DbUsers_GeneratedByUserID" FOREIGN KEY ("GeneratedByUserID") REFERENCES "DbUsers"("Id");
alter table public."DbDocumentRequests" add constraint "FK_public.DbDocumentRequests_public.DbUsers_CreatedByUserID" FOREIGN KEY ("CreatedByUserID") REFERENCES "DbUsers"("Id");
alter table public."DbEmailImportMappings" add constraint "FK_public.DbEmailImportMappings_public.DbUsers_CreatedByUserID" FOREIGN KEY ("CreatedByUserID") REFERENCES "DbUsers"("Id");
alter table public."DbESignatureTransactions" add constraint "FK_public.DbESignatureTransactions_public.DbUsers_UserID" FOREIGN KEY ("UserID") REFERENCES "DbUsers"("Id");
alter table public."DbFileInfoes" add constraint "FK_public.DbFileInfoes_public.DbUsers_CreatedByUserID" FOREIGN KEY ("CreatedByUserID") REFERENCES "DbUsers"("Id");
alter table public."DbNodeComments" add constraint "FK_public.DbNodeComments_public.DbUsers_LastModifiedByUserID" FOREIGN KEY ("LastModifiedByUserID") REFERENCES "DbUsers"("Id");
alter table public."DbNodeComments" add constraint "FK_public.DbNodeComments_public.DbUsers_CreatedByUserID" FOREIGN KEY ("CreatedByUserID") REFERENCES "DbUsers"("Id");
alter table public."DbNodes" add constraint "FK_public.DbNodes_public.DbUsers_CreatedByUserID" FOREIGN KEY ("CreatedByUserID") REFERENCES "DbUsers"("Id");
alter table public."DbPortfolios" add constraint "FK_public.DbPortfolios_public.DbUsers_OwnerUserID" FOREIGN KEY ("OwnerUserID") REFERENCES "DbUsers"("Id");
alter table public."DbPortfolioToNodes" add constraint "FK_public.DbPortfolioToNodes_public.DbUsers_AddedByUserID" FOREIGN KEY ("AddedByUserID") REFERENCES "DbUsers"("Id");
alter table public."DbPortfolioToUsers" add constraint "FK_public.DbPortfolioToUsers_public.DbUsers_UserID" FOREIGN KEY ("UserID") REFERENCES "DbUsers"("Id");
alter table public."DbResetPasswordRequests" add constraint "FK_public.DbResetPasswordRequests_public.DbUsers_UserID" FOREIGN KEY ("UserID") REFERENCES "DbUsers"("Id");
alter table public."DbRightSignatureUsers" add constraint "FK_public.DbRightSignatureUsers_public.DbUsers_UserID" FOREIGN KEY ("UserID") REFERENCES "DbUsers"("Id");
alter table public."DbRoles" add constraint "FK_public.DbRoles_public.DbUsers_UserID" FOREIGN KEY ("UserID") REFERENCES "DbUsers"("Id");
alter table public."DbSamlConfigurations" add constraint "FK_public.DbSamlConfigurations_public.DbUsers_CreatedByUserID" FOREIGN KEY ("CreatedByUserID") REFERENCES "DbUsers"("Id");
alter table public."DbTriggers" add constraint "FK_public.DbTriggers_public.DbUsers_CreatedByUserID" FOREIGN KEY ("CreatedByUserID") REFERENCES "DbUsers"("Id");
alter table public."DbUserApplicationsMfa" add constraint "FK_public.DbUserApplicationsMfa_public.DbUsers_UserID" FOREIGN KEY ("UserID") REFERENCES "DbUsers"("Id");
alter table public."DbUserExternalAuthentications" add constraint "FK_public.DbUserExternalAuthentications_public.DbUsers_UserID" FOREIGN KEY ("UserID") REFERENCES "DbUsers"("Id");
alter table public."DbUserImageStamps" add constraint "FK_public.DbUserImageStamps_public.DbUsers_UserID" FOREIGN KEY ("UserID") REFERENCES "DbUsers"("Id");
alter table public."DbUserPasswordHistories" add constraint "FK_public.DbUserPasswordHistories_public.DbUsers_UserID" FOREIGN KEY ("UserID") REFERENCES "DbUsers"("Id");
alter table public."DbUserSearches" add constraint "FK_public.DbUserSearches_public.DbUsers_UserID" FOREIGN KEY ("UserID") REFERENCES "DbUsers"("Id");
alter table public."DbUserSessions" add constraint "FK_public.DbUserSessions_public.DbUsers_UserID" FOREIGN KEY ("UserID") REFERENCES "DbUsers"("Id");
alter table public."DbUserSessions" add constraint "FK_public.DbUserSessions_public.DbUsers_GeneratedByUserID" FOREIGN KEY ("GeneratedByUserID") REFERENCES "DbUsers"("Id");
alter table public."DbEmailSettingToUsers" add constraint "FK_public.DbEmailSettingToUsers_public.DbUsers_UserID" FOREIGN KEY ("UserID") REFERENCES "DbUsers"("Id") ON DELETE CASCADE;
alter table public."DbRightSignatureDocuments" add constraint "FK_public.DbRightSignatureDocuments_public.DbRightSignatureUser" FOREIGN KEY ("SenderUserID") REFERENCES "DbRightSignatureUsers"("UserID");
alter table public."DbFormFillPendings" add constraint "FK_public.DbFormFillPendings_public.DbUsers_UserID" FOREIGN KEY ("UserID") REFERENCES "DbUsers"("Id");
alter table workflow."DbWorkflowStepInstances" add constraint "FK_workflow.DbWorkflowStepInstances_workflow.DbWorkflowSteps_Db" FOREIGN KEY ("DbWorkflowStepID") REFERENCES workflow."DbWorkflowSteps"("Id");
alter table workflow."DbWorkflowInstances" add constraint "FK_workflow.DbWorkflowInstances_workflow.DbWorkflowInstanceStat" FOREIGN KEY ("StateID") REFERENCES workflow."DbWorkflowInstanceStates"("Id");
alter table workflow."DbStageApproveResults" add constraint "FK_workflow.DbStageApproveResults_workflow.DbWorkflowStageInsta" FOREIGN KEY ("StageInstanceID") REFERENCES workflow."DbWorkflowStageInstances"("Id");
alter table workflow."DbWorkflowStepInstances" add constraint "FK_workflow.DbWorkflowStepInstances_workflow.DbWorkflowAssetI1" FOREIGN KEY ("requestFileExternal_AttachmentAssetID") REFERENCES workflow."DbWorkflowAssetInstances"("Id");
alter table workflow."DbWorkflowStepInstances" add constraint "FK_workflow.DbWorkflowStepInstances_workflow.DbWorkflowAssetI2" FOREIGN KEY ("addTrigger_DestinationAssetID") REFERENCES workflow."DbWorkflowAssetInstances"("Id");
alter table workflow."DbWorkflowStepInstances" add constraint "FK_workflow.DbWorkflowStepInstances_workflow.DbWorkflowAssetI3" FOREIGN KEY ("addTrigger_TargetAssetID") REFERENCES workflow."DbWorkflowAssetInstances"("Id");
alter table workflow."DbWorkflowStepInstances" add constraint "FK_workflow.DbWorkflowStepInstances_workflow.DbWorkflowAssetI4" FOREIGN KEY ("applyTemplate_TargetPathAssetID") REFERENCES workflow."DbWorkflowAssetInstances"("Id");
alter table workflow."DbWorkflowStepInstances" add constraint "FK_workflow.DbWorkflowStepInstances_workflow.DbWorkflowAssetI5" FOREIGN KEY ("comment_TargetAssetID") REFERENCES workflow."DbWorkflowAssetInstances"("Id");
alter table workflow."DbWorkflowStepInstances" add constraint "FK_workflow.DbWorkflowStepInstances_workflow.DbWorkflowAssetI6" FOREIGN KEY ("copy_DestinationAssetID") REFERENCES workflow."DbWorkflowAssetInstances"("Id");
alter table workflow."DbWorkflowStepInstances" add constraint "FK_workflow.DbWorkflowStepInstances_workflow.DbWorkflowAssetI7" FOREIGN KEY ("copy_ResultAssetID") REFERENCES workflow."DbWorkflowAssetInstances"("Id");
alter table workflow."DbWorkflowStepInstances" add constraint "FK_workflow.DbWorkflowStepInstances_workflow.DbWorkflowAssetI8" FOREIGN KEY ("copy_SourceAssetID") REFERENCES workflow."DbWorkflowAssetInstances"("Id");
alter table workflow."DbWorkflowStepInstances" add constraint "FK_workflow.DbWorkflowStepInstances_workflow.DbWorkflowAssetI9" FOREIGN KEY ("createLocation_ResultAssetID") REFERENCES workflow."DbWorkflowAssetInstances"("Id");
alter table workflow."DbWorkflowStepInstances" add constraint "FK_workflow.DbWorkflowStepInstances_workflow.DbWorkflowAsset10" FOREIGN KEY ("createLocation_SourceAssetID") REFERENCES workflow."DbWorkflowAssetInstances"("Id");
alter table workflow."DbWorkflowStepInstances" add constraint "FK_workflow.DbWorkflowStepInstances_workflow.DbWorkflowAsset11" FOREIGN KEY ("delete_TargetAssetID") REFERENCES workflow."DbWorkflowAssetInstances"("Id");
alter table workflow."DbWorkflowStepInstances" add constraint "FK_workflow.DbWorkflowStepInstances_workflow.DbWorkflowAsset12" FOREIGN KEY ("esignature_AuditTrailAssetID") REFERENCES workflow."DbWorkflowAssetInstances"("Id");
alter table workflow."DbWorkflowStepInstances" add constraint "FK_workflow.DbWorkflowStepInstances_workflow.DbWorkflowAsset14" FOREIGN KEY ("esignature_AuditTrailDestinationAssetID") REFERENCES workflow."DbWorkflowAssetInstances"("Id");
alter table workflow."DbWorkflowStepInstances" add constraint "FK_workflow.DbWorkflowStepInstances_workflow.DbWorkflowAsset15" FOREIGN KEY ("esignature_SignedResultAssetID") REFERENCES workflow."DbWorkflowAssetInstances"("Id");
alter table workflow."DbWorkflowStepInstances" add constraint "FK_workflow.DbWorkflowStepInstances_workflow.DbWorkflowAsset16" FOREIGN KEY ("esignature_SignedResultDestinationAssetID") REFERENCES workflow."DbWorkflowAssetInstances"("Id");
alter table workflow."DbWorkflowESignatureStepInstanceUserReferences" add constraint "FK_workflow.DbWorkflowESignatureStepInstanceUserReferences_wor1" FOREIGN KEY ("AssetID") REFERENCES workflow."DbWorkflowAssetInstances"("Id");
alter table workflow."DbWorkflowStepInstances" add constraint "FK_workflow.DbWorkflowStepInstances_workflow.DbWorkflowAsset17" FOREIGN KEY ("esignature_SourceAssetID") REFERENCES workflow."DbWorkflowAssetInstances"("Id");
alter table workflow."DbWorkflowESignatureStepInstanceTemplateDocuments" add constraint "FK_workflow.DbWorkflowESignatureStepInstanceTemplateDocuments_1" FOREIGN KEY ("SourceAssetID") REFERENCES workflow."DbWorkflowAssetInstances"("Id");
alter table workflow."DbWorkflowStepInstances" add constraint "FK_workflow.DbWorkflowStepInstances_workflow.DbWorkflowAsset18" FOREIGN KEY ("move_DestinationAssetID") REFERENCES workflow."DbWorkflowAssetInstances"("Id");
alter table workflow."DbWorkflowStepInstances" add constraint "FK_workflow.DbWorkflowStepInstances_workflow.DbWorkflowAsset19" FOREIGN KEY ("move_SourceAssetID") REFERENCES workflow."DbWorkflowAssetInstances"("Id");
alter table workflow."DbWorkflowStepInstances" add constraint "FK_workflow.DbWorkflowStepInstances_workflow.DbWorkflowAsset20" FOREIGN KEY ("rename_TargetAssetID") REFERENCES workflow."DbWorkflowAssetInstances"("Id");
alter table workflow."DbWorkflowStepInstances" add constraint "FK_workflow.DbWorkflowStepInstances_workflow.DbWorkflowAsset21" FOREIGN KEY ("sendMessage_AttachmentAssetID") REFERENCES workflow."DbWorkflowAssetInstances"("Id");
alter table workflow."DbWorkflowStepInstances" add constraint "FK_workflow.DbWorkflowStepInstances_workflow.DbWorkflowAsset22" FOREIGN KEY ("setPermissions_SourceAssetID") REFERENCES workflow."DbWorkflowAssetInstances"("Id");
alter table workflow."DbWorkflowStepInstances" add constraint "FK_workflow.DbWorkflowStepInstances_workflow.DbWorkflowAsset23" FOREIGN KEY ("setProfile_TargetAssetID") REFERENCES workflow."DbWorkflowAssetInstances"("Id");
alter table workflow."DbWorkflowStepInstances" add constraint "FK_workflow.DbWorkflowStepInstances_workflow.DbWorkflowAsset24" FOREIGN KEY ("setRetention_DestinationAssetID") REFERENCES workflow."DbWorkflowAssetInstances"("Id");
alter table workflow."DbWorkflowStepInstances" add constraint "FK_workflow.DbWorkflowStepInstances_workflow.DbWorkflowAsset25" FOREIGN KEY ("setRetention_TargetAssetID") REFERENCES workflow."DbWorkflowAssetInstances"("Id");
alter table workflow."DbWorkflowStepInstances" add constraint "FK_workflow.DbWorkflowStepInstances_workflow.DbWorkflowAsset26" FOREIGN KEY ("share_SourceAssetID") REFERENCES workflow."DbWorkflowAssetInstances"("Id");
alter table workflow."DbWorkflowStepInstances" add constraint "FK_workflow.DbWorkflowStepInstances_workflow.DbWorkflowAsset27" FOREIGN KEY ("upload_ResultAssetID") REFERENCES workflow."DbWorkflowAssetInstances"("Id");
alter table workflow."DbWorkflowStepInstances" add constraint "FK_workflow.DbWorkflowStepInstances_workflow.DbWorkflowAsset28" FOREIGN KEY ("upload_SourceAssetID") REFERENCES workflow."DbWorkflowAssetInstances"("Id");
alter table workflow."DbWorkflowStepInstances" add constraint "FK_workflow.DbWorkflowStepInstances_workflow.DbWorkflowAsset29" FOREIGN KEY ("requestFileExternal_DestinationAssetID") REFERENCES workflow."DbWorkflowAssetInstances"("Id");
alter table workflow."DbWorkflowStepInstanceDocumentRequestContainers" add constraint "FK_workflow.DbWorkflowStepInstanceDocumentRequestContainers_wo1" FOREIGN KEY ("AssetInstanceID") REFERENCES workflow."DbWorkflowAssetInstances"("Id");
alter table workflow."DbAssetInstanceNodeReferences" add constraint "FK_workflow.DbAssetInstanceNodeReferences_workflow.DbWorkflowAs" FOREIGN KEY ("AssetInstanceID") REFERENCES workflow."DbWorkflowAssetInstances"("Id");
alter table workflow."DbWorkflowAssetsStagesInstances" add constraint "FK_workflow.DbWorkflowAssetsStagesInstances_workflow.DbWorkflo1" FOREIGN KEY ("AssetID") REFERENCES workflow."DbWorkflowAssetInstances"("Id");
alter table workflow."DbWorkflowStepInstanceEmailUserGroups" add constraint "FK_workflow.DbWorkflowStepInstanceEmailUserGroups_workflow.DbWo" FOREIGN KEY ("WorkflowAddTriggerStepInstanceID") REFERENCES workflow."DbWorkflowStepInstances"("Id");
alter table workflow."DbWorkflowStepInstanceEmailUsers" add constraint "FK_workflow.DbWorkflowStepInstanceEmailUsers_workflow.DbWorkflo" FOREIGN KEY ("WorkflowAddTriggerStepInstanceID") REFERENCES workflow."DbWorkflowStepInstances"("Id");
alter table workflow."DbWorkflowESignatureStepInstanceUserReferences" add constraint "FK_workflow.DbWorkflowESignatureStepInstanceUserReferences_wor2" FOREIGN KEY ("StepInstanceID") REFERENCES workflow."DbWorkflowStepInstances"("Id");
alter table workflow."DbWorkflowESignatureStepInstanceTemplateDocuments" add constraint "FK_workflow.DbWorkflowESignatureStepInstanceTemplateDocuments_2" FOREIGN KEY ("StepInstanceID") REFERENCES workflow."DbWorkflowStepInstances"("Id");
alter table workflow."DbWorkflowSendMessageInstanceRecipients" add constraint "FK_workflow.DbWorkflowSendMessageInstanceRecipients_workflow.Db" FOREIGN KEY ("StepInstanceID") REFERENCES workflow."DbWorkflowStepInstances"("Id");
alter table workflow."DbWorkflowStepInstanceUserGroups" add constraint "FK_workflow.DbWorkflowStepInstanceUserGroups_workflow.DbWorkflo" FOREIGN KEY ("WorkflowSetPermissionsStepInstanceID") REFERENCES workflow."DbWorkflowStepInstances"("Id");
alter table workflow."DbWorkflowStepInstanceUsers" add constraint "FK_workflow.DbWorkflowStepInstanceUsers_workflow.DbWorkflowStep" FOREIGN KEY ("WorkflowSetPermissionsStepInstanceID") REFERENCES workflow."DbWorkflowStepInstances"("Id");
alter table workflow."DbWorkflowSetProfileInstanceItems" add constraint "FK_workflow.DbWorkflowSetProfileInstanceItems_workflow.DbWorkfl" FOREIGN KEY ("StepInstanceID") REFERENCES workflow."DbWorkflowStepInstances"("Id");
alter table workflow."DbWorkflowShareStepInstanceNewUserReferences" add constraint "FK_workflow.DbWorkflowShareStepInstanceNewUserReferences_workfl" FOREIGN KEY ("StepInstanceID") REFERENCES workflow."DbWorkflowStepInstances"("Id");
alter table workflow."DbWorkflowStepInstanceGroupReferences" add constraint "FK_workflow.DbWorkflowStepInstanceGroupReferences_workflow.DbWo" FOREIGN KEY ("StepInstanceID") REFERENCES workflow."DbWorkflowStepInstances"("Id");
alter table workflow."DbWorkflowStepInstanceUserReferences" add constraint "FK_workflow.DbWorkflowStepInstanceUserReferences_workflow.DbWor" FOREIGN KEY ("StepInstanceID") REFERENCES workflow."DbWorkflowStepInstances"("Id");
alter table workflow."DbWorkflowInstanceHistoryRecords" add constraint "FK_workflow.DbWorkflowInstanceHistoryRecords_workflow.DbWorkfl1" FOREIGN KEY ("StepInstanceID") REFERENCES workflow."DbWorkflowStepInstances"("Id");
alter table workflow."DbWorkflowStepInstanceDocumentRequestContainers" add constraint "FK_workflow.DbWorkflowStepInstanceDocumentRequestContainers_wo2" FOREIGN KEY ("StepInstanceID") REFERENCES workflow."DbWorkflowStepInstances"("Id");
alter table workflow."DbWorkflowRequestFileExternalStepInstanceRecipientGroups" add constraint "FK_workflow.DbWorkflowRequestFileExternalStepInstanceRecipientG" FOREIGN KEY ("WorkflowStepInstanceID") REFERENCES workflow."DbWorkflowStepInstances"("Id");
alter table workflow."DbWorkflowRequestFileExternalStepInstanceNewUserReferences" add constraint "FK_workflow.DbWorkflowRequestFileExternalStepInstanceNewUserRef" FOREIGN KEY ("StepInstanceID") REFERENCES workflow."DbWorkflowStepInstances"("Id");
alter table workflow."DbWorkflowRequestFileExternalStepInstanceRecipients" add constraint "FK_workflow.DbWorkflowRequestFileExternalStepInstanceRecipients" FOREIGN KEY ("WorkflowStepInstanceID") REFERENCES workflow."DbWorkflowStepInstances"("Id");
alter table workflow."DbWorkflowStepDocumentRequestContainers" add constraint "FK_workflow.DbWorkflowStepDocumentRequestContainers_workflow.D1" FOREIGN KEY ("StepID") REFERENCES workflow."DbWorkflowSteps"("Id");
alter table workflow."DbWorkflowRequestFileExternalStepRecipientGroups" add constraint "FK_workflow.DbWorkflowRequestFileExternalStepRecipientGroups_wo" FOREIGN KEY ("WorkflowStepID") REFERENCES workflow."DbWorkflowSteps"("Id");
alter table workflow."DbWorkflowRequestFileExternalStepNewUserReferences" add constraint "FK_workflow.DbWorkflowRequestFileExternalStepNewUserReferences_" FOREIGN KEY ("StepID") REFERENCES workflow."DbWorkflowSteps"("Id");
alter table workflow."DbWorkflowRequestFileExternalStepRecipients" add constraint "FK_workflow.DbWorkflowRequestFileExternalStepRecipients_workflo" FOREIGN KEY ("WorkflowStepID") REFERENCES workflow."DbWorkflowSteps"("Id");
alter table workflow."DbWorkflowAddTriggerStepEmailUserGroups" add constraint "FK_workflow.DbWorkflowAddTriggerStepEmailUserGroups_workflow.Db" FOREIGN KEY ("WorkflowStepID") REFERENCES workflow."DbWorkflowSteps"("Id");
alter table workflow."DbWorkflowAddTriggerStepEmailUsers" add constraint "FK_workflow.DbWorkflowAddTriggerStepEmailUsers_workflow.DbWorkf" FOREIGN KEY ("WorkflowStepID") REFERENCES workflow."DbWorkflowSteps"("Id");
alter table workflow."DbWorkflowESignatureStepUserReferences" add constraint "FK_workflow.DbWorkflowESignatureStepUserReferences_workflow.DbW" FOREIGN KEY ("StepID") REFERENCES workflow."DbWorkflowSteps"("Id");
alter table workflow."DbWorkflowESignatureStepTemplateDocuments" add constraint "FK_workflow.DbWorkflowESignatureStepTemplateDocuments_workflow1" FOREIGN KEY ("StepID") REFERENCES workflow."DbWorkflowSteps"("Id");
alter table workflow."DbWorkflowSendMessageRecipients" add constraint "FK_workflow.DbWorkflowSendMessageRecipients_workflow.DbWorkflow" FOREIGN KEY ("StepID") REFERENCES workflow."DbWorkflowSteps"("Id");
alter table workflow."DbWorkflowSetPermissionsStepUserGroups" add constraint "FK_workflow.DbWorkflowSetPermissionsStepUserGroups_workflow.DbW" FOREIGN KEY ("WorkflowStepID") REFERENCES workflow."DbWorkflowSteps"("Id");
alter table workflow."DbWorkflowSetPermissionsStepUsers" add constraint "FK_workflow.DbWorkflowSetPermissionsStepUsers_workflow.DbWorkfl" FOREIGN KEY ("WorkflowStepID") REFERENCES workflow."DbWorkflowSteps"("Id");
alter table public."DbNodeClosures" add constraint "FK_public.DbNodeClosures_public.DbNodes_ParentID_AccountID" FOREIGN KEY ("ParentID", "AccountID") REFERENCES "DbNodes"("Id", "AccountID");
alter table public."DbTriggers" add constraint "FK_public.DbTriggers_public.DbAccounts_AccountID" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbEmailContent" add constraint "FK_public.DbEmailContent_public.DbAccounts_AccountID" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbEventTriggers" add constraint "FK_public.DbEventTriggers_public.DbAccounts_AccountID" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbTimeTriggers" add constraint "FK_public.DbTimeTriggers_public.DbAccounts_AccountID" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbTriggerInfoNodes" add constraint "FK_public.DbTriggerInfoNodes_public.DbAccounts_AccountID" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbTriggerToNode" add constraint "FK_public.DbTriggerToNode_public.DbAccounts_AccountID" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbTriggerToWorkflow" add constraint "FK_public.DbTriggerToWorkflow_public.DbAccounts_AccountID" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbTriggerToRoles" add constraint "FK_public.DbTriggerToRoles_public.DbAccounts_AccountID" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbTriggerToSearchCriteria" add constraint "FK_public.DbTriggerToSearchCriteria_public.DbAccounts_AccountID" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbProfileValueNodes" add constraint "FK_public.DbProfileValueNodes_public.DbAccounts_AccountID" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbProfileToProfileItems" add constraint "FK_public.DbProfileToProfileItems_public.DbAccounts_AccountID" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbProfileValueRoles" add constraint "FK_public.DbProfileValueRoles_public.DbAccounts_AccountID" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbRoleRelationships" add constraint "FK_public.DbRoleRelationships_public.DbAccounts_AccountID" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbRoleToAccountFeatures" add constraint "FK_public.DbRoleToAccountFeatures_public.DbAccounts_AccountID" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbSystemPermissions" add constraint "FK_public.DbSystemPermissions_public.DbAccounts_AccountID" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbEmailQueueAttachmentNodes" add constraint "FK_public.DbEmailQueueAttachmentNodes_public.DbAccounts_Account" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbTemplateNodeChangeLogs" add constraint "FK_public.DbTemplateNodeChangeLogs_public.DbAccounts_AccountID" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbTemplateNodeLinks" add constraint "FK_public.DbTemplateNodeLinks_public.DbAccounts_AccountID" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbWorkflowStageInstanceToNotifications" add constraint "FK_public.DbWorkflowStageInstanceToNotifications_public.DbAccou" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbRoleClosures" add constraint "FK_public.DbRoleClosures_public.DbAccounts_AccountID" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbAccessLinksToNodeAndTriggers" add constraint "FK_public.DbAccessLinksToNodeAndTriggers_public.DbAccounts_Acco" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbDocumentRequestRoles" add constraint "FK_public.DbDocumentRequestRoles_public.DbAccounts_AccountID" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbNodeComments" add constraint "FK_public.DbNodeComments_public.DbNodes_NodeID_AccountID" FOREIGN KEY ("NodeID", "AccountID") REFERENCES "DbNodes"("Id", "AccountID");
alter table public."DbNodeShares" add constraint "FK_public.DbNodeShares_public.DbNodes_AccountWorkspaceNodeID_Ac" FOREIGN KEY ("AccountWorkspaceNodeID", "AccountID") REFERENCES "DbNodes"("Id", "AccountID");
alter table public."DbNodeShares" add constraint "FK_public.DbNodeShares_public.DbNodes_SharedWorkspaceNodeID_Acc" FOREIGN KEY ("SharedWorkspaceNodeID", "AccountID") REFERENCES "DbNodes"("Id", "AccountID");
alter table public."DbNodeToFileInfoes" add constraint "FK_public.DbNodeToFileInfoes_public.DbNodes_NodeID_AccountID" FOREIGN KEY ("NodeID", "AccountID") REFERENCES "DbNodes"("Id", "AccountID");
alter table public."DbPermissions" add constraint "FK_public.DbPermissions_public.DbNodes_NodeID_AccountID" FOREIGN KEY ("NodeID", "AccountID") REFERENCES "DbNodes"("Id", "AccountID");
alter table public."DbNodes" add constraint "FK_public.DbNodes_public.DbProfiles_ProfileID_AccountID" FOREIGN KEY ("ProfileID", "AccountID") REFERENCES "DbProfiles"("Id", "AccountID");
alter table public."DbProfileValueNodes" add constraint "FK_public.DbProfileValueNodes_public.DbNodes_NodeID_AccountID" FOREIGN KEY ("NodeID", "AccountID") REFERENCES "DbNodes"("Id", "AccountID");
alter table public."DbRightSignatureDocuments" add constraint "FK_public.DbRightSignatureDocuments_public.DbNodes_NodeID_Accou" FOREIGN KEY ("NodeID", "AccountID") REFERENCES "DbNodes"("Id", "AccountID");
alter table public."DbSfLinks" add constraint "FK_public.DbSfLinks_public.DbNodes_NodeID_AccountID" FOREIGN KEY ("NodeID", "AccountID") REFERENCES "DbNodes"("Id", "AccountID");
alter table public."DbSfMappings" add constraint "FK_public.DbSfMappings_public.DbNodes_ParentNodeID_AccountID" FOREIGN KEY ("ParentNodeID", "AccountID") REFERENCES "DbNodes"("Id", "AccountID");
alter table public."DbTemplateNodeChangeLogs" add constraint "FK_public.DbTemplateNodeChangeLogs_public.DbNodes_TemplateNodeI" FOREIGN KEY ("TemplateNodeID", "AccountID") REFERENCES "DbNodes"("Id", "AccountID");
alter table public."DbTemplateNodeLinks" add constraint "FK_public.DbTemplateNodeLinks_public.DbNodes_AppliedNodeID_Acco" FOREIGN KEY ("AppliedNodeID", "AccountID") REFERENCES "DbNodes"("Id", "AccountID");
alter table public."DbTemplateNodeLinks" add constraint "FK_public.DbTemplateNodeLinks_public.DbNodes_TemplateNodeID_Acc" FOREIGN KEY ("TemplateNodeID", "AccountID") REFERENCES "DbNodes"("Id", "AccountID");
alter table public."DbTriggerInfoNodes" add constraint "FK_public.DbTriggerInfoNodes_public.DbNodes_NodeID_AccountID" FOREIGN KEY ("NodeID", "AccountID") REFERENCES "DbNodes"("Id", "AccountID");
alter table public."DbTriggerToNode" add constraint "FK_public.DbTriggerToNode_public.DbNodes_NodeID_AccountID" FOREIGN KEY ("NodeID", "AccountID") REFERENCES "DbNodes"("Id", "AccountID");
alter table public."DbUserImageStamps" add constraint "FK_public.DbUserImageStamps_public.DbNodes_NodeID_AccountID" FOREIGN KEY ("NodeID", "AccountID") REFERENCES "DbNodes"("Id", "AccountID");
alter table public."DbAccessLinksToNodeAndTriggers" add constraint "FK_public.DbAccessLinksToNodeAndTriggers_public.DbTriggers_Trig" FOREIGN KEY ("TriggerID", "AccountID") REFERENCES "DbTriggers"("Id", "AccountID");
alter table public."DbTriggers" add constraint "FK_public.DbTriggers_public.DbEmailContent_EmailContentID_Accou" FOREIGN KEY ("EmailContentID", "AccountID") REFERENCES "DbEmailContent"("Id", "AccountID");
alter table public."DbEventTriggers" add constraint "FK_public.DbEventTriggers_public.DbTriggers_TriggerID_AccountID" FOREIGN KEY ("TriggerID", "AccountID") REFERENCES "DbTriggers"("Id", "AccountID");
alter table public."DbTimeTriggers" add constraint "FK_public.DbTimeTriggers_public.DbTriggers_TriggerID_AccountID" FOREIGN KEY ("TriggerID", "AccountID") REFERENCES "DbTriggers"("Id", "AccountID");
alter table public."DbTriggerInfoNodes" add constraint "FK_public.DbTriggerInfoNodes_public.DbTriggers_TriggerID_Accoun" FOREIGN KEY ("TriggerID", "AccountID") REFERENCES "DbTriggers"("Id", "AccountID");
alter table public."DbTriggerToApiCallouts" add constraint "FK_public.DbTriggerToApiCallouts_public.DbTriggers_TriggerID_Ac" FOREIGN KEY ("TriggerID", "AccountID") REFERENCES "DbTriggers"("Id", "AccountID");
alter table public."DbTriggerToNode" add constraint "FK_public.DbTriggerToNode_public.DbTriggers_TriggerID_AccountID" FOREIGN KEY ("TriggerID", "AccountID") REFERENCES "DbTriggers"("Id", "AccountID");
alter table public."DbTriggerToRoles" add constraint "FK_public.DbTriggerToRoles_public.DbTriggers_TriggerID_AccountI" FOREIGN KEY ("TriggerID", "AccountID") REFERENCES "DbTriggers"("Id", "AccountID");
alter table public."DbTriggerToSearchCriteria" add constraint "FK_public.DbTriggerToSearchCriteria_public.DbTriggers_TriggerID" FOREIGN KEY ("TriggerID", "AccountID") REFERENCES "DbTriggers"("Id", "AccountID") ON DELETE CASCADE;
alter table public."DbTriggerToWorkflow" add constraint "FK_public.DbTriggerToWorkflow_public.DbTriggers_TriggerID_Accou" FOREIGN KEY ("TriggerID", "AccountID") REFERENCES "DbTriggers"("Id", "AccountID");
alter table public."DbWatermarkTriggerInfo" add constraint "FK_public.DbWatermarkTriggerInfo_public.DbTriggers_TriggerID_Ac" FOREIGN KEY ("TriggerID", "AccountID") REFERENCES "DbTriggers"("Id", "AccountID");
alter table public."DbTriggerToRoles" add constraint "FK_public.DbTriggerToRoles_public.DbRoles_RoleID_AccountID" FOREIGN KEY ("RoleID", "AccountID") REFERENCES "DbRoles"("Id", "AccountID");
alter table public."DbAuditLogsToRoles" add constraint "FK_public.DbAuditLogsToRoles_public.DbRoles_RoleID_AccountID" FOREIGN KEY ("RoleID", "AccountID") REFERENCES "DbRoles"("Id", "AccountID");
alter table public."DbDocumentRequestRoles" add constraint "FK_public.DbDocumentRequestRoles_public.DbRoles_RecipientRoleID" FOREIGN KEY ("RecipientRoleID", "AccountID") REFERENCES "DbRoles"("Id", "AccountID");
alter table public."DbESignatureSigners" add constraint "FK_public.DbESignatureSigners_public.DbRoles_RoleID_AccountID" FOREIGN KEY ("RoleID", "AccountID") REFERENCES "DbRoles"("Id", "AccountID");
alter table public."DbFileInfoes" add constraint "FK_public.DbFileInfoes_public.DbRoles_CheckedOutByRoleID_Accoun" FOREIGN KEY ("CheckedOutByRoleID", "AccountID") REFERENCES "DbRoles"("Id", "AccountID");
alter table public."DbNodeShares" add constraint "FK_public.DbNodeShares_public.DbRoles_RoleID_AccountID" FOREIGN KEY ("RoleID", "AccountID") REFERENCES "DbRoles"("Id", "AccountID");
alter table public."DbNotifications" add constraint "FK_public.DbNotifications_public.DbRoles_RecipientRoleID_Accoun" FOREIGN KEY ("RecipientRoleID", "AccountID") REFERENCES "DbRoles"("Id", "AccountID");
alter table public."DbPermissions" add constraint "FK_public.DbPermissions_public.DbRoles_RoleID_AccountID" FOREIGN KEY ("RoleID", "AccountID") REFERENCES "DbRoles"("Id", "AccountID");
alter table public."DbRoles" add constraint "FK_public.DbRoles_public.DbProfiles_ProfileID_AccountID" FOREIGN KEY ("ProfileID", "AccountID") REFERENCES "DbProfiles"("Id", "AccountID");
alter table public."DbProfileValueRoles" add constraint "FK_public.DbProfileValueRoles_public.DbRoles_RoleID_AccountID" FOREIGN KEY ("RoleID", "AccountID") REFERENCES "DbRoles"("Id", "AccountID");
alter table public."DbRoleClosures" add constraint "FK_public.DbRoleClosures_public.DbRoles_ChildID_AccountID" FOREIGN KEY ("ChildID", "AccountID") REFERENCES "DbRoles"("Id", "AccountID");
alter table public."DbRoleClosures" add constraint "FK_public.DbRoleClosures_public.DbRoles_ParentID_AccountID" FOREIGN KEY ("ParentID", "AccountID") REFERENCES "DbRoles"("Id", "AccountID");
alter table public."DbRoles" add constraint "FK_public.DbRoles_public.DbRoles_RoleManagerID_AccountID" FOREIGN KEY ("RoleManagerID", "AccountID") REFERENCES "DbRoles"("Id", "AccountID");
alter table public."DbRoleRelationships" add constraint "FK_public.DbRoleRelationships_public.DbRoles_ParentRoleID_Accou" FOREIGN KEY ("ParentRoleID", "AccountID") REFERENCES "DbRoles"("Id", "AccountID");
alter table public."DbRoleRelationships" add constraint "FK_public.DbRoleRelationships_public.DbRoles_ChildRoleID_Accoun" FOREIGN KEY ("ChildRoleID", "AccountID") REFERENCES "DbRoles"("Id", "AccountID");
alter table public."DbRoleToAccountFeatures" add constraint "FK_public.DbRoleToAccountFeatures_public.DbRoles_RoleID_Account" FOREIGN KEY ("RoleID", "AccountID") REFERENCES "DbRoles"("Id", "AccountID");
alter table public."DbSamlConfigurations" add constraint "FK_public.DbSamlConfigurations_public.DbRoles_DefaultGroupID_Ac" FOREIGN KEY ("DefaultGroupID", "AccountID") REFERENCES "DbRoles"("Id", "AccountID");
alter table public."DbRoles" add constraint "FK_public.DbRoles_public.DbSecurityPolicies_SecurityPolicyID_Ac" FOREIGN KEY ("SecurityPolicyID", "AccountID") REFERENCES "DbSecurityPolicies"("Id", "AccountID");
alter table public."DbRoles" add constraint "FK_public.DbRoles_public.DbSystemPermissions_SystemPermissionID" FOREIGN KEY ("SystemPermissionID", "AccountID") REFERENCES "DbSystemPermissions"("Id", "AccountID");
alter table public."DbUserRolePreferences" add constraint "FK_public.DbUserRolePreferences_public.DbRoles_RoleID_AccountID" FOREIGN KEY ("RoleID", "AccountID") REFERENCES "DbRoles"("Id", "AccountID");
alter table public."DbUserSessionToDbRoles" add constraint "FK_public.DbUserSessionToDbRoles_public.DbRoles_RoleID_AccountI" FOREIGN KEY ("RoleID", "AccountID") REFERENCES "DbRoles"("Id", "AccountID");
alter table public."DbAuditLogsToRoles" add constraint "FK_public.DbAuditLogsToRoles_public.DbAuditLogs_AuditLogID_Acco" FOREIGN KEY ("AuditLogID", "AccountID") REFERENCES "DbAuditLogs"("Id", "AccountID");
alter table public."DbAuditLogsToRoleDetails" add constraint "FK_public.DbAuditLogsToRoleDetails_public.DbAuditLogsToRoles_Au" FOREIGN KEY ("AuditLogToRoleID", "AccountID") REFERENCES "DbAuditLogsToRoles"("Id", "AccountID");
alter table public."DbAuditLogsToNodes" add constraint "FK_public.DbAuditLogsToNodes_public.DbAuditLogs_AuditLogID_Acco" FOREIGN KEY ("AuditLogID", "AccountID") REFERENCES "DbAuditLogs"("Id", "AccountID");
alter table public."DbAuditLogsToNodeDetails" add constraint "FK_public.DbAuditLogsToNodeDetails_public.DbAuditLogsToNodes_Au" FOREIGN KEY ("AuditLogToNodeID", "AccountID") REFERENCES "DbAuditLogsToNodes"("Id", "AccountID");
alter table public."DbDocumentRequestAttachments" add constraint "FK_public.DbDocumentRequestAttachments_public.DbDocumentRequest" FOREIGN KEY ("DocumentRequestID", "AccountID") REFERENCES "DbDocumentRequests"("Id", "AccountID");
alter table public."DbDocumentRequestContainers" add constraint "FK_public.DbDocumentRequestContainers_public.DbDocumentRequests" FOREIGN KEY ("DocumentRequestID", "AccountID") REFERENCES "DbDocumentRequests"("Id", "AccountID");
alter table public."DbDocumentRequestRoles" add constraint "FK_public.DbDocumentRequestRoles_public.DbDocumentRequests_Docu" FOREIGN KEY ("DocumentRequestID", "AccountID") REFERENCES "DbDocumentRequests"("Id", "AccountID");
alter table public."DbDocumentRequestToNotifications" add constraint "FK_public.DbDocumentRequestToNotifications_public.DbDocumentReq" FOREIGN KEY ("DocumentRequestID", "AccountID") REFERENCES "DbDocumentRequests"("Id", "AccountID") ON DELETE CASCADE;
alter table public."DbDocumentRequestContainerNodes" add constraint "FK_public.DbDocumentRequestContainerNodes_public.DbDocumentRequ" FOREIGN KEY ("DocumentRequestContainerID", "AccountID") REFERENCES "DbDocumentRequestContainers"("Id", "AccountID");
alter table public."DbDocumentRequestContainers" add constraint "FK_public.DbDocumentRequestContainers_public.DbFileInfoes_FileI" FOREIGN KEY ("FileInfoID", "AccountID") REFERENCES "DbFileInfoes"("Id", "AccountID");
alter table public."DbDocumentRequestContainers" add constraint "FK_public.DbDocumentRequestContainers_public.DbFormFillDefiniti" FOREIGN KEY ("FormFillDefinitionID", "AccountID") REFERENCES "DbFormFillDefinitions"("Id", "AccountID");
alter table public."DbFileQueue" add constraint "FK_public.DbFileQueue_public.DbFileInfoes_FileInfoID_AccountID" FOREIGN KEY ("FileInfoID", "AccountID") REFERENCES "DbFileInfoes"("Id", "AccountID");
alter table public."DbFileInfoes" add constraint "FK_public.DbFileInfoes_public.DbFormFillDefinitions_FormFillDef" FOREIGN KEY ("FormFillDefinitionID", "AccountID") REFERENCES "DbFormFillDefinitions"("Id", "AccountID");
alter table public."DbFileInfoes" add constraint "FK_public.DbFileInfoes_public.DbNodeComments_NodeCommentID_Acco" FOREIGN KEY ("NodeCommentID", "AccountID") REFERENCES "DbNodeComments"("Id", "AccountID");
alter table public."DbNodeToFileInfoes" add constraint "FK_public.DbNodeToFileInfoes_public.DbFileInfoes_FileInfoID_Acc" FOREIGN KEY ("FileInfoID", "AccountID") REFERENCES "DbFileInfoes"("Id", "AccountID");
alter table public."DbFileInfoes" add constraint "FK_public.DbFileInfoes_public.DbFileInfoes_GeneratedFromFileInf" FOREIGN KEY ("GeneratedFromFileInfoID", "AccountID") REFERENCES "DbFileInfoes"("Id", "AccountID");
alter table public."DbFormFillPendings" add constraint "FK_public.DbFormFillPendings_public.DbFormFillDefinitions_FormF" FOREIGN KEY ("FormFillDefinitionID", "AccountID") REFERENCES "DbFormFillDefinitions"("Id", "AccountID") ON DELETE CASCADE;
alter table public."DbFormFillToProfileItems" add constraint "FK_public.DbFormFillToProfileItems_public.DbFormFillDefinitions" FOREIGN KEY ("FormFillDefinitionID", "AccountID") REFERENCES "DbFormFillDefinitions"("Id", "AccountID") ON DELETE CASCADE;
alter table public."DbFormFillDefinitions" add constraint "FK_public.DbFormFillDefinitions_public.DbProfiles_ProfileID_Acc" FOREIGN KEY ("ProfileID", "AccountID") REFERENCES "DbProfiles"("Id", "AccountID");
alter table public."DbFormFillPendings" add constraint "FK_public.DbFormFillPendings_public.DbFileInfoes_AppliedNodeFil" FOREIGN KEY ("AppliedNodeFileInfoID", "AccountID") REFERENCES "DbFileInfoes"("Id", "AccountID") ON DELETE CASCADE;
alter table public."DbFormFillToProfileItems" add constraint "FK_public.DbFormFillToProfileItems_public.DbProfileItems_Profil" FOREIGN KEY ("ProfileItemID", "AccountID") REFERENCES "DbProfileItems"("Id", "AccountID");
alter table public."DbPresetValues" add constraint "FK_public.DbPresetValues_public.DbProfileItems_ProfileItemID_Ac" FOREIGN KEY ("ProfileItemID", "AccountID") REFERENCES "DbProfileItems"("Id", "AccountID");
alter table public."DbProfileToProfileItems" add constraint "FK_public.DbProfileToProfileItems_public.DbProfileItems_Profile" FOREIGN KEY ("ProfileItemID", "AccountID") REFERENCES "DbProfileItems"("Id", "AccountID");
alter table public."DbProfileValueNodes" add constraint "FK_public.DbProfileValueNodes_public.DbProfileItems_ProfileItem" FOREIGN KEY ("ProfileItemID", "AccountID") REFERENCES "DbProfileItems"("Id", "AccountID");
alter table public."DbProfileValueRoles" add constraint "FK_public.DbProfileValueRoles_public.DbProfileItems_ProfileItem" FOREIGN KEY ("ProfileItemID", "AccountID") REFERENCES "DbProfileItems"("Id", "AccountID");
alter table public."DbProfileValueNodes" add constraint "FK_public.DbProfileValueNodes_public.DbPresetValues_PresetValue" FOREIGN KEY ("PresetValueID", "AccountID") REFERENCES "DbPresetValues"("Id", "AccountID");
alter table public."DbProfileValueRoles" add constraint "FK_public.DbProfileValueRoles_public.DbPresetValues_PresetValue" FOREIGN KEY ("PresetValueID", "AccountID") REFERENCES "DbPresetValues"("Id", "AccountID");
alter table public."DbProfileValueNodes" add constraint "FK_public.DbProfileValueNodes_public.DbProfiles_ProfileID_Accou" FOREIGN KEY ("ProfileID", "AccountID") REFERENCES "DbProfiles"("Id", "AccountID");
alter table public."DbProfileToProfileItems" add constraint "FK_public.DbProfileToProfileItems_public.DbProfiles_ProfileID_A" FOREIGN KEY ("ProfileID", "AccountID") REFERENCES "DbProfiles"("Id", "AccountID");
alter table public."DbProfileValueRoles" add constraint "FK_public.DbProfileValueRoles_public.DbProfiles_ProfileID_Accou" FOREIGN KEY ("ProfileID", "AccountID") REFERENCES "DbProfiles"("Id", "AccountID");
alter table public."DbDocumentRequestToNotifications" add constraint "FK_public.DbDocumentRequestToNotifications_public.DbNotificatio" FOREIGN KEY ("NotificationID", "AccountID") REFERENCES "DbNotifications"("Id", "AccountID") ON DELETE CASCADE;
alter table public."DbWorkflowStageInstanceToNotifications" add constraint "FK_public.DbWorkflowStageInstanceToNotifications_public.DbNotif" FOREIGN KEY ("NotificationID", "AccountID") REFERENCES "DbNotifications"("Id", "AccountID") ON DELETE CASCADE;
alter table public."DbESignatureNodeAssociations" add constraint "FK_public.DbESignatureNodeAssociations_public.DbESignatureTrans" FOREIGN KEY ("TransactionID", "AccountID") REFERENCES "DbESignatureTransactions"("Id", "AccountID");
alter table public."DbESignatureSigners" add constraint "FK_public.DbESignatureSigners_public.DbESignatureTransactions_T" FOREIGN KEY ("TransactionID", "AccountID") REFERENCES "DbESignatureTransactions"("Id", "AccountID");
alter table public."DbESignatureTransactions" add constraint "FK_public.DbESignatureTransactions_public.DbESignatureTransacti" FOREIGN KEY ("TemplateID", "AccountID") REFERENCES "DbESignatureTransactions"("Id", "AccountID");
alter table public."DbSamlResponses" add constraint "FK_public.DbSamlResponses_public.DbSamlConfigurations_Configura" FOREIGN KEY ("ConfigurationID", "AccountID") REFERENCES "DbSamlConfigurations"("Id", "AccountID");
alter table public."DbPermissions" add constraint "FK_public.DbPermissions_public.DbPermissions_ChildPermissionId_" FOREIGN KEY ("ChildPermissionId", "AccountID") REFERENCES "DbPermissions"("Id", "AccountID");
alter table public."DbSecurityPolicyIpAddresses" add constraint "FK_public.DbSecurityPolicyIpAddresses_public.DbSecurityPolicies" FOREIGN KEY ("SecurityPolicyID", "AccountID") REFERENCES "DbSecurityPolicies"("Id", "AccountID");
alter table public."DbSecurityPolicyLoginTimes" add constraint "FK_public.DbSecurityPolicyLoginTimes_public.DbSecurityPolicies_" FOREIGN KEY ("SecurityPolicyID", "AccountID") REFERENCES "DbSecurityPolicies"("Id", "AccountID");
alter table public."DbEmailQueueAttachmentNodes" add constraint "FK_public.DbEmailQueueAttachmentNodes_public.DbEmailQueue_Email" FOREIGN KEY ("EmailQueueID", "AccountID") REFERENCES "DbEmailQueue"("Id", "AccountID");
alter table public."DbEmailRecipients" add constraint "FK_public.DbEmailRecipients_public.DbEmailQueue_EmailQueueID_Ac" FOREIGN KEY ("EmailQueueID", "AccountID") REFERENCES "DbEmailQueue"("Id", "AccountID");
alter table public."DbSfLinks" add constraint "FK_public.DbSfLinks_public.DbSfMappings_SfMappingID_AccountID" FOREIGN KEY ("SfMappingID", "AccountID") REFERENCES "DbSfMappings"("Id", "AccountID");
alter table public."DbSfMappings" add constraint "FK_public.DbSfMappings_public.DbPermissions_GroupPermissionID_A" FOREIGN KEY ("GroupPermissionID", "AccountID") REFERENCES "DbPermissions"("Id", "AccountID");
alter table public."DbSfMappings" add constraint "FK_public.DbSfMappings_public.DbPermissions_UserPermissionID_Ac" FOREIGN KEY ("UserPermissionID", "AccountID") REFERENCES "DbPermissions"("Id", "AccountID");
alter table public."DbEmailTemplateToPartner" add constraint "FK_public.DbEmailTemplateToPartner_public.DbPartners_PartnerID" FOREIGN KEY ("PartnerID") REFERENCES "DbPartners"("Id");
alter table public."DbUserSessionToDbRoles" add constraint "FK_public.DbUserSessionToDbRoles_public.DbUserSessions_UserSess" FOREIGN KEY ("UserSessionID") REFERENCES "DbUserSessions"("Id");
alter table workflow."DbWorkflowSetProfileItems" add constraint "FK_workflow.DbWorkflowSetProfileItems_workflow.DbWorkflowSteps_" FOREIGN KEY ("StepID") REFERENCES workflow."DbWorkflowSteps"("Id");
alter table workflow."DbWorkflowShareStepNewUserReferences" add constraint "FK_workflow.DbWorkflowShareStepNewUserReferences_workflow.DbWor" FOREIGN KEY ("StepID") REFERENCES workflow."DbWorkflowSteps"("Id");
alter table workflow."DbWorkflowStepGroupReferences" add constraint "FK_workflow.DbWorkflowStepGroupReferences_workflow.DbWorkflowSt" FOREIGN KEY ("StepID") REFERENCES workflow."DbWorkflowSteps"("Id");
alter table workflow."DbWorkflowStepUserReferences" add constraint "FK_workflow.DbWorkflowStepUserReferences_workflow.DbWorkflowSte" FOREIGN KEY ("StepID") REFERENCES workflow."DbWorkflowSteps"("Id");
alter table workflow."DbWorkflowAssetsStages" add constraint "FK_workflow.DbWorkflowAssetsStages_workflow.DbWorkflowStages_St" FOREIGN KEY ("StageID") REFERENCES workflow."DbWorkflowStages"("Id");
alter table workflow."DbWorkflowStageInstances" add constraint "FK_workflow.DbWorkflowStageInstances_workflow.DbWorkflowStages_" FOREIGN KEY ("StageTypeID") REFERENCES workflow."DbWorkflowStages"("Id");
alter table workflow."DbWorkflowStageApproverGroups" add constraint "FK_workflow.DbWorkflowStageApproverGroups_workflow.DbWorkflowSt" FOREIGN KEY ("WorkflowStageID") REFERENCES workflow."DbWorkflowStages"("Id");
alter table workflow."DbWorkflowStageApprovers" add constraint "FK_workflow.DbWorkflowStageApprovers_workflow.DbWorkflowStages_" FOREIGN KEY ("WorkflowStageID") REFERENCES workflow."DbWorkflowStages"("Id");
alter table workflow."DbWorkflowStageAssigneeGroups" add constraint "FK_workflow.DbWorkflowStageAssigneeGroups_workflow.DbWorkflowSt" FOREIGN KEY ("WorkflowStageID") REFERENCES workflow."DbWorkflowStages"("Id");
alter table workflow."DbWorkflowStageAssignees" add constraint "FK_workflow.DbWorkflowStageAssignees_workflow.DbWorkflowStages_" FOREIGN KEY ("WorkflowStageID") REFERENCES workflow."DbWorkflowStages"("Id");
alter table workflow."DbProfileRoutingRules" add constraint "FK_workflow.DbProfileRoutingRules_workflow.DbWorkflowStages_Sta" FOREIGN KEY ("StageID") REFERENCES workflow."DbWorkflowStages"("Id");
alter table workflow."DbWorkflowSteps" add constraint "FK_workflow.DbWorkflowSteps_workflow.DbWorkflowStages_StageID" FOREIGN KEY ("StageID") REFERENCES workflow."DbWorkflowStages"("Id");
alter table workflow."DbWorkflowSteps" add constraint "FK_workflow.DbWorkflowSteps_workflow.DbWorkflowAssets_requestF1" FOREIGN KEY ("requestFileExternal_AttachmentAssetID") REFERENCES workflow."DbWorkflowAssets"("Id");
alter table workflow."DbWorkflowSteps" add constraint "FK_workflow.DbWorkflowSteps_workflow.DbWorkflowAssets_requestF2" FOREIGN KEY ("requestFileExternal_DestinationAssetID") REFERENCES workflow."DbWorkflowAssets"("Id");
alter table workflow."DbWorkflowStepDocumentRequestContainers" add constraint "FK_workflow.DbWorkflowStepDocumentRequestContainers_workflow.D2" FOREIGN KEY ("AssetID") REFERENCES workflow."DbWorkflowAssets"("Id");
alter table workflow."DbAssetNodeReference" add constraint "FK_workflow.DbAssetNodeReference_workflow.DbWorkflowAssets_Asse" FOREIGN KEY ("AssetID") REFERENCES workflow."DbWorkflowAssets"("Id");
alter table workflow."DbWorkflowAssetsStages" add constraint "FK_workflow.DbWorkflowAssetsStages_workflow.DbWorkflowAssets_As" FOREIGN KEY ("AssetID") REFERENCES workflow."DbWorkflowAssets"("Id");
alter table workflow."DbWorkflowStages" add constraint "FK_workflow.DbWorkflowStages_workflow.DbWorkflowAssets_Approval" FOREIGN KEY ("ApprovalAssetID") REFERENCES workflow."DbWorkflowAssets"("Id");
alter table workflow."DbProfileRoutingRules" add constraint "FK_workflow.DbProfileRoutingRules_workflow.DbWorkflowAssets_Ass" FOREIGN KEY ("AssetID") REFERENCES workflow."DbWorkflowAssets"("Id");
alter table workflow."DbWorkflowSteps" add constraint "FK_workflow.DbWorkflowSteps_workflow.DbWorkflowAssets_addTrigg1" FOREIGN KEY ("addTrigger_DestinationAssetID") REFERENCES workflow."DbWorkflowAssets"("Id");
alter table workflow."DbWorkflowSteps" add constraint "FK_workflow.DbWorkflowSteps_workflow.DbWorkflowAssets_addTrigg2" FOREIGN KEY ("addTrigger_TargetAssetID") REFERENCES workflow."DbWorkflowAssets"("Id");
alter table workflow."DbWorkflowSteps" add constraint "FK_workflow.DbWorkflowSteps_workflow.DbWorkflowAssets_applyTemp" FOREIGN KEY ("applyTemplate_TargetPathAssetID") REFERENCES workflow."DbWorkflowAssets"("Id");
alter table workflow."DbWorkflowSteps" add constraint "FK_workflow.DbWorkflowSteps_workflow.DbWorkflowAssets_comment_T" FOREIGN KEY ("comment_TargetAssetID") REFERENCES workflow."DbWorkflowAssets"("Id");
alter table workflow."DbWorkflowSteps" add constraint "FK_workflow.DbWorkflowSteps_workflow.DbWorkflowAssets_copy_Dest" FOREIGN KEY ("copy_DestinationAssetID") REFERENCES workflow."DbWorkflowAssets"("Id");
alter table workflow."DbWorkflowSteps" add constraint "FK_workflow.DbWorkflowSteps_workflow.DbWorkflowAssets_copy_Resu" FOREIGN KEY ("copy_ResultAssetID") REFERENCES workflow."DbWorkflowAssets"("Id");
alter table workflow."DbWorkflowSteps" add constraint "FK_workflow.DbWorkflowSteps_workflow.DbWorkflowAssets_copy_Sour" FOREIGN KEY ("copy_SourceAssetID") REFERENCES workflow."DbWorkflowAssets"("Id");
alter table workflow."DbWorkflowSteps" add constraint "FK_workflow.DbWorkflowSteps_workflow.DbWorkflowAssets_createLo1" FOREIGN KEY ("createLocation_ParentPathAssetID") REFERENCES workflow."DbWorkflowAssets"("Id");
alter table workflow."DbWorkflowSteps" add constraint "FK_workflow.DbWorkflowSteps_workflow.DbWorkflowAssets_createLo2" FOREIGN KEY ("createLocation_ResultAssetID") REFERENCES workflow."DbWorkflowAssets"("Id");
alter table workflow."DbWorkflowSteps" add constraint "FK_workflow.DbWorkflowSteps_workflow.DbWorkflowAssets_delete_Ta" FOREIGN KEY ("delete_TargetAssetID") REFERENCES workflow."DbWorkflowAssets"("Id");
alter table workflow."DbWorkflowSteps" add constraint "FK_workflow.DbWorkflowSteps_workflow.DbWorkflowAssets_esignatu1" FOREIGN KEY ("esignature_AuditTrailAssetID") REFERENCES workflow."DbWorkflowAssets"("Id");
alter table workflow."DbWorkflowSteps" add constraint "FK_workflow.DbWorkflowSteps_workflow.DbWorkflowAssets_esignatu2" FOREIGN KEY ("esignature_AuditTrailDestinationAssetID") REFERENCES workflow."DbWorkflowAssets"("Id");
alter table workflow."DbWorkflowSteps" add constraint "FK_workflow.DbWorkflowSteps_workflow.DbWorkflowAssets_esignatu3" FOREIGN KEY ("esignature_SignedResultAssetID") REFERENCES workflow."DbWorkflowAssets"("Id");
alter table workflow."DbWorkflowSteps" add constraint "FK_workflow.DbWorkflowSteps_workflow.DbWorkflowAssets_esignatu4" FOREIGN KEY ("esignature_SignedResultDestinationAssetID") REFERENCES workflow."DbWorkflowAssets"("Id");
alter table workflow."DbWorkflowSteps" add constraint "FK_workflow.DbWorkflowSteps_workflow.DbWorkflowAssets_esignatu5" FOREIGN KEY ("esignature_SourceAssetID") REFERENCES workflow."DbWorkflowAssets"("Id");
alter table workflow."DbWorkflowESignatureStepTemplateDocuments" add constraint "FK_workflow.DbWorkflowESignatureStepTemplateDocuments_workflow2" FOREIGN KEY ("SourceAssetID") REFERENCES workflow."DbWorkflowAssets"("Id");
alter table workflow."DbWorkflowSteps" add constraint "FK_workflow.DbWorkflowSteps_workflow.DbWorkflowAssets_move_Dest" FOREIGN KEY ("move_DestinationAssetID") REFERENCES workflow."DbWorkflowAssets"("Id");
alter table workflow."DbWorkflowSteps" add constraint "FK_workflow.DbWorkflowSteps_workflow.DbWorkflowAssets_move_Sour" FOREIGN KEY ("move_SourceAssetID") REFERENCES workflow."DbWorkflowAssets"("Id");
alter table workflow."DbWorkflowSteps" add constraint "FK_workflow.DbWorkflowSteps_workflow.DbWorkflowAssets_rename_Ta" FOREIGN KEY ("rename_TargetAssetID") REFERENCES workflow."DbWorkflowAssets"("Id");
alter table workflow."DbWorkflowSteps" add constraint "FK_workflow.DbWorkflowSteps_workflow.DbWorkflowAssets_sendMessa" FOREIGN KEY ("sendMessage_AttachmentAssetID") REFERENCES workflow."DbWorkflowAssets"("Id");
alter table workflow."DbWorkflowSteps" add constraint "FK_workflow.DbWorkflowSteps_workflow.DbWorkflowAssets_setPermis" FOREIGN KEY ("setPermissions_TargetAssetID") REFERENCES workflow."DbWorkflowAssets"("Id");
alter table workflow."DbWorkflowSteps" add constraint "FK_workflow.DbWorkflowSteps_workflow.DbWorkflowAssets_setProfil" FOREIGN KEY ("setProfile_TargetAssetID") REFERENCES workflow."DbWorkflowAssets"("Id");
alter table workflow."DbWorkflowSteps" add constraint "FK_workflow.DbWorkflowSteps_workflow.DbWorkflowAssets_setReten1" FOREIGN KEY ("setRetention_DestinationAssetID") REFERENCES workflow."DbWorkflowAssets"("Id");
alter table workflow."DbWorkflowSteps" add constraint "FK_workflow.DbWorkflowSteps_workflow.DbWorkflowAssets_setReten2" FOREIGN KEY ("setRetention_TargetAssetID") REFERENCES workflow."DbWorkflowAssets"("Id");
alter table workflow."DbWorkflowSteps" add constraint "FK_workflow.DbWorkflowSteps_workflow.DbWorkflowAssets_share_Sou" FOREIGN KEY ("share_SourceAssetID") REFERENCES workflow."DbWorkflowAssets"("Id");
alter table workflow."DbWorkflowSteps" add constraint "FK_workflow.DbWorkflowSteps_workflow.DbWorkflowAssets_upload_Re" FOREIGN KEY ("upload_ResultAssetID") REFERENCES workflow."DbWorkflowAssets"("Id");
alter table workflow."DbWorkflowSteps" add constraint "FK_workflow.DbWorkflowSteps_workflow.DbWorkflowAssets_upload_So" FOREIGN KEY ("upload_SourceAssetID") REFERENCES workflow."DbWorkflowAssets"("Id");
alter table workflow."DbWorkflowAssetInstances" add constraint "FK_workflow.DbWorkflowAssetInstances_workflow.DbWorkflowAssets_" FOREIGN KEY ("WorkflowAssetID") REFERENCES workflow."DbWorkflowAssets"("Id");
alter table workflow."DbWorkflowAssets" add constraint "FK_workflow.DbWorkflowAssets_workflow.DbWorkflows_WorkflowID" FOREIGN KEY ("WorkflowID") REFERENCES workflow."DbWorkflows"("Id");
alter table workflow."DbWorkflowInstanceHistoryRecords" add constraint "FK_workflow.DbWorkflowInstanceHistoryRecords_workflow.DbWorkfl2" FOREIGN KEY ("WorkflowID") REFERENCES workflow."DbWorkflows"("Id");
alter table workflow."DbWorkflowInstances" add constraint "FK_workflow.DbWorkflowInstances_workflow.DbWorkflows_WorkflowID" FOREIGN KEY ("WorkflowID") REFERENCES workflow."DbWorkflows"("Id");
alter table workflow."DbWorkflowsAvailableStates" add constraint "FK_workflow.DbWorkflowsAvailableStates_workflow.DbWorkflows_Wor" FOREIGN KEY ("WorkflowID") REFERENCES workflow."DbWorkflows"("Id");
alter table workflow."DbWorkflowNotificationConfigurations" add constraint "FK_workflow.DbWorkflowNotificationConfigurations_workflow.DbWor" FOREIGN KEY ("Id") REFERENCES workflow."DbWorkflows"("Id");
alter table workflow."DbWorkflowOwnerGroups" add constraint "FK_workflow.DbWorkflowOwnerGroups_workflow.DbWorkflows_Workflow" FOREIGN KEY ("WorkflowID") REFERENCES workflow."DbWorkflows"("Id");
alter table workflow."DbWorkflowOwners" add constraint "FK_workflow.DbWorkflowOwners_workflow.DbWorkflows_WorkflowID" FOREIGN KEY ("WorkflowID") REFERENCES workflow."DbWorkflows"("Id");
alter table workflow."DbWorkflowScheduleConfigurations" add constraint "FK_workflow.DbWorkflowScheduleConfigurations_workflow.DbWorkflo" FOREIGN KEY ("Id") REFERENCES workflow."DbWorkflows"("Id");
alter table workflow."DbWorkflowStages" add constraint "FK_workflow.DbWorkflowStages_workflow.DbWorkflows_WorkflowID" FOREIGN KEY ("WorkflowID") REFERENCES workflow."DbWorkflows"("Id");
alter table workflow."DbWorkflowStarterGroups" add constraint "FK_workflow.DbWorkflowStarterGroups_workflow.DbWorkflows_Workfl" FOREIGN KEY ("WorkflowID") REFERENCES workflow."DbWorkflows"("Id");
alter table workflow."DbWorkflowStarters" add constraint "FK_workflow.DbWorkflowStarters_workflow.DbWorkflows_WorkflowID" FOREIGN KEY ("WorkflowID") REFERENCES workflow."DbWorkflows"("Id");
alter table workflow."DbWorkflowWatcherGroups" add constraint "FK_workflow.DbWorkflowWatcherGroups_workflow.DbWorkflows_Workfl" FOREIGN KEY ("WorkflowID") REFERENCES workflow."DbWorkflows"("Id");
alter table workflow."DbWorkflowWatchers" add constraint "FK_workflow.DbWorkflowWatchers_workflow.DbWorkflows_WorkflowID" FOREIGN KEY ("WorkflowID") REFERENCES workflow."DbWorkflows"("Id");
alter table workflow."DbWorkflowsAvailableStates" add constraint "FK_workflow.DbWorkflowsAvailableStates_workflow.DbWorkflowInsta" FOREIGN KEY ("StateID") REFERENCES workflow."DbWorkflowInstanceStates"("Id");
alter table workflow."DbWorkflowStages" add constraint "FK_workflow.DbWorkflowStages_workflow.DbWorkflowInstanceStates1" FOREIGN KEY ("ApprovedRoutingWorkflowInstanceStateID") REFERENCES workflow."DbWorkflowInstanceStates"("Id");
alter table workflow."DbWorkflowStages" add constraint "FK_workflow.DbWorkflowStages_workflow.DbWorkflowInstanceStates2" FOREIGN KEY ("DefaultProfileRoutingWorkflowInstanceStateID") REFERENCES workflow."DbWorkflowInstanceStates"("Id");
alter table workflow."DbWorkflowStages" add constraint "FK_workflow.DbWorkflowStages_workflow.DbWorkflowInstanceStates3" FOREIGN KEY ("PastRoutingWorkflowInstanceStateID") REFERENCES workflow."DbWorkflowInstanceStates"("Id");
alter table workflow."DbProfileRoutingRules" add constraint "FK_workflow.DbProfileRoutingRules_workflow.DbWorkflowInstanceSt" FOREIGN KEY ("RoutingWorkflowInstanceStateID") REFERENCES workflow."DbWorkflowInstanceStates"("Id");
alter table workflow."DbWorkflowStages" add constraint "FK_workflow.DbWorkflowStages_workflow.DbWorkflowInstanceStates4" FOREIGN KEY ("RejectedRoutingWorkflowInstanceStateID") REFERENCES workflow."DbWorkflowInstanceStates"("Id");
alter table workflow."DbWorkflowAssetInstances" add constraint "FK_workflow.DbWorkflowAssetInstances_workflow.DbWorkflowInstanc" FOREIGN KEY ("WorkflowID") REFERENCES workflow."DbWorkflowInstances"("Id");
alter table workflow."DbWorkflowInstanceHistoryRecords" add constraint "FK_workflow.DbWorkflowInstanceHistoryRecords_workflow.DbWorkfl3" FOREIGN KEY ("WorkflowInstanceID") REFERENCES workflow."DbWorkflowInstances"("Id");
alter table workflow."DbWorkflowStageInstances" add constraint "FK_workflow.DbWorkflowStageInstances_workflow.DbWorkflowInstanc" FOREIGN KEY ("WorkflowID") REFERENCES workflow."DbWorkflowInstances"("Id");
alter table workflow."DbWorkflowInstanceHistoryRecords" add constraint "FK_workflow.DbWorkflowInstanceHistoryRecords_workflow.DbWorkfl4" FOREIGN KEY ("StageInstanceID") REFERENCES workflow."DbWorkflowStageInstances"("Id");
alter table workflow."DbWorkflowStepInstances" add constraint "FK_workflow.DbWorkflowStepInstances_workflow.DbWorkflowStageIns" FOREIGN KEY ("StageID") REFERENCES workflow."DbWorkflowStageInstances"("Id");
alter table workflow."DbWorkflowInstances" add constraint "FK_workflow.DbWorkflowInstances_workflow.DbWorkflowStageInstanc" FOREIGN KEY ("CurrentStageID") REFERENCES workflow."DbWorkflowStageInstances"("Id");
alter table workflow."DbWorkflowAssetsStagesInstances" add constraint "FK_workflow.DbWorkflowAssetsStagesInstances_workflow.DbWorkflo2" FOREIGN KEY ("StageID") REFERENCES workflow."DbWorkflowStageInstances"("Id");
alter table workflow."DbWorkflowSetProfileInstanceItemPresetValues" add constraint "FK_workflow.DbWorkflowSetProfileInstanceItemPresetValues_workfl" FOREIGN KEY ("StepProfileItemID") REFERENCES workflow."DbWorkflowSetProfileInstanceItems"("Id");
alter table workflow."DbWorkflowSetProfileItemPresetValues" add constraint "FK_workflow.DbWorkflowSetProfileItemPresetValues_workflow.DbWor" FOREIGN KEY ("StepProfileItemID") REFERENCES workflow."DbWorkflowSetProfileItems"("Id");
alter table public."DbWorkflowStageInstanceToNotifications" add constraint "FK_DbWorkflowStageInstanceToNotifications_DbWorkflowStageInstan" FOREIGN KEY ("WorkflowStageInstanceID") REFERENCES workflow."DbWorkflowStageInstances"("Id");
alter table public."DbRoles" add constraint "CK_RoleManagerID" CHECK ("RoleType" = 3 AND "RoleManagerID" IS NOT NULL OR "RoleType" <> '-1'::integer AND "RoleManagerID" IS NULL);
alter table public."DbDocumentRequestAttachments" add constraint "FK_public.DbDocumentRequestAttachments_public.DbAccounts_Accoun" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbFormFillDefinitions" add constraint "FK_public.DbFormFillDefinitions_public.DbAccounts_AccountID" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbDocumentRequestContainers" add constraint "FK_public.DbDocumentRequestContainers_public.DbAccounts_Account" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbDocumentRequestContainerNodes" add constraint "FK_public.DbDocumentRequestContainerNodes_public.DbAccounts_Acc" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbFormFillPendings" add constraint "FK_public.DbFormFillPendings_public.DbAccounts_AccountID" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbFormFillToProfileItems" add constraint "FK_public.DbFormFillToProfileItems_public.DbAccounts_AccountID" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbNodeComments" add constraint "FK_public.DbNodeComments_public.DbAccounts_AccountID" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbESignatureSigners" add constraint "FK_public.DbESignatureSigners_public.DbAccounts_AccountID" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbESignatureNodeAssociations" add constraint "FK_public.DbESignatureNodeAssociations_public.DbAccounts_Accoun" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbSecurityPolicyIpAddresses" add constraint "FK_public.DbSecurityPolicyIpAddresses_public.DbAccounts_Account" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbSecurityPolicyLoginTimes" add constraint "FK_public.DbSecurityPolicyLoginTimes_public.DbAccounts_AccountI" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbUserRolePreferences" add constraint "FK_public.DbUserRolePreferences_public.DbAccounts_AccountID" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbTriggerToApiCallouts" add constraint "FK_public.DbTriggerToApiCallouts_public.DbAccounts_AccountID" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbWatermarkTriggerInfo" add constraint "FK_public.DbWatermarkTriggerInfo_public.DbAccounts_AccountID" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbLegacyNodeMappings" add constraint "FK_public.DbLegacyNodeMappings_public.DbAccounts_AccountID" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbAccessLinksToDocumentRequests" add constraint "FK_public.DbAccessLinksToDocumentRequests_public.DbAccounts_Acc" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbDocumentRequestToNotifications" add constraint "FK_public.DbDocumentRequestToNotifications_public.DbAccounts_Ac" FOREIGN KEY ("AccountID") REFERENCES "DbAccounts"("Id");
alter table public."DbPermissions" add constraint ck_permission CHECK ("Restrict" = false OR "Restrict" = true AND "Preview" = false AND "Read" = false AND "Write" = false AND "Delete" = false AND "Admin" = false AND "UploadFiles" = false AND "CreateDirectories" = false AND "ChildPermissionId" IS NULL AND ("Enforce" = false OR "Enforce" = true));
select create_distributed_function('"patindex"(character varying,character varying)');
select create_distributed_function('"isnumeric"(text)');
select create_distributed_function('"func_getnaturalsortablevalue"(character varying)');
select create_distributed_function('"datediff"(character varying,timestamp without time zone,timestamp without time zone)');
select create_distributed_function('"func_insertintodbtemptablesearchresults"(dbtemptablesearchresulttype[])');
CREATE OR REPLACE FUNCTION createrelationships() RETURNS TRIGGER AS $$
BEGIN
EXECUTE format(
'insert into %1$s ("ParentID", "ChildID", "Depth", "AccountID") values (($1)."Id", ($1)."Id", 0, ($1)."AccountID");
insert into %1$s ("ParentID", "ChildID", "Depth", "AccountID")
select closures."ParentID", ($1)."Id", closures."Depth" + 1, ($1)."AccountID"
from %1$s as closures WHERE ($1)."ParentID" = closures."ChildID";',
TG_ARGV[0]
) USING NEW;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
select create_distributed_function('createrelationships()');
SELECT run_command_on_colocated_placements(
'public."DbNodes"',
'public."DbNodeClosures"',
$cmd$
CREATE TRIGGER tr_dbnode_insert AFTER INSERT ON %s
FOR EACH ROW EXECUTE PROCEDURE createRelationships(%L)
$cmd$
);
CREATE OR REPLACE FUNCTION updateRelationships() RETURNS TRIGGER AS $$
BEGIN
EXECUTE format(
'delete from %1$s
where "ChildID" in (select "ChildID" from %1$s where "ParentID" = ($1)."Id" and "AccountID" = ($1)."AccountID")
and "ParentID" in (select "ParentID" from %1$s where "ChildID" = ($1)."Id" and "ParentID" != "ChildID" and "AccountID" = ($1)."AccountID");
insert into %1$s ("ParentID", "ChildID", "Depth", "AccountID")
select supertree."ParentID", subtree."ChildID", supertree."Depth" + subtree."Depth" + 1, supertree."AccountID"
from %1$s supertree, %1$s subtree
where supertree."ChildID" = ($1)."ParentID" and subtree."ParentID" = ($1)."Id" and supertree."AccountID" = subtree."AccountID";',
TG_ARGV[0]
) USING NEW;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
select create_distributed_function('updateRelationships()');
SELECT run_command_on_colocated_placements(
'public."DbNodes"',
'public."DbNodeClosures"',
$cmd$
CREATE TRIGGER tr_dbnode_update AFTER UPDATE ON %s
FOR EACH ROW WHEN ((old."ParentID" IS DISTINCT FROM new."ParentID")) EXECUTE PROCEDURE updaterelationships(%L)
$cmd$
);
CREATE OR REPLACE FUNCTION createdroleclosurerelationship() RETURNS TRIGGER AS $$
DECLARE
closure bigint := NULL;
BEGIN
EXECUTE format(
'SELECT * FROM "%s" WHERE "ChildID" = ($1)."ParentID" AND "ParentID" = ($1)."ChildID" AND ($1)."AccountID" = "AccountID";',
TG_ARGV[0]) USING NEW INTO closure;
IF closure IS NOT NULL
THEN
RETURN NULL;
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
select create_distributed_function('createdroleclosurerelationship()');
SELECT run_command_on_placements(
'public."DbRoleClosures"',
$cmd$
CREATE TRIGGER tr_dbroleclosures_insert BEFORE INSERT ON %1$s
FOR EACH ROW EXECUTE FUNCTION createdroleclosurerelationship(%1$s)
$cmd$
);
CREATE OR REPLACE FUNCTION createrolerelationship() RETURNS TRIGGER AS $$
BEGIN
EXECUTE format(
'INSERT INTO %s ("ParentID", "ChildID", "AccountID") values (($1)."Id", ($1)."Id", ($1)."AccountID");',
TG_ARGV[0]
) USING NEW;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
select create_distributed_function('createrolerelationship()');
SELECT run_command_on_colocated_placements(
'public."DbRoles"',
'public."DbRoleClosures"',
$cmd$
CREATE TRIGGER tr_dbrole_insert AFTER INSERT ON %s
FOR EACH ROW EXECUTE FUNCTION createrolerelationship(%L);
$cmd$
);
CREATE OR REPLACE FUNCTION deleterolerelationship() RETURNS TRIGGER AS $$
BEGIN
EXECUTE format(
'DELETE FROM %s
where "ParentID" = "ChildID" and "ChildID" = ($1)."Id" and "AccountID" = ($1)."AccountID";',
TG_ARGV[0]
) USING OLD;
RETURN OLD;
END;
$$ LANGUAGE plpgsql;
select create_distributed_function('deleterolerelationship()');
SELECT run_command_on_colocated_placements(
'public."DbRoles"',
'public."DbRoleClosures"',
$cmd$
CREATE TRIGGER tr_dbrole_delete BEFORE DELETE ON %s
FOR EACH ROW EXECUTE FUNCTION deleterolerelationship(%L);
$cmd$
);
CREATE OR REPLACE PROCEDURE sp_insertRoleRelationshipClosures(tableName text, parentid bigint, childid bigint, accountID int)
AS $$
BEGIN
EXECUTE format(
'INSERT INTO %1$s ("ParentID", "ChildID", "AccountID")
SELECT cl."ParentID", child."ChildID", child."AccountID"
FROM %1$s AS cl
JOIN %1$s AS child on child."ParentID" = $2 AND child."AccountID" = cl."AccountID"
WHERE cl."ChildID" = $1 AND cl."AccountID" = $3;',
tableName
) USING parentid, childid, accountID;
END;
$$ LANGUAGE 'plpgsql';
select create_distributed_function('"sp_insertrolerelationshipclosures"(text,bigint,bigint,integer)');
CREATE OR REPLACE FUNCTION insertrolerelationshipclosures() RETURNS TRIGGER AS $$
BEGIN
EXECUTE format(
'CALL sp_insertRoleRelationshipClosures(''%1$s'', ($1)."ParentRoleID", ($1)."ChildRoleID", ($1)."AccountID");',
TG_ARGV[0]
) USING NEW;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
select create_distributed_function('insertrolerelationshipclosures()');
SELECT run_command_on_colocated_placements(
'public."DbRoleRelationships"',
'public."DbRoleClosures"',
$cmd$
CREATE TRIGGER tr_dbrolerelationships_insert AFTER INSERT ON %s
FOR EACH ROW EXECUTE FUNCTION insertrolerelationshipclosures(%L);
$cmd$
);
CREATE OR REPLACE PROCEDURE sp_deleteRoleRelationshipClosures(tablename text, parentid bigint, childid bigint, accountid int)
AS $$
DECLARE
db_row RECORD;
db_cursor refcursor;
BEGIN
OPEN db_cursor FOR EXECUTE format(
'SELECT parent."ParentID", child."ChildID"
FROM %1$s AS parent
JOIN %1$s AS child ON child."ParentID" = $2 AND child."AccountID" = parent."AccountID"
WHERE parent."ChildID" = $1 AND parent."AccountID" = $3
GROUP BY parent."ParentID", child."ChildID"', tablename) USING parentid, childid, accountid;
LOOP
FETCH db_cursor INTO db_row;
EXIT WHEN NOT FOUND;
EXECUTE format('DELETE FROM %s cl WHERE cl."ParentID" = $1 AND cl."ChildID" = $2 AND cl."AccountID" = $3;', tablename) USING db_row."ParentID", db_row."ChildID", accountid;
END LOOP;
CLOSE db_cursor;
END;
$$ LANGUAGE 'plpgsql';
select create_distributed_function('"sp_deleterolerelationshipclosures"(text,bigint,bigint,int)');
CREATE OR REPLACE FUNCTION deleteRoleRelationshipClosures() RETURNS TRIGGER AS $$
BEGIN
EXECUTE format(
'CALL sp_deleterolerelationshipclosures(''%1$s'', ($1)."ParentRoleID", ($1)."ChildRoleID", ($1)."AccountID")',
TG_ARGV[0]
) USING OLD;
RETURN OLD;
END;
$$ LANGUAGE plpgsql;
select create_distributed_function('deleteRoleRelationshipClosures()');
SELECT run_command_on_colocated_placements(
'public."DbRoleRelationships"',
'public."DbRoleClosures"',
$cmd$
CREATE TRIGGER tr_DbRoleRelationships_delete BEFORE DELETE ON %s
FOR EACH ROW EXECUTE PROCEDURE deleteRoleRelationshipClosures(%L);
$cmd$
);
CREATE OR REPLACE FUNCTION updateRoleRelationshipClosures()
RETURNS trigger AS $$
BEGIN
EXECUTE format('CALL sp_deleterolerelationshipclosures(''%1$s'', ($1)."ParentRoleID", ($1)."ChildRoleID", ($1)."AccountID");', TG_ARGV[0]) USING OLD;
EXECUTE format('CALL sp_insertrolerelationshipclosures(''%1$s'', ($1)."ParentRoleID", ($1)."ChildRoleID", ($1)."AccountID");', TG_ARGV[0]) USING NEW;
RETURN NEW;
END;
$$ LANGUAGE 'plpgsql';
select create_distributed_function('updateRoleRelationshipClosures()');
SELECT run_command_on_colocated_placements(
'public."DbRoleRelationships"',
'public."DbRoleClosures"',
$cmd$
CREATE TRIGGER tr_dbrolerelationships_update AFTER UPDATE ON %s
FOR EACH ROW EXECUTE FUNCTION updaterolerelationshipclosures(%L);
$cmd$
);
IMPORTANT!
- When you mark table as "distributed" all referenced table must be a distributed table or a reference table.
- When you mark table as "distributed" PK and Unique constraints must include distribution key (AccountID)
- You can't use
GENERATED BY ... AS IDENTITY
The Following SQL Queries were super helpful in generating the script to distribute the database.
namespace CitusTableDistributionTool.SQL
{
internal static class SqlQueries
{
public static string CreateDbAccountsDistributedTableCommand => @"SELECT create_distributed_table('""DbAccounts""', 'Id');";
public static string CreateDbUsersSessionsReferenceTableCommand => @"SELECT create_reference_table('""public"".""DbUserSessions""');";
public static string QueryAddConstraintCommands => @"
select 'alter table '||quote_ident(ns.nspname)||'.'||quote_ident(tb.relname)||
' add constraint '||quote_ident(conname)||' '||
pg_get_constraintdef(c.oid, true)||';' as ddl
from pg_constraint c
join pg_class tb on tb.oid = c.conrelid
left outer join pg_inherits on pg_inherits.inhrelid = tb.oid
join pg_namespace ns on ns.oid = tb.relnamespace
where ns.nspname in ('public', 'workflow')
and c.contype in ('f', 'c')
and pg_inherits.inhrelid is null;";
public static string QueryCreateDistributedTablesCommands => @"
select 'SELECT create_distributed_table(''""' || t.table_schema || '"".""' || t.table_name || '""'', ''AccountID'');'
from information_schema.tables t
inner join information_schema.columns c on c.table_name = t.table_name
and c.table_schema = t.table_schema
join pg_class on pg_class.relname = c.table_name
left outer join pg_inherits on pg_inherits.inhrelid = pg_class.oid
where c.column_name = 'AccountID'
and t.table_name != 'DbUserSessions'
and t.table_schema in ('public')
and t.table_type = 'BASE TABLE'
and pg_inherits.inhrelid is null
and (pg_class.relkind = 'r' or pg_class.relkind = 'p')
order by t.table_schema;";
public static string QueryCreatePublicReferenceTablesCommands => @"
select 'SELECT create_reference_table(''""' || t.table_schema || '"".""' || t.table_name || '""'');'
from information_schema.tables t
left join (select table_schema, table_name
from information_schema.columns
where column_name = 'AccountID') c
on c.table_name = t.table_name
and c.table_schema = t.table_schema
join pg_class on pg_class.relname = t.table_name
left outer join pg_inherits on pg_inherits.inhrelid = pg_class.oid
where c.table_name is null
and t.table_name != 'DbAccounts'
and t.table_schema in ('public')
and t.table_type = 'BASE TABLE'
and pg_inherits.inhrelid is null
and (pg_class.relkind = 'r' or pg_class.relkind = 'p')
order by t.table_schema,
t.table_name;";
public static string QueryCreateTriggerCommands => @"
SELECT pg_get_triggerdef(oid) || ';'
FROM information_schema.triggers
JOIN pg_trigger ON pg_trigger.tgname = information_schema.triggers.trigger_name
WHERE trigger_schema in ('public', 'workflow');";
public static string QueryCreateWorkflowReferenceTablesCommands => @"
select 'SELECT create_reference_table(''""' || t.table_schema || '"".""' || t.table_name || '""'');'
from information_schema.tables t
join pg_class on pg_class.relname = t.table_name
left outer join pg_inherits on pg_inherits.inhrelid = pg_class.oid
where t.table_schema in ('workflow')
and t.table_type = 'BASE TABLE'
and pg_inherits.inhrelid is null
and (pg_class.relkind = 'r' or pg_class.relkind = 'p')
order by t.table_schema,
t.table_name;";
public static string QueryDistributeFunctionsAndStoredProceduresInfo => @"
select 'select create_distributed_function(''""' || p.proname || '""(' || '{0}' || ')'');' as CommandTemplate,
pg_get_function_arguments(p.oid) as Arguments
from pg_proc p
left join pg_namespace n on p.pronamespace = n.oid
left join pg_language l on p.prolang = l.oid
left join pg_type t on t.oid = p.prorettype
where n.nspname not in ('pg_catalog', 'information_schema')
and n.nspname in ('public', 'workflow')
and p.proname not like '%uuid_%';
";
public static string QueryDropConstraintCommands => @"
select 'alter table '||quote_ident(ns.nspname)||'.'||quote_ident(tb.relname)||
' drop constraint '||quote_ident(conname)||';' as ddl
from pg_constraint c
join pg_class tb on tb.oid = c.conrelid
left outer join pg_inherits on pg_inherits.inhrelid = tb.oid
join pg_namespace ns on ns.oid = tb.relnamespace
where ns.nspname in ('public', 'workflow')
and c.contype in ('f', 'c')
and pg_inherits.inhrelid is null;";
public static string QueryDropTriggerCommands => @"
SELECT 'DROP TRIGGER ' || tgname || ' ON ""' || event_object_schema || '"".""' || event_object_table || '"";'
FROM information_schema.triggers
JOIN pg_trigger ON pg_trigger.tgname = information_schema.triggers.trigger_name
WHERE trigger_schema in ('public', 'workflow');";
public static string IfStatementForFutureUseInMigrations => @"
DO
$do$
BEGIN
IF EXISTS (SELECT * FROM pg_extension WHERE extname = 'citus') THEN
{COMMAND GOES HERE}
END IF;
END
$do$";
}
public class DistributeFunctionsAndStoredProceduresInfo
{
public string CommandTemplate { get; set; }
public string Arguments { get; set; }
}
// views? types?
// distrubute functions https://docs.microsoft.com/en-us/azure/postgresql/reference-hyperscale-functions
// SELECT create_distributed_function('createrolerelationship()'); - seems to only work with trigger functions - jk SELECT create_distributed_function('"func_RoleIsGroup"(bigint)');
// also need to figure out how to do complex joins
// need to apply extension uuis-ossp, triggers, to all worker nodes
}
A Few Things We Learned
This will colocate a set of tables with another table (there is also a parameter called 'colocate' to specify this when running the create_distributed_table command)
SELECT mark_tables_colocated('stores', ARRAY['products', 'line_items']);
A few changes that still need to accounted for on the quinng/citusStuffs branch.
- The Id column was dropped on the DbRoleClosures table because the id would not get autopopulated when triggers inserted new rows to this table.
- The DbUserSessions table was not distributed even though it has an accountID. It is most often not queried by the accountID. So... the following constraint had to be removed
alter table public."DbUserSessions" add constraint "FK_public.DbUserSessions_public.DbRoles_RoleID_AccountID" FOREIGN KEY ("RoleID", "AccountID") REFERENCES "DbRoles"("Id", "AccountID");
- The role_is_group function was removed because it was used in a constraint, and was having issues. This function could probably be written in a different way to get it working.
- The branch 'quinn/citusStuffs' has all the work we did to get Citus working, pay particular attention to the changes in the initial migration script.
Unit Testing
Interfaces
For interfaces that we've created exclusively for unit testing, put the interface in the same file as the implementing class.
Azure
Azure App Config
If a value was not in the azure app config before the function app started up, changes to that value will not be propogated to the app until it is restarted.
- This is still just a theory, we have not extensively tested it
- Make sure you put the values in the azure app config that the application needs before releasing the change that will use that setting
Postman
Account Management
Managing Access to Add-Ons
You may need the Admin and / or Billing role assigned to your user in order to manage access to add-ons.
You can manage user access to add-ons (like Collection Runner) by taking the following steps.
- Click the Team dropdown button in the top right (outlined in PURPLE).
- Click the Manage Team button in the dropdown (outlined in BLUE).
- In the left side navigation menu, select Product Access (outlined in orange).
- There are three tabs along to top, one for each add-on. Select the tab for the add-on you grant access to a user (outlined in YELLOW).
- Click the Add Members button (outlined in RED).
You will be shown a modal in which you can select which users have access to the add-on.
Azure Dev Ops
Build Pipelines
Allowing a build pipeline to read from a NuGet Feed in a different ADO Project
- Make sure the Build Authorization Scope is set to Project Collection
- Make sure that the right services have permission to the NuGet feed. See this Microsoft article for details. Basically, the feed needs to have contributor permission for all project and organization build services.
Offloaded Operations
Documentation of all Offloaded Operations from a development perspective
Generate SQL for migration:
Update-Database -Script -SourceMigration: [CurrentAppliedMigrationName] -TargetMigration: [MigrationToUpdateToName]
Update for updating remote DB's/connections that require authentication:
update-database -verbose -ProjectName DataAccess -ConnectionString "data source={databaseserveraddress};User={databaseUsername};password={password};initial catalog={schemaName};integrated security=False;MultipleActiveResultSets=True;App=EntityFramework" -ConfigurationTypeName UtopiaDbMigrationConfiguration -ConnectionProviderName System.Data.SqlClient
Update DB to the last state - NO VERBOSE
update-database -ProjectName DataAccess -ConnectionString "data source=(localdb)\MSSQLLocalDB;initial catalog=UtopiaDB;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework" -ConfigurationTypeName UtopiaDbMigrationConfiguration -ConnectionProviderName System.Data.SqlClient
This message comes through when I went and changed DbNodeClosures ID, needing to drop the restraint and change the Primary Key name. We were forcing users to Manual to change these, but we can use this script (or a variant of it) to do the rename automatically.
From Roman Alekhin
@BryanC this script searching constraint name in sys.key_constraints which contains constrains names for all tables. We just specify table name and constraint type (PK or UK) and receive for example primary key name for specific DB. As result we will receive correct name for any person's DB.
This will find PK or UK by table name in sys.key_constraints and generate SQL script for dropping it
This just replaces <constraitType> macro to PK
And this drops PK for all tables in list: