def delete(request, cred_id): cred = get_object_or_404(Cred, pk=cred_id) if cred.latest is not None: raise Http404 try: lastchange = CredAudit.objects.filter( cred=cred, audittype__in=[CredAudit.CREDCHANGE, CredAudit.CREDADD], ).latest().time except CredAudit.DoesNotExist: lastchange = _("Unknown (Logs deleted)") # Check user has perms (user must be member of the password owner group) if not cred.is_owned_by(request.user): raise Http404 if request.method == 'POST': CredAudit(audittype=CredAudit.CREDDELETE, cred=cred, user=request.user).save() cred.delete() return HttpResponseRedirect(reverse('cred:list')) CredAudit(audittype=CredAudit.CREDVIEW, cred=cred, user=request.user).save() return render(request, 'cred_detail.html', {'cred': cred, 'lastchange': lastchange, 'action': reverse('cred:delete', args=(cred_id,)), 'delete': True})
def edit(request, cred_id): cred = get_object_or_404(Cred, pk=cred_id) if cred.latest is not None: raise Http404 next = request.GET.get('next', None) # Check user has perms if not cred.is_visible_by(request.user): raise Http404 if request.method == 'POST': form = CredForm(request.user, request.POST, request.FILES, instance=cred) # Password change possible only for owner group if form.is_valid() and cred.group in request.user.groups.all(): # Assume metedata change chgtype = CredAudit.CREDMETACHANGE # Unless something thats not metadata changes for c in form.changed_data: if c not in Cred.METADATA: chgtype = CredAudit.CREDCHANGE # Clear pre-existing change queue items if chgtype == CredAudit.CREDCHANGE: CredChangeQ.objects.filter(cred=cred).delete() # Create audit log CredAudit(audittype=chgtype, cred=cred, user=request.user).save() form.save() # If we dont have anywhere to go, go to the details page if next is None: return HttpResponseRedirect( reverse('cred.views.detail', args=(cred.id, ))) else: return HttpResponseRedirect(next) else: form = CredForm(request.user, instance=cred) CredAudit(audittype=CredAudit.CREDPASSVIEW, cred=cred, user=request.user).save() return render( request, 'cred_edit.html', { 'form': form, 'action': reverse('cred.views.edit', args=(cred.id, )), 'next': next, 'icons': get_icon_list(), 'cred': cred, })
def add(request): if request.method == 'POST': form = CredForm(request.user, request.POST, request.FILES) if form.is_valid(): form.save() cred = form.instance # add empty extra fields before saving tags = cred.tags.all() tag_extras = [] for tag in tags: try: tag_extras += Extra.objects.filter(tag=tag.id) except: pass for ex in tag_extras: ef = ExtraField(value='', extra=ex) ef.save() cred.extrafields.add(ef) cred.save() CredAudit(audittype=CredAudit.CREDADD, cred=cred, user=request.user).save() return HttpResponseRedirect(reverse('detail', args=(cred.pk, ))) else: form = CredForm(request.user) return render(request, 'cred_edit.html', { 'form': form, 'action': reverse('add'), 'icons': get_icon_list() })
def detail(request, cred_id): cred = get_object_or_404(Cred, pk=cred_id) # Check user has perms as owner or viewer if not cred.is_visible_by(request.user): raise Http404 CredAudit(audittype=CredAudit.CREDVIEW, cred=cred, user=request.user).save() if request.user.is_staff: credlogs = cred.logs.all()[:5] morelink = reverse('staff:audit', args=('cred', cred.id)) else: credlogs = None morelink = None # User is not in the password owner group, show a read-only UI if cred.group in request.user.groups.all(): readonly = False else: readonly = True return render(request, 'cred_detail.html', { 'cred': cred, 'credlogs': credlogs, 'morelink': morelink, 'readonly': readonly, 'groups': request.user.groups, })
def download(request): if request.method == 'POST': # If the form has been submitted... # ContactForm was defined in the the previous section form = ExportForm(request.POST) # A form bound to the POST data if form.is_valid(): # All validation rules pass # Get the creds to export creds = Cred.objects.accessible(request.user) # Make the Audit logs auditlogs = [] for c in creds: auditlogs.append( CredAudit( audittype=CredAudit.CREDEXPORT, cred=c, user=request.user, )) # Create all Audit logs at once CredAudit.objects.bulk_create(auditlogs) # Give the Keepass file to the user return export_keepass(creds, form.cleaned_data['password']) else: form = ExportForm() # An unbound form return render(request, 'cred_export.html', { 'form': form, })
def addtoqueue(request, cred_id): cred = get_object_or_404(Cred, pk=cred_id) # Check user has perms (user must be member of the password owner group) if not cred.is_owned_by(request.user): raise Http404 CredChangeQ.objects.add_to_changeq(cred) CredAudit(audittype=CredAudit.CREDSCHEDCHANGE, cred=cred, user=request.user).save() return HttpResponseRedirect(reverse('cred:list', args=('special', 'changeq')))
def addtoqueue(request, cred_id): cred = get_object_or_404(Cred, pk=cred_id) # Check user has perms if not cred.is_accessible_by(request.user): raise Http404 CredChangeQ.objects.add_to_changeq(cred) CredAudit(audittype=CredAudit.CREDSCHEDCHANGE, cred=cred, user=request.user).save() return HttpResponseRedirect(reverse('cred.views.list', args=('special', 'changeq')))
def bulkdelete(request): todel = Cred.objects.filter(id__in=request.POST.getlist('credcheck')) for c in todel: if c.is_owned_by(request.user) and c.latest is None: CredAudit(audittype=CredAudit.CREDDELETE, cred=c, user=request.user).save() c.delete() redirect = request.POST.get('next', reverse('cred:list')) return HttpResponseRedirect(redirect)
def bulkaddtoqueue(request): tochange = Cred.objects.filter(id__in=request.POST.getlist('credcheck')) for c in tochange: if c.is_owned_by(request.user) and c.latest is None: CredAudit(audittype=CredAudit.CREDSCHEDCHANGE, cred=c, user=request.user).save() CredChangeQ.objects.add_to_changeq(c) redirect = request.POST.get('next', reverse('cred:list')) return HttpResponseRedirect(redirect)
def bulktagcred(request): tochange = Cred.objects.filter(id__in=request.POST.getlist('credcheck')) tag = get_object_or_404(Tag, pk=request.POST.get('tag')) for c in tochange: if c.is_owned_by(request.user) and c.latest is None: CredAudit(audittype=CredAudit.CREDMETACHANGE, cred=c, user=request.user).save() c.tags.add(tag) redirect = request.POST.get('next', reverse('cred:list')) return HttpResponseRedirect(redirect)
def bulkundelete(request): toundel = Cred.objects.filter(id__in=request.POST.getlist('credcheck')) for c in toundel: if c.is_owned_by(request.user): CredAudit(audittype=CredAudit.CREDADD, cred=c, user=request.user).save() c.is_deleted = False c.save() redirect = request.POST.get('next', reverse('cred:list')) return HttpResponseRedirect(redirect)
def add(request): if request.method == 'POST': form = CredForm(request.user, request.POST, request.FILES) if form.is_valid(): form.save() CredAudit(audittype=CredAudit.CREDADD, cred=form.instance, user=request.user).save() return HttpResponseRedirect(reverse('cred:list')) else: form = CredForm(request.user) return render(request, 'cred_edit.html', {'form': form, 'action': reverse('cred:add'), 'icons': get_icon_list()})
def download(request, cfilter="special", value="all"): if request.method == 'POST': # If the form has been submitted... form = ExportForm(request.POST) # A form bound to the POST data if form.is_valid(): # All validation rules pass # Get the creds to export (search_object, creds) = cred_search(request.user, cfilter, value) filename = 'RatticExport.kdb' # Decide on the filename if cfilter == 'tag': filename = 'RatticExportTag-%s.kdb' % search_object.name elif cfilter == 'group': filename = 'RatticExportGroup-%s.kdb' % search_object.name elif cfilter == 'search': filename = 'RatticExportSearch-%s.kdb' % search_object elif cfilter == 'special' and value == 'all': filename = 'RatticExportAll.kdb' elif cfilter == 'special' and value == 'trash': filename = 'RatticExportTrash.kdb' else: raise Http404 # Make the Audit logs auditlogs = [] for c in creds: auditlogs.append( CredAudit( audittype=CredAudit.CREDEXPORT, cred=c, user=request.user, )) # Create all Audit logs at once CredAudit.objects.bulk_create(auditlogs) # Give the Keepass file to the user return export_keepass(creds, form.cleaned_data['password'], filename) else: form = ExportForm() # An unbound form return render(request, 'cred_export.html', { 'form': form, })
def otp(request, cred_id): cred = get_object_or_404(Cred, pk=cred_id) # Check user has perms as owner or viewer if not cred.is_visible_by(request.user): raise Http404 CredAudit(audittype=CredAudit.CREDVIEWOTP, cred=cred, user=request.user).save() otp = "EMPTY" if cred.two_factor_auth_secret: otp = pyotp.totp.TOTP(cred.two_factor_auth_secret).now() return JsonResponse({"otp": otp})
def detail(request, cred_id): cred = get_object_or_404(Cred, pk=cred_id) # Check user has perms if not cred.is_accessible_by(request.user): raise Http404 CredAudit(audittype=CredAudit.CREDVIEW, cred=cred, user=request.user).save() if request.user.is_staff: credlogs = cred.logs.all()[:5] morelink = reverse('staff.views.audit', args=('cred', cred.id)) else: credlogs = None morelink = None return render(request, 'cred_detail.html', { 'cred': cred, 'credlogs': credlogs, 'morelink': morelink })
def downloadattachment(request, cred_id, typ="attachment"): # Get the credential cred = get_object_or_404(Cred, pk=cred_id) # Check user has perms if not cred.is_visible_by(request.user): raise Http404 # Make sure there is an attachment if getattr(cred, typ) is None: raise Http404 # Write the audit log, as a password view CredAudit(audittype=CredAudit.CREDPASSVIEW, cred=cred, user=request.user).save() # Send the result back in a way that prevents the browser from executing it, # forces a download, and names it the same as when it was uploaded. response = HttpResponse(mimetype='application/octet-stream') response.write(getattr(cred, typ).read()) response['Content-Disposition'] = 'attachment; filename="%s"' % getattr(cred, "%s_name" % typ) response['Content-Length'] = response.tell() return response
def edit(request, cred_id): cred = get_object_or_404(Cred, pk=cred_id) if cred.latest is not None: raise Http404 next = request.GET.get('next', None) # Check user has perms if not cred.is_visible_by(request.user): raise Http404 # generate and save extra fields for all cred's tags if empty # First let's see what Extra fields this cred already has tags = cred.tags.all() cred_extras = [] for exf in cred.extrafields.all(): cred_extras.append(exf.extra) # Let's see now what Extra fields are coming with the tags this cred has tag_extras = [] for tag in tags: try: tag_extras += Extra.objects.filter(tag=tag.id) except: pass for ex in tag_extras: if not ex in cred_extras: ef = ExtraField(value='', extra=ex) ef.save() cred.extrafields.add(ef) cred.save() # We are gonna pass this into templates cred_extra_fields = cred.extrafields.all() if request.method == 'POST': form = CredForm(request.user, request.POST, request.FILES, instance=cred) # Password change possible only for owner group if form.is_valid() and cred.group in request.user.groups.all(): # Assume metedata change chgtype = CredAudit.CREDMETACHANGE # Unless something thats not metadata changes for c in form.changed_data: if c not in Cred.METADATA: chgtype = CredAudit.CREDCHANGE # Clear pre-existing change queue items if chgtype == CredAudit.CREDCHANGE: CredChangeQ.objects.filter(cred=cred).delete() # Save extra fields post_extra_keys = request.POST.keys() # Quite an ugly way: POST brings the <input> values with names "extra_<extra_id>" post_extra_keys = filter(lambda x: 'extra_' in x, post_extra_keys) new_tag_ids = map(int, request.POST.getlist('tags', default=[])) ex_changed = False for ex_key in post_extra_keys: ex_id = ex_key.split('_')[1] e = cred.extrafields.get(extra=int(ex_id)) if not e.extra.tag.id in new_tag_ids: # We need to make sure that if some tags were removed, # their extra fields are not saved to this cred e.delete() else: new_value = request.POST.get(ex_key, default='') if new_value != e.value: ex_changed = True e.value = new_value e.save() # Create audit log # Record if extra foelds were changed if ex_changed: CredAudit(audittype=CredAudit.CREDEXTRACHANGE, cred=cred, user=request.user).save() if chgtype != CredAudit.CREDMETACHANGE: CredAudit(audittype=chgtype, cred=cred, user=request.user).save() else: CredAudit(audittype=chgtype, cred=cred, user=request.user).save() form.save() # If we dont have anywhere to go, go to the details page if next is None: return HttpResponseRedirect(reverse('detail', args=(cred.id, ))) else: return HttpResponseRedirect(next) else: form = CredForm(request.user, instance=cred) CredAudit(audittype=CredAudit.CREDPASSVIEW, cred=cred, user=request.user).save() return render( request, 'cred_edit.html', { 'form': form, 'action': reverse('edit', args=(cred.id, )), 'next': next, 'icons': get_icon_list(), 'cred': cred, 'cred_extra_fields': cred_extra_fields, })