Merge branch 'master' of https://git.efi.th-nuernberg.de/gitea/kaufmannga71933/DRM-fuer-ePA
This commit is contained in:
commit
30c0f32981
0
Licenseserver/drm_server/__init__.py
Normal file
0
Licenseserver/drm_server/__init__.py
Normal file
16
Licenseserver/drm_server/asgi.py
Normal file
16
Licenseserver/drm_server/asgi.py
Normal file
@ -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()
|
127
Licenseserver/drm_server/settings.py
Normal file
127
Licenseserver/drm_server/settings.py
Normal file
@ -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 = '/'
|
27
Licenseserver/drm_server/urls.py
Normal file
27
Licenseserver/drm_server/urls.py
Normal file
@ -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)
|
16
Licenseserver/drm_server/wsgi.py
Normal file
16
Licenseserver/drm_server/wsgi.py
Normal file
@ -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()
|
5
Licenseserver/health_view/.babelrc
Normal file
5
Licenseserver/health_view/.babelrc
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"presets": [
|
||||
"@babel/preset-env", "@babel/preset-react"
|
||||
]
|
||||
}
|
0
Licenseserver/health_view/__init__.py
Normal file
0
Licenseserver/health_view/__init__.py
Normal file
26
Licenseserver/health_view/admin.py
Normal file
26
Licenseserver/health_view/admin.py
Normal file
@ -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')
|
||||
# }),
|
||||
# )
|
5
Licenseserver/health_view/apps.py
Normal file
5
Licenseserver/health_view/apps.py
Normal file
@ -0,0 +1,5 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class HealthViewConfig(AppConfig):
|
||||
name = 'health_view'
|
50
Licenseserver/health_view/cron.py
Normal file
50
Licenseserver/health_view/cron.py
Normal file
@ -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))
|
||||
|
||||
|
||||
|
||||
|
84
Licenseserver/health_view/crypto_functions.py
Normal file
84
Licenseserver/health_view/crypto_functions.py
Normal file
@ -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)
|
||||
|
||||
|
38
Licenseserver/health_view/forms.py
Normal file
38
Licenseserver/health_view/forms.py
Normal file
@ -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()
|
60
Licenseserver/health_view/models.py
Normal file
60
Licenseserver/health_view/models.py
Normal file
@ -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())
|
||||
|
||||
|
4173
Licenseserver/health_view/package-lock.json
generated
Normal file
4173
Licenseserver/health_view/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
43
Licenseserver/health_view/package.json
Normal file
43
Licenseserver/health_view/package.json
Normal file
@ -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"
|
||||
}
|
||||
}
|
406
Licenseserver/health_view/src/components/App.js
Normal file
406
Licenseserver/health_view/src/components/App.js
Normal file
@ -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'))
|
||||
}
|
4
Licenseserver/health_view/src/index.js
Normal file
4
Licenseserver/health_view/src/index.js
Normal file
@ -0,0 +1,4 @@
|
||||
var buffer = require('buffer');
|
||||
var Buffer = require('buffer');
|
||||
import App from "./components/App";
|
||||
|
83
Licenseserver/health_view/static/css/styles.css
Normal file
83
Licenseserver/health_view/static/css/styles.css
Normal file
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
BIN
Licenseserver/health_view/static/favicon.png
Normal file
BIN
Licenseserver/health_view/static/favicon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.8 KiB |
BIN
Licenseserver/health_view/static/images/wall.jpg
Normal file
BIN
Licenseserver/health_view/static/images/wall.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 313 KiB |
64
Licenseserver/health_view/templates/base_generic.html
Normal file
64
Licenseserver/health_view/templates/base_generic.html
Normal file
@ -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 %}
|
14
Licenseserver/health_view/templates/index.html
Normal file
14
Licenseserver/health_view/templates/index.html
Normal file
@ -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 %}
|
3
Licenseserver/health_view/tests.py
Normal file
3
Licenseserver/health_view/tests.py
Normal file
@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
12
Licenseserver/health_view/urls.py
Normal file
12
Licenseserver/health_view/urls.py
Normal file
@ -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')
|
||||
]
|
184
Licenseserver/health_view/views.py
Normal file
184
Licenseserver/health_view/views.py
Normal file
@ -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")
|
30
Licenseserver/health_view/webpack.config.js
Normal file
30
Licenseserver/health_view/webpack.config.js
Normal file
@ -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'),
|
||||
})
|
||||
],
|
||||
}
|
6
Licenseserver/templates/registration/logged_out.html
Normal file
6
Licenseserver/templates/registration/logged_out.html
Normal file
@ -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 %}
|
44
Licenseserver/templates/registration/login.html
Normal file
44
Licenseserver/templates/registration/login.html
Normal file
@ -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 %}
|
Loading…
x
Reference in New Issue
Block a user