Controlled access on an open project

Problem

You want to constrain respondents to a single questionnaire but also want to allow unknown respondents in.

Solution

You could use # Control by cookie but another, maybe more robust, solution is to add a font-end project to control access.

Discussion

The # Control by cookie activates a cookie-based control system which prevents the creation of a second questionnaire by a given computer. However, it is limited to fully open projects, works in callweb.cgi only, not in cwx.cgi, and is not immuned to users deleting the cookie or using a second browser to access more questionnaires.

The general solution proposed here is to create a small project (hereby called the gatekeeper) that is used to control access to the second, real questionnaire. The gatekeeper project requests the respondent's email address and emails a one-time use code to authenticate the user at that address. Once the code is correctly entered, the gatekeeper project looks up the _telkey corresponding to the email address in the second project or creates a record in the second project, and flows the respondent to that record in the main project. This can work even if the second project is closed. It can also allow or disallow access by email addresses that are not already prepopped into the second project.

Gatekeeper project

Here are example code snipplets.

    EMAIL
    % Question
      [EN]Please enter your professional email address. <span class="NOBOLD">Please note that we are asking your email address only to assign you your own unique survey link while ensuring that you are the owner of that address. This will allow you to leave the survey and return to the last question you were on in case you cannot complete the survey in one sitting. Your email address will not be associated with your responses in any of the analysis and reporting.</span>
      [FR]Veuillez fournir votre adresse de courriel professionnel. <span class="NOBOLD">Veuillez noter que nous recueillons votre adresse de courriel uniquement pour vous attribuer un lien d'enquête propre à vous tout en nous assurant que vous êtes le propriétaire de cette adresse. Cela vous permettra de quitter le sondage et de revenir à la dernière question à laquelle vous répondiez au cas où vous ne pourriez pas répondre au sondage d'une traite. Votre adresse de courriel ne sera associée à vos réponses dans aucune des analyses et rapports.</span>
    % Note
    % Categories
      *1*[EN]Email[FR]Courriel
      *2*[EN]I prefer not to answer[FR]Je préfère ne pas répondre
    % Skips
      2 = COMPLETE
    % Condition
    % Open
      1 = E100 1 40
    ! ==============================================================
    TELKEY CALCUL
    % Question
      ATELKEY =
        {
        if ( n_dossiers("AEMAIL=\"$AEMAIL\"","MAINproject") == 0 )
          { put_values_in_case(_proj => "MAINproject", AEMAIL => $AEMAIL, ORIGINAL_SAMPLE => 2) }
        return pull_value("UNIQUE","_telkey","MAINproject","AEMAIL=\"$AEMAIL\"");
        }
    % Note
    % Categories

    % Skips
    % Condition
    % Open
    1 = C10 1 10
    ! ==============================================================
    STORE2FA CALCUL
    % texte de la question
      DUMP =
        {
        $STORE2FA = calcule_une_combinaison("NNNNNN");
        email("from\@example.com",$AEMAIL,"EMAIL2FA");
        }
    % texte de la note
    % catégories de réponses
    % sauts inconditionnels
    % condition
    % partie ouverte
    ! ==================================================
    EMAIL2FA EMAIL
    % texte de la question
      Your confirmation code for {$contexte{projet}} / Votre code de confirmation pour {$contexte{projet}}
    % texte de la note
      <p>(Le français suit l'anglais.)</p>
      <p>------------------------------------------------------------</p>
      <p>This message was sent to the email address found in your questionnaire for project "{$contexte{projet}}".</p>
      <p>Please enter this six-digit code in the web form to confirm that you control this email address.</p>
      <p>&@STORE2FA</p>
      <p>------------------------------------------------------------</p>
      <p>Ce message a été envoyé à l'adresse de courriel identifiée dans votre questionnaire pour le projet « {$contexte{projet}} ».</p>
      <p>Veuillez saisir le code à six chiffres suivant dans le formulaire Web pour confirmer que vous contrôlez cette adresse courriel.</p>
      <p>&@STORE2FA</p>

        <html>

        <head></head>

        <body style='margin: 0px 0px 0px 0px; font-family: Arial, Helvetica, sans-serif; font-size: 18px; color: #000000;'>

        <table border="0" cellpadding="5" cellspacing="5" width="100%">

        <tr>
        <td width="48%" height="0"></td>
        <td width="4%" height="0"></td>
        <td width="48%" height="0"></td>
        </tr>

        <tr valign="top">
        <td>This message was sent to the email address found in your questionnaire for project "{$contexte{projet}}".</td>
        <td> </td>
        <td>Ce message a été envoyé à l'adresse de courriel identifiée dans votre questionnaire pour le projet « {$contexte{projet}} ».</td>
        </tr>

        <tr valign="top">
        <td>Please enter this six-digit code in the web form to confirm that you control this email address.</td>
        <td> </td>
        <td>Veuillez saisir le code à six chiffres suivant dans le formulaire Web pour confirmer que vous contrôlez cette adresse courriel.</td>
        </tr>

        <tr>
        <td colspan="3" align="center"><div style="font-size: 24px; background-color: red ;color: white;">&@STORE2FA</div></td>
        </tr>

        </table>

        </body>

        </html>
    % catégories de réponses
    % sauts inconditionnels
    % condition
    % partie ouverte
    ! ==================================================
    COLLECT2FA
    % texte de la question
      [EN]A six-digit code has been emailed to &&AEMAIL to confirm that you are the owner of this address. Please enter this six-digit code below.
      [FR]Un code à six chiffres a été envoyé par courriel à l'adresse &&AEMAIL pour confirmer que vous êtes bien propriétaire de cette adresse. Veuillez saisir ce code à six chiffres ci-bas.
    % texte de la note
    % catégories de réponses

    % sauts inconditionnels
    % condition
    % partie ouverte
      1 = C10 1 10
    ! ==================================================
    CODEOK CALCUL
    % texte de la question
      $CODEOK =
        {
        my $res = ( $ACOLLECT2FA eq $STORE2FA ) ? 1 : 0;
        $ACOLLECT2FA = "";
        $STORE2FA = "";
        return $res;
        }
    % texte de la note
    % catégories de réponses
      *0*[EN]Bad[FR]Mauvais
      *1*[EN]Good[FR]Bon
    % sauts inconditionnels
    % condition
    % partie ouverte
    ! ==================================================
    WRONGCODE BACKWALL
    % texte de la question
      [EN]The code you entered does not match the one emailed to &&AEMAIL. Do you want to get a new code?
      [FR]Le code que vous avez saisi ne correspond pas au code envoyé à &&AEMAIL. Voulez-vous recevoir un autre code?
    % texte de la note
    % catégories de réponses
      [EN]Yes[FR]Oui
      [EN]No[FR]Non
    % sauts inconditionnels
      1 = STORE2FA
    % condition
      CODEOK.EQ.0
    % partie ouverte
    ! ==================================================
    # URL = [EN]https://example.com/en/MAINproject/&&ATELKEY[FR]https://example.com/fr/MAINproject/&&ATELKEY
    QEND MIN=0 MAX=0 CULDESAC BACKWALL
    % texte de la question
      [EN]<p align="center">Thank you for your collaboration.<br />You may now close this window.</p>
      [FR]<p align="center">Merci pour votre collaboration.<br />Vous pouvez maintenant fermer cette fenêtre.</p>
    % texte de la note
    % catégories de réponses
    % sauts inconditionnels
    % condition
      EMAIL.EQ.2 .OR. WRONGCODE.EQ.2
    % partie ouverte
    ! ==================================================

Main project

The requirements of the main project are minimal.

  • it can be open if the designer wants to maintain the ability to access it directly; this kind of defeats the purpose though, so it is likely closed.
  • it contains a STOCK field to store the email address; this field is prepopulated with email addresses expected to fill out the questionnaire and, if so desired, it can accept new addresses supplied by the gatekeeper project.

Controlled access on an open project

Problem

You want to constrain respondents to a single questionnaire but also want to allow unknown respondents in.

Solution

You could use # Control by cookie but another, maybe more robust, solution is to add a font-end project to control access.

Discussion

The # Control by cookie activates a cookie-based control system which prevents the creation of a second questionnaire by a given computer. However, it is limited to fully open projects, works in callweb.cgi only, not in cwx.cgi, and is not immuned to users deleting the cookie or using a second browser to access more questionnaires.

The general solution proposed here is to create a small project (hereby called the gatekeeper) that is used to control access to the second, real questionnaire. The gatekeeper project requests the respondent's email address and emails a one-time use code to authenticate the user at that address. Once the code is correctly entered, the gatekeeper project looks up the _telkey corresponding to the email address in the second project or creates a record in the second project, and flows the respondent to that record in the main project. This can work even if the second project is closed. It can also allow or disallow access by email addresses that are not already prepopped into the second project.

Gatekeeper project

Here are example code snipplets.

    EMAIL
    % Question
      [EN]Please enter your professional email address. <span class="NOBOLD">Please note that we are asking your email address only to assign you your own unique survey link while ensuring that you are the owner of that address. This will allow you to leave the survey and return to the last question you were on in case you cannot complete the survey in one sitting. Your email address will not be associated with your responses in any of the analysis and reporting.</span>
      [FR]Veuillez fournir votre adresse de courriel professionnel. <span class="NOBOLD">Veuillez noter que nous recueillons votre adresse de courriel uniquement pour vous attribuer un lien d'enquête propre à vous tout en nous assurant que vous êtes le propriétaire de cette adresse. Cela vous permettra de quitter le sondage et de revenir à la dernière question à laquelle vous répondiez au cas où vous ne pourriez pas répondre au sondage d'une traite. Votre adresse de courriel ne sera associée à vos réponses dans aucune des analyses et rapports.</span>
    % Note
    % Categories
      *1*[EN]Email[FR]Courriel
      *2*[EN]I prefer not to answer[FR]Je préfère ne pas répondre
    % Skips
      2 = COMPLETE
    % Condition
    % Open
      1 = E100 1 40
    ! ==============================================================
    TELKEY CALCUL
    % Question
      ATELKEY =
        {
        if ( n_dossiers("AEMAIL=\"$AEMAIL\"","MAINproject") == 0 )
          { put_values_in_case(_proj => "MAINproject", AEMAIL => $AEMAIL, ORIGINAL_SAMPLE => 2) }
        return pull_value("UNIQUE","_telkey","MAINproject","AEMAIL=\"$AEMAIL\"");
        }
    % Note
    % Categories

    % Skips
    % Condition
    % Open
    1 = C10 1 10
    ! ==============================================================
    STORE2FA CALCUL
    % texte de la question
      DUMP =
        {
        $STORE2FA = calcule_une_combinaison("NNNNNN");
        email("from\@example.com",$AEMAIL,"EMAIL2FA");
        }
    % texte de la note
    % catégories de réponses
    % sauts inconditionnels
    % condition
    % partie ouverte
    ! ==================================================
    EMAIL2FA EMAIL
    % texte de la question
      Your confirmation code for {$contexte{projet}} / Votre code de confirmation pour {$contexte{projet}}
    % texte de la note
      <p>(Le français suit l'anglais.)</p>
      <p>------------------------------------------------------------</p>
      <p>This message was sent to the email address found in your questionnaire for project "{$contexte{projet}}".</p>
      <p>Please enter this six-digit code in the web form to confirm that you control this email address.</p>
      <p>&@STORE2FA</p>
      <p>------------------------------------------------------------</p>
      <p>Ce message a été envoyé à l'adresse de courriel identifiée dans votre questionnaire pour le projet « {$contexte{projet}} ».</p>
      <p>Veuillez saisir le code à six chiffres suivant dans le formulaire Web pour confirmer que vous contrôlez cette adresse courriel.</p>
      <p>&@STORE2FA</p>

        <html>

        <head></head>

        <body style='margin: 0px 0px 0px 0px; font-family: Arial, Helvetica, sans-serif; font-size: 18px; color: #000000;'>

        <table border="0" cellpadding="5" cellspacing="5" width="100%">

        <tr>
        <td width="48%" height="0"></td>
        <td width="4%" height="0"></td>
        <td width="48%" height="0"></td>
        </tr>

        <tr valign="top">
        <td>This message was sent to the email address found in your questionnaire for project "{$contexte{projet}}".</td>
        <td> </td>
        <td>Ce message a été envoyé à l'adresse de courriel identifiée dans votre questionnaire pour le projet « {$contexte{projet}} ».</td>
        </tr>

        <tr valign="top">
        <td>Please enter this six-digit code in the web form to confirm that you control this email address.</td>
        <td> </td>
        <td>Veuillez saisir le code à six chiffres suivant dans le formulaire Web pour confirmer que vous contrôlez cette adresse courriel.</td>
        </tr>

        <tr>
        <td colspan="3" align="center"><div style="font-size: 24px; background-color: red ;color: white;">&@STORE2FA</div></td>
        </tr>

        </table>

        </body>

        </html>
    % catégories de réponses
    % sauts inconditionnels
    % condition
    % partie ouverte
    ! ==================================================
    COLLECT2FA
    % texte de la question
      [EN]A six-digit code has been emailed to &&AEMAIL to confirm that you are the owner of this address. Please enter this six-digit code below.
      [FR]Un code à six chiffres a été envoyé par courriel à l'adresse &&AEMAIL pour confirmer que vous êtes bien propriétaire de cette adresse. Veuillez saisir ce code à six chiffres ci-bas.
    % texte de la note
    % catégories de réponses

    % sauts inconditionnels
    % condition
    % partie ouverte
      1 = C10 1 10
    ! ==================================================
    CODEOK CALCUL
    % texte de la question
      $CODEOK =
        {
        my $res = ( $ACOLLECT2FA eq $STORE2FA ) ? 1 : 0;
        $ACOLLECT2FA = "";
        $STORE2FA = "";
        return $res;
        }
    % texte de la note
    % catégories de réponses
      *0*[EN]Bad[FR]Mauvais
      *1*[EN]Good[FR]Bon
    % sauts inconditionnels
    % condition
    % partie ouverte
    ! ==================================================
    WRONGCODE BACKWALL
    % texte de la question
      [EN]The code you entered does not match the one emailed to &&AEMAIL. Do you want to get a new code?
      [FR]Le code que vous avez saisi ne correspond pas au code envoyé à &&AEMAIL. Voulez-vous recevoir un autre code?
    % texte de la note
    % catégories de réponses
      [EN]Yes[FR]Oui
      [EN]No[FR]Non
    % sauts inconditionnels
      1 = STORE2FA
    % condition
      CODEOK.EQ.0
    % partie ouverte
    ! ==================================================
    # URL = [EN]https://example.com/en/MAINproject/&&ATELKEY[FR]https://example.com/fr/MAINproject/&&ATELKEY
    QEND MIN=0 MAX=0 CULDESAC BACKWALL
    % texte de la question
      [EN]<p align="center">Thank you for your collaboration.<br />You may now close this window.</p>
      [FR]<p align="center">Merci pour votre collaboration.<br />Vous pouvez maintenant fermer cette fenêtre.</p>
    % texte de la note
    % catégories de réponses
    % sauts inconditionnels
    % condition
      EMAIL.EQ.2 .OR. WRONGCODE.EQ.2
    % partie ouverte
    ! ==================================================

Main project

The requirements of the main project are minimal.

  • it can be open if the designer wants to maintain the ability to access it directly; this kind of defeats the purpose though, so it is likely closed.
  • it contains a STOCK field to store the email address; this field is prepopulated with email addresses expected to fill out the questionnaire and, if so desired, it can accept new addresses supplied by the gatekeeper project.