From 69efef67a8cce81867db26cd5103136435eb84e5 Mon Sep 17 00:00:00 2001 From: KlemenSpruk Date: Fri, 13 Oct 2023 11:08:55 +0200 Subject: [PATCH 1/5] #620 User workflow: create new account (#142) * saving * addes todos * read function for sending email from settings * use system sender id * read sms sender for system notifications * throttlinh for system notifications * check code * delete cookie after login, show errors * pr fix --- django_project_base/account/rest/account.py | 63 ++++++-- django_project_base/account/rest/login.py | 1 + django_project_base/account/rest/profile.py | 24 ++- .../account/service/register_user_service.py | 30 ++++ .../service/reset_password_email_service.py | 10 +- django_project_base/base/event.py | 3 + django_project_base/licensing/logic.py | 8 +- .../notifications/base/channels/channel.py | 6 +- .../notifications/base/notification.py | 11 ++ .../base/send_notification_mixin.py | 2 + .../notifications/email_notification.py | 55 +++++++ django_project_base/settings.py | 2 + vue/components/notifications-editor.vue | 3 +- vue/components/user-session/login-inline.vue | 151 +++++++++++++++++- 14 files changed, 332 insertions(+), 37 deletions(-) create mode 100644 django_project_base/account/service/register_user_service.py diff --git a/django_project_base/account/rest/account.py b/django_project_base/account/rest/account.py index 46a96fd2..220cf089 100644 --- a/django_project_base/account/rest/account.py +++ b/django_project_base/account/rest/account.py @@ -2,19 +2,24 @@ from typing import Optional import swapper -from django.contrib.auth import get_user_model, update_session_auth_hash +from django.contrib.auth import get_user_model, login, update_session_auth_hash from django.contrib.auth.models import AnonymousUser +from django.core.cache import cache +from django.core.exceptions import ValidationError as DjangoValidationError +from django.core.validators import validate_email from django.utils.translation import gettext_lazy as _ from drf_spectacular.utils import extend_schema, extend_schema_view, OpenApiParameter, OpenApiResponse, OpenApiTypes from dynamicforms import fields as df_fields, serializers as df_serializers, viewsets as df_viewsets from dynamicforms.action import Actions from rest_framework import fields, serializers, status, viewsets from rest_framework.decorators import action +from rest_framework.exceptions import PermissionDenied, ValidationError from rest_framework.permissions import IsAdminUser, IsAuthenticated from rest_framework.request import Request from rest_framework.response import Response from rest_framework.serializers import ModelSerializer -from rest_registration.api.views import change_password, logout, register, verify_registration +from rest_registration.api.views import change_password, logout, register +from rest_registration.settings import registration_settings from social_django.models import UserSocialAuth from django_project_base.account.rest.reset_password import ResetPasswordSerializer @@ -179,15 +184,7 @@ class SuperUserChangePasswordSerializer(ChangePasswordSerializer): return response -class VerifyRegistrationSerializer(serializers.Serializer): - user_id = fields.CharField(required=True) - timestamp = fields.IntegerField(required=True) - signature = fields.CharField(required=True) - - class VerifyRegistrationViewSet(viewsets.ViewSet): - serializer_class = VerifyRegistrationSerializer() - @extend_schema( description="Verify registration with signature. The endpoint will generate an e-mail with a confirmation URL " "which the user should GET to confirm the account.", @@ -199,11 +196,53 @@ class VerifyRegistrationViewSet(viewsets.ViewSet): @action( detail=False, methods=["post"], - url_path="verify_registration", + url_path="verify-registration", url_name="verify-registration", ) def verify_registration(self, request: Request) -> Response: - return verify_registration(request._request) + if ( + (flow_id := request.COOKIES.get("register-flow")) + and (code := cache.get(flow_id)) + and (req_code := request.data.get("code")) + and code == req_code + and len(code) + and len(req_code) + and (user := cache.get(code)) + ): + user.is_active = True + user.save(update_fields=["is_active"]) + login(request, user, backend="django_project_base.base.auth_backends.UsersCachingBackend") + response = Response() + response.delete_cookie("register-flow") + return response + raise ValidationError(dict(code=[_("Code invalid")])) + + @action( + detail=False, + methods=["post"], + url_path="verify-registration-email-change", + url_name="verify-registration-email-change", + ) + def verify_registration_change_email(self, request: Request) -> Response: + if ( + (flow_id := request.COOKIES.get("register-flow")) + and (code := cache.get(flow_id)) + and len(code) + and (user := cache.get(code)) + ): + email = request.data.get("email") + if not email: + raise ValidationError(dict(email=[_("Email invalid")])) + try: + validate_email(email) + except DjangoValidationError: + raise ValidationError(dict(email=[_("Email invalid")])) + user.email = email + user.save(update_fields=["email"]) + if registration_settings.REGISTER_VERIFICATION_ENABLED: + registration_settings.REGISTER_VERIFICATION_EMAIL_SENDER(request=request, user=user) + return Response() + raise PermissionDenied class AbstractRegisterSerializer(df_serializers.Serializer): diff --git a/django_project_base/account/rest/login.py b/django_project_base/account/rest/login.py index 44ffb874..99537b7e 100644 --- a/django_project_base/account/rest/login.py +++ b/django_project_base/account/rest/login.py @@ -104,4 +104,5 @@ def create(self, request: Request, *args, **kwargs) -> Response: and (user := get_user_model().objects.filter(pk=user_id).first()) ): UserLoginEvent(user=user).trigger(payload=request) + response.delete_cookie("register-flow") return response diff --git a/django_project_base/account/rest/profile.py b/django_project_base/account/rest/profile.py index 47696565..c0912807 100644 --- a/django_project_base/account/rest/profile.py +++ b/django_project_base/account/rest/profile.py @@ -1,4 +1,5 @@ import datetime +import uuid from random import randrange import django @@ -11,6 +12,7 @@ from django.db.models import ForeignKey, Model, QuerySet from django.template.loader import render_to_string from django.utils import timezone +from django.utils.crypto import get_random_string from django.utils.translation import gettext_lazy as _ from drf_spectacular.utils import extend_schema, extend_schema_view, OpenApiParameter, OpenApiResponse from dynamicforms import fields @@ -36,7 +38,10 @@ from django_project_base.account.rest.project_profiles_utils import get_project_members from django_project_base.base.event import UserRegisteredEvent from django_project_base.constants import NOTIFY_NEW_USER_SETTING_NAME -from django_project_base.notifications.email_notification import EMailNotification, EMailNotificationWithListOfEmails +from django_project_base.notifications.email_notification import ( + EMailNotificationWithListOfEmails, + SystemEMailNotification, +) from django_project_base.notifications.models import DjangoProjectBaseMessage from django_project_base.permissions import BasePermissions from django_project_base.rest.project import ProjectSerializer, ProjectViewSet @@ -327,7 +332,17 @@ def list(self, request, *args, **kwargs): permission_classes=[], ) def register_account(self, request: Request, **kwargs): - return Response(ProfileRegisterSerializer(None, context=self.get_serializer_context()).data) + register_flow_identifier = str(uuid.uuid4()) + response = Response(ProfileRegisterSerializer(None, context=self.get_serializer_context()).data) + response.set_cookie( + "register-flow", + register_flow_identifier, + max_age=settings.CONFIRMATION_CODE_TIMEOUT, + httponly=True, + samesite="Strict", + ) + cache.set(register_flow_identifier, get_random_string(length=6), timeout=settings.CONFIRMATION_CODE_TIMEOUT) + return response @extend_schema( description="Registering new account", @@ -342,7 +357,7 @@ def register_account(self, request: Request, **kwargs): def create_new_account(self, request: Request, **kwargs): # set default values request.data["date_joined"] = datetime.datetime.now() - request.data["is_active"] = True + request.data["is_active"] = False # call serializer to do the data processing drf way - hijack serializer = ProfileRegisterSerializer( @@ -592,7 +607,7 @@ def create(self, request, *args, **kwargs): .first() ) and sett.python_value: recipients = [response.data[get_pk_name(get_user_model())]] - EMailNotification( + SystemEMailNotification( message=DjangoProjectBaseMessage( subject=_("Your account was created for you"), body=render_to_string( @@ -604,7 +619,6 @@ def create(self, request, *args, **kwargs): footer="", content_type=DjangoProjectBaseMessage.HTML, ), - raw_recipents=recipients, project=project.slug, recipients=recipients, user=self.request.user.pk, diff --git a/django_project_base/account/service/register_user_service.py b/django_project_base/account/service/register_user_service.py new file mode 100644 index 00000000..93d1095e --- /dev/null +++ b/django_project_base/account/service/register_user_service.py @@ -0,0 +1,30 @@ +from django.conf import settings +from django.core.cache import cache +from django.utils.translation import gettext as __ +from natural.date import compress +from rest_framework.request import Request + +from django_project_base.notifications.email_notification import SystemEMailNotification +from django_project_base.notifications.models import DjangoProjectBaseMessage + + +def send_register_verification_email_notification( + request: Request, + user, +) -> None: + if (flow_id := request.COOKIES.get("register-flow")) and (code := cache.get(flow_id)): + SystemEMailNotification( + message=DjangoProjectBaseMessage( + subject=f"{__('Account confirmation for')} {request.META['HTTP_HOST']}", + body=f"{__('You or someone acting as you registered an account at')} " + f"{request.META['HTTP_HOST']}. " + f"\n\n{__('Your verification code is')}: " + f"{code} \n\n {__('Code is valid for')} {compress(settings.CONFIRMATION_CODE_TIMEOUT)}.\n\n" + f"{__('If this was not you or it was unintentional, you may safely ignore this message.')}", + footer="", + content_type=DjangoProjectBaseMessage.PLAIN_TEXT, + ), + recipients=[user.pk], + user=user.pk, + ).send() + cache.set(code, user, timeout=settings.CONFIRMATION_CODE_TIMEOUT) diff --git a/django_project_base/account/service/reset_password_email_service.py b/django_project_base/account/service/reset_password_email_service.py index 8b362d4e..871601ad 100644 --- a/django_project_base/account/service/reset_password_email_service.py +++ b/django_project_base/account/service/reset_password_email_service.py @@ -12,8 +12,7 @@ from rest_registration.utils.users import get_user_verification_id from django_project_base.account.constants import RESET_USER_PASSWORD_VERIFICATION_CODE -from django_project_base.notifications.base.enums import NotificationLevel, NotificationType as NotificationTypeDPB -from django_project_base.notifications.email_notification import EMailNotification +from django_project_base.notifications.email_notification import SystemEMailNotification from django_project_base.notifications.models import DjangoProjectBaseMessage @@ -31,7 +30,7 @@ def send_reset_password_verification_email(request: Request, user, send=False) - code = get_random_string(length=6) cache.set(code_ck, code, timeout=settings.CONFIRMATION_CODE_TIMEOUT) - EMailNotification( + SystemEMailNotification( message=DjangoProjectBaseMessage( subject=f"{__('Password recovery for')} {request.META['HTTP_HOST']}", body=f"{__('You or someone acting as you requested a password reset for your account at')} " @@ -42,11 +41,6 @@ def send_reset_password_verification_email(request: Request, user, send=False) - footer="", content_type=DjangoProjectBaseMessage.PLAIN_TEXT, ), - raw_recipents=[user.pk], - project=None, - persist=True, - level=NotificationLevel.INFO, - type=NotificationTypeDPB.STANDARD, recipients=[user.pk], user=request.user.pk, ).send() diff --git a/django_project_base/base/event.py b/django_project_base/base/event.py index 77b94e5d..93f98d50 100644 --- a/django_project_base/base/event.py +++ b/django_project_base/base/event.py @@ -4,6 +4,7 @@ import swapper from django.conf import settings from django.shortcuts import get_object_or_404 +from rest_registration.settings import registration_settings from django_project_base.constants import EMAIL_SENDER_ID_SETTING_NAME @@ -98,6 +99,8 @@ def trigger(self, payload=None, **kwargs): UserInviteFoundEvent(self.user).trigger(payload=invite, request=payload) return payload.session.pop("invite-pk", None) + if registration_settings.REGISTER_VERIFICATION_ENABLED: + registration_settings.REGISTER_VERIFICATION_EMAIL_SENDER(request=payload, user=self.user) class UserLoginEvent(BaseEvent): diff --git a/django_project_base/licensing/logic.py b/django_project_base/licensing/logic.py index b25d1e5d..5a87b8c3 100644 --- a/django_project_base/licensing/logic.py +++ b/django_project_base/licensing/logic.py @@ -93,10 +93,12 @@ def log( if not allowed_users: allowed_users = getattr(kwargs.get("settings", object()), "NOTIFICATIONS_ALLOWED_USERS", []) - if str(user_profile_pk) not in list(map(str, allowed_users)): + is_system_notification = kwargs.get("is_system_notification") + + if not is_system_notification and str(user_profile_pk) not in list(map(str, allowed_users)): raise PermissionDenied - if used >= MONTHLY_ACCESS_LIMIT_IN_CURRENCY_UNITS: # janez medja + if not is_system_notification and used >= MONTHLY_ACCESS_LIMIT_IN_CURRENCY_UNITS: # janez medja raise PermissionDenied(gettext("Your license is consumed. Please contact support.")) if on_sucess: @@ -112,7 +114,7 @@ def log( content_type_object_id=str(record.pk).replace("-", ""), content_type=content_type, amount=amount, - comment=dict(comment=comment, count=accesses_used, item_price=item_price), + comment=dict(comment=comment, count=accesses_used, item_price=item_price, sender=kwargs.get("sender", "")), ) return accesses_used diff --git a/django_project_base/notifications/base/channels/channel.py b/django_project_base/notifications/base/channels/channel.py index 8d8f5e95..6dc232d8 100644 --- a/django_project_base/notifications/base/channels/channel.py +++ b/django_project_base/notifications/base/channels/channel.py @@ -62,7 +62,8 @@ def _set_provider(self, val: ProviderIntegration): def sender(self, notification: DjangoProjectBaseNotification) -> str: _sender = getattr(notification, "sender", {}).get(self.name) - assert _sender, "Notification sender is required" + if not getattr(settings, "TESTING", False): + assert _sender, "Notification sender is required" return _sender def _find_provider( @@ -135,7 +136,8 @@ def send(self, notification: DjangoProjectBaseNotification, extra_data, **kwargs def make_send(notification_obj, rec_obj, message_str, dlr_pk) -> Optional[DeliveryReport]: try: - self.provider.client_send(self.sender(notification_obj), rec_obj, message_str, dlr_pk) + if not getattr(settings, "TESTING", False): + self.provider.client_send(self.sender(notification_obj), rec_obj, message_str, dlr_pk) sent = True except Exception as te: logger.exception(te) diff --git a/django_project_base/notifications/base/notification.py b/django_project_base/notifications/base/notification.py index b4a6dc1d..842f25d2 100644 --- a/django_project_base/notifications/base/notification.py +++ b/django_project_base/notifications/base/notification.py @@ -213,6 +213,10 @@ def _ensure_channels( for channel_name in channels: # ensure dlr user and check providers channel = ChannelIdentifier.channel(channel_name, extra_data=self._extra_data, project_slug=self._project) + + if not channel and self._extra_data.get("is_system_notification"): + continue + assert channel if self.send_notification_sms and channel.name == MailChannel.name: @@ -223,4 +227,11 @@ def _ensure_channels( notification.user = self._user notification.sender = Notification._get_sender_config(self._project) + + if self._extra_data.get("is_system_notification"): + notification.sender[MailChannel.name] = getattr(settings, "SYSTEM_EMAIL_SENDER_ID", "") + from django_project_base.notifications.base.channels.sms_channel import SmsChannel + + notification.sender[SmsChannel.name] = getattr(settings, "SYSTEM_SMS_SENDER_ID", "") + return notification diff --git a/django_project_base/notifications/base/send_notification_mixin.py b/django_project_base/notifications/base/send_notification_mixin.py index 3539ac8b..c769ca7d 100644 --- a/django_project_base/notifications/base/send_notification_mixin.py +++ b/django_project_base/notifications/base/send_notification_mixin.py @@ -72,6 +72,8 @@ def make_send(self, notification: DjangoProjectBaseNotification, extra_data) -> on_sucess=lambda: channel.send(notification, extra_data), db=db_connection, settings=extra_data.get("SETTINGS", object()), + is_system_notification=extra_data.get("is_system_notification"), + sender=channel.sender(notification), ) sent_channels.append(channel) if any_sent > 0 else failed_channels.append(channel) except Exception as e: diff --git a/django_project_base/notifications/email_notification.py b/django_project_base/notifications/email_notification.py index d9127820..6f5364e5 100644 --- a/django_project_base/notifications/email_notification.py +++ b/django_project_base/notifications/email_notification.py @@ -2,6 +2,9 @@ import uuid from typing import List, Optional, Type +from django.core.cache import cache +from rest_framework.exceptions import PermissionDenied + from django_project_base.notifications.base.channels.channel import Channel from django_project_base.notifications.base.channels.mail_channel import MailChannel from django_project_base.notifications.base.enums import NotificationLevel, NotificationType @@ -89,3 +92,55 @@ def send(self) -> DjangoProjectBaseNotification: ] self.enqueue_notification(notification, self._extra_data) return notification + + +class SystemEMailNotification(EMailNotification): + system_mail_throttling_ck = "system-mail-throttling-ck" + allowed_number_of_system_requests_per_minute = 5 + + def __init__( + self, + message: DjangoProjectBaseMessage, + recipients, + **kwargs, + ) -> None: + super().__init__( + message, + raw_recipents=recipients, + project=None, + persist=True, + level=None, + locale=None, + delay=int(datetime.datetime.now().timestamp()), + type=None, + recipients=recipients, + is_system_notification=True, + **kwargs, + ) + + def _get_system_email_cache_key(self) -> str: + return f"{self.system_mail_throttling_ck}-{datetime.datetime.now().minute}" + + def _get_system_email_cache_value(self) -> List[float]: + if ck_val := cache.get(self._get_system_email_cache_key()): + return ck_val + return [] + + def _check_request_limit(self): + if len(self._get_system_email_cache_value()) > self.allowed_number_of_system_requests_per_minute: + raise PermissionDenied + + def _register_system_email(self): + if ck_val := self._get_system_email_cache_value(): + if len(ck_val) > self.allowed_number_of_system_requests_per_minute + 1: + return + ck_val.append(datetime.datetime.now().timestamp()) + cache.set(self._get_system_email_cache_key(), ck_val, timeout=70) + return + cache.set(self._get_system_email_cache_key(), [datetime.datetime.now().timestamp()], timeout=70) + + def send(self) -> DjangoProjectBaseNotification: + # throttling for system messages + self._check_request_limit() + self._register_system_email() + return super().send() diff --git a/django_project_base/settings.py b/django_project_base/settings.py index 101e147a..80f2ed60 100644 --- a/django_project_base/settings.py +++ b/django_project_base/settings.py @@ -36,6 +36,8 @@ "RESET_PASSWORD_VERIFICATION_ENABLED": True, "RESET_PASSWORD_SERIALIZER_PASSWORD_CONFIRM": True, "SEND_RESET_PASSWORD_LINK_USER_FINDER": "django_project_base.account.service.reset_password_email_service.find_user_by_send_reset_password_link_data", # noqa: E501 + "REGISTER_VERIFICATION_ENABLED": True, + "REGISTER_VERIFICATION_EMAIL_SENDER": "django_project_base.account.service.register_user_service.send_register_verification_email_notification", # noqa: E501 }, }, {"name": "NOTIFICATION_SENDERS", "default": {}}, diff --git a/vue/components/notifications-editor.vue b/vue/components/notifications-editor.vue index 3354400b..fd79ca88 100644 --- a/vue/components/notifications-editor.vue +++ b/vue/components/notifications-editor.vue @@ -2,8 +2,7 @@ import { APIConsumer, ComponentDisplay, - ConsumerLogicApi, - FormConsumerApiOneShot, gettext, + ConsumerLogicApi, FormConsumerApiOneShot, gettext, useActionHandler, } from '@velis/dynamicforms'; import { onMounted, onUnmounted, ref } from 'vue'; diff --git a/vue/components/user-session/login-inline.vue b/vue/components/user-session/login-inline.vue index 0c2f5d82..7fe8b814 100644 --- a/vue/components/user-session/login-inline.vue +++ b/vue/components/user-session/login-inline.vue @@ -33,7 +33,7 @@ {{ gettext('Login') }} - {{ gettext('Register') }} + {{ gettext('Register') }} @@ -41,12 +41,15 @@ From 852df6b40c3aaf0f44fe9891a7b39a2b392ab5e9 Mon Sep 17 00:00:00 2001 From: KlemenSpruk Date: Fri, 13 Oct 2023 11:09:17 +0200 Subject: [PATCH 3/5] =?UTF-8?q?#727=20Sender=20email=20se=20ve=C4=8Dkrat?= =?UTF-8?q?=20po=C5=A1lje=20(#143)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * addes todos * send email to sender only once * updated js import --- .../notifications/base/channels/integrations/aws_ses.py | 4 ++-- .../notifications/base/channels/mail_channel.py | 9 +++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/django_project_base/notifications/base/channels/integrations/aws_ses.py b/django_project_base/notifications/base/channels/integrations/aws_ses.py index f4c9c9e9..73bc71bc 100644 --- a/django_project_base/notifications/base/channels/integrations/aws_ses.py +++ b/django_project_base/notifications/base/channels/integrations/aws_ses.py @@ -89,9 +89,9 @@ def client_send(self, sender: str, recipient: Recipient, msg: dict, dlr_id: str) .client("ses") .send_email( Destination={ - "ToAddresses": [sender], + "ToAddresses": [recipient.email], "CcAddresses": [], - "BccAddresses": [recipient.email], + "BccAddresses": [], }, Message=msg, Source=sender, diff --git a/django_project_base/notifications/base/channels/mail_channel.py b/django_project_base/notifications/base/channels/mail_channel.py index dc8d8a88..acf84481 100644 --- a/django_project_base/notifications/base/channels/mail_channel.py +++ b/django_project_base/notifications/base/channels/mail_channel.py @@ -1,3 +1,4 @@ +import uuid from typing import List from django.conf import settings @@ -24,6 +25,14 @@ def send(self, notification: DjangoProjectBaseNotification, extra_data, **kwargs list(map(int, notification.recipients.split(","))) if notification.recipients else [] ) return len(recipients) + message = self.provider.get_message(notification) + sender = self.sender(notification) + self.provider.client_send( + self.sender(notification), + Recipient(identifier=str(uuid.uuid4()), phone_number="", email=sender), + message, + str(uuid.uuid4()), + ) return super().send(notification=notification, extra_data=extra_data) def get_recipients(self, notification: DjangoProjectBaseNotification, unique_identifier=""): From a30d0f6612edbf23634e826b0dcdc9948d6f65f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jure=20Erzno=C5=BEnik?= Date: Fri, 13 Oct 2023 13:04:21 +0200 Subject: [PATCH 4/5] bump versions --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 100de7f3..25dabe21 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "export-pdf": "press-export-pdf --debug export docs" }, "peerDependencies": { - "@velis/dynamicforms": "^0.74.18", + "@velis/dynamicforms": "^0.74.21", "axios": "^1.2.0", "lodash": "^4.17.15", "pinia": "^2.0.33", From 184c4f720da7183a2d2e1ab5f44746e9e0c41e6b Mon Sep 17 00:00:00 2001 From: adamPrestor Date: Fri, 13 Oct 2023 13:13:36 +0200 Subject: [PATCH 5/5] Fix imports --- vue/components/notifications-editor.vue | 6 +++--- vue/components/user-session/login.ts | 4 ++-- vue/components/user-session/project-list.vue | 4 ++-- vue/components/user-session/user-profile.vue | 8 ++++---- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/vue/components/notifications-editor.vue b/vue/components/notifications-editor.vue index fd79ca88..63f4dcc9 100644 --- a/vue/components/notifications-editor.vue +++ b/vue/components/notifications-editor.vue @@ -2,7 +2,7 @@ import { APIConsumer, ComponentDisplay, - ConsumerLogicApi, FormConsumerApiOneShot, gettext, + ConsumerLogicApi, FormConsumerOneShotApi, gettext, useActionHandler, } from '@velis/dynamicforms'; import { onMounted, onUnmounted, ref } from 'vue'; @@ -49,12 +49,12 @@ const notificationLogic = ref(new ConsumerLogicApi( notificationLogic.value.getFullDefinition(); const actionViewLicense = async (): Promise => { - await FormConsumerApiOneShot({ url: licenseConsumerUrl, trailingSlash: licenseConsumerUrlTrailingSlash, pk: 'new' }); + await FormConsumerOneShotApi({ url: licenseConsumerUrl, trailingSlash: licenseConsumerUrlTrailingSlash, pk: 'new' }); return true; }; const actionAddNotification = async (): Promise => { - await FormConsumerApiOneShot({ + await FormConsumerOneShotApi({ url: consumerUrl, trailingSlash: consumerTrailingSlash, pk: 'new', diff --git a/vue/components/user-session/login.ts b/vue/components/user-session/login.ts index 224691e0..209d7eff 100644 --- a/vue/components/user-session/login.ts +++ b/vue/components/user-session/login.ts @@ -3,7 +3,7 @@ import { ConsumerLogicApi, dfModal as dfModalApi, dfModal, DialogSize, DisplayMode, - FilteredActions, FormConsumerApiOneShot, + FilteredActions, FormConsumerOneShotApi, FormPayload, gettext, } from '@velis/dynamicforms'; @@ -221,7 +221,7 @@ function useLogin() { socialAuth.value = formDef.payload.social_auth_providers; } - const openRegistration = async () => FormConsumerApiOneShot( + const openRegistration = async () => FormConsumerOneShotApi( { url: '/account/profile/register', trailingSlash: false }, ); diff --git a/vue/components/user-session/project-list.vue b/vue/components/user-session/project-list.vue index f3cddc19..66f32031 100644 --- a/vue/components/user-session/project-list.vue +++ b/vue/components/user-session/project-list.vue @@ -3,7 +3,7 @@ import { Action, apiClient, dfModal, - FormConsumerApiOneShot, + FormConsumerOneShotApi, FormPayload, } from '@velis/dynamicforms'; import slugify from 'slugify'; @@ -59,7 +59,7 @@ async function addNewProject() { } return false; }; - const addProjectModal = await FormConsumerApiOneShot( + const addProjectModal = await FormConsumerOneShotApi( { url: '/project', trailingSlash: false, diff --git a/vue/components/user-session/user-profile.vue b/vue/components/user-session/user-profile.vue index 74ae5363..1324a48d 100644 --- a/vue/components/user-session/user-profile.vue +++ b/vue/components/user-session/user-profile.vue @@ -1,5 +1,5 @@