Commit 08775551 authored by ibuler's avatar ibuler

[Update] Rename app

parent edce831e
...@@ -11,7 +11,7 @@ from ..models import LoginConfirmSetting ...@@ -11,7 +11,7 @@ from ..models import LoginConfirmSetting
from ..serializers import LoginConfirmSettingSerializer from ..serializers import LoginConfirmSettingSerializer
from .. import errors from .. import errors
__all__ = ['LoginConfirmSettingUpdateApi', 'UserOrderAcceptAuthApi'] __all__ = ['LoginConfirmSettingUpdateApi', 'UserTicketAcceptAuthApi']
logger = get_logger(__name__) logger = get_logger(__name__)
...@@ -30,27 +30,42 @@ class LoginConfirmSettingUpdateApi(UpdateAPIView): ...@@ -30,27 +30,42 @@ class LoginConfirmSettingUpdateApi(UpdateAPIView):
return s return s
class UserOrderAcceptAuthApi(APIView): class UserTicketAcceptAuthApi(APIView):
permission_classes = () permission_classes = ()
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
from orders.models import LoginConfirmOrder from tickets.models import LoginConfirmTicket
order_id = self.request.session.get("auth_order_id") ticket_id = self.request.session.get("auth_ticket_id")
logger.debug('Login confirm order id: {}'.format(order_id)) logger.debug('Login confirm ticket id: {}'.format(ticket_id))
if not order_id: if not ticket_id:
order = None ticket = None
else: else:
order = get_object_or_none(LoginConfirmOrder, pk=order_id) ticket = get_object_or_none(LoginConfirmTicket, pk=ticket_id)
try: try:
if not order: if not ticket:
raise errors.LoginConfirmOrderNotFound(order_id) raise errors.LoginConfirmTicketNotFound(ticket_id)
if order.status == order.STATUS_ACCEPTED: if ticket.action == LoginConfirmTicket.ACTION_APPROVE:
self.request.session["auth_confirm"] = "1" self.request.session["auth_confirm"] = "1"
return Response({"msg": "ok"}) return Response({"msg": "ok"})
elif order.status == order.STATUS_REJECTED: elif ticket.action == LoginConfirmTicket.ACTION_REJECT:
raise errors.LoginConfirmRejectedError(order_id) raise errors.LoginConfirmRejectedError(ticket_id)
else: else:
raise errors.LoginConfirmWaitError(order_id) raise errors.LoginConfirmWaitError(ticket_id)
except errors.AuthFailedError as e: except errors.AuthFailedError as e:
data = e.as_data() data = e.as_data()
return Response(data, status=400) return Response(data, status=400)
class UserTicketCancelAuthApi(APIView):
permission_classes = ()
def get(self, request, *args, **kwargs):
from tickets.models import LoginConfirmTicket
ticket_id = self.request.session.get("auth_ticket_id")
logger.debug('Login confirm ticket id: {}'.format(ticket_id))
if not ticket_id:
ticket = None
else:
ticket = get_object_or_none(LoginConfirmTicket, pk=ticket_id)
if not ticket:
ticket.status = "close"
...@@ -47,9 +47,9 @@ mfa_failed_msg = _("MFA code invalid, or ntp sync server time") ...@@ -47,9 +47,9 @@ mfa_failed_msg = _("MFA code invalid, or ntp sync server time")
mfa_required_msg = _("MFA required") mfa_required_msg = _("MFA required")
login_confirm_required_msg = _("Login confirm required") login_confirm_required_msg = _("Login confirm required")
login_confirm_wait_msg = _("Wait login confirm order for accept") login_confirm_wait_msg = _("Wait login confirm ticket for accept")
login_confirm_rejected_msg = _("Login confirm order was rejected") login_confirm_rejected_msg = _("Login confirm ticket was rejected")
login_confirm_order_not_found_msg = _("Order not found") login_confirm_ticket_not_found_msg = _("Ticket not found")
class AuthFailedNeedLogMixin: class AuthFailedNeedLogMixin:
...@@ -155,8 +155,8 @@ class LoginConfirmError(AuthFailedError): ...@@ -155,8 +155,8 @@ class LoginConfirmError(AuthFailedError):
msg = login_confirm_wait_msg msg = login_confirm_wait_msg
error = 'login_confirm_wait' error = 'login_confirm_wait'
def __init__(self, order_id, **kwargs): def __init__(self, ticket_id, **kwargs):
self.order_id = order_id self.ticket_id = ticket_id
super().__init__(**kwargs) super().__init__(**kwargs)
def as_data(self): def as_data(self):
...@@ -164,7 +164,7 @@ class LoginConfirmError(AuthFailedError): ...@@ -164,7 +164,7 @@ class LoginConfirmError(AuthFailedError):
"error": self.error, "error": self.error,
"msg": self.msg, "msg": self.msg,
"data": { "data": {
"order_id": self.order_id "ticket_id": self.ticket_id
} }
} }
...@@ -179,6 +179,6 @@ class LoginConfirmRejectedError(LoginConfirmError): ...@@ -179,6 +179,6 @@ class LoginConfirmRejectedError(LoginConfirmError):
error = 'login_confirm_rejected' error = 'login_confirm_rejected'
class LoginConfirmOrderNotFound(LoginConfirmError): class LoginConfirmTicketNotFound(LoginConfirmError):
msg = login_confirm_order_not_found_msg msg = login_confirm_ticket_not_found_msg
error = 'login_confirm_order_not_found' error = 'login_confirm_ticket_not_found'
...@@ -91,30 +91,30 @@ class AuthMixin: ...@@ -91,30 +91,30 @@ class AuthMixin:
raise errors.MFAFailedError(username=user.username, request=self.request) raise errors.MFAFailedError(username=user.username, request=self.request)
def check_user_login_confirm_if_need(self, user): def check_user_login_confirm_if_need(self, user):
from orders.models import LoginConfirmOrder from tickets.models import LoginConfirmTicket
confirm_setting = user.get_login_confirm_setting() confirm_setting = user.get_login_confirm_setting()
if self.request.session.get('auth_confirm') or not confirm_setting: if self.request.session.get('auth_confirm') or not confirm_setting:
return return
order = None ticket = None
if self.request.session.get('auth_order_id'): if self.request.session.get('auth_ticket_id'):
order_id = self.request.session['auth_order_id'] ticket_id = self.request.session['auth_ticket_id']
order = get_object_or_none(LoginConfirmOrder, pk=order_id) ticket = get_object_or_none(LoginConfirmTicket, pk=ticket_id)
if not order: if not ticket:
order = confirm_setting.create_confirm_order(self.request) ticket = confirm_setting.create_confirm_ticket(self.request)
self.request.session['auth_order_id'] = str(order.id) self.request.session['auth_ticket_id'] = str(ticket.id)
if order.status == "accepted": if ticket.status == "accepted":
return return
elif order.status == "rejected": elif ticket.status == "rejected":
raise errors.LoginConfirmRejectedError(order.id) raise errors.LoginConfirmRejectedError(ticket.id)
else: else:
raise errors.LoginConfirmWaitError(order.id) raise errors.LoginConfirmWaitError(ticket.id)
def clear_auth_mark(self): def clear_auth_mark(self):
self.request.session['auth_password'] = '' self.request.session['auth_password'] = ''
self.request.session['auth_mfa'] = '' self.request.session['auth_mfa'] = ''
self.request.session['auth_confirm'] = '' self.request.session['auth_confirm'] = ''
self.request.session['auth_order_id'] = '' self.request.session['auth_ticket_id'] = ''
def send_auth_signal(self, success=True, user=None, username='', reason=''): def send_auth_signal(self, success=True, user=None, username='', reason=''):
if success: if success:
......
...@@ -48,8 +48,8 @@ class LoginConfirmSetting(CommonModelMixin): ...@@ -48,8 +48,8 @@ class LoginConfirmSetting(CommonModelMixin):
def get_user_confirm_setting(cls, user): def get_user_confirm_setting(cls, user):
return get_object_or_none(cls, user=user) return get_object_or_none(cls, user=user)
def create_confirm_order(self, request=None): def create_confirm_ticket(self, request=None):
from orders.models import LoginConfirmOrder from tickets.models import LoginConfirmTicket
title = _('User login confirm: {}').format(self.user) title = _('User login confirm: {}').format(self.user)
if request: if request:
remote_addr = get_request_ip(request) remote_addr = get_request_ip(request)
...@@ -58,20 +58,20 @@ class LoginConfirmSetting(CommonModelMixin): ...@@ -58,20 +58,20 @@ class LoginConfirmSetting(CommonModelMixin):
self.user, remote_addr, city, timezone.now() self.user, remote_addr, city, timezone.now()
) )
else: else:
city = '' city = 'Localhost'
remote_addr = '' remote_addr = '127.0.0.1'
body = '' body = ''
reviewer = self.reviewers.all() reviewer = self.reviewers.all()
reviewer_names = ','.join([u.name for u in reviewer]) reviewer_names = ','.join([u.name for u in reviewer])
order = LoginConfirmOrder.objects.create( ticket = LoginConfirmTicket.objects.create(
user=self.user, user_display=str(self.user), user=self.user, user_display=str(self.user),
title=title, body=body, title=title, body=body,
city=city, ip=remote_addr, city=city, ip=remote_addr,
assignees_display=reviewer_names, assignees_display=reviewer_names,
type=LoginConfirmOrder.TYPE_LOGIN_CONFIRM, type=LoginConfirmTicket.TYPE_LOGIN_CONFIRM,
) )
order.assignees.set(reviewer) ticket.assignees.set(reviewer)
return order return ticket
def __str__(self): def __str__(self):
return '{} confirm'.format(self.user.username) return '{} confirm'.format(self.user.username)
......
...@@ -18,7 +18,7 @@ urlpatterns = [ ...@@ -18,7 +18,7 @@ urlpatterns = [
path('connection-token/', path('connection-token/',
api.UserConnectionTokenApi.as_view(), name='connection-token'), api.UserConnectionTokenApi.as_view(), name='connection-token'),
path('otp/verify/', api.UserOtpVerifyApi.as_view(), name='user-otp-verify'), path('otp/verify/', api.UserOtpVerifyApi.as_view(), name='user-otp-verify'),
path('order/auth/', api.UserOrderAcceptAuthApi.as_view(), name='user-order-auth'), path('order/auth/', api.UserTicketAcceptAuthApi.as_view(), name='user-order-auth'),
path('login-confirm-settings/<uuid:user_id>/', api.LoginConfirmSettingUpdateApi.as_view(), name='login-confirm-setting-update') path('login-confirm-settings/<uuid:user_id>/', api.LoginConfirmSettingUpdateApi.as_view(), name='login-confirm-setting-update')
] ]
......
...@@ -126,8 +126,8 @@ class UserLoginGuardView(mixins.AuthMixin, RedirectView): ...@@ -126,8 +126,8 @@ class UserLoginGuardView(mixins.AuthMixin, RedirectView):
return self.format_redirect_url(self.login_otp_url) return self.format_redirect_url(self.login_otp_url)
confirm_setting = user.get_login_confirm_setting() confirm_setting = user.get_login_confirm_setting()
if confirm_setting and not self.request.session.get('auth_confirm'): if confirm_setting and not self.request.session.get('auth_confirm'):
order = confirm_setting.create_confirm_order(self.request) ticket = confirm_setting.create_confirm_ticket(self.request)
self.request.session['auth_order_id'] = str(order.id) self.request.session['auth_ticket_id'] = str(ticket.id)
url = self.format_redirect_url(self.login_confirm_url) url = self.format_redirect_url(self.login_confirm_url)
return url return url
self.login_success(user) self.login_success(user)
...@@ -159,26 +159,26 @@ class UserLoginWaitConfirmView(TemplateView): ...@@ -159,26 +159,26 @@ class UserLoginWaitConfirmView(TemplateView):
template_name = 'authentication/login_wait_confirm.html' template_name = 'authentication/login_wait_confirm.html'
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
from orders.models import LoginConfirmOrder from tickets.models import LoginConfirmTicket
order_id = self.request.session.get("auth_order_id") ticket_id = self.request.session.get("auth_ticket_id")
if not order_id: if not ticket_id:
order = None ticket = None
else: else:
order = get_object_or_none(LoginConfirmOrder, pk=order_id) ticket = get_object_or_none(LoginConfirmTicket, pk=ticket_id)
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
if order: if ticket:
order_detail_url = reverse('orders:login-confirm-order-detail', kwargs={'pk': order_id}) ticket_detail_url = reverse('tickets:login-confirm-ticket-detail', kwargs={'pk': ticket_id})
timestamp_created = datetime.datetime.timestamp(order.date_created) timestamp_created = datetime.datetime.timestamp(ticket.date_created)
msg = _("""Wait for <b>{}</b> confirm, You also can copy link to her/him <br/> msg = _("""Wait for <b>{}</b> confirm, You also can copy link to her/him <br/>
Don't close this page""").format(order.assignees_display) Don't close this page""").format(ticket.assignees_display)
else: else:
timestamp_created = 0 timestamp_created = 0
order_detail_url = '' ticket_detail_url = ''
msg = _("No order found") msg = _("No ticket found")
context.update({ context.update({
"msg": msg, "msg": msg,
"timestamp": timestamp_created, "timestamp": timestamp_created,
"order_detail_url": order_detail_url "ticket_detail_url": ticket_detail_url
}) })
return context return context
......
...@@ -71,7 +71,7 @@ INSTALLED_APPS = [ ...@@ -71,7 +71,7 @@ INSTALLED_APPS = [
'audits.apps.AuditsConfig', 'audits.apps.AuditsConfig',
'authentication.apps.AuthenticationConfig', # authentication 'authentication.apps.AuthenticationConfig', # authentication
'applications.apps.ApplicationsConfig', 'applications.apps.ApplicationsConfig',
'orders.apps.OrdersConfig', 'tickets.apps.TicketsConfig',
'rest_framework', 'rest_framework',
'rest_framework_swagger', 'rest_framework_swagger',
'drf_yasg', 'drf_yasg',
......
...@@ -24,7 +24,7 @@ api_v1 = [ ...@@ -24,7 +24,7 @@ api_v1 = [
path('authentication/', include('authentication.urls.api_urls', namespace='api-auth')), path('authentication/', include('authentication.urls.api_urls', namespace='api-auth')),
path('common/', include('common.urls.api_urls', namespace='api-common')), path('common/', include('common.urls.api_urls', namespace='api-common')),
path('applications/', include('applications.urls.api_urls', namespace='api-applications')), path('applications/', include('applications.urls.api_urls', namespace='api-applications')),
path('orders/', include('orders.urls.api_urls', namespace='api-orders')), path('tickets/', include('tickets.urls.api_urls', namespace='api-tickets')),
] ]
api_v2 = [ api_v2 = [
...@@ -43,7 +43,7 @@ app_view_patterns = [ ...@@ -43,7 +43,7 @@ app_view_patterns = [
path('orgs/', include('orgs.urls.views_urls', namespace='orgs')), path('orgs/', include('orgs.urls.views_urls', namespace='orgs')),
path('auth/', include('authentication.urls.view_urls'), name='auth'), path('auth/', include('authentication.urls.view_urls'), name='auth'),
path('applications/', include('applications.urls.views_urls', namespace='applications')), path('applications/', include('applications.urls.views_urls', namespace='applications')),
path('orders/', include('orders.urls.views_urls', namespace='orders')), path('tickets/', include('tickets.urls.views_urls', namespace='tickets')),
re_path(r'flower/(?P<path>.*)', celery_flower_view, name='flower-view'), re_path(r'flower/(?P<path>.*)', celery_flower_view, name='flower-view'),
] ]
......
from django.apps import AppConfig
class OrdersConfig(AppConfig):
name = 'orders'
def ready(self):
from . import signals_handler
return super().ready()
# -*- coding: utf-8 -*-
#
from rest_framework import serializers
from django.utils.translation import ugettext_lazy as _
from .models import LoginConfirmOrder, Comment
class LoginConfirmOrderSerializer(serializers.ModelSerializer):
class Meta:
model = LoginConfirmOrder
fields = [
'id', 'user', 'user_display', 'title', 'body',
'ip', 'city', 'assignees', 'assignees_display',
'type', 'status', 'date_created', 'date_updated',
]
class LoginConfirmOrderActionSerializer(serializers.Serializer):
ACTION_CHOICES = (
('accept', _('Accept')),
('reject', _('Reject')),
('comment', _('Comment'))
)
action = serializers.ChoiceField(choices=ACTION_CHOICES)
comment = serializers.CharField(allow_blank=True)
def update(self, instance, validated_data):
pass
def create_comments(self, order, user, validated_data):
comment_data = validated_data.get('comment')
action = validated_data.get('action')
comments_data = []
if comment_data:
comments_data.append(comment_data)
Comment.objects.create(
order_id=order.id, body=comment_data, user=user,
user_display=str(user)
)
if action != "comment":
action_display = dict(self.ACTION_CHOICES).get(action)
comment_data = '{} {} {}'.format(user, action_display, _("this order"))
comments_data.append(comment_data)
comments = [
Comment(order_id=order.id, body=data, user=user, user_display=str(user))
for data in comments_data
]
Comment.objects.bulk_create(comments)
@staticmethod
def perform_action(order, user, validated_data):
action = validated_data.get('action')
if action == "accept":
status = "accepted"
elif action == "reject":
status = "rejected"
else:
status = None
if status:
order.status = status
order.assignee = user
order.assignee_display = str(user)
order.save()
def create(self, validated_data):
order = self.context['order']
user = self.context['request'].user
self.create_comments(order, user, validated_data)
self.perform_action(order, user, validated_data)
return validated_data
# -*- coding: utf-8 -*-
#
from django.urls import path
from .. import views
app_name = 'orders'
urlpatterns = [
path('login-confirm-orders/', views.LoginConfirmOrderListView.as_view(), name='login-confirm-order-list'),
path('login-confirm-orders/<uuid:pk>/', views.LoginConfirmOrderDetailView.as_view(), name='login-confirm-order-detail')
]
...@@ -554,3 +554,7 @@ span.select2-selection__placeholder { ...@@ -554,3 +554,7 @@ span.select2-selection__placeholder {
height: 22px; height: 22px;
max-width: inherit; max-width: inherit;
} }
table.table-striped.table-bordered {
width: 100% !important;
}
<style>
li.dropdown-submenu {
width: 100%;
}
</style>
<ul class="dropdown-menu multi-level search-help" role="menu" aria-labelledby="dropdownMenu"> <ul class="dropdown-menu multi-level search-help" role="menu" aria-labelledby="dropdownMenu">
</ul> </ul>
......
...@@ -122,12 +122,12 @@ ...@@ -122,12 +122,12 @@
{% endif %} {% endif %}
{% if request.user.can_admin_current_org and LOGIN_CONFIRM_ENABLE %} {% if request.user.can_admin_current_org and LOGIN_CONFIRM_ENABLE %}
<li id="orders"> <li id="tickets">
<a> <a>
<i class="fa fa-check-square-o" style="width: 14px"></i> <span class="nav-label">{% trans 'Orders' %}</span><span class="fa arrow"></span> <i class="fa fa-check-square-o" style="width: 14px"></i> <span class="nav-label">{% trans 'Tickets' %}</span><span class="fa arrow"></span>
</a> </a>
<ul class="nav nav-second-level"> <ul class="nav nav-second-level">
<li id="login-confirm-orders"><a href="{% url 'orders:login-confirm-order-list' %}">{% trans 'Login confirm' %}</a></li> <li id="login-confirm-orders"><a href="{% url 'tickets:login-confirm-ticket-list' %}">{% trans 'Login confirm' %}</a></li>
</ul> </ul>
</li> </li>
{% endif %} {% endif %}
......
# -*- coding: utf-8 -*-
#
from .base import *
from .login_confirm import *
# -*- coding: utf-8 -*-
#
from rest_framework import viewsets, generics
from .. import serializers, models
class TicketViewSet(viewsets.ModelViewSet):
serializer_class = serializers.TicketSerializer
def get_queryset(self):
queryset = models.Ticket.objects.all().none()
return queryset
class CommentViewSet(viewsets.ModelViewSet):
serializer_class = serializers.CommentSerializer
def get_queryset(self):
queryset = models.Comment.objects.none()
return queryset
...@@ -5,35 +5,35 @@ from django.shortcuts import get_object_or_404 ...@@ -5,35 +5,35 @@ from django.shortcuts import get_object_or_404
from common.permissions import IsValidUser from common.permissions import IsValidUser
from common.mixins import CommonApiMixin from common.mixins import CommonApiMixin
from . import serializers from .. import serializers
from .models import LoginConfirmOrder from ..models import LoginConfirmTicket
class LoginConfirmOrderViewSet(CommonApiMixin, viewsets.ModelViewSet): class LoginConfirmTicketViewSet(CommonApiMixin, viewsets.ModelViewSet):
serializer_class = serializers.LoginConfirmOrderSerializer serializer_class = serializers.LoginConfirmTicketSerializer
permission_classes = (IsValidUser,) permission_classes = (IsValidUser,)
filter_fields = ['status', 'title'] filter_fields = ['status', 'title']
search_fields = ['user_display', 'title', 'ip', 'city'] search_fields = ['user_display', 'title', 'ip', 'city']
def get_queryset(self): def get_queryset(self):
queryset = LoginConfirmOrder.objects.all()\ queryset = LoginConfirmTicket.objects.all()\
.filter(assignees=self.request.user) .filter(assignees=self.request.user)
return queryset return queryset
class LoginConfirmOrderCreateActionApi(generics.CreateAPIView): class LoginConfirmTicketsCreateActionApi(generics.CreateAPIView):
permission_classes = (IsValidUser,) permission_classes = (IsValidUser,)
serializer_class = serializers.LoginConfirmOrderActionSerializer serializer_class = serializers.LoginConfirmTicketActionSerializer
def get_order(self): def get_ticket(self):
order_id = self.kwargs.get('pk') ticket_id = self.kwargs.get('pk')
queryset = LoginConfirmOrder.objects.all()\ queryset = LoginConfirmTicket.objects.all()\
.filter(assignees=self.request.user) .filter(assignees=self.request.user)
order = get_object_or_404(queryset, id=order_id) ticket = get_object_or_404(queryset, id=ticket_id)
return order return ticket
def get_serializer_context(self): def get_serializer_context(self):
context = super().get_serializer_context() context = super().get_serializer_context()
order = self.get_order() ticket = self.get_ticket()
context['order'] = order context['ticket'] = ticket
return context return context
from django.apps import AppConfig
class TicketsConfig(AppConfig):
name = 'tickets'
# Generated by Django 2.2.5 on 2019-10-31 10:23 # Generated by Django 2.2.5 on 2019-11-07 08:02
from django.conf import settings from django.conf import settings
from django.db import migrations, models from django.db import migrations, models
...@@ -16,7 +16,7 @@ class Migration(migrations.Migration): ...@@ -16,7 +16,7 @@ class Migration(migrations.Migration):
operations = [ operations = [
migrations.CreateModel( migrations.CreateModel(
name='LoginConfirmOrder', name='Ticket',
fields=[ fields=[
('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)),
('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')), ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')),
...@@ -27,18 +27,28 @@ class Migration(migrations.Migration): ...@@ -27,18 +27,28 @@ class Migration(migrations.Migration):
('body', models.TextField(verbose_name='Body')), ('body', models.TextField(verbose_name='Body')),
('assignee_display', models.CharField(blank=True, max_length=128, null=True, verbose_name='Assignee display name')), ('assignee_display', models.CharField(blank=True, max_length=128, null=True, verbose_name='Assignee display name')),
('assignees_display', models.CharField(blank=True, max_length=128, verbose_name='Assignees display name')), ('assignees_display', models.CharField(blank=True, max_length=128, verbose_name='Assignees display name')),
('type', models.CharField(choices=[('login_confirm', 'Login confirm')], max_length=16, verbose_name='Type')), ('type', models.CharField(default='general', max_length=16, verbose_name='Type')),
('status', models.CharField(choices=[('accepted', 'Accepted'), ('rejected', 'Rejected'), ('pending', 'Pending')], default='pending', max_length=16)), ('status', models.CharField(choices=[('open', 'Open'), ('closed', 'Closed')], default='open', max_length=16)),
('assignee', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='ticket_handled', to=settings.AUTH_USER_MODEL, verbose_name='Assignee')),
('assignees', models.ManyToManyField(related_name='ticket_assigned', to=settings.AUTH_USER_MODEL, verbose_name='Assignees')),
('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='ticket_requested', to=settings.AUTH_USER_MODEL, verbose_name='User')),
],
options={
'ordering': ('-date_created',),
},
),
migrations.CreateModel(
name='LoginConfirmTicket',
fields=[
('ticket_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='tickets.Ticket')),
('ip', models.GenericIPAddressField(blank=True, null=True)), ('ip', models.GenericIPAddressField(blank=True, null=True)),
('city', models.CharField(blank=True, default='', max_length=16)), ('city', models.CharField(blank=True, default='', max_length=16)),
('assignee', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='loginconfirmorder_handled', to=settings.AUTH_USER_MODEL, verbose_name='Assignee')), ('action', models.CharField(blank=True, choices=[('approve', 'Approve'), ('reject', 'Reject')], default='', max_length=16)),
('assignees', models.ManyToManyField(related_name='loginconfirmorder_assigned', to=settings.AUTH_USER_MODEL, verbose_name='Assignees')),
('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='loginconfirmorder_requested', to=settings.AUTH_USER_MODEL, verbose_name='User')),
], ],
options={ options={
'ordering': ('-date_created',),
'abstract': False, 'abstract': False,
}, },
bases=('tickets.ticket',),
), ),
migrations.CreateModel( migrations.CreateModel(
name='Comment', name='Comment',
...@@ -47,9 +57,9 @@ class Migration(migrations.Migration): ...@@ -47,9 +57,9 @@ class Migration(migrations.Migration):
('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')), ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')),
('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')),
('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')),
('order_id', models.UUIDField()),
('user_display', models.CharField(max_length=128, verbose_name='User display name')), ('user_display', models.CharField(max_length=128, verbose_name='User display name')),
('body', models.TextField(verbose_name='Body')), ('body', models.TextField(verbose_name='Body')),
('ticket', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='tickets.Ticket')),
('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='comments', to=settings.AUTH_USER_MODEL, verbose_name='User')), ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='comments', to=settings.AUTH_USER_MODEL, verbose_name='User')),
], ],
options={ options={
......
# -*- coding: utf-8 -*-
#
from .base import *
from .login_confirm import *
# -*- coding: utf-8 -*-
#
from django.db import models from django.db import models
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from common.mixins.models import CommonModelMixin from common.mixins.models import CommonModelMixin
__all__ = ['LoginConfirmOrder', 'Comment'] __all__ = ['Ticket', 'Comment']
class Comment(CommonModelMixin):
order_id = models.UUIDField()
user = models.ForeignKey('users.User', on_delete=models.SET_NULL, null=True, verbose_name=_("User"), related_name='comments')
user_display = models.CharField(max_length=128, verbose_name=_("User display name"))
body = models.TextField(verbose_name=_("Body"))
class Meta:
ordering = ('date_created', )
class BaseOrder(CommonModelMixin): class Ticket(CommonModelMixin):
STATUS_ACCEPTED = 'accepted' STATUS_OPEN = 'open'
STATUS_REJECTED = 'rejected' STATUS_CLOSED = 'closed'
STATUS_PENDING = 'pending'
STATUS_CHOICES = ( STATUS_CHOICES = (
(STATUS_ACCEPTED, _("Accepted")), (STATUS_OPEN, _("Open")),
(STATUS_REJECTED, _("Rejected")), (STATUS_CLOSED, _("Closed"))
(STATUS_PENDING, _("Pending"))
) )
TYPE_GENERAL = 'general'
TYPE_LOGIN_CONFIRM = 'login_confirm' TYPE_LOGIN_CONFIRM = 'login_confirm'
TYPE_CHOICES = ( TYPE_CHOICES = (
(TYPE_LOGIN_CONFIRM, 'Login confirm'), (TYPE_GENERAL, _("General")),
(TYPE_LOGIN_CONFIRM, _("Login confirm"))
) )
user = models.ForeignKey('users.User', on_delete=models.SET_NULL, null=True, related_name='%(class)s_requested', verbose_name=_("User")) user = models.ForeignKey('users.User', on_delete=models.SET_NULL, null=True, related_name='%(class)s_requested', verbose_name=_("User"))
user_display = models.CharField(max_length=128, verbose_name=_("User display name")) user_display = models.CharField(max_length=128, verbose_name=_("User display name"))
...@@ -38,8 +31,8 @@ class BaseOrder(CommonModelMixin): ...@@ -38,8 +31,8 @@ class BaseOrder(CommonModelMixin):
assignee_display = models.CharField(max_length=128, blank=True, null=True, verbose_name=_("Assignee display name")) assignee_display = models.CharField(max_length=128, blank=True, null=True, verbose_name=_("Assignee display name"))
assignees = models.ManyToManyField('users.User', related_name='%(class)s_assigned', verbose_name=_("Assignees")) assignees = models.ManyToManyField('users.User', related_name='%(class)s_assigned', verbose_name=_("Assignees"))
assignees_display = models.CharField(max_length=128, verbose_name=_("Assignees display name"), blank=True) assignees_display = models.CharField(max_length=128, verbose_name=_("Assignees display name"), blank=True)
type = models.CharField(choices=TYPE_CHOICES, max_length=16, verbose_name=_('Type')) type = models.CharField(max_length=16, default='general', verbose_name=_("Type"))
status = models.CharField(choices=STATUS_CHOICES, max_length=16, default='pending') status = models.CharField(choices=STATUS_CHOICES, max_length=16, default='open')
def __str__(self): def __str__(self):
return '{}: {}'.format(self.user_display, self.title) return '{}: {}'.format(self.user_display, self.title)
...@@ -57,10 +50,16 @@ class BaseOrder(CommonModelMixin): ...@@ -57,10 +50,16 @@ class BaseOrder(CommonModelMixin):
return self.get_status_display() return self.get_status_display()
class Meta: class Meta:
abstract = True
ordering = ('-date_created',) ordering = ('-date_created',)
class LoginConfirmOrder(BaseOrder): class Comment(CommonModelMixin):
ip = models.GenericIPAddressField(blank=True, null=True) ticket = models.ForeignKey(Ticket, on_delete=models.CASCADE)
city = models.CharField(max_length=16, blank=True, default='') user = models.ForeignKey('users.User', on_delete=models.SET_NULL, null=True, verbose_name=_("User"), related_name='comments')
user_display = models.CharField(max_length=128, verbose_name=_("User display name"))
body = models.TextField(verbose_name=_("Body"))
class Meta:
ordering = ('date_created', )
# -*- coding: utf-8 -*-
#
from django.db import models
from django.utils.translation import ugettext_lazy as _
from .base import Ticket
__all__ = ['LoginConfirmTicket']
class LoginConfirmTicket(Ticket):
ACTION_APPROVE = 'approve'
ACTION_REJECT = 'reject'
ACTION_CHOICES = (
(ACTION_APPROVE, _('Approve')),
(ACTION_REJECT, _('Reject')),
)
ip = models.GenericIPAddressField(blank=True, null=True)
city = models.CharField(max_length=16, blank=True, default='')
action = models.CharField(choices=ACTION_CHOICES, max_length=16, default='', blank=True)
# -*- coding: utf-8 -*-
#
from .base import *
from .login_confirm import *
# -*- coding: utf-8 -*-
#
from rest_framework import serializers
from .. import models
__all__ = ['TicketSerializer', 'CommentSerializer']
class TicketSerializer(serializers.ModelSerializer):
class Meta:
model = models.Ticket
fields = [
'id', 'user', 'user_display', 'title', 'body',
'assignees', 'assignees_display',
'status', 'date_created', 'date_updated',
]
read_only_fields = [
'user_display', 'assignees_display',
'date_created', 'date_updated',
]
class CommentSerializer(serializers.ModelSerializer):
class Meta:
model = models.Comment
fields = [
'id', 'ticket', 'body', 'user', 'user_display',
'date_created', 'date_updated'
]
read_only_fields = [
'user_display', 'date_created', 'date_updated'
]
# -*- coding: utf-8 -*-
#
from rest_framework import serializers
from .base import TicketSerializer
from ..models import LoginConfirmTicket
__all__ = ['LoginConfirmTicketSerializer', 'LoginConfirmTicketActionSerializer']
class LoginConfirmTicketSerializer(serializers.ModelSerializer):
class Meta:
model = LoginConfirmTicket
fields = TicketSerializer.Meta.fields + [
'ip', 'city', 'action'
]
read_only_fields = TicketSerializer.Meta.read_only_fields
class LoginConfirmTicketActionSerializer(serializers.ModelSerializer):
comment = serializers.CharField(allow_blank=True)
class Meta:
model = LoginConfirmTicket
fields = ['action', 'comment']
def update(self, instance, validated_data):
pass
def create(self, validated_data):
pass
...@@ -4,9 +4,9 @@ from django.dispatch import receiver ...@@ -4,9 +4,9 @@ from django.dispatch import receiver
from django.db.models.signals import m2m_changed, post_save from django.db.models.signals import m2m_changed, post_save
from common.utils import get_logger from common.utils import get_logger
from .models import LoginConfirmOrder from .models import LoginConfirmTicket
from .utils import ( from .utils import (
send_login_confirm_order_mail_to_assignees, send_login_confirm_ticket_mail_to_assignees,
send_login_confirm_action_mail_to_user send_login_confirm_action_mail_to_user
) )
...@@ -14,18 +14,18 @@ from .utils import ( ...@@ -14,18 +14,18 @@ from .utils import (
logger = get_logger(__name__) logger = get_logger(__name__)
@receiver(m2m_changed, sender=LoginConfirmOrder.assignees.through) @receiver(m2m_changed, sender=LoginConfirmTicket.assignees.through)
def on_login_confirm_order_assignees_set(sender, instance=None, action=None, def on_login_confirm_ticket_assignees_set(sender, instance=None, action=None,
model=None, pk_set=None, **kwargs): model=None, pk_set=None, **kwargs):
if action == 'post_add': if action == 'post_add':
logger.debug('New order create, send mail: {}'.format(instance.id)) logger.debug('New ticket create, send mail: {}'.format(instance.id))
assignees = model.objects.filter(pk__in=pk_set) assignees = model.objects.filter(pk__in=pk_set)
send_login_confirm_order_mail_to_assignees(instance, assignees) send_login_confirm_ticket_mail_to_assignees(instance, assignees)
@receiver(post_save, sender=LoginConfirmOrder) @receiver(post_save, sender=LoginConfirmTicket)
def on_login_confirm_order_status_change(sender, instance=None, created=False, **kwargs): def on_login_confirm_ticket_status_change(sender, instance=None, created=False, **kwargs):
if created or instance.status == "pending": if created or instance.status == "pending":
return return
logger.debug('Order changed, send mail: {}'.format(instance.id)) logger.debug('Ticket changed, send mail: {}'.format(instance.id))
send_login_confirm_action_mail_to_user(instance) send_login_confirm_action_mail_to_user(instance)
...@@ -112,9 +112,9 @@ ...@@ -112,9 +112,9 @@
{% endblock %} {% endblock %}
{% block custom_foot_js %} {% block custom_foot_js %}
<script> <script>
var orderId = "{{ object.id }}"; var ticketId = "{{ object.id }}";
var status = "{{ object.status }}"; var status = "{{ object.status }}";
var actionCreateUrl = "{% url 'api-orders:login-confirm-order-create-action' pk=object.id %}"; var actionCreateUrl = "{% url 'api-tickets:login-confirm-ticket-create-action' pk=object.id %}";
$(document).ready(function () { $(document).ready(function () {
if (status !== "pending") { if (status !== "pending") {
$('.btn-update').attr('disabled', '1') $('.btn-update').attr('disabled', '1')
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
{% block custom_head_css_js %} {% block custom_head_css_js %}
{% endblock %} {% endblock %}
{% block table_container %} {% block table_container %}
<table class="table table-striped table-bordered table-hover " id="login_confirm_order_list_table" > <table class="table table-striped table-bordered table-hover " id="login_confirm_ticket_list_table" >
<thead> <thead>
<tr> <tr>
<th class="text-center"> <th class="text-center">
...@@ -27,15 +27,15 @@ ...@@ -27,15 +27,15 @@
{% block content_bottom_left %}{% endblock %} {% block content_bottom_left %}{% endblock %}
{% block custom_foot_js %} {% block custom_foot_js %}
<script> <script>
var orderTable = 0; var ticketTable = 0;
function initTable() { function initTable() {
var options = { var options = {
ele: $('#login_confirm_order_list_table'), ele: $('#login_confirm_ticket_list_table'),
oSearch: {sSearch: "status:pending"}, oSearch: {sSearch: "status:open"},
columnDefs: [ columnDefs: [
{targets: 1, createdCell: function (td, cellData, rowData) { {targets: 1, createdCell: function (td, cellData, rowData) {
cellData = htmlEscape(cellData); cellData = htmlEscape(cellData);
var detailBtn = '<a href="{% url "orders:login-confirm-order-detail" pk=DEFAULT_PK %}">' + cellData + '</a>'; var detailBtn = '<a href="{% url "tickets:login-confirm-ticket-detail" pk=DEFAULT_PK %}">' + cellData + '</a>';
$(td).html(detailBtn.replace("{{ DEFAULT_PK }}", rowData.id)); $(td).html(detailBtn.replace("{{ DEFAULT_PK }}", rowData.id));
}}, }},
{targets: 3, createdCell: function (td, cellData, rowData) { {targets: 3, createdCell: function (td, cellData, rowData) {
...@@ -43,12 +43,14 @@ function initTable() { ...@@ -43,12 +43,14 @@ function initTable() {
$(td).html(d) $(td).html(d)
}}, }},
{targets: 4, createdCell: function (td, cellData, rowData) { {targets: 4, createdCell: function (td, cellData, rowData) {
if (cellData === "accepted") { if (cellData === "approval") {
$(td).html('<i class="fa fa-check text-navy"></i>') $(td).html('<i class="fa fa-check text-navy"></i>')
} else if (cellData === "rejected") { } else if (cellData === "rejected") {
$(td).html('<i class="fa fa-times text-danger"></i>') $(td).html('<i class="fa fa-times text-danger"></i>')
} else if (cellData === "pending") { } else if (cellData === "open") {
$(td).html('<i class="fa fa-spinner text-info"></i>') $(td).html('<i class="fa fa-spinner text-info"></i>')
} else {
$(td).html('<i class="fa fa-circle text-info"></i>')
} }
}}, }},
{targets: 5, createdCell: function (td, cellData) { {targets: 5, createdCell: function (td, cellData) {
...@@ -62,25 +64,25 @@ function initTable() { ...@@ -62,25 +64,25 @@ function initTable() {
rejectBtn = rejectBtn.replace('{{ DEFAULT_PK }}', cellData); rejectBtn = rejectBtn.replace('{{ DEFAULT_PK }}', cellData);
var acceptBtnRef = $(acceptBtn); var acceptBtnRef = $(acceptBtn);
var rejectBtnRef = $(rejectBtn); var rejectBtnRef = $(rejectBtn);
if (rowData.status !== "pending") { if (rowData.action !== "") {
acceptBtnRef.attr('disabled', 'disabled'); acceptBtnRef.attr('disabled', 'disabled');
rejectBtnRef.attr('disabled', 'disabled'); rejectBtnRef.attr('disabled', 'disabled');
} }
var btn = acceptBtnRef.prop('outerHTML') + ' ' + rejectBtnRef.prop('outerHTML'); var btn = acceptBtnRef.prop('outerHTML') + ' ' + rejectBtnRef.prop('outerHTML');
$(td).html(btn) $(td).html(btn)
}}], }}],
ajax_url: '{% url "api-orders:login-confirm-order-list" %}', ajax_url: '{% url "api-tickets:login-confirm-ticket-list" %}',
columns: [ columns: [
{data: "id"}, {data: "title", className: "text-left"}, {data: "id"}, {data: "title"},
{data: "user_display"}, {data: "ip"}, {data: "user_display"}, {data: "ip"},
{data: "status", orderable: false, width: "30px"}, {data: "status", ticketable: false},
{data: "date_created", width: "120px"}, {data: "date_created", width: "120px"},
{data: "id", orderable: false, width: "100px"} {data: "id", ticketable: false}
], ],
op_html: $('#actions').html() op_html: $('#actions').html()
}; };
orderTable = jumpserver.initServerSideDataTable(options); ticketTable = jumpserver.initServerSideDataTable(options);
return orderTable return ticketTable
} }
$(document).ready(function(){ $(document).ready(function(){
...@@ -89,16 +91,19 @@ $(document).ready(function(){ ...@@ -89,16 +91,19 @@ $(document).ready(function(){
{title: "IP", value: "ip"}, {title: "IP", value: "ip"},
{title: "{% trans 'Title' %}", value: "title"}, {title: "{% trans 'Title' %}", value: "title"},
{title: "{% trans 'Status' %}", value: "status", submenu: [ {title: "{% trans 'Status' %}", value: "status", submenu: [
{title: "{% trans 'Pending' %}", value: "pending"}, {title: "{% trans 'Open' %}", value: "open"},
{title: "{% trans 'Accepted' %}", value: "accepted"}, {title: "{% trans 'Closed' %}", value: "closed"},
{title: "{% trans 'Rejected' %}", value: "rejected"} ]},
]} {title: "{% trans 'Action' %}", value: "action", submenu: [
{title: "{% trans 'Approve' %}", value: "approve"},
{title: "{% trans 'Reject' %}", value: "reject"},
]},
]; ];
initTableFilterDropdown('#login_confirm_order_list_table_filter input', menu) initTableFilterDropdown('#login_confirm_ticket_list_table_filter input', menu)
}).on('click', '.btn-action', function () { }).on('click', '.btn-action', function () {
var actionCreateUrl = "{% url 'api-orders:login-confirm-order-create-action' pk=DEFAULT_PK %}"; var actionCreateUrl = "{% url 'api-tickets:login-confirm-ticket-create-action' pk=DEFAULT_PK %}";
var orderId = $(this).data('uid'); var ticketId = $(this).data('uid');
actionCreateUrl = actionCreateUrl.replace("{{ DEFAULT_PK }}", orderId); actionCreateUrl = actionCreateUrl.replace("{{ DEFAULT_PK }}", ticketId);
var action = $(this).data('action'); var action = $(this).data('action');
var comment = ''; var comment = '';
var data = { var data = {
......
...@@ -5,16 +5,19 @@ from rest_framework.routers import DefaultRouter ...@@ -5,16 +5,19 @@ from rest_framework.routers import DefaultRouter
from .. import api from .. import api
app_name = 'orders' app_name = 'tickets'
router = DefaultRouter() router = DefaultRouter()
router.register('login-confirm-orders', api.LoginConfirmOrderViewSet, 'login-confirm-order') router.register('tickets', api.TicketViewSet, 'ticket')
router.register('login-confirm-tickets', api.LoginConfirmTicketViewSet, 'login-confirm-ticket')
router.register('tickets/<uuid:ticket_id>/comments/', api.CommentViewSet, 'ticket-comment')
urlpatterns = [ urlpatterns = [
path('login-confirm-order/<uuid:pk>/actions/', path('login-confirm-tickets/<uuid:pk>/actions/',
api.LoginConfirmOrderCreateActionApi.as_view(), api.LoginConfirmTicketsCreateActionApi.as_view(),
name='login-confirm-order-create-action' name='login-confirm-ticket-create-action'
), ),
] ]
urlpatterns += router.urls urlpatterns += router.urls
# -*- coding: utf-8 -*-
#
from django.urls import path
from .. import views
app_name = 'tickets'
urlpatterns = [
path('login-confirm-tickets/', views.LoginConfirmTicketListView.as_view(), name='login-confirm-ticket-list'),
path('login-confirm-tickets/<uuid:pk>/', views.LoginConfirmTicketDetailView.as_view(), name='login-confirm-ticket-detail')
]
...@@ -9,54 +9,54 @@ from common.tasks import send_mail_async ...@@ -9,54 +9,54 @@ from common.tasks import send_mail_async
logger = get_logger(__name__) logger = get_logger(__name__)
def send_login_confirm_order_mail_to_assignees(order, assignees): def send_login_confirm_ticket_mail_to_assignees(ticket, assignees):
recipient_list = [user.email for user in assignees] recipient_list = [user.email for user in assignees]
user = order.user user = ticket.user
if not recipient_list: if not recipient_list:
logger.error("Order not has assignees: {}".format(order.id)) logger.error("Ticket not has assignees: {}".format(ticket.id))
return return
subject = '{}: {}'.format(_("New order"), order.title) subject = '{}: {}'.format(_("New ticket"), ticket.title)
detail_url = reverse('orders:login-confirm-order-detail', detail_url = reverse('tickets:login-confirm-ticket-detail',
kwargs={'pk': order.id}, external=True) kwargs={'pk': ticket.id}, external=True)
message = _(""" message = _("""
<div> <div>
<p>Your has a new order</p> <p>Your has a new ticket</p>
<div> <div>
<b>Title:</b> {order.title} <b>Title:</b> {ticket.title}
<br/> <br/>
<b>User:</b> {user} <b>User:</b> {user}
<br/> <br/>
<b>Assignees:</b> {order.assignees_display} <b>Assignees:</b> {ticket.assignees_display}
<br/> <br/>
<b>City:</b> {order.city} <b>City:</b> {ticket.city}
<br/> <br/>
<b>IP:</b> {order.ip} <b>IP:</b> {ticket.ip}
<br/> <br/>
<a href={url}>click here to review</a> <a href={url}>click here to review</a>
</div> </div>
</div> </div>
""").format(order=order, user=user, url=detail_url) """).format(ticket=ticket, user=user, url=detail_url)
send_mail_async.delay(subject, message, recipient_list, html_message=message) send_mail_async.delay(subject, message, recipient_list, html_message=message)
def send_login_confirm_action_mail_to_user(order): def send_login_confirm_action_mail_to_user(ticket):
if not order.user: if not ticket.user:
logger.error("Order not has user: {}".format(order.id)) logger.error("Ticket not has user: {}".format(ticket.id))
return return
user = order.user user = ticket.user
recipient_list = [user.email] recipient_list = [user.email]
subject = '{}: {}'.format(_("Order has been reply"), order.title) subject = '{}: {}'.format(_("Ticket has been reply"), ticket.title)
message = _(""" message = _("""
<div> <div>
<p>Your order has been replay</p> <p>Your ticket has been replay</p>
<div> <div>
<b>Title:</b> {order.title} <b>Title:</b> {ticket.title}
<br/> <br/>
<b>Assignee:</b> {order.assignee_display} <b>Assignee:</b> {ticket.assignee_display}
<br/> <br/>
<b>Status:</b> {order.status_display} <b>Status:</b> {ticket.status_display}
<br/> <br/>
</div> </div>
</div> </div>
""").format(order=order) """).format(ticket=ticket)
send_mail_async.delay(subject, message, recipient_list, html_message=message) send_mail_async.delay(subject, message, recipient_list, html_message=message)
...@@ -2,33 +2,33 @@ from django.views.generic import TemplateView, DetailView ...@@ -2,33 +2,33 @@ from django.views.generic import TemplateView, DetailView
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from common.permissions import PermissionsMixin, IsOrgAdmin from common.permissions import PermissionsMixin, IsOrgAdmin
from .models import LoginConfirmOrder from .models import LoginConfirmTicket
class LoginConfirmOrderListView(PermissionsMixin, TemplateView): class LoginConfirmTicketListView(PermissionsMixin, TemplateView):
template_name = 'orders/login_confirm_order_list.html' template_name = 'tickets/login_confirm_ticket_list.html'
permission_classes = (IsOrgAdmin,) permission_classes = (IsOrgAdmin,)
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
context.update({ context.update({
'app': _("Orders"), 'app': _("Tickets"),
'action': _("Login confirm order list") 'action': _("Login confirm ticket list")
}) })
return context return context
class LoginConfirmOrderDetailView(PermissionsMixin, DetailView): class LoginConfirmTicketDetailView(PermissionsMixin, DetailView):
template_name = 'orders/login_confirm_order_detail.html' template_name = 'tickets/login_confirm_ticket_detail.html'
permission_classes = (IsOrgAdmin,) permission_classes = (IsOrgAdmin,)
def get_queryset(self): def get_queryset(self):
return LoginConfirmOrder.objects.filter(assignees=self.request.user) return LoginConfirmTicket.objects.filter(assignees=self.request.user)
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
context.update({ context.update({
'app': _("Orders"), 'app': _("Tickets"),
'action': _("Login confirm order detail") 'action': _("Login confirm ticket detail")
}) })
return context return context
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
{% endblock %} {% endblock %}
{% block table_container %} {% block table_container %}
<div class="uc pull-left m-r-5"><a href="{% url "users:user-create" %}" class="btn btn-sm btn-primary"> {% trans "Create user" %} </a></div> <div class="uc pull-left m-r-5"><a href="{% url "users:user-create" %}" class="btn btn-sm btn-primary"> {% trans "Create user" %} </a></div>
<table class="table table-striped table-bordered table-hover " id="user_list_table" > <table class="table table-striped table-bordered table-hover " id="user_list_table">
<thead> <thead>
<tr> <tr>
<th class="text-center"> <th class="text-center">
...@@ -125,7 +125,7 @@ function initTable() { ...@@ -125,7 +125,7 @@ function initTable() {
{data: "groups_display", orderable: false}, {data: "groups_display", orderable: false},
{data: "source"}, {data: "source"},
{data: "is_valid", orderable: false}, {data: "is_valid", orderable: false},
{data: "id", orderable: false, width: "100px"} {data: "id", orderable: false}
], ],
op_html: $('#actions').html() op_html: $('#actions').html()
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment