Use Case

To install the following use cases, please:

  • Create the page and tt-content records.
  • Copy the JSON form code to a new empty form (open Form in JSON mode).

Self Registration

Concept:

  • The T3 FE User record will be created on the fly in the last step, when the user set’s the password.
  • Form Registration
    • Input: last name, first name, email.
    • Create record in table Person, if no name or email sibling is found. Else give a hint to do a password reset.
    • Set a new Person.auth token.
    • Set Person.authExpired = NOW() + INTERVAL 1 DAY.
    • Send an email to the given email address with a password reset link (incl. the token) which is time limited.
    • Further steps: See Set password.
  • Form Request password reset link
    • This is optional, but useful to offer the opportunity to reset the own password.
    • Input: email address.
    • Send an email to the given email address with a password reset link (incl. a token) which is time limited.
      • Only send email if the email address is known!
      • If email is not found, the user should not be noticed. This prohibits misusing the form to validate email adresses.
      • Set a new Person.auth token.
      • Set Person.authExpired = NOW() + INTERVAL 1 DAY.
  • Form Set password
    • The user types in the new password.
    • On save:
      • If the FE account does not exist, it will be created.
      • Set the FE user password.
      • Clear Person.authExpired.

Table: Person

CREATE TABLE `Person` (
  `id` int(11) UNSIGNED NOT NULL,
  `lastName` varchar(64) NOT NULL DEFAULT '',
  `firstName` varchar(64) NOT NULL DEFAULT '',
  `email` varchar(128) NOT NULL,
  `account` varchar(128) NOT NULL,
  `auth`  varchar(32) NOT NULL,
  `authExpire` datetime NOT NULL,
) ENGINE=InnoDB DEFAULT CHARSET=utf8 PACK_KEYS=1;

Registration

Page: Registration

  • Page Alias: registration

QFQ content record:

#
# {{action:SE}}: thanksRegistration
#


form={{SELECT IF('{{action:SE}}' = '','registration','') }}

20.sql = SELECT "<p>Thank you for your registration.</p><p>An email with further instructions has been sent to you.</p>"
                , "<p>You should receive the mail during the next 5 minutes. If not, please check your SPAM folder.</p>"

            FROM (SELECT '') AS fake
            WHERE '{{action:SE}}' = 'thanksRegistration'
              AND '{{form:SE}}'=''

Form: registration

{
    "title": "Registration",
    "tableName": "Person",
    "permitNew": "always",
    "permitEdit": "never",
    "showButton": "close,save",
    "forwardMode": "url-sip-skip-history",
    "forwardPage": "?id=registration&action=thanksRegistration",
    "parameter": "submitButtonText=Register",
    "FormElement_ff": [
        {
            "enabled": "yes",
            "name": "firstName",
            "label": "First name",
            "mode": "required",
            "type": "text"
        },
        {
            "enabled": "yes",
            "name": "lastName",
            "label": "Last name",
            "mode": "required",
            "type": "text"
        },
        {
            "enabled": "yes",
            "name": "email",
            "label": "Email",
            "mode": "required",
            "class": "native",
            "type": "text",
            "checkType": "email",
            "parameter": "retype\r\nretypeLabel=Retype email"
        },
        {
            "enabled": "yes",
            "label": "Check for double registration",
            "mode": "show",
            "modeSql": "",
            "class": "action",
            "type": "beforeSave",
            "parameter": "sqlValidate={{!SELECT p.id FROM Person AS p WHERE p.email='{{email:F:alnumx}}'  OR ('{{firstName:F:allbut}}'=p.firstName AND  '{{lastName:F:allbut}}'=p.lastName ) LIMIT 1 }}\r\n expectRecords=0\r\nmessageFail=Sorry, person already registered by name or email. Please just reset the password under <a href='?id=reset'>reset</a>"
        },
        {
            "enabled": "yes",
            "label": "auth, deadline",
            "class": "action",
            "type": "afterSave",
            "parameter": "# Set token & expiration\r\nsqlBefore={{UPDATE Person SET auth='{{random:V}}', authExpire=DATE_ADD(NOW(), INTERVAL 1 DAY) WHERE id={{id:R}} }}"
        },
        {
            "enabled": "yes",
            "label": "a) sendEmail, b) fe user",
            "mode": "show",
            "class": "action",
            "type": "sendMail",
            "value": "Dear new user\r\nPlease set a new password under {{baseUrl:Y}}?id=set&auth={{auth:R}}\r\nRegards.",
            "parameter": "sendMailTo={{email:R}}\r\nsendMailSubject=Registration confirmation\r\nsendMailFrom={{ADMINISTRATIVE_EMAIL:Y}}\r\n\r\n# Create User in T3\r\nsqlAfter={{INSERT INTO {{dbNameT3:Y}}.fe_users (pid, usergroup, username, password, first_name, last_name, name, email) VALUES (6, '1', '{{email:F:alnumx}}','$p$initial invalid hash',  '{{firstName:R}}', '{{lastName:R}}', '{{firstName:R}} {{lastName:R}}', '{{email:F:alnumx}}') }}"
        }
    ]
}

Set new password

Page: set

  • Page
    • Alias: set
    • Hide in menu: yes

QFQ content record:

#
# {{auth:CE}} - empty >> Form 'setPassword'
# {{auth:CE}} - unknown | expired >> Error message
# {{auth:SE}} - valid >> Set Password
#
# {{action:CE}} - 'thanks'

form={{SELECT IF( ISNULL(p.id), '', 'passwordSet' )
          FROM (SELECT '') AS fake
          LEFT JOIN Person AS p
            ON p.auth='{{auth:C:alnumx}}'
              AND p.auth!=''
              AND NOW()<p.authExpire }}

r={{SELECT IFNULL(p.id, 0) FROM (SELECT '') AS fake LEFT JOIN Person AS p ON p.auth='{{auth:C:alnumx}}' AND p.auth!='' AND NOW()<p.authExpire}}


10 {
  sql = SELECT IF( ISNULL(p.id)
                   , 'Token invalid'
                   , IF( NOW()<p.authExpire
                        ,''
                        , IF( p.authExpire=0, 'Password already set', 'Token expired') )
                 )
          FROM (SELECT '') AS fake
          LEFT JOIN Person AS p
            ON p.auth='{{auth:C:alnumx}}'
              AND p.auth!=''
          WHERE '{{action:SE}}'=''
              AND (ISNULL(p.id) OR NOW()>=p.authExpire)
  head = <div class="alert alert-warning" role="alert">
  tail = </div>
}

20.sql = SELECT 'Thanks for setting the password. Please <a href="?id=login">log in</a> now.'
           FROM (SELECT '') AS fake
           WHERE '{{action:SE}}'='thanks'

Form: passwordSet

Note

Please adjust the numbers for usergroup and pid in FormElement Update fe_user.password > parameter > sqlInsert to your needs. Remember that every FE-User needs at least one FE-Group to log in successfully.

Form ‘passwordSet’:

{
    "title": "Set password",
    "tableName": "Person",
    "permitNew": "never",
    "permitEdit": "always",
    "escapeTypeDefault": "c",
    "render": "bootstrap",
    "dirtyMode": "exclusive",
    "showButton": "save",
    "multiMode": "none",
    "forwardMode": "url-sip-skip-history",
    "forwardPage": "?{{pageAlias:T}}&action=thanks",
    "parameter": "submitButtonText='Set password'",
    "FormElement_ff": [
        {
            "enabled": "yes",
            "name": "myValue",
            "label": "Password",
            "mode": "show",
            "class": "native",
            "type": "password",
            "checkType": "pattern",
            "checkPattern": "[a-zA-Z0-9-_+ *\\\/.,:;]{10,}",
            "ord": 10,
            "parameter": "retype\r\nretypeLabel=Retype password\r\ndata-pattern-error=At least 10 characters are required. Valid characters: a-z A-Z 0-9 -_+*\/.,:;\r\nextraButtonPassword"
        },
        {
            "enabled": "yes",
            "label": "Update fe_user.password",
            "mode": "show",
            "class": "action",
            "type": "afterSave",
            "encode": "specialchar",
            "ord": 20,
            "parameter": "slaveId={{SELECT fe.uid FROM {{dbNameT3:Y}}.fe_users AS fe WHERE fe.username='{{email:RE}}' AND fe.username!='' AND fe.deleted=0 LIMIT 1}}\r\n\r\n# Create FE User. Please update values of `pid`, `usergroup` to your setup.\r\nsqlInsert = {{INSERT INTO {{dbNameT3:Y}}.fe_users ( `pid`, `usergroup`, `username`, `email`, `name`, `password`,`crdate`) VALUES ( 5 , 1 , '{{email:RE}}', '{{email:RE}}', '{{lastName:RE}}, {{firstName:RE}}', '{{myValue:FE:all:p}}',  UNIX_TIMESTAMP() ) }}\r\n\r\nsqlUpdate = {{UPDATE {{dbNameT3:Y}}.fe_users SET password='{{myValue:FE:all:p}}' WHERE uid={{slaveId:V0}}  }}\r\n\r\nsqlAfter={{UPDATE Person SET authExpire=0 WHERE id={{id:R}} }}"
        }
    ]
}