Skip to content
Snippets Groups Projects
Commit 58d5c631 authored by Tomáš Valenta's avatar Tomáš Valenta
Browse files

Merge branch 'test' of gitlab.pirati.cz:/to/contract-registry

parents 1faf65b3 777e77a5
Branches
No related tags found
No related merge requests found
Pipeline #13278 passed
......@@ -43,6 +43,8 @@ RUN DATABASE_URL=postgres://x/x \
DEFAULT_CONTRACTEE_DISTRICT=x \
DEFAULT_CONTRACTEE_ICO_NUMBER=x \
DEFAULT_STAFF_GROUPS=x \
NASTENKA_API_URL=x \
NASTENKA_API_TOKEN=x \
python manage.py collectstatic --noinput --settings=registry.settings.production
RUN bash -c "adduser --disabled-login --quiet --gecos app app && \
......
import copy
import json
import logging
import typing
import requests
from admin_auto_filters.filters import AutocompleteFilterFactory
from django.conf import settings
from django.contrib import admin
from django.contrib.auth.models import Permission
from django.db import models
......@@ -33,6 +37,8 @@ from .models import (
SigneeSignatureRepresentative,
)
logger = logging.getLogger()
class IndexHiddenModelAdmin(MarkdownxGuardedModelAdmin):
def has_module_permission(self, request):
......@@ -314,6 +320,8 @@ class ContractAdmin(
return queryset
def save_model(self, request, obj, form, change):
is_new = obj.created_by is None
# Need to generate primary keys first
parent_save_response = super().save_model(request, obj, form, change)
......@@ -333,6 +341,40 @@ class ContractAdmin(
obj.valid_start_date = last_signature_date
from users.models import User
if is_new:
try:
sso_ids = []
for user in User.objects.filter(is_staff=True).all():
if user.is_superuser or user.has_perm("contracts.approve"):
sso_ids.append(user.sso_id)
requests.post(
settings.NASTENKA_API_URL,
data=json.dumps(
{
"name": f"Nová smlouva ke schválení - {obj.name}",
"description": (
obj.summary
if obj.summary is not None
else "Bez popisu."
),
"contract_id": obj.id,
"sso_ids": sso_ids,
}
),
headers={
"Authorization": f"Token {settings.NASTENKA_API_TOKEN}",
"Content-Type": "application/json",
},
)
except Exception as exception:
logger.error(
"Failed to synchronizace Nástěnka notices: %s", str(exception)
)
return parent_save_response
def has_change_permission(self, request, obj=None):
......
......@@ -4,15 +4,19 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('contracts', '0061_alter_contract_id_number'),
("contracts", "0061_alter_contract_id_number"),
]
operations = [
migrations.AddField(
model_name='contract',
name='paper_form_person_responsible',
field=models.CharField(blank=True, max_length=256, null=True, verbose_name='Osoba zodpovědná za doručení'),
model_name="contract",
name="paper_form_person_responsible",
field=models.CharField(
blank=True,
max_length=256,
null=True,
verbose_name="Osoba zodpovědná za doručení",
),
),
]
......@@ -747,10 +747,11 @@ class Contract(NameStrMixin, models.Model):
)
if (
self.paper_form_state not in (
self.paper_form_state
not in (
self.PaperFormStates.STORED,
self.PaperFormStates.SHREDDED,
self.PaperFormStates.LOST
self.PaperFormStates.LOST,
)
and not self.paper_form_person_responsible
):
......
<div class="hidden md:block">
<table class="table table-auto w-full table--striped table--bordered">
<thead>
<tr>
<td class="font-bold">Název</td>
<td>Typy</td>
<td>Platná</td>
<td class="whitespace-nowrap">Účinná od</td>
<td class="whitespace-nowrap">Účinná do</td>
<td class="whitespace-nowrap">Podepsána s</td>
</tr>
</thead>
<tbody>
{% for contract in page %}
<tr>
<td{% if not contract.is_public %} class="!bg-red-100"{% endif %}>
{% if not contract.is_public %}
{% include "contracts/includes/private_info_icon.html" %}
{% endif %}
<a
class="underline"
href="{% url "contracts:view_contract" contract.id %}"
>{{ contract.name }}</a>
</td>
<td{% if not contract.is_public %} class="!bg-red-100"{% endif %}>
<ul class="flex flex-wrap gap-1.5">
{% for type in contract.types.all %}
<li class="flex">
{% include "contracts/includes/tag.html" with url=type.url icon="ico--folder" content=type.name public=contract.is_public %}
</li>
{% endfor %}
</ul>
</td>
<td{% if not contract.is_public %} class="!bg-red-100"{% endif %}>
<i
class="{% if contract.is_valid %}ico--checkmark{% else %}ico--cross{% endif %}"
aria-label="{% if contract.is_public %}Ano{% else %}Ne{% endif %}"
></i>
</td>
<td class="whitespace-nowrap{% if not contract.is_public %} !bg-red-100{% endif %}">
{{ contract.valid_start_date }}
</td>
<td class="whitespace-nowrap{% if not contract.is_public %} !bg-red-100{% endif %}">
{% if contract.valid_end_date %}
{{ contract.valid_end_date }}
{% else %}
<span class="text-grey-200">Neurčité</span>
{% endif %}
</td>
<td{% if not contract.is_public %} class="!bg-red-100"{% endif %}>
<ul class="flex flex-wrap gap-1.5">
{% for signature in contract.signee_signatures.all %}
<li class="flex">
{% if signature.signee.entity_type == signature.signee.EntityTypes.LEGAL_ENTITY or signature.signee.entity_type == signature.signee.EntityTypes.OTHER %}
{% include "contracts/includes/tag.html" with url=signature.signee.url icon="ico--office" content=signature.signee.name public=contract.is_public %}
{% else %}
{% include "contracts/includes/tag.html" with url=signature.signee.url icon="ico--user" content=signature.signee.name public=contract.is_public %}
{% endif %}
</li>
{% endfor %}
</ul>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<ul class="flex-col gap-4 flex md:hidden">
<ul class="flex-col gap-4 flex">
{% for contract in page %}
<li class="card elevation-10{% if not contract.is_public %} bg-red-100{% endif %}">
<div class="card__body p-5">
......@@ -96,7 +28,11 @@
<tr>
<td class="pt-1.5">Účinná od:</td>
<td class="pt-1.5">
{% if contract.valid_start_date %}
{{ contract.valid_start_date }}
{% else %}
<span class="text-grey-200">Neurčité</span>
{% endif %}
</td>
</tr>
<tr>
......
......@@ -20,3 +20,6 @@ DEFAULT_CONTRACTEE_DISTRICT="Praha 2"
DEFAULT_CONTRACTEE_ICO_NUMBER="71339698"
DEFAULT_STAFF_GROUPS="sso_cen:f,sso_cen:neverejni,sso_cen:smlouvy_ao,sso_cen:smlouvy_po,sso_cen:registr_smluv"
NASTENKA_API_URL=http://localhost:8009/contracts/api/notices
NASTENKA_API_TOKEN=cirno
......@@ -53,6 +53,7 @@ class RegistryOIDCAuthenticationBackend(PiratesOIDCAuthenticationBackend):
access_token, options={"verify_signature": False}
)
user.preferred_username = decoded_access_token["preferred_username"]
user_groups = user.groups.all()
self._remove_old_user_groups(
......
......@@ -244,6 +244,9 @@ if SENTRY_DSN != "":
## App-specific
NASTENKA_API_URL = env.str("NASTENKA_API_URL")
NASTENKA_API_TOKEN = env.str("NASTENKA_API_TOKEN")
DEFAULT_CONTRACTEE_NAME = env.str("DEFAULT_CONTRACTEE_NAME")
DEFAULT_CONTRACTEE_STREET = env.str("DEFAULT_CONTRACTEE_STREET")
DEFAULT_CONTRACTEE_ZIP = env.str("DEFAULT_CONTRACTEE_ZIP")
......
......@@ -21,3 +21,4 @@ Markdown==3.4.3
postal==1.1.10
PyJWT==2.6.0
PyYAML==6.0
requests==2.31.0
# Generated by Django 4.1.4 on 2023-06-15 05:52
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("users", "0003_alter_user_is_staff_based_on_group"),
]
operations = [
migrations.AddField(
model_name="user",
name="preferred_username",
field=models.CharField(
blank=True,
max_length=64,
null=True,
verbose_name="Username v Chobotnici",
),
),
migrations.AlterField(
model_name="user",
name="sso_id",
field=models.CharField(max_length=128, verbose_name="SSO ID"),
),
]
import uuid
from django.conf import settings
from django.contrib.auth.models import Group as AuthGroup
from django.contrib.auth.models import Permission
......@@ -18,6 +20,18 @@ class Group:
class User(pirates_models.AbstractUser):
preferred_username = models.CharField(
max_length=64,
verbose_name="Username v Chobotnici",
blank=True,
null=True,
)
sso_id = models.CharField(
"SSO ID",
max_length=128,
)
is_staff_based_on_group = models.BooleanField(
default=True,
verbose_name="Administrační přístup dle členství ve skupině",
......@@ -28,6 +42,8 @@ class User(pirates_models.AbstractUser):
),
)
USERNAME_FIELD = "preferred_username"
@property
def can_approve_contracts(self) -> bool:
return self.has_perm("contracts.approve")
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment