@@ -0,0 +1,16 @@ | |||
""" | |||
ASGI config for Licenseserver project. | |||
It exposes the ASGI callable as a module-level variable named ``application``. | |||
For more information on this file, see | |||
https://docs.djangoproject.com/en/3.1/howto/deployment/asgi/ | |||
""" | |||
import os | |||
from django.core.asgi import get_asgi_application | |||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'Licenseserver.settings') | |||
application = get_asgi_application() |
@@ -0,0 +1,127 @@ | |||
""" | |||
Django settings for Licenseserver project. | |||
Generated by 'django-admin startproject' using Django 3.1.4. | |||
For more information on this file, see | |||
https://docs.djangoproject.com/en/3.1/topics/settings/ | |||
For the full list of settings and their values, see | |||
https://docs.djangoproject.com/en/3.1/ref/settings/ | |||
""" | |||
from pathlib import Path | |||
import os | |||
# Build paths inside the project like this: BASE_DIR / 'subdir'. | |||
BASE_DIR = Path(__file__).resolve().parent.parent | |||
# Quick-start development settings - unsuitable for production | |||
# See https://docs.djangoproject.com/en/3.1/howto/deployment/checklist/ | |||
# SECURITY WARNING: keep the secret key used in production secret! | |||
SECRET_KEY = '#^9h3-tg+(r__c)5m9@51#iq+f!e+ifr2&(q3y_3w=-9h2aizr' | |||
# SECURITY WARNING: don't run with debug turned on in production! | |||
DEBUG = True | |||
ALLOWED_HOSTS = ['192.168.192.69', '188.195.130.70', '0.0.0.0', 'localhost', '127.0.0.1'] | |||
# Application definition | |||
INSTALLED_APPS = [ | |||
'django_crontab', | |||
'django.contrib.admin', | |||
'django.contrib.auth', | |||
'django.contrib.contenttypes', | |||
'django.contrib.sessions', | |||
'django.contrib.messages', | |||
'django.contrib.staticfiles', | |||
'health_view' | |||
] | |||
MIDDLEWARE = [ | |||
'django.middleware.security.SecurityMiddleware', | |||
'django.contrib.sessions.middleware.SessionMiddleware', | |||
'django.middleware.common.CommonMiddleware', | |||
'django.middleware.csrf.CsrfViewMiddleware', | |||
'django.contrib.auth.middleware.AuthenticationMiddleware', | |||
'django.contrib.messages.middleware.MessageMiddleware', | |||
'django.middleware.clickjacking.XFrameOptionsMiddleware', | |||
] | |||
ROOT_URLCONF = 'Licenseserver.urls' | |||
CRONJOBS = [ | |||
('*/1 * * * *', 'health_view.cron.check_exp_date', '>> /home/gabi/test.log') | |||
] | |||
TEMPLATES = [ | |||
{ | |||
'BACKEND': 'django.template.backends.django.DjangoTemplates', | |||
'DIRS': [os.path.join(BASE_DIR, 'templates')], | |||
'APP_DIRS': True, | |||
'OPTIONS': { | |||
'context_processors': [ | |||
'django.template.context_processors.debug', | |||
'django.template.context_processors.request', | |||
'django.contrib.auth.context_processors.auth', | |||
'django.contrib.messages.context_processors.messages', | |||
], | |||
}, | |||
}, | |||
] | |||
WSGI_APPLICATION = 'Licenseserver.wsgi.application' | |||
# Database | |||
# https://docs.djangoproject.com/en/3.1/ref/settings/#databases | |||
DATABASES = { | |||
'default': { | |||
'ENGINE': 'django.db.backends.sqlite3', | |||
'NAME': BASE_DIR / 'db.sqlite3', | |||
} | |||
} | |||
# Password validation | |||
# https://docs.djangoproject.com/en/3.1/ref/settings/#auth-password-validators | |||
AUTH_PASSWORD_VALIDATORS = [ | |||
{ | |||
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', | |||
}, | |||
{ | |||
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', | |||
}, | |||
{ | |||
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', | |||
}, | |||
{ | |||
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', | |||
}, | |||
] | |||
# Internationalization | |||
# https://docs.djangoproject.com/en/3.1/topics/i18n/ | |||
LANGUAGE_CODE = 'en-us' | |||
TIME_ZONE = 'Europe/Berlin' | |||
USE_I18N = True | |||
USE_L10N = True | |||
USE_TZ = True | |||
# Static files (CSS, JavaScript, Images) | |||
# https://docs.djangoproject.com/en/3.1/howto/static-files/ | |||
STATIC_URL = '/static/' | |||
LOGIN_REDIRECT_URL = '/' |
@@ -0,0 +1,27 @@ | |||
"""Licenseserver URL Configuration | |||
The `urlpatterns` list routes URLs to views. For more information please see: | |||
https://docs.djangoproject.com/en/3.1/topics/http/urls/ | |||
Examples: | |||
Function views | |||
1. Add an import: from my_app import views | |||
2. Add a URL to urlpatterns: path('', views.home, name='home') | |||
Class-based views | |||
1. Add an import: from other_app.views import Home | |||
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') | |||
Including another URLconf | |||
1. Import the include() function: from django.urls import include, path | |||
2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) | |||
""" | |||
from django.contrib import admin | |||
from django.urls import path, include | |||
from django.views.generic import RedirectView | |||
from django.conf import settings | |||
from django.conf.urls.static import static | |||
urlpatterns = [ | |||
path('admin/', admin.site.urls), | |||
path('health_view/', include('health_view.urls')), | |||
path('', RedirectView.as_view(url='health_view/')), | |||
path('accounts/', include('django.contrib.auth.urls')) | |||
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) |
@@ -0,0 +1,16 @@ | |||
""" | |||
WSGI config for Licenseserver project. | |||
It exposes the WSGI callable as a module-level variable named ``application``. | |||
For more information on this file, see | |||
https://docs.djangoproject.com/en/3.1/howto/deployment/wsgi/ | |||
""" | |||
import os | |||
from django.core.wsgi import get_wsgi_application | |||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'Licenseserver.settings') | |||
application = get_wsgi_application() |
@@ -0,0 +1,5 @@ | |||
{ | |||
"presets": [ | |||
"@babel/preset-env", "@babel/preset-react" | |||
] | |||
} |
@@ -0,0 +1,26 @@ | |||
from django.contrib import admin | |||
from .models import Author, Genre, Book, BookInstance, FolderInfo, Permission, License, FolderPart | |||
#admin.site.register(Book) | |||
#admin.site.register(Author) | |||
#admin.site.register(Genre) | |||
admin.site.register(FolderInfo) | |||
admin.site.register(License) | |||
admin.site.register(FolderPart) | |||
admin.site.register(Permission) | |||
#@admin.register(BookInstance) | |||
#class BookInstanceAdmin(admin.ModelAdmin): | |||
# list_display = ('book', 'status', 'borrower', 'due_back', 'id') | |||
# list_filter = ('status', 'due_back')# | |||
# | |||
# fieldsets = ( | |||
# (None, { | |||
# 'fields': ('book','imprint', 'id') | |||
# }), | |||
# ('Availability', { | |||
# 'fields': ('status', 'due_back','borrower') | |||
# }), | |||
# ) |
@@ -0,0 +1,5 @@ | |||
from django.apps import AppConfig | |||
class HealthViewConfig(AppConfig): | |||
name = 'health_view' |
@@ -0,0 +1,50 @@ | |||
from health_view.models import * | |||
from health_view.views import check_expiration_date | |||
from datetime import datetime | |||
from health_view.crypto_functions import * | |||
import requests | |||
import json | |||
loginname_restapi = 'gabi' | |||
passwort_restapi = 'Lolo7138' | |||
def check_exp_date(): | |||
licenses = License.objects.all() | |||
date_now = datetime.now() | |||
for lic in licenses: | |||
if check_expiration_date(lic): | |||
continue | |||
licenses_same_owner = License.objects.filter(justified=lic.justified, patient=lic.patient).exclude(id=lic.id) | |||
folderparts = lic.folder_parts.all().values_list() | |||
parts_to_delete = list() | |||
for part in folderparts: | |||
delete = True | |||
for license in licenses_same_owner: | |||
if not check_expiration_date(license): | |||
continue | |||
for check_part in license.folder_parts.all().values_list(): | |||
if check_part == part: | |||
delete = False | |||
if delete is True: | |||
parts_to_delete.append(part[2]) | |||
if not parts_to_delete: | |||
lic.delete() | |||
continue | |||
new_total_key = make_encrypted_key_content_server() | |||
post_content = { | |||
'patient': lic.patient.username, | |||
'justified': lic.justified.username, | |||
'new_total_key': new_total_key, | |||
'old_total_key': lic.patient.folderinfo.content_key, | |||
'folder_parts': parts_to_delete, | |||
} | |||
lic.patient.folderinfo.content_key = new_total_key | |||
lic.patient.folderinfo.save() | |||
lic.delete() | |||
request = requests.post('http://192.168.192.75:8000/manage/delete/', json=post_content, auth=(loginname_restapi, passwort_restapi)) | |||
@@ -0,0 +1,84 @@ | |||
import os | |||
from Crypto.PublicKey import RSA | |||
from Crypto import Random | |||
from Crypto.Cipher import PKCS1_OAEP | |||
from Crypto.Hash import SHA256 | |||
from Crypto.Signature import PKCS1_v1_5 | |||
from base64 import b64decode, b64encode | |||
pub_key_contentserver = b'-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDYI/jGk6f0LAT2Z6AAQUR7izbi\na5O4Zzaz4WtK00jr3AqbZMVeVZAs+As5RS35PY2BlCuEEza/J5XX1tlbUhGk/Nzu\nyYqlID6ILEk9kUqh1A6EAuNVrcCL174BRLy620pU5m+E61za0tIr1lU+Jhy4ikVK\niGQ+na5a5g0kuzZTHwIDAQAB\n-----END PUBLIC KEY-----' | |||
pub_key_own= "-----BEGIN PUBLIC KEY-----MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCG54kIgf8wi+WLrmg0OLXTsMF7BsYjJ8+mmx1/Ml1Hts2oVoisf8iKbfcC0jWBc1aEibi7EIZK9AWEmgpIHPZpf2Ezt36KX7pjA7CDgZBye/bw+G1CaDGxrN8a18db8c16hNxHMTMiqPm7WAgoyekOzlCT6/rqF+3w2oYuGx1tmQIDAQAB-----END PUBLIC KEY-----" | |||
priv_key_own = b"""-----BEGIN RSA PRIVATE KEY----- | |||
MIICWwIBAAKBgQCG54kIgf8wi+WLrmg0OLXTsMF7BsYjJ8+mmx1/Ml1Hts2oVois | |||
f8iKbfcC0jWBc1aEibi7EIZK9AWEmgpIHPZpf2Ezt36KX7pjA7CDgZBye/bw+G1C | |||
aDGxrN8a18db8c16hNxHMTMiqPm7WAgoyekOzlCT6/rqF+3w2oYuGx1tmQIDAQAB | |||
AoGAXPatHenHW0LseidDs8jos+p4SjlOzOcgV2VJHGAum77DVh/bq1ObdJl2wMDv | |||
EjfTBR6K6I3onTovm0MzlqIuw2BR2HoVkY9dkmv8v6j17jEImHvXqAXr4GyhLdcl | |||
NAG6lZ+5BAoZskDULVPSeHY04rVMvIHWAqoE4jGIbQbZOOkCQQC2XHV1KbM9VWIf | |||
H1PkrApsBiKMDa9AXSsbolawOUmsqlG38GuFv/5E0/9dVL2kSA2hDp8WfiaIsvvM | |||
Rhe0l+obAkEAvWE/kaUBjU6aVG8EtD+pm20biO4sA6eMydhXOiREriX2mUFRRef0 | |||
y696P2Ge6GEGYSCdjwlZy/nwROQYoGsCWwJARyoHsEQorUuvseOA0qEMpCE0xCDm | |||
/iAdnXgZikWg6Z/Bqh1JaHWHHYb5hYt3Qi/YGbzh+l4aXYgzWQEVaSVLdwJAcjj9 | |||
hnLnhLssClELnUvomH4uZWCB25JrMDL0KXVGl2L+YWEsC+XjmBa2vRO8LJyYpGxv | |||
m54gMw8FBAgvclIYkQJAdV52mWKano6+ikCAw1WCEp/HB5Eiz6HU6/RLOsVxN9em | |||
cz1snA0u3qV17TrZ920gzD/2od/bzU3Hul3yDhDRgQ== | |||
-----END RSA PRIVATE KEY-----""" | |||
def make_key_pair_public(username): | |||
random_generator = Random.new().read | |||
priv_key = RSA.generate(1024, random_generator) | |||
pub_key = priv_key.publickey() | |||
usercardpath = "/tmp/smartcards/" + str(username) + ".txt" | |||
file_object = open(usercardpath, "w+") | |||
file_object.write(priv_key.exportKey().decode('utf-8')) | |||
file_object.write("\n") | |||
file_object.write(pub_key.exportKey().decode('utf-8')) | |||
file_object.close() | |||
return pub_key.exportKey().decode('utf-8') | |||
def make_key_aes(): | |||
return os.urandom(32) | |||
def make_encrypted_key_content_server(): | |||
random_key = make_key_aes() | |||
key = RSA.importKey(pub_key_contentserver) | |||
pub_key = key.publickey() | |||
encrypted_key = encrypt(random_key, pub_key) | |||
return encrypted_key.hex() | |||
def decrypt(ciphertext, priv_key): | |||
cipher = PKCS1_OAEP.new(priv_key) | |||
return cipher.decrypt(ciphertext) | |||
def encrypt(message, pub_key): | |||
cipher = PKCS1_OAEP.new(pub_key) | |||
return cipher.encrypt(message) | |||
def sign(message, priv_key): | |||
priv_key = RSA.importKey(priv_key) | |||
signer = PKCS1_v1_5.new(priv_key) | |||
hash_gen = SHA256.new() | |||
hash_gen.update(message.encode()) | |||
return b64encode(signer.sign(hash_gen)).decode('utf-8') | |||
def verify(message, signature, pub_key): | |||
pub_key = pub_key.replace("-----BEGIN PUBLIC KEY-----", "") | |||
pub_key = pub_key.replace("-----END PUBLIC KEY-----", "") | |||
pub_key = pub_key.replace(" ", "") | |||
pub_key = ('\n'.join(pub_key[i:i + 64] for i in range(0, len(pub_key), 64))) | |||
pub_key = "-----BEGIN PUBLIC KEY-----\n" + pub_key + "\n-----END PUBLIC KEY-----" | |||
signature = b64decode(signature) | |||
pub_key = RSA.importKey(pub_key) | |||
verifier = PKCS1_v1_5.new(pub_key) | |||
hash_gen = SHA256.new(message.encode()) | |||
return verifier.verify(hash_gen, signature) | |||
@@ -0,0 +1,38 @@ | |||
from django import forms | |||
from .models import License | |||
from django.db.models import Q | |||
from django.contrib.auth.models import User | |||
from health_view.models import Permission | |||
class CreateLicenseForm(forms.ModelForm): | |||
class Meta: | |||
model = License | |||
fields = ('patient', 'justified', 'exp_date', 'folder_parts', 'permissions', 'signature',) | |||
def __init__(self, current_user, *args, **kwargs): | |||
super(CreateLicenseForm, self).__init__(*args, **kwargs) | |||
license = License.objects.filter(justified=current_user).order_by('patient') | |||
conditions = Q(id='0') | |||
for li in license: | |||
print(li.patient_id) | |||
conditions |= Q(id=li.patient_id) | |||
self.fields['permissions'] = forms.ModelMultipleChoiceField(queryset=Permission.objects.all()) | |||
if License.objects.filter(justified=current_user).exists() and License.objects.filter(license_creator=current_user).exists(): | |||
self.fields['patient'].queryset = User.objects.filter(conditions).distinct() | |||
elif License.objects.filter(justified=current_user).exists(): | |||
conditions |= Q(username=current_user.username) | |||
self.fields['patient'].queryset = User.objects.filter(conditions).distinct() | |||
elif License.objects.filter(license_creator=current_user).exists(): | |||
self.fields['patient'].queryset = User.objects.filter(username="-") | |||
else: | |||
self.fields['patient'].queryset = User.objects.filter(username=current_user.username) | |||
class CreateLicenseForm_filled(forms.Form): | |||
patient = forms.CharField() | |||
justified = forms.CharField() | |||
license_creator = forms.CharField() | |||
exp_date = forms.CharField() | |||
folder_parts = forms.CharField() | |||
permissions = forms.CharField() | |||
signature = forms.CharField() |
@@ -0,0 +1,60 @@ | |||
from django.db import models | |||
from django.contrib.auth.models import User | |||
from django.dispatch import receiver | |||
from django.db.models.signals import post_save | |||
from health_view.crypto_functions import * | |||
class FolderInfo(models.Model): | |||
"""Adding attributes to default model user""" | |||
patient = models.OneToOneField(User, on_delete=models.CASCADE, null=True, blank=True) | |||
pub_key = models.CharField(max_length=300, blank=True) | |||
content_key = models.CharField(max_length=300, blank=True, default="no_key") | |||
def __str__(self): | |||
"""String for representing the Model object.""" | |||
return str(self.id) | |||
@receiver(post_save, sender=User) | |||
def create_folderinfo(sender, instance, created, **kwargs): | |||
"""Creates folderinfo when user gets created""" | |||
if created: | |||
folderinfo = FolderInfo.objects.create(patient=instance) | |||
folderinfo.pub_key = make_key_pair_public(folderinfo.patient) | |||
folderinfo.save() | |||
class Permission(models.Model): | |||
shortcut = models.CharField(max_length=5) | |||
permissions = models.CharField(max_length=100) | |||
def __str__(self): | |||
"""String for representing the Model object.""" | |||
return self.permissions | |||
class FolderPart(models.Model): | |||
shortcut = models.CharField(max_length=3) | |||
part_name = models.CharField(max_length=40) | |||
def __str__(self): | |||
"""String for representing the Model object.""" | |||
return self.part_name | |||
class License(models.Model): | |||
"""License model which defines rights""" | |||
patient = models.ForeignKey(User, on_delete=models.CASCADE, related_name='patient_id') | |||
justified = models.ForeignKey(User, default=None, on_delete=models.CASCADE, related_name='justified_id') | |||
license_creator = models.ForeignKey(User, default=None, null=True, blank=True, on_delete=models.CASCADE, related_name='license_creators') | |||
exp_date = models.CharField(max_length=200, null=True, blank=True) | |||
permissions = models.ManyToManyField(Permission) | |||
folder_parts = models.ManyToManyField(FolderPart) | |||
signature = models.CharField(max_length=200, null=True) | |||
def __str__(self): | |||
"""String for representing the Model object.""" | |||
return self.justified.get_username() + " " + ''.join(p.shortcut for p in self.permissions.all()) | |||
@@ -0,0 +1,43 @@ | |||
{ | |||
"name": "frontend", | |||
"version": "1.0.0", | |||
"description": "", | |||
"main": "index.js", | |||
"scripts": { | |||
"test": "echo \"Error: no test specified\" && exit 1", | |||
"dev": "webpack --mode development ./src/index.js --output-path ./static/frontend/", | |||
"build": "webpack --mode production ./src/index.js --output-path ./static/frontend/" | |||
}, | |||
"keywords": [], | |||
"author": "", | |||
"license": "ISC", | |||
"devDependencies": { | |||
"@babel/core": "^7.12.10", | |||
"@babel/plugin-transform-runtime": "^7.12.10", | |||
"@babel/preset-env": "^7.12.11", | |||
"@babel/preset-react": "^7.12.10", | |||
"@babel/runtime": "^7.12.5", | |||
"babel-loader": "^8.2.2", | |||
"babelify": "^10.0.0", | |||
"react": "^17.0.1", | |||
"react-dom": "^17.0.1", | |||
"webpack": "^5.11.0", | |||
"webpack-cli": "^4.2.0" | |||
}, | |||
"dependencies": { | |||
"assert": "^2.0.0", | |||
"browserify": "^17.0.0", | |||
"buffer": "^6.0.3", | |||
"buffer-browserify": "^0.2.5", | |||
"core-js": "^3.8.2", | |||
"create-react-class": "^15.7.0", | |||
"crypto": "^1.0.1", | |||
"crypto-browserify": "^3.12.0", | |||
"crypto-js": "^4.0.0", | |||
"cryptojs": "^2.5.3", | |||
"jquery": "^3.5.1", | |||
"process": "^0.11.10", | |||
"regenerator-runtime": "^0.13.7", | |||
"stream-browserify": "^3.0.0" | |||
} | |||
} |
@@ -0,0 +1,406 @@ | |||
import React from 'react'; | |||
import ReactDOM from 'react-dom'; | |||
import crypto from 'crypto'; | |||
import "core-js/stable"; | |||
import "regenerator-runtime/runtime"; | |||
import * as cryptojs from 'crypto-js'; | |||
import $ from 'jquery'; | |||
var Buffer = require('buffer').Buffer; | |||
var folderparts = 0; | |||
var permissions = "0"; | |||
var patient = 0; | |||
var justified = "0"; | |||
class Generate_Sign_Butn extends React.Component { | |||
RSASign(string_sign) { | |||
console.log(string_sign) | |||
var signerObject = crypto.createSign("RSA-SHA256"); | |||
var PrivateKey = sessionStorage.getItem('privkey') | |||
signerObject.update(string_sign); | |||
var signature = signerObject.sign(PrivateKey, false); | |||
console.log(signature); | |||
var b64encoded = btoa(String.fromCharCode.apply(null, signature)) | |||
return(b64encoded) | |||
} | |||
get_license_signed(){ | |||
var patient_id = document.getElementById('id_patient').value; | |||
var user = document.getElementById('username').innerHTML; | |||
var justified_id = document.getElementById('id_justified').value; | |||
var expdate_id = document.getElementById('id_exp_date').value; | |||
var permissions_object = document.getElementById('id_permissions') | |||
var folder_parts_object = document.getElementById('id_folder_parts') | |||
var patient_object = document.getElementById('id_patient') | |||
var justified_object = document.getElementById('id_justified') | |||
var buttsn = new Generate_Sign_Butn(); | |||
patient_id = buttsn.return_string_fromObject(patient, patient_object) | |||
justified_id = buttsn.return_string_fromObject(justified, justified_object) | |||
permissions = buttsn.return_string_fromObject(permissions, permissions_object) | |||
folderparts = buttsn.return_string_fromObject(folderparts, folder_parts_object) | |||
var signature_string = patient_id + "&" + justified_id + "&" + user + "&" + expdate_id.replace(" ", ",") + "&" + permissions + "&" + folderparts | |||
var signatured = buttsn.RSASign(signature_string) | |||
document.getElementById('id_signature').value = signatured | |||
return signatured; | |||
} | |||
return_string_fromObject(ids, element){ | |||
var object_string = ""; | |||
for (var i = 0; i < ids.length; i++){ | |||
object_string += element.options[ids[i]].text | |||
object_string += "," | |||
} | |||
object_string = object_string.substring(0, object_string.length-1) | |||
return object_string | |||
} | |||
render() { | |||
return ( | |||
<button onClick={this.get_license_signed}>Generate Signature</button> | |||
); | |||
} | |||
} | |||
function get_Params(){ | |||
var patient_id = document.getElementById('id_patient').textContent; | |||
var justified_id = document.getElementById('id_justified').textContent; | |||
var expdate_id = document.getElementById('id_exp_date').textContent; | |||
var permissions = document.getElementById('id_permission').textContent | |||
var folderparts = document.getElementById('id_folder_parts').textContent | |||
var creator = document.getElementById('id_license_creator').textContent | |||
var signature = document.getElementById('id_signature').textContent | |||
signature = signature.replaceAll("\n", "") | |||
signature = signature.replaceAll(" ", "") | |||
var content_key = document.getElementById('id_content_key').textContent | |||
content_key = content_key.replaceAll("\n", "") | |||
content_key = content_key.replaceAll(" ", "") | |||
var serversign = document.getElementById('licenseserver_sign').textContent | |||
if (serversign){ | |||
serversign = serversign.replaceAll("\n", "") | |||
serversign = serversign.replaceAll(" ", "") | |||
var sig_array = [patient_id, creator, justified_id, expdate_id, permissions, folderparts, signature, content_key, serversign]} | |||
else { | |||
var sig_array = [patient_id, creator, justified_id, expdate_id, permissions, folderparts, signature, content_key] | |||
} | |||
return sig_array; | |||
} | |||
function getPrivKey(){ | |||
var privkey = document.getElementById('privkey').value; | |||
var pubkey = document.getElementById('pubkey').value; | |||
sessionStorage.setItem("privkey", privkey); | |||
sessionStorage.setItem("pubkey", pubkey); | |||
} | |||
var submitLogin = document.getElementById('submit_login'); | |||
if(submitLogin){ | |||
if (submitLogin.attachEvent) { submitLogin.attachEvent("submit", getPrivKey)} else { | |||
submitLogin.addEventListener("submit", getPrivKey)}} | |||
var check_submit = document.getElementById('submit_button_license'); | |||
if(check_submit){ | |||
document.getElementById("id_patient").onclick = function() { | |||
patient = Array.from(this.selectedOptions).map(option => option.index) | |||
} | |||
document.getElementById("id_justified").onclick = function() { | |||
justified = Array.from(this.selectedOptions).map(option => option.index) | |||
} | |||
document.getElementById("id_folder_parts").onclick = function() { | |||
folderparts = Array.from(this.selectedOptions).map(option => option.index) | |||
} | |||
document.getElementById("id_permissions").onclick = function() { | |||
permissions = Array.from(this.selectedOptions).map(option => option.index) | |||
} | |||
} | |||
async function display_folderpart(id){ | |||
var jsonArr = [] | |||
var params = get_Params() | |||
var license = new License(params) | |||
license.serversign = params[8] | |||
jsonArr.push(license) | |||
jsonArr.push(id) | |||
var response_create = await fetch('http://192.168.192.75:8000/folder/read/', { | |||
method: 'POST', | |||
body: JSON.stringify(jsonArr), // string or object | |||
headers: { | |||
'Content-Type': 'application/json' | |||
} | |||
}) | |||
var myJason = await response_create.json() | |||
console.log(response_create) | |||
console.log(myJason.key) | |||
console.log(base64ToArrayBuffer(myJason.key)) | |||
var key = decrypt_key(base64ToArrayBuffer(myJason.key)) | |||
var enc_content = myJason.content.replace(id, "") | |||
var content = aes_decrypt(key, enc_content) | |||
console.log(content) | |||
if (license.permissions.includes("Write")) { | |||
ReactDOM.render(<div><div>{id}</div> | |||
<textarea id="check_in_data" cols="40" rows="5"></textarea> | |||
<div><button onClick={() => check_in_data(id, key, jsonArr)}>Check In</button></div></div>, document.getElementById('content_parts')) | |||
} else { | |||
ReactDOM.render(<div>{content}</div>, document.getElementById('license_cfaesontent')) | |||
} | |||
document.getElementById("check_in_data").value = content | |||
} | |||
async function check_in_data(id, key, jsonArr){ | |||
var content = document.getElementById("check_in_data").value | |||
console.log(content) | |||
var butin = new Generate_Sign_Butn() | |||
var privkey = get_priv_key() | |||
var encrypted_content = aes_encrypt(key, content) | |||
var today = new Date() | |||
var date = today.getFullYear()+'-'+(today.getMonth()+1)+'-'+today.getDate() | |||
var time = today.getHours() + ":" + today.getMinutes() + ":" + today.getSeconds() | |||
var date_time = date + "|" + time | |||
var change_signature = butin.RSASign(date_time + "|" + encrypted_content) | |||
console.log(encrypted_content) | |||
jsonArr.push(encrypted_content) | |||
jsonArr.push(date_time) | |||
jsonArr.push(change_signature) | |||
var response_create = await fetch('http://192.168.192.75:8000/folder/write/', { | |||
method: 'POST', | |||
body: JSON.stringify(jsonArr), // string or object | |||
headers: { | |||
'Content-Type': 'application/json' | |||
} | |||
}) | |||
var myJason = await response_create.json() | |||
console.log("jo") | |||
} | |||
class Buaton_API extends React.Component { | |||
async call_api (){ | |||
var jsonArr = [] | |||
var license = new License(get_Params()) | |||
folderparts = license.folderparts | |||
folderparts = folderparts.split(", ") | |||
document.getElementById("license_content").style.visibility = "visible" | |||
var i = folderparts.map((part) => { | |||
return <button id={part} onClick={() => display_folderpart(part)}>{part}</button>}) | |||
ReactDOM.render(i, document.getElementById('part_buttons')) | |||
} | |||
render() { | |||
return ( | |||
<button onClick={this.call_api}>Use License</button> | |||
); | |||
} | |||
} | |||
var readAPI = document.getElementById('use_license'); | |||
if (readAPI) { | |||
ReactDOM.render(<Buaton_API />, document.getElementById('use_license')) | |||
} | |||
var check_if_creating = document.getElementById('create_available'); | |||
if (check_if_creating) { | |||
ReactDOM.render(<Generate_Sign_Butn />, document.getElementById('create_available')) | |||
} | |||
function get_pub_key(){ | |||
var pubkey = sessionStorage.getItem('pubkey') | |||
return pubkey | |||
} | |||
function get_priv_key(){ | |||
var privkey = sessionStorage.getItem('privkey') | |||
return privkey | |||
} | |||
function get_random_key(){ | |||
var key = crypto.randomBytes(32) | |||
return key | |||
} | |||
function encrypt_key(key){ | |||
var pubkey = get_pub_key() | |||
var encryptkey = btoa(String.fromCharCode.apply(null, crypto.publicEncrypt(pubkey, key))) | |||
return encryptkey | |||
} | |||
function encrypt_key_public(key, pubkey){ | |||
var encryptkey = btoa(String.fromCharCode.apply(null, crypto.publicEncrypt(pubkey, key))) | |||
return encryptkey | |||
} | |||
function decrypt_key(key){ | |||
var priv_key = get_priv_key() | |||
var decrypted_key = btoa(String.fromCharCode.apply(null, crypto.privateDecrypt(priv_key, key))) | |||
return decrypted_key | |||
} | |||
var base64Matcher = new RegExp("^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{4})$"); | |||
function aes_encrypt(key, message){ | |||
let cfg = { | |||
mode: cryptojs.mode.ECB | |||
}; | |||
if(!base64Matcher.test(key)){ | |||
key = btoa(String.fromCharCode.apply(null, key))} | |||
var encrypted = cryptojs.AES.encrypt(message, key, cfg).toString() | |||
console.log(encrypted) | |||
return encrypted | |||
} | |||
function base64ToArrayBuffer(base64) { | |||
var binary_string = atob(base64); | |||
var len = binary_string.length; | |||
var bytes = new Uint8Array(len); | |||
for (var i = 0; i < len; i++) { | |||
bytes[i] = binary_string.charCodeAt(i); | |||
} | |||
return bytes; | |||
} | |||
function aes_decrypt(key, message){ | |||
let cfg = { | |||
mode: cryptojs.mode.ECB | |||
}; | |||
var decryptedkey = cryptojs.AES.decrypt(message, key, cfg).toString(cryptojs.enc.Utf8) | |||
return decryptedkey | |||
} | |||
class newFolder_part { | |||
constructor(part_class, encrypt_key, content){ | |||
this.part_class = part_class | |||
this.encrypted_key = encrypt_key | |||
this.content = content | |||
} | |||
} | |||
class License{ | |||
constructor(licensearr){ | |||
this.patient = licensearr[0] | |||
this.creator = licensearr[1] | |||
this.justified = licensearr[2] | |||
this.expdate = licensearr[3] | |||
this.permissions = licensearr[4] | |||
this.folderparts = licensearr[5] | |||
this.signature = licensearr[6] | |||
this.content_key = licensearr[7] | |||
} | |||
} | |||
class CreatePatientFolderButton extends React.Component { | |||
async call_api (){ | |||
const response = await fetch('http://192.168.192.75:8000/folderpartnames/') | |||
const myJason = await response.json() | |||
var data = { | |||
"part_class": "Röntgenbilder", | |||
"folder_id": "1", | |||
"part_context": "descht" | |||
} | |||
console.log(myJason) | |||
var jsonArr = [] | |||
var testkeys = [] | |||
console.log(myJason.part_name) | |||
var params = get_Params() | |||
var license = new License(params) | |||
license.serversign = params[8] | |||
jsonArr.push(license) | |||
for (var i = 0; i < myJason.results.length; i++){ | |||
var key = get_random_key() | |||
var content = aes_encrypt(key, myJason.results[i].part_name) | |||
var part = new newFolder_part(myJason.results[i].part_name, encrypt_key(key), content) | |||
jsonArr.push(part) | |||
testkeys.push(part) | |||
} | |||
var response_create = await fetch('http://192.168.192.75:8000/folder/create/', { | |||
method: 'POST', | |||
body: JSON.stringify(jsonArr), // string or object | |||
headers: { | |||
'Content-Type': 'application/json' | |||
} | |||
})} | |||
render() { | |||
return ( | |||
<button onClick={this.call_api}>CreateFolder</button> | |||
) | |||
} | |||
} | |||
var is_creating_folder = document.getElementById('create_patientfolder'); | |||
if (is_creating_folder) { | |||
ReactDOM.render(<CreatePatientFolderButton />, document.getElementById('create_patientfolder')) | |||
} | |||
class UseLicenseButton extends React.Component { | |||
async call_api (){ | |||
var jsonArr = [] | |||
var testkeys = [] | |||
var license = new License(get_Params()) | |||
folderparts = license.folderparts | |||
folderparts = folderparts.split(", ") | |||
print(folderparts) | |||
render_info = folderparts.map((part) => { | |||
return <button>{part}</button>}) | |||
ReactDOM.render(render_info, document.getElementById('call_api')) | |||
jsonArr.push(license) | |||
var response_create = await fetch('http://192.168.192.75:8000/folder/create/', { | |||
method: 'POST', | |||
body: JSON.stringify(jsonArr), // string or object | |||
headers: { | |||
'Content-Type': 'application/json' | |||
} | |||
}) | |||
} | |||
render() { | |||
return ( | |||
<button onClick={this.call_api}>UseLicense</button> | |||
) | |||
} | |||
} | |||
var needs_call_api = document.getElementById('call_api'); | |||
if (needs_call_api) { | |||
ReactDOM.render(<UseLicenseButton />, document.getElementById('call_api')) | |||
} | |||
class CreateLicenseButton extends React.Component { | |||
async call_api (){ | |||
var jsonArr = [] | |||
var params = get_Params() | |||
var license = new License(params) | |||
license.serversign = params[8] | |||
jsonArr.push(license) | |||
console.log(license.folderparts) | |||
var folderparts = license.folderparts.split(",") | |||
for (var i = 0; i < folderparts.length; i++){ | |||
var part = folderparts[i] | |||
jsonArr[1] = part | |||
jsonArr[2] = "get" | |||
var response_create = await fetch('http://192.168.192.75:8000/folder/read/', { | |||
method: 'POST', | |||
body: JSON.stringify(jsonArr), // string or object | |||
headers: { | |||
'Content-Type': 'application/json' | |||
} | |||
}) | |||
var myJason = await response_create.json() | |||
var key = decrypt_key(base64ToArrayBuffer(myJason.key)) | |||
var pubkey = myJason.pubkey | |||
pubkey = pubkey.replace("-----BEGIN PUBLIC KEY-----", "-----BEGINPUBLICKEY-----") | |||
pubkey = pubkey.replace("-----END PUBLIC KEY-----", "-----ENDPUBLICKEY-----") | |||
pubkey = pubkey.replaceAll(" ", "\n") | |||
pubkey = pubkey.replace("-----BEGINPUBLICKEY-----", "-----BEGIN PUBLIC KEY-----") | |||
pubkey = pubkey.replace("-----ENDPUBLICKEY-----", "-----END PUBLIC KEY-----") | |||
jsonArr[2] = encrypt_key_public(base64ToArrayBuffer(key), pubkey) | |||
var response_create = await fetch('http://192.168.192.75:8000/create/key/', { | |||
method: 'POST', | |||
body: JSON.stringify(jsonArr), // string or object | |||
headers: { | |||
'Content-Type': 'application/json' | |||
} | |||
}) | |||
} | |||
} | |||
render() { | |||
return ( | |||
<button onClick={this.call_api}>Create License</button> | |||
) | |||
} | |||
} | |||
var want_create_license = document.getElementById('call_api_button'); | |||
if (want_create_license) { | |||
ReactDOM.render(<CreateLicenseButton />, document.getElementById('call_api_button')) | |||
} |
@@ -0,0 +1,4 @@ | |||
var buffer = require('buffer'); | |||
var Buffer = require('buffer'); | |||
import App from "./components/App"; | |||
@@ -0,0 +1,83 @@ | |||
@import url(https://fonts.googleapis.com/css?family=Lato); | |||
.topic { | |||
font-family: Verdana,Geneva,Arial,Helvetica,sans-serif; | |||
font-size: 15px; | |||
font-style: normal; | |||
font-weight: bold; | |||
margin-bottom: 6pt; | |||
margin-left: 0pt; | |||
margin-top: 6pt; | |||
} | |||
.content { | |||
font-family: Verdana,Geneva,Arial,Helvetica,sans-serif; | |||
font-size: 15px; | |||
font-style: normal; | |||
font-weight: normal; | |||
margin-bottom: 6pt; | |||
margin-left: 25px; | |||
margin-top: 6pt; | |||
} | |||
button { | |||
background-color: rgba(54, 94, 239, 0.3); | |||
border-radius: 25px; | |||
padding: 10px; | |||
box-shadow: 0 10px 20px rgba(0, 0, 0, .7); | |||
backdrop-filter: blur(6px); | |||
border: 0; | |||
} | |||
.sidebar-nav { | |||
text-align: center; | |||
margin-top: 20px; | |||
list-style: none; | |||
flex-direction: column; | |||
list-style-type: none; | |||
background-color: rgba(54, 94, 239, 0.3); | |||
border-radius: 25px; | |||
padding: 10px; | |||
box-shadow: 0 10px 20px rgba(0, 0, 0, .7); | |||
backdrop-filter: blur(6px); | |||
} | |||
.sidebar-nav li | |||
{ | |||
padding: 6px 0; | |||
} | |||
.sidebar-nav a { | |||
position: relative; | |||
display: block; | |||
padding: 10px 0; | |||
font-family: Lato, sans-serif; | |||
color: #000000; | |||
text-decoration: none; | |||
text-transform: uppercase; | |||
transition: 0.5s; | |||
} | |||
.sidebar-nav a:after { | |||
position: absolute; | |||
content: ""; | |||
top: 100%; | |||
left: 0; | |||
width: 100%; | |||
height: 3px; | |||
background: #222222; | |||
transform: scaleX(0); | |||
transition: transform 0.5s; | |||
} | |||
.sidebar-nav a:hover, li:hover, button:hover{ | |||
color: #95a5a6; | |||
} | |||
.sidebar-nav a:hover::after { | |||
transform: scaleX(1); | |||
} | |||
@@ -0,0 +1,64 @@ | |||
<!DOCTYPE html> | |||
<html lang="en"> | |||
<head> | |||
{% block title %}<title>Gabriel's DRM</title>{% endblock %} | |||
<meta charset="utf-8"> | |||
<meta name="viewport" content="width=device-width, initial-scale=1"> | |||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css" integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2" crossorigin="anonymous"> | |||
{% load static %} | |||
<link rel="stylesheet" href="{% static 'css/styles.css' %}"> | |||
<link rel="shortcut icon" type="image/png" href="{% static 'favicon.png' %}"/> | |||
<style> | |||
{% load static %} | |||
body { | |||
background-image: url('{% static "images/wall.jpg" %}'); | |||
color: black; | |||
} | |||
.col-sm-5{ | |||
margin-top: 20px; | |||
border-radius: 25px; | |||
padding: 20px; | |||
box-shadow: 0 10px 20px rgba(0, 0, 0, .7); | |||
backdrop-filter: blur(6px); | |||
} | |||
</style> | |||
</head> | |||
<body> | |||
<div class="container-fluid"> | |||
<div class="row"> | |||
<div class="col-sm-2"> | |||
{% block sidebar %} | |||
<ul class="sidebar-nav"> | |||
<li><a href="{% url 'index' %}">Home</a></li> | |||
{% if user.is_authenticated %} | |||
<li> Username: </li> | |||
<li id="username">{{ user.get_username }}</li> | |||
<li> Folder ID: {{ user.folderinfo }}</li> | |||
<li><a href="{% url 'create-license' user.folderinfo.id %}">Create License</a></li> | |||
<li><a href="{% url 'given-licenses' %}">Given Licenses</a></li> | |||
<li><a href="{% url 'my-licenses' %}">My Licenses</a></li> | |||
<li><a href="{% url 'logout'%}?next={{request.path}}">Logout</a></li> | |||
{% else %} | |||
<li><a href="{% url 'login'%}?next={{request.path}}">Login</a></li> | |||
{% endif %} | |||
</ul> | |||
{% endblock %} | |||
</div> | |||
<div class="col-sm-5">{% block content %}{% endblock %}</div> | |||
{% if "license/show" in request.path %} | |||
<div class="col-sm-5" style="visibility: hidden" id="license_content"> | |||
<div class="row"> | |||
<div class="col-sm-3"> | |||
<div id="part_buttons"></div> | |||
</div> | |||
<div class="col-sm-6"> | |||
<div id="content_parts"></div> | |||
</div> | |||
</div> | |||
</div> | |||
{% endif %} | |||
</div> | |||
</div> | |||
<script src="{% static 'frontend/main.js' %}"></script> | |||
</body> | |||
</html> |
@@ -0,0 +1,13 @@ | |||
{% extends "base_generic.html" %} | |||
{% block content %} | |||
<h1>Creating Process...</h1> | |||
<form id="application" action="" method="post"> | |||
{% csrf_token %} | |||
<table> | |||
{{ form.as_p }} | |||
</table> | |||
<input type="submit" style="margin: 10px" value="Submit" id="submit_button_license"/> | |||
</form> | |||
<div id="create_available"/> | |||
{% endblock %} |
@@ -0,0 +1,76 @@ | |||
{% extends "base_generic.html" %} | |||
{% block content %} | |||
{% if "create" in request.path %} | |||
{% if serversign %} | |||
<h1>Licensezertificate now:</h1> | |||
{% else %} | |||
<h1>License now:</h1> | |||
{% endif %} | |||
{% else %} | |||
{% if serversign %} | |||
<h1>Licensezertificate:</h1> | |||
{% else %} | |||
<h1>License:</h1> | |||
{% endif %} | |||
{% endif %} | |||
<div class="topic" > Patient: </div> | |||
<div class="content" id="id_patient">{{patient}}</div> | |||
<div class="topic"> Justified: </div> | |||
<div class="content" id="id_justified">{{justified}}</div> | |||
<div class="topic"> License Creator: </div> | |||
<div class="content" id="id_license_creator">{{license_creator}}</div> | |||
<div class="topic"> Expiration date: </div> | |||
<div class="content" id="id_exp_date">{{exp_date}}</div> | |||
<div class="topic"> Permission: </div> | |||
<div class="content" id="id_permission">{{permission}}</div> | |||
<div class="topic"> Folder Parts: </div> | |||
<div class="content" id="id_folder_parts">{{folderparts}}</div> | |||
<div class="topic"> Signature: </div> | |||
<div class="content" id="id_signature"> | |||
{{signature.0}} | |||
{{signature.1}} | |||
{{signature.2}} | |||
{{signature.3}} | |||
</div> | |||
<div class="topic"> | |||
{% if new_folder %} | |||
New Content Key: | |||
{% else %} | |||
Content Key: | |||
{% endif %} | |||
</div> | |||
<div class="content" id="id_content_key"> | |||
{{key_split.0}} | |||
{{key_split.1}} | |||
{{key_split.2}} | |||
{{key_split.3}} | |||
</div> | |||
{% if serversign %} | |||
<div class="topic"> | |||
Licenseserver signature: | |||
</div> | |||
<div class="content" id="licenseserver_sign"> | |||
{{serversign.0}} | |||
{{serversign.1}} | |||
{{serversign.2}} | |||
{{serversign.3}} | |||
</div> | |||
{% endif %} | |||
{% if "given" in request.path %} | |||
<a href="{% url 'delete_license' %}"><button type="button" id="delete">Delete it</button></a> | |||
{% elif "own" in request.path %} | |||
<div id="use_license"></div> | |||
{% else %} | |||
{% if new_folder == True %} | |||
<div id="create_patientfolder"></div> | |||
{% else %} | |||
<div id="call_api_button"></div> | |||
{% endif %} | |||
{% endif %} | |||
{% if "show" in request.path %} | |||
{% endif %} | |||
{% endblock %} | |||
@@ -0,0 +1,20 @@ | |||
{% extends "base_generic.html" %} | |||
{% block content %} | |||
<h1>Licenses</h1> | |||
{% if license_list %} | |||
<ul> | |||
{% for license in license_list %} | |||
<li> | |||
{% if "givenlicenses" in request.path %} | |||
<a href="{% url 'license-detail-given' license.pk %}">{{ license.patient }}</a> ({{license.justified}}) | |||
{% else %} | |||
<a href="{% url 'license-detail-own' license.pk %}">{{ license.patient }}</a> ({{license.justified}}) | |||
{% endif %} | |||
</li> | |||
{% endfor %} | |||
</ul> | |||
{% else %} | |||
<p>There are no Licenses.</p> | |||
{% endif %} | |||
{% endblock %} |
@@ -0,0 +1,14 @@ | |||
{% extends "base_generic.html" %} | |||
{% block title %} | |||
<title>Gabriel's DRM</title> | |||
{% endblock %} | |||
{% block content %} | |||
<h1>Local Health View</h1> | |||
<p>Welcome to <em>Gabriel Kaufmann's </em>DRM System!</p> | |||
<h2>Dynamic content</h2> | |||
<p>The System has the following record counts:</p> | |||
<ul> | |||
<li><strong>User: </strong> {{ num_user }}</li> | |||
<li><strong>Licenses:</strong> {{ num_licenses }}</li> | |||
</ul> | |||
{% endblock %} |
@@ -0,0 +1,3 @@ | |||
from django.test import TestCase | |||
# Create your tests here. |
@@ -0,0 +1,12 @@ | |||
from django.urls import path | |||
from . import views | |||
urlpatterns = [ | |||
path('', views.index, name='index'), | |||
path('mylicenses/', views.LicenseViewOwn.as_view(), name='my-licenses'), | |||
path('givenlicenses/', views.LicenseViewGiven.as_view(), name='given-licenses'), | |||
path('license/<int:fid>/create/', views.create_license, name='create-license'), | |||
path('license/show/<int:pk>/own/', views.get_license_details, name='license-detail-own'), | |||
path('license/show/<int:pk>/given/', views.get_license_details, name='license-detail-given'), | |||
path('delete_license', views.delete_license, name='delete_license') | |||
] |
@@ -0,0 +1,184 @@ | |||
from django.http import HttpResponseRedirect, HttpResponse | |||
from django.shortcuts import render, get_object_or_404 | |||
from health_view.models import License, FolderInfo, Permission, FolderPart | |||
from django.contrib.auth.models import User | |||
from django.views import generic | |||
from datetime import datetime | |||
from health_view.crypto_functions import * | |||
from health_view.forms import CreateLicenseForm | |||
from django.contrib.auth.decorators import login_required | |||
def index(request): | |||
"""View function for home page of site.""" | |||
num_licenses = License.objects.all().count() | |||
num_user = User.objects.all().count() | |||
context = { | |||
'num_licenses': num_licenses, | |||
'num_user': num_user, | |||
} | |||
return render(request, 'index.html', context=context) | |||
class FolderInfoID(generic.ListView): | |||
model = FolderInfo | |||
def get_queryset(self): | |||
return FolderInfo.objects.get(patient=self.request.user) | |||
class LicenseViewGiven(generic.ListView): | |||
model = License | |||
def get_queryset(self): | |||
return License.objects.filter(patient=self.request.user).order_by('patient') | |||
class LicenseViewOwn(generic.ListView): | |||
model = License | |||
def get_queryset(self): | |||
return License.objects.filter(justified=self.request.user).order_by('patient') | |||
@login_required | |||
def get_license_details(request, pk): | |||
model = License | |||
if "own" in request.get_full_path(): | |||
if not License.objects.filter(pk=pk, justified=request.user).exists(): | |||
return HttpResponseRedirect('/') | |||
license = get_object_or_404(License, pk=pk, justified=request.user) | |||
if "given" in request.get_full_path(): | |||
if not License.objects.filter(pk=pk, patient=request.user).exists(): | |||
return HttpResponseRedirect('/') | |||
license = get_object_or_404(License, pk=pk, patient=request.user) | |||
exp_date = license.exp_date | |||
permission = license.permissions.all().values_list() | |||
permission_string = "" | |||
for perm in permission: | |||
permission_string += perm[2] | |||
permission_string += ", " | |||
folderparts_string = "" | |||
folderparts = license.folder_parts.all().values_list() | |||
for e in folderparts: | |||
folderparts_string += e[2] | |||
folderparts_string += ", " | |||
key = license.patient.folderinfo.content_key | |||
sig = license.signature | |||
key_split = (key[0:64], key[64:128], key[128:192], key[192:256]) | |||
sig_split = (sig[0:64], sig[64:128], sig[128:192], sig[192:256]) | |||
license_creator = license.license_creator | |||
patient = license.patient | |||
justified = license.justified | |||
if "own" in request.get_full_path(): | |||
license_string = str(patient) + "&" + str(justified) + "&" + str(license_creator.username) + "&" + str(exp_date.replace(" ", ",") ) + "&" + get_string_byanser(permission) + "&" + get_string_byanser(folderparts) + "&" + sig + "&" + key | |||
server_sign = sign(license_string, priv_key_own) | |||
serversign_split = (server_sign[0:64], server_sign[64:128], server_sign[128:192]) | |||
else: | |||
serversign_split=0 | |||
context = { | |||
'patient': patient, | |||
'justified': justified, | |||
'license_creator': license_creator, | |||
'exp_date': exp_date, | |||
'permission': permission_string[:-2], | |||
'folderparts': folderparts_string[:-2], | |||
'content_key': key, | |||
'signature': sig_split, | |||
'serversign': serversign_split, | |||
'key_split': key_split} | |||
return render(request, 'health_view/license_detail.html', context) | |||
def get_string_byrequest(index_list, model_call): | |||
objectstring = "" | |||
for i in index_list: | |||
objectstring += str(model_call.objects.get(id=i)) | |||
objectstring += "," | |||
return objectstring[:-1] | |||
def check_expiration_date(license): | |||
exp_date = license.exp_date | |||
datetime_object = "" | |||
for fmt in ('%d/%m/%Y %H:%M', '%d-%m-%Y %H:%M', '%d/%m/%Y'): | |||
try: | |||
datetime_object = datetime.strptime(exp_date, fmt) | |||
except ValueError: | |||
pass | |||
try: | |||
return datetime.now() < datetime_object | |||
except Exception: | |||
return False | |||
def get_string_byanser(model_call): | |||
objectstring = "" | |||
for i in model_call: | |||
objectstring += str(i[2]) | |||
objectstring += "," | |||
print(objectstring) | |||
return objectstring[:-1] | |||
@login_required | |||
def create_license(request, fid): | |||
model = License | |||
user = get_object_or_404(User, id=fid) | |||
if request.method == 'POST': | |||
post = request.POST.copy() # to make it mutable | |||
pubkey = request.user.folderinfo.pub_key | |||
patient = User.objects.get(id=post['patient']) | |||
justified = User.objects.get(id=post['justified']) | |||
license_creator = request.user | |||
exp_date = post['exp_date'] | |||
permission_ground = request.POST.getlist("permissions") | |||
folderparts_ground = request.POST.getlist("folder_parts") | |||
permission = get_string_byrequest(permission_ground, Permission) | |||
folderparts = get_string_byrequest(folderparts_ground, FolderPart) | |||
signature_string = str(patient) + "&" + str(justified) + "&" + str(license_creator.username) + "&" + str(exp_date.replace(" ", ",")) + "&" + permission + "&" + folderparts | |||
signature = post['signature'] | |||
new_folder = False | |||
if not verify(signature_string, signature, pubkey): | |||
form = CreateLicenseForm(request.user) | |||
context = {'form': form} | |||
return render(request, 'health_view/create_license.html', context) | |||
if request.user.folderinfo.content_key == "no_key": | |||
request.user.folderinfo.content_key = make_encrypted_key_content_server() | |||
request.user.folderinfo.save() | |||
new_folder = True | |||
new_license = License(patient=patient, justified=justified, exp_date=exp_date, license_creator=license_creator, signature=signature) | |||
new_license.save() | |||
for e in permission_ground: | |||
new_license.permissions.add(Permission.objects.get(id=e)) | |||
for i in folderparts_ground: | |||
new_license.folder_parts.add(FolderPart.objects.get(id=i)) | |||
new_license.save() | |||
request.POST = post | |||
key = request.user.folderinfo.content_key | |||
key_split = (key[0:64], key[64:128], key[128:192], key[192:256]) | |||
sig_split = (signature[0:64], signature[64:128], signature[128:192], signature[192:256]) | |||
license_string = signature_string + "&" + new_license.signature + "&" + key | |||
serversign = sign(license_string, priv_key_own) | |||
serversign_split = (serversign[0:64], serversign[64:128], serversign[128:192]) | |||
context = { | |||
'patient': patient, | |||
'justified': justified, | |||
'license_creator': license_creator, | |||
'exp_date': exp_date, | |||
'permission': permission, | |||
'folderparts': folderparts, | |||
'content_key': key, | |||
'signature': sig_split, | |||
'key_split': key_split, | |||
'serversign': serversign_split, | |||
'new_folder': new_folder} | |||
return render(request, 'health_view/license_detail.html', context) | |||
else: | |||
form = CreateLicenseForm(request.user) | |||
context = {'form': form} | |||
return render(request, 'health_view/create_license.html', context) | |||
def delete_license(request): | |||
print("test") |
@@ -0,0 +1,30 @@ | |||
const webpack = require('webpack'); | |||
module.exports = { | |||
resolve:{fallback: { "crypto": require.resolve("crypto-browserify"), | |||
"stream": require.resolve("stream-browserify"), | |||
"buffer": require.resolve("buffer-browserify"), | |||
"path": require.resolve("path-browserify"), | |||
"assert": require.resolve("assert/")}}, | |||
module: { | |||
rules: [ | |||
{ | |||
test: /\.js$/, | |||
exclude: /node_modules/, | |||
use: { | |||
loader: "babel-loader", | |||
options: { | |||
presets: ["@babel/preset-env", "@babel/preset-react"], | |||
} | |||
} | |||
} | |||
] | |||
}, | |||
plugins: [ | |||
new webpack.ProvidePlugin({ | |||
process: 'process/browser', | |||
'process.env.POUCHDB_NAME': JSON.stringify(process.env.POUCHDB_NAME || 'mydb'), | |||
}) | |||
], | |||
} |
@@ -0,0 +1,6 @@ | |||
{% extends "base_generic.html" %} | |||
{% block content %} | |||
<p>Logged out!</p> | |||
<a href="{% url 'login'%}">Click here to login again.</a> | |||
{% endblock %} |
@@ -0,0 +1,44 @@ | |||
{% extends "base_generic.html" %} | |||
{% block content %} | |||
{% if form.errors %} | |||
<p>Your username and password didn't match. Please try again.</p> | |||
{% endif %} | |||
{% if next %} | |||
{% if user.is_authenticated %} | |||
<p>Your account doesn't have access to this page. To proceed, | |||
please login with an account that has access.</p> | |||
{% else %} | |||
<p>Please login...</p> | |||
{% endif %} | |||
{% endif %} | |||
<form id="submit_login" method="post" action="{% url 'login' %}"> | |||
{% csrf_token %} | |||
<table> | |||
<tr> | |||
<td>{{ form.username.label_tag }}</td> | |||
<td>{{ form.username }}</td> | |||
</tr> | |||
<tr> | |||
<td>{{ form.password.label_tag }}</td> | |||
<td>{{ form.password }}</td> | |||
</tr> | |||
<tr> | |||
<td>Private Key :P</td> | |||
<td><textarea id="privkey" cols="40" rows="5"></textarea></td> | |||
</tr> | |||
<tr> | |||
<td>Public Key:</td> | |||
<td><textarea id="pubkey" cols="40" rows="5"></textarea> </td> | |||
</tr> | |||
</table> | |||
<input type="submit" value="login"/> | |||
<input type="hidden" name="next" value="{{ next }}" /> | |||
</form> | |||
{# Assumes you setup the password_reset view in your URLconf #} | |||
<p><a href="{% url 'password_reset' %}">Lost password?</a></p> | |||
{% endblock %} |
@@ -0,0 +1,6 @@ | |||
{% extends "base_generic.html" %} | |||
{% block content %} | |||
<h1>The password has been changed!</h1> | |||
<p><a href="{% url 'login' %}">log in again?</a></p> | |||
{% endblock %} |
@@ -0,0 +1,29 @@ | |||
{% extends "base_generic.html" %} | |||
{% block content %} | |||
{% if validlink %} | |||
<p>Please enter (and confirm) your new password.</p> | |||
<form action="" method="post"> | |||
{% csrf_token %} | |||
<table> | |||
<tr> | |||
<td>{{ form.new_password1.errors }} | |||
<label for="id_new_password1">New password:</label></td> | |||
<td>{{ form.new_password1 }}</td> | |||
</tr> | |||
<tr> | |||
<td>{{ form.new_password2.errors }} | |||
<label for="id_new_password2">Confirm password:</label></td> | |||
<td>{{ form.new_password2 }}</td> | |||
</tr> | |||
<tr> | |||
<td></td> | |||
<td><input type="submit" value="Change my password" /></td> | |||
</tr> | |||
</table> | |||
</form> | |||
{% else %} | |||
<h1>Password reset failed</h1> | |||
<p>The password reset link was invalid, possibly because it has already been used. Please request a new password reset.</p> | |||
{% endif %} | |||
{% endblock %} |
@@ -0,0 +1,5 @@ | |||
{% extends "base_generic.html" %} | |||
{% block content %} | |||
<p>We've emailed you instructions for setting your password. If they haven't arrived in a few minutes, check your spam folder.</p> | |||
{% endblock %} |
@@ -0,0 +1,2 @@ | |||
Someone asked for password reset for email {{ email }}. Follow the link below: | |||
{{ protocol}}://{{ domain }}{% url 'password_reset_confirm' uidb64=uid token=token %} |
@@ -0,0 +1,12 @@ | |||
{% extends "base_generic.html" %} | |||
{% block content %} | |||
<form action="" method="post"> | |||
{% csrf_token %} | |||
{% if form.email.errors %} | |||
{{ form.email.errors }} | |||
{% endif %} | |||
<p>{{ form.email }}</p> | |||
<input type="submit" class="btn btn-default btn-lg" value="Reset password"> | |||
</form> | |||
{% endblock %} |