parent
8b1e0f74bb
commit
09ab83d1e4
4 changed files with 111 additions and 2 deletions
|
|
@ -0,0 +1,42 @@
|
|||
{% extends "frontend/base.html" %}
|
||||
{% load i18n %}
|
||||
{% block html_title %}
|
||||
{% block page_title %}
|
||||
{% translate "Accept Organization Invitation" %}
|
||||
{% endblock page_title %}
|
||||
{% endblock html_title %}
|
||||
{% block content %}
|
||||
<section class="section">
|
||||
<div class="card">
|
||||
<div class="card-content">
|
||||
<div class="card-body">
|
||||
<div class="alert alert-info">
|
||||
<i class="bi bi-info-circle"></i>
|
||||
{% blocktranslate with org_name=invitation.organization.name role=invitation.get_role_display %}
|
||||
You have been invited to join <strong>{{ org_name }}</strong> as a <strong>{{ role }}</strong>.
|
||||
{% endblocktranslate %}
|
||||
</div>
|
||||
{% if user.email|lower != invitation.email|lower %}
|
||||
<div class="alert alert-warning">
|
||||
<i class="bi bi-exclamation-triangle"></i>
|
||||
{% blocktranslate with invitation_email=invitation.email user_email=user.email %}
|
||||
<strong>Note:</strong> This invitation was sent to <strong>{{ invitation_email }}</strong>,
|
||||
but you are currently logged in as <strong>{{ user_email }}</strong>.
|
||||
{% endblocktranslate %}
|
||||
</div>
|
||||
{% endif %}
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
<div class="d-flex justify-content-end gap-2">
|
||||
<a href="{% url 'frontend:organization.selection' %}"
|
||||
class="btn btn-secondary">{% translate "Cancel" %}</a>
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<i class="bi bi-check-circle"></i> {% translate "Accept Invitation" %}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
{% endblock content %}
|
||||
|
|
@ -6,6 +6,11 @@ from servala.frontend import views
|
|||
urlpatterns = [
|
||||
path("accounts/profile/", views.ProfileView.as_view(), name="profile"),
|
||||
path("accounts/logout/", views.LogoutView.as_view(), name="logout"),
|
||||
path(
|
||||
"invitations/<str:secret>/accept/",
|
||||
views.InvitationAcceptView.as_view(),
|
||||
name="invitation.accept",
|
||||
),
|
||||
path(
|
||||
"organizations/",
|
||||
views.OrganizationSelectionView.as_view(),
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ from .generic import (
|
|||
custom_500,
|
||||
)
|
||||
from .organization import (
|
||||
InvitationAcceptView,
|
||||
OrganizationCreateView,
|
||||
OrganizationDashboardView,
|
||||
OrganizationUpdateView,
|
||||
|
|
@ -25,6 +26,7 @@ from .support import SupportView
|
|||
|
||||
__all__ = [
|
||||
"IndexView",
|
||||
"InvitationAcceptView",
|
||||
"LogoutView",
|
||||
"OrganizationCreateView",
|
||||
"OrganizationDashboardView",
|
||||
|
|
|
|||
|
|
@ -1,11 +1,17 @@
|
|||
from django.shortcuts import redirect
|
||||
from django.contrib import messages
|
||||
from django.shortcuts import get_object_or_404, redirect
|
||||
from django.urls import reverse
|
||||
from django.utils import timezone
|
||||
from django.utils.decorators import method_decorator
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.views.generic import CreateView, DetailView
|
||||
from django.views.generic import CreateView, DetailView, TemplateView
|
||||
from django_scopes import scopes_disabled
|
||||
from rules.contrib.views import AutoPermissionRequiredMixin
|
||||
|
||||
from servala.core.models import (
|
||||
BillingEntity,
|
||||
Organization,
|
||||
OrganizationInvitation,
|
||||
OrganizationMembership,
|
||||
ServiceInstance,
|
||||
)
|
||||
|
|
@ -103,3 +109,57 @@ class OrganizationUpdateView(OrganizationViewMixin, HtmxUpdateView):
|
|||
|
||||
def get_success_url(self):
|
||||
return self.request.path
|
||||
|
||||
|
||||
@method_decorator(scopes_disabled(), name="dispatch")
|
||||
class InvitationAcceptView(TemplateView):
|
||||
template_name = "frontend/organizations/invitation_accept.html"
|
||||
|
||||
def get_invitation(self):
|
||||
secret = self.kwargs.get("secret")
|
||||
return get_object_or_404(OrganizationInvitation, secret=secret)
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
invitation = self.get_invitation()
|
||||
|
||||
if invitation.is_accepted:
|
||||
messages.warning(
|
||||
request,
|
||||
_("This invitation has already been accepted."),
|
||||
)
|
||||
return redirect("frontend:organization.selection")
|
||||
if not request.user.is_authenticated:
|
||||
request.session["invitation_next"] = request.path
|
||||
messages.info(
|
||||
request,
|
||||
_("Please log in or sign up to accept this invitation."),
|
||||
)
|
||||
return redirect(f"{reverse('account_login')}?next={request.path}")
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context["invitation"] = self.get_invitation()
|
||||
return context
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
invitation = self.get_invitation()
|
||||
invitation.accepted_by = request.user
|
||||
invitation.accepted_at = timezone.now()
|
||||
invitation.save()
|
||||
|
||||
OrganizationMembership.objects.get_or_create(
|
||||
user=request.user,
|
||||
organization=invitation.organization,
|
||||
defaults={"role": invitation.role},
|
||||
)
|
||||
|
||||
messages.success(
|
||||
request,
|
||||
_("You have successfully joined {organization}!").format(
|
||||
organization=invitation.organization.name
|
||||
),
|
||||
)
|
||||
|
||||
request.session.pop("invitation_next", None)
|
||||
return redirect(invitation.organization.urls.base)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue