UGC | Version 4

Webapp

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

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

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 of the double opt in mechanism
  double-opt-in :

    # 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

    # 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 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 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

    # for legacy rating: Keep ratings in an internal cache for X seconds
    cachetimeInSec : 240

  # 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

  # 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: ""

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.

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. For votings usage of this feature has the effect that the submission is not evaluated before the user confirmed the e-mail. For quizzes and forms this 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.

Each form/quiz/voting document must contain a template for the body of the e-mail. Subject and sender address are configured globally (see doubleOptIn in the configuration section above for details). Optionally, you may set a custom subject and a sender e-mail address for each form/quiz/voting 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. Typically this placeholder will be put at the end of a URL that denotes the link the user has to click. But the ID can also be given to the user as text, so he can input it anywhere. The submitted content may also be referenced in the body text in the form of $FIELDNAME$. Additionally to the opt-in-id and the field names also keys provided to the JSP tags storeForm, storeQuiz and storeVoting can be used for replacement inside the body of the e-mail.
Instead of surrounding $ the key can also be used with curled brackets like for example {opt-in-id}. In that case the value of the key will be URL encoded.
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.

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 and Swagger UI

UGC-webapp supports Swagger and Swagger UI. Depending on the http port configured in the application.yml, e.g. 9080, you can access them under the following URLs:

  • Swagger: http://localhost:9080/rest/v2/api-docs
  • Swagger UI: http://localhost:9080/api-ui

Authentication

If you want to use some sort of authentication within the ugc-webapp backend you have to configure a webserver (e.g. Apache or Nginx) to authenticate the user and forward the request to the backend. If you use the backend in browser tabs in the deskclient you have to take care that the server adds no-cache headers. The username and password can be configured in the tab document.

In the examples below ugc_webapp is the hostname of the ugc backend.

Apache

The basic authentication with an .htpasswd file is done like the following:

<VirtualHost *:80>

    ServerName [servername for the ugc webapp]

    ProxyRequests Off
    ProxyVia On

    <Location / >
                  Options Includes ExecCGI FollowSymLinks

                  AuthType Basic
                  AuthName "Password Required"
                  AuthUserFile /htpasswd
                  Require user [required user]
    </Location>

    <IfModule mod_headers.c>
        Header set Cache-Control "private, no-cache, no-store, proxy-revalidate, no-transform"
        Header set Pragma "no-cache"
    </IfModule>

    ProxyPass / http://ugc_webapp:8080/
    ProxyPassReverse / http://ugc_webapp:8080/

</VirtualHost>

Nginx

server {
	listen 80;

	location / {
		add_header Cache-Control "private, no-cache, no-store, proxy-revalidate, no-transform";
		add_header Pragma "no-cache";
		auth_basic "Protected";
		auth_basic_user_file "/.htpasswd";
		proxy_pass http://ugc_webapp:8080;
	}
}

Last modified on 10/16/20

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

Icon