Initial commit

This commit is contained in:
2020-11-13 15:31:14 +01:00
parent 2af942da5a
commit 10e2a34143
103 changed files with 3609 additions and 0 deletions

View File

@@ -0,0 +1,45 @@
from rest_framework import viewsets, permissions, serializers
from rest_framework.permissions import BasePermission
class IsOwner(BasePermission):
def has_object_permission (self, request, view, obj ):
"""Return 'True' if permission is granted, 'False' otherwise."""
# TODO: If this is the 'way to go', we should consider adding the researcher reference to all models and save actions
return obj.researcher == request.user.researcher or obj.study.researcher == request.user.researcher
class BaseReadOnlyViewSet(viewsets.ReadOnlyModelViewSet):
permission_classes = [permissions.IsAuthenticated, IsOwner]
# TODO: If this is the 'way to go', we should consider adding the researcher reference to all models and save actions
def get_queryset(self):
try:
qs = self.queryset.filter(researcher = self.request.user.researcher)
except:
qs = self.queryset.filter(study__researcher = self.request.user.researcher)
return qs
class BaseViewSet(viewsets.ModelViewSet):
permission_classes = [permissions.IsAuthenticated, IsOwner]
# TODO: If this is the 'way to go', we should consider adding the researcher reference to all models and save actions
def get_queryset(self):
try:
qs = self.queryset.filter(researcher = self.request.user.researcher)
except:
qs = self.queryset.filter(study__researcher = self.request.user.researcher)
return qs
class BaseHyperlinkedModelSerializer(serializers.HyperlinkedModelSerializer):
# This ID field is handy to have.... Due to HyperlinkedModelSerializer we do not have this field by default
id = serializers.ReadOnlyField()
# Only show the researcher full name
researcher = serializers.StringRelatedField()
# Only show link to full researcher data
#researcher = serializers.HyperlinkedRelatedField(view_name= 'api:v1:researcher-detail', read_only=True)
# Show the full researcher information
#researcher = ResearcherSerializer(read_only=True)

View File

@@ -0,0 +1,145 @@
import requests
from requests_hawk import HawkAuth
from datetime import datetime
class VRE_API_Exception(BaseException):
def __init__(self, message, error):
# Call the base class constructor with the parameters it needs
super().__init__(message)
# Now for your custom code...
self.error = error
def __repr__(self):
return '{} ({})'.format(self.message, self.error)
class VRE_API_Exception_Factory(VRE_API_Exception):
def __new__(self, message, error_code):
if error_code == 400:
return VRE_API_400(message)
elif error_code == 403:
return VRE_API_403(message)
elif error_code == 404:
return VRE_API_404(message)
class VRE_API_400(VRE_API_Exception):
def __init__(self, message):
# Call the base class constructor with the parameters it needs
super().__init__(message, 403)
class VRE_API_403(VRE_API_Exception):
def __init__(self, message):
# Call the base class constructor with the parameters it needs
super().__init__(message, 403)
class VRE_API_404(VRE_API_Exception):
def __init__(self, message):
# Call the base class constructor with the parameters it needs
super().__init__(message, 404)
class VRE_API_Client():
DATE_TIME_FIELDS = 'created_at,updated_at,mail_sent'.split(',')
HEADERS = {
'Content-Type': 'application/json',
'cache-control': 'no-cache'
}
def __init__(self, host, url = None, token = None, secret = None):
self.host = host
self.url = url
self.token = token
self.secret = secret
self.data = {}
self.authentication = HawkAuth(id=self.token , key=self.secret)
def __get_full_url(self):
return '{}{}'.format(self.host, self.url)
def __parse_date_time_fields(self, data):
for item in data:
# TODO: Should provide better solution for this try/catch. For now it works
try:
if isinstance(item,list) or isinstance(item,dict):
self.__parse_date_time_fields(item)
elif isinstance(data[item],list) or isinstance(data[item],dict):
self.__parse_date_time_fields(data[item])
elif item in self.DATE_TIME_FIELDS and isinstance(data[item],str):
try:
data[item] = datetime.strptime(data[item],'%Y-%m-%dT%H:%M:%S.%fZ')
except Exception:
data[item] = datetime.strptime(data[item][::-1].replace(':','',1)[::-1].replace(' ','T'),'%Y-%m-%dT%H:%M:%S.%f%z')
except Exception:
pass
def __parse_data(self, start = None):
if len(self.DATE_TIME_FIELDS) > 0:
self.__parse_date_time_fields(self.data)
def set_url(self, url):
self.url = url
def set_token(self, token):
self.token = token
self.authentication = HawkAuth(id=self.token , key=self.secret)
def set_secret(self, secret):
self.secret = secret
self.authentication = HawkAuth(id=self.token , key=self.secret)
def get_data(self):
result = requests.get(self.__get_full_url(), auth=self.authentication, headers=self.HEADERS)
self.data['status_code'] = result.status_code
if result.status_code in [200,201]:
self.data = result.json()
self.__parse_data()
else:
print(result.json())
raise VRE_API_Exception_Factory('Error with url {}.'.format(self.url),result.status_code)
return self.data
def post_data(self, payload):
result = requests.post(self.__get_full_url(), json=payload, auth=self.authentication, headers=self.HEADERS)
self.data['status_code'] = result.status_code
if result.status_code in [200,201]:
self.data = result.json()
self.__parse_data()
else:
#print(result.content)
#print(result.text)
raise VRE_API_Exception_Factory('Error with url {}.'.format(self.url),result.status_code)
return self.data
def put_data(self, payload):
result = requests.put(self.__get_full_url(), json=payload, auth=self.authentication, headers=self.HEADERS)
self.data['status_code'] = result.status_code
if result.status_code in [200,201]:
self.data = result.json()
self.__parse_data()
else:
print(result.json())
raise VRE_API_Exception_Factory('Error with url {}.'.format(self.url),result.status_code)
return self.data
def delete_data(self):
try:
# Django HAWK has issues with a delete action. It needs/wants a content-type header, but there is no content.....
# https://github.com/kumar303/hawkrest/issues/46
result = requests.delete(self.__get_full_url(), auth=self.authentication, headers=self.HEADERS)
return result.status_code in [200,201,204]
except Exception:
raise VRE_API_Exception_Factory('Error with url {}.'.format(self.url),result.status_code)
return False

