UGC 4

Webapp

As a separate web application, the UGC Webapp handles the task to persist user input.

Starting the UGC Webapp

You can start the ugc by executing ugc.jar either directly or by calling java -jar ugc.jar which is an executable. Additionally, it provides a web interface to view the user data and export it. JVMARGS can be provided either as JAVA_OPTS in an ugc.conf file next to the ugc.jar or as part of the command when using java -jar ugc.jar. The content of an ugc.conf file might be:

JAVA_OPTS='-Xmx1g -Dlogging.config=/cms/ugc/config/logback.xml -Dspring.config.location=/cms/ugc/config/application.yml'

Starting ugc with java would look like this for the same properties:

java -Xmx1g -Dlogging.config=/cms/ugc/config/logback.xml -Dspring.config.location=/cms/ugc/config/application.yml -jar ugc.jar

Configuration

The configuration of the webapp is done with a file called application.yml. It's written in the commonly used YAML format. In this example all values are the default values.

# jvm arguments as a single string
vmargs : "-Xmx1g"

# all configuration parameters regarding the connection to the sophora server
sophora-server :

  # the user the ugc webapp should use to login into sophora
  username : null

  # password for this user
  password : null

  # address of the sophora server (i.e. "http://localhost:1196")
  host : null

  # if you want to use a proxy, the hostname or ip address of the proxy
  proxyHost : null

  # the name of the proxy user
  proxyUser : null

  # the password of the proxy user
  proxyPassword : null

  # port of the proxy server
  proxyPort : 0

  # number of connection retries
  connectRetries : 3

  # time between connection retries
  connectRetryInterval : 10

  # directory of the slaves.xml that holds the information on the sophora cluster
  slavesInfoDir : ""

# configuration of the database connection
database :

  # url of the jdbc connection, the last part is the name of the datadase (i.e. "jdbc:mysql://localhost:3306/usercontent")
  url : null

  # username for database
  user : null

  # password for database
  password : null

  # enable jpa caching
  jpaCache : false

# configuration of caching
caching :

  # url of the cache servlet
  cacheServerletUrl : null

  # path to cache servlet without url and context path
  cacheServletPostfix : null

  # the delivery group for the flush action
  cacheServletGroup : null

  # password for the cache servlet
  cacheServletPassword : null

  # delay invalidation tasks by X seconds
  invalidationRequestDelay : 30

# configuration for sending e-mails
# since 4.0.2
email :

  # configuration of the smtp server
  transport :

    # hostname/address
    host : "localhost"

    # port
    port : 25

    # user for smtp
    # if the user and password properties are null, no authentication is attempted.
    user : null

    # password
    # if the user and password properties are null, no authentication is attempted.
    password : null

    # use starttls
    starttls : true

    # additional JavaMail Session properties
    properties: {}

# configuration of the double opt in mechanism
double-opt-in :

  # configuration of the template message for the e-mail
  template :

    # from field
    from : null

    # subject field
    subject : "Please verify your email address"

    # reply to field
    replyTo : null

    # cc field
    cc : null

    # bcc field
    bcc : null

  # configuration of the smtp server
  # Deprecated since 4.0.2, please use email.transport instead
#  transport :
#    host : "localhost"
#    port : 25
#    user  : null
#    password : null
#    starttls : true

# configuration of the confirmation via e-mail
# since 4.0.2
confirmation :

  # configuration of the template message for the e-mail
  template :

    # from field
    from : null

    # subject field
    subject : null

    # reply to field
    replyTo : null

    # cc field
    cc : null

    # bcc field
    bcc : null

# configuration of comments
comment :

  # list of all content types as string that should support this feature
  primaryTypes : [ ]

  # how many comments should be allowed per ip address in 10 seconds?
  limitPerTenSeconds : 1

  # how many comments should be allowed per ip address in a minute?
  limitPerMinute : 2

  # how many comments should be allowed per ip address in a day?
  limitPerDay : 100

  # is the multiuser feature enabled?
  multiUserEnabled : "true"

  # the image variant of the image of an editor
  avatarVariant : "small"

  # the primaryType of the editor
  editorNodetype : "sophora-ugc-nt:ugcEditor"

  # the property name of the avatar image of the editor
  editorAvatarProperty : "sophora-ugc:avatar"

  # the property name of the name of the editor
  editorNameProperty : "sophora-ugc:name"

  # the maximal allowed size for the headline. Values between 0 and 65135 are permitted.
  headlineSize : 255

  # the maximal allowed size for the content.Values between 0 and 65135 are permitted.
  contentSize : 1000

  # additional space in the field content to edit.Values between 0 and 400 are permitted.
  editTolerance : 0

# configuration of the spam list that is used for comments
spam-list :

  # the multi string property of the spam list document with the spam words in it
  spamWordsProperty : "sophora-ugc:spamWords"

  # primary type of the spam list document
  primaryType : "sophora-ugc-nt:spamList"

  # external ID of the spam list document
  externalId : "49bc5b8c-f37e-45a4-9cc3-c16b38f3b569"

# configuration of form submissions
form :

  # the form field that should be treated as e-mail field
  formFieldName_Email : "email"

  # the boolean property that defines if double opt in is active
  doubleOptInProperty : "sophora-ugc:useDoubleOptIn"

  # the string property that is used for the body of the double opt in message
  optInEmailTextProperty : "sophora-ugc:emailText"

  # the string property for the subject of the double opt in message
  optInEmailSubjectProperty : "sophora-ugc:emailSubject"

  # the boolean property that defines if confirmation via e-mail is active
  confirmationEmailProperty : "sophora-ugc:enableConfirmationEmail"

  # the string property that is used for the body of the confirmation message
  confirmationEmailTextProperty : "sophora-ugc:confirmationEmailText"

  # the string property for the subject of the confirmation message
  confirmationEmailSubjectProperty : "sophora-ugc:confirmationEmailSubject"

  # the child node of the form fields
  formFieldsChildnode : "sophora-ugc:formFields"

  # the string property of the field name
  fieldNameProperty : "sophora-extension:formfieldname"

  # the string property of the field style (E-Mail, Text)
  fieldStyleProperty : "sophora-extension:fieldstyle"

  # the string property of the label
  labelProperty : "sophora-extension:question"

  # the boolean property that says if the field is required
  requiredProperty : "sophora-extension:formrequired"

  # string property for the headline of the form
  headlineProperty : "sophora-ugc:title"

  # the node type of the form
  primaryType : "sophora-ugc-nt:form"

  # prefer the form wizard property to the childnode to get the form fields
  useFormWizard : true

  # string property for the form wizard data
  formWizardProperty : "sophora-ugc:formWizard"

  # list of field types that should not appear in the backend
  blacklistedFieldTypes : ["submit","button","reset"]

# the regular expression and the associated validation error message for the search
form-search:
  formDataSearchRegex: ".+"
  validationErrorMsg: "Ungültige Eingabe"
  # the search results are cached. The maximum number of results in the cache is configured here. If the cache is full and a different search request is made, the result that has not been used the longest is replaced.
  numberOfResultsCached: 14
  # every 15 minutes, all cache entries are deleted that were not used for the time (ms) defined here
  removeAfter: 7200000 # 2h

# configuration of image uploads
image-upload :

  # list of all content types as string that should support this feature
  primaryTypes : [ ]

  # how many image uploads should be allowed per ip address in 10 seconds?
  limitPerTenSeconds : 1

  # how many image uploads should be allowed per ip address in a minute?
  limitPerMinute : 2

  # how many image uploads should be allowed per ip address in a day?
  limitPerDay : 100

  # the proposal section where newly imported images are listed
  proposalSection : "User-Bilder"

  # node type of images that should be imported into sophora
  imageNodeType : "sophora-extension-nt:image"

# configuration of ratings
rating :

  # list of all content types as string that should support this feature
  primaryTypes : [ ]

  # how many ratings should be allowed per ip address in 10 seconds?
  limitPerTenSeconds : 1

  # how many ratings should be allowed per ip address in a minute?
  limitPerMinute : 2

  # how many ratings should be allowed per ip address in a day?
  limitPerDay : 100

  # configuration of quizzes
  quiz :

  # the form field that should be treated as e-mail field
  formFieldName_Email : "email"

  # the string property of the answer text
  answerTextProperty : "sophora-ugc:text"

  # the string property of the answer uuid
  answerUuidProperty : "sophora-ugc:uuid"

  # the long property with the points for an answer
  answerPointsProperty : "sophora-ugc:points"

  # the string property with the description of an answer
  answerCommentProperty : "sophora-ugc:description"

  # the boolean property that determines if an answer is correct
  answerIsCorrectProperty : "sophora-ugc:isCorrect"

  # the string property with the text of a question
  questionTextProperty : "sophora-ugc:text"

  # the child node with the answers for a question
  questionAnswersChildnode : "sophora-ugc:answers"

  # string property for the headline of the quiz
  headlineProperty : "sophora-ugc:title"

  # the child node of the quiz questions
  questionsChildnode : "sophora-ugc:questions"

  # the reference property of the form
  formProperty : "sophora-ugc:form"

  # primary type of quizzes
  primaryType : "sophora-ugc-nt:quiz"

# configuration of votings
voting :

  # form field that should be treated as e-mail field
  formFieldName_Email : "email"

  # string property for the headline of the voting
  headlineProperty : "sophora-ugc:title"

  # reference property of the form
  formProperty : "sophora-ugc:form"

  # primary type of votings
  primaryType : "sophora-ugc-nt:voting"

  # date property with the date until which is property is valid
  votingToProperty : "sophora-ugc:validTo"

  # long property with the number of votes that are allowed
  numberOfVotesProperty : "sophora-ugc:numberOfVotes"

  # child node of the voting items
  itemsChildnode : "sophora-ugc:votingItems"

  # string property with the text of a property
  itemTextProperty : "sophora-ugc:text"

  # string property with voting item uuid
  itemUuidProperty : "sophora-ugc:uuid"

  # string property with description of the voting item
  itemDescriptionProperty : "sophora-ugc:description"

  # string property of the voting that declares the voting type
  votingTypeProperty : "sophora-ugc:votingType"

  # the default voting type; possible values: "simple", "ranking"
  defaultVotingType : "simple"

  # number of days after the voting stopped being valid to wait
  # until the voting report gets persisted and the user submissions get deleted
  timeoutDelay : 30

  # interval in seconds to update the internal cache for a voting
  cacheUpdateInterval : 240

  # evict a cache entry of the internal cache after X minutes without any read access
  cacheEvictAfterMinutes : 720

  # the total maximum of voting reports in the internal cache
  cacheMaxNumberOfCachedReports : 50

# configuration of the manipulation check for forms, quizzes and votings
manipulation :

  # multi string property with manipulation criteria
  filtersProperty : "sophora-ugc:manipulationFilters"

  # long property with numbers of entries allowed per interval
  entriesAllowedProperty : "sophora-ugc:entriesAllowed"

  # long property with length of the manipulation interval
  intervalProperty : "sophora-ugc:manipulationInterval"

  # string property for the time unit of an interval
  intervalTypeProperty : "sophora-ugc:manipulationIntervalType"

# configure the usage of serial programs
serial-programs :

# (type: bySelectValue)
  idProperty : "sophora-ugc:serialProgram"

  # property with selectvalue whose content is compared with the value configured in subHierarchydocument (type: bySelectValue)
  broadcastType : "sophora-content:broadcastType"

  # to configure a hierarchy document to be not a serial program. The select value is used (type: bySelectValue)
  subHierarchydocument : "subHierarchydocument"

  # the select value document (type: bySelectValue)
  externalId : "40b38a3c-dfc0-4e3b-abf2-2bcea73d01b6"

  # title for the dropdown menu (type: byDocument)
  titleProperty : "sophora-content:title"

  # allowed nodetypes (type: byDocument). If the list is empty all nodetypes are allowed. Otherwise, only documents of the specified types can be used.
  allowedNodetypes : []

# configuration of the load monitoring
load-information :

  # how many load information entries per host should be kept in memory?
  entriesPerHost : 10000

  # how many days of no new load information until all load data is removed from memory
  daysToDeclareDead : 2

# configuration of the embedded jetty server
server :

  # http port of the jetty
  port : 9080
  # respect FORWARD headers
  # necessary when using swagger UI behind a reverse procy
  forward-headers-strategy: "FRAMEWORK"

# configuration for basic auth. Basic auth is enabled only when name and password are configured
# since 4.2.0
spring:
  security:
    user:
      # the username to authenticate
      name: user
      # the password to authenticate
      password: password

# configuration for the swagger ui
springdoc: 
  swagger-ui:
    url: "/v3/api-docs"
    # to disable the default swagger url
    disable-swagger-default-url: true 
    # enable to continue using the Swagger UI when basic authentication is enabled
    csrf:
      enabled: true

# configuration of some features in the 'Sophora User Feedback Backend'
# this configuration does not affect the functions of the REST API or Swagger UI
features :

  # configure the actions an editor can use on comments
  actions :

    # enables the option to delete all comments submitted by a particular user
    enableDeleteByUser : false

    # enables the option to overwrite the username
    enableOverwriteUsername : false

    # enables the option to overwrite the externalUserId
    enableOverwriteExternalUserId : false

    # enables the option to execute bulk operations on filter
    enableActionsByFilter: false

    # enables the option to execute the delete bulk operation on filter
    enableDeleteByFilter: false

  # configuration of the filters
  filters :

    # show/hide the filter options
    documentTypes : true
    serialPrograms : false
    editors : true
    dates : true
    status : true
    markers: false

    # there are currently two types of serial programs / categories to configure: 'byDocument' and 'bySelectValue'. Read the section 'Configure SerialProgram/Category Filter' for detailed information.
    serialProgramsType : "bySelectValue"

    # the filter name can be adjusted for the special use case of the filter.
    serialProgramsName : "Sendungsreihe"

  # toggle the feature to write notes for individual comments
  notes :
    enabled : false

  # toggle the feature to pin comments
  pinning :
    enabled : false

  # to configure the marking options, the array of objects must be populated according to the following scheme:
  #  {
  #	   key : "pr",
  #     label : "Proofreading",
  #     colorValue : "#ffff00" # color specification (in an by css accepted way)
  #  }
  #
  markers : []

  comment-templates :
    # toggle the feature to use templates when commenting as an editor
    enabled : false

    # the node type used for the comment templates
    templateNodeType : "sophora-ugc-nt:commentTemplate"

    # the structure node under which new created templates are to be located
    # If the template feature is enabled, this property must be a valid structure node path
    templateStructureNodePath : null

    # the ID stem that will be used to create a new template
    templateIdStem : "kommentartemplate"

# configure if the app is the main application
isMainApp : false

# the backend for comments and image uploads has links to the preview of the documents in sophora. You can configure the preview url here. (i.e. "http://preview_host:8080/contextpath/system/preview.jsp?sophoraid=")
previewUrl : null

# to get the right property of the title of document that was rated or commented,
# use the property that is most commonly used as title or headline property
simpleDocumentHeadlineProperty : "sophora-content:title"

# this property defines the time in milliseconds to wait between failed startup attempts
# Attention: this is not a configuration parameter of the sophora client
waitingTimeBetweenStartupAttempts : 10000

# the hash values of submissions are stored in the webapp
# a submission whose hash value is already known is sorted out as a duplicate
# this property specifies the maximum number of hashes stored for duplicate checking
maxNumberOfSubmissionsSaved : 500

# this property defines whether embedding the UGC webapp in an iFrame is allowed or not. By default it is not allowed.
iFramesAllowed : false

# Management Port for jolokia/jmx
management :
  server :
    port : 1694

# username and passwort for jolokia/jmx
jolokia:
  username: ""
  password: ""

# an allowed origin of the websocket, which is used to check for new content of a UGC instance. Required only when running the ugc editorial UI with a reverse proxy. 
websocket:
  allowedOrigin: "http://host:port"

