Skip to content

Commit 53c5e09

Browse files
committed
Added encryption for note contents
1 parent 097894b commit 53c5e09

File tree

6 files changed

+167
-1
lines changed

6 files changed

+167
-1
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ A pretty easy django notes app. Have a note save it!
1010
- Easily share
1111
- Download note as PDF
1212
- Beautiful yet simple UI
13+
- Encrypted Data so that no one can phish it! ([using django-cryptography](https://github.com/georgemarshall/django-cryptography))
1314

1415
# Installation
1516

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# -*- coding: utf-8 -*-
2+
from __future__ import unicode_literals
3+
4+
from django.db import migrations, models
5+
from django_cryptography.fields import encrypt
6+
7+
app_with_model = 'notes'
8+
model_with_column = 'Note'
9+
column_to_encrypt = 'note_content'
10+
column_field_class = models.TextField
11+
column_attrs = {}
12+
column_null_status = True
13+
temporary_column = f'temp_{column_to_encrypt}'
14+
15+
def replicate_to_temporary(apps, schema_editor):
16+
Model = apps.get_model(app_with_model, model_with_column)
17+
for row in Model.objects.all():
18+
setattr(row, temporary_column, getattr(row, column_to_encrypt, None))
19+
setattr(row, column_to_encrypt, None)
20+
row.save(update_fields=[temporary_column, column_to_encrypt])
21+
22+
def replicate_to_real(apps, schema_editor):
23+
Model = apps.get_model(app_with_model, model_with_column)
24+
for row in Model.objects.all():
25+
setattr(row, column_to_encrypt, getattr(row, temporary_column))
26+
row.save(update_fields=[column_to_encrypt])
27+
28+
class Migration(migrations.Migration):
29+
30+
dependencies = [
31+
('notes', '0004_auto_20191202_1919'),
32+
]
33+
34+
operations = [
35+
# create temporary column
36+
migrations.AddField(
37+
model_name=model_with_column.lower(),
38+
name=temporary_column,
39+
field=column_field_class(
40+
verbose_name=temporary_column, null=True, **column_attrs),
41+
),
42+
# allow null entries in the real column
43+
migrations.AlterField(
44+
model_name=model_with_column.lower(),
45+
name=column_to_encrypt,
46+
field=column_field_class(
47+
verbose_name=column_to_encrypt, null=True, **column_attrs),
48+
),
49+
# push all data from real to temporary
50+
migrations.RunPython(replicate_to_temporary),
51+
# encrypt the real column (still allowing null values)
52+
migrations.AlterField(
53+
model_name=model_with_column.lower(),
54+
name=column_to_encrypt,
55+
field=encrypt(column_field_class(
56+
verbose_name=column_to_encrypt, null=True, **column_attrs)),
57+
),
58+
# push all data from temporary to real (encrypting in the processes)
59+
migrations.RunPython(replicate_to_real),
60+
# remove the temporary column
61+
migrations.RemoveField(
62+
model_name=model_with_column.lower(),
63+
name=temporary_column),
64+
# disallow null values (if applicable)
65+
migrations.AlterField(
66+
model_name=model_with_column.lower(),
67+
name=column_to_encrypt,
68+
field=encrypt(column_field_class(
69+
verbose_name=column_to_encrypt, null=column_null_status,
70+
**column_attrs)),
71+
),
72+
]
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Generated by Django 2.2.7 on 2020-02-22 03:07
2+
3+
from django.db import migrations, models
4+
import django_cryptography.fields
5+
6+
7+
class Migration(migrations.Migration):
8+
9+
dependencies = [
10+
('notes', '0005_auto_20200222_0823'),
11+
]
12+
13+
operations = [
14+
migrations.AlterField(
15+
model_name='note',
16+
name='note_content',
17+
field=django_cryptography.fields.encrypt(models.TextField(blank=True, null=True)),
18+
),
19+
]
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# Generated by Django 2.2.7 on 2020-02-22 03:15
2+
from __future__ import unicode_literals
3+
4+
from django.db import migrations, models
5+
from django_cryptography.fields import encrypt
6+
7+
app_with_model = 'notes'
8+
model_with_column = 'Note'
9+
column_to_encrypt = 'note_content'
10+
column_field_class = models.TextField
11+
column_attrs = {}
12+
column_null_status = True
13+
temporary_column = f'temp_{column_to_encrypt}'
14+
15+
def replicate_to_temporary(apps, schema_editor):
16+
Model = apps.get_model(app_with_model, model_with_column)
17+
for row in Model.objects.all():
18+
setattr(row, temporary_column, getattr(row, column_to_encrypt, None))
19+
setattr(row, column_to_encrypt, None)
20+
row.save(update_fields=[temporary_column, column_to_encrypt])
21+
22+
def replicate_to_real(apps, schema_editor):
23+
Model = apps.get_model(app_with_model, model_with_column)
24+
for row in Model.objects.all():
25+
setattr(row, column_to_encrypt, getattr(row, temporary_column))
26+
row.save(update_fields=[column_to_encrypt])
27+
28+
class Migration(migrations.Migration):
29+
30+
dependencies = [
31+
('notes', '0006_auto_20200222_0837'),
32+
]
33+
34+
operations = [
35+
# create temporary column
36+
migrations.AddField(
37+
model_name=model_with_column.lower(),
38+
name=temporary_column,
39+
field=column_field_class(
40+
verbose_name=temporary_column, null=True, **column_attrs),
41+
),
42+
# allow null entries in the real column
43+
migrations.AlterField(
44+
model_name=model_with_column.lower(),
45+
name=column_to_encrypt,
46+
field=column_field_class(
47+
verbose_name=column_to_encrypt, null=True, **column_attrs),
48+
),
49+
# push all data from real to temporary
50+
migrations.RunPython(replicate_to_temporary),
51+
# encrypt the real column (still allowing null values)
52+
migrations.AlterField(
53+
model_name=model_with_column.lower(),
54+
name=column_to_encrypt,
55+
field=encrypt(column_field_class(
56+
verbose_name=column_to_encrypt, null=True, **column_attrs)),
57+
),
58+
# push all data from temporary to real (encrypting in the processes)
59+
migrations.RunPython(replicate_to_real),
60+
# remove the temporary column
61+
migrations.RemoveField(
62+
model_name=model_with_column.lower(),
63+
name=temporary_column),
64+
# disallow null values (if applicable)
65+
migrations.AlterField(
66+
model_name=model_with_column.lower(),
67+
name=column_to_encrypt,
68+
field=encrypt(column_field_class(
69+
verbose_name=column_to_encrypt, null=column_null_status,
70+
**column_attrs)),
71+
),
72+
]

notekeeper/notes/models.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import markdown.extensions.codehilite
1515
import markdown.extensions.tables
1616
import markdown.extensions.toc
17+
from django_cryptography.fields import encrypt
1718

1819

1920
def generate_unique_slug(_class, field):
@@ -34,7 +35,7 @@ def generate_unique_slug(_class, field):
3435
class Note(models.Model):
3536
user = models.ForeignKey(User, on_delete=models.CASCADE)
3637
note_title = models.CharField(max_length=200)
37-
note_content = models.TextField(null=True, blank=True)
38+
note_content = encrypt(models.TextField(null=True, blank=True))
3839
created_at = models.DateTimeField(auto_now_add=True)
3940
updated_at = models.DateTimeField(auto_now=True)
4041
slug = models.SlugField(max_length=200, unique=True)

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,4 @@ xhtml2pdf==0.2.3
1616
Markdown==3.1.1
1717
Unidecode==1.1.1
1818
markdown-checklist==0.4.1
19+
django-cryptography==1.0

0 commit comments

Comments
 (0)