예제 #1
0
파일: tickets.py 프로젝트: achenxu/yats
def action(request, mode, ticket):
    mod_path, cls_name = settings.TICKET_CLASS.rsplit('.', 1)
    mod_path = mod_path.split('.').pop(0)
    tic = apps.get_model(mod_path, cls_name).objects.get(pk=ticket)

    if hasattr(settings, 'KEEP_IT_SIMPLE') and settings.KEEP_IT_SIMPLE:
        keep_it_simple = True
    else:
        keep_it_simple = False

    if mode == 'view':
        if request.method == 'POST':
            form = CommentForm(request.POST)
            if form.is_valid():
                com = tickets_comments()
                com.comment = form.cleaned_data['comment']
                com.ticket_id = ticket
                com.action = 6
                com.save(user=request.user)

                check_references(request, com)

                touch_ticket(request.user, ticket)

                add_history(request, tic, 6, com.comment)

                mail_comment(request, com.pk)
                jabber_comment(request, com.pk)

            else:
                if 'resolution' in request.POST:
                    if request.POST['resolution'] and int(
                            request.POST['resolution']) > 0:
                        tic.resolution_id = request.POST['resolution']
                        tic.closed = True
                        tic.close_date = timezone.now()
                        tic.state = get_flow_end()
                        tic.save(user=request.user)

                        com = tickets_comments()
                        com.comment = _(
                            'ticket closed - resolution: %(resolution)s\n\n%(comment)s'
                        ) % {
                            'resolution':
                            ticket_resolution.objects.get(
                                pk=request.POST['resolution']).name,
                            'comment':
                            request.POST.get('close_comment', '')
                        }
                        com.ticket_id = ticket
                        com.action = 1
                        com.save(user=request.user)

                        check_references(request, com)

                        touch_ticket(request.user, ticket)

                        add_history(request, tic, 1,
                                    request.POST.get('close_comment', ''))

                        mail_comment(request, com.pk)
                        jabber_comment(request, com.pk)

                    else:
                        messages.add_message(request, messages.ERROR,
                                             _('no resolution selected'))

                else:
                    messages.add_message(request, messages.ERROR,
                                         _('comment invalid'))

            # reload ticket => last_action date has changed
            tic = apps.get_model(mod_path, cls_name).objects.get(pk=ticket)

        excludes = []
        form = TicketsForm(exclude_list=excludes,
                           is_stuff=request.user.is_staff,
                           user=request.user,
                           instance=tic,
                           customer=request.organisation.id,
                           view_only=True)
        close = TicketCloseForm()
        reassign = TicketReassignForm(initial={
            'assigned': tic.assigned_id,
            'state': tic.state
        })
        flows = list(
            ticket_flow_edges.objects.select_related('next').filter(
                now=tic.state).exclude(next__type=2).values_list('next',
                                                                 flat=True))
        flows.append(tic.state_id)
        reassign.fields['state'].queryset = reassign.fields[
            'state'].queryset.filter(id__in=flows)

        participants = tickets_participants.objects.select_related(
            'user').filter(ticket=ticket)
        comments = tickets_comments.objects.select_related('c_user').filter(
            ticket=ticket).order_by('c_date')

        close_allowed = ticket_flow_edges.objects.select_related(
            'next').filter(now=tic.state, next__type=2).count() > 0

        files = tickets_files.objects.filter(ticket=ticket, active_record=True)
        paginator = Paginator(files, 10)
        page = request.GET.get('page')
        try:
            files_lines = paginator.page(page)
        except PageNotAnInteger:
            # If page is not an integer, deliver first page.
            files_lines = paginator.page(1)
        except EmptyPage:
            # If page is out of range (e.g. 9999), deliver last page of results.
            files_lines = paginator.page(paginator.num_pages)

        add_breadcrumbs(request, ticket, '#', caption=tic.caption[:20])
        if 'YATSE' in request.GET and 'isUsingYATSE' not in request.session:
            request.session['isUsingYATSE'] = True

        return render(
            request, 'tickets/view.html', {
                'layout':
                'horizontal',
                'ticket':
                tic,
                'form':
                form,
                'close':
                close,
                'reassign':
                reassign,
                'files':
                files_lines,
                'comments':
                comments,
                'participants':
                participants,
                'close_allowed':
                close_allowed,
                'keep_it_simple':
                keep_it_simple,
                'last_action_date':
                http_date(time.mktime(tic.last_action_date.timetuple()))
            })

    elif mode == 'gallery':
        images = tickets_files.objects.filter(ticket=ticket,
                                              active_record=True)
        return render(request, 'tickets/gallery.html', {
            'layout': 'horizontal',
            'ticket': tic,
            'images': images
        })

    elif mode == 'history':
        history = tickets_history.objects.filter(ticket=ticket)
        return render(
            request, 'tickets/history.html', {
                'layout': 'horizontal',
                'ticket': tic,
                'history': history,
                'keep_it_simple': keep_it_simple
            })

    elif mode == 'reopen':
        if tic.closed:
            tic.closed = False
            tic.state = get_flow_start()
            tic.resolution = None
            tic.close_date = None
            tic.save(user=request.user)

            com = tickets_comments()
            com.comment = _('ticket reopend - resolution deleted')
            com.ticket_id = ticket
            com.action = 2
            com.save(user=request.user)

            check_references(request, com)

            touch_ticket(request.user, ticket)

            add_history(request, tic, 2, None)

            mail_comment(request, com.pk)
            jabber_comment(request, com.pk)

        return HttpResponseRedirect('/tickets/view/%s/' % ticket)

    elif mode == 'move':
        if not tic.closed:
            old_state = tic.state

            tic.state = ticket_flow.objects.get(pk=request.POST['state'])
            tic.save(user=request.user)

            touch_ticket(request.user, ticket)

            oldUser = str(User.objects.get(
                pk=tic.assigned_id)) if tic.assigned_id else None

            history_data = {
                'old': {
                    'comment': '',
                    'assigned': oldUser,
                    'state': str(old_state)
                },
                'new': {
                    'comment': _('ticket moved'),
                    'assigned': oldUser,
                    'state': str(tic.state)
                }
            }
            add_history(request, tic, 7, history_data)

        return HttpResponse('OK')

    elif mode == 'reassign':
        if not tic.closed:
            if 'assigned' in request.POST:
                if request.POST['assigned'] and int(
                        request.POST['assigned']) > 0:
                    old_assigned_user = tic.assigned
                    old_state = tic.state

                    tic.assigned_id = request.POST['assigned']
                    tic.state = ticket_flow.objects.get(
                        pk=request.POST['state'])
                    tic.save(user=request.user)

                    newUser = User.objects.get(pk=request.POST['assigned'])

                    com = tickets_comments()
                    com.comment = _(
                        'ticket reassigned to %(user)s\nstate now: %(state)s\n\n%(comment)s'
                    ) % {
                        'user': newUser,
                        'comment': request.POST.get('reassign_comment', ''),
                        'state': tic.state
                    }
                    com.ticket_id = ticket
                    com.action = 7
                    com.save(user=request.user)

                    check_references(request, com)

                    touch_ticket(request.user, ticket)
                    if request.POST['assigned']:
                        touch_ticket(newUser, ticket)

                    mail_comment(request, com.pk)
                    jabber_comment(request, com.pk)

                    history_data = {
                        'old': {
                            'comment': '',
                            'assigned': str(old_assigned_user),
                            'state': str(old_state)
                        },
                        'new': {
                            'comment':
                            request.POST.get('reassign_comment', ''),
                            'assigned':
                            str(User.objects.get(pk=request.POST['assigned'])),
                            'state':
                            str(tic.state)
                        }
                    }
                    add_history(request, tic, 7, history_data)

                else:
                    messages.add_message(request, messages.ERROR,
                                         _('missing assigned user'))

        return HttpResponseRedirect('/tickets/view/%s/' % ticket)

    elif mode == 'edit' or (mode == 'simple' and
                            (not tic.keep_it_simple or tic.closed)
                            and keep_it_simple):
        excludes = ['resolution']
        if request.method == 'POST':
            form = TicketsForm(request.POST,
                               exclude_list=excludes,
                               is_stuff=request.user.is_staff,
                               user=request.user,
                               instance=tic,
                               customer=request.organisation.id)
            if form.is_valid():
                tic = form.save()

                if tic.keep_it_simple:
                    tic.keep_it_simple = False
                    tic.save(user=request.user)

                assigned = form.cleaned_data.get('assigned')
                if assigned:
                    touch_ticket(assigned, tic.pk)

                mail_ticket(request, tic.pk, form)
                jabber_ticket(request, tic.pk, form)

                remember_changes(request, form, tic)

                touch_ticket(request.user, tic.pk)

                return HttpResponseRedirect('/tickets/view/%s/' % ticket)

        else:
            form = TicketsForm(exclude_list=excludes,
                               is_stuff=request.user.is_staff,
                               user=request.user,
                               instance=tic,
                               customer=request.organisation.id)
        if 'state' in form.fields:
            form.fields['state'].queryset = form.fields[
                'state'].queryset.exclude(type=2)
        return render(request, 'tickets/edit.html', {
            'ticket': tic,
            'layout': 'horizontal',
            'form': form
        })

    elif mode == 'simple':
        if request.method == 'POST':
            form = SimpleTickets(request.POST,
                                 initial={
                                     'caption': tic.caption,
                                     'description': tic.description,
                                     'priority': tic.priority,
                                     'assigned': tic.assigned
                                 })
            if form.is_valid():
                cd = form.cleaned_data
                tic.caption = cd['caption']
                tic.description = cd['description'].replace(u"\u00A0", " ")
                tic.priority = cd['priority']
                tic.assigned = cd['assigned']
                tic.deadline = cd['deadline']
                tic.show_start = cd['show_start']
                tic.component = cd['component']
                tic.save(user=request.user)

                if cd['assigned']:
                    touch_ticket(cd['assigned'], tic.pk)

                remember_changes(request, form, tic)

                touch_ticket(request.user, tic.pk)

                mail_ticket(request, tic.pk, form)
                jabber_ticket(request, tic.pk, form)

                return HttpResponseRedirect('/tickets/view/%s/' % ticket)

        else:
            form = SimpleTickets(
                initial={
                    'caption': tic.caption,
                    'description': tic.description,
                    'priority': tic.priority,
                    'assigned': tic.assigned,
                    'deadline': tic.deadline,
                    'show_start': tic.show_start,
                    'component': tic.component,
                })
        return render(request, 'tickets/edit.html', {
            'ticket': tic,
            'layout': 'horizontal',
            'form': form,
            'mode': mode
        })

    elif mode == 'download':
        fileid = request.GET.get('file', -1)
        file_data = tickets_files.objects.get(id=fileid, ticket=ticket)
        src = '%s%s.dat' % (settings.FILE_UPLOAD_PATH, fileid)
        content_type = file_data.content_type
        if request.GET.get('preview') == 'yes' and os.path.isfile(
                '%s%s.preview' % (settings.FILE_UPLOAD_PATH, fileid)):
            src = '%s%s.preview' % (settings.FILE_UPLOAD_PATH, fileid)
            content_type = 'imgae/png'

        if request.GET.get(
                'resize',
                'no') == 'yes' and ('image' in file_data.content_type
                                    or 'pdf' in file_data.content_type):
            img = resize_image('%s' % (src), (200, 150), 75)
            output = io.BytesIO()
            img.save(output, 'PNG')
            output.seek(0)
            response = StreamingHttpResponse(output, content_type='image/png')

        else:
            response = StreamingHttpResponse(open('%s' % (src), "rb"),
                                             content_type=content_type)

        if 'noDisposition' not in request.GET:
            if request.GET.get('preview') == 'yes' and os.path.isfile(
                    '%s%s.preview' % (settings.FILE_UPLOAD_PATH, fileid)):
                response[
                    'Content-Disposition'] = 'attachment;filename="%s"' % content_type
            else:
                response[
                    'Content-Disposition'] = 'attachment;filename="%s"' % smart_str(
                        file_data.name)
        return response

    elif mode == 'upload':
        if request.method == 'POST':
            form = UploadFileForm(request.POST, request.FILES)
            if form.is_valid():
                if tickets_files.objects.filter(
                        active_record=True,
                        ticket=ticket,
                        checksum=request.FILES['file'].hash).count() > 0:
                    messages.add_message(
                        request, messages.ERROR,
                        _('File already exists: %s') %
                        request.FILES['file'].name)
                    if request.GET.get('Ajax') == '1':
                        return HttpResponse('OK')
                    return HttpResponseRedirect('/tickets/view/%s/' % ticket)
                f = tickets_files()
                f.name = request.FILES['file'].name
                f.size = request.FILES['file'].size
                f.checksum = request.FILES['file'].hash
                f.content_type = request.FILES['file'].content_type
                f.ticket_id = ticket
                f.public = True
                f.save(user=request.user)

                touch_ticket(request.user, ticket)

                add_history(request, tic, 5, request.FILES['file'].name)

                mail_file(request, f.pk)
                jabber_file(request, f.pk)

                dest = settings.FILE_UPLOAD_PATH
                if not os.path.exists(dest):
                    os.makedirs(dest)

                with open('%s%s.dat' % (dest, f.id), 'wb+') as destination:
                    for chunk in request.FILES['file'].chunks():
                        destination.write(chunk)

                if 'pdf' in f.content_type:
                    convertPDFtoImg('%s/%s.dat' % (dest, f.id),
                                    '%s/%s.preview' % (dest, f.id))
                else:
                    if 'image' not in f.content_type and isPreviewable(
                            f.content_type):
                        tmp = convertOfficeTpPDF('%s/%s.dat' % (dest, f.id))
                        convertPDFtoImg(tmp, '%s/%s.preview' % (dest, f.id))
                        if os.path.isfile(tmp):
                            os.unlink(tmp)

                return HttpResponseRedirect('/tickets/view/%s/' % tic.pk)

            else:
                msg = unicode(form.errors['file'])
                msg = re.sub('<[^<]+?>', '', msg)
                messages.add_message(request, messages.ERROR, msg)
                if request.GET.get('Ajax') == '1':
                    return HttpResponse('OK')
                return HttpResponseRedirect('/tickets/view/%s/' % ticket)

        elif request.method == 'PUT':
            # /tickets/upload/XXX/?filename=test1.txt
            upload_handlers = request.upload_handlers
            content_type = str(request.META.get('CONTENT_TYPE', ""))
            content_length = int(request.META.get('CONTENT_LENGTH', 0))

            if content_type == "":
                return HttpResponse('missing ContentType', status=400)
            if content_length == 0:
                # both returned 0
                return HttpResponse('missing ContentLength', status=400)

            content_type = content_type.split(";")[0].strip()
            try:
                charset = content_type.split(";")[1].strip()
            except IndexError:
                charset = ""

            # we can get the file name via the path, we don't actually
            file_name = request.GET['filename']
            field_name = file_name

            counters = [0] * len(upload_handlers)

            for handler in upload_handlers:
                result = handler.handle_raw_input("", request.META,
                                                  content_length, "", "")

            from django.core.files.uploadhandler import StopFutureHandlers
            for handler in upload_handlers:
                try:
                    handler.new_file(field_name, file_name, content_type,
                                     content_length, charset)
                except StopFutureHandlers:
                    break

            for i, handler in enumerate(upload_handlers):
                while True:
                    chunk = request.read(handler.chunk_size)
                    if chunk:

                        handler.receive_data_chunk(chunk, counters[i])
                        counters[i] += len(chunk)
                    else:
                        # no chunk
                        break

            for i, handler in enumerate(upload_handlers):
                file_obj = handler.file_complete(counters[i])
                if file_obj:
                    if settings.FILE_UPLOAD_VIRUS_SCAN and pyclamd:
                        # virus scan
                        try:
                            if not hasattr(pyclamd, 'scan_stream'):
                                cd = pyclamd.ClamdUnixSocket()
                            else:
                                pyclamd.init_network_socket('localhost', 3310)
                                cd = pyclamd

                            # We need to get a file object for clamav. We might have a path or we might
                            # have to read the data into memory.
                            if hasattr(file_obj, 'temporary_file_path'):
                                os.chmod(file_obj.temporary_file_path(), 0664)
                                result = cd.scan_file(
                                    file_obj.temporary_file_path())
                            else:
                                if hasattr(file_obj, 'read'):
                                    result = cd.scan_stream(file_obj.read())
                                else:
                                    result = cd.scan_stream(
                                        file_obj['content'])
                        except:
                            from socket import gethostname
                            raise Exception(
                                _(u'unable to initialize scan engine on host %s'
                                  ) % gethostname())

                        if result:
                            msg = ' '.join(result[result.keys()[0]]).replace(
                                'FOUND ', '')
                            raise Exception(
                                _(u"file is infected by virus: %s") % msg)

                    hasher = hashlib.md5()
                    # We need to get a file object for clamav. We might have a path or we might
                    # have to read the data into memory.
                    if hasattr(file_obj, 'temporary_file_path'):
                        with open(file_obj.temporary_file_path(),
                                  'rb') as afile:
                            buf = afile.read()
                            hasher.update(buf)
                        hash = hasher.hexdigest()
                    else:
                        if hasattr(file_obj, 'read'):
                            file_obj.seek(0)
                            buf = file_obj.read()
                            hasher.update(buf)
                        else:
                            hasher.update(file_obj['content'].read())
                    hash = hasher.hexdigest()

                    if tickets_files.objects.filter(active_record=True,
                                                    ticket=ticket,
                                                    checksum=hash).count() > 0:
                        raise Exception(
                            'duplicate hash value - file already exists in this ticket %s'
                            % ticket)

                    # todo: virusscan
                    f = tickets_files()
                    f.name = file_obj.name
                    f.size = file_obj.size
                    f.checksum = hash
                    f.content_type = content_type
                    f.ticket_id = ticket
                    f.public = True
                    f.save(user=request.user)

                    touch_ticket(request.user, ticket)

                    add_history(request, tic, 5, file_obj.name)

                    mail_file(request, f.pk)
                    jabber_file(request, f.pk)

                    dest = settings.FILE_UPLOAD_PATH
                    if not os.path.exists(dest):
                        os.makedirs(dest)

                    with open('%s%s.dat' % (dest, f.id), 'wb+') as destination:
                        for chunk in file_obj.chunks():
                            destination.write(chunk)

                    if 'pdf' in f.content_type:
                        convertPDFtoImg('%s/%s.dat' % (dest, f.id),
                                        '%s/%s.preview' % (dest, f.id))
                    else:
                        if 'image' not in f.content_type and isPreviewable(
                                f.content_type):
                            try:
                                tmp = convertOfficeTpPDF('%s/%s.dat' %
                                                         (dest, f.id))
                                convertPDFtoImg(tmp,
                                                '%s/%s.preview' % (dest, f.id))
                                if os.path.isfile(tmp):
                                    os.unlink(tmp)
                            except:
                                pass

                        if 'audio' in f.content_type:
                            try:
                                # https://realpython.com/python-speech-recognition/
                                import speech_recognition as sr
                                AUDIO_FILE = '%s%s.dat' % (dest, f.id)
                                r = sr.Recognizer()
                                with sr.AudioFile(AUDIO_FILE) as source:
                                    audio = r.record(
                                        source)  # read the entire audio file

                                text = r.recognize_google(audio,
                                                          language='de-DE')
                                if text:
                                    com = tickets_comments()
                                    com.comment = text
                                    com.ticket_id = ticket
                                    com.action = 6
                                    com.save(user=request.user)
                            except:
                                pass

                    return HttpResponse(status=201)

                else:
                    # some indication this didn't work?
                    return HttpResponse(status=500)

        else:
            form = UploadFileForm()

        return render(request, 'tickets/file.html', {
            'ticketid': ticket,
            'layout': 'horizontal',
            'form': form
        })

    elif mode == 'delfile':
        file = tickets_files.objects.get(pk=request.GET['fileid'],
                                         ticket=ticket)
        file.delete(user=request.user)

        touch_ticket(request.user, ticket)

        add_history(request, tic, 8, file.name)

        return HttpResponseRedirect('/tickets/view/%s/#files' % tic.pk)

    elif mode == 'notify':
        tickets_participants.objects.filter(
            ticket=tic, user=request.user).update(seen=True)
        return HttpResponse('OK')

    elif mode == 'sleep':
        interval = request.GET.get('interval')
        if interval in ['1', '2', '3', '4', '5', '6', '7', '14', '21', '30']:
            old = tic.show_start
            tic.show_start = timezone.now() + datetime.timedelta(
                days=int(interval))
            tic.save(user=request.user)

            touch_ticket(request.user, ticket)

            add_history(request, tic, 10, (tic.show_start, old))

            return HttpResponse('OK')

        else:
            raise Exception('no interval given')

    elif mode == 'ignore':
        ig = tickets_ignorants()
        ig.ticket = tic
        ig.user = request.user
        ig.save()
        return HttpResponse('OK')

    elif mode == 'todo':

        class local:
            counter = 0

        def ToDoDone(match):
            local.counter += 1
            group = match.groups()
            if local.counter == pos:
                return u'[X]'
            else:
                return u'[%s]' % group[0]

        def ToDoUnDone(match):
            local.counter += 1
            group = match.groups()
            if local.counter == pos:
                return u'[ ]'
            else:
                return u'[%s]' % group[0]

        form = ToDo(request.POST)
        if form.is_valid():
            desc = tic.description

            cd = form.cleaned_data
            text = cd['text']
            pos = cd['item']
            set = cd['set']
            if set:
                tic.description = re.sub(r'\[([ Xx])\]', ToDoDone, desc)
                old = _('undone: %s') % text
                new = _('done: %s') % text
            else:
                tic.description = re.sub(r'\[([ Xx])\]', ToDoUnDone, desc)
                new = _('undone: %s') % text
                old = _('done: %s') % text

            tic.save(user=request.user)

            touch_ticket(request.user, ticket)

            add_history(request, tic, 9, (new, old))

            data = {
                'set': set,
                'item': pos,
                'text': text,
            }
            return JsonResponse(data, safe=False)

    elif mode == 'update_comment':

        if request.method == 'POST':
            comment_id = request.GET.get("comment_id")
            comment = tickets_comments.objects.get(pk=comment_id)

            if comment.c_user == request.user:
                comment.comment = request.POST.get("comment_body", "")
                comment.edited = True
                comment.save(user=request.user)

        return HttpResponseRedirect("/tickets/view/%s/#comment_id-%s" %
                                    (ticket, comment_id))

    elif mode == 'last_modified':
        if_modified_since = request.META.get('HTTP_IF_MODIFIED_SINCE')
        if if_modified_since:
            if_modified_since = parse_http_date_safe(if_modified_since)
            if time.mktime(
                    tic.last_action_date.timetuple()) > if_modified_since:
                return HttpResponse('outdated', status=200)
            else:
                return HttpResponse('not modified', status=304)

        else:
            return HttpResponse('unknown', status=412)
