From 993db74dc9efda949a86578079ff81acff478728 Mon Sep 17 00:00:00 2001 From: Josue Balandrano Coronel Date: Fri, 7 Apr 2017 10:22:52 -0500 Subject: [PATCH] Making public data viewable by anonymous user --- designsafe/apps/api/agave/views.py | 30 +++-- designsafe/apps/api/public_data/urls.py | 2 +- designsafe/apps/api/public_data/views.py | 37 ++++-- .../apps/data/templates/data/data_depot.html | 1 + designsafe/static/scripts/data-depot/app.js | 60 ++++----- .../data-depot/controllers/community.js | 124 ++++++++++++++++++ 6 files changed, 200 insertions(+), 54 deletions(-) create mode 100644 designsafe/static/scripts/data-depot/controllers/community.js diff --git a/designsafe/apps/api/agave/views.py b/designsafe/apps/api/agave/views.py index 4d4f09f32f..9c23628324 100644 --- a/designsafe/apps/api/agave/views.py +++ b/designsafe/apps/api/agave/views.py @@ -90,14 +90,15 @@ class FileMediaView(View): def get(self, request, file_mgr_name, system_id, file_path): logger.info(file_path) if file_mgr_name == AgaveFileManager.NAME \ - or file_mgr_name == 'public': - - if file_mgr_name == 'public': - ag = get_user_model().objects.get(username='envision').agave_oauth.client - elif request.user.is_authenticated(): - ag = request.user.agave_oauth.client + or file_mgr_name == 'public' \ + or file_mgr_name == 'community': + if not request.user.is_authenticated(): + if file_mgr_name in ['public', 'community']: + ag = get_user_model().objects.get(username='envision').agave_oauth.client + else: + return HttpResponseForbidden('Log in required') else: - return HttpResponseForbidden('Log in required') + ag = request.user.agave_oauth.client fm = AgaveFileManager(agave_client=ag) f = fm.listing(system_id, file_path) @@ -216,12 +217,21 @@ def put(self, request, file_mgr_name, system_id, file_path): else: body = request.POST.copy() - if file_mgr_name == AgaveFileManager.NAME: + if file_mgr_name == AgaveFileManager.NAME \ + or file_mgr_name == 'public' \ + or file_mgr_name == 'community': + if not request.user.is_authenticated(): - return HttpResponseForbidden('Log in required') + if file_mgr_name in ['public', 'community']: + ag = get_user_model().objects.get(username='envision').agave_oauth.client + else: + return HttpResponseForbidden('Log in required') + else: + ag = request.user.agave_oauth.client - fm = AgaveFileManager(agave_client=request.user.agave_oauth.client) + fm = AgaveFileManager(agave_client=ag) action = body.get('action', '') + logger.info('action: %s', action) if action == 'copy': try: event_data = { diff --git a/designsafe/apps/api/public_data/urls.py b/designsafe/apps/api/public_data/urls.py index 4a8ca6ea81..b9b0436bc3 100644 --- a/designsafe/apps/api/public_data/urls.py +++ b/designsafe/apps/api/public_data/urls.py @@ -35,7 +35,7 @@ # PUT /media//// # DELETE /media//// url(r'^files/media/(?P[\w.-]+)/(?P[\w.-]+)/(?P[ \S]+)$', - FileMediaView.as_view(), name='public_files_media'), + PublicMediaView.as_view(), name='public_files_media'), # Permission operations: diff --git a/designsafe/apps/api/public_data/views.py b/designsafe/apps/api/public_data/views.py index 0eebcec2c2..c41cc082d7 100644 --- a/designsafe/apps/api/public_data/views.py +++ b/designsafe/apps/api/public_data/views.py @@ -23,7 +23,7 @@ HttpResponseServerError, JsonResponse) from django.shortcuts import render -from django.contrib.auth import get_user_model +from django.contrib.auth import get_user_model, login from designsafe.apps.api.views import BaseApiView from designsafe.apps.api.mixins import SecureMixin from designsafe.apps.api.agave import get_service_account_client @@ -31,6 +31,7 @@ from designsafe.apps.api.agave.models.util import AgaveJSONEncoder from designsafe.apps.api.agave.filemanager.public_search_index import PublicElasticFileManager from designsafe.apps.api.agave.filemanager.community import CommunityFileManager +from designsafe.apps.api.agave.views import FileMediaView logger = logging.getLogger(__name__) @@ -59,21 +60,30 @@ def get(self, request, file_mgr_name, return JsonResponse(listing.to_dict()) -class PublicMediaView(BaseApiView): +class PublicMediaView(FileMediaView): """Media view to render metadata""" - def get(self, request, file_mgr_name, - system_id=None, file_path=None): - """GET handler.""" - if file_mgr_name != PublicElasticFileManager.NAME: - return HttpResponseBadRequest() - if system_id is None: - system_id = PublicElasticFileManager.DEFAULT_SYSTEM_ID + def get(self, request, *args, **kwargs): + return super(PublicMediaView, self).get(request, *args, **kwargs) + + def post(self, request, *args, **kwargs): + return HttpResponseBadRequest('Invalid Action') - file_mgr = PublicElasticFileManager() - listing = file_mgr.listing(system_id, file_path) + def put(self, request, *args, **kwargs): + if request.is_ajax(): + body = json.loads(request.body) + else: + body = request.POST.copy() + + action = body.get('action', '') + if action in ['copy', 'mkdir', 'move', 'rename', 'trash']: + return HttpResponseBadRequest('Invalid Action') + + return super(PublicMediaView, self).put(request, *args, **kwargs) + + def delete(self, request, *args, **kwargs): + return HttpResponseBadRequest('Invalid Action') - return JsonResponse(listing.to_dict()) class PublicSearchView(BaseApiView): """ Search view """ @@ -104,7 +114,8 @@ class PublicPemsView(BaseApiView): def get(self, request, file_mgr_name, system_id = None, file_path = None): """ GET handler """ - if file_mgr_name != PublicElasticFileManager.NAME: + if file_mgr_name != PublicElasticFileManager.NAME \ + and file_mgr_name != 'community': return HttpResponseBadRequest() if system_id is None: diff --git a/designsafe/apps/data/templates/data/data_depot.html b/designsafe/apps/data/templates/data/data_depot.html index d0f65f88b8..b2b8e6139c 100644 --- a/designsafe/apps/data/templates/data/data_depot.html +++ b/designsafe/apps/data/templates/data/data_depot.html @@ -44,6 +44,7 @@ + {% endaddtoblock %} {% endblock %} diff --git a/designsafe/static/scripts/data-depot/app.js b/designsafe/static/scripts/data-depot/app.js index 84dadbb718..70fee0a5aa 100644 --- a/designsafe/static/scripts/data-depot/app.js +++ b/designsafe/static/scripts/data-depot/app.js @@ -282,8 +282,37 @@ } } }) + .state('communityData', { + // url: '/community/', + // template: '
local/communityData.html
' + url: '/public/designsafe.storage.community/{filePath:any}', + controller: 'CommunityDataCtrl', + templateUrl: '/static/scripts/data-depot/templates/agave-data-listing.html', + params: { + systemId: 'designsafe.storage.community', + filePath: '/' + }, + resolve: { + 'listing': ['$stateParams', 'DataBrowserService', function($stateParams, DataBrowserService) { + var options = { + system: ($stateParams.systemId || 'designsafe.storage.community'), + path: ($stateParams.filePath || '/') + }; + // if (options.path === '/') { + // options.path = Django.user; + // } + DataBrowserService.apiParams.fileMgr = 'community'; + DataBrowserService.apiParams.baseUrl = '/api/public/files'; + DataBrowserService.apiParams.searchState = 'dataSearch'; + return DataBrowserService.browse(options); + }], + 'auth': function($q) { + return true; + } + } + }) .state('publicData', { - url: '/public/{systemId}/{filePath:any}', + url: '/public/nees.public/{filePath:any}', controller: 'PublicationDataCtrl', templateUrl: '/static/scripts/data-depot/templates/agave-public-data-listing.html', params: { @@ -311,35 +340,6 @@ }] } }) - .state('communityData', { - // url: '/community/', - // template: '
local/communityData.html
' - url: '/agave/{systemId}/', - controller: 'MyDataCtrl', - templateUrl: '/static/scripts/data-depot/templates/agave-data-listing.html', - params: { - systemId: 'designsafe.storage.community', - filePath: '/' - }, - resolve: { - 'listing': ['$stateParams', 'DataBrowserService', function($stateParams, DataBrowserService) { - var options = { - system: ($stateParams.systemId || 'designsafe.storage.community'), - path: ($stateParams.filePath || '/') - }; - // if (options.path === '/') { - // options.path = Django.user; - // } - DataBrowserService.apiParams.fileMgr = 'community'; - DataBrowserService.apiParams.baseUrl = '/api/public/files'; - DataBrowserService.apiParams.searchState = 'dataSearch'; - return DataBrowserService.browse(options); - }], - 'auth': function($q) { - return true; - } - } - }) .state('trainingMaterials', { url: '/training/', template: '
local/trainingMaterials.html
' diff --git a/designsafe/static/scripts/data-depot/controllers/community.js b/designsafe/static/scripts/data-depot/controllers/community.js new file mode 100644 index 0000000000..e340cd5541 --- /dev/null +++ b/designsafe/static/scripts/data-depot/controllers/community.js @@ -0,0 +1,124 @@ +(function(window, angular) { + var app = angular.module('designsafe'); + app.requires.push('django.context'); + + app.controller('CommunityDataCtrl', ['$scope', '$state', 'Django', + 'DataBrowserService', + function ($scope, $state, Django, DataBrowserService) { + + $scope.browser = DataBrowserService.state(); + $scope.state = { + loadingMore : false, + reachedEnd : false, + page : 0 + }; + + if (! $scope.browser.error){ + $scope.browser.listing.href = $state.href('communityData', { + system: $scope.browser.listing.system, + filePath: $scope.browser.listing.path + }); + _.each($scope.browser.listing.children, function (child) { + child.href = $state.href('communityData', {system: child.system, filePath: child.path}); + }); + } + + $scope.data = { + customRoot: { + name: 'Community Data', + href: $state.href('communityData', {systemId: $scope.browser.listing.system, + filePath: '/'}) + } + }; + + $scope.resolveBreadcrumbHref = function(trailItem) { + return $state.href('communityData', {systemId: $scope.browser.listing.system, filePath: trailItem.path}); + }; + + $scope.scrollToTop = function(){ + return; + }; + $scope.scrollToBottom = function(){ + DataBrowserService.scrollToBottom(); + }; + + $scope.onBrowse = function($event, file) { + $event.preventDefault(); + $event.stopPropagation(); + + var systemId = file.system || file.systemId; + var filePath; + if (file.path == '/'){ + filePath = file.path + file.name; + } else { + filePath = file.path; + } + if (file.type === 'file'){ + DataBrowserService.preview(file, $scope.browser.listing); + } else { + $state.go('communityData', {systemId: file.system, filePath: file.path}); + } + }; + + $scope.onSelect = function($event, file) { + $event.preventDefault(); + $event.stopPropagation(); + + if ($event.ctrlKey || $event.metaKey) { + var selectedIndex = $scope.browser.selected.indexOf(file); + if (selectedIndex > -1) { + DataBrowserService.deselect([file]); + } else { + DataBrowserService.select([file]); + } + } else if ($event.shiftKey && $scope.browser.selected.length > 0) { + var lastFile = $scope.browser.selected[$scope.browser.selected.length - 1]; + var lastIndex = $scope.browser.listing.children.indexOf(lastFile); + var fileIndex = $scope.browser.listing.children.indexOf(file); + var min = Math.min(lastIndex, fileIndex); + var max = Math.max(lastIndex, fileIndex); + DataBrowserService.select($scope.browser.listing.children.slice(min, max + 1)); + } else if (typeof file._ui !== 'undefined' && + file._ui.selected){ + DataBrowserService.deselect([file]); + } else { + DataBrowserService.select([file], true); + } + }; + + $scope.showFullPath = function(item){ + if ($scope.browser.listing.path != '$PUBLIC' && + item.parentPath() != $scope.browser.listing.path && + item.parentPath() != '/'){ + return true; + } else { + return false; + } + }; + + $scope.onDetail = function($event, file) { + $event.stopPropagation(); + DataBrowserService.preview(file, $scope.browser.listing); + }; + + $scope.renderName = function(file){ + if (typeof file.metadata === 'undefined' || + file.metadata === null || + _.isEmpty(file.metadata)){ + return file.name; + } + var pathComps = file.path.split('/'); + var experiment_re = /^experiment/; + if (file.path[0] === '/' && pathComps.length === 2) { + return file.metadata.project.title; + } + else if (file.path[0] !== '/' && + pathComps.length === 2 && + experiment_re.test(file.name.toLowerCase())){ + return file.metadata.experiments[0].title; + } + return file.name; + }; + + }]); +})(window, angular);