Skip to content

Commit

Permalink
0.3
Browse files Browse the repository at this point in the history
  • Loading branch information
biodiv committed Nov 15, 2019
1 parent 025b8cb commit 84adcd3
Show file tree
Hide file tree
Showing 1,175 changed files with 87,447 additions and 25 deletions.
9 changes: 9 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
recursive-include localcosmos_server/app_admin/static *
recursive-include localcosmos_server/app_admin/templates *
recursive-include localcosmos_server/datasets/templates *
recursive-include localcosmos_server/online_content/static *
recursive-include localcosmos_server/online_content/templates *
recursive-include localcosmos_server/server_control_panel/templates *
recursive-include localcosmos_server/specifications *
recursive-include localcosmos_server/static *
recursive-include localcosmos_server/templates *
Empty file.
41 changes: 41 additions & 0 deletions build/lib/localcosmos_server/api/authentication.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
from django.contrib.auth import get_user_model

from rest_framework.authentication import BaseAuthentication
from rest_framework.authtoken.models import Token
from rest_framework.exceptions import AuthenticationFailed

User = get_user_model()

class LCTokenAuthentication(BaseAuthentication):

def authenticate(self, request):
auth = request.META.get('HTTP_AUTHORIZATION', '').split()
if not auth or auth[0].lower() != 'token':
return None

if len(auth) == 1:
msg = 'Invalid token header. No credentials provided.'
raise AuthenticationFailed(msg)
elif len(auth) > 2:
msg = 'Invalid token header. Token string should not contain spaces.'
raise AuthenticationFailed(msg)

key = auth[1]

try:
token = Token.objects.get(key=key)
except Token.DoesNotExist:
raise AuthenticationFailed('Invalid token')

try:
user = User.objects.get(pk=token.user_id)
except User.DoesNotExist:
raise AuthenticationFailed('User inactive or deleted')


if user.is_active == True:
return (user, token)

else:
msg = 'User inactive.'
raise AuthenticationFailed(msg)
65 changes: 65 additions & 0 deletions build/lib/localcosmos_server/api/permissions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
from rest_framework import permissions

from localcosmos_server.models import App


##################################################################################################################
#
# DataSet Creation
#
# - allow_anonymous_observations is set on an per-app-basis
# - server-side check should be implemented in case the user changes this permission, otherwise old app installs could still upload
# - this check uses the currently live webapp settings.json to check
#
##################################################################################################################

class CanCreateDataset(permissions.BasePermission):

def has_permission(self, request, view):

app_uuid = request.data['app_uuid']
app = App.objects.get(uuid=app_uuid)

review = False

if 'review' in request.data:
review = bool(int(request.data['review']))

api_settings = app.get_api_settings(review=review)

allow_anonymous_observations = api_settings['allow_anonymous_observations']

if allow_anonymous_observations == False and request.user.is_authenticated == False:
return False

return True



###################################################################################################################
#
# DataSet Management
#
# - only the Dataset owner may update/delete a dataset
#
###################################################################################################################

class DatasetOwnerOnly(permissions.BasePermission):

def has_object_permission(self, request, view, dataset):

# allow read for all
if request.method in permissions.SAFE_METHODS:
return True

# determine if the user is allowed to alter or delete a dataset
# owner can be determined by device uuid or dataset.user == request.user
if request.user == dataset.user:
return True

elif 'client_id' in request.query_params and request.query_params['client_id'] == dataset.client_id:
return True

return False


39 changes: 39 additions & 0 deletions build/lib/localcosmos_server/api/road_permissions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
from rest_framework import permissions

from django.conf import settings

from django_road import permissions as road_permissions
from .permissions import CanCreateDataset

import os, json


ROAD_MODEL_PERMISSIONS = {
'LocalcosmosUser' : {
'first' : [road_permissions.OwnerOnly],
'default' : [road_permissions.OwnerOnly],
'create' : [road_permissions.PermissionDenied], # uses separate api
'fetch' : [road_permissions.PermissionDenied], # do not allow this
'count' : [road_permissions.PermissionDenied], # do not allow this
},
'Dataset' : {
'get' : [],
'filter' : [],
'first' :[],
'fetch' :[],
'count' : [],
'delete' : [road_permissions.OwnerOnly],
'update' : [road_permissions.OwnerOnly],
'insert' : [CanCreateDataset], # app specific permission needed
},
'DatasetImages' : {
'get' : [],
'filter' : [],
'first' :[],
'fetch' :[],
'count' : [],
'delete' : [road_permissions.OwnerOnly],
'update' : [road_permissions.OwnerOnly],
'insert' : [CanCreateDataset], # app specific permission needed
}
}
123 changes: 123 additions & 0 deletions build/lib/localcosmos_server/api/road_serializers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
from rest_framework import serializers
from django.contrib.auth import get_user_model

from localcosmos_server.datasets.models import Dataset, DatasetImages

from django_road.serializer_fields import RemoteDBJSONField

User = get_user_model()


class LocalcosmosUserSerializer(serializers.ModelSerializer):

class Meta:
model = User
exclude = ('password',)


'''
The Dataset is stored using the RemoteDB interface of the webapp
OR by using the sync button on the native app
'''
class DatasetSerializer(serializers.ModelSerializer):

assign_authenticated_user = 'user' # assigns the authenticated user to the field user on insert and update

data = RemoteDBJSONField(binary=True)
created_at = serializers.DateTimeField()
last_modified = serializers.DateTimeField(required=False)

# SerializerMethodFields are only for to_representation
thumbnail = serializers.SerializerMethodField()

def get_thumbnail(self, obj):

image = DatasetImages.objects.filter(dataset=obj).first()

if image:
# App clients need the full url
relative_url = image.thumbnail(size=200)
url = '{0}://{1}{2}'.format(self.request.scheme, self.request.get_host(), relative_url)
return url

return None


class Meta:
model = Dataset
fields = ('__all__')
read_only_fields = ('user_id', 'client_id')


'''
DatasetImagesSerializer
- keep thumbnails in sync with [App][models.js].DatasetImages.fields.image.thumbnails
'''
APP_THUMBNAILS = {
"small" : {
"size" : [100, 100],
"type" : "cover"
},
"medium" : {
"size" : [400, 400],
"type" : "cover"
},
"full_hd" : {
"size" : [1920, 1080],
"type" : "contain"
}
}

class FlexImageField(serializers.ImageField):

def to_representation(self, image):

dataset_image = image.instance

host = '{0}://{1}'.format(self.parent.request.scheme, self.parent.request.get_host())

relative_url = image.url
url = '{0}{1}'.format(host,relative_url)

fleximage = {
'url' : url,
}

for name, definition in APP_THUMBNAILS.items():

if definition['type'] == 'cover':
relative_thumb_url = dataset_image.thumbnail(definition['size'][0])

else:
relative_thumb_url = dataset_image.resized(name, max_size=definition['size'])

thumb_url = '{0}{1}'.format(host, relative_thumb_url)
fleximage[name] = thumb_url

return fleximage


'''
return the DatasetImages.Dataset as a serialized Dataset
'''
class DatasetField(serializers.PrimaryKeyRelatedField):

def to_representation(self, value):
data = {
'id' : value.pk
}

return data


class DatasetImagesSerializer(serializers.ModelSerializer):

# there is only 1 FK
serializer_related_field = DatasetField

class Meta:
model = DatasetImages
fields = ('__all__')

from django.db.models import ImageField
DatasetImagesSerializer.serializer_field_mapping[ImageField] = FlexImageField

0 comments on commit 84adcd3

Please sign in to comment.