The most important configuration is the option isMainApp. If you run more than one ugc webapp, only one should be configured as main app. The main app is responsible for cleanup in general and for the manipulation check of forms, quizzes and votings.

Authentication

Basic Authentication is enabled when a username and password are specified in the configuration. This is done via the spring.security.user.name and spring.security.user.password properties. If these properties are set, you must authenticate yourself to use UGC. The session ends when you close your browser. See the configuration section above for details.

Please keep in mind to provide authentication credentials via sophora.ugc.baseurl in the configuration of the Taglib and sophora.ugc.submitter.webapp.csrfTokenUrl in the configuration of the Submitter in your webapp.

Jolokia

Jolokia is started if a management port has been specified in the configuration. This is done using the property management.server.port. With management enabled Jolokia can be accessed using the path jolokia e.g. http://<hostname>:<server.port>/jolokia.

Configure the SerialProgram/Category Filter

There are two versions of the serialProgram filter. These filters are disabled by default because of the required configuration. This filter can be used to create a filter for categories other than serialPrograms. For this use the label of the selection filter can be adjusted with serialProgramsName property in the application.yml.

byDocument

This version is for an implementation in which a corresponding document exists for each serialProgram or category. This filter uses the categoryExternalId field. To use the filter this field must be filled with the corresponding externalIds of the serialProgram/category documents. The documents used by this filter can be restricted by adding nodetypes to the allowedNodetypes list. If the list is empty (default), all node types are allowed.

You can adjust the title of the filter in the ugc-webapp backend via the serialProgramsName configuration property.

# example configuration
serial-programs : 
	titleProperty : "sophora-content:title"
    allowedNodetypes : []
features : 
	filters :  
		serialPrograms : true
		serialProgramsType: "byDocument"
		serialProgramsName: "Serialprogram"

This filter allows the selection of several values. If the filter will be used via REST interface, the externalIds should be entered individually in the filter map which is included in the page request. Accepted names for the assignment match the regex "category\d*".
Example: "category5" : "categoryExternalId"

bySelectValue

This version uses the SelectValues of the document with the id entered in externalId. This filter uses the serialProgram field into which the value of a SelectValue can be entered.

serial-programs :  	
	idProperty : "sophora-ugc:serialProgram"
 	broadcastType : "sophora-content:broadcastType"
 	subHierarchydocument : "subHierarchydocument"
 	externalId : "40b38a3c-dfc0-4e3b-abf2-2bcea73d01b6" 
features : 
	filters : 
 		serialPrograms : true
 	 	serialProgramsType: "bySelectValue"

The externalId is the externalId of the SelectValue Document. The value of the select value has to be insert into the

Configure the size of the headline and content

The maximum size of the fields headline and content can be configured in the application.yml. Values between 0 and 65135 are permitted. If no size is configured, the default value for headline is 255 characters and for content 1000 characters.

In addition, there is the possibility to give the editor additional space in the content field for editing comments. The maximum size for edited comments is {contentSize + editTolerance} characters. Values between 0 (default) and 400 are allowed.

# example configuration
comment: 
    ...
    editTolerance: 400
    headlineSize: 255
    contentSize: 2000

Marking example configuration

In order to mark comments and then filter them, the configuration must be adjusted.
Example configuration with a marker option:

features: 
    filters: 
        markers: true
    markers: [{
        key: "pr",
        label: "Proofreading",
        colorValue: "#ffff00"
        }
    ]

If a used option is removed and existing comments have the key, the comments are treated as if they had no key. But it is not possible to save comments with an unconfigured key.

Configuration of allowed actions

There are three actions that are not displayed in the webapp by default due to their impact. These actions can still be executed via the rest interface.

features : 
    actions : 
        enableDeleteByUser : false
        enableOverwriteUsername: false
        enableOverwriteExternalUserId: false
        enableActionsByFilter: false
        enableDeleteByFilter: false

enableDeleteByUser

Allows editors to delete all comments of all selected users.

enableOverwriteUsername/enableOverwriteExternalUserId

If these actions are unlocked, there is an input field in the edit view for each unlocked field. The username or externalUserId can then be changed via these input fields in the webapp.

enableActionsByFilter/enableDeleteByFilter

