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

Release v1.5 #564

Merged
merged 60 commits into from
Apr 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
0091b05
[#1249] Added headers to the logs, fixed requests hooks
vaszig Mar 16, 2023
d350639
[#1249] Fixed authorization header removal
vaszig Mar 16, 2023
9640d6f
[#1249] Fixed test
vaszig Mar 16, 2023
7d28611
[#1238] Started with adding cta button inside product content
vaszig Mar 15, 2023
f43cbb2
[#1238] Changed slug to id data attribute
vaszig Mar 15, 2023
8c273cc
[#1238] Fixed ckeditor for product detail content
vaszig Mar 16, 2023
04816a9
[#1238] Removed ckeditor button
vaszig Mar 17, 2023
029e965
[#1238] Fixed form links and button style
vaszig Mar 21, 2023
ff5d1eb
[#1238] Fixed conflict in migrations
vaszig Mar 21, 2023
f0437e6
Splitting up configuration
alextreme Mar 21, 2023
c1df53b
[#1238] Fixed tests
vaszig Mar 21, 2023
179464a
[#1249] Fixed tests and migrations
vaszig Mar 21, 2023
f62301b
[#1249] Remove authorization without affecting the initial headers
vaszig Mar 21, 2023
0bb7974
[#1248] Use next url after login
vaszig Mar 21, 2023
a8c844e
[#1238] Fixed translations and tests
vaszig Mar 21, 2023
815c451
[#1249] Fixed headers format and tests
vaszig Mar 22, 2023
1eab24a
[#1270] Fixed image in contact approval
vaszig Mar 22, 2023
9c64c4c
[#1231] Fixed breadcrumbs in plans
vaszig Mar 23, 2023
5bc8464
[#1249] Removed unnecessary function and fixed tests
vaszig Mar 23, 2023
0c9c4ea
[#1248] Added template tag for next url
vaszig Mar 23, 2023
111a455
:lipstick: [#1169] Make images/icons have static sizes in cards
jiromaykin Mar 10, 2023
8c29141
[#1268] Disabled button in case document upload when form is being su…
vaszig Mar 23, 2023
8606ce6
Merge pull request #535 from maykinmedia/feature/1238-markdown-ctabut…
alextreme Mar 23, 2023
13c0973
[#1248] Fixed template tag and tests
vaszig Mar 23, 2023
39c85e8
[#1231] Removed unnecessary template tag
vaszig Mar 23, 2023
9d9d0c3
Merge pull request #526 from maykinmedia/feature/1169-make-images-hav…
alextreme Mar 23, 2023
22b78ff
Merge pull request #551 from maykinmedia/fix/1270-show-proper-image-i…
alextreme Mar 23, 2023
462a316
Merge pull request #539 from maykinmedia/fix/1249-add-headers-to-outg…
alextreme Mar 23, 2023
a752ebf
[#1253] Remove case result if none
vaszig Mar 24, 2023
c01369e
[#1258] Fixed order of phonenumber and email and added tel,email links
vaszig Mar 24, 2023
8ee7a9c
[#1027] Disabled applications dropdown in 2factor admin
vaszig Mar 24, 2023
44ee257
[#1177] Added through model for Plan.plan_contact m2m
Mar 13, 2023
d57f997
[#1177] Show new plan contact count in menu
Mar 13, 2023
04c448e
[#1177] Reset the counter when viewing plans list view
Mar 13, 2023
68b4ae3
[#1177] Fix plan counter visibility issue for owner
Mar 20, 2023
5d0683a
[#1177] Fixed problem with TestMigrations and related (historical) mo…
Mar 20, 2023
90627e2
[#1258] Add function for escaping characters
vaszig Mar 27, 2023
6e33ba6
Merge pull request #557 from maykinmedia/fix/1027-fix-2factor-layout
alextreme Mar 27, 2023
4c27434
Merge pull request #555 from maykinmedia/fix/1253-hide-cases-result-f…
alextreme Mar 27, 2023
93846c6
Merge pull request #550 from maykinmedia/fix/1248-redirect-to-initial…
alextreme Mar 27, 2023
6eed780
Merge pull request #552 from maykinmedia/fix/1231-fix-breadcrumbs-in-…
alextreme Mar 27, 2023
78db5ce
[#1274] Downgraded ZGW role-retrieval's error-level in notification h…
Mar 27, 2023
1c851d7
[#1258] Fixed duplicate variable
vaszig Mar 27, 2023
66a56a2
[#1259] Changed axes and oidc cache to the default one
vaszig Mar 27, 2023
4487bdd
Merge pull request #559 from maykinmedia/fix/1274-silence-nrc-role-re…
alextreme Mar 27, 2023
d8a7f0f
Merge pull request #556 from maykinmedia/fix/1258-productlocation-pho…
alextreme Mar 27, 2023
558fd88
Merge pull request #527 from maykinmedia/feature/1177-new-plan-count
alextreme Mar 27, 2023
65bc4d9
Merge pull request #560 from maykinmedia/fix/1259-show-azure-login-on…
alextreme Mar 27, 2023
7f4462f
:art: [#1021] Split cards with images off to new template, make cards…
jiromaykin Mar 23, 2023
0e275da
:art: [#1021] Refactored card templates
jiromaykin Mar 27, 2023
6806072
:green_heart: Making test deterministic
alextreme Mar 27, 2023
0435f72
[#1268] Added style for disabled document upload button
vaszig Mar 28, 2023
39e7dc9
:art: [#1021] Refactored card templates to become more static
jiromaykin Mar 28, 2023
06eb6bb
:alien: [#1301] Modifying HC BRP HTTP header due to v2.0-beta vs v2.0…
alextreme Mar 29, 2023
880a7b9
Simplified error handling codestyle in ZGW fetch-functions
Mar 30, 2023
7ef810e
Simplified error handling codestyle in Haalcentraal fetch-functions
Mar 30, 2023
04727ce
Merge pull request #554 from maykinmedia/feature/1021-make-entire-pro…
alextreme Apr 2, 2023
0b06110
Merge pull request #562 from maykinmedia/fix/simpler-fetchers
alextreme Apr 2, 2023
a90a00e
Merge pull request #553 from maykinmedia/fix/1268-prevent-multiple-ca…
alextreme Apr 2, 2023
89e0c58
Create SECURITY.md
alextreme Apr 2, 2023
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
20 changes: 20 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Security Policy

## Reporting a Vulnerability

**Short version: please report security issues by emailing security@maykinmedia.nl.**

If you discover security issues in Open Inwoner or related projects under the same
organization, we request you to disclose these in a *responsible* way by e-mailing to
security@maykinmedia.nl.

It is extremely useful if you have a reproducible test case and/or clear steps on how to
reproduce the vulnerability.

Please do not report security issues on the public Github issue tracker, as this makes
it visible which exploits exist before a fix is available, potentially comprising a lot
of unprotected instances.

Once you’ve submitted an issue via email, you should receive an acknowledgment from a
member of the security team as soon as possible, and depending on the action to be taken,
you may receive further followup emails.
4 changes: 3 additions & 1 deletion src/log_outgoing_requests/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ class OutgoingRequestsLogAdmin(admin.ModelAdmin):
"timestamp",
"req_content_type",
"res_content_type",
"req_headers",
"res_headers",
"trace",
)
readonly_fields = fields
Expand All @@ -30,7 +32,7 @@ class OutgoingRequestsLogAdmin(admin.ModelAdmin):
"timestamp",
)
list_filter = ("method", "status_code", "hostname")
search_fields = ("params", "query_params", "hostname")
search_fields = ("url", "params", "hostname")
date_hierarchy = "timestamp"
show_full_result_count = False

Expand Down
7 changes: 7 additions & 0 deletions src/log_outgoing_requests/formatters.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,28 @@


class HttpFormatter(logging.Formatter):
def _formatHeaders(self, d):
return "\n".join(f"{k}: {v}" for k, v in d.items())

def formatMessage(self, record):
result = super().formatMessage(record)
if record.name == "requests":
result += textwrap.dedent(
"""
---------------- request ----------------
{req.method} {req.url}
{reqhdrs}

---------------- response ----------------
{res.status_code} {res.reason} {res.url}
{reshdrs}

"""
).format(
req=record.req,
res=record.res,
reqhdrs=self._formatHeaders(record.req.headers),
reshdrs=self._formatHeaders(record.res.headers),
)

return result
11 changes: 10 additions & 1 deletion src/log_outgoing_requests/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,15 @@ def emit(self, record):

# save only the requests coming from the library requests
if record and record.getMessage() == "Outgoing request":
safe_req_headers = record.req.headers.copy()

if "Authorization" in safe_req_headers:
safe_req_headers["Authorization"] = "***hidden***"

if record.exc_info:
trace = traceback.format_exc()

parsed_url = urlparse(record.req.url)

kwargs = {
"url": record.req.url,
"hostname": parsed_url.hostname,
Expand All @@ -29,7 +33,12 @@ def emit(self, record):
"res_content_type": record.res.headers.get("Content-Type", ""),
"timestamp": record.requested_at,
"response_ms": int(record.res.elapsed.total_seconds() * 1000),
"req_headers": self.format_headers(safe_req_headers),
"res_headers": self.format_headers(record.res.headers),
"trace": trace,
}

OutgoingRequestsLog.objects.create(**kwargs)

def format_headers(self, headers):
return "\n".join(f"{k}: {v}" for k, v in headers.items())
2 changes: 1 addition & 1 deletion src/log_outgoing_requests/log_requests.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def install_outgoing_requests_logging():
Session._original_request = Session.request

def new_request(self, *args, **kwargs):
kwargs.setdefault("hooks", {"response": hook_requests_logging})
self.hooks["response"].append(hook_requests_logging)
return self._original_request(*args, **kwargs)

Session.request = new_request
33 changes: 33 additions & 0 deletions src/log_outgoing_requests/migrations/0003_auto_20230321_0724.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Generated by Django 3.2.15 on 2023-03-21 06:24

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("log_outgoing_requests", "0002_alter_outgoingrequestslog_url"),
]

operations = [
migrations.AddField(
model_name="outgoingrequestslog",
name="req_headers",
field=models.TextField(
blank=True,
help_text="The request headers.",
null=True,
verbose_name="Request headers",
),
),
migrations.AddField(
model_name="outgoingrequestslog",
name="res_headers",
field=models.TextField(
blank=True,
help_text="The response headers.",
null=True,
verbose_name="Response headers",
),
),
]
21 changes: 19 additions & 2 deletions src/log_outgoing_requests/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ class OutgoingRequestsLog(models.Model):
default="",
help_text=_("The url of the outgoing request."),
)

# hostname is added so we can filter on it in the admin page
hostname = models.CharField(
verbose_name=_("Hostname"),
max_length=255,
Expand Down Expand Up @@ -52,6 +54,18 @@ class OutgoingRequestsLog(models.Model):
blank=True,
help_text=_("The content type of the response."),
)
req_headers = models.TextField(
verbose_name=_("Request headers"),
blank=True,
null=True,
help_text=_("The request headers."),
)
res_headers = models.TextField(
verbose_name=_("Response headers"),
blank=True,
null=True,
help_text=_("The response headers."),
)
response_ms = models.PositiveIntegerField(
verbose_name=_("Response in ms"),
default=0,
Expand Down Expand Up @@ -79,6 +93,9 @@ def __str__(self):
)

@cached_property
def url_parsed(self):
return urlparse(self.url)

@property
def query_params(self):
parsed_url = urlparse(self.url)
return parsed_url.query
return self.url_parsed.query
51 changes: 45 additions & 6 deletions src/log_outgoing_requests/tests/test_logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ def _setUpMocks(self, m):
content=b"some content",
)

@override_settings(LOG_OUTGOING_REQUESTS_DB_SAVE=True)
def test_outgoing_requests_are_logged(self, m):
self._setUpMocks(m)

Expand All @@ -30,9 +31,8 @@ def test_outgoing_requests_are_logged(self, m):

@override_settings(LOG_OUTGOING_REQUESTS_DB_SAVE=True)
def test_expected_data_is_saved_when_saving_enabled(self, m):
self._setUpMocks(m)

methods = [
("GET", requests.get, m.get),
("POST", requests.post, m.post),
("PUT", requests.put, m.put),
("PATCH", requests.patch, m.patch),
Expand All @@ -45,10 +45,31 @@ def test_expected_data_is_saved_when_saving_enabled(self, m):
mocked(
"http://example.com/some-path?version=2.0",
status_code=200,
content=b"some content",
json={"test": "data"},
request_headers={
"Authorization": "test",
"Content-Type": "text/html",
},
headers={
"Date": "Tue, 21 Mar 2023 15:24:08 GMT",
"Content-Type": "application/json",
},
)
expected_req_headers = (
"User-Agent: python-requests/2.26.0\n"
"Accept-Encoding: gzip, deflate, br\n"
"Accept: */*\n"
"Connection: keep-alive\n"
"Authorization: ***hidden***\n"
"Content-Type: text/html"
)
if method not in ["HEAD", "GET"]:
expected_req_headers += "\nContent-Length: 0"

response = func("http://example.com/some-path?version=2.0")
response = func(
"http://example.com/some-path?version=2.0",
headers={"Authorization": "test", "Content-Type": "text/html"},
)

request_log = OutgoingRequestsLog.objects.last()

Expand All @@ -60,15 +81,33 @@ def test_expected_data_is_saved_when_saving_enabled(self, m):
self.assertEqual(request_log.query_params, "version=2.0")
self.assertEqual(response.status_code, 200)
self.assertEqual(request_log.method, method)
self.assertEqual(request_log.req_content_type, "")
self.assertEqual(request_log.res_content_type, "")
self.assertEqual(request_log.req_content_type, "text/html")
self.assertEqual(request_log.res_content_type, "application/json")
self.assertEqual(request_log.response_ms, 0)
self.assertEqual(request_log.req_headers, expected_req_headers)
self.assertEqual(
request_log.res_headers,
"Date: Tue, 21 Mar 2023 15:24:08 GMT\nContent-Type: application/json",
)
self.assertEqual(
request_log.timestamp.strftime("%Y-%m-%d %H:%M:%S"),
"2021-10-18 13:00:00",
)
self.assertIsNone(request_log.trace)

@override_settings(LOG_OUTGOING_REQUESTS_DB_SAVE=True)
def test_authorization_header_is_hidden(self, m):
self._setUpMocks(m)

requests.get(
"http://example.com/some-path?version=2.0",
headers={"Authorization": "test"},
)
log = OutgoingRequestsLog.objects.get()

self.assertIn("Authorization: ***hidden***", log.req_headers)

@override_settings(LOG_OUTGOING_REQUESTS_DB_SAVE=False)
def test_data_is_not_saved_when_saving_disabled(self, m):
self._setUpMocks(m)

Expand Down
11 changes: 11 additions & 0 deletions src/open_inwoner/accounts/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
validate_phone_number,
)

from ..plans.models import PlanContact
from .choices import ContactTypeChoices, LoginTypeChoices, StatusChoices, TypeChoices
from .managers import ActionQueryset, DigidManager, UserManager, eHerkenningManager
from .query import InviteQuerySet, MessageQuerySet
Expand Down Expand Up @@ -284,6 +285,16 @@ def is_email_of_contact(self, email):
or self.contacts_for_approval.filter(email=email).exists()
)

def get_plan_contact_new_count(self):
return (
PlanContact.objects.filter(user=self, notify_new=True)
.exclude(plan__created_by=self)
.count()
)

def clear_plan_contact_new_count(self):
PlanContact.objects.filter(user=self).update(notify_new=False)

def is_digid_and_brp(self) -> bool:
"""
Returns whether user is logged in with digid and data has
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

{% block content %}

<div class="registration-grid">
{% render_grid %}
{% render_column span=9 %}
{% render_card tinted=True %}
Expand All @@ -11,5 +12,6 @@ <h1 class="h1">{% trans "Registratie voltooien" %}</h1><br>
{% endrender_card %}
{% endrender_column %}
{% endrender_grid %}
</div>

{% endblock content %}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

{% block content %}

<div class="registration-grid">
{% render_grid %}
{% render_column start=5 span=5 %}
{% render_card direction='horizontal' tinted=True %}
Expand All @@ -23,5 +24,6 @@ <h1 class="h3">{% trans "Registreren met E-mail" %}</h1><br>
{% endif %}

{% endrender_grid %}
</div>

{% endblock content %}
15 changes: 12 additions & 3 deletions src/open_inwoner/accounts/templates/registration/login.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@


{% block content %}
<div class="login-grid">
{% render_grid %}
{% render_column start=5 span=5 %}
{% render_card %}
Expand All @@ -21,10 +22,13 @@ <h1 class="h1">{% trans 'Welkom' %}</h1>
<a href="{% url 'digid:login' %}" class="link digid-logo" aria-describedby="Digid logo" title="Digid logo">
<img class="digid-logo__image" src="{% static 'accounts/digid_logo.svg' %}" alt="Digid logo">
</a>
{% link href='digid:login' text=_('Inloggen met DigiD') secondary=True icon='arrow_forward' extra_classes="link--digid" %}
{% url 'digid:login' as href %}
{% with href|addnexturl:next as href_with_next %}
{% link href=href_with_next text=_('Inloggen met DigiD') secondary=True icon='arrow_forward' extra_classes="link--digid" %}
{% endwith %}
{% endrender_card %}
{% endif %}

{% get_solo 'mozilla_django_oidc_db.OpenIDConnectConfig' as oidc_config %}
{% get_solo 'configurations.SiteConfiguration' as site_config %}
{% if oidc_config.enabled %}
Expand All @@ -36,14 +40,18 @@ <h1 class="h1">{% trans 'Welkom' %}</h1>
{% else %}
<div></div>
{% endif %}
{% link text=site_config.openid_connect_login_text href='oidc_authentication_init' secondary=True icon='arrow_forward' icon_position="after" %}
{% url 'oidc_authentication_init' as href %}
{% with href|addnexturl:next as href_with_next %}
{% link text=site_config.openid_connect_login_text href=href_with_next secondary=True icon='arrow_forward' icon_position="after" %}
{% endwith %}
{% endrender_card %}
{% endif %}

{% if login_allow_registration %}
{% render_card tinted=True %}
{% render_form id="login-form" method="POST" form=form %}
{% csrf_token %}
<input type="hidden" name="next" value="{{next}}" />
{% input form.username %}
{% input form.password %}
{% button text=_('Wachtwoord vergeten?') href='password_reset' secondary=True transparent=True align='right' %}
Expand All @@ -54,4 +62,5 @@ <h1 class="h1">{% trans 'Welkom' %}</h1>
{% endrender_card %}
{% endrender_column %}
{% endrender_grid %}
</div>
{% endblock content %}
6 changes: 6 additions & 0 deletions src/open_inwoner/accounts/tests/test_action_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,12 @@ def test_action_history(self):
self.assertEqual(response.status_code, 200)
self.assertContains(response, self.action.name)

def test_action_history_breadcrumbs(self):
response = self.app.get(self.history_url, user=self.user)
crumbs = response.pyquery(".breadcrumbs__list-item")
self.assertIn(_("Mijn profiel"), crumbs[1].text_content())
self.assertIn(_("Mijn acties"), crumbs[2].text_content())

def test_action_history_not_your_action(self):
other_user = UserFactory()
self.app.get(self.history_url, user=other_user, status=404)
Expand Down
Loading