humhub-contrib / legal

2 stars 8 forks source link

One time Cookie Notice #65

Open ArchBlood opened 8 months ago

ArchBlood commented 8 months ago

Currently when you visit a HumHub instance with cookie notice enabled you have to accept each time you visit the site.

ArchBlood commented 7 months ago

Seems that this issue only happens on the community site;

https://community.humhub.com/dashboard

luke- commented 7 months ago

Hmm, I cannot reproduce this on our community. The notice does not appear again for me.

ArchBlood commented 7 months ago

Latest version of Chrome on Windows 11 it appears every time I visit the community site, but no other HumHub instance have I seen this happen. Screenshot_1

It also apparently shows up every time the page is refreshed as well. :thinking:

felixhahnweilheim commented 7 months ago

I have the same as @ArchBlood on my phone (Android 13) with Chrome, and (Chrome-based) PWA.

ArchBlood commented 7 months ago

I have the same as @ArchBlood on my phone (Android 13) with Chrome, and (Chrome-based) PWA.

I can confirm that the issue is also happening on Chrome mobile browser as well.

luke- commented 7 months ago

@yurabakhtin Can you please take a look into it?

yurabakhtin commented 7 months ago

@luke- I have the same bug today when I open https://community.humhub.com in Chrome on Windows 11.

I find 2 cookie records:

cookies

If manually remove the 2 records then it works as expected, i.e. after first click "Got it!" the cookie block is hidden and doesn't appears again. I cannot find how the record with domain .humhub.com was created there. Locally I tried to reproduce the issue by the following steps:


The cookie block is initialized by this JS library https://www.osano.com/cookieconsent/documentation/javascript-api/ I tried to set cookie.domain to humhub.local then cookie record is created for domain .humhub.local and the cookie block is hidden after accept button clicking and doesn't appear after page reloading. If set cookie.domain to alias.humhub.local then cookie record is created for domain .alias.humhub.local and this solution works only for the site alias.humhub.local. It would be good the JS library set cookie domain without adding a dot before provided domain name, because I am not sure we can allow accept cookies for all sub sites when it was accepted on root domain.

ArchBlood commented 7 months ago

Can't we just use something like this to set the cookie domain?

// Set the cookie to a specific domain
$cookieDomain = \yii\helpers\Url::base()'; // Replace 'yourdomain.com' with your desired domain
setcookie('cookieconsent_status', 'accepted', time() + 31536000, '/', $cookieDomain, false, true);

Or something like the following?

        // Get the current site's domain
        $currentDomain = Yii::$app->request->hostInfo;

        // Set the cookie using Yii's response component
        $response = Yii::$app->response;
        $response->cookies->add(new \yii\web\Cookie([
            'name' => 'cookieconsent_status',
            'value' => 'accepted',
            'expire' => time() + 31536000,
            'path' => '/',
            'domain' => $currentDomain,
            'httpOnly' => true,
            'secure' => true, // Set to true if your site uses HTTPS
        ]));

We should be able to do this in /widgets/CookieNote.php

ArchBlood commented 7 months ago

Another option would be the following;

<?php

namespace humhub\modules\legal\widgets;

use humhub\components\Widget;
use humhub\modules\legal\models\Page;
use Yii;
use yii\web\HttpException;

/**
 * Class CookieNote
 * @package humhub\modules\legal\widgets
 */
class CookieNote extends Widget
{
    public function run()
    {
        $page = Page::getPage(Page::PAGE_KEY_COOKIE_NOTICE);
        if ($page === null) {
            return "";
        }

        // Get the current site's domain
        $currentDomain = Yii::$app->request->hostInfo;

        // Extract the root domain to cover all subdomains and aliases
        $rootDomain = $this->getRootDomain($currentDomain);

        // Set the cookie using Yii's response component
        $response = Yii::$app->response;
        $response->cookies->add(new \yii\web\Cookie([
            'name' => 'cookieconsent_status',
            'value' => 'accepted',
            'expire' => time() + 31536000,
            'path' => '/',
            'domain' => $rootDomain,
            'httpOnly' => true,
            'secure' => true, // Set to true if your site uses HTTPS
        ]));

        return $this->render('cookies', ['page' => $page]);
    }

    // Function to extract the root domain from a given domain
    private function getRootDomain($domain)
    {
        $domainParts = explode('.', $domain);
        $partsCount = count($domainParts);
        if ($partsCount > 2) {
            // Construct the root domain for subdomains or alias domains
            $rootDomain = $domainParts[$partsCount - 2] . '.' . $domainParts[$partsCount - 1];
            return '.' . $rootDomain;
        }
        return $domain; // Return original domain if it's already a root domain
    }
}

Although I've not tested this specific method.

yurabakhtin commented 7 months ago

@ArchBlood Thank you for the help, but the problem was from JS side. @luke- Fixed in PR https://github.com/humhub-contrib/legal/pull/66:

cookie

This fix will hides the cookie consent window on all browsers even if they still have two records for root domain and for the strange records with domain like .domain.com

I have compared the JS method getCookie from here https://github.com/osano/cookieconsent/blob/dev/src/bundle.js#L2739-L2743:

const getCookie = name => {
  const value = ' ' + document.cookie;
  const parts = value.split(' ' + name + '=');
  return parts.length < 2 ? undefined : parts.pop().split(';').shift();
};

and from the humhub file version:

getCookie: function (e) {
    var t = "; " + document.cookie,
        i = t.split("; " + e + "=");
    return 2 != i.length ? void 0 : i.pop().split(";").shift();
},

so the difference was between parts.length < 2 and 2 != i.length

My fix is a manual updating only of the code, because I tried to use new version completely from here https://github.com/osano/cookieconsent/blob/dev/build/cookieconsent.min.js and I updated the initialisation code from window.cookieconsent.initialise({ to new new window.CookieConsent({, but I don't understand why when press to accept I don't find that cookie record is created in my browser, so the cookie consent window appears again and again after page reloading.

luke- commented 7 months ago

@yurabakhtin Thanks.

I'll keep this issue open, because we should find a better solution in future, instead of fixing the minifed version.