If enableActionsByFilter is set to true it allows the user to execute bulk operations (accept and deny) on a filtered list of comments. If enableDeleteByFilter is also set to true, also the delete option is allowed.

Commenting as an Editor

To comment as an editor, the multiuser feature must be enabled (multiUserEnabled: "true").
Furthermore a valid editorNodetype (editorNodetype) must be provided. The editorNodetype must contain at least a string property for the name (editorNameProperty) and a property for the avatar (editorAvatarProperty). The avatar childnode contains a reference to an image document. For the avatar an image variant (avatarVariant) must be provided. It can be any of the image variants.
To use the feature there must be at least one published document of the editorNodetype.
The mixin sophora-ugc-mix:ugcEditor and the example nodetype sophora-ugc-nt:ugcEditor for the editorNodetype is provided with the imports.

PropertyDescription
multiUserEnabledEnable the multiUser feature (boolean)
avatarVariantName of an valid image variant
editorNodetypePrimary type of the editorNodetype
editorNamePropertyProperty name of the name property defined in the editorNodetype
editorAvatarPropertyProperty name of the avatar property defined in the editorNodetype

Forms

There are two ways to model form fields in Sophora:

  • as childnodes using the form fields input field type or a dynamic table
  • as String property using the form wizard input field type

The ugc webapp needs to be configured to understand how you decided to model forms. The configuration parameter form.formWizardProperty decides which String property is interpreted as form wizard input field. The configuration parameter form.useFormWizard tells the webapp, if this property should be used to get the form fields. If the value of the property is blank or form.useFormWizard is set to false, the ugc webapp tries to get the form fields from the childnode configured in form.formFieldsChildnode.

Voting Items and Quiz Answers

In the configuration there are two configuration parameters that have similar importance:

  • voting.itemUuidProperty
  • quiz.answerUuidProperty

These parameters define properties that represent UUIDs for the quiz answers and the voting items. This means that a property needs to be configured for each of these childnodes. The best way to achieve this is via document changing script that assures that this property is set for each childnode.

Example Script for Voting Items

class SaveVotingItemListener implements IScriptDocumentChangeListener {

   private Logger log;

	public void documentChanging(IScriptDocumentChangeEvent event) {
 		// use the primary type of your voting here
		if (event.getStateChange().equals(DocumentChangedEvent.StateChange.NONE) &amp;&amp; event.getDocument().getPrimaryType().equals("sophora-ugc-nt:voting")) {
			INode node = event.getDocument();
 			// use the name of the cildnode of the voting items here
			for(INode answer : node.getNodesByName("sophora-ugc:votingItems")) {
				// use the uuid property of the voting item childnode here
				if(!answer.hasProperty("sophora-ugc:uuid")) {
					// and here
					answer.setString("sophora-ugc:uuid",UUID.randomUUID().toString());
				}
			}
		}


	}

	public void init(IScriptContext context) {
		log = context.getLogger();
		log.info("Logging started");
	}

	public void destroy() {
		log.info("Logging stopped");
	}

}
return new SaveVotingItemListener();

Example Script for Quiz items

class SaveQuizAnswerListener implements IScriptDocumentChangeListener {

   private Logger log;

	public void documentChanging(IScriptDocumentChangeEvent event) {
		// use the primary type of your quiz here
		if (event.getStateChange().equals(DocumentChangedEvent.StateChange.NONE) &amp;&amp; event.getDocument().getPrimaryType().equals("sophora-ugc-nt:question")) {
			INode node = event.getDocument();
			// use the name of the cildnode of the quiz answers here
			for(INode answer : node.getNodesByName("sophora-ugc:answers")) {
				// use the uuid property of the answer childnode here
				if(!answer.hasProperty("sophora-ugc:uuid")) {
					// and here
					answer.setString("sophora-ugc:uuid",UUID.randomUUID().toString());
				}
			}
		}


	}

	public void init(IScriptContext context) {
		log = context.getLogger();
		log.info("Logging started");
	}

	public void destroy() {
		log.info("Logging stopped");
	}

}
return new SaveQuizAnswerListener();