예제 #2
0
파일: tickets.py 프로젝트: visitorone/yats
def action(request, mode, ticket):
    mod_path, cls_name = settings.TICKET_CLASS.rsplit('.', 1)
    mod_path = mod_path.split('.').pop(0)
    tic = get_model(mod_path, cls_name).objects.get(pk=ticket)

    if mode == 'view':
        if request.method == 'POST':
            form = CommentForm(request.POST)
            if form.is_valid():
                com = tickets_comments()
                com.comment = form.cleaned_data['comment']
                com.ticket_id = ticket
                com.action = 6
                com.save(user=request.user)

                check_references(request, com)

                touch_ticket(request.user, ticket)

                add_history(request, tic, 6, com.comment)

                mail_comment(request, com.pk)

            else:
                if 'resolution' in request.POST:
                    if request.POST['resolution'] and int(request.POST['resolution']) > 0:
                        tic.resolution_id = request.POST['resolution']
                        tic.closed = True
                        tic.close_date = datetime.datetime.now()
                        tic.state = get_flow_end()
                        tic.save(user=request.user)

                        com = tickets_comments()
                        com.comment = _('ticket closed - resolution: %(resolution)s\n\n%(comment)s') % {'resolution': ticket_resolution.objects.get(pk=request.POST['resolution']).name, 'comment': request.POST.get('close_comment', '')}
                        com.ticket_id = ticket
                        com.action = 1
                        com.save(user=request.user)

                        check_references(request, com)

                        touch_ticket(request.user, ticket)

                        add_history(request, tic, 1, request.POST.get('close_comment', ''))

                        mail_comment(request, com.pk)

                    else:
                        messages.add_message(request, messages.ERROR, _('no resolution selected'))

                else:
                    messages.add_message(request, messages.ERROR, _('comment invalid'))

        excludes = []
        form = TicketsForm(exclude_list=excludes, is_stuff=request.user.is_staff, user=request.user, instance=tic, customer=request.organisation.id, view_only=True)
        close = TicketCloseForm()
        reassign = TicketReassignForm(initial={'assigned': tic.assigned_id, 'state': tic.state})
        flows = list(ticket_flow_edges.objects.select_related('next').filter(now=tic.state).exclude(next__type=2).values_list('next', flat=True))
        flows.append(tic.state_id)
        reassign.fields['state'].queryset = reassign.fields['state'].queryset.filter(id__in=flows)

        participants = tickets_participants.objects.select_related('user').filter(ticket=ticket)
        comments = tickets_comments.objects.select_related('c_user').filter(ticket=ticket).order_by('c_date')

        close_allowed = ticket_flow_edges.objects.select_related('next').filter(now=tic.state, next__type=2).count() > 0

        files = tickets_files.objects.filter(ticket=ticket)
        paginator = Paginator(files, 10)
        page = request.GET.get('page')
        try:
            files_lines = paginator.page(page)
        except PageNotAnInteger:
            # If page is not an integer, deliver first page.
            files_lines = paginator.page(1)
        except EmptyPage:
            # If page is out of range (e.g. 9999), deliver last page of results.
            files_lines = paginator.page(paginator.num_pages)

        add_breadcrumbs(request, ticket, '#')

        return render_to_response('tickets/view.html', {'layout': 'horizontal', 'ticket': tic, 'form': form, 'close': close, 'reassign': reassign, 'files': files_lines, 'comments': comments, 'participants': participants, 'close_allowed': close_allowed}, RequestContext(request))

    elif mode == 'history':
        history = tickets_history.objects.filter(ticket=ticket)
        return render_to_response('tickets/history.html', {'layout': 'horizontal', 'ticket': tic, 'history': history}, RequestContext(request))

    elif mode == 'reopen':
        if tic.closed:
            tic.closed = False
            tic.state = get_flow_start()
            tic.resolution = None
            tic.close_date = None
            tic.save(user=request.user)

            com = tickets_comments()
            com.comment = _('ticket reopend - resolution deleted')
            com.ticket_id = ticket
            com.action = 2
            com.save(user=request.user)

            check_references(request, com)

            touch_ticket(request.user, ticket)

            add_history(request, tic, 2, None)

            mail_comment(request, com.pk)

        return HttpResponseRedirect('/tickets/view/%s/' % ticket)

    elif mode == 'reassign':
        if not tic.closed:
            if 'assigned' in request.POST:
                if request.POST['assigned'] and int(request.POST['assigned']) > 0:
                    old_assigned_user = tic.assigned
                    old_state = tic.state

                    tic.assigned_id = request.POST['assigned']
                    tic.state = ticket_flow.objects.get(pk=request.POST['state'])
                    tic.save(user=request.user)

                    newUser = User.objects.get(pk=request.POST['assigned'])

                    com = tickets_comments()
                    com.comment = _('ticket reassigned to %(user)s\nstate now: %(state)s\n\n%(comment)s') % {'user': newUser, 'comment': request.POST.get('reassign_comment', ''), 'state': tic.state}
                    com.ticket_id = ticket
                    com.action = 7
                    com.save(user=request.user)

                    check_references(request, com)

                    touch_ticket(request.user, ticket)
                    if request.POST['assigned']:
                        touch_ticket(newUser, ticket)

                    history_data = {
                                    'old': {'comment': '', 'assigned': str(old_assigned_user), 'state': str(old_state)},
                                    'new': {'comment': request.POST.get('reassign_comment', ''), 'assigned': str(User.objects.get(pk=request.POST['assigned'])), 'state': str(tic.state)}
                                    }
                    add_history(request, tic, 7, history_data)

                    mail_comment(request, com.pk)
                else:
                    messages.add_message(request, messages.ERROR, _('missing assigned user'))

        return HttpResponseRedirect('/tickets/view/%s/' % ticket)

    elif mode == 'edit':
        excludes = ['resolution']
        if request.method == 'POST':
            form = TicketsForm(request.POST, exclude_list=excludes, is_stuff=request.user.is_staff, user=request.user, instance=tic, customer=request.organisation.id)
            if form.is_valid():
                tic = form.save()

                assigned = form.cleaned_data.get('assigned')
                if assigned:
                    touch_ticket(assigned, tic.pk)

                remember_changes(request, form, tic)

                touch_ticket(request.user, tic.pk)

                mail_ticket(request, tic.pk, form)

                return HttpResponseRedirect('/tickets/view/%s/' % ticket)

        else:
            form = TicketsForm(exclude_list=excludes, is_stuff=request.user.is_staff, user=request.user, instance=tic, customer=request.organisation.id)
        if 'state' in form.fields:
            form.fields['state'].queryset = form.fields['state'].queryset.exclude(type=2)
        return render_to_response('tickets/edit.html', {'ticket': tic, 'layout': 'horizontal', 'form': form}, RequestContext(request))

    elif mode == 'download':
        fileid = request.GET.get('file', -1)
        file_data = tickets_files.objects.get(id=fileid, ticket=ticket)
        src = '%s%s.dat' % (settings.FILE_UPLOAD_PATH, fileid)

        if request.GET.get('resize', 'no') == 'yes' and 'image' in file_data.content_type:
            img = resize_image('%s' % (src), (200, 150), 75)
            output = io.BytesIO()
            img.save(output, 'PNG')
            output.seek(0)
            response = StreamingHttpResponse(output, mimetype=smart_str(file_data.content_type))

        else:
            response = StreamingHttpResponse(open('%s' % (src),"rb"), mimetype=smart_str(file_data.content_type))
        response['Content-Disposition'] = 'attachment;filename=%s' % smart_str(file_data.name)
        return response

    elif mode == 'upload':
        if request.method == 'POST':
            form = UploadFileForm(request.POST, request.FILES)
            if form.is_valid():
                f = tickets_files()
                f.name = request.FILES['file'].name
                f.size = request.FILES['file'].size
                f.content_type = request.FILES['file'].content_type
                f.ticket_id = ticket
                f.public = True
                f.save(user=request.user)

                touch_ticket(request.user, ticket)

                add_history(request, tic, 5, request.FILES['file'].name)

                mail_file(request, f.pk)

                dest = settings.FILE_UPLOAD_PATH
                if not os.path.exists(dest):
                    os.makedirs(dest)

                with open('%s%s.dat' % (dest, f.id), 'wb+') as destination:
                    for chunk in request.FILES['file'].chunks():
                        destination.write(chunk)

                return HttpResponseRedirect('/tickets/view/%s/' % tic.pk)
        else:
            form = UploadFileForm()

        return render_to_response('tickets/file.html', {'ticketid': ticket, 'layout': 'horizontal', 'form': form}, RequestContext(request))
