Exemplo n.º 1
0
def view_current_note(request, name):
    """
		view_current_note views. Handle notes/view/ call GET.
		:param request: Must be <HttpRequest>
		:return:  <HttpResponse> instance
		:rtype: <HttpResponse>
	"""

    try:
        # recover encrypted symetric key
        # convert string to hexadecimal
        note = models.Notes.objects.get(
            name=name, user=User.objects.get(username=request.user.username))
        key = models.Keys.objects.get(note=note)
        cipherkey = binascii.unhexlify(key.key)

        # decrypt key with master key
        master_key = binascii.unhexlify(request.session["master_key"])
        algorithm = aes.AdvancedEncryptionStandard(master_key)
        plaintext_key = algorithm.decrypt(cipherkey)

        # convert string to hexadecimal
        # decrypt summary with symetric key
        algorithm = aes.AdvancedEncryptionStandard(plaintext_key)
        ciphersummary = binascii.unhexlify(note.summary)
        summary = algorithm.decrypt(ciphersummary)

        # update note stats
        note.views = note.views + 1
        note.save()

        context = {"note": note, "summary": summary.decode()}
        return render(request, "notes/view-note.html", context)
    except models.Notes.DoesNotExist as err:
        # appear whether note does not exist
        # add error message in request
        # tag : notes
        # errors displayed with topper.js
        messages.error(request, err, extra_tags="notes")
        return HttpResponseRedirect(reverse("view_available_notes", args=()))
Exemplo n.º 2
0
def export_all_notes(request):
    """
		export_all_notes view. Export all notes in json file.
		:param request: HttpRequest instance. Must be a HttpRequest class.
		:return: HttpResponse instance.
		:rtype: HttpResponse class.
	"""

    notes = models.Notes.objects.filter(user=User.objects.get(
        username=request.user.username))
    if len(notes) > 0:
        data = {}
        data["notes"] = []
        master_key = binascii.unhexlify(request.session["master_key"])

        for note in notes:
            key = models.Keys.objects.get(note=note)
            cipherkey = binascii.unhexlify(key.key)

            # decrypt key with master keys
            algorithm = aes.AdvancedEncryptionStandard(master_key)
            plaintext_key = algorithm.decrypt(cipherkey)

            # convert string to hexadecimal
            # decrypt summary with symetric key
            algorithm = aes.AdvancedEncryptionStandard(plaintext_key)
            ciphersummary = binascii.unhexlify(note.summary)
            summary = algorithm.decrypt(ciphersummary)

            data["notes"].append({
                "name":
                note.name,
                "summary":
                bleach.clean(summary.decode(), tags=[], strip=True),
                "published_date":
                timezone.datetime.strftime(note.published_date,
                                           format="%b. %d, %Y, %H:%m %p."),
                "updated_date":
                timezone.datetime.strftime(note.updated_date,
                                           format="%b. %d, %Y, %H:%m %p."),
                "author":
                request.user.username
            })

        date = timezone.datetime.strftime(timezone.now(),
                                          format="%Y_%M_%d_%H_%m_%S")
        filename = "-".join([request.user.username, "notes", date])

        response = HttpResponse(json.dumps(data),
                                content_type="application/json")
        response[
            "Content-Disposition"] = "attachment; filename={}.json".format(
                filename)

        return response
    else:
        # appear whether note does not exist
        # add error message in request
        # tag : profiles
        # errors displayed with topper.js
        messages.error(request, "No notes available.", extra_tags="profiles")
        return HttpResponseRedirect(reverse("view_current_profile", args=()))
Exemplo n.º 3
0
def change_current_password(request):
    """
		change_current_password view. Decrypt current keys then encrypt keys with new master key,
		update current user session and change the user password.
		:param request: HttpRequest instance. Must be a HttpRequest class.
		:return: HttpResponse instance.
		:rtype: HttpResponse class.
	"""

    try:
        form = forms.ChangePasswordForm(data=request.POST)
        if form.is_valid():
            username = bleach.clean(form.cleaned_data["username"],
                                    tags=[],
                                    strip=True)
            current_password = bleach.clean(
                form.cleaned_data["current_password"], tags=[], strip=True)
            new_password = bleach.clean(form.cleaned_data["new_password"],
                                        tags=[],
                                        strip=True)
            confirm_password = bleach.clean(
                form.cleaned_data["confirm_password"], tags=[], strip=True)

            if username == request.user.username:
                user = models.User.objects.get(username=request.user.username)
                if user.check_password(current_password):
                    if new_password == confirm_password:
                        notes = models.Notes.objects.filter(user=user)
                        current_master_key = binascii.unhexlify(
                            request.session["master_key"])

                        profile = models.Profiles.objects.get(user=user)
                        new_master_key = crypto.hashlib.pbkdf2_hmac(
                            "sha256", new_password.encode(),
                            profile.salt.encode(), 100000)

                        algorithm = aes.AdvancedEncryptionStandard(
                            current_master_key)

                        for note in notes:
                            key = models.Keys.objects.get(note=note)
                            cipherkey = binascii.unhexlify(key.key)

                            # decrypt key with master key
                            plaintext_key = algorithm.decrypt(cipherkey)
                            algorithm = aes.AdvancedEncryptionStandard(
                                new_master_key)

                            cipherkey = algorithm.encrypt(plaintext_key)
                            key.key = cipherkey.hex()
                            key.save()

                        user.set_password(new_password)
                        user.save()

                        update_session_auth_hash(request, user)
                        request.session["master_key"] = new_master_key.hex()
                    else:
                        messages.error(request,
                                       "Password does not match.",
                                       extra_tags="profiles")
                else:
                    messages.error(request,
                                   "Invalid password.",
                                   extra_tags="profiles")
            else:
                messages.error(request,
                               "Invalid username.",
                               extra_tags="profiles")
        else:
            # form errors
            # errors displayed in form
            for k, v in form.errors.items():
                messages.error(request, v.data[0].message, extra_tags=k)
    except models.User.DoesNotExist as err:
        messages.error(request, err, extra_tags="profiles")

    return HttpResponseRedirect(reverse("view_current_profile", args=()))
Exemplo n.º 4
0
def export_current_note(request, name):
    """
		export_current_note views. Handle notes/export/ page call GET. Export the note as PDF file.
		:param request: Must be <HttpRequest>
		:return: PDF file.
		:rtype: <HttpResponse>
	"""
    def render_to_pdf(template, context):
        """
			render_to_pdf.
			:param request: Must be <HttpRequest>
			:return: PDF file.
			:rtype: <HttpResponse>
		"""

        template = get_template(template)
        html = template.render(context)

        result = io.BytesIO()
        pdf = pisa.pisaDocument(io.BytesIO(html.encode("ISO-8859-1")), result)

        if pdf.err:
            return None
        else:
            return result.getvalue()

    try:
        # recover encrypted symetric key
        # convert string to hexadecimal
        note = models.Notes.objects.get(
            name=name, user=User.objects.get(username=request.user.username))
        key = models.Keys.objects.get(note=note)
        cipherkey = binascii.unhexlify(key.key)

        # decrypt key with master key
        master_key = binascii.unhexlify(request.session["master_key"])
        algorithm = aes.AdvancedEncryptionStandard(master_key)
        plaintext_key = algorithm.decrypt(cipherkey)

        # convert string to hexadecimal
        # decrypt summary with symetric key
        algorithm = aes.AdvancedEncryptionStandard(plaintext_key)
        ciphersummary = binascii.unhexlify(note.summary)
        summary = algorithm.decrypt(ciphersummary)
        context = {"note": note, "summary": summary.decode()}

        result = render_to_pdf("notes/export-note.html", context)

        if result:
            # update note stats
            note.exports = note.exports + 1
            note.save()

            return HttpResponse(result, content_type="application/pdf")
        else:
            messages.error(request,
                           "Unable to generate the PDF file.",
                           extra_tags="notes")
            return HttpResponseRedirect(
                reverse("view_current_note", args=(name, )))
    except models.Notes.DoesNotExist as err:
        # appear whether note does not exist
        # add error message in request
        # tag : notes
        # errors displayed with topper.js
        messages.error(request, err, extra_tags="notes")
        return HttpResponseRedirect(reverse("view_available_notes", args=()))
Exemplo n.º 5
0
def edit_current_note(request, name):
    """
		edit_current_note views. Edit current <Notes> entry then update the <Notes> entry fromform input.
		:param request: Must be <HttpRequest>
		:return: <HttpResponse> instance
		:rtype: <HttpResponse>
	"""

    if request.method == "GET":
        # GET call
        try:
            # recover encrypted symetric key
            # convert string to hexadecimal
            note = models.Notes.objects.get(
                name=name,
                user=User.objects.get(username=request.user.username))
            key = models.Keys.objects.get(note=note)
            cipherkey = binascii.unhexlify(key.key)

            # decrypt key with master key
            master_key = binascii.unhexlify(request.session["master_key"])
            algorithm = aes.AdvancedEncryptionStandard(master_key)
            plaintext_key = algorithm.decrypt(cipherkey)

            # convert string to hexadecimal
            # decrypt summary with symetric key
            algorithm = aes.AdvancedEncryptionStandard(plaintext_key)
            ciphersummary = binascii.unhexlify(note.summary)
            summary = algorithm.decrypt(ciphersummary)

            data = {"name": note.name, "summary": summary.decode()}
            form = forms.EditNoteForm(initial=data)

            context = {"note": note, "form": form}
            return render(request, "notes/edit-note.html", context)
        except models.Notes.DoesNotExist as err:
            # appear whether note does not exist
            # add error message in request
            # tag : notes
            # errors displayed with topper.js
            messages.error(request, err, extra_tags="notes")
            return HttpResponseRedirect(
                reverse("view_available_notes", args=()))
    else:
        # POST call
        form = forms.EditNoteForm(data=request.POST)
        if form.is_valid():
            summary = bleach.clean(
                form.cleaned_data["summary"],
                tags=const.BLEACH["AUTHORIZED_TAGS"],
                attributes=const.BLEACH["AUTHORIZED_ATTRIBUTES"],
                styles=const.BLEACH["AUTHORIZED_STYLES"],
                strip=True)

            if len(summary) > 0:
                try:
                    # recover encrypted symetric key
                    # convert string to hexadecimal
                    note = models.Notes.objects.get(
                        name=name,
                        user=User.objects.get(username=request.user.username))
                    key = models.Keys.objects.get(note=note)
                    cipherkey = binascii.unhexlify(key.key)

                    # decrypt key with master key
                    master_key = binascii.unhexlify(
                        request.session["master_key"])
                    algorithm = aes.AdvancedEncryptionStandard(master_key)
                    plaintext_key = algorithm.decrypt(cipherkey)

                    # convert string to hexadecimal
                    # decrypt summary with symetric key
                    algorithm = aes.AdvancedEncryptionStandard(plaintext_key)
                    ciphersummary = algorithm.encrypt(summary.encode())

                    note.summary = ciphersummary.hex()
                    note.updated_date = timezone.now()
                    note.changes = note.changes + 1
                    note.save()

                except models.Notes.DoesNotExist as err:
                    # appear whether note does not exist
                    # add error message in request
                    # tag : notes
                    # errors displayed with topper.js
                    messages.error(request, err, extra_tags="notes")
                    return HttpResponseRedirect(
                        reverse("view_available_notes", args=()))
            else:
                # appear whether note does not exist
                # add error message in request
                # tag : notes
                # errors displayed with topper.js
                messages.error(request,
                               "SUMMARY field is empty.",
                               extra_tags="notes")
        else:
            # form errors
            # errors displayed in form
            for k, v in form.errors.items():
                messages.error(request, v.data[0].message, extra_tags=k)

        return HttpResponseRedirect(reverse("edit_current_note",
                                            args=(name, )))
Exemplo n.º 6
0
def create_new_note(request):
    """
		create_new_note views. Create new <Notes> entry into database from form input then redirect to notes/ page.
		:param request: Must be <HttpRequest>
		:return: <HttpResponse> instance
		:rtype: <HttpResponse>
	"""

    if request.method == "GET":
        # GET call
        # create Note form
        context = {"form": forms.NewNoteForm()}
    else:
        # POST call
        # create Note form with POST inputs
        form = forms.NewNoteForm(data=request.POST)
        if form.is_valid():
            name = bleach.clean(form.cleaned_data["name"], tags=[], strip=True)
            summary = bleach.clean(
                form.cleaned_data["summary"],
                tags=const.BLEACH["AUTHORIZED_TAGS"],
                attributes=const.BLEACH["AUTHORIZED_ATTRIBUTES"],
                styles=const.BLEACH["AUTHORIZED_STYLES"],
                strip=True)

            notes = models.Notes.objects.filter(
                name=name,
                user=User.objects.get(username=request.user.username))
            if notes.exists():
                # add error message in request
                # tag : notes
                # errors displayed with topper.js
                messages.error(request,
                               "A note with this name already in use.",
                               extra_tags="notes")
            elif len(name) > 0 and len(summary) > 0:
                # generate random symetric key
                # encrypt summary with random symetric key
                key = crypto.get_random_string(const.KEYS["key"])
                algorithm = aes.AdvancedEncryptionStandard(key.encode())
                ciphersummary = algorithm.encrypt(summary.encode())

                # create note entry in database
                note = form.save(commit=False)
                note.name = name
                note.summary = ciphersummary.hex()
                note.published_date = timezone.now()
                note.updated_date = timezone.now()
                note.changes = 0
                note.views = 0
                note.exports = 0
                note.user = User.objects.get(username=request.user.username)
                note.save()

                # encrypt symetric key with master_key
                master_key = binascii.unhexlify(request.session["master_key"])
                algorithm = aes.AdvancedEncryptionStandard(master_key)
                cipherkey = algorithm.encrypt(key.encode())

                # create key entry
                models.Keys.objects.create(key=cipherkey.hex(), note=note)

                return HttpResponseRedirect(
                    reverse("view_available_notes", args=()))
            else:
                # add error message in request
                # tag : notes
                # errors displayed with topper.js
                messages.error(request,
                               "NAME or SUMMARY field is empty.",
                               extra_tags="notes")
        else:
            # form errors
            # errors displayed in form
            for k, v in form.errors.items():
                messages.error(request, v.data[0].message, extra_tags=k)

        context = {"form": form}

    return render(request, "notes/new-note.html", context)