Cleanup

When a document gets deleted the user generated content gets deleted as well.

Votings have a more sophisticated behaviour. On deletion, the voting report gets persisted before the user submissions get deleted. Additionally, you can set a date until which the voting is valid (voting.votingToProperty) and a delay in days (voting.timeoutDelay). The delay specifies the number of days to wait after the valid-to date to delete user submissions and persist the voting report.

Caching

When new user submissions change the comments to be displayed or might have changed the voting report or the rating evaluation, invalidation requests for the cache fragments associated with the user generated content get sent. In order to prevent many requests from damaging the performance of the web application, the invalidation requests get bundled. The administration webapp waits a configurable amount of time (caching.invalidationRequestDelay) before it sends an invalidation request. During this time all other invalidation requests for this document get ignored. In consequence, there is a certain delay before the updated results get visible in your webapp.

To achieve that all fragments on all deliveries get invalidated, Sophora's cache servlet is used. It is crucial that you configure either the URL of the cache servlet or the path to the cache servlet without URL and context path and in both cases the delivery group:
(caching.cacheServerletUrl || caching.cacheServletPostfix) && caching.cacheServletGroup.
Otherwise, this cache invalidation feature is deactivated.

Additionally, there is an internal cache for votings, which can be configured as well. This means that changes in the voting report might take a while until they get updated - even in the UI of the ugc-webapp.

Manipulation Control

Votings, Quizzes, Forms

Manipulation criteria can be configured per form, quiz or voting document. There are properties usually configured on a dedicated tab where you can configure the following:

  • criteria that make up a user. IP address (ipAddress), referrer (referrer), e-mail address (eMail) and user agent (userAgent) are the options. The criteria are connected with AND. I.e., all checked criteria have to be equal in submissions to be considered by the same user
  • length of the considered interval for manipulation check
  • interval time unit (ms/s/m/h/d)
  • number of submissions by the same user that are allowed per interval

If one of these values is not set in the form, quiz or voting document, the voting is considered to be without manipulation control.

If the manipulation control is active, new entries are checked before they are saved in the database. If entries are considered as manipulation attempts according to the criteria, they are discarded and not saved in the database.

If the form, quiz or voting document is published, and there have been changes to the manipulation criteria, all entries for that document will be checked again to determine whether or not they are considered manipulation under the new criteria. If entries are found to be manipulated, they will be flagged and will not be added to the results. Entries that are subsequently recognized as manipulation are not deleted from the database, so that accidental changes to the criteria do not lead to the loss of data for entries that are already in the database.

Comments, Image Uploads, Ratings

For these three features only the IP address is considered to identify malicious attempts. You can limit the number of submissions per:

  • ten seconds
  • minute
  • day

If the number of submissions per IP address and time interval is already exceeded, a new submission for this IP address won't be saved in the database.

Ratings have an additional limit. Only one rating submission is allowed per IP address and rateable document.

Double Opt-In

Double opt-in means that a user has to confirm his submission via e-mail. This addon supports this feature for forms, quizzes and votings. Using this feature for votings has the effect that the submission is not evaluated before the user confirmed the e-mail. For quizzes and forms, double opt-in only has the effect that the submissions are marked differently in the backend.

The double opt-in process consists of three steps:

  1. The user submits a form, quiz or voting result, including their e-mail address. This is the first opt-in.
  2. The double opt-in asks the user via e-mail to confirm his input. The e-mail contains a link with a unique ID representing the opt-in request.
  3. The user confirms the double opt-in request by clicking on the link in the e-mail. This is the second opt-in.

Usage

Double opt-in can be configured in a form document. To enable it for quizzes and votings, add a reference to a form document in your quiz or voting.

The form needs to at least contain a field for the user's e-mail address. The form document must also contain a template for the body of the e-mail. An e-mail template including subject and sender address can be configured globally (see doubleOptIn in the configuration section above for details). Optionally, you may set a custom subject and a sender e-mail address in each form document.

The body text should contain the placeholder string $opt-in-id$, which will be replaced with the actual unique ID used to identify the opt-in request. You can also use curly brackets, {opt-in-id}, to insert the value in URL encoding. Typically, this placeholder will be put at the end of a URL that denotes the link the user has to click. The generated link should point to a request handler that stores the successful opt-in request. Typically this is done using the JSP tag storeDoubleOptIn (see the Taglibrary documentation page). The ID may also be given to the user as plain text, so he can input it anywhere.

The submitted content may be referenced in the body text as $FIELDNAME$ or URL encoded as {FIELDNAME} using the (technical) name of a form field. Additional keys for replacements inside the body of the e-mail can be provided to the JSP tags storeForm, storeQuiz and storeVoting as parameter doubleOptInParams (see the Taglibrary documentation page).

Confirmation mail message

You can enable an automated reply message that users receive via e-mail once they submitted a form, voting or quiz result. The confirmation mail is sent after the data is written to the database, so that the user can use the confirmation mail as a submission receipt.

If double opt-in is enabled, the confirmation mail is sent after succesful submission of the second opt-in.

Usage

The confimation mail can be configured in a form document. To enable it for quizzes and votings, add a reference to a form document in your quiz or voting.

The form needs to at least contain a field for the user's e-mail address. The form document must also contain a template for the body of the e-mail. An e-mail template including subject and sender address can be configured globally (see confirmation in the configuration section above for details). Optionally, you may set a custom subject and a sender e-mail address in each form document.

The submitted form content may be referenced in the body text as $FIELDNAME$ using the (technical) name of a form field. You can also use curly brackets, {FIELDNAME}, to insert the values in URL encoding.

Admin UI

You can access the backend at the http port configured in the application.yml. E.g.: http://localhost:9080.

Sophora allows you to configure browser tabs by document types. These browser tabs make it possible to have an exact view on the user generated content on a per document basis.

URLs for browser tabs
TypeViewURL
CommentsList of all commentshttp://HOSTNAME:PORT/#!/comments/${sophora:externalId}?nav=false
http://HOSTNAME:PORT/#!/comments/${sophora:id}?nav=false&idType=sophoraId
Form submissionsList of participantshttp://HOSTNAME:PORT/#!/participants/forms/${sophora:externalId}/withResetPermission?nav=false
http://HOSTNAME:PORT/#!/participants/forms/${sophora:id}/withResetPermission?nav=false&idType=sophoraId
Image uploadsList of all image uploadshttp://HOSTNAME:PORT/#!/imageUploads/${sophora:externalId}?nav=false
http://HOSTNAME:PORT/#!/imageUploads/${sophora:id}?nav=false&idType=sophoraId
QuizzesList of participantshttp://HOSTNAME:PORT/#!/participants/quizzes/${sophora:externalId}/withResetPermission?nav=false
http://HOSTNAME:PORT/#!/participants/quizzes/${sophora:id}/withResetPermission?nav=false&idType=sophoraId
VotingsList of participantshttp://HOSTNAME:PORT/#!/participants/votings/${sophora:externalId}/withResetPermission?nav=false
http://HOSTNAME:PORT/#!/participants/votings/${sophora:id}/withResetPermission?nav=false&idType=sophoraId
VotingsThe voting reporthttp://HOSTNAME:PORT/#!/votingreport/${sophora:externalId}/withResetPermission?nav=false
http://HOSTNAME:PORT/#!/votingreport/${sophora:id}/withResetPermission?nav=false&idType=sophoraId

Swagger UI and OpenAPI Specification

UGC Webapp provides an interactive Swagger UI to document the REST endpoints. The REST API is specified according to the OpenAPI Specification standard. Depending on the http port configured in the application.yml, e.g. 9080, you can access them under the following URLs:

Before UGC 4.3.0
  • Swagger UI: http://localhost:9080/api-ui/
  • Swagger: http://localhost:9080/v2/api-docs
UGC 4.3.0 and later versions
  • Swagger UI: http://localhost:9080/swagger-ui.html
  • OpenAPI Specification: http://localhost:9080/v3/api-docs

Last modified on 12/30/22

The content of this page is licensed under the CC BY 4.0 License. Code samples are licensed under the MIT License.

Icon