Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Develop to master merge for cookie notice and other improvements #1405

Merged
merged 55 commits into from
Sep 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
da2d1bd
Bump follow-redirects from 1.15.4 to 1.15.6 (#1384)
dependabot[bot] Mar 16, 2024
f85806d
Disallow util login
akmiller01 Mar 21, 2024
965375b
Merge pull request #1385 from devinit/security/more-robots-disallow
akmiller01 Mar 21, 2024
1a943e5
Bump webpack-dev-middleware and webpack-dev-server (#1387)
dependabot[bot] Mar 22, 2024
d9d3a30
Bump express from 4.18.2 to 4.19.2 (#1388)
dependabot[bot] Mar 28, 2024
3b342e3
Bump gunicorn from 20.1.0 to 22.0.0 (#1390)
dependabot[bot] Apr 17, 2024
6cffb8f
Section-optional banner block for mid-content
akmiller01 Apr 17, 2024
79d30bd
Unable to modify block attributes like that
akmiller01 Apr 17, 2024
2e4d848
Merge pull request #1391 from devinit/feature/content-banner-block
akmiller01 Apr 18, 2024
ce37a23
Add 2fa to website CMS
wakibi Apr 15, 2024
0a5cb35
Add environment to name
wakibi Apr 15, 2024
f996953
Add braces
wakibi Apr 15, 2024
ec27757
Use correct 2fa package and add docs
wakibi Apr 18, 2024
05adf89
Add 2fa docs
wakibi Apr 18, 2024
385cce6
Merge pull request #1389 from devinit/feature/2fa
wakibi Apr 23, 2024
21bebc5
Basic box 1 cookie notice formatting
akmiller01 Jul 1, 2024
a6ab692
Re-run skelly build
akmiller01 Jul 1, 2024
b1a4989
Record user choice in cookie
akmiller01 Jul 1, 2024
37b1a12
Don't appear on set cookie page
akmiller01 Jul 1, 2024
2bb9f3b
Non-disappearing modal on privacy page
akmiller01 Jul 1, 2024
6abdf02
Working log backend
akmiller01 Jul 2, 2024
be5d17a
Sonarcloud rel noopener
akmiller01 Jul 2, 2024
3b03b18
Fix delete bug
akmiller01 Jul 2, 2024
de7c379
Increase expire time to 6 mo
akmiller01 Jul 3, 2024
bcba81c
No header on privacy page
akmiller01 Jul 3, 2024
cf6d5d2
Merge pull request #1394 from devinit/feature/di-cookie-consent
akmiller01 Jul 3, 2024
ff408ea
Commit migration
akmiller01 Jul 3, 2024
b4feeea
Merge pull request #1395 from devinit/feature/di-cookie-consent
akmiller01 Jul 3, 2024
be10c2f
Style faux radio buttons for cookie consent
akmiller01 Jul 8, 2024
56bdb43
Cookie preference button
akmiller01 Jul 8, 2024
ad4e758
Checkout basic
akmiller01 Jul 8, 2024
3a6c1e7
Try and fix all SCSS for sonarcloud
akmiller01 Jul 8, 2024
6f7ee7d
Re-run build
akmiller01 Jul 8, 2024
97c2cfb
Lint more SCSS
akmiller01 Jul 8, 2024
474ae2e
Rebuild
akmiller01 Jul 8, 2024
518bf43
Checkout master basic
akmiller01 Jul 8, 2024
14f5c2a
Error proof API
akmiller01 Jul 9, 2024
6e36e7e
Merge pull request #1396 from devinit/feature/cookie-banner-styling
akmiller01 Jul 9, 2024
5863456
Unify two cookie consent styles
akmiller01 Jul 9, 2024
1d16da4
Merge branch 'develop' of https://github.com/devinit/DIwebsite-redesi…
akmiller01 Jul 9, 2024
3ad17ef
Reset base
akmiller01 Jul 9, 2024
f762eac
Move anchor
akmiller01 Jul 9, 2024
1df7251
Remove comments
akmiller01 Jul 9, 2024
6ed6f19
Merge pull request #1397 from devinit/feature/cookie-banner-styling
akmiller01 Jul 9, 2024
0d09017
Bump wagtail from 4.2.4 to 5.2.6 (#1398)
dependabot[bot] Jul 11, 2024
a094269
Base64 encoded memorial
akmiller01 Jul 16, 2024
d394820
Merge pull request #1399 from devinit/feature/memorial
akmiller01 Jul 21, 2024
5d14924
Remove deprecated edit handler code
akmiller01 Jul 22, 2024
848e15e
Merge pull request #1400 from devinit/fix/edit_handler_crash
akmiller01 Jul 22, 2024
31b59be
Fix responsive image node
akmiller01 Jul 22, 2024
56543cb
Remove debug
akmiller01 Jul 22, 2024
d7bcc6b
Merge pull request #1401 from devinit/fix/responsiveImageNode
akmiller01 Jul 22, 2024
a30d551
Upgrade wagtail-2fa version
akmiller01 Aug 5, 2024
32db52c
Merge pull request #1402 from devinit/fix/2fa-version
akmiller01 Aug 5, 2024
2826f19
Bump webpack from 5.76.0 to 5.94.0 (#1404)
dependabot[bot] Aug 30, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -255,3 +255,7 @@ docker inspect e20e0a57d399
```

First, bash into nginx, then `curl -sX GET http://consul:8500/v1/catalog/service/blue` to get the ServiceId. Followed by `docker-compose -f docker-compose-consul.yml exec consul consul services deregister -id=ab9298cc69bd:blue:8090`

## 2FA Notes

We are using [wagtail-2fa](https://github.com/labd/wagtail-2fa/). The documentation about which version of this package matching with a specific version of wagtail is terrible. You will have to go through all the changelogs or something similar. If you intend to upgrade either `Wagtail` or `wagtail-2fa`, we advise you set `DEBUG = False` after running all your tests in debug mode, and test 2FA login as well with debug set off. This is because this package attempts to use `wagtail.svg` which keeps changing names in the Wagtail package, and `ManifestStaticFilesStorage` will not throw any errors with `DEBUG = True`. So the only way to test that the two packages (Wagtail and wagtail-2fa) are compatible is turning off debug. Also, don't forget to `collectstatic` before testing.
30 changes: 30 additions & 0 deletions di_website/api/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Generated by Django 3.2.25 on 2024-07-02 13:13

from django.db import migrations, models


class Migration(migrations.Migration):

initial = True

dependencies = [
]

operations = [
migrations.CreateModel(
name='CookieConsentLogEntry',
fields=[
('token', models.CharField(max_length=255, primary_key=True, serialize=False)),
('anonymised_ip_address', models.GenericIPAddressField()),
('first_seen', models.DateTimeField(auto_now_add=True)),
('modified', models.DateTimeField(auto_now=True)),
('url', models.URLField()),
('user_agent', models.TextField()),
('choice', models.CharField(max_length=255)),
],
options={
'verbose_name': 'Cookie Consent Log Entry',
'verbose_name_plural': 'Cookie Consent Log Entries',
},
),
]
19 changes: 19 additions & 0 deletions di_website/api/models.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,22 @@
from django.db import models
from wagtail.snippets.models import register_snippet

# Create your models here.

@register_snippet
class CookieConsentLogEntry(models.Model):
token = models.CharField(max_length=255, primary_key=True)
anonymised_ip_address = models.GenericIPAddressField()
first_seen = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
url = models.URLField()
user_agent = models.TextField()
choice = models.CharField(max_length=255)


def __str__(self):
return self.token or 'Unknown log entry'

class Meta():
verbose_name = "Cookie Consent Log Entry"
verbose_name_plural = "Cookie Consent Log Entries"
5 changes: 3 additions & 2 deletions di_website/api/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@

from di_website.api.views import (
footer_view, spotlights_navigation_view, spotlight_page_view,
spotlight_pages_view, dashboard_data_view)
spotlight_pages_view, dashboard_data_view, post_cookie_consent_log_entry)

urlpatterns = [
path('spotlights/navigation/', spotlights_navigation_view, name='spotlight-navigation'),
path('spotlights/pages/', spotlight_pages_view, name='spotlight-pages'),
path('spotlights/page/<slug:slug>/', spotlight_page_view, name='spotlight-page'),
path('footer/', footer_view),
path('dashboard/data/', dashboard_data_view)
path('dashboard/data/', dashboard_data_view),
path('cookie-consent/', post_cookie_consent_log_entry),
]
15 changes: 15 additions & 0 deletions di_website/api/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,3 +115,18 @@ def serialise_location_comparison_page(live_pages):
serialised_data['default_locations'].append(block.value)

return serialised_data


def get_client_ip(request):
x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
if x_forwarded_for:
ip = x_forwarded_for.split(',')[0]
else:
ip = request.META.get('REMOTE_ADDR')
return ip


def anonymise_ip_address(ip_address):
ip_split = ip_address.split(".")
ip_split[-1] = "0"
return ".".join(ip_split)
28 changes: 25 additions & 3 deletions di_website/api/views.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import csv

import json
import requests

from django.conf import settings
from django.http import JsonResponse
from django.http import JsonResponse, HttpResponse
from django.views.decorators.http import require_http_methods
from django.db.utils import DataError

from github import Github
from wagtail.models import Site
Expand All @@ -18,7 +19,9 @@
from .utils import (fetch_and_serialise_footer_sections,
fetch_and_serialise_newsletters,
serialise_location_comparison_page, serialise_page,
serialise_spotlight_theme, serialiseDatasources)
serialise_spotlight_theme, serialiseDatasources,
get_client_ip, anonymise_ip_address)
from .models import CookieConsentLogEntry


@require_http_methods(["GET"])
Expand Down Expand Up @@ -134,3 +137,22 @@ def dashboard_data_view(request):

print(e)
return JsonResponse({ 'error': 'An error occurred' }, safe=False)


@require_http_methods(["POST"])
def post_cookie_consent_log_entry(request):
json_data = json.loads(request.body)
token = json_data.pop('token')
client_ip = get_client_ip(request)
anon_ip = anonymise_ip_address(client_ip)
if anon_ip == '0':
anon_ip = '0.0.0.0'
json_data['anonymised_ip_address'] = anon_ip
try:
CookieConsentLogEntry.objects.update_or_create(
token=token,
defaults=json_data
)
except DataError:
pass
return HttpResponse(status=204)
5 changes: 5 additions & 0 deletions di_website/common/blocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,11 @@ class Meta():
label = 'Banner Block'


class ContentBannerBlock(BannerBlock):
class Meta():
template = 'blocks/banner/content_banner_block.html'


class SectionParagraphBlock(StructBlock):
text = RichTextBlock(features=RICHTEXT_FEATURES_NO_FOOTNOTES)
center = BooleanBlock(default=False, required=False)
Expand Down
53 changes: 0 additions & 53 deletions di_website/common/edit_handlers.py
Original file line number Diff line number Diff line change
@@ -1,59 +1,6 @@
from django.forms.utils import pretty_name
from django.utils.html import format_html
from django.utils.translation import ugettext_lazy as _
from django.utils.html import mark_safe

from wagtail.admin.panels import EditHandler
from wagtail.admin.panels import HelpPanel as WagtailHelpPanel


class BaseReadOnlyPanel(EditHandler):
def render(self):
value = getattr(self.instance, self.field_name)
if callable(value):
value = value()
return format_html(
'<div style="padding-top: 1.2em;">{}</div>',
mark_safe(value))

def render_as_object(self):
return format_html(
'<fieldset><legend>{}</legend>'
'<ul class="fields"><li><div class="field">{}</div></li></ul>'
'</fieldset>',
self.heading, self.render())

def render_as_field(self):
return format_html(
'<div class="field">'
'<label>{}{}</label>'
'<div class="field-content">{}</div>'
'</div>',
self.heading, _(':'), self.render())


class ReadOnlyPanel(BaseReadOnlyPanel):
"""
Custom implementation of readonly panel, refer to issue on from wagtail
https://github.com/wagtail/wagtail/issues/2893
"""

def __init__(self, field_name, *args, **kwargs):
super().__init__(*args, **kwargs)
self.field_name = field_name

def clone_kwargs(self):
kwargs = super().clone_kwargs()
kwargs.update(
field_name=self.field_name
)
return kwargs

def bind_to_model(self, model):
return type(str(_('ReadOnlyPanel')), (BaseReadOnlyPanel,), {
'model': self.model, 'heading': self.heading, 'classname': self.classname})


def HelpPanel(
content='',
template='wagtailadmin/panels/help_panel.html',
Expand Down
2 changes: 1 addition & 1 deletion di_website/common/templatetags/responsive.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ def render(self, context):
return ''

try:
rendition = image.get_rendition(self.filter)
rendition = image.get_rendition(self.filter_specs)
except SourceImageIOError:
# It's fairly routine for people to pull down remote databases to their
# local dev versions without retrieving the corresponding image files.
Expand Down
6 changes: 6 additions & 0 deletions di_website/common/templatetags/string_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -260,3 +260,9 @@ def buzzsprout_container_id(buzzsprout_url):
return container_ids[0]
else:
return ""

@register.filter
def remove_url_parameters(url):
"""Remove parameters from a url-like string"""
split_url = url.split("?")
return split_url[0]
28 changes: 28 additions & 0 deletions di_website/home/migrations/0079_auto_20240701_1535.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Generated by Django 3.2.25 on 2024-07-01 15:35

from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
('wagtailcore', '0083_workflowcontenttype'),
('home', '0078_auto_20231117_1216'),
]

operations = [
migrations.RemoveField(
model_name='cookienotice',
name='cookie_policy',
),
migrations.RemoveField(
model_name='cookienotice',
name='download_link_caption',
),
migrations.AddField(
model_name='cookienotice',
name='set_cookie_page',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailcore.page', verbose_name='Page'),
),
]
12 changes: 4 additions & 8 deletions di_website/home/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,23 +166,19 @@ class Meta:
class CookieNotice(models.Model):
heading = models.CharField(max_length=255, blank=True, null=True)
body = models.TextField(blank=True, null=True)
download_link_caption = models.CharField(max_length=255, blank=True, null=True, verbose_name='Link Caption')
cookie_policy = models.ForeignKey(
'wagtaildocs.Document',
set_cookie_page = models.ForeignKey(
'wagtailcore.Page',
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name='+',
verbose_name='Policy Doc'
verbose_name='Page'
)

panels = [
FieldPanel('heading'),
FieldPanel('body'),
MultiFieldPanel([
FieldPanel('download_link_caption'),
FieldPanel('cookie_policy'),
], heading='Download Link'),
PageChooserPanel('set_cookie_page')
]

def __str__(self):
Expand Down
5 changes: 3 additions & 2 deletions di_website/publications/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

from di_website.common.constants import RICHTEXT_FEATURES, RICHTEXT_FEATURES_NO_FOOTNOTES, FOOTNOTE_RICHTEXT_FEATURES
from .infographic import PublicationInfographic
from di_website.common.blocks import AccordionBlock, AnchorBlock, CallToActionBlock, SectionBlockQuote
from di_website.common.blocks import AccordionBlock, AnchorBlock, CallToActionBlock, SectionBlockQuote, ContentBannerBlock


class CaptionedImage(StructBlock):
Expand Down Expand Up @@ -337,7 +337,8 @@ class Meta:
('advanced_interactive_chart', AdvancedInteractiveChartBlock()),
('cta', CallToActionBlock()),
('accordion', AccordionBlock()),
('so_what', SoWhat())
('so_what', SoWhat()),
('content_banner', ContentBannerBlock()),
]

def flexible_content_streamfield(blank=False):
Expand Down
45 changes: 45 additions & 0 deletions di_website/publications/migrations/0126_auto_20240417_1654.py

Large diffs are not rendered by default.

11 changes: 11 additions & 0 deletions di_website/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,11 @@
'django.contrib.staticfiles',
'django.contrib.postgres',

# Wagtail 2FA (https://github.com/labd/wagtail-2fa)
'wagtail_2fa',
'django_otp',
'django_otp.plugins.otp_totp',

]

MIDDLEWARE = [
Expand All @@ -105,6 +110,8 @@
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
# Wagtail 2FA (https://github.com/labd/wagtail-2fa)
'wagtail_2fa.middleware.VerifyUserMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.security.SecurityMiddleware',
Expand Down Expand Up @@ -233,6 +240,10 @@

WAGTAIL_SITE_NAME = "Development Initiatives Website"

# Wagtail 2FA settings (https://github.com/labd/wagtail-2fa)
WAGTAIL_2FA_REQUIRED = True
WAGTAIL_2FA_OTP_TOTP_NAME = f"DI Website CMS ({os.getenv('ENVIRONMENT') or 'Dev'})"

# Base URL to use when referring to full URLs within the Wagtail admin backend -
# e.g. in notification emails. Don't include '/admin' or a trailing slash
WAGTAILADMIN_BASE_URL = os.getenv('BASE_URL') or 'http://devinit.org'
Expand Down
Loading
Loading