def authorize(request, page=None, edit=False, add=False, delete=False, view=False, do_raise=True): if isinstance(page, basestring): page = Page.objects.get(slug=page).get_content_model() user = get_user(request) request.user = user auth = True if auth and page is not None: request.user = user if edit: auth = page.can_change(request) if add: auth = auth and page.can_add(request) if delete: auth = auth and page.can_delete(request) elif view: auth = auth and (not hasattr(page, 'can_view')) or \ (auth and hasattr(page, 'can_view') and page.can_view(request)) if do_raise and not auth: raise PermissionDenied(json.dumps({ "error": "Unauthorized", "user": user.email if user.is_authenticated() else None, "page": page.slug if page else None, "edit": edit, "add": add, "delete": delete, "view": view })) return user
def _check_webapp_in_user_open_with_list(tool_res_obj, request_obj): if request_obj.user.is_authenticated(): user_obj = get_user(request_obj) return tool_res_obj.rlabels.is_open_with_app(user_obj) else: return False
def can_view(self, request): user = get_user(request) if self.public or not self.owner: return True if user.is_authenticated(): if not self.owner: return user.is_superuser elif user.pk == self.owner.pk: return True else: users = self.view_users groups = self.view_groups if len(users) > 0 and user.pk in users: return True elif len(groups) > 0: return user.groups.filter(pk__in=groups).exists() else: return False else: return False
def can_change(self, request): user = get_user(request) ret = True if user.is_authenticated(): if not self.owner: ret = user.is_superuser elif user.pk == self.owner.pk: ret = True else: users = self.edit_users groups = self.edit_groups if len(users) > 0 and user.pk in users: ret = True elif len(groups) > 0: ret = user.groups.filter(pk__in=groups).exists() else: ret = False else: ret = False return ret
def authorize(request, res_id, needed_permission=ACTION_TO_AUTHORIZE.VIEW_RESOURCE, raises_exception=True): """ This function checks if a user has authorization for resource related actions as outlined below. This function doesn't check authorization for user sharing resource with another user. How this function should be called for different actions on a resource by a specific user? 1. User wants to view a resource (both metadata and content files) which includes downloading resource bag or resource content files: authorize(request, res_id=id_of_resource, needed_permission=ACTION_TO_AUTHORIZE.VIEW_RESOURCE) 2. User wants to view resource metadata only: authorize(request, res_id=id_of_resource, needed_permission=ACTION_TO_AUTHORIZE.VIEW_METADATA) 3. User wants to edit a resource which includes: a. edit metadata b. add file to resource c. delete a file from the resource authorize(request, res_id=id_of_resource, needed_permission=ACTION_TO_AUTHORIZE.EDIT_RESOURCE) 4. User wants to set resource flag (public, published, shareable etc): authorize(request, res_id=id_of_resource, needed_permission=ACTION_TO_AUTHORIZE.SET_RESOURCE_FLAG) 5. User wants to delete a resource: authorize(request, res_id=id_of_resource, needed_permission=ACTION_TO_AUTHORIZE.DELETE_RESOURCE) 6. User wants to create new version of a resource: authorize(request, res_id=id_of_resource, needed_permission=ACTION_TO_AUTHORIZE.CREATE_RESOURCE_VERSION) Note: resource 'shareable' status has no effect on authorization """ authorized = False user = get_user(request) try: res = hydroshare.utils.get_resource_by_shortkey(res_id, or_404=False) except ObjectDoesNotExist: raise NotFound(detail="No resource was found for resource id:%s" % res_id) if needed_permission == ACTION_TO_AUTHORIZE.VIEW_METADATA: if res.raccess.discoverable or res.raccess.public: authorized = True elif user.is_authenticated() and user.is_active: authorized = user.uaccess.can_view_resource(res) elif user.is_authenticated() and user.is_active: if needed_permission == ACTION_TO_AUTHORIZE.VIEW_RESOURCE: authorized = user.uaccess.can_view_resource(res) elif needed_permission == ACTION_TO_AUTHORIZE.EDIT_RESOURCE: authorized = user.uaccess.can_change_resource(res) elif needed_permission == ACTION_TO_AUTHORIZE.DELETE_RESOURCE: authorized = user.uaccess.can_delete_resource(res) elif needed_permission == ACTION_TO_AUTHORIZE.SET_RESOURCE_FLAG: authorized = user.uaccess.can_change_resource_flags(res) elif needed_permission == ACTION_TO_AUTHORIZE.CREATE_RESOURCE_VERSION: authorized = user.uaccess.owns_resource(res) elif needed_permission == ACTION_TO_AUTHORIZE.VIEW_RESOURCE_ACCESS: authorized = user.uaccess.can_view_resource(res) elif needed_permission == ACTION_TO_AUTHORIZE.EDIT_RESOURCE_ACCESS: authorized = user.uaccess.can_share_resource(res, 2) elif needed_permission == ACTION_TO_AUTHORIZE.VIEW_RESOURCE: authorized = res.raccess.public if raises_exception and not authorized: raise PermissionDenied() else: return res, authorized, user
def create_scidas_virtual_app(request, res_id, cluster): user = get_user(request) if not user.is_authenticated() or not user.is_active: messages.error( request, "Only authorized user can make appliance provision request.") return HttpResponseRedirect(request.META['HTTP_REFERER']) res, _, _ = authorize(request, res_id, needed_permission=ACTION_TO_AUTHORIZE.VIEW_RESOURCE) cluster_name = cluster if cluster_name != 'chameleon' and cluster_name != 'aws' and cluster_name != 'azure': cluster_name = '' file_data_list = [] p_data = {} file_path = '/' + ds.IRODS_ZONE + '/home/' + ds.IRODS_USERNAME for rf in ResourceFile.objects.filter(object_id=res.id): fname = '' if rf.resource_file.name: fname = os.path.join(file_path, rf.resource_file.name) elif rf.fed_resource_file.name: fname = rf.fed_resource_file.name if fname: file_data_list.append(fname) if fname.endswith('.json') and not p_data: temp_json_file = get_file_from_irods(rf) with open(temp_json_file, 'r') as fp: jdata = load(fp) if 'id' in jdata and 'containers' in jdata: p_data = jdata url = settings.PIVOT_URL app_id = user.username + '_cs_app_id' preset_url = '' if not p_data: p_data = { "id": app_id, "containers": [{ "id": app_id, "image": "scidas/irods-jupyter-hydroshare", "resources": { "cpus": 2, "mem": 2048 }, "port_mappings": [{ "container_port": 8888, "host_port": 0, "protocol": "tcp" }], "args": ["--ip=0.0.0.0", "--NotebookApp.token=\"\""], "data": file_data_list }] } else: app_id = p_data['id'] p_data['containers'][0]['data'] = file_data_list if cluster_name: p_data['containers'][0]['cluster'] = cluster_name if 'endpoints' in p_data['containers'][0]: if p_data['containers'][0]['endpoints']: preset_ep_data = p_data['containers'][0]['endpoints'][0] preset_url = 'http://' + preset_ep_data['host'] + ':' + str( preset_ep_data['host_port']) # delete the appliance before posting to create a new one in case it already exists app_url = url + '/' + app_id response = requests.delete(app_url) is_deleted = False if response.status_code != status.HTTP_404_NOT_FOUND and \ response.status_code != status.HTTP_200_OK: idx = 0 while idx < 2: get_response = requests.get(app_url) idx += 1 if get_response.status_code == status.HTTP_404_NOT_FOUND: is_deleted = True break else: # appliance is not deleted successfully yet, wait and poll # again one more time time.sleep(2) else: is_deleted = True if not is_deleted: errmsg = 'The old appliance ' + app_id + ' cannot be deleted successfully' messages.error(request, errmsg) return HttpResponseRedirect(request.META['HTTP_REFERER']) response = requests.post(url, data=dumps(p_data)) if response.status_code != status.HTTP_200_OK and \ response.status_code != status.HTTP_201_CREATED: return HttpResponseBadRequest(content=response.text) while True: response = requests.get(app_url) if not response.status_code == status.HTTP_200_OK: return HttpResponseBadRequest(content=response.text) return_data = loads(response.content) con_ret_data_list = return_data['containers'] con_ret_data = con_ret_data_list[0] con_state = con_ret_data['state'] ep_data_list = con_ret_data['endpoints'] if con_state == 'running' and (ep_data_list or preset_url): break else: # the jupyter appliance is not ready yet, need to wait and poll again time.sleep(2) if preset_url: app_url = preset_url else: ep_data = ep_data_list[0] app_url = 'http://' + ep_data['host'] + ':' + str(ep_data['host_port']) # make sure the new directed url is loaded and working before redirecting. # Since scidas will install dependencies included in requirements.txt, it will take some time # before the app_url is ready to go after the appliance is provisioned, hence wait for up to 30 seconds # before erroring out if connection to the url keeps being refused. idx = 0 while True: try: ret = urlopen(app_url, timeout=10) break except URLError as ex: errmsg = ex.reason if hasattr(ex, 'reason') else 'URLError' idx += 1 time.sleep(5) if idx > 6: messages.error(request, errmsg) return HttpResponseRedirect(request.META['HTTP_REFERER']) if ret.code == 200: return HttpResponseRedirect(app_url) else: messages.error(request, 'time out error') return HttpResponseRedirect(request.META['HTTP_REFERER'])