def rollback_vuid(request, vuid_id): if request.method == 'GET': raise Http404 if request.method == 'POST': if request.user.usersettings.creative_services or request.user.usersettings.project_manager or request.user.is_superuser: try: vuid = get_object_or_404(VUID, pk=vuid_id) result = helpers.rollback_vuid(vuid, vuid_id, vuid.project) vuid.delete() messages.success( request, 'VUID \"{0}\" has been rolled back and removed.'.format( result)) return HttpResponse(json.dumps({'success': True})) except Exception as e: return HttpResponse( json.dumps({ 'success': False, 'error': e.message })) else: return HttpResponse( json.dumps({ 'success': False, 'error': 'You have no authority to perform this operation.' }))
def users(request): """View for user management dashboard""" if request.method == 'GET': return render(request, "settings/users.html", {'users': User.objects.all().order_by('username')}) elif request.method == 'POST': if "update_user" in request.POST: uid = request.POST.get('uid', "") if uid: user = get_object_or_404(User, pk=uid) user.is_active = request.POST.get('is_active', False) user.is_staff = request.POST.get('is_staff', False) user.usersettings.creative_services = request.POST.get('is_cs', False) user.usersettings.project_manager = request.POST.get('is_pm', False) user.is_superuser = request.POST.get('is_superuser', False) user.save() user.usersettings.save() messages.success(request, "Updated user \"{0}\"".format(user.username)) return redirect("settings:users") messages.danger(request, "Unable to delete user") return render(request, "settings/users.html", {'users': User.objects.all().order_by("username")}) elif "delete_user" in request.POST: uid = request.POST.get('uid', "") if uid: user = get_object_or_404(User, pk=uid) user.delete() messages.success(request, "User \"{0}\" has been deleted".format(user.username)) return redirect("settings:users") messages.danger(request, "Unable to delete user") return render(request, "settings/users.html", {'users': User.objects.all().order_by("username")}) return HttpResponseNotFound()
def delete_slot(request, slot_id): if request.method == 'GET': raise Http404 if request.method == 'POST': if request.user.usersettings.creative_services or request.user.usersettings.project_manager or request.user.is_superuser: try: slot = get_object_or_404(VoiceSlot, pk=slot_id) slot.delete() messages.success( request, 'Voice Slot \"{0}\" has been deleted.'.format(slot.name)) return HttpResponse(json.dumps({'success': True})) except Exception as e: return HttpResponse( json.dumps({ 'success': False, 'error': e.message })) else: return HttpResponse( json.dumps({ 'success': False, 'error': 'You have no authority to perform this operation.' }))
def fetch(request, pid): if request.method == 'GET': p = get_object_or_404(Project, pk=pid) if p.bravo_server: try: with pysftp.Connection( p.bravo_server.address, username=p.bravo_server.account, private_key=settings.PRIVATE_KEY) as sftp: result = helpers.fetch_slots_from_server( p, sftp, request.user) if result['valid']: messages.success(request, result["message"]) Action.log(request.user, Action.UPDATE_FILE_STATUSES, 'File status update ran', p) else: messages.danger(request, result['message']) return redirect("projects:project", pid) except pysftp.ConnectionException: messages.danger( request, "Connection error to server \"{0}\"".format( p.bravo_server.name)) return redirect("projects:project", pid) except pysftp.CredentialException: messages.danger( request, "Credentials error to server \"{0}\"".format( p.bravo_server.name)) return redirect("projects:project", pid) except pysftp.AuthenticationException: messages.danger( request, "Authentication error to server \"{0}\"".format( p.bravo_server.name)) return redirect("projects:project", pid) except pysftp.SSHException: messages.danger( request, "SSH error to server \"{0}\"".format(p.bravo_server.name)) return redirect("projects:project", pid) messages.danger(request, "No server associated with project") return redirect("projects:project", pid) return HttpResponseNotFound()
def able_update_file_status(request, p): try: with pysftp.Connection(p.bravo_server.address, username=p.bravo_server.account, private_key=settings.PRIVATE_KEY) as sftp: result = helpers.fetch_slots_from_server(p, sftp, request.user) if result['valid']: messages.success(request, result["message"]) Action.log(request.user, Action.UPDATE_FILE_STATUSES, 'File status update ran', p) return True else: messages.danger(request, result['message']) return False except (pysftp.ConnectionException, pysftp.CredentialException, pysftp.AuthenticationException, pysftp.SSHException): messages.danger( request, "Connection error to server \"{0}\"".format(p.bravo_server.name)) return False
def voiceslots(request, pid): if request.method == 'GET': p = get_object_or_404(Project, pk=pid) # check if update file status from bravo server if not p.voiceslots().filter(status__in=[ VoiceSlot.READY, VoiceSlot.PASS, VoiceSlot.FAIL, VoiceSlot.MISSING ]).exists(): messages.danger(request, 'Please update file statuses from bravo server') return redirect('projects:project', pid=pid) lang = request.GET.get('language', 'master').strip().lower() if lang == 'master' or lang in p.language_list(): if request.GET.get('export', False) == 'csv': return contexts.context_language_csv( p, HttpResponse(content_type='text/csv'), lang) return render( request, "projects/language.html", contexts.context_language(request.user, p, language_type=lang)) if request.method == 'POST': p = get_object_or_404(Project, pk=pid) lang = request.GET.get('language', 'master').strip().lower() if lang == 'master' or lang in p.language_list(): vsid = request.POST.get('vsid', "") if "update_slot" in request.POST: if vsid: slot = get_object_or_404(VoiceSlot, pk=vsid) is_checkedout = request.POST.get('is_checkedout', False) if is_checkedout == slot.checked_out: messages.info( request, "Nothing to update for slot \"{0}\"".format( slot.name)) response = redirect("projects:voiceslots", pid=pid) response['Location'] += '?language={0}'.format(lang) return response if request.POST.get('is_checkedout', False): slot.check_out(request.user, forced=True) else: slot.check_in(request.user, forced=True) messages.success( request, "Updated voice slot \"{0}\"".format(slot.name)) response = redirect("projects:voiceslots", pid=pid) response['Location'] += '?language={0}'.format(lang) return response messages.danger(request, "Unable to update voice slot") return render(request, "projects/language.html", contexts.context_language(p, language_type=lang)) elif "retest_slot" in request.POST: if vsid: slot = get_object_or_404(VoiceSlot, pk=vsid) return redirect("projects:testslot", pid, vsid) messages.danger(request, "Unable to find voice slot") response = redirect("projects:voiceslots", pid=pid) return response elif "delete_slot" in request.POST: if vsid: slot = get_object_or_404(VoiceSlot, pk=vsid) slot.delete() return render( request, "projects/language.html", contexts.context_language(request.user, p, language_type=lang)) messages.danger(request, "Unable to find voice slot") return redirect("projects:voiceslots", pik=pid) return HttpResponseNotFound()
def submitslot(request, vsid): if request.method == 'POST': if "submit_test" in request.POST: slot = get_object_or_404(VoiceSlot, pk=vsid) p = slot.language.project slot_status = request.POST.get('slot_status', False) finish_listen_post = request.POST.get('finish_listen', 'notyet') already_listen_post = request.GET.get('listened', 'notyet') fail_select = request.GET.get('fail_select', False) if not slot_status and (finish_listen_post == 'heard' or already_listen_post == 'heard') and fail_select != 'selected': messages.danger(request, "Please enter a pass or fail") # return redirect("projects:testslot", pid=p.pk, vsid=vsid) response = redirect("projects:testslot", pid=p.pk, vsid=vsid) response['Location'] += '?listened=heard' return response if slot_status == 'pass': slot.status = VoiceSlot.PASS slot.check_in(request.user) slot.save() helpers.update_checksum(pid=p.pk, vsid=vsid, user=request.user) Action.log(request.user, Action.TESTER_PASS_SLOT, '{0} passed by manual testing'.format(slot.name), slot) # do updates to files here and get count for p pass count = p.voiceslots_match(slot, request) else: if not request.POST.get('notes', False): messages.danger(request, "Please provide notes on test failure") response = redirect("projects:testslot", pid=p.pk, vsid=vsid) response[ 'Location'] += '?listened=heard&fail_select=selected' return response slot.status = VoiceSlot.FAIL slot.check_in(request.user) slot.save() helpers.update_checksum(pid=p.pk, vsid=vsid, user=request.user) Action.log(request.user, Action.TESTER_FAIL_SLOT, request.POST['notes'], slot) # do updates to files here and get count for p failure count = p.voiceslots_match(slot, request) p.failure_count += 1 p.tests_run += 1 p.save() messages.success( request, u"Tested voice slot \"{0}\", {1} matching slots updated". format(slot.name, count)) return redirect("projects:project", pid=p.pk) elif "cancel_test" in request.POST: slot = get_object_or_404(VoiceSlot, pk=vsid) slot.check_in(request.user) return redirect("projects:project", pid=slot.language.project.pk) return HttpResponseNotFound()
def queue(request, pid): if request.method == 'GET': # check if voice slot already listened finish_listen = request.GET.get('listened', 'notyet') fail_select = request.GET.get('fail_select', False) p = get_object_or_404(Project, pk=pid) # check if update file status from bravo server if not p.voiceslots().filter(status=VoiceSlot.READY).exists(): messages.danger(request, 'No files are pending test.') return redirect('projects:project', pid=pid) lang = get_object_or_404(Language, project=p, name=request.GET.get('language', '__malformed').lower()) slots_out = request.user.voiceslot_set.all() # TODO check this block if slots_out.count() > 0: slot = slots_out.order_by('?').first() if slot.language.pk == lang.pk: try: slot_file = slot.download() except IOError: slot.status = VoiceSlot.MISSING slot.save() return queue(request, pid) return render( request, "projects/testslot.html", contexts.context_testslot(request.user_agent.browser, p, slot, slot_file, finish_listen, fail_select)) else: for slot in slots_out: slot.check_in(request.user) slot = lang.voiceslot_set.filter( status=VoiceSlot.READY, checked_out=False).order_by('?').first() # check if all voice slots have been tested if not slot: messages.warning(request, 'No new voice slots available to be tested') return redirect('projects:project', pid=pid) # check if project has default bravo server if not p.bravo_server: messages.warning(request, 'Please set default bravo server') return redirect('projects:project', pid=pid) try: slot_file = slot.download() except IOError: slot.status = VoiceSlot.MISSING slot.save() return queue(request, pid) return render( request, "projects/testslot.html", contexts.context_testslot(request.user_agent.browser, p, slot, slot_file, finish_listen, fail_select)) elif request.method == 'POST': p = get_object_or_404(Project, pk=pid) lang = get_object_or_404(Language, project=p, name=request.GET.get('language', '__malformed').lower()) tested_slot = get_object_or_404(VoiceSlot, pk=request.POST.get('slot-id', -1)) if "cancel_test" in request.POST: tested_slot.check_in(request.user) return redirect("projects:project", pid=pid) elif "submit_test" in request.POST: test_result = request.POST.get('slot_status', False) finish_listen_post = request.POST.get('finish_listen', 'notyet') already_listen_post = request.GET.get('listened', 'notyet') fail_select = request.GET.get('fail_select', False) # finish_listen to check if finish listened without Pass/Fail selection if not test_result and (finish_listen_post == 'heard' or already_listen_post == 'heard') and fail_select != 'selected': messages.danger(request, "Please enter a pass or fail") return HttpResponseRedirect( reverse("projects:queue", args=(p.pk, )) + "?language=" + lang.name + '&listened=heard') elif test_result == 'pass': tested_slot.status = VoiceSlot.PASS tested_slot.check_in(request.user) tested_slot.save() Action.log( request.user, Action.TESTER_PASS_SLOT, '{0} passed in queue testing'.format(tested_slot.name), tested_slot) # do updates to files here and get count for p pass count = p.voiceslots_match(tested_slot, request) else: if not request.POST.get('notes', False): messages.danger(request, "Please provide notes on test failure") return HttpResponseRedirect( reverse("projects:queue", args=(p.pk, )) + "?language=" + lang.name + '&listened=heard&fail_select=selected') tested_slot.status = VoiceSlot.FAIL tested_slot.check_in(request.user) tested_slot.save() Action.log(request.user, Action.TESTER_FAIL_SLOT, request.POST['notes'], tested_slot) # do updates to files here and get count for p failure count = p.voiceslots_match(tested_slot, request) p.failure_count += 1 p.tests_run += 1 p.save() if count > 0: messages.success(request, "{0} matching slots updated".format(count)) slot_filter = lang.voiceslot_set.filter(status=VoiceSlot.READY, checked_out=False) if slot_filter.count() > 0: slot = slot_filter.order_by('?').first() else: ten_minutes_ago = datetime.now() - timedelta(minutes=10) slot_filter = lang.voiceslot_set.filter( status=VoiceSlot.READY, checked_out=True, checked_out_time__lte=ten_minutes_ago) if slot_filter.count() > 0: slot = slot_filter.order_by('?').first() else: messages.success( request, "All slots in this language are tested or recently checked out for testing." ) return redirect("projects:project", pid=pid) slot_file = slot.download() # reset if finish listen to not yet #finish_listen = 'notyet' #fail_select = False #return render(request, "projects/testslot.html", contexts.context_testslot(request.user_agent.browser, p, slot, slot_file, finish_listen, fail_select)) return HttpResponseRedirect( reverse("projects:queue", args=(p.pk, )) + "?language=" + lang.name) else: return HttpResponseNotFound()
def project(request, pid): if request.method == 'GET': p = get_object_or_404(Project, pk=pid) # status = UpdateStatus.objects.get_or_create(project=p)[0] # if status.running: # status.running = False # status.save() return render( request, "projects/project.html", contexts.context_project( p, server_form=ServerForm( initial={'server': p.current_server_pk()}))) elif request.method == 'POST': messages.danger(request, '1') if "update_server" in request.POST: form = ServerForm(request.POST) p = get_object_or_404(Project, pk=pid) if form.is_valid(): server = form.cleaned_data['server'] if server is None: if p.bravo_server is None: return redirect("projects:project", pid=pid) p.bravo_server = None p.save() else: if p.bravo_server is not None: if server == p.bravo_server.name: return redirect("projects:project", pid=pid) # force update file status from bravo server old_bravo_server = p.bravo_server p.bravo_server = Server.objects.get(name=server) p.save() if not able_update_file_status(request, p): p.bravo_server = old_bravo_server p.save() messages.warning( request, 'Cannot update file status, set Bravo Server back') return redirect("projects:project", pid=pid) Action.log(request.user, Action.UPDATE_BRAVO_SERVER, u'Bravo server updated to ' + unicode(server), p) messages.success(request, "Updated server successfully") return redirect("projects:project", pid=pid) messages.danger(request, "Unable to update server") return render(request, "projects/project.html", contexts.context_project(p, server_form=form)) elif "upload_file" in request.POST: messages.danger(request, '2') form = UploadForm(request.POST, request.FILES) p = get_object_or_404(Project, pk=pid) if form.is_valid(): messages.danger(request, '3') # if user not member in CS, PM, Superuser cannot upload if not (request.user.usersettings.creative_services or request.user.usersettings.project_manager or request.user.is_superuser): messages.danger(request, 'You have no authority to upload.') elif 'file' in request.FILES and request.FILES[ 'file'].name.endswith('.xlsx'): result = helpers.upload_vuid(form.cleaned_data['file'], request.user, p) if result['valid']: messages.success(request, result["message"]) else: messages.danger(request, result['message']) elif 'file' in request.FILES: messages.danger( request, "Invalid file type, unable to upload (must be .xlsx)") return redirect("projects:project", pid=pid) messages.danger(request, "Unable to upload file") return render( request, "projects/project.html", contexts.context_project( p, upload_form=form, server_form=ServerForm( initial={'server': p.current_server_pk()}))) elif "update_root_path" in request.POST: messages.danger(request, '4') form = ProjectRootPathForm(request.POST) p = get_object_or_404(Project, pk=pid) if form.is_valid(): root_path = form.cleaned_data['root_path'] if not os.path.isabs(root_path): messages.danger(request, 'Bravo Server Root Path Format Incorrect') return redirect('projects:project', pid=pid) #remove last slash of root path while root_path and root_path[-1] == '/': root_path = root_path[:-1] if p.root_path and not helpers.verify_update_root_path( p, root_path): messages.danger(request, 'New root path not allowed') return redirect('projects:project', pid=pid) p.root_path = root_path p.save() Action.log( request.user, Action.UPDATE_ROOT_PATH, u'Bravo server root path updated to ' + unicode(root_path), p) messages.success(request, 'Updated Bravo Server Path Successfully') return redirect('projects:project', pid=pid) messages.danger(request, '5') messages.danger( request, 'valid? ' + str(UploadForm(request.POST, request.FILES))) return redirect("projects:project", pid=pid) return HttpResponseNotFound()
def new(request): if request.method == 'GET': return render(request, "projects/new.html", contexts.context_new()) elif request.method == 'POST': if "create_project" in request.POST: form = ProjectForm(request.POST, request.FILES) if form.is_valid(): # Check if default Bravo Server exist try: bravo_server = Server.objects.get(active=True) except Server.DoesNotExist: messages.danger(request, "Please set default Bravo Server first.") return render(request, "projects/new.html", contexts.context_new(form)) n = form.cleaned_data['name'] root_path = form.cleaned_data['root_path'] if root_path and not os.path.isabs(root_path): messages.danger(request, 'Bravo Server Root Path Format Incorrect') return render(request, 'projects/new.html', contexts.context_new(form)) # remove last slash of root path while root_path and root_path[-1] == '/': root_path = root_path[:-1] p = Project(name=n) try: p.full_clean() p.save() p.users.add(request.user) p.bravo_server = bravo_server # set default bravo server p.root_path = root_path p.save() messages.success(request, "Created project") if 'file' in request.FILES and request.FILES[ 'file'].name.endswith('.xlsx'): result = helpers.upload_vuid(form.cleaned_data['file'], request.user, p) if result['valid']: messages.success(request, result["message"]) else: messages.danger(request, result['message']) elif 'file' in request.FILES: messages.danger( request, "Invalid file type, unable to upload (must be .xlsx)" ) Action.log(request.user, Action.CREATE_PROJECT, '{0} created'.format(p.name), p) return redirect("projects:project", pid=p.pk) except ValidationError as e: if 'name' in e.message_dict: messages.danger(request, e.message_dict.get('name')[0]) return render(request, "projects/new.html", contexts.context_new(form)) messages.danger(request, "Unable to create project") return render(request, "projects/new.html", contexts.context_new(form)) return HttpResponseNotFound()
def servers(request): if request.method == 'GET': return render(request, "settings/servers.html", {'servers': Server.objects.all().order_by("name"), 'server_form': ServerForm()}) elif request.method == 'POST': if "add_server" in request.POST: form = ServerForm(request.POST) if form.is_valid(): name = form.cleaned_data['name'] address = form.cleaned_data['address'] account = form.cleaned_data['account'] server = Server(name=name, address=address, account=account) try: server.full_clean() server.save() messages.success(request, "Added server to list") return redirect("settings:servers") except ValidationError as e: print e.message_dict if 'name' in e.message_dict: messages.danger(request, e.message_dict.get('name')[0]) elif 'address' in e.message_dict: messages.danger(request, e.message_dict.get('address')[0]) return render(request, "settings/servers.html", {'servers': Server.objects.all().order_by("name"), 'server_form': form}) messages.danger(request, "Unable to add server to list") return render(request, "settings/servers.html", {'servers': Server.objects.all().order_by("name"), 'server_form': form}) elif "delete_server" in request.POST: sid = request.POST.get('sid', "") if sid: server = get_object_or_404(Server, pk=sid) server.delete() messages.success(request, "Server \"{0}\" has been deleted".format(server.name)) return redirect("settings:servers") messages.danger(request, "Unable to delete server") return render(request, "settings/servers.html", {'servers': Server.objects.all().order_by("name"), 'server_form': ServerForm()}) elif "test_connection" in request.POST: sid = request.POST.get('sid', "") if sid: server = get_object_or_404(Server, pk=sid) try: with pysftp.Connection(server.address, username=str(server.account), private_key=settings.PRIVATE_KEY) as conn: conn.chdir('/') except IOError: messages.danger(request, "Unable to connect to server \"{0}\"".format(server.name)) return redirect("settings:servers") except pysftp.ConnectionException: messages.danger(request, "Connection error to server \"{0}\"".format(server.name)) return redirect("settings:servers") except pysftp.CredentialException: messages.danger(request, "Credentials error to server \"{0}\"".format(server.name)) return redirect("settings:servers") except pysftp.AuthenticationException: messages.danger(request, "Authentication error to server \"{0}\"".format(server.name)) return redirect("settings:servers") except pysftp.SSHException: messages.danger(request, "SSH error to server \"{0}\"".format(server.name)) return redirect("settings:servers") messages.success(request, "Successful connection to server \"{0}\"".format(server.name)) return redirect("settings:servers") elif "update_active" in request.POST: sid = request.POST.get('sid', "") servers = Server.objects.all() for server_active in servers: if server_active: server_active.active = False server_active.save() server = get_object_or_404(Server, pk=sid) server.active = True server.save() return redirect("settings:servers") return HttpResponseNotFound()
def servers_preprod(request): if request.method == 'GET': return render(request, "settings/servers_preprod.html", {'servers_preprod': PreprodServer.objects.all().order_by("name"), # Application type default: Producer-1, NativeVxml-2 'server_form_preprod': ServerPreprodForm(initial={'application_type': '1'})}) elif request.method == 'POST': if "add_server_preprod" in request.POST: form = ServerPreprodForm(request.POST) if form.is_valid(): name = form.cleaned_data['name'] address = form.cleaned_data['address'] account = form.cleaned_data['account'] application_type = form.cleaned_data['application_type'] server = PreprodServer(name=name, address=address, account=account, application_type=application_type ) try: server.full_clean() server.save() messages.success(request, "Added preprod server to list") return redirect("settings:servers_preprod") except ValidationError as e: if 'name' in e.message_dict: messages.danger(request, e.message_dict.get('name')[0]) elif 'address' in e.message_dict: messages.danger(request, e.message_dict.get('address')[0]) return render(request, "settings/servers_preprod.html", {'servers_preprod': PreprodServer.objects.all().order_by("name"), 'server_form_preprod': form}) messages.danger(request, "Unable to add server to list") return render(request, "settings/servers_preprod.html", {'servers_preprod': PreprodServer.objects.all().order_by("name"), 'server_form_preprod': form}) elif "delete_server_preprod" in request.POST: sid = request.POST.get('sid', "") if sid: server = get_object_or_404(PreprodServer, pk=sid) server.delete() messages.success(request, "Preprod Server \"{0}\" has been deleted".format(server.name)) return redirect("settings:servers_preprod") messages.danger(request, "Unable to delete preprod server") return render(request, "settings/servers_preprod.html", {'servers_preprod': PreprodServer.objects.all().order_by("name"), 'server_form_preprod': ServerPreprodForm() }) elif "test_connection_preprod" in request.POST: sid = request.POST.get('sid', "") if sid: server = get_object_or_404(PreprodServer, pk=sid) try: with pysftp.Connection(server.address, username=str(server.account), private_key=settings.PRIVATE_KEY) as conn: conn.chdir('/') except IOError: messages.danger(request, "Unable to connect to preprod server \"{0}\"".format(server.name)) return redirect("settings:servers_preprod") except pysftp.ConnectionException: messages.danger(request, "Connection error to preprod server \"{0}\"".format(server.name)) return redirect("settings:servers_preprod") except pysftp.CredentialException: messages.danger(request, "Credentials error to preprod server \"{0}\"".format(server.name)) return redirect("settings:servers_preprod") except pysftp.AuthenticationException: messages.danger(request, "Authentication error to preprod server \"{0}\"".format(server.name)) return redirect("settings:servers_preprod") except pysftp.SSHException: messages.danger(request, "SSH error to preprod server \"{0}\"".format(server.name)) return redirect("settings:servers_preprod") messages.success(request, "Connecting to preprod server \"{0}\"".format(server.name)) return redirect("settings:servers_preprod") return HttpResponseNotFound()