View File

@@ -0,0 +1,20 @@
from django.db import models
from django.utils.translation import gettext_lazy as _
class MetaDataModel(models.Model):
"""
This is an abstract Django model with some general meta fields that can be used for other models.
Attributes
----------
created_at : datetime
The date and time when the model has been created. This will be automatically set once during creating.
updated_at : datetime
The date and time when the model has been updated. This will be automatically updated when the model is updated.
"""
created_at = models.DateTimeField(_('Date created'),auto_now_add=True, help_text=_('The date and time this model has been created'))
updated_at = models.DateTimeField(_('Date updated'),auto_now=True, help_text=_('The date and time this model has been updated'))
class Meta:
abstract = True

View File

@@ -0,0 +1,84 @@
import os.path
import re
import mimetypes
from email.mime.base import MIMEBase
from django.core.mail import EmailMultiAlternatives, SafeMIMEMultipart
from django.conf import settings
# Source: https://djangosnippets.org/snippets/2215/
class EmailMultiRelated(EmailMultiAlternatives):
"""
A version of EmailMessage that makes it easy to send multipart/related
messages. For example, including text and HTML versions with inline images.
"""
related_subtype = 'related'
def __init__(self, subject='', body='', from_email=None, to=None, bcc=None,
connection=None, attachments=None, headers=None, alternatives=None):
# self.related_ids = []
self.related_attachments = []
super(EmailMultiRelated, self).__init__(subject, body, from_email, to, bcc, connection, attachments, headers, alternatives)
def attach_related(self, filename=None, content=None, mimetype=None):
"""
Attaches a file with the given filename and content. The filename can
be omitted and the mimetype is guessed, if not provided.
If the first parameter is a MIMEBase subclass it is inserted directly
into the resulting message attachments.
"""
if isinstance(filename, MIMEBase):
assert content == mimetype == None
self.related_attachments.append(filename)
else:
assert content is not None
self.related_attachments.append((filename, content, mimetype))
def attach_related_file(self, path, mimetype=None):
"""Attaches a file from the filesystem."""
filename = os.path.basename(path)
content = open(path, 'rb').read()
if mimetype is None:
mimetypes.init()
mimetype = mimetypes.guess_type(filename)[0]
self.attach_related(filename, content, mimetype)
def _create_message(self, msg):
return self._create_attachments(self._create_related_attachments(self._create_alternatives(msg)))
def _create_alternatives(self, msg):
for i, (content, mimetype) in enumerate(self.alternatives):
if mimetype == 'text/html':
for filename, _, _ in self.related_attachments:
content = re.sub(r'(?<!cid:)%s' % re.escape(filename), 'cid:%s' % filename, content)
self.alternatives[i] = (content, mimetype)
return super(EmailMultiRelated, self)._create_alternatives(msg)
def _create_related_attachments(self, msg):
encoding = self.encoding or settings.DEFAULT_CHARSET
if self.related_attachments:
body_msg = msg
msg = SafeMIMEMultipart(_subtype=self.related_subtype, encoding=encoding)
if self.body:
msg.attach(body_msg)
for related in self.related_attachments:
msg.attach(self._create_related_attachment(*related))
return msg
def _create_related_attachment(self, filename, content, mimetype=None):
"""
Convert the filename, content, mimetype triple into a MIME attachment
object. Adjust headers to use Content-ID where applicable.
Taken from http://code.djangostudy.com/ticket/4771
"""
attachment = super(EmailMultiRelated, self)._create_attachment(filename, content, mimetype)
if filename:
mimetype = attachment['Content-Type']
del(attachment['Content-Type'])
del(attachment['Content-Disposition'])
attachment.add_header('Content-Disposition', 'inline', filename=filename)
attachment.add_header('Content-Type', mimetype, name=filename)
attachment.add_header('Content-ID', '<%s>' % filename)
return attachment

View File

@@ -0,0 +1,26 @@
import re
import random
import string
def remove_html_tags(text):
"""Remove html tags from a string"""
clean = re.compile('<.*?>')
return re.sub(clean, '', text)
def get_random_int_value(length = 6):
return ''.join(list(map(lambda x: str(random.randint(1,9)), list(range(length)))))
def get_random_string(length = 8):
return ''.join(random.choices(string.ascii_uppercase + string.digits + string.ascii_lowercase, k=length))
def generate_encryption_key(length = 32):
return get_random_string(length)
def get_ip_address(request):
""" use requestobject to fetch client machine's IP Address """
x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR', None)
if x_forwarded_for:
ip = x_forwarded_for.split(',')[0]
else:
ip = request.META.get('REMOTE_ADDR') ### Real IP address of client Machine
return ip