Grav Comments + Mosparo

In this guide, I will show you how to integrate mosparo spam protection into grave CMS comments plugin.

  1. Install mosparo

  2. Install grav (In this guid I am using the docker installation. I am using the following docker-compose.yaml file)

  3. Install grav comments plugin

  4. After creating a new mosparo project, go to the project setting and notice the following settings for the next step: mosparo-project-setting

    • host: (example: https://mosparo.example.com) (IP-Address or Hostname of your mosparo Server)
    • Unique identification number (uiid): (example: 1d85f632-XXXX-XXXX-XXXX-082ae814ddee)
    • Public key: (example: kJPK7acjNuXXXXXXXXXXXXXXXXXXXXXXXXXXXajQdQa38)
  5. Put the email-Block behind the addComment-Block in the following yaml files:

    • config/www/user/plugins/comments/comments.yaml and
    • config/www/user/config/plugins/comments.yaml
      ...
      process:
      #        - captcha:
      #            recaptcha_secret: ej32oiej23oiej32oijeoi32jeio32je
      - addComment:
      - email:
          subject: PLUGIN_COMMENTS.EMAIL_NEW_COMMENT_SUBJECT
          body: "{% include 'forms/data.html.twig' %}"
      - message: PLUGIN_COMMENTS.THANK_YOU_MESSAGE
      - reset: true
  6. Edit the following file on your grav Server: config/www/user/plugins/comments/templates/partials/comments.html.twig

    ...
    {% include "forms/fields/formname/formname.html.twig" %}
    
        <!-- ######################## BEGIN Mosparo integration ######################## -->
        <div style="margin-top:10px; margin-bottom:10px;" id="mosparo-box"></div>
        <script src="https://mosparo.example.com/build/mosparo-frontend.js" defer></script>
        <script>
            var m;
            window.onload = function(){
                m = new mosparo(
                   'mosparo-box', 
                   'https://mosparo.example.com',
                   '1d85f632-XXXX-XXXX-XXXX-082ae814ddee',
                   'kJPK7acjNuXXXXXXXXXXXXXXXXXXXXXXXXXXXajQdQa38',
                   {
                      loadCssResource: true
                   }
                );
            };
        </script>
        <!-- ######################## END Mosparo integration ######################## -->
    
        <div class="buttons">
        {% for button in grav.config.plugins.comments.form.buttons %}
            <button class="button" type="{{ button.type|default('submit') }}">{{ button.value|t|default('Submit') }}</button>
    ...

    Now we implemented mosparo into the frontend of the grav comments plugin. But for hacker or other criminal person it is easy to comment out the mosparo integration (live edit source code of webpage). To prevent this we need to integrate mopsaro into th backend of the grav comment plugin as well.

  7. Open internal the internal shell of the grav container and perform following commands:

    cd /config/www/user/plugins/comments
    php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
    php -r "if (hash_file('sha384', 'composer-setup.php') === 'e21205b207c3ff031906575712edab6f13eb0b361f2085f1f1237b7126d785e826a450292b6cfd1d64d92e6563bbde02') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
    php composer-setup.php
    php -r "unlink('composer-setup.php');"
    
    ./composer.phar require mosparo/php-api-client
    rm composer.*
    chown -R abc:users vendor
  8. Now we replace the function onFormProcessed() in the following file /config/www/user/plugins/comments/comments.php:

    Please edit the following parameters of the function new \Mosparo\ApiClient\Client() in the following code block:

    • First parameter: host: (example: https://mosparo.example.com) (IP-Address or Hostname of your mosparo Server)
    • Second parameter: Public key: (example: kJPK7acjNuXXXXXXXXXXXXXXXXXXXXXXXXXXXajQdQa38)
    • Third parameter: Private key: (example: hjeJfcWf3BXXXXXXXXXXXXXXXXXXXXXXXXXXXhZKT53GD)
    ...
    public function onFormProcessed(Event $event)
    {
        $form = $event['form'];
        $action = $event['action'];
        $params = $event['params'];
    
        if (!$this->active) {
            return;
        }
    
        switch ($action) {
            case 'addComment':
                // ######################## BEGIN Mosparo integration ########################
                require_once(__DIR__ . '/vendor/autoload.php');
    
                $client = new \Mosparo\ApiClient\Client("https://mosparo.example.com", "kJPK7acjNuXXXXXXXXXXXXXXXXXXXXXXXXXXXajQdQa38", "hjeJfcWf3BXXXXXXXXXXXXXXXXXXXXXXXXXXXhZKT53GD", ['verify' => true]);
    
                $mosparoSubmitToken = $_POST['_mosparo_submitToken'];
                $mosparoValidationToken = $_POST['_mosparo_validationToken'];
    
                $result = $client->verifySubmission($_POST, $mosparoSubmitToken, $mosparoValidationToken);
    
                if ($result->isSubmittable()) {
                    // Send the email and process the data
                    $post = isset($_POST['data']) ? $_POST['data'] : [];
    
                    $path = $this->grav['uri']->path();
    
                    $lang = htmlspecialchars(urldecode($post['lang']), ENT_QUOTES);
                    $text = htmlspecialchars(urldecode($post['text']), ENT_QUOTES);
                    $name = htmlspecialchars(urldecode($post['name']), ENT_QUOTES);
                    if ($name == "SuitDeer" || $name == "suitdeer" || $name == "DeerSuit" || $name == "deersuit" || $name == "Suit" || $name == "suit" || $name == "Deer" || $name == "deer" || $name == "Gero"|| $name == "gero"  ) {
                        break;
                    }
                    $email = filter_var(urldecode($post['email']), FILTER_SANITIZE_EMAIL);
                    $title = htmlspecialchars(urldecode($post['title']), ENT_QUOTES);
    
                    if (isset($this->grav['user'])) {
                        $user = $this->grav['user'];
                        if ($user->authenticated) {
                            $name = $user->fullname;
                            $email = $user->email;
                        }
                    }
    
                    /** @var Language $language */
                    $language = $this->grav['language'];
                    $lang = $language->getLanguage();
    
                    $filename = DATA_DIR . 'comments';
                    $filename .= ($lang ? '/' . $lang : '');
                    $filename .= $path . '.yaml';
                    $file = File::instance($filename);
    
                    if (file_exists($filename)) {
                        $data = Yaml::parse($file->content());
    
                        $data['comments'][] = [
                            'text' => $text,
                            'date' => date('D, d M Y H:i:s', time()),
                            'author' => $name,
                            'email' => $email
                        ];
                    } else {
                        $data = array(
                            'title' => $title,
                            'lang' => $lang,
                            'comments' => array([
                                'text' => $text,
                                'date' => date('D, d M Y H:i:s', time()),
                                'author' => $name,
                                'email' => $email
                            ])
                        );
                    }
    
                    $file->save(Yaml::dump($data));
    
                    //clear cache
                    $this->grav['cache']->delete($this->comments_cache_id);
    
                    break;
                }
                // ######################## END Mosparo integration ########################
        }
    }
    ...
  9. Now we replace the function prepareFormData() in the following file config/www/user/plugins/comments/vendor/mosparo/php-api-client/src/RequestHelper.php:

    ...
        public function prepareFormData(array $formData): array
        {
            $formData = $this->cleanupFormData($formData);
    
            $final_array = array();
            $final_array = array(
               'data[date]' => $formData['data']['date'],
               'data[email]' => $formData['data']['email'],
               'data[name]' => $formData['data']['name'],
               'data[path]' => $formData['data']['path'],
               'data[text]' => $formData['data']['text'],
               'data[title]' => $formData['data']['title'],
               'data[lang]' => $formData['data']['lang']
            );
    
            $data = [];
            foreach ($final_array as $key => $value) {
                if (is_array($value)) {
                    $data[$key] = $this->prepareFormData($value);
                } else {
                    if (is_numeric($value)) {
                        $value = strval($value);
                    } else if ($value === null) {
                        $value = '';
                    }
    
                    $data[$key] = hash('sha256', $value);
                }
            }
    
            ksort($data);
    
            return $data;
        }
    ...

Previous Post Next Post

Add a comment