.middleware.grouper.grouper.5.12.0.source-code.grouper.base.properties Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of grouper Show documentation
Show all versions of grouper Show documentation
Internet2 Groups Management Toolkit
#
# Copyright 2014 Internet2
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#
# Grouper Configuration
# $Id: grouper.example.properties,v 1.48 2009-12-16 06:02:30 mchyzer Exp $
#
########################################
## Config chaining hierarchy
## Grouper uses Grouper Configuration Overlays (documented on wiki)
## By default the configuration is read from grouper.base.properties
## (which should not be edited), and the grouper.properties overlays
## the base settings. See the grouper.base.properties for the possible
## settings that can be applied to the grouper.properties
########################################
# comma separated config files that override each other (files on the right override the left)
# each should start with file: or classpath:
# e.g. classpath:grouper.example.properties, file:c:/something/myconfig.properties
# {valueType: "string", required: true, multiple: true}
grouper.config.hierarchy = classpath:grouper.base.properties, classpath:grouper.properties, database:grouper
# seconds between checking to see if the config files are updated
# {valueType: "integer", required: true}
grouper.config.secondsBetweenUpdateChecks = 600
########################################
## General settings
########################################
# used to identify your institution (e.g. in TIER instrumentation)
# {valueType: "string"}
grouper.institution.name =
# in cases where grouper is logging or emailing, it will use this to differentiate test vs dev vs prod
# {valueType: "string"}
grouper.env.name =
#put the URL which will be used e.g. in emails to users. include the webappname at the end, and nothing after that.
#e.g. https://server.school.edu/grouper/
# {valueType: "string"}
grouper.ui.url =
# tmp dir to use, will set this to the env var for tmp dir during cache operations...
# note, if you are using a backslash, you need to escape it with another, e.g. c:\\temp
# see the temp dir in logs with this in log4j.properties
# {valueType: "string"}
grouper.tmp.dir =
# main stem for grouper built in objects
# Note: there are more locations to change than just this
# {valueType: "stem"}
grouper.rootStemForBuiltinObjects = etc
#######################################
## Inititalization and configuration settings
#######################################
#if grouper should auto init the registry if not initted (i.e. insert the root stem, built in fields, etc)
#defaults to true
# {valueType: "boolean", required: true}
registry.autoinit = true
#if grouper should try and detect and log configuration errors on startup
#in general this should be true, unless the output is too annoying or if it is causing a problem
# {valueType: "boolean", required: true}
configuration.detect.errors = true
#if the startup message should display
# {valueType: "boolean", required: true}
configuration.display.startup.message = true
#if groups like the wheel group should be auto-created for convenience (note: check config needs to be on)
# {valueType: "boolean", required: true}
configuration.autocreate.system.groups = true
# auto-create groups (increment the integer index), and auto-populate with users
#(note: check config needs to be on)
# {valueType: "group", regex: "^configuration\\.autocreate\\.group\\.name\\.[0-9]+$"}
#configuration.autocreate.group.name.0 = $$grouper.rootStemForBuiltinObjects$$:uiUsers
# auto-create group description (increment the integer index)
# {valueType: "string", regex: "^configuration\\.autocreate\\.group\\.description\\.[0-9]+$"}
#configuration.autocreate.group.description.0 = users allowed to log in to the UI
#auto-create group subject ids or identifiers, comma separated, to bootstrap the registry on startup
# (increment the integer index)
# {valueType: "subject", multiple: true, regex: "^configuration\\.autocreate\\.group\\.subjects\\.[0-9]+$"}
#configuration.autocreate.group.subjects.0 = johnsmith
# if should check database and utf in new thread
# {valueType: "boolean", required: true}
configuration.checkDatabaseAndUtf.inNewThread = true
# if grouper should check to see if the database has case sensitive selects
# {valueType: "boolean", required: true}
configuration.detect.db.caseSensitive.problems = true
# if grouper should give a success message on case sensitive matching
# {valueType: "boolean", required: true}
configuration.display.db.caseSensitive.success.message = false
# (Deprecated) if grouper should check to see if utf-8 works on startup (both files and db). This
# property never worked as intended; instead of setting this, see the individual properties
# "configuration.detect.utf8.file.problems" and "configuration.detect.utf8.db.problems"
# {valueType: "boolean", required: false}
#configuration.detect.utf8.problems = false
# 2016/04/15 utf-8 checking doesnt work, we need to fix this before default to true
# if grouper should check to see if utf-8 works on startup in files
# {valueType: "boolean", required: true}
configuration.detect.utf8.file.problems = false
# if grouper should check that utf-8 works on startup in files
# {valueType: "boolean", required: true}
configuration.detect.utf8.db.problems = true
# if grouper should give a success message on utf8 inputs
# {valueType: "boolean", required: true}
configuration.display.utf8.success.message = false
# if grouper in the utf8 check will check to see if grouper supports transaction
# {valueType: "boolean", required: true}
configuration.detect.db.transaction.problems = true
# display a success message on transactions
# {valueType: "boolean", required: true}
configuration.display.transaction.success.message = false
# {valueType: "string", defaultValue: "jdbc"}
configuration.registrySubjectSource = jdbc
###################################
## Security settings
###################################
# If set to _true_, the ALL subject will be granted optin on
# each new group that is created. Note, you can override the default
# checkboxes on screen of UI in media.properties.
# {valueType: "boolean", required: true}
groups.create.grant.all.optin = false
# If set to _true_, the ALL subject will be granted optout on
# each new group that is created. Note, you can override the default
# checkboxes on screen of UI in media.properties.
# {valueType: "boolean", required: true}
groups.create.grant.all.optout = false
# If set to _true_, the ALL subject will be granted read on
# each new group that is created. Note, you can override the default
# checkboxes on screen of UI in media.properties.
# {valueType: "boolean", required: true}
groups.create.grant.all.read = false
# If set to _true_, the ALL subject will be granted view on
# each new group that is created. Note, you can override the default
# checkboxes on screen of UI in media.properties.
# {valueType: "boolean", required: true}
groups.create.grant.all.view = false
# If set to _true_, the ALL subject will be granted attrRead on
# each new group that is created. Note, you can override the default
# checkboxes on screen of UI in media.properties.
# {valueType: "boolean", required: true}
groups.create.grant.all.groupAttrRead = false
# If set to _true_, the ALL subject will be granted attrUpdate on
# each new group that is created. Note, you can override the default
# checkboxes on screen of UI in media.properties.
# {valueType: "boolean", required: true}
groups.create.grant.all.groupAttrUpdate = false
# If set to _true_, the ALL subject will be granted create on
# each new stem that is created.
# {valueType: "boolean", required: true}
stems.create.grant.all.create = false
# If set to _true_, the ALL subject will be granted admin on
# each new stem that is created.
# {valueType: "boolean", required: true}
stems.create.grant.all.stemAdmin = false
# If set to _true_, the ALL subject will be granted attrRead on
# each new stem that is created.
# {valueType: "boolean", required: true}
stems.create.grant.all.stemAttrRead = false
# If set to _true_, the ALL subject will be granted attrUpdate on
# each new stem that is created.
# {valueType: "boolean", required: true}
stems.create.grant.all.stemAttrUpdate = false
# If set to _true_, the ALL subject will be granted attrAdmin on
# each new attributeDef that is created.
# {valueType: "boolean", required: true}
attributeDefs.create.grant.all.attrAdmin = false
# If set to _true_, the ALL subject will be granted attrOptin on
# each new attributeDef that is created.
# {valueType: "boolean", required: true}
attributeDefs.create.grant.all.attrOptin = false
# If set to _true_, the ALL subject will be granted attrOptout on
# each new attributeDef that is created.
# {valueType: "boolean", required: true}
attributeDefs.create.grant.all.attrOptout = false
# If set to _true_, the ALL subject will be granted attrRead on
# each new attributeDef that is created.
# {valueType: "boolean", required: true}
attributeDefs.create.grant.all.attrRead = false
# If set to _true_, the ALL subject will be granted attrUpdate on
# each new attributeDef that is created.
# {valueType: "boolean", required: true}
attributeDefs.create.grant.all.attrUpdate = false
# If set to _true_, the ALL subject will be granted attrView on
# each new attributeDef that is created.
# {valueType: "boolean", required: true}
attributeDefs.create.grant.all.attrView = false
# If set to _true_, the ALL subject will be granted attrDefAttrRead on
# each new attributeDef that is created.
# {valueType: "boolean", required: true}
attributeDefs.create.grant.all.attrDefAttrRead = false
# If set to _true_, the ALL subject will be granted attrDefAttrAdmin on
# each new attributeDef that is created.
# {valueType: "boolean", required: true}
attributeDefs.create.grant.all.attrDefAttrUpdate = false
# if set to true, then the ALL subject will be granted view on new entities
# {valueType: "boolean", required: true}
entities.create.grant.all.view = false
# GRP-1664: do not add admin privileges to root or wheel when creating objects
# {valueType: "boolean", required: true}
privileges.assignAdminToWheelOrRootOnCreate = false
# GRP-1665: do not add admin privileges to inherited admins
# {valueType: "boolean", required: true}
privileges.assignAdminToInheritedAdminsOnCreate = false
# A wheel group allows you to enable non-GrouperSystem subjects to act
# like a root user when interacting with the registry.
# {valueType: "boolean", required: true}
groups.wheel.use = true
# Set to the name of the group you want to treat as the wheel group.
# The members of this group will be treated as root-like users.
# {valueType: "group", required: true}
groups.wheel.group = $$grouper.rootStemForBuiltinObjects$$:sysadmingroup
# A viewonly wheel group allows you to enable non-GrouperSystem subjects to act
# like a root user when viewing the registry.
# {valueType: "boolean", required: true}
groups.wheel.viewonly.use = true
# Set to the name of the group you want to treat as the viewonly wheel group.
# The members of this group will be treated as root-like users when viewing objects.
# {valueType: "group", required: true}
groups.wheel.viewonly.group = $$grouper.rootStemForBuiltinObjects$$:sysadminViewersGroup
# A readonly wheel group allows you to enable non-GrouperSystem subjects to act
# like a root user when reading the registry.
# {valueType: "boolean", required: true}
groups.wheel.readonly.use = true
# Set to the name of the group you want to treat as the readonly wheel group.
# The members of this group will be treated as root-like users when reading objects.
# {valueType: "group", required: true}
groups.wheel.readonly.group = $$grouper.rootStemForBuiltinObjects$$:sysadminReadersGroup
# To change the internal names for GrouperAll and GrouperSystem
# uncomment and change. Review UI nav.properties to ensure consistency
# {valueType: "string", required: true}
subject.internal.grouperall.name = EveryEntity
# {valueType: "string", required: true}
subject.internal.groupersystem.name = GrouperSysAdmin
# Search and sort strings for internal users
# {valueType: "string", multiple: true}
internalSubjects.searchAttribute0.el = ${subject.name},${subject.id}
# {valueType: "string"}
internalSubjects.sortAttribute0.el = ${subject.name}
#by default, anyone with admin rights on a group can edit the types or attributes
#specify types (related attributes will also be protected) which are wheel only, or restricted to a certain group
# {valueType: "boolean", required: true, regex: "^security\\.types\\.([^.]+)\\.wheelOnly$"}
#security.types.typeName.wheelOnly = true
#by default, anyone with admin rights on a group can edit the types or attributes
#specify types (related attributes will also be protected) which are wheel only, or restricted to a certain group
# {valueType: "boolean", required: true}
security.types.grouperLoader.wheelOnly = true
#by default, anyone with admin rights on a group can edit the types or attributes
#specify types (related attributes will also be protected) which are wheel only, or restricted to a certain group
# {valueType: "boolean", required: true}
security.types.grouperGroupMembershipSettings.wheelOnly = true
# if only a certain group can control the type
# {valueType: "group", required: true, regex: "^security\\.types\\.([^.]+)\\.allowOnlyGroup$"}
#security.types.typeName.allowOnlyGroup = $$grouper.rootStemForBuiltinObjects$$:someAdminGroup
# If this property is set, then to move a stem, in addition to having the appropriate stem privileges for the stem being moved and the destination stem,
# a user must also be a member of the defined group. Note that users in the wheel group will have access regardless of this property.
# {valueType: "group", required: true}
#security.stem.groupAllowedToMoveStem = $$grouper.rootStemForBuiltinObjects$$:someAdminGroup
# If this property is set, then to rename a stem, in addition to having the appropriate stem privilege for the stem being renamed,
# a user must also be a member of the defined group. Note that users in the wheel group will have access regardless of this property.
# {valueType: "group", required: true}
#security.stem.groupAllowedToRenameStem = $$grouper.rootStemForBuiltinObjects$$:someAdminGroup
# If this property is set, then to copy a stem, a user must be a member of the defined group. Note that users in the wheel group will have access regardless of this property.
# {valueType: "group", required: true}
#security.stem.groupAllowedToCopyStem = $$grouper.rootStemForBuiltinObjects$$:someAdminGroup
# By default, all users have access to sort using any of the sort strings in the member table.
# You can restrict to wheel only or to a certain group. The integer index denotes the specific string
# {valueType: "group", required: true, regex: "^security\\.member\\.sort\\.string([0-9]+)\\.allowOnlyGroup$"}
#security.member.sort.string0.allowOnlyGroup = $$grouper.rootStemForBuiltinObjects$$:someGroup
# By default, all users have access to sort using any of the sort strings in the member table.
# You can restrict to wheel only or to a certain group. The integer index denotes the specific string
# {valueType: "boolean", required: true, regex: "^security\\.member\\.sort\\.string([0-9]+)\\.wheelOnly$"}
#security.member.sort.string0.wheelOnly = true
# By default, all users have access to search strings in the member table.
# You can restrict to wheel only or to a certain group. The integer index denotes the specific string
# {valueType: "group", required: true, regex: "^security\\.member\\.search\\.string([0-9]+)\\.allowOnlyGroup$"}
#security.member.search.string0.allowOnlyGroup = $$grouper.rootStemForBuiltinObjects$$:someGroup
# By default, all users have access to search strings in the member table.
# You can restrict to wheel only or to a certain group. The integer index denotes the specific string
# {valueType: "boolean", required: true, regex: "^security\\.member\\.search\\.string([0-9]+)\\.wheelOnly$"}
#security.member.search.string2.wheelOnly = true
# if all folders should be shown only if there is an object inside that the user can see (or a privilege on that folder).
# this has been re-coded and is the new setting. The old setting "security.show.folders.where.user.can.see.subobjects" is not used anymore
# {valueType: "boolean", required: true}
security.folders.are.viewable.by.all = false
# put in a group name to exclude non admins who have a lot of privileges who have bad performance
# {valueType: "group"}
security.show.all.folders.if.in.group = $$grouper.rootStemForBuiltinObjects$$:sysadminStemViewers
# recalc in change log if the user has needed privileges in the last X seconds, default to 604800 which is one week
# so if someone has needed stem view privileges in the last week, then have the change log keep it up to date
# 0 means dont do this for anyone (full recalc each time), -1 means do this for everyone who has ever checked stem view,
# other negative values are not valid.
# {valueType: "integer"}
security.folders.view.privileges.recalcChangeLog.ifNeededInLastSeconds = 604800
# log error if performance is above this number of seconds. tells you to exclude some users or disable feature
# leave blank or -1 to disable
# {valueType: "integer", required: true}
security.show.all.folders.log.above.seconds = 30
# log security folder view privilege change log consumer
# {valueType: "boolean", required: true}
security.folder.view.privileges.changeLogConsumer.log = false
# log security folder view privilege full daemon
# {valueType: "boolean", required: true}
security.folder.view.privileges.fullDaemon.log = false
# group which pre-loads stem view privileges in the full daemon run. Run the full to prime the privileges or wait for it to run
# {valueType: "String", required: true}
security.folder.view.privileges.precompute.group = $$grouper.rootStemForBuiltinObjects$$:privilege:stemViewPrecompute
###################################
## Member sort and search
###################################
# Attributes of members are kept in the grouper_members table to allow easy sorting and searching (for instance when listing group members).
# When performing a sort or search and an index is not specified, then a default index will be used as configured below. The value is comma-separated,
# so that if the user does not have access to the first index, then next will be tried and so forth.
# Note: all sources should have attributes configured for all default indexes.
# {valueType: "integer", required: true}
member.search.defaultIndexOrder=0
# {valueType: "integer", required: true}
member.sort.defaultIndexOrder=0
###################################
## Database confirmation of changes
## whitelist (allow) and blacklist (deny) for db/ldap data or object deletes, without prompting the user to confirm
## if a listing is in the whitelist (allow), it will be allowed to delete db/ldap
## if a listing is in the blacklist (deny), it will be denied from deleting db/ldap
## multiple inputs can be entered with .0, .1, .2, etc. These numbers must be sequential, starting with 0
## for ldap, the user will be something like this: uid=admin,ou=system
## for ldap, the url will be something like this: ldap://localhost:10389
###################################
# allow this database user to make changes to the DDL without confirmation (e.g. non-prod, testing)
# {valueType: "string", required: true, regex: "^db\\.change\\.allow\\.user\\.([0-9]+)$"}
db.change.allow.user.0=grouper_v5abc
# allow this database user to make changes to the DDL without confirmation (e.g. non-prod, testing)
# {valueType: "string", required: true, regex: "^db\\.change\\.allow\\.url\\.([0-9]+)$"}
db.change.allow.url.0=jdbc:postgresql://localhost:5432/postgres?currentSchema=grouper_v5abc
# allow this database user to make changes to the DDL without confirmation (e.g. non-prod, testing)
# {valueType: "string", required: true, regex: "^db\\.change\\.allow\\.user\\.([0-9]+)$"}
db.change.allow.user.1=grouper1
# allow this database user to make changes to the DDL without confirmation (e.g. non-prod, testing)
# {valueType: "string", required: true}
db.change.allow.url.1=jdbc:mysql://localhost:3306/grouper1?useSSL=false
# allow this database user to make changes to the DDL without confirmation (e.g. non-prod, testing)
# {valueType: "string", required: true}
db.change.deny.user.0=grouper2
# allow this database user to make changes to the DDL without confirmation (e.g. non-prod, testing)
# {valueType: "string", required: true}
db.change.deny.url.0=jdbc:mysql://localhost:3306/grouper2?useSSL=false
# if should give error when detect driver mismatch (set to false if using an
# unknown driver, and tell the grouper team so we can add to list)
# {valueType: "boolean", required: true}
db.log.driver.mismatch = true
###################################
## Grouper include / exclude and requireGroups
## If enabled, will make sure the Type is installed, and when that type is
## applied to a group, it will auto-create the other groups needed to manage the include and exclude lists
## see: https://bugs.internet2.edu/jira/browse/GRP-178
## the naming settings below are only used when the type is applied to a group, will not affect
## existing include/exclude groups
###################################
#if the addIncludeExclude and requireInGroups should be enabled, and if the type(s) should be
#auto-created, and used to auto create groups to facilitate include and exclude lists, and require lists
# {valueType: "boolean", required: true}
grouperIncludeExclude.use = false
# {valueType: "boolean", required: true}
grouperIncludeExclude.requireGroups.use = false
# for requireGroups (groups that the members must be to be in the overall group). name is the name of the attribute or type.
# note attributes are a global namespace, so you might want to use a naming convention,
# e.g. prefix with "require". increment the integer to add multiple
# {valueType: "string", required: true, regex: "^grouperIncludeExclude\\.requireGroup\\.name\\.([0-9]+)$"}
#grouperIncludeExclude.requireGroup.name.0 = requireActiveEmployee
# requireGroups: attributeOrType is either attribute for an attribute underneath the requireInGroups type, or type to be a top level type.
# increment the integer to add multiple
# {valueType: "string", required: true, regex: "^grouperIncludeExclude\\.requireGroup\\.attributeOrType\\.([0-9]+)$"}
#grouperIncludeExclude.requireGroup.attributeOrType.0 = type
# requireGroups: group that is required ("and"ed). increment the integer to add multiple
# {valueType: "group", required: true, regex: "^grouperIncludeExclude\\.requireGroup\\.group\\.([0-9]+)$"}
#grouperIncludeExclude.requireGroup.group.0 = school:community:activeEmployee
# requireGroups: description is the tooltip. increment the integer to add multiple
# {valueType: "string", regex: "^grouperIncludeExclude\\.requireGroup\\.description\\.([0-9]+)$"}
#grouperIncludeExclude.requireGroup.description.0 = If value is true, members of the overall group must be an active employee (in the school:community:activeEmployee group). Otherwise, leave this value not filled in.
# set name for include/exclude
# {valueType: "string"}
grouperIncludeExclude.type.name = addIncludeExclude
# set tooltip for include/exclude
# {valueType: "string"}
grouperIncludeExclude.tooltip = Select this type to auto-create other groups which facilitate having include and exclude list
# set name for requireGroups
# {valueType: "string"}
grouperIncludeExclude.requireGroups.type.name = requireInGroups
# set tooltip for requireGroups
# {valueType: "string"}
grouperIncludeExclude.requireGroups.tooltip = Select this type to auto-create other groups which set up group math so that other groups can be required for membership (e.g. activeEmployee)
# require also in groups (ad hoc)
# leave grouperIncludeExclude.andGroups.attributeName blank if you dont want to use this attribute...
# though if you were using it, it wont remove already configured groups
# {valueType: "string"}
grouperIncludeExclude.requireGroups.attributeName = requireAlsoInGroups
# toolip for require also in groups
# {valueType: "string"}
grouperIncludeExclude.requireGroups.attribute.tooltip = Enter in comma separated group path(s). An entity must be in these groups for it to be in the overall group. e.g. stem1:stem2:group1, stem1:stem3:group2
#suffixes for various include/exclude groups (can use ${space} for space).
#note, these should uniquely identify various parts of the include/exclude.
#i.e. if the grouperIncludeExclude type is applied to a group with a suffix of the include suffix,
#the other groups will not be created...
# {valueType: "string"}
grouperIncludeExclude.systemOfRecord.extension.suffix = _systemOfRecord
# suffix for include group of include/exclude
# {valueType: "string"}
grouperIncludeExclude.include.extension.suffix = _includes
# suffix for exclude group of include/exclude
# {valueType: "string"}
grouperIncludeExclude.exclude.extension.suffix = _excludes
# suffix for system-of_record and includes (virtual union) group of include/exclude
# {valueType: "string"}
grouperIncludeExclude.systemOfRecordAndIncludes.extension.suffix = _systemOfRecordAndIncludes
# suffix for includes minus excludes group of include/exclude
# {valueType: "string"}
grouperIncludeExclude.includesMinusExcludes.extension.suffix = _includesMinusExcludes
# suffix of the require groups helper group
# note, put a ${i} in there for where the 1 based index will go
# {valueType: "string"}
grouperIncludeExclude.requireGroups.extension.suffix = _requireGroups${i}
# display extension suffix for system of record group
# suffixes for various include/exclude groups (can use ${space} for space)
# {valueType: "string"}
grouperIncludeExclude.systemOfRecord.displayExtension.suffix = ${space}system of record
# display extension suffix for include group
# {valueType: "string"}
grouperIncludeExclude.include.displayExtension.suffix = ${space}includes
# display extension suffix for exclude group
# {valueType: "string"}
grouperIncludeExclude.exclude.displayExtension.suffix = ${space}excludes
# display extension suffix for system of record and include group
# {valueType: "string"}
grouperIncludeExclude.systemOfRecordAndIncludes.displayExtension.suffix = ${space}system of record and includes
# display extension suffix for include minus exclude group. this is used if you have include/exclude and requireGroups
# {valueType: "string"}
grouperIncludeExclude.includesMinusExcludes.displayExtension.suffix = ${space}includes minus excludes
# require gruops display extension suffix.
# note, put a ${i} in there for where the 1 based index will go
# {valueType: "string"}
grouperIncludeExclude.requireGroups.displayExtension.suffix = ${space}requireGroups ${i}
# include/exclude overall description
#can use ${extension} as the group extension, or ${displayExtension} for group display extension
# {valueType: "string"}
grouperIncludeExclude.overall.description = Group containing list of ${displayExtension} after adding the includes and subtracting the excludes
# include/exclude systemOfRecord description
# {valueType: "string"}
grouperIncludeExclude.systemOfRecord.description = Group containing list of ${displayExtension} (generally straight from the system of record) without yet considering manual include or exclude lists
# include/exclude include description
# {valueType: "string"}
grouperIncludeExclude.include.description = Group containing manual list of includes for group ${displayExtension} which will be added to the system of record list (unless the subject is also in the excludes group)
# include/exclude exclude description
# {valueType: "string"}
grouperIncludeExclude.exclude.description = Group containing manual list of excludes for group ${displayExtension} which will not be in the overall group
# include/exclude systemOfRecord-and-includes description
# {valueType: "string"}
grouperIncludeExclude.systemOfRecordAndIncludes.description = Internal utility group for group ${displayExtension} which facilitates the group math for the include and exclude lists
# include/exclude includes minus excludes description
# {valueType: "string"}
grouperIncludeExclude.includesMinusExclude.description = Internal utility group for group ${displayExtension} which facilitates includes, excludes, and required groups (e.g. activeEmployee)
# requireGroups description
# note, put a ${i} in there for where the 1 based index will go
# {valueType: "string"}
grouperIncludeExclude.requireGroups.description = Internal utility group for group ${displayExtension} which facilitates required groups (e.g. activeEmployee)
# if should use transaction in include/exclude
# {valueType: "boolean", required: true}
grouperIncludeExcludeUseTransaction = true
###################################
## Composites
###################################
# When immediate membership changes are made, if the group being modified matches this regex,
# then composite membership changes will be made synchronously instead of by the daemon
# {valueType: "string"}
composites.synchronousCalculationGroupNameRegex =
###################################
## Subject settings
###################################
# if finding across multiple threadable sources, use threads to do the work faster
# {valueType: "boolean", required: true}
subjects.allPage.useThreadForkJoin = false
# if finding across multiple threadable sources, use threads to do the work faster
# {valueType: "boolean", required: true}
subjects.idOrIdentifier.useThreadForkJoin = false
# if the creator and last updater should be group subject attributes (you get
# a performance gain if you set to false, but if true you can see subject id from UI in 2.0
# {valueType: "boolean", required: true}
subjects.group.useCreatorAndModifierAsSubjectAttributes = true
# customize subjects by implementing this interface: edu.internet2.middleware.grouper.subj.SubjectCustomizer
# or extending this class: edu.internet2.middleware.grouper.subj.SubjectCustomizerBase (recommended)
# note the instance will be reused to make sure it is threadsafe
# {valueType: "class", mustExtendClass: "edu.internet2.middleware.grouper.subj.SubjectCustomizerBase"}
subjects.customizer.className =
# if we should use a root session if one isnt started for subject lookups (behavior in v2.0-
# {valueType: "boolean", required: true}
subjects.startRootSessionIfOneIsntStarted = false
###################################
## Hooks
## You can register multiple classes for one hook base class by comma separating the hooks implementations
## You can also register hooks at runtime with:
## GrouperHookType.addHookManual("hooks.group.class", YourSchoolGroupHooks2.class);
###################################
#implement a group attribute hook by extending edu.internet2.middleware.grouper.hooks.AttributeHooks
# {valueType: "class", mustExtendClass: "edu.internet2.middleware.grouper.hooks.AttributeHooks"}
#hooks.attribute.class=edu.yourSchool.it.YourSchoolGroupHooks,edu.yourSchool.it.YourSchoolGroupHooks2
#implement an attribute def hook by extending edu.internet2.middleware.grouper.hooks.AttributeDefHooks
# {valueType: "class", mustExtendClass: "edu.internet2.middleware.grouper.hooks.AttributeDefHooks"}
#hooks.attributeDef.class=edu.yourSchool.it.YourSchoolAttributeDefHooks,edu.yourSchool.it.YourSchoolAttributeDefHooks2
#implement an attribute def name hook by extending edu.internet2.middleware.grouper.hooks.AttributeDefNameHooks
# {valueType: "class", mustExtendClass: "edu.internet2.middleware.grouper.hooks.AttributeDefNameHooks"}
#hooks.attributeDefName.class=edu.yourSchool.it.YourSchoolAttributeDefNameHooks,edu.yourSchool.it.YourSchoolAttributeDefNameHooks2
#implement an attribute assign hook by extending edu.internet2.middleware.grouper.hooks.AttributeAssignHooks
# {valueType: "class", mustExtendClass: "edu.internet2.middleware.grouper.hooks.AttributeAssignHooks"}
#hooks.attributeAssign.class=edu.yourSchool.it.YourSchoolAttributeAssignHooks,edu.yourSchool.it.YourSchoolAttributeAssignHooks2
#implement an attribute assign hook by extending edu.internet2.middleware.grouper.hooks.AttributeAssignValueHooks
# {valueType: "class", mustExtendClass: "edu.internet2.middleware.grouper.hooks.AttributeAssignValueHooks"}
#hooks.attributeAssignValue.class=edu.yourSchool.it.YourSchoolAttributeAssignValueHooks,edu.yourSchool.it.YourSchoolAttributeAssignValueHooks2
#implement a group hook by extending edu.internet2.middleware.grouper.hooks.GroupHooks
# {valueType: "class", mustExtendClass: "edu.internet2.middleware.grouper.hooks.GroupHooks"}
#hooks.group.class=edu.yourSchool.it.YourSchoolGroupHooks,edu.yourSchool.it.YourSchoolGroupHooks2
#implement a grouper lifecycle hook by extending edu.internet2.middleware.grouper.hooks.LifecycleHooks
# {valueType: "class", mustExtendClass: "edu.internet2.middleware.grouper.hooks.LifecycleHooks"}
#hooks.lifecycle.class=edu.yourSchool.it.YourSchoolLifecycleHooks
#implement a membership hook by extending edu.internet2.middleware.grouper.hooks.MembershipHooks
# {valueType: "class", mustExtendClass: "edu.internet2.middleware.grouper.hooks.MembershipHooks"}
#hooks.membership.class=edu.yourSchool.it.YourSchoolMembershipHooks
#implement a member hook by extending edu.internet2.middleware.grouper.hooks.MemberHooks
# {valueType: "class", mustExtendClass: "edu.internet2.middleware.grouper.hooks.MemberHooks"}
#hooks.member.class=edu.yourSchool.it.YourSchoolMemberHooks
#implement a stem hook by extending edu.internet2.middleware.grouper.hooks.StemHooks
# {valueType: "class", mustExtendClass: "edu.internet2.middleware.grouper.hooks.StemHooks"}
#hooks.stem.class=edu.yourSchool.it.YourSchoolStemHooks
#implement a composite hook by extending edu.internet2.middleware.grouper.hooks.CompositeHooks
# {valueType: "class", mustExtendClass: "edu.internet2.middleware.grouper.hooks.CompositeHooks"}
#hooks.composite.class=edu.yourSchool.it.YourSchoolCompositeHooks
#implement a field hook by extending edu.internet2.middleware.grouper.hooks.FieldHooks
# {valueType: "class", mustExtendClass: "edu.internet2.middleware.grouper.hooks.FieldHooks"}
#hooks.field.class=edu.yourSchool.it.YourSchoolFieldHooks
#implement a grouperSession hook by extending edu.internet2.middleware.grouper.hooks.GrouperSessionHooks
# {valueType: "class", mustExtendClass: "edu.internet2.middleware.grouper.hooks.GrouperSessionHooks"}
#hooks.grouperSession.class=edu.yourSchool.it.YourSchoolGrouperSessionHooks
#implement a groupType hook by extending edu.internet2.middleware.grouper.hooks.GroupTypeHooks
# {valueType: "class", mustExtendClass: "edu.internet2.middleware.grouper.hooks.GroupTypeHooks"}
#hooks.groupType.class=edu.yourSchool.it.YourSchoolGroupTypeHooks
#implement a groupTypeTuple hook by extending edu.internet2.middleware.grouper.hooks.GroupTypeTupleHooks
# {valueType: "class", mustExtendClass: "edu.internet2.middleware.grouper.hooks.GroupTypeTupleHooks"}
#hooks.groupTypeTuple.class=edu.yourSchool.it.YourSchoolGroupTypeTupleHooks
#implement a loader hook by extending edu.internet2.middleware.grouper.hooks.LoaderHooks
# {valueType: "class", mustExtendClass: "edu.internet2.middleware.grouper.hooks.LoaderHooks"}
#hooks.loader.class=edu.yourSchool.it.YourSchoolLoaderHooks
#implement an external subject hook by extending edu.internet2.middleware.grouper.hooks.ExternalSubjectHooks
# {valueType: "class", mustExtendClass: "edu.internet2.middleware.grouper.hooks.ExternalSubjectHooks"}
#hooks.externalSubject.class=edu.yourSchool.it.YourSchoolExternalSubjectHooks
# if the edu.internet2.middleware.grouper.hooks.examples.GroupUniqueExtensionHook is case insensitive
# {valueType: "boolean", required: true}
hook.group.unique.extension.caseInsensitive = false
# if the auto assign attribute assign hook should be auto registered
# {valueType: "boolean", required: true}
grouperHook.attributeAssign.autoAssign.autoRegister = true
# if the auto register hook checks groups to see if new memberships are valid
# {valueType: "boolean", required: true}
grouperHook.MembershipRequireMembershipHook.autoRegister = true
# if the auto register hook checks stems with same name case insensitive
# {valueType: "boolean", required: true}
grouperHook.StemUniqueNameCaseInsensitiveHook.autoRegister = true
# if the auto register hook checks groups with same name case insensitive
# {valueType: "boolean", required: true}
grouperHook.GroupUniqueNameCaseInsensitiveHook.autoRegister = true
# if the auto register hook checks attribute defs with same name case insensitive
# {valueType: "boolean", required: true}
grouperHook.AttributeDefUniqueNameCaseInsensitiveHook.autoRegister = true
# if the auto register hook checks attribute def names with same name case insensitive
# {valueType: "boolean", required: true}
grouperHook.AttributeDefNameUniqueNameCaseInsensitiveHook.autoRegister = true
# if the hook to veto deprovisioned users should be registered
# {valueType: "boolean", required: true}
grouperHook.MembershipVetoIfDeprovisionedHook.autoRegister = true
###################################
## Rules
###################################
# Rules users who are in the following group can use the actAs field to act as someone else
# You can put multiple groups separated by commas. e.g. a:b:c, e:f:g
# You can put a single entry as the group the calling user has to be in, and the grouper the actAs has to be in
# separated by 4 colons
# e.g. if the configured values is: a:b:c, e:f:d :::: r:e:w, x:e:w
# then if the calling user is in a:b:c or x:e:w, then the actAs can be anyone
# if not, then if the calling user is in e:f:d, then the actAs must be in r:e:w. If multiple rules, then
# if one passes, then it is a success, if they all fail, then fail.
# {valueType: "string"}
rules.act.as.group =
# any actAs subject in this group has access to more objects when the EL fires on
# the IF or THEN EL clause
# {valueType: "group"}
rules.accessToApiInEl.group =
# cache the decision to allow a user to actAs another, so it doesnt have to be calculated each time
# defaults to 30 minutes
# {valueType: "integer", required: true}
rules.act.as.cache.minutes = 30
# uuids (comma separated) of the attribute assign record which is the rule type to the owner object
# e.g. SELECT gaagv.attribute_assign_id FROM grouper_attr_asn_group_v gaagv WHERE gaagv.attribute_def_name_name LIKE '%:rule' AND gaagv.group_name = 'stem:a'
# make sure log info level is set for RuleEngine
# log4j.logger.edu.internet2.middleware.grouper.rules.RuleEngine = INFO
# {valueType: "string"}
rules.attributeAssignTypeIdsToLog = abc1234abc123, def456def345
# if this is true, then log a lot of info about why rules do or do not fire... only turn on temporarily
# since it takes a lot of resources... note you need log DEBUG set for the rules engine in log4j.properties too e.g.
# log4j.logger.edu.internet2.middleware.grouper.rules = DEBUG
# {valueType: "boolean", required: true}
rules.logWhyRulesDontFire = false
# put in fully qualified classes to add to the EL context. Note that they need a default constructor
# comma separated. The alias will be the simple class name without a first cap.
# e.g. if the class is test.Test the alias is "test"
# {valueType: "class", multiple: true}
rules.customElClasses =
# If the CHECK, IF, and THEN are all exactly what is needed for managing inherited stem privileges
# Then allow an actAs GrouperSystem in source g:isa
# {valueType: "boolean", required: true}
rules.allowActAsGrouperSystemForInheritedStemPrivileges =
# If not blank, then keep email templates in this folder instead of classpath
# If in classpath, it is classpath: grouperRulesEmailTemplates/someTemplate.txt
# {valueType: "string"}
rules.emailTemplatesFolder =
# If not blank, then only allow members of this group to create rules in the UI
# {valueType: "string"}
rules.restrictRulesUiToMembersOfThisGroupName =
# If not blank, then only allow members of this group to send emails from rules
# {valueType: "string"}
rules.restrictRulesEmailSendersToMembersOfThisGroupName =
# If not blank, then rules associated with these groups require at least VIEW access on the groups and folders associated with the rules
# {valueType: "string"}
rules.groupNamesRestrictRules =
# If not blank, then rules associated with these folders require at least VIEW access on the groups and folders associated with the rules
# {valueType: "string"}
rules.stemNamesRestrictRules =
# if in daemon check to see if restricted folders have memberships or privileges from subjects in restricted group
# and remove them
# {valueType: "boolean", required: true}
grouperRuleDaemon_GRP_2143_Remove_memberships_from_restricted_stem_when_removed_from_dependent_group = true
# if in change log check to see if removed users from restricted group has memberships or privileges in folders
# and remove them
# {valueType: "boolean", required: true}
grouperRuleChangeLog_GRP_2143_Remove_memberships_from_restricted_stem_when_removed_from_dependent_group = true
###################################
## Group attribute validation via regex
## You can attach a regex to an attribute name (including built ins)
## If none are registered, the built in hook will not be enabled
## The built ins are description, displayName, extension, displayExtension, name
## Configure a group.attribute.validator.attributeName.X for attribute name
## group.attribute.validator.regex.X for the regex
## group.attribute.validator.vetoMessage.X for the veto message (can contain the variable $attributeValue$ which will substitute)
## the X must be a sequential integer which groups the config entries together.
## do not repeat two config entries
###################################
# if there is not another group extension validation, then validate by alphanumerics, underscore, and dash
# {valueType: "boolean", required: true}
group.validateExtensionByDefault = true
# if there is not another stem extension validation, then validate by alphanumerics, underscore, and dash
# {valueType: "boolean", required: true}
stem.validateExtensionByDefault = true
# if there is not another attributeDef extension validation, then validate by alphanumerics, underscore, and dash
# {valueType: "boolean", required: true}
attributeDef.validateExtensionByDefault = true
# if there is not another attributeDefName extension validation, then validate by alphanumerics, underscore, and dash
# {valueType: "boolean", required: true}
attributeDefName.validateExtensionByDefault = true
# Attach a regex validator by attribute name. This is the attribute name
# {valueType: "string", required: true, regex: "^group\\.attribute\\.validator\\.attributeName\\.([0-9]+)$"}
# group.attribute.validator.attributeName.0=extension
# Attach a regex validator by attribute name. This is the regex
# {valueType: "string", required: true, regex: "^group\\.attribute\\.validator\\.regex\\.([0-9]+)$"}
# group.attribute.validator.regex.0=^[a-zA-Z0-9]+$
# Attach a regex validator by attribute name. This is the veto message if a group create has an invalid attribute
# {valueType: "string", required: true, regex: "^group\\.attribute\\.validator\\.vetoMessage\\.([0-9]+)$"}
# group.attribute.validator.vetoMessage.0=Group ID '$attributeValue$' is invalid since it must contain only alpha-numerics
###################################
## Stem attribute validation via regex
## You can attach a regex to an attribute name (including built ins)
## If none are registered, the built in hook will not be enabled
## The built ins are description, displayName, extension, displayExtension, name
## Configure a stem.attribute.validator.attributeName.X for attribute name
## stem.attribute.validator.regex.X for the regex
## stem.attribute.validator.vetoMessage.X for the veto message (can contain the variable $attributeValue$ which will substitute)
## the X must be a sequential integer which groups the config entries together.
## do not repeat two config entries
###################################
# Attach a regex validator by attribute name. This is the attribute name
# {valueType: "string", required: true, regex: "^stem\\.attribute\\.validator\\.attributeName\\.([0-9]+)$"}
# stem.attribute.validator.attributeName.0=extension
# Attach a regex validator by attribute name. This is the regex
# {valueType: "string", required: true, regex: "^stem\\.attribute\\.validator\\.regex\\.([0-9]+)$"}
# stem.attribute.validator.regex.0=^[a-zA-Z0-9]+$
# Attach a regex validator by attribute name. This is the veto message if a stem create has an invalid attribute
# {valueType: "string", required: true, regex: "^stem\\.attribute\\.validator\\.vetoMessage\\.([0-9]+)$"}
# stem.attribute.validator.vetoMessage.0=Stem ID '$attributeValue$' is invalid since it must contain only alpha-numerics
###################################
## Attribute def field validation via regex
## You can attach a regex to a field name (including built ins)
## If none are registered, the built in hook will not be enabled
## The built ins are description, extension, name
## Configure a attributeDef.attribute.validator.attributeName.X for attribute name
## attributeDef.attribute.validator.regex.X for the regex
## attributeDef.attribute.validator.vetoMessage.X for the veto message (can contain the variable $attributeValue$ which will substitute)
## the X must be a sequential integer which groups the config entries together.
## do not repeat two config entries
###################################
# Attach a regex validator by field name. This is the field name
# {valueType: "string", required: true, regex: "^attributeDef\\.attribute\\.validator\\.attributeName\\.([0-9]+)$"}
# attributeDef.attribute.validator.attributeName.0=extension
# Attach a regex validator by field name. This is the regex
# {valueType: "string", required: true, regex: "^attributeDef\\.attribute\\.validator\\.regex\\.([0-9]+)$"}
# attributeDef.attribute.validator.regex.0=^[a-zA-Z0-9]+$
# Attach a regex validator by field name. This is the veto message if an attributeDef create has an invalid field
# {valueType: "string", required: true, regex: "^attributeDef\\.attribute\\.validator\\.vetoMessage\\.([0-9]+)$"}
# attributeDef.attribute.validator.vetoMessage.0=AttributeDef ID '$attributeValue$' is invalid since it must contain only alpha-numerics
###################################
## Attribute def name field validation via regex
## You can attach a regex to a field name (including built ins)
## If none are registered, the built in hook will not be enabled
## The built ins are description, displayName, extension, displayExtension, name
## Configure a attributeDefName.attribute.validator.attributeName.X for attribute name
## attributeDefName.attribute.validator.regex.X for the regex
## attributeDefName.attribute.validator.vetoMessage.X for the veto message (can contain the variable $attributeValue$ which will substitute)
## the X must be a sequential integer which groups the config entries together.
## do not repeat two config entries
###################################
# Attach a regex validator by field name. This is the field name
# {valueType: "string", required: true, regex: "^attributeDefName\\.attribute\\.validator\\.attributeName\\.([0-9]+)$"}
#attributeDefName.attribute.validator.attributeName.0=extension
# Attach a regex validator by attribute name. This is the regex
# {valueType: "string", required: true, regex: "^attributeDefName\\.attribute\\.validator\\.regex\\.([0-9]+)$"}
#attributeDefName.attribute.validator.regex.0=^[a-zA-Z0-9]+$
# Attach a regex validator by attribute name. This is the veto message if an attributeDefName create has an invalid attribute
# {valueType: "string", required: true, regex: "^attributeDefName\\.attribute\\.validator\\.vetoMessage\\.([0-9]+)$"}
#attributeDefName.attribute.validator.vetoMessage.0=AttributeDefName ID '$attributeValue$' is invalid since it must contain only alpha-numerics
#####################################
## Audit settings
#####################################
# if set to true, then exceptions will be thrown if any actions are not audited... exceptions
# should not be thrown since everything should be audited, so this is a switch to make it absorb
# errors if there is a problem (will be logged instead if second param is true)
# {valueType: "boolean", required: true}
audit.requireAuditsForAllActions = false
# if should log audits for missing actions
# {valueType: "boolean", required: true}
audit.logAuditsForMissingActions = false
# max length of text fields in audit if the DB has a constraint. Might need to set to 2675 for some versions / configs of postgres
# {valueType: "integer", required: true}
audit.maxLengthTruncateTextFieldsIndexed = 4000
#####################################
## Change log settings
#####################################
# if we should insert records into grouper_change_log_temp when events happen
# defaults to true. Note, it is not currently supported to set this to false...
# {valueType: "boolean", required: true}
changeLog.enabled = true
#####################################
## Settings to track last membership changes for groups and stems.
#####################################
# If true, when an immediate membership changes for a group (either a privilege or a list member),
# then an update will be made to the lastImmediateMembershipChange property for the group.
# {valueType: "boolean", required: true}
groups.updateLastImmediateMembershipTime = false
# If true, when an immediate, composite, or effective membership changes for a group (either a privilege or a list member),
# then an update will be made to the lastMembershipChange property for the group.
# {valueType: "boolean", required: true}
groups.updateLastMembershipTime = false
# If true, when an immediate or effective membership changes for a stem (this would be a naming privilege),
# then an update will be made to the lastMembershipChange property for the stem.
# {valueType: "boolean", required: true}
stems.updateLastMembershipTime = false
#####################################
## Database structure data definition language (DDL) settings
#####################################
# ddlutils db name will be set by default, you can override it here, it must be one of:
# mysql, mysql5, oracle, oracle10, oracle9, postgresql
# {valueType: "string"}
#ddlutils.dbname.override = oracle10
# if you want to not create the subject tables (grouper examples for unit testing),
# then set this to true
# {valueType: "boolean", required: true}
ddlutils.exclude.subject.tables = false
# set the path where ddl scripts are generated (they will be uniquely named in this directory).
# if blank, the directory used will be the current directory
# {valueType: "string"}
ddlutils.directory.for.scripts = ddlScripts
# during schema export, should it install grouper data also or not. e.g. insert the root stem, default true
# {valueType: "boolean", required: true}
ddlutils.schemaexport.installGrouperData = true
# when grouper starts, should it shut down if not right version?
# {valueType: "boolean", required: true}
ddlutils.failIfNotRightVersion = true
# after you have converted id's, and are happy with the conversion of removing the uuid col,
# this will remove the backup uuid cols when running the gsh command: gsh -registry -deep
# {valueType: "boolean", required: true}
ddlutils.dropBackupUuidCols = false
# after you have converted field id foreign keys, and are happy with the conversion of removing the attribute name,
# membership list name, and type cols,
# this will remove the backup field name/type cols when running the gsh command: gsh -registry -deep
# {valueType: "boolean", required: true}
ddlutils.dropBackupFieldNameTypeCols = false
# before the group name etc was moved to the grouper_groups table, the attributes table
# was backed up. If it should not be backed up, or if the upgrade is done and works, then it can
# be removed, set to true, run: gsh -registry -deep
# {valueType: "boolean", required: true}
ddlutils.dropAttributeBackupTableFromGroupUpgrade = false
# Since grouper_memberships no longer has effective memberships, that table doesn't need via_id,
# depth and parent_membership. If they were converted, this will drop the backup of those cols with: gsh -registry -deep
# {valueType: "boolean", required: true}
ddlutils.dropMembershipBackupColsFromOwnerViaUpgrade = false
# After legacy attributes are converted, the backed up tables can be dropped with: gsh -registry -deep
# {valueType: "boolean", required: true}
ddlutils.dropLegacyAttributes = false
# this is the schema ddlutils uses to query metadata with jdbc. usually this can be omitted,
# and it defaults to your database loginid, however, in postgres, it can be different, so enter here
# in sql server, it might need to be: dbo
# {valueType: "string"}
#ddlutils.schema = public
#if you are running a DB that supports them, but you dont want them, disable comments here (defaults to false)
# {valueType: "boolean", required: true}
ddlutils.disableComments = false
#set to true and we wont subsitute varchar 4000 for text in mysql (wont work in innodb utf-8 databases
# {valueType: "boolean", required: true}
ddlutils.dontSubstituteVarchar4000forTextMysql = false
# this is obscure, but if you are having trouble with direct sql for attribute updates, set this to false
# {valueType: "boolean", required: true}
grouperAllowSqlOnAttributeValueUpdate = true
# if you want to change the max size for names of groups. Note, cant be larger than the
# database column and unicode might take extra chars. i.e. if you want to make it smaller that is fine.
# this is for object name and display name
# the default is 1024 or 900 for SQL server
# {valueType: "integer"}
grouper.groupName.maxSize =
# if you want to change the max size for names of attributeDefs. Note, cant be larger than the
# database column and unicode might take extra chars. i.e. if you want to make it smaller that is fine.
# this is for object name and display name
# the default is 1024 or 900 for SQL server
# {valueType: "integer"}
grouper.nameOfAttributeDef.maxSize =
# if you want to change the max size for names of attributeDefNames. Note, cant be larger than the
# database column and unicode might take extra chars. i.e. if you want to make it smaller that is fine.
# this is for object name and display name
# the default is 1024 or 900 for SQL server
# {valueType: "integer"}
grouper.nameOfAttributeDefName.maxSize =
# if you want to change the max size for names of folders. Note, cant be larger than the
# database column and unicode might take extra chars. i.e. if you want to make it smaller that is fine.
# this is for object name and display name
# the default is 1024 or 900 for SQL server
# default for stem name in 2.3 and before is 255: GRP-1807: grouper folder names limited to 255 but should be longer
# {valueType: "integer"}
grouper.stemName.maxSize =
#####################################
## Mail settings
#####################################
#smtp server is a domain name or dns name. set to "testing" if you want to log instead of send. eg: whatever.school.edu
# {valueType: "string"}
mail.smtp.server =
#leave blank if unauthenticated
# {valueType: "string"}
#mail.smtp.user =
#leave blank if unauthenticated
# {valueType: "password", sensitive: true}
#mail.smtp.pass =
# comma separated group name and uuid's to be allow email addresses to dereference.
# for instance: a:b:c@grouper, def345@grouper
# If a configuration enters in one of those email addresses, and it is in this allow list, then
# dereference the group and member and send email to their individual email addresses. Note that
# groups in this list can have their members discovered so treat their membership as non private.
# using the uuid@grouper gives a little bit of obscurity since the uuid of the group needs to be known
# is it is still security by obscurity which is not true security. There is a max of 100 members it will
# send to
# {valueType: "string", multiple: true}
mail.smtp.groupUuidAndNameEmailDereferenceAllow =
#leave blank or false for no ssl, true for ssl
# {valueType: "boolean"}
mail.smtp.ssl = false
# leave blank or false for no tls, true for tls
# {valueType: "boolean"}
mail.smtp.starttls.enable = false
# if you are doing SSL/TLS, you should put the smtp server here so it is trusted
# {valueType: "string"}
mail.smtp.ssl.trust =
#leave blank for default (probably 25), if ssl is true, default is 465, else specify
# {valueType: "integer"}
#mail.smtp.port =
# mail transport protocol you generally dont need to change
# {valueType: "string", defaultValue: "smtp"}
mail.smtp.transport.protocol =
# in the java mail settings if "smtp" or whatever the protocol is should be in the property names
# {valueType: "boolean", defaultValue: "true"}
mail.smtp.use.protocol.in.property.names =
# if you have trouble connecting to SSL/TLS, try a different SSL protocol, e.g. TLSv1.2
# {valueType: "string"}
# mail.smtp.ssl.protocols =
# generally saying SSL true is enough, though you might need to set a class. generally leasve this blank
# {valueType: "string"}
# mail.smtp.socketFactory.class =
# generally you will leave this blank unless doing something advanced
# {valueType: "boolean"}
# mail.smtp.socketFactory.fallback =
#this is the default email address where mail from grouper will come from. eg: [email protected]
# {valueType: "string", required: true}
mail.smtp.from.address =
#this is the subject prefix of emails, which will help differentiate prod vs test vs dev etc. eg: TEST:
#note, you can use $space$ to put a space at the end of the config, otherwise it will be trimmed.
# {valueType: "string"}
mail.smtp.subject.prefix =
# in non-prod send all messages to this address to see what messages would have been sent out (or comma separate multiple addresses).
# if you set addresses here, no real email will be sent out. eg: [email protected]
# {valueType: "string"}
mail.smtp.sendAllMessagesHere =
# if debug info from java mail should be printed
# {valueType: "boolean", defaultValue: "false"}
mail.smtp.debug =
# if this smtp connector is enabled
# {valueType: "boolean", defaultValue: "true"}
# mail.smtp.enabled =
# content type, default is: text/plain; charset=utf-8
# {valueType: "string"}
mail.smtp.grouperEmailContentType =
# external system test "to" address type: emailAddress, emailToSubject, emailToGroup
# {valueType: "string", required: true, formElement: "dropdown", optionValues: ["emailAddress", "emailToSubject", "emailToGroup"]}
mail.smtp.externalSystemTestToType =
# external system test "to" address
# {valueType: "string", required: true, showEl: "${externalSystemTestToType == 'emailAddress'}"}
mail.smtp.externalSystemTestToAddress =
# external system test "to" source id, required if not providing an "External system to address"
# {valueType: "string", required: true, showEl: "${externalSystemTestToType == 'emailToSubject'}", formElement: "dropdown", optionValuesFromClass: "edu.internet2.middleware.subject.provider.SourceManagerOptionValueDriver"}
mail.smtp.externalSystemTestToSubjectSourceId =
# external system test "to" subject id, required if not providing an "External system to address" though mutually exclusive
# {valueType: "string", required: true, showEl: "${externalSystemTestToType == 'emailToSubject'}", formElement: "dropdown", optionValues: ["subjectId", "subjectIdentifier"]}
mail.smtp.externalSystemTestToSubjectIdType =
# external system test "to" subject id, required if not providing an "External system to address" though mutually exclusive
# {valueType: "string", required: true, showEl: "${externalSystemTestToType == 'emailToSubject' && externalSystemTestToSubjectIdType == 'subjectId'}"}
mail.smtp.externalSystemTestToSubjectId =
# external system test "to" subject id, required if not providing an "External system to address" though mutually exclusive
# {valueType: "string", required: true, showEl: "${externalSystemTestToType == 'emailToSubject' && externalSystemTestToSubjectIdType == 'subjectIdentifier'}"}
mail.smtp.externalSystemTestToSubjectIdentifier =
# external system test "to" a group. Send to group UUID or name?
# {valueType: "string", required: true, showEl: "${externalSystemTestToType == 'emailToGroup'}", formElement: "dropdown", optionValues: ["groupUuid", "groupName"]}
mail.smtp.externalSystemTestToGroupIdType =
# external system test "to" group UUID
# {valueType: "string", required: true, showEl: "${externalSystemTestToType == 'emailToGroup' && externalSystemTestToGroupIdType == 'groupUuid'}"}
mail.smtp.externalSystemTestToGroupId =
# external system test "to" group name
# {valueType: "string", required: true, showEl: "${externalSystemTestToType == 'emailToGroup' && externalSystemTestToGroupIdType == 'groupName'}"}
mail.smtp.externalSystemTestToGroupName =
# subject of email
# {valueType: "string", required: true}
mail.smtp.externalSystemTestSubject =
# body of email
# {valueType: "string", required: true, formElement: "textarea"}
mail.smtp.externalSystemTestBody =
# cc of email
# {valueType: "string"}
mail.smtp.externalSystemTestCcAddress =
# bcc of email
# {valueType: "string"}
mail.smtp.externalSystemTestBccAddress =
# from of email. Will default to the global default from address
# {valueType: "string"}
mail.smtp.externalSystemTestFromAddress =
# comma separated reply-to addresses of email. Will default to the global default from address
# {valueType: "string"}
mail.smtp.externalSystemTestReplyAddresses =
# when running junit tests, this is the address that will be used. eg: [email protected]
# {valueType: "string"}
# mail.test.address =
#####################################
## Performance timers
#####################################
# if log performance info on GroupSave
# set in log4j2.xml: log4j.logger.edu.internet2.middleware.grouper.util.PerformanceLogger = INFO
# {valueType: "boolean", required: true}
grouper.log.performance.info.on.GroupSave = false
# if log performance info on StemSave
# set in log4j2.xml: log4j.logger.edu.internet2.middleware.grouper.util.PerformanceLogger = INFO
# {valueType: "boolean", required: true}
grouper.log.performance.info.on.StemSave = false
# if log performance info on Stem view screen
# set in log4j2.xml: log4j.logger.edu.internet2.middleware.grouper.util.PerformanceLogger = INFO
# {valueType: "boolean", required: true}
grouper.log.performance.info.on.StemUiView = false
# if log performance info on Stem more actions
# set in log4j2.xml: log4j.logger.edu.internet2.middleware.grouper.util.PerformanceLogger = INFO
# {valueType: "boolean", required: true}
grouper.log.performance.info.on.StemUiMoreActions = false
# if log performance info on left tree menu
# set in log4j2.xml: log4j.logger.edu.internet2.middleware.grouper.util.PerformanceLogger = INFO
# {valueType: "boolean", required: true}
grouper.log.performance.info.on.UiTreeMenu = false
#####################################
## Misc settings which probably dont need to be changed
#####################################
# dao factory has no other options and shouldnt be changed
# {valueType: "class", required: true, mustExtendClass: "edu.internet2.middleware.grouper.misc.GrouperDAOFactory"}
dao.factory = edu.internet2.middleware.grouper.internal.dao.hib3.Hib3DAOFactory
# if tables that are hibernated should have optimistic locking or not (assumes the data layer supports this, hibernate does)
# {valueType: "boolean", required: true}
dao.optimisticLocking = true
# set the API as readonly (e.g. during upgrades). Any updates will throw an exception
# {valueType: "boolean", required: true}
grouper.api.readonly = false
# When searching for memberships using the getMemberships WS (or underlying API call), limit the number of memberships
# which can be returned, else throws exception. -1 means dont check.
# {valueType: "integer", required: true}
ws.getMemberships.maxResultSize = 30000
# When searching for memberships using the getMemberships WS (or underlying API call), limit the page size
# which can be returned, else throws exception.
# {valueType: "integer", required: true}
ws.getMemberships.maxPageSize = 500
# When searching for attribute assignments using the getAttributeAssignments WS (or underlying API call), limit the number of assignments
# which can be returned, else throws exception. -1 means dont check.
# {valueType: "integer", required: true}
ws.findAttrAssignments.maxResultSize = 30000
# When searching attribute def names, this is max size
# {valueType: "integer", required: true}
findAllAttributeDefNames.maxResultSize = 30000
# create the type and attribuute for membership lite ui config by group
# {valueType: "boolean", required: true}
membershipUpdateLiteTypeAutoCreate = false
# default min idIndex
# {valueType: "integer", required: true}
grouperTableIndexDefaultMinIndex = 1000000
# min idIndex for groups
# {valueType: "integer", required: true}
grouper.tableIndex.group.minIndex = 1000000
# min idIndex for folders
# {valueType: "integer", required: true}
grouper.tableIndex.stem.minIndex = 1000000
# min idIndex for attributeDefs
# {valueType: "integer", required: true}
grouper.tableIndex.attributeDef.minIndex = 1000000
# min idIndex for attributeDefNames
# {valueType: "integer", required: true}
grouper.tableIndex.attributeDefName.minIndex = 1000000
# verify that table indexes are set and the pointers are ok, incurs a bit of overhead to grouper startup
# {valueType: "boolean", required: true}
grouper.tableIndex.verifyOnStartup = true
# in different circumstances, retrieve a different number of IDs at once.
# if it is a system where the JVM is starting and stopping (e.g. GSH), then
# dont reserve that many at once
# {valueType: "integer", required: true}
grouper.tableIndex.reserveIdsGsh = 1
# in different circumstances, retrieve a different number of IDs at once.
# if it is a system where the JVM is starting and stopping (e.g. GSH), then
# dont reserve that many at once
# {valueType: "integer", required: true}
grouper.tableIndex.reserveIdsDefault = 10
# in different circumstances, retrieve a different number of IDs at once.
# if it is a system where the JVM is starting and stopping (e.g. GSH), then
# dont reserve that many at once
# {valueType: "integer", required: true}
grouper.tableIndex.reserveIdsLoader = 10
# in different circumstances, retrieve a different number of IDs at once.
# if it is a system where the JVM is starting and stopping (e.g. GSH), then
# dont reserve that many at once
# {valueType: "integer", required: true}
grouper.tableIndex.reserveIdsWs = 10
# in different circumstances, retrieve a different number of IDs at once.
# if it is a system where the JVM is starting and stopping (e.g. GSH), then
# dont reserve that many at once
# {valueType: "integer", required: true}
grouper.tableIndex.reserveIdsUi = 10
# group who can assign id index cols (also, wheel or root is allowed)
# {valueType: "group"}
grouper.tableIndex.groupWhoCanAssignIdIndex = $$grouper.rootStemForBuiltinObjects$$:canAssignIdIndex
# number of bytes in DB that a non ascii char takes
# {valueType: "integer", required: true}
grouper.nonAsciiCharDbBytesLength = 3
# cache size for jexl expressions
# {valueType: "integer", required: true}
jexl.cacheSize = 1024
# when reading writing files from util classes, this is encoding (was ISO-8859-1)
# {valueType: "string"}
grouper.default.fileEncoding = UTF-8
# if you want a checkbox to not let users add themself to a group
# {valueType: "boolean", requiresRestart: "true"}
grouper.enable.rule.cannotAddSelfToGroup = false
# if you do not want non sysadmins to be able to add EveryEntity to a group or privilege
# {valueType: "boolean", requiresRestart: "true"}
grouper.enable.rule.cannotAddEveryEntity = false
# if you want group admins to be able to assign cannotAddSelf
# {valueType: "boolean"}
grouper.cannotAddSelfToGroup.allowAssignByGroupAdmins = true
# if group admins are not allowed to assign cannotAddSelf, then this group can, if blank then only Grouper admins can assign
# {valueType: "string"}
grouper.cannotAddSelfToGroup.groupCanAssignByGroupAdmins = $$grouper.rootStemForBuiltinObjects$$:cannotAddSelfToGroup:canAssignCannotAddSelf
# if you want group admins to be able to revoke cannotAddSelf
# {valueType: "boolean"}
grouper.cannotAddSelfToGroup.allowRevokeByGroupAdmins = false
# if group admins are not allowed to revoke cannotAddSelf, then this group can, if blank then only Grouper admins can revoke
# {valueType: "string"}
grouper.cannotAddSelfToGroup.groupCanRevokeByGroupAdmins = $$grouper.rootStemForBuiltinObjects$$:cannotAddSelfToGroup:canRevokeCannotAddSelf
# find bad memberships batch size
# {valueType: "integer", defaultValue: "1"}
findBadMemberships.batchSize =
#####################################
## Testing settings
#####################################
# if the ldappc tests should be included when running all tests (default false)
# {valueType: "boolean", required: true}
junit.test.ldappc = false
# if the loader tests should be included when running all tests (default true)
# {valueType: "boolean", required: true}
junit.test.loader = true
# if the tableSync tests should be included when running all tests (default true)
# {valueType: "boolean", required: true}
junit.test.tableSync = true
# if the ddl tests should be included when running all tests (default true)
# {valueType: "boolean", required: true}
junit.test.ddl = true
# if the sql provisioning tests should be included when running all tests (default false)
# {valueType: "boolean", required: true}
junit.test.sqlProvisioning = false
# if the gsh tests should be included when running all tests (default false)
# {valueType: "boolean", required: true}
junit.test.gsh = false
# if the stress tests should be included when running all tests (default false)
# {valueType: "boolean", required: true}
junit.test.stress = false
# if test client configs which requires hardcoded filenames
# {valueType: "boolean", required: true}
junit.test.clientConfig = false
# if grouper should run tests that require tomcat
# {valueType: "boolean", defaultValue: "false"}
junit.test.tomcat =
# if the external subject tests should be included when running all tests, note you need the jabber attribute in the view (default false)
# {valueType: "boolean", required: true}
junit.test.externalSubjects = false
# if the group sync should be tested... note you need the demo server available to test this, or change some settings...
# {valueType: "boolean", required: true}
junit.test.groupSync = false
# unit test group sync url
# {valueType: "string"}
junit.test.groupSync.url = https://grouperdemo.internet2.edu/grouper-ws_v2_0_0/servicesRest
# unit test group sync user
# {valueType: "string"}
junit.test.groupSync.user = remoteUser
# unit test group sync password
# {valueType: "password", sensitive: true}
junit.test.groupSync.password = R:/pass/grouperDemoRemoteUser.pass
# unti test group sync folder
#folder where the user can create/stem which the user can use to run tests
# {valueType: "stem"}
junit.test.groupSync.folder = test2:whateverFolder
#this is true unless testing to an older grouper which doesnt support this
# {valueType: "boolean", required: true}
junit.test.groupSync.pushAddExternalSubjectIfNotExist = true
# create remote folder if not exists
# {valueType: "boolean", required: true}
junit.test.groupSync.createRemoteFolderIfNotExist = true
# remote source id
# {valueType: "string"}
junit.test.groupSync.remoteSourceId = grouperExternal
# identifier for remote subject read
# {valueType: "string"}
junit.test.groupSync.remoteReadSubjectId = identifier
# identifier for remote subject write
# {valueType: "string"}
junit.test.groupSync.remoteWriteSubjectId = identifier
# to test this setup the source and set this to true
# {valueType: "boolean", required: true}
junit.test.ldap.source = false
# make sure docker is there
# {valueType: "boolean", required: true}
junit.test.ldap.dinkel = false
# these tests work locally but not on CI server
# {valueType: "boolean", required: true}
junit.test.databaseCache = false
# command to start tomcat for unit tests,
# e.g. cmd /c C:/mchyzer/tomcatJunit/bin/startup.bat
# e.g. bash /some/where/tomcat/startup.sh
# set to "none" and you have 10 seconds to start it on prompt
# {valueType: "string"}
junit.test.tomcat.startCommand =
# command to stop tomcat for unit tests,
# e.g. cmd /c C:/mchyzer/tomcatJunit/bin/shutdown.bat
# e.g. bash /some/where/tomcat/shutdown.sh
# set to "none" and you have 10 seconds to stop it on prompt
# {valueType: "string"}
junit.test.tomcat.stopCommand =
# http port to look for to see if tomcat has started, e.g. 8500
# {valueType: "integer", defaultValue: "8080"}
junit.test.tomcat.port = 8080
# ip address for tomcat
# {valueType: "string", defaultValue: "0.0.0.0"}
junit.test.tomcat.ipAddress = 0.0.0.0
# domain name for tomcat
# {valueType: "string", defaultValue: "localhost"}
junit.test.tomcat.domainName = localhost
# if should wait for tomcat start command to return (unix?) or spawn a thread (windows?)
# {valueType: "boolean"}
junit.test.tomcat.waitForProcessReturn =
# if this is ssl
# {valueType: "boolean", defaultValue: "false"}
junit.test.tomcat.ssl =
# sleep on startup to wait for ldap
# {valueType: "integer", defaultValue: "14000"}
junit.test.ldapSleepMillisOnTestStartup =
#####################################
## Attribute framework
#####################################
# root stem in grouper where built in attributes are put
# {valueType: "stem"}
grouper.attribute.rootStem = $$grouper.rootStemForBuiltinObjects$$:attribute
# comma separated names of attribute defs will not be audited or change log or point in time
# same as ${edu.internet2.middleware.grouper.cfg.GrouperConfig.retrieveConfig().propertyValueStringRequired('grouper.attribute.rootStem')}
# e.g. $$grouper.attribute.rootStem$$:userData:grouperUserDataValueDef
# note: some of these are hard coded in GrouperConfig.java
# {valueType: "attributeDef", multiple: true}
grouper.attribute.namesOfAttributeDefsToIgnoreAuditsChangeLogPit =
# comma separated names of attribute def names will not be audited or change log or point in time
# note: some of these are hard coded in GrouperConfig.java
# e.g. $$grouper.attribute.rootStem$$:attestation:attestationCalculatedDaysLeft
# {valueType: "attributeDefName", multiple: true}
grouper.attribute.namesOfAttributeDefNamesToIgnoreAuditsChangeLogPit =
# allow every entity to be able to read and assign subject identifiers to local entities they own
# note: there is also: grouper.permissions.limits.builtin.createAs.public
# {valueType: "boolean", required: true}
grouper.attribute.allow.everyEntity.privileges = false
#####################################
## Centrally managed permissions
#####################################
# if the permissions limits should be readable and updatable by GrouperAll (set when created)...
# note there is also: grouper.attribute.allow.everyEntity.privileges
# {valueType: "boolean", required: true}
grouper.permissions.limits.builtin.createAs.public = false
# text amount less than
# {valueType: "string"}
grouper.permissions.limits.builtin.displayExtension.limitAmountLessThan = amount less than
# text amount less than equal to
# {valueType: "string"}
grouper.permissions.limits.builtin.displayExtension.limitAmountLessThanOrEqual = amount less than or equal to
# text expression
# {valueType: "string"}
grouper.permissions.limits.builtin.displayExtension.limitExpression = Expression
# text ip address on network realm
# {valueType: "string"}
grouper.permissions.limits.builtin.displayExtension.limitIpOnNetworkRealm = ipAddress on network realm
# text ip address on networks
# {valueType: "string"}
grouper.permissions.limits.builtin.displayExtension.limitIpOnNetworks = ipAddress on networks
# text labels contain
# {valueType: "string"}
grouper.permissions.limits.builtin.displayExtension.limitLabelsContain = labels contains
# text weekday 9 to 5
# {valueType: "string"}
grouper.permissions.limits.builtin.displayExtension.limitWeekday9to5 = Weekday 9 to 5
# el classes to add to the el context for a limitExpression. Comma-separated fully qualified classnames
# {valueType: "class", multiple: true}
grouper.permissions.limits.el.classes =
# permission limits linked to subclasses of edu.internet2.middleware.grouper.permissions.limits.PermissionLimitBase by the name of the attribute (the attributeDefName not the attributeDef)) mutually exclusive with limitNameOfAttributeDef
# {valueType: "string", regex: "^grouper\\.permissions\\.limits\\.logic\\.([^.]+)\\.limitName$"}
# grouper.permissions.limits.logic.someName.limitName =
# permission limits where all attribute names for the limit attribute def should be configured mutually exclusive with limitName
# {valueType: "string", regex: "^grouper\\.permissions\\.limits\\.logic\\.([^.]+)\\.limitNameOfAttributeDef$"}
# grouper.permissions.limits.logic.someName.limitNameOfAttributeDef =
# permission limits linked to subclasses of edu.internet2.middleware.grouper.permissions.limits.PermissionLimitBase
# {valueType: "class", regex: "^grouper\\.permissions\\.limits\\.logic\\.([^.]+)\\.logicClass$", mustExtendClass: "edu.internet2.middleware.grouper.permissions.limits.PermissionLimitBase"}
# grouper.permissions.limits.logic.someName.logicClass =
# if you are doing ip address limits, you can put realms here
# {valueType: "string", multiple: true, regex: "^grouper\\.permissions\\.limits\\.realm\\.([^.]+)$"}
# grouper.permissions.limits.realm.someName = 1.2.3.4/24, 2.3.4.5/16
#####################################
## External subjects
#####################################
# Use new UI to self register external users
# {valueType: "boolean", required: true}
externalSubject.selfRegister.useNewUI = true
#manages the description of a user automatically
# {valueType: "string"}
externalSubjects.desc.el = ${grouperUtil.appendPrefixIfStringNotBlank('[unverifiedInfo]', ' ', grouperUtil.appendIfNotBlankString(externalSubject.name, ' - ', externalSubject.institution))} [externalUserID] ${externalSubject.identifier}
#search and sort strings added to member objects, increment the index to add multiple
# {valueType: "string", regex: "^externalSubjects\\.searchAttribute([0-9]+)\\.el$"}
externalSubjects.searchAttribute0.el = ${subject.name},${subjectUtils.defaultIfBlank(subject.getAttributeValue("institution"), "")},${subjectUtils.defaultIfBlank(subject.getAttributeValue("identifier"), "")},${subject.id},${subjectUtils.defaultIfBlank(subject.getAttributeValue("email"), "")}
# external subject sort attribute, increment the index to add multiple
# {valueType: "string", regex: "^externalSubjects\\.sortAttribute([0-9]+)\\.el$"}
externalSubjects.sortAttribute0.el = ${subject.name}
# external subject sort attribute, increment the index to add multiple
# {valueType: "string"}
externalSubjects.sortAttribute1.el = ${subjectUtils.defaultIfBlank(subject.getAttributeValue("identifier"), "")}
# external subject sort attribute, increment the index to add multiple
# {valueType: "string"}
externalSubjects.sortAttribute2.el = ${subjectUtils.defaultIfBlank(subject.getAttributeValue("institution"), "")}
# false if the description should be managed via EL (config above)
# {valueType: "boolean", required: true}
externalSubjects.desc.manual = false
# external subject name required
# {valueType: "boolean", required: true}
externalSubjects.name.required = true
# external subject email required
# {valueType: "boolean", required: true}
externalSubjects.email.required = false
# external subject email enabled
# {valueType: "boolean", required: true}
externalSubjects.email.enabled = true
# these field names (uuid, institution, identifier, uuid, email, name) or attribute names
# will be toLowered, and appended with comma separators. e.g. if you add attributes, add them here too
# {valueType: "string", multiple: true}
externalSubjects.searchStringFields = name, institution, identifier, uuid, email
# external subject institution required
# {valueType: "boolean", required: true}
externalSubjects.institution.required = false
# external subject institution enabled
# {valueType: "boolean", required: true}
externalSubjects.institution.enabled = true
# note, this must be only alphanumeric lower case or underscore
# (valid db column name, subject attribute name)
# {valueType: "string", regex: "^externalSubjects\\.attributes\\.([^.]+)\\.systemName$"}
# externalSubjects.attributes.jabber.systemName = jabber
# if the external subject attribute is required
# {valueType: "boolean", regex: "^externalSubjects\\.attributes\\.([^.]+)\\.required$"}
# externalSubjects.attributes.jabber.required = false
# comment on column in DB (no special characters allowed)
# {valueType: "string", regex: "^externalSubjects\\.attributes\\.([^.]+)\\.comment$"}
# externalSubjects.attributes.jabber.comment = The jabber ID of the user
# if wheel or root can edit external users
# {valueType: "boolean", required: true}
externalSubjects.wheelOrRootCanEdit = true
# group which is allowed to edit external users
# {valueType: "group", required: true}
externalSubjects.groupAllowedForEdit =
# if the view on the external subjects should be created.
# turn this off if it doesnt compile, othrewise should be fine
# {valueType: "boolean", required: true}
externalSubjects.createView = true
#name of external subject source, defaults to grouperExternal
# {valueType: "string"}
externalSubject.sourceId = grouperExternal
# external subject source name
# {valueType: "string"}
externalSubject.sourceName = External Users
# grouper can auto create a jdbc2 source for the external subjects
# {valueType: "boolean", required: true}
externalSubjects.autoCreateSource = true
# put in fully qualified classes to add to the EL context. Note that they need a default constructor
# comma separated. The alias will be the simple class name without a first cap.
# e.g. if the class is test.Test the alias is "test"
# {valueType: "class", required: true, multiple: true}
externalSubjects.customElClasses =
# change these to affect the storage where external subjects live (e.g. to store in ldap),
# must implement each respective storable interface
# {valueType: "class", mustImplementInterface: "edu.internet2.middleware.grouper.externalSubjects.ExternalSubjectStorable"}
externalSubjects.storage.ExternalSubjectStorable.class = edu.internet2.middleware.grouper.externalSubjects.ExternalSubjectDbStorage
# change these to affect the storage where external subjects live (e.g. to store in ldap),
# must implement each respective storable interface
# {valueType: "class", mustImplementInterface: "edu.internet2.middleware.grouper.externalSubjects.ExternalSubjectAttributeStorable"}
externalSubjects.storage.ExternalSubjectAttributeStorable.class = edu.internet2.middleware.grouper.externalSubjects.ExternalSubjectAttributeDbStorage
# you can use the variables $newline$, $inviteLink$. Note, you need to change this default message...
# {valueType: "string"}
externalSubjectsInviteDefaultEmail = Hello,$newline$$newline$This is an invitation to register at our site to be able to access our applications. This invitation expires in 7 days. Click on the link below and sign in with your InCommon credentials. If you do not have InCommon credentials you can register at a site like protectnetwork.org and use those credentials.$newline$$newline$$inviteLink$$newline$$newline$Regards.
# default subject for email
# {valueType: "string"}
externalSubjectsInviteDefaultEmailSubject = Register to access applications
# you can use the variables $newline$, $inviteeIdentifier$, $inviteeEmailAddress$. Note, you need to change this default message...
# {valueType: "string"}
externalSubjectsNotifyInviterEmail = Hello,$newline$$newline$This is a notification that user $inviteeIdentifier$ from email address $inviteeEmailAddress$ has registered with the identity management service. They can now use applications at this institution.$newline$$newline$Regards.
# {valueType: "string"}
externalSubjectsNotifyInviterSubject = $inviteeIdentifier$ has registered
# numner of days after which this request will expire. If -1, then will not expire
# {valueType: "integer", required: true}
externalSubjectsInviteExpireAfterDays = 7
#put some group names comma separated for groups to auto add subjects to
# {valueType: "group", multiple: true}
externalSubjects.autoaddGroups=
#should be insert, or update, or insert,update
# {valueType: "string", multiple: true}
externalSubjects.autoaddGroupActions=insert,update
#if a number is here, expire the group assignment after a certain number of days
# {valueType: "integer"}
externalSubjects.autoaddGroupExpireAfterDays=
# add multiple group assignment actions by URL param: externalSubjectInviteName
# {valueType: "string", regex: "^externalSubjects\\.autoadd\\.([^.]+)\\.externalSubjectInviteName$"}
#externalSubjects.autoadd.testingLibrary.externalSubjectInviteName=library
# comma separated groups to add for this type of invite
# {valueType: "group", multiple: true, regex: "^externalSubjects\\.autoadd\\.([^.]+)\\.groups$"}
#externalSubjects.autoadd.testingLibrary.groups=
# should be insert, update, or insert,update
# {valueType: "string", multiple: true, regex: "^externalSubjects\\.autoadd\\.([^.]+)\\.groups$"}
#externalSubjects.autoadd.testingLibrary.actions=insert,update
# expire after days
# {valueType: "integer", regex: "^externalSubjects\\.autoadd\\.([^.]+)\\.groups$"}
#externalSubjects.autoadd.testingLibrary.expireAfterDays=
#if registrations are only allowed if invited or existing...
# {valueType: "boolean", required: true}
externalSubjects.registerRequiresInvite=true
#make sure the identifier when logging in is like an email address or eppn, e.g. [email protected]
# {valueType: "boolean", required: true}
externalSubjects.validateIndentiferLikeEmail=true
#put regexes here, increment the 0 for multiple entries, e.g. restrict your own institution
#note, the extensions must be sequential (dont skip), regex e.g. ^.*@myschool\\.edu$
# {valueType: "string", regex: "^externalSubjects\\.regexForInvalidIdentifier\\.([0-9]+)$"}
externalSubjects.regexForInvalidIdentifier.0=
#####################################
## Org management
#####################################
# if the orgs table(s) should be included in the DDL (includes the hierarchical table
# {valueType: "boolean", required: true}
orgs.includePocOrgsTablesInDdl = false
# loader connection of the database where orgs are (grouper means the grouper db in grouper.hibernate.properties)
# {valueType: "string"}
orgs.databaseName = grouper
#table name of the org table (can prefix by schema name if you like)
# {valueType: "string"}
orgs.orgTableName = grouperorgs_poc_orgs
#column names of this table
# {valueType: "string"}
orgs.orgIdCol = id
# column of org name
# {valueType: "string"}
orgs.orgNameCol = org_name
# column of org display name
# {valueType: "string"}
orgs.orgDisplayNameCol = org_display_name
# column or org parent id
# {valueType: "string"}
orgs.orgParentIdCol = parent_id
# stem where the orgs are, e.g. poc:orgs
# {valueType: "stem"}
orgs.parentStemName = poc:orgs
#org config name
# {valueType: "group"}
orgs.configGroupName = poc:orgs:orgsConfig
######################################
## Grouper client connections
## if this grouper needs to talk to another grouper, this is the client connection information
######################################
# id of the source, should match the part in the property name
# {valueType: "string", regex: "^grouperClient\\.([^.]+)\\.id$"}
#grouperClient.someOtherSchool.id = someOtherSchool
# url of web service, should include everything up to the first resource to access
# e.g. https://groups.school.edu/grouperWs/servicesRest
# {valueType: "string", regex: "^grouperClient\\.([^.]+)\\.properties\\.grouperClient\\.webService\\.url$"}
#grouperClient.someOtherSchool.properties.grouperClient.webService.url = https://some.other.school.edu/grouperWs/servicesRest
# login ID
# {valueType: "string", regex: "^grouperClient\\.([^.]+)\\.properties\\.grouperClient\\.webService\\.login$"}
#grouperClient.someOtherSchool.properties.grouperClient.webService.login = someRemoteLogin
# password for shared secret authentication to web service
# or you can put a filename with an encrypted password
# {valueType: "password", sensitive: true, regex: "^grouperClient\\.([^.]+)\\.properties\\.grouperClient\\.webService\\.password$"}
#grouperClient.someOtherSchool.properties.grouperClient.webService.password = *********
# client version should match or be related to the server on the other end...
# {valueType: "string", regex: "^grouperClient\\.([^.]+)\\.properties\\.grouperClient\\.webService\\.client\\.version$"}
#grouperClient.someOtherSchool.properties.grouperClient.webService.client.version = v2_0_000
# this is the subject to act as local, if blank, act as GrouperSystem, specify with SubjectFinder packed string, e.g.
# subjectIdOrIdentifier or sourceId::::subjectId or ::::subjectId or sourceId::::::subjectIdentifier or ::::::subjectIdentifier
# sourceId::::::::subjectIdOrIdentifier or ::::::::subjectIdOrIdentifier
# {valueType: "string", regex: "^grouperClient\\.([^.]+)\\.localActAsSubject$"}
#grouperClient.someOtherSchool.localActAsSubject =
# the id of this source, generally the same as the name in the property name. This is mandatory
# {valueType: "string", regex: "^grouperClient\\.([^.]+)\\.source\\.([^.]+)\\.id$"}
#grouperClient.someOtherSchool.source.jdbc.id = jdbc
# the part between "grouperClient.someOtherSchool.source." and ".id" links up the configs,
# in this case, "jdbc", make sure it has no special chars. sourceId can be blank if you dont want to specify
# {valueType: "string", regex: "^grouperClient\\.([^.]+)\\.source\\.([^.]+)\\.local\\.sourceId$"}
#grouperClient.someOtherSchool.source.jdbc.local.sourceId = jdbc
# this is the identifier that goes between them, it is "id" or an attribute name. subjects without this attribute will not be processed
# {valueType: "string", regex: "^grouperClient\\.([^.]+)\\.source\\.([^.]+)\\.local\\.read\\.subjectId$"}
#grouperClient.someOtherSchool.source.jdbc.local.read.subjectId = identifier
# this is the identifier to lookup to add a subject, should be "id" or "identifier" or "idOrIdentifier"
# {valueType: "string", regex: "^grouperClient\\.([^.]+)\\.source\\.([^.]+)\\.local\\.write\\.subjectId$"}
#grouperClient.someOtherSchool.source.jdbc.local.write.subjectId = identifier
# sourceId of the remote system, can be blank
# {valueType: "string", regex: "^grouperClient\\.([^.]+)\\.source\\.([^.]+)\\.remote\\.sourceId$"}
#grouperClient.someOtherSchool.source.jdbc.remote.sourceId = jdbc
# this is the identifier that goes between them, it is "id" or an attribute name. subjects without this attribute will not be processed
# {valueType: "string", regex: "^grouperClient\\.([^.]+)\\.source\\.([^.]+)\\.remote\\.read\\.subjectId$"}
#grouperClient.someOtherSchool.source.jdbc.remote.read.subjectId =
# this is the identifier to lookup to add a subject, should be "id" or "identifier" or "idOrIdentifier"
# {valueType: "string", regex: "^grouperClient\\.([^.]+)\\.source\\.([^.]+)\\.remote\\.write\\.subjectId$"}
#grouperClient.someOtherSchool.source.jdbc.remote.write.subjectId =
######################################
## Sync to/from another grouper
## Only sync one group to one other group, do not sync one group to
## two report groupers. If you need to do this, add the group to another group
######################################
# we need to know where our
# connection name in grouper client connections above
# {valueType: "string", regex: "^syncAnotherGrouper\\.([^.]+)\\.connectionName$"}
#syncAnotherGrouper.testGroup0.connectionName = someOtherSchool
# incremental or push or pull or incremental_push. Note, incremental push is cron'ed and incremental (to make sure no discrepancies arise)
# {valueType: "string", regex: "^syncAnotherGrouper\\.([^.]+)\\.syncType$"}
#syncAnotherGrouper.testGroup0.syncType = incremental_push
# local group which is being synced
# {valueType: "group", regex: "^syncAnotherGrouper\\.([^.]+)\\.local\\.groupName$"}
#syncAnotherGrouper.testGroup0.local.groupName = test:testGroup
# remote group at another grouper which is being synced
# {valueType: "string", regex: "^syncAnotherGrouper\\.([^.]+)\\.remote\\.groupName$"}
#syncAnotherGrouper.testGroup0.remote.groupName = test2:testGroup2
# if subjects are external and should be created if not exist
# {valueType: "string", regex: "^syncAnotherGrouper\\.([^.]+)\\.addExternalSubjectIfNotFound$"}
#syncAnotherGrouper.testGroup0.addExternalSubjectIfNotFound = true
###########################################
## Text bundles for UI
###########################################
# the default index
# {valueType: "integer"}
grouper.text.defaultBundleIndex = 0
# language for this bundle
# {valueType: "string", regex: "^grouper.text.bundle.([0-9]+).language$"}
grouper.text.bundle.0.language = en
# country for this bundle
# {valueType: "string", regex: "^grouper.text.bundle.([0-9]+).country$"}
grouper.text.bundle.0.country = us
# filename in the package grouperText that is before the .base.properties, and .properties
# {valueType: "string", regex: "^grouper.text.bundle.([0-9]+).fileNamePrefix$"}
grouper.text.bundle.0.fileNamePrefix = grouperText/grouper.textNg.en.us
###################################
## User data settings
###################################
# amount of time to cache groups in use
# {valueType: "integer", required: true}
grouperUserData.group.cache.seconds = 120
######################################
## Legacy attributes
######################################
# legacy attribute base stem
# {valueType: "stem"}
legacyAttribute.baseStem=$$grouper.rootStemForBuiltinObjects$$:legacy:attribute
# legacy attribute prefix for group types
# {valueType: "string"}
legacyAttribute.groupTypeDef.prefix=legacyGroupTypeDef_
# legacy attribute prefix for attribute definitions
# {valueType: "string"}
legacyAttribute.attributeDef.prefix=legacyAttributeDef_
# legacy custom list def prefix
# {valueType: "string"}
legacyAttribute.customListDef.prefix=legacyCustomListDef_
# legacy attribute group type prefix
# {valueType: "string"}
legacyAttribute.groupType.prefix=legacyGroupType_
# legacy attribute prefix
# {valueType: "string"}
legacyAttribute.attribute.prefix=legacyAttribute_
# legacy custom list prefix
# {valueType: "string"}
legacyAttribute.customList.prefix=legacyCustomList_
# if we should use threads in legacy attribute migration
# {valueType: "boolean", required: true}
legacyAttributeMigration.useThreads = true
# if we are using threads in legacy attribute migration, this is the threads pool size
# {valueType: "integer"}
legacyAttributeMigration.threadPoolSize = 20
######################################
## Group types edit view
## Identify marker attributes or single valued string attributes to be viewed or edited on group screen
## "theConfigId" is the config ID of the attribute
######################################
# attribute name that should be able to be seen on screen, e.g. a:b:c
# {valueType: "string"}
#groupScreen.attribute.theConfigId.attributeName =
# label on the left side of screen for attribute
# {valueType: "string"}
#groupScreen.attribute.theConfigId.label =
# description on the right side of screen for attribute
# {valueType: "string"}
#groupScreen.attribute.theConfigId.description =
# numeric index of the order of the attribute on the screen
# {valueType: "integer"}
#groupScreen.attribute.theConfigId.index =
######################################
## Point in time audit
######################################
# if grouper should use threads when syncing point in time
# {valueType: "boolean", required: true}
pit.sync.useThreads = true
# grouper pit thread pool size
# {valueType: "integer", required: true}
pit.sync.threadPoolSize = 20
######################################
## Stem sets
######################################
# {valueType: "boolean", required: true}
stemSet.sync.useThreads = true
# {valueType: "integer", required: true}
stemSet.sync.threadPoolSize = 20
######################################
## Group sets
######################################
# {valueType: "boolean", required: true}
groupSet.sync.useThreads = true
# {valueType: "integer", required: true}
groupSet.sync.threadPoolSize = 20
########################
## LDAP provisioning hook
## Will add the LDAPProvisioningExclude group type to groups that shouldnt be provisioned
########################
# Increment the integer starting with 0 to add multiple. Will add the LDAPProvisioningExclude group type to groups that shouldnt be provisioned, e.g. .*_excludes$, .*_includes$, .*_systemOfRecord$, .*_systemOfRecordAndIncludes$
# {valueType: "string", regex: "^LDAPProvisioningHook\\.exclude\\.regex\\.([0-9]+)$"}
#LDAPProvisioningHook.exclude.regex.0=.*_excludes$
#########################################
## Unresolvable Subject Deletion Utility
#########################################
# folder where system objects are for usdu
# {valueType: "stem"}
usdu.systemFolder = $$grouper.rootStemForBuiltinObjects$$:usdu
# global across all sources: Don't do anything if more than this number of unresolvable subjects are found
# {valueType: "integer", required: true}
usdu.failsafe.maxUnresolvableSubjects = 500
# global across all sources: if the first X subjects should be removed but stop after that limit: usdu.failsafe.maxUnresolvableSubjects
usdu.failsafe.removeUpToFailsafe = false
# global across all sources: only delete unresolvables if unresolvable for 30 days. -1 means remove now
# {valueType: "integer", required: false}
usdu.delete.ifAfterDays = 30
# local to one source supersedes the global settings: source ID
# {valueType: "string", required: true, regex: "^usdu\\.source\\.([^.]+)\\.sourceId$"}
# usdu.source.someLabel.sourceId = someSourceId
# local to one source supersedes the global settings: Don't do anything if more than this number of unresolvable subjects are found
# {valueType: "integer", required: true, regex: "^usdu\\.source\\.([^.]+)\\.failsafe\\.maxUnresolvableSubjects$"}
# usdu.source.someLabel.failsafe.maxUnresolvableSubjects = 500
# local to one source supersedes the global settings: if the first X subjects should be removed but stop after that limit: usdu.failsafe.maxUnresolvableSubjects
# {valueType: "integer", required: true, regex: "^usdu\\.source\\.([^.]+)\\.failsafe\\.removeUpToFailsafe$"}
# usdu.source.someLabel.failsafe.removeUpToFailsafe = false
# local to one source supersedes the global settings: Don't do anything if more than this number of unresolvable subjects are found
# {valueType: "integer", required: true, regex: "^usdu\\.source\\.([^.]+)\\.delete\\.ifAfterDays$"}
# usdu.source.someLabel.delete.ifAfterDays = 30
########################################
## Diagnostics
## In UI and WS
########################################
#if ignore tests. Note, in job names, invalid chars need to be replaced with underscore (e.g. colon)
#anything in this regex: [^a-zA-Z0-9._-]
# {valueType: "boolean", required: true, regex: "^ws\\.diagnostic\\.ignore\\.([a-zA-Z0-9._-]+)$"}
ws.diagnostic.ignore.memoryTest = false
#if ignore tests. Note, in job names, invalid chars need to be replaced with underscore (e.g. colon)
#anything in this regex: [^a-zA-Z0-9._-]
# {valueType: "boolean", required: true}
ws.diagnostic.ignore.dbTest_grouper = false
#if ignore tests. Note, in job names, invalid chars need to be replaced with underscore (e.g. colon)
#anything in this regex: [^a-zA-Z0-9._-]
# {valueType: "boolean", required: true}
ws.diagnostic.ignore.source_jdbc = false
#if ignore tests. Note, in job names, invalid chars need to be replaced with underscore (e.g. colon)
#anything in this regex: [^a-zA-Z0-9._-]
# {valueType: "boolean", required: true}
ws.diagnostic.ignore.loader_CHANGE_LOG_changeLogTempToChangeLog = false
#if ignore sync all pit tables one timer.
#anything in this regex: [^a-zA-Z0-9._-]
# {valueType: "boolean", required: true}
ws.diagnostic.ignore.loader_OTHER_JOB_syncAllPitTables = false
#if ignore sync all set tables one timer.
#anything in this regex: [^a-zA-Z0-9._-]
# {valueType: "boolean", required: true}
ws.diagnostic.ignore.loader_OTHER_JOB_syncAllSetTables = false
# this is 52 hours... 48 for 2 days, and 4 more for the job to run. So if the warehouse is down for updates,
# then the daily job will not give an error
# {valueType: "integer", required: true}
ws.diagnostic.defaultMinutesSinceLastSuccess = 3120
# change log can only for 30 minutes of failing before diagnostics fails
# {valueType: "integer", required: true}
ws.diagnostic.defaultMinutesChangeLog = 30
# number of minute that can go by without a success before an error is thrown
# {valueType: "integer", required: true, regex: "^ws\\.diagnostic\\.minutesSinceLastSuccess\\.([a-zA-Z0-9._-]+)$"}
ws.diagnostic.minutesSinceLastSuccess.loader_SQL_GROUP_LIST__aStem_aGroup2 = 60
# list groups which should check the size, in this case, "employee" or "students" in the key name is a variable
# {valueType: "group", required: true, regex: "^ws\\.diagnostic\\.checkGroupSize\\.([a-zA-Z0-9._-]+)\\.groupName$"}
# ws.diagnostic.checkGroupSize.employees.groupName = community:employees
# min group size of known groups
# {valueType: "integer", required: true, regex: "^ws\\.diagnostic\\.checkGroupSize\\.([a-zA-Z0-9._-]+)\\.minSize$"}
# ws.diagnostic.checkGroupSize.employees.minSize = 28000
#if a change log consumer hasn't had a success but it is running and progress is being made, treat as a success
# {valueType: "boolean", required: true}
ws.diagnostic.successIfChangeLogConsumerProgress = true
# usdu daemon minutes since success 10 days
# {valueType: "integer"}
ws.diagnostic.minutesSinceLastSuccess.loader_OTHER_JOB_usduDaemon = 14400
# allow diagnostics from these IP ranges, e.g. 1.2.3.4/32 or 2.3.4.5/24, comma separated, leave blank if available from everywhere
# {valueType: "string", multiple: true}
ws.diagnostic.sourceIpAddresses =
# if status details should be sent to the client or just logged
# {valueType: "boolean", required: true}
ws.diagnostic.sendDetailsInResponse = true
#########################################
## Instrumentation
#########################################
# if instrumentation is thread enabled
# {valueType: "boolean", required: true}
instrumentation.thread.enabled = true
# make updates in this many seconds
# {valueType: "integer", required: true}
instrumentation.updateGrouperIntervalInSeconds = 3600
# must be divisible by 3600
# {valueType: "integer", required: true}
instrumentation.updateIncrements = 3600
# you may want to use a substring instead of the full hostname (e.g. ui-01 instead of grouper-ui-01.xyz.edu) if you're sending this to TIER
# {valueType: "string", required: true}
instrumentation.serverLabel.el = ${grouperUtil.hostname()}
# number of days to retain instrumentation data. -1 is forever.
# {valueType: "integer", required: true}
instrumentation.retainData.days=30
# number of days to retain instrumentation instances without any activity. -1 is forever. Only applicable if instrumentation.retainData.days is not -1.
# {valueType: "integer", required: true}
instrumentation.retainInactiveInstances.days=365
# if set, will save the instance file containing the server uuid into this directory. Otherwise, will use /opt/grouper/instrumentation
# {valueType: "string"}
#instrumentation.instanceFile.directory =
#########################################
## GSH
#########################################
# if legacy gsh should be used
# {valueType: "boolean", required: true}
gsh.useLegacy = false
# when starting gsh, whether to immediately exit if there's a problem verifying the subject source configuration and connections
# {valueType: "boolean", required: true}
gsh.exitOnSubjectCheckConfigProblem = true
# if running gsh with a file or runarg parameter and there's an error, whether to exit instead of continuing with the next command
# {valueType: "boolean", required: true}
gsh.exitOnNonInteractiveError = true
# if running gsh in an otherjob or programmatically, exit if a line has an errror
# {valueType: "boolean", required: true}
gsh.exitOnProgrammaticError = true
#########################################
## Messages
#########################################
# if a message is not marked as processed in this many seconds, then send again to be processed
# {valueType: "integer", required: true}
grouper.builtin.messaging.timeout.receive.seconds = 300
# number of seconds to sleep while waiting to see if the database has records, minimum 1
# {valueType: "integer", required: true}
grouper.builtin.messaging.polling.sleep.seconds = 5
# default page size for messages
# {valueType: "integer", required: true}
grouper.builtin.messaging.defaultPageSize = 10
# max page size for messages
# {valueType: "integer", required: true}
grouper.builtin.messaging.maxPageSize = 50
#########################################
## Attestation
#########################################
#default value of attestation days until recertify. Every group/folder can define their own days until recertify value and if they don't provide, use the following one.
# {valueType: "integer", required: true}
attestation.default.daysUntilRecertify = 180
#number of groups shown in the body of attestation email
# {valueType: "integer", required: true}
attestation.email.group.count = 100
#attestation reminder email subject
# {valueType: "string"}
attestation.reminder.email.subject = You have $objectCount$ groups and/or folders that require attestation
#attestation reminder email body (links and groups/folders are added dynamically)
# {valueType: "string"}
attestation.reminder.email.body = You need to attest the following groups and/or folders. Review each group/folder and click the button to mark it as reviewed.
# attestation line in email when there are more than 100 emails
# {valueType: "string"}
attestation.reminder.email.body.greaterThan100 = There are $remaining$ more groups and/or folders to be attested.
###################################
## Deprovisioning
###################################
# if deprovisioning should be enabled
# {valueType: "boolean", required: true}
deprovisioning.enable = true
# comma separated affiliations for deprovisioning e.g. employee, student, etc
# these need to be alphanumeric suitable for properties keys for further config or for group extensions
# {valueType: "string"}
deprovisioning.affiliations =
# Group name of the group that identifies generally if an entity is in this affiliation. So if a group is deprovisioned
# by various affiliations, then only deprovision if the entity in the group is not in any affiliation eligible group.
# e.g. VPN is deprovisioned by affiliations employee and student. If the person is no longer an employee, but is still
# a student, then dont deprovision.
# for example deprovisioning.affiliation_.groupNameMeansInAffiliation set to a:b:c
# deprovisioning.affiliation_employee.groupNameMeansInAffiliation = community:employee
# number of minutes to cache deprovisioned members / admins
# {valueType: "integer", required: true}
deprovisioning.cacheMembersForMinutes = 5
# number of seconds to wait for refresh before giving up and using failsafe (if caching)
# {valueType: "integer", required: true}
deprovisioning.cacheFailsafeSeconds = 10
# folder where system objects are for deprovisioning
# e.g. managersWhoCanDeprovision_
# e.g. usersWhoHaveBeenDeprovisioned_
# {valueType: "stem"}
deprovisioning.systemFolder = $$grouper.rootStemForBuiltinObjects$$:deprovisioning
# autocreate the deprovisioning groups
# {valueType: "boolean", required: true}
deprovisioning.autocreate.groups = true
# default if the loader should not let deprovisioned users in that affiliation in loader jobs
# {valueType: "boolean", required: true}
deprovisioning.autoChangeLoader = true
# users in this group who are admins of a affiliation but who are not Grouper SysAdmins, will be
# able to deprovision from all grouper groups/objects, not just groups they have access to UPDATE/ADMIN
# {valueType: "group"}
deprovisioning.admin.group = $$deprovisioning.systemFolder$$:deprovisioningAdmins
# number of days in deproivisioning group. Should be the amount of time for
# systems of record to catch up and
# for people to change external systems of record in manual processes
# {valueType: "integer", required: true}
deprovisioning.defaultNumberOfDaysInDeprovisioningGroup = 14
#number of objects shown in the body of deprovisioning email
# {valueType: "integer", required: true}
deprovisioning.email.object.count = 100
#deprovisioning reminder email subject
# {valueType: "string"}
deprovisioning.reminder.email.subject = You have $objectCount$ objects that have suggested users to be deprovisioned
#deprovisioning reminder email body (links and groups are added dynamically)
# {valueType: "string"}
deprovisioning.reminder.email.body = You need to review the memberships of the following objects. Review the memberships of each object and click: Group actions -> Deprovisioning -> Members of this object have been reviewed
# deprovisioning email line when there are more than 100 objects to be reviewed
# {valueType: "string"}
deprovisioning.reminder.email.body.greaterThan100 = There are $remaining$ more objects to be reviewed.
###################################
## Grouper object types
###################################
# if object types should be enabled
# {valueType: "boolean", required: true}
objectTypes.enable = true
# folder where system objects are for objectTypes
# {valueType: "stem"}
objectTypes.systemFolder = $$grouper.rootStemForBuiltinObjects$$:objectTypes
# maximum groups/stems to show when suggesting auto assign types
# {valueType: "integer"}
objectTypes.max.autoAssign.objectCount = 2000
###################################
## Grouper workflow approvals
###################################
# if workflow should be enabled
# {valueType: "boolean", required: true}
workflow.enable = true
# folder where system objects are for workflow
# {valueType: "stem"}
workflow.systemFolder = $$grouper.rootStemForBuiltinObjects$$:workflow
# workflow editors group name
# {valueType: "group"}
workflow.editorsGroup = $$grouper.rootStemForBuiltinObjects$$:workflowEditors
# workflow config types. comma separated list. grouper must be in the list
# {valueType: "string"}
workflow.configTypes = grouper
# workflow storage option. valid values are database, fileSystem or S3
# {valueType: "string", required: true}
workflow.storage.option = database
# file system path where worklow files will be stored, e.g. /opt/grouper/workflow
# {valueType: "string", required: false}
workflow.file.system.path = /tmp/grouper/workflow
# grouper workflow s3 bucket name where the files will be uploaded
# {valueType: "string", required: false}
workflow.s3.bucket.name =
# grouper workflow s3 region e.g. us-west-2
# {valueType: "string", required: false}
workflow.s3.region =
# grouper workflow s3 access key
# {valueType: "string", required: false}
workflow.s3.access.key =
# grouper workflow s3 secret key
# {valueType: "string", required: false}
workflow.s3.secret.key =
#grouper workflow email subject
# {valueType: "string"}
workflow.email.subject = Report $$reportConfigName$$ generated
#grouper workflow email body. Can use variables
# {valueType: "string"}
workflow.email.body = Hello $$subjectName$$, \n\n Report $$reportConfigName$$ has been generated. Download the report: $$reportLink$$ \n\n Thanks
#########################################
## Provisioning in UI
#########################################
# if provisioning in ui should be enabled
# {valueType: "boolean", required: true}
provisioningInUi.enable = true
# folder where system objects are for provisioning
# {valueType: "stem"}
provisioningInUi.systemFolder = $$grouper.rootStemForBuiltinObjects$$:provisioning
# key for target
# {valueType: "string"}
#provisioning.target.pspngLdap1.key = pspngLdap1Key
# members of this group, wheel group members and system user are allowed to assign this target
# {valueType: "group"}
#provisioning.target.pspngLdap1.groupAllowedToAssign =
# should this target be assigned to only one stem
# {valueType: "boolean", required: false}
#provisioning.target.pspngLdap1.allowAssignmentsOnlyOnOneStem = false
# should this target be read only
# {valueType: "boolean", required: false}
#provisioning.target.pspngLdap1.readOnly = false
######################################
## Grouper Reporting
######################################
# folder where system objects are for reporting config
# {valueType: "stem"}
reportConfig.systemFolder = $$grouper.rootStemForBuiltinObjects$$:reportConfig
# if grouper reporting should be enabled
# {valueType: "boolean", required: true}
grouperReporting.enable = true
# grouper reporting storage option. valid values are database, fileSystem or S3
# {valueType: "string", required: true}
reporting.storage.option = database
# grouper reporting file system path where reports will be stored, e.g. /opt/grouper/reports
# {valueType: "string", required: false}
reporting.file.system.path =
# grouper reporting s3 bucket name where the reports will be uploaded
# {valueType: "string", required: false}
reporting.s3.bucket.name =
# grouper reporting s3 bucket name where the reports will be uploaded, e.g. us-west-2
# {valueType: "string", required: false}
reporting.s3.region =
# grouper reporting s3 access key
# {valueType: "string", required: false}
reporting.s3.access.key =
# grouper reporting s3 secret key
# {valueType: "string", required: false}
reporting.s3.secret.key =
#grouper reporting email subject
# {valueType: "string"}
reporting.email.subject = Report $$reportConfigName$$ generated
#grouper reporting email body. Can use variables
# {valueType: "string"}
reporting.email.body = Hello $$subjectName$$, \n\n Report $$reportConfigName$$ has been generated. Download the report: $$reportLink$$ \n\n Thanks
#########################################
## LDAP
#########################################
# you shouldnt need to change this, but this is the implementation of the
# ldap sessions. examples are:
# edu.internet2.middleware.grouper.ldap.ldaptive.LdaptiveSessionImpl (must be this)
# ${valueType: "class", mustImplementInterface: "edu.internet2.middleware.grouper.ldap.LdapSession"}
ldap.implementation.className = edu.internet2.middleware.grouper.ldap.ldaptive.LdaptiveSessionImpl
#########################################
## Custom composites
## This feature allows users to easily do a custom intersection or complement on their group with another group when viewing the members in the Grouper UI.
## Define your custom composites in the override configuration. Users must have READ privilege on the group.
#########################################
# Each custom composite also needs to be defined in the Grouper UI text properties in order to provide a friendly description in the UI. customCompositeMinusEmployees and customCompositeIntersectIt are also defined as examples there.
# {valueType: "string", regex: "^grouper\\.membership\\.customComposite\\.uiKey\\.\\d+$"}
# grouper.membership.customComposite.uiKey.0 = customCompositeMinusEmployees
# complement or intersection
# {valueType: "string", regex: "^grouper\\.membership\\.customComposite\\.compositeType\\.\\d+$"}
# grouper.membership.customComposite.compositeType.0 = complement
# {valueType: "group", regex: "^grouper\\.membership\\.customComposite\\.groupName\\.\\d+$"}
# grouper.membership.customComposite.groupName.0 = ref:activeEmployees
#########################################
## Custom veto composites membership requirement
## This feature allows users to auto-veto ineligible members or remove them when they become ineligible.
## Note that each custom composite also needs to be defined in the Grouper UI text properties in order
## to provide a friendly description in the UI. customCompositeMinusEmployees and customCompositeIntersectIt are also defined as examples there.
#########################################
# how long should logs of membership requirement logs be stored in database?
# {valueType: "integer", regex: "^grouper\\.membershipRequirement\\.keepLogsForDays$"}
grouper.membershipRequirement.keepLogsForDays = 90
# should hook for membership veto be enabled
# {valueType: "boolean", regex: "^grouper\\.membershipRequirement\\.hookEnable$"}
grouper.membershipRequirement.hookEnable = true
# should changeLog for membership veto change log be enabled in general
# {valueType: "boolean", regex: "^grouper\\.membershipRequirement\\.changeLogEnable$"}
grouper.membershipRequirement.changeLogEnable = true
# ui key to externalize text
# {valueType: "string", regex: "^grouper\\.membershipRequirement\\.[^.]+\\.uiKey$"}
#grouper.membershipRequirement.someConfigId.uiKey = customVetoCompositeRequireEmployee
# attribute name that signifies this requirement
# {valueType: "string", regex: "^grouper\\.membershipRequirement\\.[^.]+\\.attributeName$"}
#grouper.membershipRequirement.someConfigId.attributeName = etc:attribute:customComposite:requireEmployee
# group name which is the population group
# {valueType: "group", regex: "^grouper\\.membershipRequirement\\.[^.]+\\.requireGroupName$"}
#grouper.membershipRequirement.someConfigId.requireGroupName = org:centralIt:staff:itStaff
# if the overall hook is enabled, is the hook for this specific config enabled? defaults to true.
# {valueType: "boolean", regex: "^grouper\\.membershipRequirement\\.[^.]+\\.hookEnable$"}
#grouper.membershipRequirement.someConfigId.hookEnable = true
#########################################
## Unique extension in folder hook
#########################################
# comma separated folder names (id path). Configure multiple with different config ids
# {valueType: "string", regex: "^groupUniqueExtensionInFolderHook\\.[^.]+\\.folderNames$"}
#groupUniqueExtensionInFolderHook.someConfigId.folderNames = a:b, b:c
# optional config for case sensitive extensions (default true)
# {valueType: "string", regex: "^groupUniqueExtensionInFolderHook\\.[^.]+\\.caseSensitive$"}
#groupUniqueExtensionInFolderHook.someConfigId.caseSensitive = false
##################################
## Membership self read
##################################
# Allow users to see their own memberships on groups that they have VIEW privilege on
# {valueType: "boolean", defaultValue : "false"}
grouper.membership.allowSelfRead = false
##################################
## Lockout groups. Could be used for other things, but used for policy group templates at least
## if there is no allowed group, then anyone could use it
##################################
# group name of a lockout group
# {valueType: "group", regex: "^grouper\\.lockoutGroup\\.name\\.\\d+$"}
# grouper.lockoutGroup.name.0 = ref:lockout
# allowed to use this lockout group. If not configured, anyone could use
# {valueType: "group", regex: "^grouper\\.lockoutGroup\\.allowedToUse\\.\\d+$"}
# grouper.lockoutGroup.allowedToUse.0 = ref:lockoutCanUse
##################################
## Require groups. Could be used for other things, but used for policy group templates at least
## if there is no allowed group, then anyone could use it
##################################
# group name of a require group
# {valueType: "group", regex: "^grouper\\.requireGroup\\.name\\.\\d+$"}
# grouper.requireGroup.name.0 = ref:active
# allowed to use this require group. If not configured, anyone could use
# {valueType: "group", regex: "^grouper\\.lockoutGroup\\.requireGroup\\.\\d+$"}
# grouper.requireGroup.allowedToUse.0 = ref:activeCanUse
##################################
## Visualization
## Object styles for visualization modules
##################################
# semicolon-delimited regular expressions for folder names to exclude;
# for example, ^etc:.*;^$ will filter out folders etc:* and the root folder
# {valueType: "string"}
visualization.skipFolderNamePatterns =
# semicolon-delimited regular expressions for group names to exclude
# {valueType: "string"}
visualization.skipGroupNamePatterns =
# sample style properties, for illustration. It's useful to have property names
# correspond to css styles, so that they can be plugged in directly to output,
# without needing to rename them
# {valueType: "string"}
visualization.style.default.style =
# default color
# {valueType: "string"}
visualization.style.default.color =
# default bgcolor
# {valueType: "string"}
visualization.style.default.bgcolor =
# default border
# {valueType: "string"}
visualization.style.default.border =
# default font
# {valueType: "string"}
visualization.style.default.font = Courier,monospace
# default font size
# {valueType: "string"}
visualization.style.default.font-size = 12.0
# default font color
# {valueType: "string"}
visualization.style.default.font-color = black
# default shape
# {valueType: "string"}
visualization.style.default.shape =
# default shape stype
# {valueType: "string"}
visualization.style.default.shape-style =
# default edge style
# {valueType: "string"}
visualization.style.default.edge-style =
# default arrow tail
# {valueType: "string"}
visualization.style.default.arrowtail =
# default arrow head
# {valueType: "string"}
visualization.style.default.arrowhead =
# default dir
# {valueType: "string"}
visualization.style.default.dir =
# default inherit
# {valueType: "string"}
visualization.style.default.inherit =
# set up a default style inheritance (can be overridden for specific modules)
# {valueType: "string"}
visualization.style.start_group.inherit = group
# skipt group inherit
# {valueType: "string"}
visualization.style.skip_group.inherit = group
# inherit loader group
# {valueType: "string"}
visualization.style.loader_group.inherit = group
# inherit loader group
# {valueType: "string"}
visualization.style.start_loader_group.inherit = loader_group,start_group
# inherit simple loader group
# {valueType: "string"}
visualization.style.simple_loader_group.inherit = loader_group
# inherit simple loader group
# {valueType: "string"}
visualization.style.start_simple_loader_group.inherit = simple_loader_group,start_group
# inherit intersect group
# {valueType: "string"}
visualization.style.intersect_group.inherit = group
# inherit complement group
# {valueType: "string"}
visualization.style.complement_group.inherit = group
# inherit start stem
# {valueType: "string"}
visualization.style.start_stem.inherit = stem
# inherit skip stem
# {valueType: "string"}
visualization.style.skip_stem.inherit = stem
# inherit start subject
# {valueType: "string"}
visualization.style.start_subject.inherit = subject
# inherit edge loader
# {valueType: "string"}
visualization.style.edge_loader.inherit = edge
# inherit edge membership
# {valueType: "string"}
visualization.style.edge_membership.inherit = edge
# inherit edge provisioner
# {valueType: "string"}
visualization.style.edge_provisioner.inherit = edge
# inherit edge complement left
# {valueType: "string"}
visualization.style.edge_complement_left.inherit = edge
# inherit edge complement right
# {valueType: "string"}
visualization.style.edge_complement_right.inherit = edge
# inherit edge intersect left
# {valueType: "string"}
visualization.style.edge_intersect_left.inherit = edge
# inherit edge intersect right
# {valueType: "string"}
visualization.style.edge_intersect_right.inherit = edge
# inherit edge intersect
# {valueType: "string"}
visualization.style.edge_intersect.inherit = edge
# inherit group is member
# {valueType: "string"}
visualization.style.group_is_member.inherit = group
# inherit group is not member
# {valueType: "string"}
visualization.style.group_is_not_member.inherit = group
# inherit start group is member
# {valueType: "string"}
visualization.style.start_group_is_member.inherit = start_group,group_is_member
# inherit loader group is member
# {valueType: "string"}
visualization.style.loader_group_is_member.inherit = loader_group,group_is_member
# inherit start loader group is member
# {valueType: "string"}
visualization.style.start_loader_group_is_member.inherit = start_loader_group,group_is_member
# inherit simple loader group is member
# {valueType: "string"}
visualization.style.simple_loader_group_is_member.inherit = simple_loader_group,group_is_member
# inherit start simple loader group is member
# {valueType: "string"}
visualization.style.start_simple_loader_group_is_member.inherit = start_simple_loader_group,group_is_member
# inherit complement group is member
# {valueType: "string"}
visualization.style.complement_group_is_member.inherit = complement_group,group_is_member
# inherit intersect group is member
# {valueType: "string"}
visualization.style.intersect_group_is_member.inherit = intersect_group,group_is_member
# inherit start group is not member
# {valueType: "string"}
visualization.style.start_group_is_not_member.inherit = start_group,group_is_not_member
# inherit loader group is not member
# {valueType: "string"}
visualization.style.loader_group_is_not_member.inherit = loader_group,group_is_not_member
# inherit start loader group is not member
# {valueType: "string"}
visualization.style.start_loader_group_is_not_member.inherit = start_loader_group,group_is_not_member
# inherit simple loader group is not member
# {valueType: "string"}
visualization.style.simple_loader_group_is_not_member.inherit = simple_loader_group,group_is_not_member
# inherit start simple loader group is not member
# {valueType: "string"}
visualization.style.start_simple_loader_group_is_not_member.inherit = start_simple_loader_group,group_is_not_member
# inherit complement group is not member
# {valueType: "string"}
visualization.style.complement_group_is_not_member.inherit = complement_group,group_is_not_member
# inherit intersect group is not member
# {valueType: "string"}
visualization.style.intersect_group_is_not_member.inherit = intersect_group,group_is_not_member
# Link type to determine which UiV2Visualization method to invoke. Mostly relies on inheritence for subtypes
# {valueType: "string"}
visualization.style.stem.linkType = stem
# link type group
# {valueType: "string"}
visualization.style.group.linkType = group
# link type subject
# {valueType: "string"}
visualization.style.subject.linkType = subject
# link type loader group
# {valueType: "string"}
visualization.style.loader_group.linkType = group
# link type group is member
# {valueType: "string"}
visualization.style.group_is_member.linkType = group
# link type group is not member
# {valueType: "string"}
visualization.style.group_is_not_member.linkType = group
# Base type used in the ui to reduce the number of types to check; relies a lot on inheritence
# {valueType: "string"}
visualization.style.stem.baseType = stem
# group base type
# {valueType: "string"}
visualization.style.group.baseType = group
# subject base type
# {valueType: "string"}
visualization.style.subject.baseType = subject
# loader group base type
# {valueType: "string"}
visualization.style.loader_group.baseType = loader_group
# complement group base type
# {valueType: "string"}
visualization.style.complement_group.baseType = complement_group
# intersect group base type
# {valueType: "string"}
visualization.style.intersect_group.baseType = intersect_group
# Used to determine some calculated display text
# {valueType: "string"}
visualization.style.stem.displayTag = folder
# group display tag
# {valueType: "string"}
visualization.style.group.displayTag = group
# intersect group display tag
# {valueType: "string"}
visualization.style.intersect_group.displayTag = intersection group
# complement group display tag
# {valueType: "string"}
visualization.style.complement_group.displayTag = complement group
# subject display tag
# {valueType: "string"}
visualization.style.subject.displayTag = subject
# provisioner display tag
# {valueType: "string"}
visualization.style.provisioner.displayTag = provisioner
# loader group display tag
# {valueType: "string"}
visualization.style.loader_group.displayTag = loader job
# enabled style modules, comma-separated
# {valueType: "string"}
visualization.modules = text, dot
# styles for GraphViz dot format
# {valueType: "string"}
visualization.module.dot.graph.style = center=true; splines=spline; ratio=auto; ranksep = ".5"; nodesep = ".25 equally"; rankdir=LR; fontname="Courier,monospace"; bgcolor=gray91; packmode=clust;
# dot graph node style
# {valueType: "string"}
visualization.module.dot.graph.nodestyle = shape=rect; fontname="Courier,monospace"; fontsize="12.0";
# dot stem color
# {valueType: "string"}
visualization.module.dot.stem.color = powderblue
# dot stem shape
# {valueType: "string"}
visualization.module.dot.stem.shape = folder
# dot stem style
# {valueType: "string"}
visualization.module.dot.stem.style = filled
# dot start stem border
# {valueType: "string"}
visualization.module.dot.start_stem.border = 1
# start stem color e.g. deepskyblue
# {valueType: "string"}
visualization.module.dot.start_stem.color = sandybrown
# dot skip stem color
# {valueType: "string"}
visualization.module.dot.skip_stem.color = sandybrown
# dot group is member color
# {valueType: "string"}
visualization.module.dot.group_is_member.fillcolor = forestgreen
# dot group is member style
# {valueType: "string"}
visualization.module.dot.group_is_member.style = filled
# dot group is member fontcolor
# {valueType: "string"}
visualization.module.dot.group_is_member.fontcolor = white
# dot group is not member color
# {valueType: "string"}
visualization.module.dot.group_is_not_member.fillcolor = mistyrose
# dot group is not member style
# {valueType: "string"}
visualization.module.dot.group_is_not_member.style = filled
# dot group is not member fontcolor
# {valueType: "string"}
visualization.module.dot.group_is_not_member.fontcolor = black
# dot start group color
# {valueType: "string"}
visualization.module.dot.start_group.color = sandybrown
# dot start group style
# {valueType: "string"}
visualization.module.dot.start_group.style = bold
# dot start group border
# {valueType: "string"}
visualization.module.dot.start_group.border = 1
# dot intersect group color
# {valueType: "string"}
visualization.module.dot.intersect_group.color = blue
# dot intersect group style
# {valueType: "string"}
visualization.module.dot.intersect_group.style = bold
# dot start intersect group color
# {valueType: "string"}
visualization.module.dot.start_intersect_group.color = sandybrown
# dot complement group color
# {valueType: "string"}
visualization.module.dot.complement_group.color = green4
# dot complement group style
# {valueType: "string"}
visualization.module.dot.complement_group.style = bold
# dot start complement group color
# {valueType: "string"}
visualization.module.dot.start_complement_group.color = sandybrown
# dot subject color
# {valueType: "string"}
visualization.module.dot.subject.color = sandybrown
# dot subject style
# {valueType: "string"}
visualization.module.dot.subject.style = filled
# dot provisioner color
# {valueType: "string"}
visualization.module.dot.provisioner.color = red
# dot edge style
# {valueType: "string"}
visualization.module.dot.edge.style = solid
# dot edge loader color
# {valueType: "string"}
visualization.module.dot.edge_loader.color = forestgreen
# dot edge loader style
# {valueType: "string"}
visualization.module.dot.edge_loader.style = dashed
# dot edge provisioner color
# {valueType: "string"}
visualization.module.dot.edge_provisioner.color = red
# dot edge provisioner style
# {valueType: "string"}
visualization.module.dot.edge_provisioner.style = dashed
# dot edge membership style
# {valueType: "string"}
visualization.module.dot.edge_membership.style = dashed
# dot edge complement left color
# {valueType: "string"}
visualization.module.dot.edge_complement_left.color = green3
# dot edge complement left headlabel
# {valueType: "string"}
visualization.module.dot.edge_complement_left.headlabel = "(+)"
# dot edge complement left labeldistance
# {valueType: "string"}
visualization.module.dot.edge_complement_left.labeldistance = 2
# dot edge complement right color
# {valueType: "string"}
visualization.module.dot.edge_complement_right.color = red3
# dot edge complement right style
# {valueType: "string"}
visualization.module.dot.edge_complement_right.style = dashed
# dot edge complement right headlabel
# {valueType: "string"}
visualization.module.dot.edge_complement_right.headlabel = "(-)"
# dot edge complement right labeldistance
# {valueType: "string"}
visualization.module.dot.edge_complement_right.labeldistance = 2
# dot edge intersect left color
# {valueType: "string"}
visualization.module.dot.edge_intersect_left.color = blue
# dot edge intersect left headlabel
# {valueType: "string"}
visualization.module.dot.edge_intersect_left.headlabel = "(i)"
# dot edge intersect left labeldistance
# {valueType: "string"}
visualization.module.dot.edge_intersect_left.labeldistance = 2
# dot edge intersect right color
# {valueType: "string"}
visualization.module.dot.edge_intersect_right.color = blue
# dot edge intersect right headlabel
# {valueType: "string"}
visualization.module.dot.edge_intersect_right.headlabel = "(i)"
# dot edge intersect right labeldistance
# {valueType: "string"}
visualization.module.dot.edge_intersect_right.labeldistance = 2
# graph viz start stem label styles
# {valueType: "string"}
# visualization.module.graphviz.start_stem.label_styles = BGCOLOR="purple3" COLOR="blue"
# graphviz start stem label fontstyles
# {valueType: "string"}
# visualization.module.graphviz.start_stem.label_fontstyles = COLOR="white"
# graphviz loader group label fontstyles
# {valueType: "string"}
# visualization.module.graphviz.loader_group.label_fontstyles = COLOR="white"
##################################
## Configuration in the DB
##################################
# seconds between checking to see if the config files are updated in the database. If anything edited, then refresh all.
# Note that the last edited is stored in a config property for deletes. -1 means dont check for incrementals.
# Note if *.config.secondsBetweenUpdateChecks is greater than this number
# for this config, then it wont update until that amount has passed.
# {valueType: "integer", required: true}
grouper.config.secondsBetweenUpdateChecksToDb = 30
# seconds between full refreshes of the database config
# {valueType: "integer", required: true}
grouper.config.secondsBetweenFullRefresh = 600
# millis since that config inserted, edited or deleted. Grouper will update this config. Do not edit it
# Note change this with jdbc and dont audit.
# if grouper.config.secondsBetweenUpdateChecks is -1, then dont use this property
# {valueType: "integer", required: true}
grouper.config.millisSinceLastDbConfigChanged = 0
##################################
## Proxy config
##################################
# proxy requests here, e.g. https://server:1234
# {valueType: "string"}
grouper.http.proxy.url =
# socks or http
# {valueType: "string", formElement: "dropdown", optionValues: ["PROXY_HTTP", "PROXY_SOCKS5"]}
grouper.http.proxy.type =
# if this is blank then all urls are included by default. If there is a regex here, then only include urls that match, e.g. ^abc$
# note for SFTP the url is sftp://the.host.name
# {valueType: "string"}
grouper.http.proxy.includeUrlRegexPattern =
# if this is blank then excludes are not considered by default. If there is a regex here, then only exclude urls that match, e.g. ^abc$
# note for SFTP the url is sftp://the.host.name
# {valueType: "string"}
grouper.http.proxy.excludeUrlRegexPattern =
##################################
## SFTP sites
## the "configId" will be the identifier used in code to pull up that site, dont put special chars in it
## you shouldnt have the same host and username in two different configIds since its essentially the primary key
## e.g. if you sftp server is "depot.school.edu", the configId could be "depot"
##################################
# SFTP needs to use some files to connect. Keep this in a dir that only the tomcat user can read
# otherwise it will use the tmp dir configured in grouper.properties.
# {valueType: "string"}
grouperSftpBaseDirName =
# default proxy host for all sftp external systems
# {valueType: "string"}
grouperSftp.proxyHost =
# default proxy port for all sftp external systems
# {valueType: "integer"}
grouperSftp.proxyPort =
# default proxy type for all sftp external systems: PROXY_HTTP, PROXY_SOCKS5, PROXY_STREAM
# {valueType: "string", formElement: "dropdown", optionValues: ["PROXY_HTTP", "PROXY_SOCKS5", "PROXY_STREAM"]}
grouperSftp.proxyType =
# host: e.g. some.server.com
# {valueType: "string", regex: "^grouperSftp\\.site\\.[a-zA-Z0-9._-]+\\.host$", required: true}
# grouperSftp.site.configId.host =
# user: e.g. someuser
# {valueType: "string", regex: "^grouperSftp\\.site\\.[a-zA-Z0-9._-]+\\.user$", required: true}
# grouperSftp.site.configId.user =
# you can encrypt the private key to connect with. if its more than 4k encrypted, then take it in chunks and they will be concatenated
# and use _0, _1, _2, etc. Note, replace newlines with $newline$ so it fits in a textfield
# {valueType: "password", sensitive: true, regex: "^grouperSftp\\.site\\.[a-zA-Z0-9._-]+\\.secret\\.privateKey_[0-9]$"}
# grouperSftp.site.configId.secret.privateKey_0 =
# private key passphrase
# {valueType: "password", sensitive: true, regex: "^grouperSftp\\.site\\.[a-zA-Z0-9._-]+\\.secret\\.privateKeyPassphrase$"}
# grouperSftp.site.configId.secret.privateKeyPassphrase =
# password if not using private key
# {valueType: "password", sensitive: true, regex: "^grouperSftp\\.site\\.[a-zA-Z0-9._-]+\\.password$"}
# grouperSftp.site.configId.password =
# connect to the host, and copy the known_hosts entry for the host to connect to
# e.g. host.whatever ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEA3B00cx5W9KPSjzik3E
# {valueType: "string", regex: "^grouperSftp\\.site\\.[a-zA-Z0-9._-]+\\.knownHostsEntry$"}
# grouperSftp.site.configId.knownHostsEntry =
# if any temporary files (e.g. private key and known hosts) should be deleted after session, default true
# {valueType: "boolean", defaultValue: "true", regex: "^grouperSftp\\.site\\.[a-zA-Z0-9._-]+\\.deleteTempFilesAfterSession$"}
# grouperSftp.site.configId.deleteTempFilesAfterSession =
# timeout in millis defaults to 10000
# {valueType: "integer", regex: "^grouperSftp\\.site\\.[a-zA-Z0-9._-]+\\.timeoutMillis$"}
# grouperSftp.site.configId.timeoutMillis =
# if this sftp connector is enabled
# {valueType: "boolean", regex: "^grouperSftp\\.site\\.[a-zA-Z0-9._-]+\\.enabled$", defaultValue: "true"}
# grouperSftp.site.configId.enabled =
# Proxy host for this sftp external system, or default to the global default: grouper.properties: grouperSftp.proxyHost
# {valueType: "string", regex: "^grouperSftp\\.site\\.[a-zA-Z0-9._-]+\\.proxyHost$"}
# grouperSftp.site.configId.proxyHost =
# Proxy port for this sftp external system, or default to the global default: grouper.properties: grouperSftp.proxyPort
# {valueType: "integer", regex: "^grouperSftp\\.site\\.[a-zA-Z0-9._-]+\\.proxyPort$"}
# grouperSftp.site.configId.proxyPort =
# Proxy type for this sftp external system: PROXY_HTTP, PROXY_SOCKS5, PROXY_STREAM, or default to the global default: grouper.properties: grouperSftp.proxyType
# {valueType: "string", regex: "^grouperSftp\\.site\\.[a-zA-Z0-9._-]+\\.proxyType$", formElement: "dropdown", optionValues: ["PROXY_HTTP", "PROXY_SOCKS5", "PROXY_STREAM"]}
# grouperSftp.site.configId.proxyType =
##################################
## authentication hash type
##################################
# hash for DB authn
# {valueType: "string", required: true}
grouper.authentication.encryptionType = SHA-256
# if we should cache UI authns
# {valueType: "boolean", required : true}
grouper.authentication.UI.cache = false
# if we should cache WS authns
# {valueType: "boolean", required : true}
grouper.authentication.WS.cache = false
# cache timeout for UI authns
# {valueType: "integer", required: true}
grouper.authentication.UI.cacheTimeMinutes = 2
# cache timeout for WS authns
# {valueType: "integer", required: true}
grouper.authentication.WS.cacheTimeMinutes = 2
# when splitting basic auth header (which doesnt handle colons well), split on first or last colon
# first colon means usernames dont have colons, but passwords do.
# splitting on last colon means usernames have colons (e.g. local entities), but passwords dont
# note you can also escape colons
# {valueType: "boolean", defaultValue : "false"}
grouper.authentication.splitBasicAuthOnFirstColon = false
# You can escape colons in usernames and passwords, and they will be unescaped. escape with :
# set this to false to not unescape colons
# {valueType: "boolean", defaultValue : "false"}
grouper.authentication.basicAuthUnescapeColon = true
##################################
## ws self-service jwt
##################################
# if public private key should be enabled
# {valueType: "boolean", defaultValue: "true"}
grouper.selfService.jwt.enable =
# if you fill in a group name here, then only members of this group can manage jwt private keys on the ui
# {valueType: "string"}
grouper.selfService.jwt.groupNameAllowedToManage =
# maximum number of seconds for which a jwt can stay valid
# {valueType: "integer"}
grouper.selfService.jwt.maxValidTimeInSeconds = 600
############################################
## dev environment allow missing servlets
############################################
# {valueType: "string", required: false}
grouper.dev.env.allowMissingServlets = false
############################################
## O365 connector
## See documentation at http://graph.microsoft.io/en-us/docs
############################################
# tenant ID
# {valueType: "string", required: true, regex: "^grouper\\.o365Connector\\.([^.]+)\\.tenantId$"}
# grouper.o365Connector.myO365.tenantId =
# client ID
# {valueType: "string", required: true, regex: "^grouper\\.o365Connector\\.([^.]+)\\.clientId$"}
# grouper.o365Connector.myO365.clientId =
# client secret
# {valueType: "password", required: true, regex: "^grouper\\.o365Connector\\.([^.]+)\\.clientSecret$"}
# grouper.o365Connector.myO365.clientSecret =
# ID attribute
# {valueType: "string", required: true, regex: "^grouper\\.o365Connector\\.([^.]+)\\.idAttribute$"}
# grouper.o365Connector.myO365.idAttribute =
# group JEXL
# {valueType: "string", required: true, regex: "^grouper\\.o365Connector\\.([^.]+)\\.groupJexl$"}
# grouper.o365Connector.myO365.groupJexl =
# if this O365 connector is enabled
# {valueType: "boolean", regex: "^grouper\\.o365Connector\\.([^.]+)\\.enabled$", defaultValue: "true"}
# grouper.o365Connector.myO365.enabled =
############################################
## Google connector
## A Google Apps admin must follow the steps at Perform Google Apps Domain-Wide Delegation of Authority to
## create a service application/account that is used by the provisioner to connect to Google. The steps can
## be followed as written with one exception. The account will need to be given these grants:
## https://www.googleapis.com/auth/admin.directory.user, https://www.googleapis.com/auth/admin.directory.group,
## https://www.googleapis.com/auth/apps.groups.settings.
############################################
# The Google managed domain name. (e.g. example.org)
# {valueType: "string", required: true, regex: "^grouper\\.googleConnector\\.([^.]+)\\.domain$"}
# grouper.googleConnector.myGoogle.domain =
# The Google managed group domain name. (e.g. example.org)
# {valueType: "string", regex: "^grouper\\.googleConnector\\.([^.]+)\\.groupDomain$"}
# grouper.googleConnector.myGoogle.groupDomain =
# The service account email address created by Google.
# {valueType: "string", required: true, regex: "^grouper\\.googleConnector\\.([^.]+)\\.serviceAccountEmail$"}
# grouper.googleConnector.myGoogle.serviceAccountEmail =
# The path of the PKCS12 file created and downloaded from Google. The OS account running Grouper
# needs to have read permissions to this file. Access to this file should be limited.
# {valueType: "string", regex: "^grouper\\.googleConnector\\.([^.]+)\\.serviceAccountPKCS12FilePath$"}
# grouper.googleConnector.myGoogle.serviceAccountPKCS12FilePath =
# If not reading from a file, this is the private key. You can get it by running "openssl pkcs12 -info -in pathToYourP12File -nodes"
# {valueType: "password", formElement: "textarea", regex: "^grouper\\.googleConnector\\.([^.]+)\\.serviceAccountPrivateKeyPEM$"}
# grouper.googleConnector.myGoogle.serviceAccountPrivateKeyPEM =
# This is the account that all actions will be made by. It needs to exists and will be the creator and modifier
# account associated with the Google auditing logs.
# {valueType: "string", required: true, regex: "^grouper\\.googleConnector\\.([^.]+)\\.serviceImpersonationUser$"}
# grouper.googleConnector.myGoogle.serviceImpersonationUser =
# Google app token url
# {valueType: "string", defaultValue: "https://oauth2.googleapis.com/token", regex: "^grouper\\.googleConnector\\.([^.]+)\\.tokenUrl$"}
# grouper.googleConnector.myGoogle.tokenUrl =
# Base url for google directory APIs
# {valueType: "string", defaultValue: "https://admin.googleapis.com/admin/directory/v1", regex: "^grouper\\.googleConnector\\.([^.]+)\\.directoryApiBaseUrl$"}
# grouper.googleConnector.myGoogle.directoryApiBaseUrl =
# URL for google group settings api
# {valueType: "string", defaultValue: "https://www.googleapis.com/groups/v1/groups", regex: "^grouper\\.googleConnector\\.([^.]+)\\.groupSettingsApiBaseUrl$"}
# grouper.googleConnector.myGoogle.groupSettingsApiBaseUrl =
# page size for groups
# {valueType: "integer", defaultValue: "200", regex: "^grouper\\.googleConnector\\.([^.]+)\\.pageSizeGroup$"}
# grouper.googleConnector.myGoogle.pageSizeGroup =
# page size for users
# {valueType: "integer", defaultValue: "500", regex: "^grouper\\.googleConnector\\.([^.]+)\\.pageSizeUser$"}
# grouper.googleConnector.myGoogle.pageSizeUser =
# page size for memberships
# {valueType: "integer", defaultValue: "200", regex: "^grouper\\.googleConnector\\.([^.]+)\\.pageSizeMembership$"}
# grouper.googleConnector.myGoogle.pageSizeMembership =
# proxy requests here, e.g. https://server:1234
# {valueType: "string", regex: "^grouper\\.googleConnector\\.([^.]+)\\.proxyUrl$"}
# grouper.googleConnector.myGoogle.proxyUrl =
# socks or http
# {valueType: "string", regex: "^grouper\\.googleConnector\\.([^.]+)\\.proxyType$", formElement: "dropdown", optionValues: ["PROXY_HTTP", "PROXY_SOCKS5"]}
# grouper.googleConnector.myGoogle.proxyType =
# if this google connector is enabled
# {valueType: "boolean", regex: "^grouper\\.googleConnector\\.([^.]+)\\.enabled$", defaultValue: "true"}
# grouper.googleConnector.myGoogle.enabled =
############################################
## ActiveMQ
############################################
# host address of activemq queue. eg: example.org
# {valueType: "string", required: true, regex: "^grouper\\.activeMqConnector\\.([^.]+)\\.host$"}
# grouper.activeMqConnector.myConnector.host =
# port of activemq queue, default is 5672
# {valueType: "integer", required: true, regex: "^grouper\\.activeMqConnector\\.([^.]+)\\.port$"}
# grouper.activeMqConnector.myConnector.port =
# username of activemq queue
# {valueType: "string", required: true, regex: "^grouper\\.activeMqConnector\\.([^.]+)\\.username$"}
# grouper.activeMqConnector.myConnector.username =
# password of activemq queue
# {valueType: "password", required: true, regex: "^grouper\\.activeMqConnector\\.([^.]+)\\.password$"}
# grouper.activeMqConnector.myConnector.password =
# if this activemq connector is enabled
# {valueType: "boolean", regex: "^grouper\\.activeMqConnector\\.([^.]+)\\.enabled$", defaultValue: "true"}
# grouper.activeMqConnector.myConnector.enabled =
############################################
## RabbitMQ
############################################
# host address of rabbitmq queue. eg: example.org
# {valueType: "string", required: true, regex: "^grouper\\.rabbitMqConnector\\.([^.]+)\\.host$"}
# grouper.rabbitMqConnector.myConnector.host =
# virtual host address of rabbitmq queue. eg: example.org
# {valueType: "string", required: true, regex: "^grouper\\.rabbitMqConnector\\.([^.]+)\\.virtualhost$"}
# grouper.rabbitMqConnector.myConnector.virtualhost =
# port of rabbitmq queue
# {valueType: "integer", required: true, regex: "^grouper\\.rabbitMqConnector\\.([^.]+)\\.port$"}
# grouper.rabbitMqConnector.myConnector.port =
# username
# {valueType: "string", required: true, regex: "^grouper\\.rabbitMqConnector\\.([^.]+)\\.username$"}
# grouper.rabbitMqConnector.myConnector.username =
# password
# {valueType: "password", required: true, regex: "^grouper\\.rabbitMqConnector\\.([^.]+)\\.password$"}
# grouper.rabbitMqConnector.myConnector.password =
# set the following three properties if you want to use TLS connection to rabbitmq. All three need to be populated.
# TLS Version. eg: TLSv1.1
# {valueType: "string", regex: "^grouper\\.rabbitMqConnector\\.([^.]+)\\.tlsVersion$"}
# grouper.rabbitMqConnector.myConnector.tlsVersion =
# path to trust store file
# {valueType: "string", regex: "^grouper\\.rabbitMqConnector\\.([^.]+)\\.pathToTrustStore$"}
# grouper.rabbitMqConnector.myConnector.pathToTrustStore =
# trust passphrase
# {valueType: "password", regex: "^grouper\\.rabbitMqConnector\\.([^.]+)\\.trustPassphrase$"}
# grouper.rabbitMqConnector.myConnector.trustPassphrase =
# if this rabbitmq connector is enabled
# {valueType: "boolean", regex: "^grouper\\.rabbitMqConnector\\.([^.]+)\\.enabled$", defaultValue: "true"}
# grouper.rabbitMqConnector.myConnector.enabled =
############################################
## AWS SQS
############################################
# access key
# {valueType: "string", required: true, regex: "^grouper\\.sqsConnector\\.([^.]+)\\.accessKey$"}
# grouper.sqsConnector.myConnector.accessKey =
# secret key
# {valueType: "password", required: true, regex: "^grouper\\.sqsConnector\\.([^.]+)\\.secretKey$"}
# grouper.sqsConnector.myConnector.secretKey =
# if this SQS connector is enabled
# {valueType: "boolean", regex: "^grouper\\.sqsConnector\\.([^.]+)\\.enabled$", defaultValue: "true"}
# grouper.sqsConnector.myConnector.enabled =
############################################
## Duo connector
############################################
# endpoint domain name
# {valueType: "string", required: true, regex: "^grouper\\.duoConnector\\.([^.]+)\\.adminDomainName$"}
# grouper.duoConnector.myConnector.adminDomainName =
# integration key
# {valueType: "string", required: true, regex: "^grouper\\.duoConnector\\.([^.]+)\\.adminIntegrationKey$"}
# grouper.duoConnector.myConnector.adminIntegrationKey =
# secret key
# {valueType: "password", required: true, regex: "^grouper\\.duoConnector\\.([^.]+)\\.adminSecretKey$"}
# grouper.duoConnector.myConnector.adminSecretKey =
# Use SSL
# {valueType: "boolean", defaultValue: "true", regex: "^grouper\\.duoConnector\\.([^.]+)\\.useSsl$"}
# grouper.duoConnector.myConnector.useSsl =
# proxy requests here, e.g. https://server:1234
# {valueType: "string", regex: "^grouper\\.duoConnector\\.([^.]+)\\.proxyUrl$"}
# grouper.duoConnector.myConnector.proxyUrl =
# socks or http
# {valueType: "string", regex: "^grouper\\.duoConnector\\.([^.]+)\\.proxyType$", formElement: "dropdown", optionValues: ["PROXY_HTTP", "PROXY_SOCKS5"]}
# grouper.duoConnector.myConnector.proxyType =
# if this duo connector is enabled
# {valueType: "boolean", regex: "^grouper\\.duoConnector\\.([^.]+)\\.enabled$", defaultValue: "true"}
# grouper.duoConnector.myConnector.enabled =
############################################
## Duo mock
############################################
# endpoint domain name
# {valueType: "string"}
# grouperTest.duo.mock.configId =
############################################
## Remedy connector
############################################
# url
# {valueType: "string", required: true, regex: "^grouper\\.remedyConnector\\.([^.]+)\\.url$"}
# grouper.remedyConnector.myConnector.url =
# authentication url
# {valueType: "string", required: true, regex: "^grouper\\.remedyConnector\\.([^.]+)\\.tokenUrl$"}
# grouper.remedyConnector.myConnector.tokenUrl =
# username
# {valueType: "string", required: true, regex: "^grouper\\.remedyConnector\\.([^.]+)\\.username$"}
# grouper.remedyConnector.myConnector.username =
# password
# {valueType: "password", required: true, regex: "^grouper\\.remedyConnector\\.([^.]+)\\.password$"}
# grouper.remedyConnector.myConnector.password =
# if this remedy connector is enabled
# {valueType: "boolean", regex: "^grouper\\.remedyConnector\\.([^.]+)\\.enabled$", defaultValue: "true"}
# grouper.remedyConnector.myConnector.enabled =
############################################
## Remedy digital marketplace connector
############################################
# url
# {valueType: "string", required: true, regex: "^grouper\\.remedyDigitalMarketplaceConnector\\.([^.]+)\\.url$"}
# grouper.remedyDigitalMarketplaceConnector.myConnector.url =
# authentication url
# {valueType: "string", required: true, regex: "^grouper\\.remedyDigitalMarketplaceConnector\\.([^.]+)\\.tokenUrl$"}
# grouper.remedyDigitalMarketplaceConnector.myConnector.tokenUrl =
# username
# {valueType: "string", required: true, regex: "^grouper\\.remedyDigitalMarketplaceConnector\\.([^.]+)\\.username$"}
# grouper.remedyDigitalMarketplaceConnector.myConnector.username =
# password
# {valueType: "password", required: true, regex: "^grouper\\.remedyDigitalMarketplaceConnector\\.([^.]+)\\.password$"}
# grouper.remedyDigitalMarketplaceConnector.myConnector.password =
# X-Requested-By
# {valueType: "string", required: true, regex: "^grouper\\.remedyDigitalMarketplaceConnector\\.([^.]+)\\.xRequestedByHeader$"}
# grouper.remedyDigitalMarketplaceConnector.myConnector.xRequestedByHeader =
############################################
## Recent memberships
############################################
# if the recent-membership loader job should be created and scheduled nightly at 3:41am. It runs real time too so it shouldnt
# need to run more frequently than daily
# {valueType: "boolean", defaultValue: "true"}
grouper.recentMemberships.loaderJob.enable = true
# if this digital marketplace connector is enabled
# {valueType: "boolean", regex: "^grouper\\.remedyDigitalMarketplaceConnector\\.([^.]+)\\.enabled$", defaultValue: "true"}
# grouper.remedyDigitalMarketplaceConnector.myConnector.enabled =
############################################
## Grouper cache database
############################################
# If we should run a thread to check the database to see if a cache changed in another JVM
# {valueType: "boolean", defaultValue: "true"}
grouper.cache.database.use = true
# How much time to sleep between checks in seconds
# {valueType: "integer", defaultValue: "5"}
grouper.cache.database.checkIncrementalAfterSeconds = 5
# How much time in between full checks (select all from cache instance table)
# {valueType: "integer", defaultValue: "3600"}
grouper.cache.database.checkFullAfterSeconds = 3600
############################################
## External systems
############################################
# How much time to sleep between checks in seconds
# {valueType: "integer", defaultValue: "60"}
grouper.externalSystem.connectionRefresher.checkIntervalInSeconds = 60
############################################
## Mock services
############################################
# If requests and responses should be logged
# {valueType: "boolean", defaultValue: "false"}
grouper.mock.services.logRequestsResponses = false
############################################
## Custom UI
############################################
# enabled or disabled
# {valueType: "boolean", defaultValue: "true", order: 1000 }
# grouperCustomUI.testCustomUI.enabled =
# group uuid
# {valueType: "string", required: true, order: 2000 }
# grouperCustomUI.testCustomUI.groupUUIDOrName =
# use externalized text for labels and descriptions?
# {valueType: "boolean", defaultValue: "false", order: 3000 }
# grouperCustomUI.testCustomUI.externalizedText =
# If in this group then can pull other users up to check their UI or add or remove them
# {valueType: "string", order: 3100 }
# grouperCustomUI.testCustomUI.groupOfManagers =
# If in this group then can see user environment. This is for people who support the application
# {valueType: "string", order: 3110 }
# grouperCustomUI.testCustomUI.groupCanSeeUserEnvironment =
# If in this group then can see screen state. This is for developers of the custom ui
# {valueType: "string", order: 3120 }
# grouperCustomUI.testCustomUI.groupCanSeeScreenState =
# If in this group then can assign variables in the URL. This is for people verifying that the custom UI is working correctly
# {valueType: "string", order: 3130 }
# grouperCustomUI.testCustomUI.groupCanAssignVariables =
# number of queries
# {valueType: "string", defaultValue: "0", subSection: "cuQuery", order: 4000, formElement: "dropdown", optionValues: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "100"] }
# grouperCustomUI.testCustomUI.numberOfQueries =
# user query type
# {valueType: "string", order: 7000, showEl: "${numberOfQueries > $i$}", repeatGroup: "cuQuery", repeatCount: 100, formElement: "dropdown", optionValues: ["azure", "expressionLanguage", "grouper", "ldap", "sql", "url", "zoom"] }
# grouperCustomUI.testCustomUI.cuQuery.$i$.userQueryType =
# uuid of attribute def to look up
# {valueType: "string", order: 8000, showEl: "${numberOfQueries > $i$ && (cuQuery.$i$.userQueryType == 'expressionLanguage' || cuQuery.$i$.userQueryType == 'grouper' || cuQuery.$i$.userQueryType == 'sql') }", repeatGroup: "cuQuery", repeatCount: 100}
# grouperCustomUI.testCustomUI.cuQuery.$i$.attributeDefId =
# azure group id
# {valueType: "string", order: 9000, showEl: "${numberOfQueries > $i$ && (cuQuery.$i$.userQueryType == 'azure') }", repeatGroup: "cuQuery", repeatCount: 100}
# grouperCustomUI.testCustomUI.cuQuery.$i$.azureGroupId =
# bind variable 0
# {valueType: "string", order: 10000, showEl: "${numberOfQueries > $i$ && (cuQuery.$i$.userQueryType == 'sql') }", repeatGroup: "cuQuery", repeatCount: 100}
# grouperCustomUI.testCustomUI.cuQuery.$i$.bindVar0 =
# bind variable 0 type
# {valueType: "string", order: 11000, showEl: "${numberOfQueries > $i$ && (cuQuery.$i$.userQueryType == 'sql') }", repeatGroup: "cuQuery", repeatCount: 100}
# grouperCustomUI.testCustomUI.cuQuery.$i$.bindVar0Type =
# bind variable 1
# {valueType: "string", order: 12000, showEl: "${numberOfQueries > $i$ && (cuQuery.$i$.userQueryType == 'sql') }", repeatGroup: "cuQuery", repeatCount: 100}
# grouperCustomUI.testCustomUI.cuQuery.$i$.bindVar1 =
# bind variable 1 type
# {valueType: "string", order: 13000, showEl: "${numberOfQueries > $i$ && (cuQuery.$i$.userQueryType == 'sql') }", repeatGroup: "cuQuery", repeatCount: 100}
# grouperCustomUI.testCustomUI.cuQuery.$i$.bindVar1Type =
# bind variable 2
# {valueType: "string", order: 14000, showEl: "${numberOfQueries > $i$ && (cuQuery.$i$.userQueryType == 'sql') }", repeatGroup: "cuQuery", repeatCount: 100}
# grouperCustomUI.testCustomUI.cuQuery.$i$.bindVar2 =
# bind variable 2 type
# {valueType: "string", order: 15000, showEl: "${numberOfQueries > $i$ && (cuQuery.$i$.userQueryType == 'sql') }", repeatGroup: "cuQuery", repeatCount: 100}
# grouperCustomUI.testCustomUI.cuQuery.$i$.bindVar2Type =
# config id
# {valueType: "string", order: 16000, requiredEl: "${cuQuery.$i$.userQueryType == 'azure' || cuQuery.$i$.userQueryType == 'ldap' || cuQuery.$i$.userQueryType == 'zoom'}", showEl: "${numberOfQueries > $i$ && (cuQuery.$i$.userQueryType == 'azure' || cuQuery.$i$.userQueryType == 'ldap' || cuQuery.$i$.userQueryType == 'zoom' || cuQuery.$i$.userQueryType == 'sql') }", repeatGroup: "cuQuery", repeatCount: 100}
# grouperCustomUI.testCustomUI.cuQuery.$i$.configId =
# enabled
# {valueType: "boolean", order: 17000, defaultValue: "true", showEl: "${numberOfQueries > $i$ && (cuQuery.$i$.userQueryType == 'azure' || cuQuery.$i$.userQueryType == 'ldap' || cuQuery.$i$.userQueryType == 'zoom' || cuQuery.$i$.userQueryType == 'sql' || cuQuery.$i$.userQueryType == 'grouper' || cuQuery.$i$.userQueryType == 'expressionLanguage' || cuQuery.$i$.userQueryType == 'url') }", repeatGroup: "cuQuery", repeatCount: 100}
# grouperCustomUI.testCustomUI.cuQuery.$i$.enabled =
# error label
# {valueType: "string", order: 18000, requiredEl: "${cuQuery.$i$.userQueryType == 'azure' || cuQuery.$i$.userQueryType == 'zoom'}", showEl: "${numberOfQueries > $i$ && (cuQuery.$i$.userQueryType == 'azure' || cuQuery.$i$.userQueryType == 'zoom' || cuQuery.$i$.userQueryType == 'ldap' || cuQuery.$i$.userQueryType == 'sql' || cuQuery.$i$.userQueryType == 'grouper' || cuQuery.$i$.userQueryType == 'expressionLanguage' || cuQuery.$i$.userQueryType == 'url') }", repeatGroup: "cuQuery", repeatCount: 100}
# grouperCustomUI.testCustomUI.cuQuery.$i$.errorLabel =
# field names
# {valueType: "string", order: 19000, showEl: "${numberOfQueries > $i$ && (cuQuery.$i$.userQueryType == 'grouper') }", repeatGroup: "cuQuery", repeatCount: 100}
# grouperCustomUI.testCustomUI.cuQuery.$i$.fieldNames =
# for logged in user
# {valueType: "boolean", order: 20000, defaultValue: "false", showEl: "${numberOfQueries > $i$ && (cuQuery.$i$.userQueryType == 'azure' || cuQuery.$i$.userQueryType == 'ldap' || cuQuery.$i$.userQueryType == 'sql' || cuQuery.$i$.userQueryType == 'grouper' || cuQuery.$i$.userQueryType == 'expressionLanguage') }", repeatGroup: "cuQuery", repeatCount: 100}
# grouperCustomUI.testCustomUI.cuQuery.$i$.forLoggedInUser =
# group id
# {valueType: "string", order: 21000, showEl: "${numberOfQueries > $i$ && (cuQuery.$i$.userQueryType == 'azure' || cuQuery.$i$.userQueryType == 'ldap' || cuQuery.$i$.userQueryType == 'sql' || cuQuery.$i$.userQueryType == 'grouper' || cuQuery.$i$.userQueryType == 'expressionLanguage') }", repeatGroup: "cuQuery", repeatCount: 100}
# grouperCustomUI.testCustomUI.cuQuery.$i$.groupId =
# group name
# {valueType: "string", order: 22000, showEl: "${numberOfQueries > $i$ && (cuQuery.$i$.userQueryType == 'azure' || cuQuery.$i$.userQueryType == 'ldap' || cuQuery.$i$.userQueryType == 'sql' || cuQuery.$i$.userQueryType == 'grouper' || cuQuery.$i$.userQueryType == 'expressionLanguage') }", repeatGroup: "cuQuery", repeatCount: 100}
# grouperCustomUI.testCustomUI.cuQuery.$i$.groupName =
# label
# {valueType: "string", order: 23000, required: true, showEl: "${numberOfQueries > $i$ && (cuQuery.$i$.userQueryType == 'azure' || cuQuery.$i$.userQueryType == 'ldap' || cuQuery.$i$.userQueryType == 'zoom' || cuQuery.$i$.userQueryType == 'sql' || cuQuery.$i$.userQueryType == 'grouper' || cuQuery.$i$.userQueryType == 'expressionLanguage' || cuQuery.$i$.userQueryType == 'url') }", repeatGroup: "cuQuery", repeatCount: 100}
# grouperCustomUI.testCustomUI.cuQuery.$i$.label =
# label externalized text key
# {valueType: "string", order: 23500, required: true, showEl: "${numberOfQueries > $i$ && externalizedText && (cuQuery.$i$.userQueryType == 'azure' || cuQuery.$i$.userQueryType == 'ldap' || cuQuery.$i$.userQueryType == 'zoom' || cuQuery.$i$.userQueryType == 'sql' || cuQuery.$i$.userQueryType == 'grouper' || cuQuery.$i$.userQueryType == 'expressionLanguage')}", repeatGroup: "cuQuery", repeatCount: 100}
# grouperCustomUI.testCustomUI.cuQuery.$i$.labelExternalizedTextKey =
# ldap attribute to retrieve
# {valueType: "string", order: 24000, showEl: "${numberOfQueries > $i$ && cuQuery.$i$.userQueryType == 'ldap'}", repeatGroup: "cuQuery", repeatCount: 100}
# grouperCustomUI.testCustomUI.cuQuery.$i$.ldapAttributeToRetrieve =
# ldap filter
# {valueType: "string", order: 25000, showEl: "${numberOfQueries > $i$ && cuQuery.$i$.userQueryType == 'ldap'}", repeatGroup: "cuQuery", repeatCount: 100}
# grouperCustomUI.testCustomUI.cuQuery.$i$.ldapFilter =
# ldap search dn
# {valueType: "string", order: 26000, showEl: "${numberOfQueries > $i$ && cuQuery.$i$.userQueryType == 'ldap'}", repeatGroup: "cuQuery", repeatCount: 100}
# grouperCustomUI.testCustomUI.cuQuery.$i$.ldapSearchDn =
# name of attribute def
# {valueType: "string", order: 27000, showEl: "${numberOfQueries > $i$ && (cuQuery.$i$.userQueryType == 'sql' || cuQuery.$i$.userQueryType == 'grouper' || cuQuery.$i$.userQueryType == 'expressionLanguage') }", repeatGroup: "cuQuery", repeatCount: 100}
# grouperCustomUI.testCustomUI.cuQuery.$i$.nameOfAttributeDef =
# order
# {valueType: "integer", order: 28000, showEl: "${numberOfQueries > $i$ && (cuQuery.$i$.userQueryType == 'azure' || cuQuery.$i$.userQueryType == 'ldap' || cuQuery.$i$.userQueryType == 'zoom' || cuQuery.$i$.userQueryType == 'sql' || cuQuery.$i$.userQueryType == 'grouper' || cuQuery.$i$.userQueryType == 'expressionLanguage' || cuQuery.$i$.userQueryType == 'url') }", repeatGroup: "cuQuery", repeatCount: 100}
# grouperCustomUI.testCustomUI.cuQuery.$i$.order =
# query
# {valueType: "string", order: 29000, showEl: "${numberOfQueries > $i$ && cuQuery.$i$.userQueryType == 'sql'}", repeatGroup: "cuQuery", repeatCount: 100}
# grouperCustomUI.testCustomUI.cuQuery.$i$.query =
# script
# {valueType: "string", order: 30000, requiredEl: "${cuQuery.$i$.userQueryType == 'expressionLanguage'}", showEl: "${numberOfQueries > $i$ && (cuQuery.$i$.userQueryType == 'azure' || cuQuery.$i$.userQueryType == 'zoom' || cuQuery.$i$.userQueryType == 'expressionLanguage') }", repeatGroup: "cuQuery", repeatCount: 100}
# grouperCustomUI.testCustomUI.cuQuery.$i$.script =
# stem id
# {valueType: "string", order: 31000, showEl: "${numberOfQueries > $i$ && (cuQuery.$i$.userQueryType == 'expressionLanguage' || cuQuery.$i$.userQueryType == 'grouper' || cuQuery.$i$.userQueryType == 'sql') }", repeatGroup: "cuQuery", repeatCount: 100}
# grouperCustomUI.testCustomUI.cuQuery.$i$.stemId =
# stem name
# {valueType: "string", order: 32000, showEl: "${numberOfQueries > $i$ && (cuQuery.$i$.userQueryType == 'expressionLanguage' || cuQuery.$i$.userQueryType == 'grouper' || cuQuery.$i$.userQueryType == 'sql') }", repeatGroup: "cuQuery", repeatCount: 100}
# grouperCustomUI.testCustomUI.cuQuery.$i$.stemName =
# variable to assign
# {valueType: "string", order: 33000, required: true, showEl: "${numberOfQueries > $i$ && (cuQuery.$i$.userQueryType == 'expressionLanguage' || cuQuery.$i$.userQueryType == 'grouper' || cuQuery.$i$.userQueryType == 'ldap' || cuQuery.$i$.userQueryType == 'sql' || cuQuery.$i$.userQueryType == 'azure' || cuQuery.$i$.userQueryType == 'zoom' || cuQuery.$i$.userQueryType == 'url') }", repeatGroup: "cuQuery", repeatCount: 100}
# grouperCustomUI.testCustomUI.cuQuery.$i$.variableToAssign =
# variable to assign on error
# {valueType: "string", order: 34000, requiredEl: "${cuQuery.$i$.userQueryType == 'azure' || cuQuery.$i$.userQueryType == 'zoom'}", showEl: "${numberOfQueries > $i$ && (cuQuery.$i$.userQueryType == 'azure' || cuQuery.$i$.userQueryType == 'zoom' || cuQuery.$i$.userQueryType == 'expressionLanguage' || cuQuery.$i$.userQueryType == 'grouper' || cuQuery.$i$.userQueryType == 'ldap' || cuQuery.$i$.userQueryType == 'sql' || cuQuery.$i$.userQueryType == 'url') }", repeatGroup: "cuQuery", repeatCount: 100}
# grouperCustomUI.testCustomUI.cuQuery.$i$.variableToAssignOnError =
# variable type
# {valueType: "string", order: 35000, defaultValue: "string", showEl: "${numberOfQueries > $i$ && (cuQuery.$i$.userQueryType == 'expressionLanguage' || cuQuery.$i$.userQueryType == 'grouper' || cuQuery.$i$.userQueryType == 'ldap' || cuQuery.$i$.userQueryType == 'sql' || cuQuery.$i$.userQueryType == 'azure' || cuQuery.$i$.userQueryType == 'zoom' || cuQuery.$i$.userQueryType == 'url') }", repeatGroup: "cuQuery", formElement: "dropdown", optionValues: ["boolean", "integer", "string"], repeatCount: 100}
# grouperCustomUI.testCustomUI.cuQuery.$i$.variableType =
# allow assign from url
# {valueType: "boolean", order: 35100, defaultValue: "false", showEl: "${numberOfQueries > $i$ && (cuQuery.$i$.userQueryType == 'expressionLanguage' || cuQuery.$i$.userQueryType == 'grouper' || cuQuery.$i$.userQueryType == 'ldap' || cuQuery.$i$.userQueryType == 'sql' || cuQuery.$i$.userQueryType == 'azure' || cuQuery.$i$.userQueryType == 'zoom' || cuQuery.$i$.userQueryType == 'url')}", repeatGroup: "cuQuery", repeatCount: 100}
# grouperCustomUI.testCustomUI.cuQuery.$i$.allowAssignFromUrl =
# number of text configs
# {valueType: "string", defaultValue: "0", subSection: "cuTextConfigs", order: 36000, formElement: "dropdown", optionValues: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "100"] }
# grouperCustomUI.testCustomUI.numberOfTextConfigs =
# custom ui text type
# {valueType: "string", order: 37000, required: true, showEl: "${numberOfTextConfigs > $i$ }", repeatGroup: "cuTextConfig", repeatCount: 100, formElement: "dropdown", optionValues: ["canAssignVariables", "canSeeScreenState", "canSeeUserEnvironment", "emailBccGroupName", "emailBody", "emailSubject", "emailToUser", "enrollButtonShow", "enrollButtonText", "enrollmentLabel", "header", "helpLink", "instructions1", "logo", "managerInstructions", "unenrollButtonShow", "unenrollButtonText", "manageMembership", "redirectToUrl", "gshScript"]}
# grouperCustomUI.testCustomUI.cuTextConfig.$i$.textType =
# enabled
# {valueType: "boolean", order: 37500, showEl: "${numberOfTextConfigs > $i$ }", repeatGroup: "cuTextConfig", repeatCount: 100}
# grouperCustomUI.testCustomUI.cuTextConfig.$i$.enabled =
# end if matches
# {valueType: "boolean", order: 38000, defaultValue: "false", showEl: "${numberOfTextConfigs > $i$ }", repeatGroup: "cuTextConfig", repeatCount: 100}
# grouperCustomUI.testCustomUI.cuTextConfig.$i$.endIfMatches =
# index
# {valueType: "integer", order: 39000, required: true, showEl: "${numberOfTextConfigs > $i$ }", repeatGroup: "cuTextConfig", repeatCount: 100}
# grouperCustomUI.testCustomUI.cuTextConfig.$i$.index =
# default text
# {valueType: "boolean", order: 40000, defaultValue: "false", showEl: "${numberOfTextConfigs > $i$ }", repeatGroup: "cuTextConfig", repeatCount: 100}
# grouperCustomUI.testCustomUI.cuTextConfig.$i$.defaultText =
# text
# {valueType: "string", order: 41000, required: true, showEl: "${numberOfTextConfigs > $i$ && !(cuTextConfig.$i$.textType == 'canAssignVariables' || cuTextConfig.$i$.textType == 'canSeeScreenState' || cuTextConfig.$i$.textType == 'canSeeUserEnvironment' || cuTextConfig.$i$.textType == 'emailToUser' || cuTextConfig.$i$.textType == 'enrollButtonShow' || cuTextConfig.$i$.textType == 'unenrollButtonShow' || cuTextConfig.$i$.textType == 'manageMembership' ) }", formElement: "textarea", repeatGroup: "cuTextConfig", repeatCount: 100}
# grouperCustomUI.testCustomUI.cuTextConfig.$i$.text =
# text is script?
# {valueType: "boolean", order: 41500, defaultValue: "false", showEl: "${numberOfTextConfigs > $i$ && (cuTextConfig.$i$.textType == 'canAssignVariables' || cuTextConfig.$i$.textType == 'canSeeScreenState' || cuTextConfig.$i$.textType == 'canSeeUserEnvironment' || cuTextConfig.$i$.textType == 'emailToUser' || cuTextConfig.$i$.textType == 'enrollButtonShow' || cuTextConfig.$i$.textType == 'unenrollButtonShow' || cuTextConfig.$i$.textType == 'manageMembership' ) }", repeatGroup: "cuTextConfig", repeatCount: 100}
# grouperCustomUI.testCustomUI.cuTextConfig.$i$.textIsScript =
# text boolean scalar
# {valueType: "boolean", order: 41600, required: true, showEl: "${numberOfTextConfigs > $i$ && !cuTextConfig.$i$.textIsScript && (cuTextConfig.$i$.textType == 'canAssignVariables' || cuTextConfig.$i$.textType == 'canSeeScreenState' || cuTextConfig.$i$.textType == 'canSeeUserEnvironment' || cuTextConfig.$i$.textType == 'emailToUser' || cuTextConfig.$i$.textType == 'enrollButtonShow' || cuTextConfig.$i$.textType == 'unenrollButtonShow' || cuTextConfig.$i$.textType == 'manageMembership' ) }", repeatGroup: "cuTextConfig", repeatCount: 100}
# grouperCustomUI.testCustomUI.cuTextConfig.$i$.textBoolean =
# text boolean script
# {valueType: "string", order: 41700, required: true, showEl: "${numberOfTextConfigs > $i$ && cuTextConfig.$i$.textIsScript && (cuTextConfig.$i$.textType == 'canAssignVariables' || cuTextConfig.$i$.textType == 'canSeeScreenState' || cuTextConfig.$i$.textType == 'canSeeUserEnvironment' || cuTextConfig.$i$.textType == 'emailToUser' || cuTextConfig.$i$.textType == 'enrollButtonShow' || cuTextConfig.$i$.textType == 'unenrollButtonShow' || cuTextConfig.$i$.textType == 'manageMembership' ) }", repeatGroup: "cuTextConfig", repeatCount: 100}
# grouperCustomUI.testCustomUI.cuTextConfig.$i$.textBooleanScript =
# script
# {valueType: "string", order: 42000, showEl: "${numberOfTextConfigs > $i$ }", repeatGroup: "cuTextConfig", repeatCount: 100}
# grouperCustomUI.testCustomUI.cuTextConfig.$i$.script =
############################################
## Gsh templates configuration
############################################
# Template type
# {valueType: "string", required: true, order: 500, formElement: "dropdown", optionValues: ["gsh", "abac"] }
# grouperGshTemplate.testGshTemplate.templateType =
# enabled or disabled
# {valueType: "boolean", defaultValue: "true", order: 1000 }
# grouperGshTemplate.testGshTemplate.enabled =
# GSH template version. V1 is the original legacy version. V2 needs to implement edu.internet2.middleware.grouper.app.gsh.template.GshTemplateV2 and assign to:
# gsh_builtin_gshTemplateRuntime.assignGshTemplateV2(gshTemplateV2);
# {valueType: "string", defaultValue: "V1", order: 3000, formElement: "dropdown", optionValues: ["V1", "V2"] }
# grouperGshTemplate.testGshTemplate.templateVersion =
# show on folders
# {valueType: "boolean", defaultValue: "false", order: 6000, showEl: "${templateType == 'gsh'}" }
# grouperGshTemplate.testGshTemplate.showOnFolders =
# folder show type
# {valueType: "string", required: true, order: 7000, showEl: "${showOnFolders}", formElement: "dropdown", optionValues: ["certainFolders", "allFolders"] }
# grouperGshTemplate.testGshTemplate.folderShowType =
# comma separated folder uuids/names to show
# {valueType: "string", required: true, order: 8000, showEl: "${showOnFolders && folderShowType == 'certainFolders'}"}
# grouperGshTemplate.testGshTemplate.folderUuidToShow =
# folder show on descendants
# {valueType: "string", required: true, order: 9000, showEl: "${showOnFolders && folderShowType == 'certainFolders'}", formElement: "dropdown", optionValues: ["certainFolders", "oneChildLevel", "certainFoldersAndOneChildLevel", "descendants", "certainFoldersAndDescendants"]}
# grouperGshTemplate.testGshTemplate.folderShowOnDescendants =
# show on groups
# {valueType: "boolean", defaultValue: "false", order: 9100, showEl: "${templateType == 'gsh'}" }
# grouperGshTemplate.testGshTemplate.showOnGroups =
# groups show type
# {valueType: "string", required: true, order: 9200, showEl: "${showOnGroups}", formElement: "dropdown", optionValues: ["certainGroups", "groupsInFolder", "allGroups"] }
# grouperGshTemplate.testGshTemplate.groupShowType =
# comma separated group uuids/names to show
# {valueType: "string", required: true, order: 9300, showEl: "${showOnGroups && groupShowType == 'certainGroups'}"}
# grouperGshTemplate.testGshTemplate.groupUuidsToShow =
# folder uuid/name under which all the groups will see this template
# {valueType: "string", required: true, order: 9400, showEl: "${showOnGroups && groupShowType == 'groupsInFolder'}"}
# grouperGshTemplate.testGshTemplate.folderUuidForGroupsInFolder =
# group show on descendants
# {valueType: "string", required: true, order: 9500, showEl: "${showOnGroups && groupShowType == 'groupsInFolder'}", formElement: "dropdown", optionValues: ["oneChildLevel", "descendants"]}
# grouperGshTemplate.testGshTemplate.groupShowOnDescendants =
# default run button group or folder
# {valueType: "string", order: 9550, showEl: "${showOnFolders || showOnGroups}", formElement: "dropdown", optionValues: ["group", "folder"] }
# grouperGshTemplate.testGshTemplate.runButtonGroupOrFolder =
# group uuid or name for which this template will be run as default
# {valueType: "string", required: true, order: 9600, showEl: "${showOnGroups && runButtonGroupOrFolder == 'group' && showOnGroups}"}
# grouperGshTemplate.testGshTemplate.defaultRunButtonGroupUuidOrName =
# folder uuid or name for which this template will be run as default
# {valueType: "string", required: true, order: 9650, showEl: "${showOnFolders && runButtonGroupOrFolder == 'folder' && showOnFolders}"}
# grouperGshTemplate.testGshTemplate.defaultRunButtonFolderUuidOrName =
# security run type
# {valueType: "string", required: true, order: 10000,formElement: "dropdown", optionValues: ["wheel", "specifiedGroup", "privilegeOnObject", "everyone"] }
# grouperGshTemplate.testGshTemplate.securityRunType =
# group uuid can run
# {valueType: "string", required: true, order: 11000, showEl: "${securityRunType == 'specifiedGroup'}"}
# grouperGshTemplate.testGshTemplate.groupUuidCanRun =
# require folder privilege
# {valueType: "string", required: true, order: 12000, showEl: "${showOnFolders && securityRunType == 'privilegeOnObject'}", formElement: "dropdown", optionValues: ["admin", "create", "stemAttrRead", "stemAttrUpdate"] }
# grouperGshTemplate.testGshTemplate.requireFolderPrivilege =
# run as type
# {valueType: "string", required: true, order: 14000, formElement: "dropdown", optionValues: ["currentUser", "GrouperSystem", "specifiedSubject"] }
# grouperGshTemplate.testGshTemplate.runAsType =
# act as group uuid
# {valueType: "string", order: 14500, showEl: "${templateType == 'gsh'}" }
# grouperGshTemplate.testGshTemplate.actAsGroupUUID =
# run as specified subject source id
# {valueType: "string", required: true, order: 15000, formElement: "dropdown", showEl: "${runAsType == 'specifiedSubject'}", optionValuesFromClass: "edu.internet2.middleware.subject.provider.SourceManagerOptionValueDriver" }
# grouperGshTemplate.testGshTemplate.runAsSpecifiedSubjectSourceId =
# run as specified subject id
# {valueType: "string", required: true, order: 16000, showEl: "${runAsType == 'specifiedSubject'}"}
# grouperGshTemplate.testGshTemplate.runAsSpecifiedSubjectId =
# use externalized text for labels and descriptions?
# {valueType: "boolean", defaultValue: "false", order: 16500 }
# grouperGshTemplate.testGshTemplate.externalizedText =
# template name externalized text key
# {valueType: "string", required: true, order: 17000, showEl: "${externalizedText}" }
# grouperGshTemplate.testGshTemplate.templateNameExternalizedTextKey =
# template name
# {valueType: "string", required: true, order: 17500, showEl: "${!externalizedText}" }
# grouperGshTemplate.testGshTemplate.templateName =
# template description externalized text key
# {valueType: "string", required: true, order: 18000, showEl: "${externalizedText}"}
# grouperGshTemplate.testGshTemplate.templateDescriptionExternalizedTextKey =
# template description
# {valueType: "string", required: true, order: 18500, showEl: "${!externalizedText}", formElement: "textarea"}
# grouperGshTemplate.testGshTemplate.templateDescription =
# should show in More actions
# {valueType: "boolean", defaultValue: "false", order: 18550, showEl: "${templateType == 'gsh'}"}
# grouperGshTemplate.testGshTemplate.showInMoreActions =
# More actions externalized label
# {valueType: "string", required: true, order: 18551, showEl: "${externalizedText && showInMoreActions}" }
# grouperGshTemplate.testGshTemplate.moreActionsLabelExternalizedTextKey =
# More actions label
# {valueType: "string", required: true, order: 18552, showEl: "${!externalizedText && showInMoreActions}" }
# grouperGshTemplate.testGshTemplate.moreActionsLabel =
# Display error message and output on screen
# {valueType: "boolean", defaultValue: "false", order: 18555 }
# grouperGshTemplate.testGshTemplate.displayErrorOutput =
# gsh lightweight
# {valueType: "boolean", defaultValue: "false", order: 18600, showEl: "${templateType == 'gsh'}" }
# grouperGshTemplate.testGshTemplate.gshLightweight =
# run gsh script in a transaction
# {valueType: "boolean", defaultValue: "true", order: 18700, showEl: "${templateType == 'gsh'}" }
# grouperGshTemplate.testGshTemplate.runGshInTransaction =
# use individual audits?
# {valueType: "boolean", defaultValue: "true", order: 18800, showEl: "${templateType == 'gsh'}" }
# grouperGshTemplate.testGshTemplate.useIndividualAudits =
# consolidate output
# {valueType: "boolean", defaultValue: "true", order: 18900, showEl: "${templateType == 'gsh'}" }
# grouperGshTemplate.testGshTemplate.consolidateOutput =
# simplified ui
# {valueType: "boolean", defaultValue: "false", order: 18950 }
# grouperGshTemplate.testGshTemplate.simplifiedUi =
# allow WS from no owner
# {valueType: "boolean", defaultValue: "false", order: 18975 }
# grouperGshTemplate.testGshTemplate.allowWsFromNoOwner =
# gsh template code
# {valueType: "string", required: true, order: 19000, formElement: "textarea" }
# grouperGshTemplate.testGshTemplate.gshTemplate =
# number of inputs
# {valueType: "string", defaultValue: "0", order: 20000, formElement: "dropdown", optionValues: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "50"] }
# grouperGshTemplate.testGshTemplate.numberOfInputs =
# input name
# {valueType: "string", required: true, order: 21000, showEl: "${numberOfInputs > $i$}", repeatGroup: "input", repeatCount: 50}
# grouperGshTemplate.testGshTemplate.input.$i$.name =
# label externalized text key
# {valueType: "string", order: 22000, required: true, showEl: "${numberOfInputs > $i$ && externalizedText}", repeatGroup: "input", repeatCount: 50}
# grouperGshTemplate.testGshTemplate.input.$i$.labelExternalizedTextKey =
# label text
# {valueType: "string", order: 22500, required: true, showEl: "${numberOfInputs > $i$ && !externalizedText}", repeatGroup: "input", repeatCount: 50}
# grouperGshTemplate.testGshTemplate.input.$i$.label =
# label externalized description key
# {valueType: "string", order: 23000, required: true, showEl: "${numberOfInputs > $i$ && externalizedText}", repeatGroup: "input", repeatCount: 50}
# grouperGshTemplate.testGshTemplate.input.$i$.descriptionExternalizedTextKey =
# description
# {valueType: "string", order: 23500, required: true, showEl: "${numberOfInputs > $i$ && !externalizedText}", repeatGroup: "input", repeatCount: 50}
# grouperGshTemplate.testGshTemplate.input.$i$.description =
# input type
# {valueType: "string", order: 24000, showEl: "${numberOfInputs > $i$}", defaultValue: "string", repeatGroup: "input", repeatCount: 50, formElement: "dropdown", optionValues: ["integer", "boolean", "string"]}
# grouperGshTemplate.testGshTemplate.input.$i$.type =
# form element type
# {valueType: "string", order: 25000, showEl: "${numberOfInputs > $i$ && input.$i$.type != 'boolean' }", defaultValue: "text", repeatGroup: "input", repeatCount: 50, formElement: "dropdown", optionValues: ["text", "textarea", "dropdown", "password"]}
# grouperGshTemplate.testGshTemplate.input.$i$.formElementType =
# value format for dropdowns
# {valueType: "string", order: 25500, showEl: "${numberOfInputs > $i$ && input.$i$.formElementType == 'dropdown'}", defaultValue: "csv", repeatGroup: "input", repeatCount: 50, formElement: "dropdown", optionValues: ["csv", "dynamicFromTemplate", "javaclass", "json", "sql"]}
# grouperGshTemplate.testGshTemplate.input.$i$.dropdownValueFormat =
# value format csv
# {valueType: "string", order: 25600, showEl: "${numberOfInputs > $i$ && input.$i$.formElementType == 'dropdown' && input.$i$.dropdownValueFormat == 'csv'}", required: true, repeatGroup: "input", repeatCount: 50, formElement: "textarea"}
# grouperGshTemplate.testGshTemplate.input.$i$.dropdownCsvValue =
# value format sql database
# {valueType: "string", order: 25630, showEl: "${numberOfInputs > $i$ && input.$i$.formElementType == 'dropdown' && input.$i$.dropdownValueFormat == 'sql'}", required: true, repeatGroup: "input", repeatCount: 50, formElement: "dropdown", optionValuesFromClass: "edu.internet2.middleware.grouper.app.loader.db.DatabaseGrouperExternalSystem"}
# grouperGshTemplate.testGshTemplate.input.$i$.dropdownSqlDatabase =
# value format sql
# {valueType: "string", order: 25640, showEl: "${numberOfInputs > $i$ && input.$i$.formElementType == 'dropdown' && input.$i$.dropdownValueFormat == 'sql'}", required: true, repeatGroup: "input", repeatCount: 50, formElement: "textarea"}
# grouperGshTemplate.testGshTemplate.input.$i$.dropdownSqlValue =
# cache for minutes (default 2)
# {valueType: "string", order: 25660, showEl: "${numberOfInputs > $i$ && input.$i$.formElementType == 'dropdown' && input.$i$.dropdownValueFormat == 'sql'}", defaultValue: "2", repeatGroup: "input", repeatCount: 50}
# grouperGshTemplate.testGshTemplate.input.$i$.dropdownSqlCacheForMinutes =
# value format json
# {valueType: "string", order: 25700, showEl: "${numberOfInputs > $i$ && input.$i$.formElementType == 'dropdown' && input.$i$.dropdownValueFormat == 'json'}", required: true, repeatGroup: "input", repeatCount: 50, formElement: "textarea"}
# grouperGshTemplate.testGshTemplate.input.$i$.dropdownJsonValue =
# value format javaclass
# {valueType: "string", order: 25800, showEl: "${numberOfInputs > $i$ && input.$i$.formElementType == 'dropdown' && input.$i$.dropdownValueFormat == 'javaclass'}", required: true, repeatGroup: "input", repeatCount: 50}
# grouperGshTemplate.testGshTemplate.input.$i$.dropdownJavaClassValue =
# max length
# {valueType: "integer", defaultValue: "500", order: 26500, showEl: "${numberOfInputs > $i$ && (input.$i$.formElementType == 'text' || input.$i$.formElementType == 'textarea') && input.$i$.type != 'boolean'}", repeatGroup: "input", repeatCount: 50}
# grouperGshTemplate.testGshTemplate.input.$i$.maxLength =
# index
# {valueType: "string", order: 26000, showEl: "${numberOfInputs > $i$}", defaultValue: "0", repeatGroup: "input", repeatCount: 50}
# grouperGshTemplate.testGshTemplate.input.$i$.index =
# validation type
# {valueType: "string", required: true, order: 27000, showEl: "${numberOfInputs > $i$ && input.$i$.type != 'boolean' && input.$i$.formElementType != 'dropdown'}", repeatGroup: "input", repeatCount: 50, formElement: "dropdown", optionValues: ["builtin", "regex", "jexl", "none"]}
# grouperGshTemplate.testGshTemplate.input.$i$.validationType =
# builtin validation type
# {valueType: "string", required: true, order: 27500, showEl: "${numberOfInputs > $i$ && input.$i$.validationType == 'builtin'}", repeatGroup: "input", repeatCount: 50, formElement: "dropdown", optionValues: ["alpha", "alphaNumeric", "alphaNumericUnderscore", "alphaNumericDash", "alphaNumericUnderscoreDash", "noColons"]}
# grouperGshTemplate.testGshTemplate.input.$i$.validationBuiltin =
# validation regex
# {valueType: "string", required: true, order: 28000, showEl: "${numberOfInputs > $i$ && input.$i$.validationType == 'regex'}", repeatGroup: "input", repeatCount: 50}
# grouperGshTemplate.testGshTemplate.input.$i$.validationRegex =
# validation jexl
# {valueType: "string", required: true, order: 29000, showEl: "${numberOfInputs > $i$ && input.$i$.validationType == 'jexl'}", repeatGroup: "input", repeatCount: 50}
# grouperGshTemplate.testGshTemplate.input.$i$.validationJexl =
# validation message exteranlized text key
# {valueType: "string", order: 30000, repeatGroup: "input", repeatCount: 50, showEl: "${numberOfInputs > $i$ && externalizedText && input.$i$.validationType != 'none' && input.$i$.type != 'boolean' && input.$i$.formElementType != 'dropdown'}"}
# grouperGshTemplate.testGshTemplate.input.$i$.validationMessageExternalizedTextKey =
# validation message text
# {valueType: "string", order: 30500, repeatGroup: "input", repeatCount: 50, showEl: "${numberOfInputs > $i$ && !externalizedText && input.$i$.validationType != 'none' && input.$i$.type != 'boolean' && input.$i$.formElementType != 'dropdown'}"}
# grouperGshTemplate.testGshTemplate.input.$i$.validationMessage =
# required or not
# {valueType: "boolean", defaultValue: "false", order: 31000, repeatGroup: "input", repeatCount: 50, showEl: "${numberOfInputs > $i$}"}
# grouperGshTemplate.testGshTemplate.input.$i$.required =
# default value for the input if none is provided
# {valueType: "string", order: 32000, repeatGroup: "input", repeatCount: 50, showEl: "${numberOfInputs > $i$ && !input.$i$.required}"}
# grouperGshTemplate.testGshTemplate.input.$i$.defaultValue =
# show el jexl
# {valueType: "string", order: 33000, showEl: "${numberOfInputs > $i$}", repeatGroup: "input", repeatCount: 50}
# grouperGshTemplate.testGshTemplate.input.$i$.showEl =
# trim whitespace in values
# {valueType: "boolean", order: 33500, defaultValue: "true", showEl: "${numberOfInputs > $i$ && input.$i$.type != 'boolean' && input.$i$.formElementType !='dropdown'}", repeatGroup: "input", repeatCount: 50}
# grouperGshTemplate.testGshTemplate.input.$i$.trimWhitespace =
# number of tests
# {valueType: "string", defaultValue: "0", order: 34000, subSection: "test", formElement: "dropdown", optionValues: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20"] }
# 1grouperGshTemplate.testGshTemplate.numberOfTests =
# delete side effects if exist gsh
# {valueType: "string", order: 35000, formElement: "textarea", showEl: "${numberOfTests > $i$}", repeatGroup: "test", repeatCount: 20}
# 1grouperGshTemplate.testGshTemplate.test.$i$.deleteSideEffectsIfExistGsh =
# set up gsh
# {valueType: "string", order: 36000, formElement: "textarea", showEl: "${numberOfTests > $i$}", repeatGroup: "test", repeatCount: 20}
# 1grouperGshTemplate.testGshTemplate.test.$i$.setupGsh =
# test gsh
# {valueType: "string", order: 37000, formElement: "textarea", required: true, showEl: "${numberOfTests > $i$}", repeatGroup: "test", repeatCount: 20}
# 1grouperGshTemplate.testGshTemplate.test.$i$.testGsh =
# verify gsh
# {valueType: "string", order: 37000, formElement: "textarea", showEl: "${numberOfTests > $i$}", repeatGroup: "test", repeatCount: 20}
# 1grouperGshTemplate.testGshTemplate.test.$i$.verifyGsh =
############################################
## Ws trusted jwt config
############################################
# enabled or disabled
# {valueType: "boolean", defaultValue: "true", order: 1000 }
# grouper.jwt.trusted.testConfigId.enabled =
# subject source id
# {valueType: "string", order: 2000, formElement: "checkbox", checkboxValuesFromClass: "edu.internet2.middleware.grouper.SubjectFinder"}
# grouper.jwt.trusted.testConfigId.subjectSourceIds =
# subject id type
# {valueType: "string", required: true, order: 3000, formElement: "dropdown", optionValues: ["subjectId", "subjectIdentifier", "subjectIdOrIdentifier"] }
# grouper.jwt.trusted.testConfigId.subjectIdType =
# some claim name that has the subjectId in it. optional, can just label claim name as "subjectId", "subjectIdentifier", or "subjectIdOrIdentifier". e.g. employeeId
# {valueType: "string", order: 4000 }
# grouper.jwt.trusted.testConfigId.subjectIdClaimName =
# JWTs only last for so long. e.g. 600 is 10 minutes. -1 means never expire (not recommended)
# {valueType: "integer", order: 5000}
# grouper.jwt.trusted.testConfigId.expirationSeconds =
# number of keys
# {valueType: "string", defaultValue: "0", order: 6000, formElement: "dropdown", optionValues: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"] }
# grouper.jwt.trusted.testConfigId.numberOfKeys =
# public key
# {valueType: "string", formElement: "textarea", required: true, order: 7000, showEl: "${numberOfKeys > $i$}", repeatGroup: "key", repeatCount: 10}
# grouper.jwt.trusted.testConfigId.key.$i$.publicKey =
# encryption type
# {valueType: "string", required: true, order: 8000, showEl: "${numberOfKeys > $i$}", repeatGroup: "key", repeatCount: 10, formElement: "dropdown", optionValues: ["RS-256", "RS-384", "RS-512"]}
# grouper.jwt.trusted.testConfigId.key.$i$.encryptionType =
# optional: yyyy-mm-dd hh:mm:ss.SSS
# {valueType: "string", order: 9000, showEl: "${numberOfKeys > $i$}", repeatGroup: "key", repeatCount: 10}
# grouper.jwt.trusted.testConfigId.key.$i$.expiresOn =
######################################
## Global entity attribute resolvers
## These SQL or LDAP attribute resolvers could be used in multiple provisioners or other areas
## entityAttributeResolverId is the unique configId for the attribute resolver
######################################
# Entity attribute resolver type
# {valueType: "string", order: 1000, regex: "^entityAttributeResolver\\.([^.]+)\\.resolverType$", required: true, formElement: "dropdown", optionValues: ["sql", "ldap"]}
# entityAttributeResolver.entityAttributeResolverId.resolverType =
# if this resolver is enabled
# {valueType: "boolean", defaultValue: "true", order: 2000 }
# entityAttributeResolver.entityAttributeResolverId.enabled =
# SQL configId for database connection, default to grouper database
# {valueType: "string", order: 3000, regex: "^entityAttributeResolver\\.([^.]+)\\.sqlConfigId$", formElement: "dropdown", optionValuesFromClass: "edu.internet2.middleware.grouper.app.loader.db.DatabaseGrouperExternalSystem", showEl: "${resolverType == 'sql'}"}
# entityAttributeResolver.entityAttributeResolverId.sqlConfigId =
# Table of user data, must have a subject source (optional), and matching/search col (required), and columns with single valued attributes
# {valueType: "string", order: 4000, regex: "^entityAttributeResolver\\.([^.]+)\\.tableOrViewName$", required: true, showEl: "${resolverType == 'sql'}"}
# entityAttributeResolver.entityAttributeResolverId.tableOrViewName =
# Comma separated column names from the entity attributes table that need to be added as attributes in the target system
# {valueType: "string", order: 4500, regex: "^entityAttributeResolver\\.([^.]+)\\.columnNames$", required: true, showEl: "${resolverType == 'sql'}"}
# entityAttributeResolver.entityAttributeResolverId.columnNames =
# The subject source id column
# {valueType: "string", order: 5000, regex: "^entityAttributeResolver\\.([^.]+)\\.subjectSourceIdColumn$", showEl: "${resolverType == 'sql'}", formElement: "dropdown", optionValuesFromClass: "edu.internet2.middleware.subject.provider.SourceManagerOptionValueDriver"}
# entityAttributeResolver.entityAttributeResolverId.subjectSourceIdColumn =
# Column that searches and matches an entity
# {valueType: "string", order: 6000, regex: "^entityAttributeResolver\\.([^.]+)\\.subjectSearchMatchingColumn$", required: true, showEl: "${resolverType == 'sql'}"}
# entityAttributeResolver.entityAttributeResolverId.subjectSearchMatchingColumn =
# Grouper attribute that matches the row
# {valueType: "string", order: 7000, regex: "^entityAttributeResolver\\.([^.]+)\\.grouperAttributeThatMatchesRow$", required: true, showEl: "${resolverType == 'sql'}", formElement: "dropdown", optionValues: ['subjectId', 'subjectIdentifer0']}
# entityAttributeResolver.entityAttributeResolverId.grouperAttributeThatMatchesRow =
# The last updated column, e.g. a timestamp or number field (number of millis since 1970)
# {valueType: "string", order: 8000, regex: "^entityAttributeResolver\\.([^.]+)\\.lastUpdatedColumn$", showEl: "${resolverType == 'sql'}"}
# entityAttributeResolver.entityAttributeResolverId.lastUpdatedColumn =
# The last updated column type, e.g. timestamp, millisSince1970. If this is provided then the incremental provisioner will process people that have been recently updated
# {valueType: "string", order: 9000, regex: "^entityAttributeResolver\\.([^.]+)\\.lastUpdatedColumn$", showEl: "${resolverType == 'sql'}", formElement: "dropdown", optionValues: ['timestamp', 'millisSince1970']}
# entityAttributeResolver.entityAttributeResolverId.lastUpdatedType =
# LDAP configId for connection
# {valueType: "string", order: 10000, regex: "^entityAttributeResolver\\.([^.]+)\\.ldapConfigId$", required: true, formElement: "dropdown", optionValuesFromClass: "edu.internet2.middleware.grouper.app.externalSystem.LdapGrouperExternalSystem", showEl: "${resolverType == 'ldap'}"}
#entityAttributeResolver.entityAttributeResolverId.ldapConfigId =
# Base DN for search
# {valueType: "string", order: 11000, regex: "^entityAttributeResolver\\.([^.]+)\\.baseDn$", showEl: "${resolverType == 'ldap'}", required: true}
# entityAttributeResolver.entityAttributeResolverId.baseDn =
# subject source id of subjects
# {valueType: "string", order: 11500, regex: "^entityAttributeResolver\\.([^.]+)\\.subjectSourceId$", formElement: "dropdown", optionValuesFromClass: "edu.internet2.middleware.subject.provider.SourceManagerOptionValueDriver"}
# entityAttributeResolver.entityAttributeResolverId.subjectSourceId =
# Search scope, default is SUBTREE_SCOPE
# {valueType: "string", order: 12000, regex: "^entityAttributeResolver\\.([^.]+)\\.searchScope$", showEl: "${resolverType == 'ldap'}", required: true, formElement: "dropdown", optionValues: ['ONELEVEL_SCOPE', ' SUBTREE_SCOPE']}
# entityAttributeResolver.entityAttributeResolverId.searchScope =
# If there is more to the filter for all users or selected user than just the search attribute, then put that here. e.g. if you have a search attribute of employeeID, and you want the
# filter to be (&(employeeID=12345678)(objectClass=person)) then you should fill in this value as: (objectClass=person)
# {valueType: "string", order: 13000, regex: "^entityAttributeResolver\\.([^.]+)\\.filterPart$", showEl: "${resolverType == 'ldap'}"}
# entityAttributeResolver.entityAttributeResolverId.filterPart =
# Attributes to retrieve (multi-valued attributes will be stored in appropriate structure)
# {valueType: "string", order: 14000, regex: "^entityAttributeResolver\\.([^.]+)\\.ldapAttributes$", showEl: "${resolverType == 'ldap'}", required: true}
# entityAttributeResolver.entityAttributeResolverId.ldapAttributes =
# Which attributes are multivalued
# {valueType: "string", order: 14500, regex: "^entityAttributeResolver\\.([^.]+)\\.multiValuedLdapAttributes$", showEl: "${resolverType == 'ldap'}"}
# entityAttributeResolver.entityAttributeResolverId.multiValuedLdapAttributes =
# LDAP matching / search attribute, this needs to be the same as the subject ID or subject identifier0
# {valueType: "string", order: 15000, regex: "^entityAttributeResolver\\.([^.]+)\\.subjectSearchMatchingAttribute$", showEl: "${resolverType == 'ldap'}", required: true}
# entityAttributeResolver.entityAttributeResolverId.subjectSearchMatchingAttribute =
# Grouper attribute that matches the record
# {valueType: "string", order: 16000, regex: "^entityAttributeResolver\\.([^.]+)\\.grouperAttributeThatMatchesRecord$", required: true, showEl: "${resolverType == 'ldap'}", formElement: "dropdown", optionValues: ['subjectId', 'subjectIdentifer0']}
# entityAttributeResolver.entityAttributeResolverId.grouperAttributeThatMatchesRecord =
# If provided the incremental can poll for new records to process. e.g. the filter would be (openldap / edirectory) (modifyTimestamp>=20211119082103Z), or Active Directory: (modifyTimestamp>= 20211119163324.0Z)
# {valueType: "string", order: 17000, regex: "^entityAttributeResolver\\.([^.]+)\\.lastUpdatedAttribute$", showEl: "${resolverType == 'ldap'}"}
# entityAttributeResolver.entityAttributeResolverId.lastUpdatedAttribute =
# This is optional, if not selected it will select default 20211119082103Z for a non AD connection and activeDirectory 20211119163324.0Z for
# an active directory connection (which is selected in the external system)
# {valueType: "string", order: 18000, regex: "^entityAttributeResolver\\.([^.]+)\\.ldapLastUpdatedFormat$", showEl: "${resolverType == 'ldap'}", formElement: "dropdown", optionValues: ['default', 'activeDirectory']}
# entityAttributeResolver.entityAttributeResolverId.ldapLastUpdatedFormat =
############################################
## OIDC external system
############################################
# if this oidc connector is enabled
# {valueType: "boolean", defaultValue: "true", order: 1000 }
# grouper.oidcExternalSystem.myOidcConfigId.enabled =
# Do you want to specify URLs or want to use the well known URL?
# {valueType: "boolean", required: true, order: 1250 }
# grouper.oidcExternalSystem.myOidcConfigId.useConfigurationMetadata =
# Configuration metadata uri
# {valueType: "string", required: true, order: 1500, showEl: "${useConfigurationMetadata}"}
# grouper.oidcExternalSystem.myOidcConfigId.configurationMetadataUri =
# url to decode the oidc code into an access token: https://idp.institution.edu/idp/profile/oidc/token
# {valueType: "string", required: true, order: 2000, showEl: "${!useConfigurationMetadata}" }
# grouper.oidcExternalSystem.myOidcConfigId.tokenEndpointUri =
# URL to log in (without parameters) https://idp.institution.edu/idp/profile/oidc/authorize
# {valueType: "string", required: false, order: 3500, showEl: "${!useConfigurationMetadata}" }
# grouper.oidcExternalSystem.myOidcConfigId.authorizeUri =
# client id to authorize url (required)
# {valueType: "string", required: true, order: 4000 }
# grouper.oidcExternalSystem.myOidcConfigId.clientId =
# secret to ws (required)
# {valueType: "password", sensitive: true, required: true, order: 5000 }
# grouper.oidcExternalSystem.myOidcConfigId.clientSecret =
# proxy requests here, e.g. https://server:1234
# {valueType: "string", order: 6000 }
# grouper.oidcExternalSystem.myOidcConfigId.proxyUrl =
# socks or http
# {valueType: "string", order: 7000, formElement: "dropdown", optionValues: ["PROXY_HTTP", "PROXY_SOCKS5"] }
# grouper.oidcExternalSystem.myOidcConfigId.proxyType =
# needed for retrieving an access token, e.g. https://my.app/someUrlBackFromIdp
# {valueType: "string", order: 10000 }
# grouper.oidcExternalSystem.myOidcConfigId.redirectUri =
# Scope to retrieve from oidc, e.g. openid email profile (required)
# {valueType: "string", required: true, order: 11000}
# grouper.oidcExternalSystem.myOidcConfigId.scope =
# subject source id
# {valueType: "string", order: 12000, formElement: "checkbox", checkboxValuesFromClass: "edu.internet2.middleware.grouper.SubjectFinder"}
# grouper.oidcExternalSystem.myOidcConfigId.subjectSourceIds =
# Subject id type
# {valueType: "string", required: true, order: 13000, formElement: "dropdown", optionValues: ["subjectId", "subjectIdentifier", "subjectIdOrIdentifier"] }
# grouper.oidcExternalSystem.myOidcConfigId.subjectIdType =
# Source for claims
# {valueType: "string", defaultValue: "userInfoEndpoint", order: 13100, formElement: "dropdown", optionValues: ["userInfoEndpoint", "idToken"]}
# grouper.oidcExternalSystem.myOidcConfigId.claimSource =
# url to get the user info from the access token https://idp.pennkey.upenn.edu/idp/profile/oidc/userinfo
# {valueType: "string", required: true, order: 13200, indent: 1, showEl: "${!useConfigurationMetadata && claimSource == 'userInfoEndpoint'}" }
# grouper.oidcExternalSystem.myOidcConfigId.userInfoUri =
# Token issuer (iss claim in id token)
# {valueType: "string", required: true, order: 13300, indent: 1, showEl: "${!useConfigurationMetadata && claimSource == 'idToken'}" }
# grouper.oidcExternalSystem.myOidcConfigId.issuer =
# The maximum acceptable clock skew in seconds for timestamps in the id token
# {valueType: "integer", defaultValue: "300", order: 13400, indent: 1, showEl: "${claimSource == 'idToken'}" }
# grouper.oidcExternalSystem.myOidcConfigId.maxClockSkew =
# some claim name that has the subjectId / subjectIdentifier / subjectIdOrIdentifier in it. e.g. preferred_username
# {valueType: "string", defaultValue: "preferred_username", order: 14000 }
# grouper.oidcExternalSystem.myOidcConfigId.subjectIdClaimName =
# e.g. code
# {valueType: "string", order: 15000 }
# grouper.oidcExternalSystem.myOidcConfigId.oidcResponseType =
# Use for UI?
# {valueType: "boolean", defaultValue: "false", order: 16000 }
# grouper.oidcExternalSystem.myOidcConfigId.useForUi =
# Use for WS?
# {valueType: "boolean", defaultValue: "false", order: 17000 }
# grouper.oidcExternalSystem.myOidcConfigId.useForWs =
############################################
## osgi config
############################################
# directory of plugins, default to /opt/grouper/grouperWebapp/WEB-INF/grouperPlugins
# {valueType: "string", required: true, order: 1000}
grouper.osgi.jar.dir = /opt/grouper/grouperWebapp/WEB-INF/grouperPlugins
# directory of felix cache of plugins, default to /opt/grouper/grouperWebapp/WEB-INF/grouperFelixCache
# {valueType: "string", required: true, order: 2000}
grouper.felix.cache.rootdir = /opt/grouper/grouperWebapp/WEB-INF/grouperFelixCache
# only enable osgi if you use it
# {valueType: "boolean", defaultValue: "false", order: 3000}
grouper.osgi.enable =
# jar name of plugin e.g. my-plugin-with-embedded-dependencies-1.2.3.jar
# {valueType: "string", required: true, order: 10000}
# grouperOsgiPlugin.testConfigId.jarName =
# number of implementations that this jar provides
# {valueType: "integer", required: true, order: 11000, formElement: "dropdown", optionValues: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"] }
# grouperOsgiPlugin.testConfigId.numberOfImplementations =
# implementation class that implements an interface, e.g. some.package.SomeClass
# {valueType: "string", required: true, order: 12000, showEl: "${numberOfImplementations > $i$}", repeatGroup: "osgiImplementation", repeatCount: 10}
# grouperOsgiPlugin.testConfigId.osgiImplementation.$i$.implementationClass =
# interface that the class implements. e.g. edu.interent2.middleware.grouper.some.package.SomeInterface
# {valueType: "string", required: true, order: 13000, showEl: "${numberOfImplementations > $i$}", repeatGroup: "osgiImplementation", repeatCount: 10}
# grouperOsgiPlugin.testConfigId.osgiImplementation.$i$.implementsInterface =
############################################
## logging loggers (levels and appenders)
## dynamically update grouper on config change
############################################
# if should check for dynamic updates
# {valueType: "boolean", defaultValue: "true" }
# grouper.logging.dynamicUpdates.run =
# sleep for this amount of seconds after each run
# {valueType: "boolean", defaultValue: "60" }
# grouper.logging.dynamicUpdates.checkAfterSeconds =
# this is the package or class to log, required
# {valueType: "string", regex: "^grouper\\.logger\\.[^.]+\\.name$"}
# grouper.logger..name =
# required log level, should be one of: off, fatal, error, warn, info, debug, trace, all
# {valueType: "string", regex: "^grouper\\.logger\\.[^.]+\\.level$", formElement: "dropdown", optionValues: ["off", "fatal", "error", "warn", "info", "debug", "trace", "all"] }
# grouper.logger..level =
# which appender to send logs to (optional), default to the appender for the class logs to, or default to: grouper_error
# e.g. CATALINA, stderr, grouper_error, grouper_daemon, grouper_pspng, grouper_provisioning, grouper_ws, grouper_ws_longRunning
# {valueType: "string", regex: "^grouper\\.logger\\.[^.]+\\.appender$"}
# grouper.logger..appender =
###########################################################################
## institution specific external systems. For e.g. for custom provisioner
###########################################################################
# This is the external system class that extends edu.internet2.middleware.grouper.app.externalSystem.GrouperExternalSystem
# {valueType: "string", regex: "^grouperExtraExternalSystem\\.[^.]+\\.class$", mustExtendClass: "edu.internet2.middleware.grouper.app.externalSystem.GrouperExternalSystem"}
# grouperExtraExternalSystem..class =
###########################################################################
## grouper dictionary
###########################################################################
# max terms in memory
# {valueType: "integer"}
grouper.dictionary.maxTermsInMemoryCache = 50000
# how long to cache terms
# {valueType: "integer"}
grouper.dictionary.cacheStoreForMinutes = 120
###########################################################################
## privacy realms
###########################################################################
# name of this privacy realm, not really used, just here to configure the realm
# {valueType: "string", required: true, regex: "^grouperPrivacyRealm\\.[^.]+\\.privacyRealmName$"}
# grouperPrivacyRealm.privacyRealmConfigId.privacyRealmName =
# if this field can be seen by anyone, even if not authenticated
# {valueType: "boolean", defaultValue: "false", regex: "^grouperPrivacyRealm\\.[^.]+\\.privacyRealmPublic$"}
# grouperPrivacyRealm.privacyRealmConfigId.privacyRealmPublic =
# if this field can be seen by anyone who is authenticated
# {valueType: "boolean", defaultValue: "false", regex: "^grouperPrivacyRealm\\.[^.]+\\.privacyRealmAuthenticated$", showEl: "${!privacyRealmPublic}"}
# grouperPrivacyRealm.privacyRealmConfigId.privacyRealmAuthenticated =
# if this field can be seen by grouper sysadmins who are not in the viewers group
# {valueType: "boolean", defaultValue: "true", regex: "^grouperPrivacyRealm\\.[^.]+\\.privacyRealmSysadminsCanView$", showEl: "${!privacyRealmPublic && !privacyRealmAuthenticated}"}
# grouperPrivacyRealm.privacyRealmConfigId.privacyRealmSysadminsCanView =
# group name of the group who can view and use fields marked in this privacy realm
# {valueType: "string", required: true, regex: "^grouperPrivacyRealm\\.[^.]+\\.privacyRealmViewersGroupName$", showEl: "${!privacyRealmPublic && !privacyRealmAuthenticated}"}
# grouperPrivacyRealm.privacyRealmConfigId.privacyRealmViewersGroupName =
# group name of the group who can update and use fields marked in this privacy realm
# {valueType: "string", required: true, regex: "^grouperPrivacyRealm\\.[^.]+\\.privacyRealmUpdatersGroupName$", showEl: "${!privacyRealmPublic && !privacyRealmAuthenticated}"}
# grouperPrivacyRealm.privacyRealmConfigId.privacyRealmUpdatersGroupName =
# group name of the group who can read and use fields marked in this privacy realm
# {valueType: "string", required: true, regex: "^grouperPrivacyRealm\\.[^.]+\\.privacyRealmReadersGroupName$", showEl: "${!privacyRealmPublic && !privacyRealmAuthenticated}"}
# grouperPrivacyRealm.privacyRealmConfigId.privacyRealmReadersGroupName =
###########################################################################
## grouper data fields
###########################################################################
# aliases that this field is referred to as
# {valueType: "string", required: true, multiple: true, regex: "^grouperDataField\\.[^.]+\\.fieldAliases$"}
# grouperDataField.dataFieldConfigId.fieldAliases =
# privacy realm for people who can see or use this data field
# {valueType: "string", required: true, regex: "^grouperDataField\\.[^.]+\\.fieldPrivacyRealm$", formElement: "dropdown", optionValuesFromClass: "edu.internet2.middleware.grouper.dataField.GrouperPrivacyRealm"}
# grouperDataField.dataFieldConfigId.fieldPrivacyRealm =
# Description html
# {valueType: "string", required: true, regex: "^grouperDataField\\.[^.]+\\.descriptionHtml$", formElement: "textarea"}
# grouperDataField.dataFieldConfigId.descriptionHtml =
# Data owner html
# {valueType: "string", regex: "^grouperDataField\\.[^.]+\\.dataOwnerHtml$", formElement: "textarea"}
# grouperDataField.dataFieldConfigId.dataOwnerHtml =
# How to get access html
# {valueType: "string", regex: "^grouperDataField\\.[^.]+\\.howToGetAccessHtml$", formElement: "textarea"}
# grouperDataField.dataFieldConfigId.howToGetAccessHtml =
# Zero to many examples html
# {valueType: "string", regex: "^grouperDataField\\.[^.]+\\.zeroToManyExamplesHtml$", formElement: "textarea"}
# grouperDataField.dataFieldConfigId.zeroToManyExamplesHtml =
# if this field can have multiple values
# {valueType: "boolean", defaultValue: "false", regex: "^grouperDataField\\.[^.]+\\.fieldMultiValued$"}
# grouperDataField.dataFieldConfigId.fieldMultiValued =
# data type for this field
# {valueType: "string", defaultValue: "string", regex: "^grouperDataField\\.[^.]+\\.fieldDataType$", formElement: "dropdown", optionValues: ["string", "integer", "timestamp", "boolean"]}
# grouperDataField.dataFieldConfigId.fieldDataType =
# data structure for this field
# {valueType: "string", defaultValue: "attribute", regex: "^grouperDataField\\.[^.]+\\.fieldDataStructure$", formElement: "dropdown", optionValues: ["attribute", "rowColumn"]}
# grouperDataField.dataFieldConfigId.fieldDataStructure =
# use of this field. If it is access related then it will be available in an abac script
# {valueType: "string", defaultValue: "access", regex: "^grouperDataField\\.[^.]+\\.fieldDataUse$", formElement: "dropdown", optionValues: ["access", "identifier", "informational"]}
# grouperDataField.dataFieldConfigId.fieldDataUse =
# if this field is calculated from multiple providers. If it is calculated from one provider, it can be configured in that provider
# {valueType: "boolean", defaultValue: "false", regex: "^grouperDataField\\.[^.]+\\.fieldDataCalculated$"}
# grouperDataField.dataFieldConfigId.fieldDataCalculated =
# script to build this data field value from multiple providers
# {valueType: "string", defaultValue: "false", regex: "^grouperDataField\\.[^.]+\\.fieldDataCalculatedScript$", formElement: "textarea"}
# grouperDataField.dataFieldConfigId.fieldDataCalculatedScript =
# if this informational data field is dynamic based on privacy levels
# {valueType: "boolean", defaultValue: "false", regex: "^grouperDataField\\.[^.]+\\.fieldDataInformationalDynamicPrivacyLevel$", showEl: "${fieldDataUse == 'informational'}"}
# grouperDataField.dataFieldConfigId.fieldDataInformationalDynamicPrivacyLevel =
# Config ids in order to see if the user can see them,
# {valueType: "string", regex: "^grouperDataField\\.[^.]+\\.fieldDataInformationalDynamicPrivacyLevelConfigIds$", showEl: "${fieldDataInformationalDynamicPrivacyLevel}"}
# grouperDataField.dataFieldConfigId.fieldDataInformationalDynamicPrivacyLevelConfigIds =
# does this identifier require the data field name or is the identifier unique across all identifiers
# {valueType: "boolean", regex: "^grouperDataField\\.[^.]+\\.fieldDataIdentifierRequiresName$", showEl: "${fieldDataUse == 'identifier'}"}
# grouperDataField.dataFieldConfigId.fieldDataIdentifierRequiresName =
# field source. Could be sourced from a data provider. Could be sourced from a group membership.
# {valueType: "string", defaultValue: "provider", regex: "^grouperDataField\\.[^.]+\\.fieldDataSource$", formElement: "dropdown", optionValues: ["provider", "group"], showEl: "${fieldDataUse == 'access'}"}
# grouperDataField.dataFieldConfigId.fieldDataSource =
# group name of source of this data field
# {valueType: "string", defaultValue: "attribute", regex: "^grouperDataField\\.[^.]+\\.fieldDataGroupName$", showEl: "${fieldDataSource == 'group'}"}
# grouperDataField.dataFieldConfigId.fieldDataGroupName =
# should this field be stored in PIT. All identifiers will be in PIT.
# {valueType: "boolean", regex: "^grouperDataField\\.[^.]+\\.fieldDataStorePit$", showEl: "${fieldDataUse == 'access' || fieldDataUse == 'informational' }"}
# grouperDataField.dataFieldConfigId.fieldDataStorePit =
# how many days to store PIT.
# {valueType: "integer", defaultValue: "730", regex: "^grouperDataField\\.[^.]+\\.fieldDataStorePitDays$", showEl: "${fieldDataStorePit}"}
# grouperDataField.dataFieldConfigId.fieldDataStorePitDays =
# Is this assignable to groups or individuals.
# {valueType: "string", regex: "^grouperDataField\\.[^.]+\\.fieldDataAssignableTo$", formElement: "dropdown", optionValues: ["global", "groups", "individuals"]}
# grouperDataField.dataFieldConfigId.fieldDataAssignableTo =
# Are the values for this data fields a list of values with less than 100ish options? Used for validation of ABAC scripts
# {valueType: "boolean", defaultValue: "false", regex: "^grouperDataField\\.[^.]+\\.fieldDataLov$"}
# grouperDataField.dataFieldConfigId.fieldDataLov =
# Should the list of value be existing assigned values? This is the easiest way to configure, but every value must be assigned at least once
# {valueType: "boolean", defaultValue: "false", regex: "^grouperDataField\\.[^.]+\\.fieldDataLovExistingValues$", showEl: "${fieldDataLov}"}
# grouperDataField.dataFieldConfigId.fieldDataLovExistingValues =
# Database external system config ID for list of values
# {valueType: "string", required: true, regex: "^grouperDataField\\.[^.]+\\.fieldDataLovDatabaseConfigId$", showEl: "${fieldDataLov && !fieldDataLovExistingValues}"}
# grouperDataField.dataFieldConfigId.fieldDataLovDatabaseConfigId =
# Database query for list of values should have one column and the data type (string, int, etc) will be converted to the data field type.
# {valueType: "string", required: true, regex: "^grouperDataField\\.[^.]+\\.fieldDataLovDatabaseConfigId$", showEl: "${fieldDataLov && !fieldDataLovExistingValues}"}
# grouperDataField.dataFieldConfigId.fieldDataLovDatabaseQuery =
# How long to cache list of values. Note: if a new value is used which is not known, the cache will refresh to be sure. So 1440 (one day) should be fine.
# {valueType: "integer", defaultValue: "1440", regex: "^grouperDataField\\.[^.]+\\.fieldDataLovDatabaseConfigId$", showEl: "${fieldDataLov && !fieldDataLovExistingValues}"}
# grouperDataField.dataFieldConfigId.fieldDataLovCacheforMinutes =
###########################################################################
## grouper data rows
###########################################################################
# aliases that this row is referred to as
# {valueType: "string", order: 1000, subSection: "dataRowConfig", required: true, multiple: true, regex: "^grouperDataRow\\.[^.]+\\.rowAliases$"}
# grouperDataRow.dataRowConfigId.rowAliases =
# privacy realm for people who can see or use this data row
# {valueType: "string", order: 2000, subSection: "dataRowConfig", required: true, regex: "^grouperDataRow\\.[^.]+\\.rowPrivacyRealm$", formElement: "dropdown", optionValuesFromClass: "edu.internet2.middleware.grouper.dataField.GrouperPrivacyRealm"}
# grouperDataRow.dataRowConfigId.rowPrivacyRealm =
# Description html
# {valueType: "string", required: true, regex: "^dataRowConfigId\\.[^.]+\\.descriptionHtml$", formElement: "textarea"}
# grouperDataRow.dataRowConfigId.descriptionHtml =
# Data owner html
# {valueType: "string", regex: "^dataRowConfigId\\.[^.]+\\.dataOwnerHtml$", formElement: "textarea"}
# grouperDataRow.dataRowConfigId.dataOwnerHtml =
# How to get access html
# {valueType: "string", regex: "^dataRowConfigId\\.[^.]+\\.howToGetAccessHtml$", formElement: "textarea"}
# grouperDataRow.dataRowConfigId.howToGetAccessHtml =
# Zero to many examples html
# {valueType: "string", regex: "^dataRowConfigId\\.[^.]+\\.zeroToManyExamplesHtml$", formElement: "textarea"}
# grouperDataRow.dataRowConfigId.zeroToManyExamplesHtml =
# number of fields in this row
# {valueType: "string", order: 3000, subSection: "dataRowConfig", required: true, regex: "^grouperDataRow\\.[^.]+\\.rowNumberOfDataFields$", formElement: "dropdown", optionValues: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30"]}
# grouperDataRow.dataRowConfigId.rowNumberOfDataFields =
# data field for this column
# {valueType: "string", required: true, order: 4000, showEl: "${rowNumberOfDataFields > $i$}", repeatGroup: "rowDataField", repeatCount: 30, formElement: "dropdown", optionValuesFromClass: "edu.internet2.middleware.grouper.dataField.GrouperDataField"}
# grouperDataRow.dataRowConfigId.rowDataField.$i$.colDataFieldConfigId =
# if this data field is the key or part of a composite key that uniquely matches this row from source and grouper
# {valueType: "boolean", order: 4010, defaultValue: "false", showEl: "${rowNumberOfDataFields > $i$}", repeatGroup: "rowDataField", repeatCount: 30}
# grouperDataRow.dataRowConfigId.rowDataField.$i$.rowKeyField =
###########################################################################
## grouper data providers
###########################################################################
# data provider name, not really needed or used, but there to setup the provider
# {valueType: "string", required: true, multiple: true, regex: "^grouperDataProvider\\.[^.]+\\.name$"}
# grouperDataProvider.dataProviderConfigId.name =
###########################################################################
## grouper data provider change log query
###########################################################################
# data provider config id
# {valueType: "string", order: 1000, subSection: "dataProviderChangeLogQueryConfig", required: true, regex: "^grouperDataProviderChangeLogQuery\\.[^.]+\\.providerConfigId$", formElement: "dropdown", optionValuesFromClass: "edu.internet2.middleware.grouper.dataField.GrouperDataProvider"}
# grouperDataProviderChangeLogQuery.dataProviderChangeLogQueryConfigId.providerConfigId =
# data provider change log query type
# {valueType: "string", order: 2000, subSection: "dataProviderChangeLogQueryConfig", required: true, regex: "^grouperDataProviderChangeLogQuery\\.[^.]+\\.providerChangeLogQueryType$", formElement: "dropdown", optionValues: ["sql"]}
# grouperDataProviderChangeLogQuery.dataProviderChangeLogQueryConfigId.providerChangeLogQueryType =
# SQL config id
# {valueType: "string", order: 3000, subSection: "dataProviderChangeLogQueryConfig", required: true, formElement: "dropdown", optionValuesFromClass: "edu.internet2.middleware.grouper.app.loader.db.DatabaseGrouperExternalSystem", regex: "^grouperDataProviderChangeLogQuery\\.[^.]+\\.providerChangeLogQuerySqlConfigId$", showEl: "${providerChangeLogQueryType == 'sql'}"}
# grouperDataProviderChangeLogQuery.dataProviderChangeLogQueryConfigId.providerChangeLogQuerySqlConfigId =
# SQL change log query
# {valueType: "string", order: 4000, subSection: "dataProviderChangeLogQueryConfig", required: true, regex: "^grouperDataProviderChangeLogQuery\\.[^.]+\\.providerChangeLogQuerySqlQuery$", showEl: "${providerChangeLogQueryType == 'sql'}"}
# grouperDataProviderChangeLogQuery.dataProviderChangeLogQueryConfigId.providerChangeLogQuerySqlQuery =
# Change log attribute that is the primary key
# {valueType: "string", order: 5000, subSection: "dataProviderChangeLogQueryConfig", required: true, regex: "^grouperDataProviderChangeLogQuery\\.[^.]+\\.providerChangeLogQueryPrimaryKeyAttribute$"}
# grouperDataProviderChangeLogQuery.dataProviderChangeLogQueryConfigId.providerChangeLogQueryPrimaryKeyAttribute =
# Change log attribute that contains the timestamp for when this row was added, e.g. a timestamp or number field (number of millis since 1970). Should be indexed where possible.
# {valueType: "string", order: 6000, subSection: "dataProviderChangeLogQueryConfig", required: true, regex: "^grouperDataProviderChangeLogQuery\\.[^.]+\\.providerChangeLogQueryTimestampAttribute$"}
# grouperDataProviderChangeLogQuery.dataProviderChangeLogQueryConfigId.providerChangeLogQueryTimestampAttribute =
# Change log attribute which links this data to subjects
# {valueType: "string", order: 7000, subSection: "dataProviderChangeLogQueryConfig", required: true, regex: "^grouperDataProviderChangeLogQuery\\.[^.]+\\.providerChangeLogQuerySubjectIdAttribute$"}
# grouperDataProviderChangeLogQuery.dataProviderChangeLogQueryConfigId.providerChangeLogQuerySubjectIdAttribute =
# Which type of subject id
# {valueType: "string", order: 8000, subSection: "dataProviderChangeLogQueryConfig", regex: "^grouperDataProviderChangeLogQuery\\.[^.]+\\.providerChangeLogQuerySubjectIdType$", formElement: "dropdown", optionValues: ["subjectId", "subjectIdentifier"]}
# grouperDataProviderChangeLogQuery.dataProviderChangeLogQueryConfigId.providerChangeLogQuerySubjectIdType =
# which subject source this is a subject id for
# {valueType: "string", order: 9000, subSection: "dataProviderChangeLogQueryConfig", regex: "^grouperDataProviderChangeLogQuery\\.[^.]+\\.providerChangeLogQuerySubjectSourceId$"}
# grouperDataProviderChangeLogQuery.dataProviderChangeLogQueryConfigId.providerChangeLogQuerySubjectSourceId =
###########################################################################
## grouper data provider query
###########################################################################
# data provider config id
# {valueType: "string", order: 1000, subSection: "dataProviderQueryConfig", required: true, regex: "^grouperDataProviderQuery\\.[^.]+\\.providerConfigId$", formElement: "dropdown", optionValuesFromClass: "edu.internet2.middleware.grouper.dataField.GrouperDataProvider"}
# grouperDataProviderQuery.dataProviderQueryConfigId.providerConfigId =
# data provider query type
# {valueType: "string", order: 2000, subSection: "dataProviderQueryConfig", required: true, regex: "^grouperDataProviderQuery\\.[^.]+\\.providerQueryType$", formElement: "dropdown", optionValues: ["sql", "ldap"]}
# grouperDataProviderQuery.dataProviderQueryConfigId.providerQueryType =
# SQL config id
# {valueType: "string", order: 3000, subSection: "dataProviderQueryConfig", required: true, formElement: "dropdown", optionValuesFromClass: "edu.internet2.middleware.grouper.app.loader.db.DatabaseGrouperExternalSystem", regex: "^grouperDataProviderQuery\\.[^.]+\\.providerQuerySqlConfigId$", showEl: "${providerQueryType == 'sql'}"}
# grouperDataProviderQuery.dataProviderQueryConfigId.providerQuerySqlConfigId =
# LDAP config id
# {valueType: "string", order: 3500, subSection: "dataProviderQueryConfig", required: true, formElement: "dropdown", optionValuesFromClass: "edu.internet2.middleware.grouper.app.externalSystem.LdapGrouperExternalSystem", regex: "^grouperDataProviderQuery\\.[^.]+\\.providerQueryLdapConfigId$", showEl: "${providerQueryType == 'ldap'}"}
# grouperDataProviderQuery.dataProviderQueryConfigId.providerQueryLdapConfigId =
# SQL query
# {valueType: "string", order: 4000, subSection: "dataProviderQueryConfig", required: true, regex: "^grouperDataProviderQuery\\.[^.]+\\.providerQuerySqlQuery$", showEl: "${providerQueryType == 'sql'}"}
# grouperDataProviderQuery.dataProviderQueryConfigId.providerQuerySqlQuery =
# LDAP base dn
# {valueType: "string", order: 4100, subSection: "dataProviderQueryConfig", required: true, regex: "^grouperDataProviderQuery\\.[^.]+\\.providerQueryLdapBaseDn$", showEl: "${providerQueryType == 'ldap'}"}
# grouperDataProviderQuery.dataProviderQueryConfigId.providerQueryLdapBaseDn =
# LDAP search scope
# {valueType: "string", order: 4200, subSection: "dataProviderQueryConfig", required: true, regex: "^grouperDataProviderQuery\\.[^.]+\\.providerQueryLdapSearchScope$", showEl: "${providerQueryType == 'ldap'}", formElement: "dropdown", optionValues: ['ONELEVEL_SCOPE', ' SUBTREE_SCOPE']}
# grouperDataProviderQuery.dataProviderQueryConfigId.providerQueryLdapSearchScope =
# LDAP filter
# {valueType: "string", order: 4300, subSection: "dataProviderQueryConfig", required: true, regex: "^grouperDataProviderQuery\\.[^.]+\\.providerQueryLdapFilter$", showEl: "${providerQueryType == 'ldap'}"}
# grouperDataProviderQuery.dataProviderQueryConfigId.providerQueryLdapFilter =
# Data structure
# {valueType: "string", order: 5000, subSection: "dataProviderQueryConfig", required: true, regex: "^grouperDataProviderQuery\\.[^.]+\\.providerQueryDataStructure$", formElement: "dropdown", optionValues: ["attribute", "row"], showEl: "${providerQueryType == 'sql'}"}
# grouperDataProviderQuery.dataProviderQueryConfigId.providerQueryDataStructure =
# Data row to link to
# {valueType: "string", order: 6000, subSection: "dataProviderQueryConfig", required: true, regex: "^grouperDataProviderQuery\\.[^.]+\\.providerQueryRowConfigId$", formElement: "dropdown", optionValuesFromClass: "edu.internet2.middleware.grouper.dataField.GrouperDataRow", showEl: "${providerQueryDataStructure == 'row'}"}
# grouperDataProviderQuery.dataProviderQueryConfigId.providerQueryRowConfigId =
# Attribute which links this data to subjects
# {valueType: "string", order: 7000, subSection: "dataProviderQueryConfig", required: true, regex: "^grouperDataProviderQuery\\.[^.]+\\.providerQuerySubjectIdAttribute$"}
# grouperDataProviderQuery.dataProviderQueryConfigId.providerQuerySubjectIdAttribute =
# Which type of subject id
# {valueType: "string", order: 8000, subSection: "dataProviderQueryConfig", regex: "^grouperDataProviderQuery\\.[^.]+\\.providerQuerySubjectIdType$", formElement: "dropdown", optionValues: ["subjectId", "subjectIdentifier"]}
# grouperDataProviderQuery.dataProviderQueryConfigId.providerQuerySubjectIdType =
# which subject source this is a subject id for
# {valueType: "string", order: 9000, subSection: "dataProviderQueryConfig", regex: "^grouperDataProviderQuery\\.[^.]+\\.providerQuerySubjectSourceId$"}
# grouperDataProviderQuery.dataProviderQueryConfigId.providerQuerySubjectSourceId =
# number of fields in this row
# {valueType: "string", order: 10000, subSection: "dataProviderQueryConfig", required: true, regex: "^dataProviderQueryConfigId\\.[^.]+\\.rowNumberOfDataFields$", formElement: "dropdown", optionValues: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30"]}
# grouperDataProviderQuery.dataProviderQueryConfigId.providerQueryNumberOfDataFields =
# data field for this column
# {valueType: "string", order: 11000, showEl: "${providerQueryNumberOfDataFields > $i$}", repeatGroup: "providerQueryDataField", repeatCount: 30, required: true, regex: "^dataProviderQueryConfigId\\.[^.]+\\.providerQueryDataField\\.[0-9]+\\.providerDataFieldConfigId$", formElement: "dropdown", optionValuesFromClass: "edu.internet2.middleware.grouper.dataField.GrouperDataField"}
# grouperDataProviderQuery.dataProviderQueryConfigId.providerQueryDataField.$i$.providerDataFieldConfigId =
# mapping type for this data field, e.g. could be translation eventually
# {valueType: "string", order: 12000, showEl: "${providerQueryNumberOfDataFields > $i$}", repeatGroup: "providerQueryDataField", repeatCount: 30, required: true, regex: "^dataProviderQueryConfigId\\.[^.]+\\.providerQueryDataField\\.[0-9]+\\.providerDataFieldMappingType$", formElement: "dropdown", optionValues: ["attribute"]}
# grouperDataProviderQuery.dataProviderQueryConfigId.providerQueryDataField.$i$.providerDataFieldMappingType =
# mapping type for this data field
# {valueType: "string", order: 13000, showEl: "${providerQueryNumberOfDataFields > $i$}", repeatGroup: "providerQueryDataField", repeatCount: 30, required: true, regex: "^dataProviderQueryConfigId\\.[^.]+\\.providerQueryDataField\\.[0-9]+\\.providerDataFieldAttribute$", showEl: "${providerQueryDataField.$i$.providerDataFieldMappingType == 'attribute'}"}
# grouperDataProviderQuery.dataProviderQueryConfigId.providerQueryDataField.$i$.providerDataFieldAttribute =
###########################################################################
## JEXL script testing
###########################################################################
# Users have to be sysadmins and member of this group to be able to run JEXL script tests
# {valueType: "group"}
jexlScriptTestingGroup = $$grouper.rootStemForBuiltinObjects$$:jexlScriptTestingGroup
# In order to have institution specific JEXL test example for an existing script type
# {valueType: "string"}
# jexlScriptTest.institutionExample.. =
###########################################################################
## Box mock testing properties
###########################################################################
# box mock config id
# {valueType: "string"}
# grouperTest.box.mock.configId =
# box mock public key
# {valueType: "string"}
# grouperTest.box.mock.publicKey =
# box mock private key
# {valueType: "string"}
# grouperTest.box.mock.privateKey =
# box mock public key id
# {valueType: "string"}
# grouperTest.box.mock.publicKeyId =
###########################################################################
## Json serializing deserializing settings
###########################################################################
# use json lib when legacy is set to true. False means use jackson. Jackson is much faster.
# {valueType: "boolean"}
grouper.json.serialize.deserialize.useLegacy = false
# the legacy serialization would not throw an error if an invalid property is sent (when marhsaled to bean). if there is an
# exception with the new way, log it once an hour and use the legacy
# {valueType: "boolean"}
grouper.json.serialize.deserialize.useLegacyOnError = true
# dont fill up logs, only log after this many millis, 1000*60*60
# {valueType: "integer"}
grouper.json.serialize.deserialize.parseErrorLogEveryMillis = 3600000
###########################################################################
## HTTP client settings
###########################################################################
# default pool size for an HTTP client. i.e. this is the max number of connections outbound at once per container instance
# {valueType: "integer", defaultValue: "100"}
httpClientMaxTotalPoolSize =
# default number of connections at once for an endpoint from a container
# {valueType: "integer", defaultValue: "30"}
httpClientDefaultMaxPerRoute =
# if HTTP client instances should be re-used
# {valueType: "boolean", defaultValue: "true"}
httpClientReuse =