예제 #3
0
def action(request, mode, ticket):
    mod_path, cls_name = settings.TICKET_CLASS.rsplit('.', 1)
    mod_path = mod_path.split('.').pop(0)
    tic = apps.get_model(mod_path, cls_name).objects.get(pk=ticket)

    if hasattr(settings, 'KEEP_IT_SIMPLE') and settings.KEEP_IT_SIMPLE:
        keep_it_simple = True
    else:
        keep_it_simple = False

    if mode == 'view':
        if request.method == 'POST':
            form = CommentForm(request.POST)
            if form.is_valid():
                com = tickets_comments()
                com.comment = form.cleaned_data['comment']
                com.ticket_id = ticket
                com.action = 6
                com.save(user=request.user)

                check_references(request, com)

                touch_ticket(request.user, ticket)

                add_history(request, tic, 6, com.comment)

                mail_comment(request, com.pk)
                jabber_comment(request, com.pk)

            else:
                if 'resolution' in request.POST:
                    if request.POST['resolution'] and int(request.POST['resolution']) > 0:
                        tic.resolution_id = request.POST['resolution']
                        tic.closed = True
                        tic.close_date = timezone.now()
                        tic.state = get_flow_end()
                        tic.save(user=request.user)

                        com = tickets_comments()
                        com.comment = _('ticket closed - resolution: %(resolution)s\n\n%(comment)s') % {'resolution': ticket_resolution.objects.get(pk=request.POST['resolution']).name, 'comment': request.POST.get('close_comment', '')}
                        com.ticket_id = ticket
                        com.action = 1
                        com.save(user=request.user)

                        check_references(request, com)

                        touch_ticket(request.user, ticket)

                        add_history(request, tic, 1, request.POST.get('close_comment', ''))

                        mail_comment(request, com.pk)
                        jabber_comment(request, com.pk)

                    else:
                        messages.add_message(request, messages.ERROR, _('no resolution selected'))

                else:
                    messages.add_message(request, messages.ERROR, _('comment invalid'))

        excludes = []
        form = TicketsForm(exclude_list=excludes, is_stuff=request.user.is_staff, user=request.user, instance=tic, customer=request.organisation.id, view_only=True)
        close = TicketCloseForm()
        reassign = TicketReassignForm(initial={'assigned': tic.assigned_id, 'state': tic.state})
        flows = list(ticket_flow_edges.objects.select_related('next').filter(now=tic.state).exclude(next__type=2).values_list('next', flat=True))
        flows.append(tic.state_id)
        reassign.fields['state'].queryset = reassign.fields['state'].queryset.filter(id__in=flows)

        participants = tickets_participants.objects.select_related('user').filter(ticket=ticket)
        comments = tickets_comments.objects.select_related('c_user').filter(ticket=ticket).order_by('c_date')

        close_allowed = ticket_flow_edges.objects.select_related('next').filter(now=tic.state, next__type=2).count() > 0

        files = tickets_files.objects.filter(ticket=ticket, active_record=True)
        paginator = Paginator(files, 10)
        page = request.GET.get('page')
        try:
            files_lines = paginator.page(page)
        except PageNotAnInteger:
            # If page is not an integer, deliver first page.
            files_lines = paginator.page(1)
        except EmptyPage:
            # If page is out of range (e.g. 9999), deliver last page of results.
            files_lines = paginator.page(paginator.num_pages)

        add_breadcrumbs(request, ticket, '#', caption=tic.caption[:20])
        if 'YATSE' in request.GET and 'isUsingYATSE' not in request.session:
            request.session['isUsingYATSE'] = True

        return render(request, 'tickets/view.html', {'layout': 'horizontal', 'ticket': tic, 'form': form, 'close': close, 'reassign': reassign, 'files': files_lines, 'comments': comments, 'participants': participants, 'close_allowed': close_allowed, 'keep_it_simple': keep_it_simple, 'last_action_date': http_date(time.mktime(tic.last_action_date.timetuple()))})

    elif mode == 'gallery':
        images = tickets_files.objects.filter(ticket=ticket, active_record=True)
        return render(request, 'tickets/gallery.html', {'layout': 'horizontal', 'ticket': tic, 'images': images})

    elif mode == 'history':
        history = tickets_history.objects.filter(ticket=ticket)
        return render(request, 'tickets/history.html', {'layout': 'horizontal', 'ticket': tic, 'history': history, 'keep_it_simple': keep_it_simple})

    elif mode == 'reopen':
        if tic.closed:
            tic.closed = False
            tic.state = get_flow_start()
            tic.resolution = None
            tic.close_date = None
            tic.save(user=request.user)

            com = tickets_comments()
            com.comment = _('ticket reopend - resolution deleted')
            com.ticket_id = ticket
            com.action = 2
            com.save(user=request.user)

            check_references(request, com)

            touch_ticket(request.user, ticket)

            add_history(request, tic, 2, None)

            mail_comment(request, com.pk)
            jabber_comment(request, com.pk)

        return HttpResponseRedirect('/tickets/view/%s/' % ticket)

    elif mode == 'move':
        if not tic.closed:
            old_state = tic.state

            tic.state = ticket_flow.objects.get(pk=request.POST['state'])
            tic.save(user=request.user)

            touch_ticket(request.user, ticket)

            oldUser = str(User.objects.get(pk=tic.assigned_id)) if tic.assigned_id else None

            history_data = {
                            'old': {'comment': '', 'assigned': oldUser, 'state': str(old_state)},
                            'new': {'comment': _('ticket moved'), 'assigned': oldUser, 'state': str(tic.state)}
                            }
            add_history(request, tic, 7, history_data)

        return HttpResponse('OK')

    elif mode == 'reassign':
        if not tic.closed:
            if 'assigned' in request.POST:
                if request.POST['assigned'] and int(request.POST['assigned']) > 0:
                    old_assigned_user = tic.assigned
                    old_state = tic.state

                    tic.assigned_id = request.POST['assigned']
                    tic.state = ticket_flow.objects.get(pk=request.POST['state'])
                    tic.save(user=request.user)

                    newUser = User.objects.get(pk=request.POST['assigned'])

                    com = tickets_comments()
                    com.comment = _('ticket reassigned to %(user)s\nstate now: %(state)s\n\n%(comment)s') % {'user': newUser, 'comment': request.POST.get('reassign_comment', ''), 'state': tic.state}
                    com.ticket_id = ticket
                    com.action = 7
                    com.save(user=request.user)

                    check_references(request, com)

                    touch_ticket(request.user, ticket)
                    if request.POST['assigned']:
                        touch_ticket(newUser, ticket)

                    mail_comment(request, com.pk)
                    jabber_comment(request, com.pk)

                    history_data = {
                                    'old': {'comment': '', 'assigned': str(old_assigned_user), 'state': str(old_state)},
                                    'new': {'comment': request.POST.get('reassign_comment', ''), 'assigned': str(User.objects.get(pk=request.POST['assigned'])), 'state': str(tic.state)}
                                    }
                    add_history(request, tic, 7, history_data)

                else:
                    messages.add_message(request, messages.ERROR, _('missing assigned user'))

        return HttpResponseRedirect('/tickets/view/%s/' % ticket)

    elif mode == 'edit' or (mode == 'simple' and (not tic.keep_it_simple or tic.closed) and keep_it_simple):
        excludes = ['resolution']
        if request.method == 'POST':
            form = TicketsForm(request.POST, exclude_list=excludes, is_stuff=request.user.is_staff, user=request.user, instance=tic, customer=request.organisation.id)
            if form.is_valid():
                tic = form.save()

                if tic.keep_it_simple:
                    tic.keep_it_simple = False
                    tic.save(user=request.user)

                assigned = form.cleaned_data.get('assigned')
                if assigned:
                    touch_ticket(assigned, tic.pk)

                mail_ticket(request, tic.pk, form)
                jabber_ticket(request, tic.pk, form)

                remember_changes(request, form, tic)

                touch_ticket(request.user, tic.pk)

                return HttpResponseRedirect('/tickets/view/%s/' % ticket)

        else:
            form = TicketsForm(exclude_list=excludes, is_stuff=request.user.is_staff, user=request.user, instance=tic, customer=request.organisation.id)
        if 'state' in form.fields:
            form.fields['state'].queryset = form.fields['state'].queryset.exclude(type=2)
        return render(request, 'tickets/edit.html', {'ticket': tic, 'layout': 'horizontal', 'form': form})

    elif mode == 'simple':
        if request.method == 'POST':
            form = SimpleTickets(request.POST, initial={
                    'caption': tic.caption,
                    'description': tic.description,
                    'priority': tic.priority,
                    'assigned': tic.assigned
                })
            if form.is_valid():
                cd = form.cleaned_data
                tic.caption = cd['caption']
                tic.description = cd['description'].replace(u"\u00A0", " ")
                tic.priority = cd['priority']
                tic.assigned = cd['assigned']
                tic.deadline = cd['deadline']
                tic.show_start = cd['show_start']
                tic.component = cd['component']
                tic.save(user=request.user)

                if cd['assigned']:
                    touch_ticket(cd['assigned'], tic.pk)

                remember_changes(request, form, tic)

                touch_ticket(request.user, tic.pk)

                mail_ticket(request, tic.pk, form)
                jabber_ticket(request, tic.pk, form)

                return HttpResponseRedirect('/tickets/view/%s/' % ticket)

        else:
            form = SimpleTickets(initial={
                    'caption': tic.caption,
                    'description': tic.description,
                    'priority': tic.priority,
                    'assigned': tic.assigned,
                    'deadline': tic.deadline,
                    'show_start': tic.show_start,
                    'component': tic.component,
                })
        return render(request, 'tickets/edit.html', {'ticket': tic, 'layout': 'horizontal', 'form': form, 'mode': mode})

    elif mode == 'download':
        fileid = request.GET.get('file', -1)
        file_data = tickets_files.objects.get(id=fileid, ticket=ticket)
        src = '%s%s.dat' % (settings.FILE_UPLOAD_PATH, fileid)
        content_type = file_data.content_type
        if request.GET.get('preview') == 'yes' and os.path.isfile('%s%s.preview' % (settings.FILE_UPLOAD_PATH, fileid)):
            src = '%s%s.preview' % (settings.FILE_UPLOAD_PATH, fileid)
            content_type = 'imgae/png'

        if request.GET.get('resize', 'no') == 'yes' and ('image' in file_data.content_type or 'pdf' in file_data.content_type):
            img = resize_image('%s' % (src), (200, 150), 75)
            output = io.BytesIO()
            img.save(output, 'PNG')
            output.seek(0)
            response = StreamingHttpResponse(output, content_type='image/png')

        else:
            response = StreamingHttpResponse(open('%s' % (src), "rb"), content_type=content_type)

        if 'noDisposition' not in request.GET:
            if request.GET.get('preview') == 'yes' and os.path.isfile('%s%s.preview' % (settings.FILE_UPLOAD_PATH, fileid)):
                response['Content-Disposition'] = 'attachment;filename="%s"' % content_type
            else:
                response['Content-Disposition'] = 'attachment;filename="%s"' % smart_str(file_data.name)
        return response

    elif mode == 'upload':
        if request.method == 'POST':
            form = UploadFileForm(request.POST, request.FILES)
            if form.is_valid():
                if tickets_files.objects.filter(active_record=True, ticket=ticket, checksum=request.FILES['file'].hash).count() > 0:
                    messages.add_message(request, messages.ERROR, _('File already exists: %s') % request.FILES['file'].name)
                    if request.GET.get('Ajax') == '1':
                        return HttpResponse('OK')
                    return HttpResponseRedirect('/tickets/view/%s/' % ticket)
                f = tickets_files()
                f.name = request.FILES['file'].name
                f.size = request.FILES['file'].size
                f.checksum = request.FILES['file'].hash
                f.content_type = request.FILES['file'].content_type
                f.ticket_id = ticket
                f.public = True
                f.save(user=request.user)

                touch_ticket(request.user, ticket)

                add_history(request, tic, 5, request.FILES['file'].name)

                mail_file(request, f.pk)
                jabber_file(request, f.pk)

                dest = settings.FILE_UPLOAD_PATH
                if not os.path.exists(dest):
                    os.makedirs(dest)

                with open('%s%s.dat' % (dest, f.id), 'wb+') as destination:
                    for chunk in request.FILES['file'].chunks():
                        destination.write(chunk)

                if 'pdf' in f.content_type:
                    convertPDFtoImg('%s/%s.dat' % (dest, f.id), '%s/%s.preview' % (dest, f.id))
                else:
                    if 'image' not in f.content_type and isPreviewable(f.content_type):
                        tmp = convertOfficeTpPDF('%s/%s.dat' % (dest, f.id))
                        convertPDFtoImg(tmp, '%s/%s.preview' % (dest, f.id))
                        if os.path.isfile(tmp):
                            os.unlink(tmp)

                return HttpResponseRedirect('/tickets/view/%s/' % tic.pk)

            else:
                msg = unicode(form.errors['file'])
                msg = re.sub('<[^<]+?>', '', msg)
                messages.add_message(request, messages.ERROR, msg)
                if request.GET.get('Ajax') == '1':
                    return HttpResponse('OK')
                return HttpResponseRedirect('/tickets/view/%s/' % ticket)

        elif request.method == 'PUT':
            # /tickets/upload/XXX/?filename=test1.txt
            upload_handlers = request.upload_handlers
            content_type = str(request.META.get('CONTENT_TYPE', ""))
            content_length = int(request.META.get('CONTENT_LENGTH', 0))

            if content_type == "":
                return HttpResponse('missing ContentType', status=400)
            if content_length == 0:
                # both returned 0
                return HttpResponse('missing ContentLength', status=400)

            content_type = content_type.split(";")[0].strip()
            try:
                charset = content_type.split(";")[1].strip()
            except IndexError:
                charset = ""

            # we can get the file name via the path, we don't actually
            file_name = request.GET['filename']
            field_name = file_name

            counters = [0]*len(upload_handlers)

            for handler in upload_handlers:
                result = handler.handle_raw_input("", request.META, content_length, "", "")

            from django.core.files.uploadhandler import StopFutureHandlers
            for handler in upload_handlers:
                try:
                    handler.new_file(field_name, file_name,
                                     content_type, content_length, charset)
                except StopFutureHandlers:
                    break

            for i, handler in enumerate(upload_handlers):
                while True:
                    chunk = request.read(handler.chunk_size)
                    if chunk:

                        handler.receive_data_chunk(chunk, counters[i])
                        counters[i] += len(chunk)
                    else:
                        # no chunk
                        break

            for i, handler in enumerate(upload_handlers):
                file_obj = handler.file_complete(counters[i])
                if file_obj:
                    if settings.FILE_UPLOAD_VIRUS_SCAN and pyclamd:
                        # virus scan
                        try:
                            if not hasattr(pyclamd, 'scan_stream'):
                                cd = pyclamd.ClamdUnixSocket()
                            else:
                                pyclamd.init_network_socket('localhost', 3310)
                                cd = pyclamd

                            # We need to get a file object for clamav. We might have a path or we might
                            # have to read the data into memory.
                            if hasattr(file_obj, 'temporary_file_path'):
                                os.chmod(file_obj.temporary_file_path(), 0664)
                                result = cd.scan_file(file_obj.temporary_file_path())
                            else:
                                if hasattr(file_obj, 'read'):
                                    result = cd.scan_stream(file_obj.read())
                                else:
                                    result = cd.scan_stream(file_obj['content'])
                        except:
                            from socket import gethostname
                            raise Exception(_(u'unable to initialize scan engine on host %s') % gethostname())

                        if result:
                            msg = ' '.join(result[result.keys()[0]]).replace('FOUND ', '')
                            raise Exception(_(u"file is infected by virus: %s") % msg)

                    hasher = hashlib.md5()
                    # We need to get a file object for clamav. We might have a path or we might
                    # have to read the data into memory.
                    if hasattr(file_obj, 'temporary_file_path'):
                        with open(file_obj.temporary_file_path(), 'rb') as afile:
                            buf = afile.read()
                            hasher.update(buf)
                        hash = hasher.hexdigest()
                    else:
                        if hasattr(file_obj, 'read'):
                            file_obj.seek(0)
                            buf = file_obj.read()
                            hasher.update(buf)
                        else:
                            hasher.update(file_obj['content'].read())
                    hash = hasher.hexdigest()

                    if tickets_files.objects.filter(active_record=True, ticket=ticket, checksum=hash).count() > 0:
                        raise Exception('duplicate hash value - file already exists in this ticket %s' % ticket)

                    # todo: virusscan
                    f = tickets_files()
                    f.name = file_obj.name
                    f.size = file_obj.size
                    f.checksum = hash
                    f.content_type = content_type
                    f.ticket_id = ticket
                    f.public = True
                    f.save(user=request.user)

                    touch_ticket(request.user, ticket)

                    add_history(request, tic, 5, file_obj.name)

                    mail_file(request, f.pk)
                    jabber_file(request, f.pk)

                    dest = settings.FILE_UPLOAD_PATH
                    if not os.path.exists(dest):
                        os.makedirs(dest)

                    with open('%s%s.dat' % (dest, f.id), 'wb+') as destination:
                        for chunk in file_obj.chunks():
                            destination.write(chunk)

                    if 'pdf' in f.content_type:
                        convertPDFtoImg('%s/%s.dat' % (dest, f.id), '%s/%s.preview' % (dest, f.id))
                    else:
                        if 'image' not in f.content_type and isPreviewable(f.content_type):
                            try:
                                tmp = convertOfficeTpPDF('%s/%s.dat' % (dest, f.id))
                                convertPDFtoImg(tmp, '%s/%s.preview' % (dest, f.id))
                                if os.path.isfile(tmp):
                                    os.unlink(tmp)
                            except:
                                pass

                        if 'audio' in f.content_type:
                            try:
                                # https://realpython.com/python-speech-recognition/
                                import speech_recognition as sr
                                AUDIO_FILE = '%s%s.dat' % (dest, f.id)
                                r = sr.Recognizer()
                                with sr.AudioFile(AUDIO_FILE) as source:
                                    audio = r.record(source)  # read the entire audio file

                                text = r.recognize_google(audio, language='de-DE')
                                if text:
                                    com = tickets_comments()
                                    com.comment = text
                                    com.ticket_id = ticket
                                    com.action = 6
                                    com.save(user=request.user)
                            except:
                                pass

                    return HttpResponse(status=201)

                else:
                    # some indication this didn't work?
                    return HttpResponse(status=500)

        else:
            form = UploadFileForm()

        return render(request, 'tickets/file.html', {'ticketid': ticket, 'layout': 'horizontal', 'form': form})

    elif mode == 'delfile':
        file = tickets_files.objects.get(pk=request.GET['fileid'], ticket=ticket)
        file.delete(user=request.user)

        touch_ticket(request.user, ticket)

        add_history(request, tic, 8, file.name)

        return HttpResponseRedirect('/tickets/view/%s/#files' % tic.pk)

    elif mode == 'notify':
        tickets_participants.objects.filter(ticket=tic, user=request.user).update(seen=True)
        return HttpResponse('OK')

    elif mode == 'sleep':
        interval = request.GET.get('interval')
        if interval in ['1', '7', '30']:
            old = tic.show_start
            tic.show_start = timezone.now() + datetime.timedelta(days=int(interval))
            tic.save(user=request.user)

            touch_ticket(request.user, ticket)

            add_history(request, tic, 10, (tic.show_start, old))

            return HttpResponse('OK')

        else:
            raise Exception('no interval given')

    elif mode == 'ignore':
        ig = tickets_ignorants()
        ig.ticket = tic
        ig.user = request.user
        ig.save()
        return HttpResponse('OK')

    elif mode == 'todo':
        class local:
            counter = 0

        def ToDoDone(match):
            local.counter += 1
            group = match.groups()
            if local.counter == pos:
                return u'[X]'
            else:
                return u'[%s]' % group[0]

        def ToDoUnDone(match):
            local.counter += 1
            group = match.groups()
            if local.counter == pos:
                return u'[ ]'
            else:
                return u'[%s]' % group[0]

        form = ToDo(request.POST)
        if form.is_valid():
            desc = tic.description

            cd = form.cleaned_data
            text = cd['text']
            pos = cd['item']
            set = cd['set']
            if set:
                tic.description = re.sub(r'\[([ Xx])\]', ToDoDone, desc)
                old = _('undone: %s') % text
                new = _('done: %s') % text
            else:
                tic.description = re.sub(r'\[([ Xx])\]', ToDoUnDone, desc)
                new = _('undone: %s') % text
                old = _('done: %s') % text

            tic.save(user=request.user)

            touch_ticket(request.user, ticket)

            add_history(request, tic, 9, (new, old))

            data = {
                'set': set,
                'item': pos,
                'text': text,
            }
            return JsonResponse(data, safe=False)

    elif mode == 'update_comment':

        if request.method == 'POST':
            comment_id = request.GET.get("comment_id")
            comment = tickets_comments.objects.get(pk=comment_id)

            if comment.c_user == request.user:
                comment.comment = request.POST.get("comment_body", "")
                comment.edited = True
                comment.save(user=request.user)

        return HttpResponseRedirect("/tickets/view/%s/#comment_id-%s" % (ticket, comment_id))

    elif mode == 'last_modified':
        if_modified_since = request.META.get('HTTP_IF_MODIFIED_SINCE')
        if if_modified_since:
            if_modified_since = parse_http_date_safe(if_modified_since)
            if time.mktime(tic.last_action_date.timetuple()) > if_modified_since:
                return HttpResponse('outdated', status=200)
            else:
                return HttpResponse('not modified', status=304)

        else:
            return HttpResponse('unknown', status=412)
예제 #4
0
파일: tickets.py 프로젝트: crystal3a/yats
def action(request, mode, ticket):
    mod_path, cls_name = settings.TICKET_CLASS.rsplit('.', 1)
    mod_path = mod_path.split('.').pop(0)
    tic = apps.get_model(mod_path, cls_name).objects.get(pk=ticket)

    if hasattr(settings, 'KEEP_IT_SIMPLE') and settings.KEEP_IT_SIMPLE:
        keep_it_simple = True
    else:
        keep_it_simple = False

    if mode == 'view':
        if request.method == 'POST':
            form = CommentForm(request.POST)
            if form.is_valid():
                com = tickets_comments()
                com.comment = form.cleaned_data['comment']
                com.ticket_id = ticket
                com.action = 6
                com.save(user=request.user)

                check_references(request, com)

                touch_ticket(request.user, ticket)

                add_history(request, tic, 6, com.comment)

                mail_comment(request, com.pk)

            else:
                if 'resolution' in request.POST:
                    if request.POST['resolution'] and int(request.POST['resolution']) > 0:
                        tic.resolution_id = request.POST['resolution']
                        tic.closed = True
                        tic.close_date = timezone.now()
                        tic.state = get_flow_end()
                        tic.save(user=request.user)

                        com = tickets_comments()
                        com.comment = _('ticket closed - resolution: %(resolution)s\n\n%(comment)s') % {'resolution': ticket_resolution.objects.get(pk=request.POST['resolution']).name, 'comment': request.POST.get('close_comment', '')}
                        com.ticket_id = ticket
                        com.action = 1
                        com.save(user=request.user)

                        check_references(request, com)

                        touch_ticket(request.user, ticket)

                        add_history(request, tic, 1, request.POST.get('close_comment', ''))

                        mail_comment(request, com.pk)

                    else:
                        messages.add_message(request, messages.ERROR, _('no resolution selected'))

                else:
                    messages.add_message(request, messages.ERROR, _('comment invalid'))

        excludes = []
        form = TicketsForm(exclude_list=excludes, is_stuff=request.user.is_staff, user=request.user, instance=tic, customer=request.organisation.id, view_only=True)
        close = TicketCloseForm()
        reassign = TicketReassignForm(initial={'assigned': tic.assigned_id, 'state': tic.state})
        flows = list(ticket_flow_edges.objects.select_related('next').filter(now=tic.state).exclude(next__type=2).values_list('next', flat=True))
        flows.append(tic.state_id)
        reassign.fields['state'].queryset = reassign.fields['state'].queryset.filter(id__in=flows)

        participants = tickets_participants.objects.select_related('user').filter(ticket=ticket)
        comments = tickets_comments.objects.select_related('c_user').filter(ticket=ticket).order_by('c_date')

        close_allowed = ticket_flow_edges.objects.select_related('next').filter(now=tic.state, next__type=2).count() > 0

        files = tickets_files.objects.filter(ticket=ticket, active_record=True)
        paginator = Paginator(files, 10)
        page = request.GET.get('page')
        try:
            files_lines = paginator.page(page)
        except PageNotAnInteger:
            # If page is not an integer, deliver first page.
            files_lines = paginator.page(1)
        except EmptyPage:
            # If page is out of range (e.g. 9999), deliver last page of results.
            files_lines = paginator.page(paginator.num_pages)

        add_breadcrumbs(request, ticket, '#')
        if 'YATSE' in request.GET and 'isUsingYATSE' not in request.session:
            request.session['isUsingYATSE'] = True

        return render(request, 'tickets/view.html', {'layout': 'horizontal', 'ticket': tic, 'form': form, 'close': close, 'reassign': reassign, 'files': files_lines, 'comments': comments, 'participants': participants, 'close_allowed': close_allowed, 'keep_it_simple': keep_it_simple})

    elif mode == 'history':
        history = tickets_history.objects.filter(ticket=ticket)
        return render(request, 'tickets/history.html', {'layout': 'horizontal', 'ticket': tic, 'history': history, 'keep_it_simple': keep_it_simple})

    elif mode == 'reopen':
        if tic.closed:
            tic.closed = False
            tic.state = get_flow_start()
            tic.resolution = None
            tic.close_date = None
            tic.save(user=request.user)

            com = tickets_comments()
            com.comment = _('ticket reopend - resolution deleted')
            com.ticket_id = ticket
            com.action = 2
            com.save(user=request.user)

            check_references(request, com)

            touch_ticket(request.user, ticket)

            add_history(request, tic, 2, None)

            mail_comment(request, com.pk)

        return HttpResponseRedirect('/tickets/view/%s/' % ticket)

    elif mode == 'reassign':
        if not tic.closed:
            if 'assigned' in request.POST:
                if request.POST['assigned'] and int(request.POST['assigned']) > 0:
                    old_assigned_user = tic.assigned
                    old_state = tic.state

                    tic.assigned_id = request.POST['assigned']
                    tic.state = ticket_flow.objects.get(pk=request.POST['state'])
                    tic.save(user=request.user)

                    newUser = User.objects.get(pk=request.POST['assigned'])

                    com = tickets_comments()
                    com.comment = _('ticket reassigned to %(user)s\nstate now: %(state)s\n\n%(comment)s') % {'user': newUser, 'comment': request.POST.get('reassign_comment', ''), 'state': tic.state}
                    com.ticket_id = ticket
                    com.action = 7
                    com.save(user=request.user)

                    check_references(request, com)

                    touch_ticket(request.user, ticket)
                    if request.POST['assigned']:
                        touch_ticket(newUser, ticket)

                    history_data = {
                                    'old': {'comment': '', 'assigned': str(old_assigned_user), 'state': str(old_state)},
                                    'new': {'comment': request.POST.get('reassign_comment', ''), 'assigned': str(User.objects.get(pk=request.POST['assigned'])), 'state': str(tic.state)}
                                    }
                    add_history(request, tic, 7, history_data)

                    mail_comment(request, com.pk)
                else:
                    messages.add_message(request, messages.ERROR, _('missing assigned user'))

        return HttpResponseRedirect('/tickets/view/%s/' % ticket)

    elif mode == 'edit' or (mode == 'simple' and (not tic.keep_it_simple or tic.closed) and keep_it_simple):
        excludes = ['resolution']
        if request.method == 'POST':
            form = TicketsForm(request.POST, exclude_list=excludes, is_stuff=request.user.is_staff, user=request.user, instance=tic, customer=request.organisation.id)
            if form.is_valid():
                tic = form.save()

                if tic.keep_it_simple:
                    tic.keep_it_simple = False
                    tic.save(user=request.user)

                assigned = form.cleaned_data.get('assigned')
                if assigned:
                    touch_ticket(assigned, tic.pk)

                remember_changes(request, form, tic)

                touch_ticket(request.user, tic.pk)

                mail_ticket(request, tic.pk, form)

                return HttpResponseRedirect('/tickets/view/%s/' % ticket)

        else:
            form = TicketsForm(exclude_list=excludes, is_stuff=request.user.is_staff, user=request.user, instance=tic, customer=request.organisation.id)
        if 'state' in form.fields:
            form.fields['state'].queryset = form.fields['state'].queryset.exclude(type=2)
        return render(request, 'tickets/edit.html', {'ticket': tic, 'layout': 'horizontal', 'form': form})

    elif mode == 'simple':
        if request.method == 'POST':
            form = SimpleTickets(request.POST, initial={
                    'caption': tic.caption,
                    'description': tic.description,
                    'priority': tic.priority,
                    'assigned': tic.assigned
                })
            if form.is_valid():
                cd = form.cleaned_data
                tic.caption = cd['caption']
                tic.description = cd['description']
                tic.priority = cd['priority']
                tic.assigned = cd['assigned']
                tic.deadline = cd['deadline']
                tic.save(user=request.user)

                if cd['assigned']:
                    touch_ticket(cd['assigned'], tic.pk)

                remember_changes(request, form, tic)

                touch_ticket(request.user, tic.pk)

                mail_ticket(request, tic.pk, form)

                return HttpResponseRedirect('/tickets/view/%s/' % ticket)

        else:
            form = SimpleTickets(initial={
                    'caption': tic.caption,
                    'description': tic.description,
                    'priority': tic.priority,
                    'assigned': tic.assigned,
                    'deadline': tic.deadline,
                })
        return render(request, 'tickets/edit.html', {'ticket': tic, 'layout': 'horizontal', 'form': form, 'mode': mode})

    elif mode == 'download':
        fileid = request.GET.get('file', -1)
        file_data = tickets_files.objects.get(id=fileid, ticket=ticket)
        src = '%s%s.dat' % (settings.FILE_UPLOAD_PATH, fileid)
        content_type = file_data.content_type
        if request.GET.get('preview') == 'yes' and os.path.isfile('%s%s.preview' % (settings.FILE_UPLOAD_PATH, fileid)):
            src = '%s%s.preview' % (settings.FILE_UPLOAD_PATH, fileid)
            content_type = 'imgae/png'

        if request.GET.get('resize', 'no') == 'yes' and ('image' in file_data.content_type or 'pdf' in file_data.content_type):
            img = resize_image('%s' % (src), (200, 150), 75)
            output = io.BytesIO()
            img.save(output, 'PNG')
            output.seek(0)
            response = StreamingHttpResponse(output, content_type='image/png')

        else:
            response = StreamingHttpResponse(open('%s' % (src), "rb"), content_type=content_type)

        if request.GET.get('preview') == 'yes' and os.path.isfile('%s%s.preview' % (settings.FILE_UPLOAD_PATH, fileid)):
            response['Content-Disposition'] = 'attachment;filename=%s' % content_type
        else:
            response['Content-Disposition'] = 'attachment;filename=%s' % smart_str(file_data.name)
        return response

    elif mode == 'upload':
        if request.method == 'POST':
            form = UploadFileForm(request.POST, request.FILES)
            if form.is_valid():
                if tickets_files.objects.filter(active_record=True, ticket=ticket, checksum=request.FILES['file'].hash).count() > 0:
                    messages.add_message(request, messages.ERROR, _('File already exists: %s') % request.FILES['file'].name)
                    if request.GET.get('Ajax') == '1':
                        return HttpResponse('OK')
                    return HttpResponseRedirect('/tickets/view/%s/' % ticket)
                f = tickets_files()
                f.name = request.FILES['file'].name
                f.size = request.FILES['file'].size
                f.checksum = request.FILES['file'].hash
                f.content_type = request.FILES['file'].content_type
                f.ticket_id = ticket
                f.public = True
                f.save(user=request.user)

                touch_ticket(request.user, ticket)

                add_history(request, tic, 5, request.FILES['file'].name)

                mail_file(request, f.pk)

                dest = settings.FILE_UPLOAD_PATH
                if not os.path.exists(dest):
                    os.makedirs(dest)

                with open('%s%s.dat' % (dest, f.id), 'wb+') as destination:
                    for chunk in request.FILES['file'].chunks():
                        destination.write(chunk)

                if 'pdf' in f.content_type:
                    convertPDFtoImg('%s/%s.dat' % (dest, f.id), '%s/%s.preview' % (dest, f.id))
                else:
                    if 'image' not in f.content_type:
                        tmp = convertOfficeTpPDF('%s/%s.dat' % (dest, f.id))
                        convertPDFtoImg(tmp, '%s/%s.preview' % (dest, f.id))
                        os.unlink(tmp)

                return HttpResponseRedirect('/tickets/view/%s/' % tic.pk)

            else:
                msg = unicode(form.errors['file'])
                msg = re.sub('<[^<]+?>', '', msg)
                messages.add_message(request, messages.ERROR, msg)
                if request.GET.get('Ajax') == '1':
                    return HttpResponse('OK')
                return HttpResponseRedirect('/tickets/view/%s/' % ticket)
        else:
            form = UploadFileForm()

        return render(request, 'tickets/file.html', {'ticketid': ticket, 'layout': 'horizontal', 'form': form})

    elif mode == 'delfile':
        file = tickets_files.objects.get(pk=request.GET['fileid'], ticket=ticket)
        file.delete(user=request.user)

        touch_ticket(request.user, ticket)

        add_history(request, tic, 8, file.name)

        return HttpResponseRedirect('/tickets/view/%s/#files' % tic.pk)

    elif mode == 'remove':
            del_breadcrumbs(request)

            return HttpResponse('OK')