def siloview(self, silo): if not ag.granary.issilo(silo): abort(404) ident = request.environ.get('repoze.who.identity') c.ident = ident c.silo_name = silo c.editor = False if ag.metadata_embargoed: if not ident: abort(401, "Not Authorised") silos = ag.authz(ident) if silo not in silos: abort(403, "Forbidden") c.editor = True elif ident: silos = ag.authz(ident) if silo in silos: c.editor = True rdfsilo = ag.granary.get_rdf_silo(silo) state_info = ag.granary.describe_silo(silo) if 'title' in state_info and state_info['title']: c.title = state_info['title'] c.embargos = {} c.items = [] for item in rdfsilo.list_items(): c.embargos[item] = None try: c.embargos[item] = is_embargoed(rdfsilo, item) except: pass c.items.append(item) #c.embargos[item] = () # conneg return accept_list = None if 'HTTP_ACCEPT' in request.environ: try: accept_list = conneg_parse(request.environ['HTTP_ACCEPT']) except: accept_list= [MT("text", "html")] if not accept_list: accept_list= [MT("text", "html")] mimetype = accept_list.pop(0) while(mimetype): if str(mimetype).lower() in ["text/html", "text/xhtml"]: return render('/siloview.html') elif str(mimetype).lower() in ["text/plain", "application/json"]: response.content_type = 'application/json; charset="UTF-8"' response.status_int = 200 response.status = "200 OK" return simplejson.dumps(c.embargos) try: mimetype = accept_list.pop(0) except IndexError: mimetype = None #Whoops nothing satisfies - return text/html return render('/siloview.html')
def datasetview(self, silo, id): if not ag.granary.issilo(silo): abort(404) ident = request.environ.get('repoze.who.identity') if not ident: abort(401, "Not Authorised") silos = ag.authz(ident) if silo not in silos: abort(403, "Forbidden") silos_admin = ag.authz(ident, permission='administrator') silos_manager = ag.authz(ident, permission='manager') rdfsilo = ag.granary.get_rdf_silo(silo) if not rdfsilo.exists(id): abort(404) item = rdfsilo.get_item(id) creator = None if item.manifest and item.manifest.state and 'metadata' in item.manifest.state and item.manifest.state['metadata'] and \ 'createdby' in item.manifest.state['metadata'] and item.manifest.state['metadata']['createdby']: creator = item.manifest.state['metadata']['createdby'] #if not (ident['repoze.who.userid'] == creator or ident.get('role') in ["admin", "manager"]): if not (ident['repoze.who.userid'] == creator or silo in silos_admin or silo in silos_manager): abort(403, "Forbidden. You should be the creator or manager or administrator to view this information") options = request.GET if 'version' in options and options['version']: if not options['version'] in item.manifest['versions']: abort(404) currentversion = str(item.currentversion) vnum = str(options['version']) if vnum and not vnum == currentversion: item.set_version_cursor(vnum) parts = item.list_parts(detailed=True) dataset = {} dataset['parts'] = {} for part in parts: dataset['parts'][part] = serialisable_stat(parts[part]) if item.manifest: dataset['state'] = item.manifest.state # Always return application/json response.content_type = 'application/json; charset="UTF-8"' response.status_int = 200 response.status = "200 OK" return simplejson.dumps(dataset)
def siloview(self, silo): if not request.environ.get('repoze.who.identity'): abort(401, "Not Authorised") if not ag.granary.issilo(silo): abort(404) ident = request.environ.get('repoze.who.identity') c.ident = ident silos = ag.authz(ident, permission=['administrator', 'manager']) if not silo in silos: abort(403, "Do not have administrator or manager credentials for silo %s"%silo) user_groups = list_user_groups(ident['user'].user_name) if ('*', 'administrator') in user_groups: c.roles = ["admin", "manager", "user"] elif (silo, 'administrator') in user_groups: c.roles = ["admin", "manager", "user"] elif (silo, 'manager') in user_groups: c.roles = ["manager", "user"] else: abort(403, "Do not have administrator or manager credentials for silo %s"%silo) c.silo = silo http_method = request.environ['REQUEST_METHOD'] if http_method == "GET": c.users = list_group_users(silo) accept_list = None if 'HTTP_ACCEPT' in request.environ: try: accept_list = conneg_parse(request.environ['HTTP_ACCEPT']) except: accept_list= [MT("text", "html")] if not accept_list: accept_list= [MT("text", "html")] mimetype = accept_list.pop(0) while(mimetype): if str(mimetype).lower() in ["text/html", "text/xhtml"]: return render("/silo_users.html") elif str(mimetype).lower() in ["text/plain", "application/json"]: response.content_type = 'application/json; charset="UTF-8"' response.status_int = 200 response.status = "200 OK" return simplejson.dumps(c.users) try: mimetype = accept_list.pop(0) except IndexError: mimetype = None #Whoops nothing satisfies - return text/plain response.content_type = 'application/json; charset="UTF-8"' response.status_int = 200 response.status = "200 OK" return simplejson.dumps(c.users)
def service_document(self, path=None): """ Construct the Service Document. This takes the set of collections that are in the store, and places them in an Atom Service document as the individual entries """ service = ServiceDocument(version=self.config.sword_version, max_upload_size=self.config.max_upload_size) # get the authorised list of silos silos = ag.authz(self.auth_credentials.identity) # now for each collection create an sdcollection collections = [] for col_name in silos: href = self.um.silo_url(col_name) title = col_name mediation = self.config.mediation # content types accepted accept = [] multipart_accept = [] if not self.config.accept_nothing: if self.config.app_accept is not None: for acc in self.config.app_accept: accept.append(acc) if self.config.multipart_accept is not None: for acc in self.config.multipart_accept: multipart_accept.append(acc) # SWORD packaging formats accepted accept_package = [] for format in self.config.sword_accept_package: accept_package.append(format) col = SDCollection(href=href, title=title, accept=accept, multipart_accept=multipart_accept, accept_package=accept_package, mediation=mediation) collections.append(col) service.add_workspace("Silos", collections) # serialise and return return service.serialise()
def subitemview(self, silo, id, path, subpath): # Function to retreive a file from the zipfile # TODO # I check to see the path is avlid and it is a zip file. # I do not deal with subpath. if it is a file - serve it. If it is a dir, show the contents of it. # tmpl_context variables needed: c.silo_name, c.zipfile_contents c.ident, c.id, c.path if not ag.granary.issilo(silo): abort(404) if not (path or subpath): abort(400, "You must supply a filename to unpack") rdfsilo = ag.granary.get_rdf_silo(silo) if not rdfsilo.exists(id): abort(404) c.silo_name = silo c.id = id c.path = path c.subpath = subpath ident = request.environ.get("repoze.who.identity") c.ident = ident dataset = rdfsilo.get_item(id) if dataset.metadata.get("embargoed") not in ["false", 0, False]: if not ident: abort(401, "Not Authorised") silos = ag.authz(ident) if silo not in silos: abort(403, "Forbidden") item_real_filepath = dataset.to_dirpath() target_filepath = "%s/%s" % (item_real_filepath, path) # c.parts = dataset.list_parts(detailed=False) if not dataset.isfile(path): abort(404, "File not found") if not os.path.isfile(target_filepath): abort(404, "File not found") if not check_file_mimetype(target_filepath, "application/zip"): abort(415, "File is not of type application/zip") # TODO : if subpath is a file - serve it. If subpath is a dir, show the contents of the dir return render("/zipfilesubitemview.html")
def index(self): ident = request.environ.get('repoze.who.identity') c.ident = ident #granary_list = ag.granary.silos #c.silos = granary_list c.silos = list_silos() if ag.metadata_embargoed: if not ident: abort(401, "Not Authorised") c.silos = ag.authz(ident) c.silo_infos = {} for silo in c.silos: c.silo_infos[silo] = [] state_info = ag.granary.describe_silo(silo) if 'title' in state_info and state_info['title']: c.silo_infos[silo].append(state_info['title']) else: c.silo_infos[silo].append(silo) c.silo_infos[silo].append(get_datasets_count(silo)) c.silo_infos[silo].append(getSiloModifiedDate(silo)) # conneg return accept_list = None if 'HTTP_ACCEPT' in request.environ: try: accept_list = conneg_parse(request.environ['HTTP_ACCEPT']) except: accept_list= [MT("text", "html")] if not accept_list: accept_list= [MT("text", "html")] mimetype = accept_list.pop(0) while(mimetype): if str(mimetype).lower() in ["text/html", "text/xhtml"]: return render('/list_of_silos.html') elif str(mimetype).lower() in ["text/plain", "application/json"]: response.content_type = 'application/json; charset="UTF-8"' response.status_int = 200 response.status = "200 OK" return simplejson.dumps(c.silos) try: mimetype = accept_list.pop(0) except IndexError: mimetype = None #Whoops nothing satisfies - return text/html return render('/list_of_silos.html')
def container_exists(self, path): # extract information from the path silo, dataset_id, accept_parameters = self.um.interpret_path(path) # is this a silo? if not ag.granary.issilo(silo): return False # is this an authorised silo? silos = ag.authz(self.auth_credentials.identity) if silo not in silos: return False # get a full silo object rdf_silo = ag.granary.get_rdf_silo(silo) # is the dataset in the authorised silo? if not rdf_silo.exists(dataset_id): return False # if we get here without failing, then the container exists (from the # perspective of the user) return True
def _get_authorised_rdf_silo(self, silo): if not ag.granary.issilo(silo): return SwordError(status=404, empty=True) # get the authorised list of silos #granary_list = ag.granary.silos granary_list = list_silos() silos = ag.authz(self.auth_credentials.identity) # does the collection/silo exist? If not, we can't do a deposit if silo not in silos: # if it's not in the silos it is either non-existant or it is # forbidden... if silo in granary_list: # forbidden raise SwordError(status=403, empty=True) else: # not found raise SwordError(status=404, empty=True) # get a full silo object rdf_silo = ag.granary.get_rdf_silo(silo) return rdf_silo
def datasetview(self, silo, id): """Get a list of zipfiles in dataset 'id' within the silo 'silo' and unpack a dataset.""" if not ag.granary.issilo(silo): abort(404) rdfsilo = ag.granary.get_rdf_silo(silo) if not rdfsilo.exists(id): abort(404) # tmpl_context variables needed: c.silo_name, c.zipfiles, c.ident, c.id, c.path c.silo_name = silo c.id = id ident = request.environ.get("repoze.who.identity") c.ident = ident dataset = rdfsilo.get_item(id) creator = None if ( dataset.manifest and dataset.manifest.state and "metadata" in dataset.manifest.state and dataset.manifest.state["metadata"] and "createdby" in dataset.manifest.state["metadata"] and dataset.manifest.state["metadata"]["createdby"] ): creator = dataset.manifest.state["metadata"]["createdby"] http_method = request.environ["REQUEST_METHOD"] if http_method == "GET": c.editor = False if ag.metadata_embargoed: if not ident: abort(401, "Not Authorised") silos = ag.authz(ident) if silo not in silos: abort(403, "Forbidden") silos_admin = ag.authz(ident, permission="administrator") silos_manager = ag.authz(ident, permission="manager") # if ident['repoze.who.userid'] == creator or ident.get('role') in ["admin", "manager"]: if ident["repoze.who.userid"] == creator or silo in silos_admin or silo in silos_manager: c.editor = True elif ident: silos = ag.authz(ident) if silo in silos: silos_admin = ag.authz(ident, permission="administrator") silos_manager = ag.authz(ident, permission="manager") # if ident['repoze.who.userid'] == creator or ident.get('role') in ["admin", "manager"]: if ident["repoze.who.userid"] == creator or silo in silos_admin or silo in silos_manager: c.editor = True else: # identity management of item if not ident: abort(401, "Not Authorised") silos = ag.authz(ident) if silo not in silos: abort(403, "Forbidden") silos_admin = ag.authz(ident, permission="administrator") silos_manager = ag.authz(ident, permission="manager") # if not (ident['repoze.who.userid'] == creator or ident.get('role') in ["admin", "manager"]): if not (ident["repoze.who.userid"] == creator or silo in silos_admin or silo in silos_manager): abort(403, "Forbidden") if http_method == "GET": c.zipfiles = get_zipfiles_in_dataset(dataset) # conneg return accept_list = None if "HTTP_ACCEPT" in request.environ: try: accept_list = conneg_parse(request.environ["HTTP_ACCEPT"]) except: accept_list = [MT("text", "html")] if not accept_list: accept_list = [MT("text", "html")] mimetype = accept_list.pop(0) while mimetype: if str(mimetype).lower() in ["text/html", "text/xhtml"]: return render("/list_of_zipfiles.html") elif str(mimetype).lower() in ["text/plain", "application/json"]: response.content_type = 'application/json; charset="UTF-8"' response.status_int = 200 response.status = "200 OK" # return simplejson.dumps(dict(c.zipfiles)) return simplejson.dumps(list(c.zipfiles.keys())) try: mimetype = accept_list.pop(0) except IndexError: mimetype = None # Whoops nothing satisfies - return text/html return render("/list_of_zipfiles.html") elif http_method == "POST": params = request.POST if not (params.has_key("filename") and params["filename"]): abort(400, "You must supply a filename to unpack") item_real_filepath = dataset.to_dirpath() target_filepath = "%s/%s" % (item_real_filepath, params["filename"]) if not os.path.isfile(target_filepath): abort(404, "File to unpack not found") if not check_file_mimetype(target_filepath, "application/zip"): abort(415, "File is not of type application/zip") if params.has_key("id") and params["id"]: target_dataset_name = params["id"] else: # (head, fn) = os.path.split(params['filename']) # (fn, ext) = os.path.splitext(fn) # target_dataset_name = "%s-%s"%(id,fn) target_dataset_name = id # step 1: Create / initialize target dataset if not rdfsilo.exists(target_dataset_name): if not allowable_id2(target_dataset_name): response.content_type = "text/plain" response.status_int = 400 response.status = "400 Bad request. Data package name not valid" return ( "Data package name can contain only the following characters - %s and has to be more than 1 character" % ag.naming_rule_humanized ) target_dataset = create_new(rdfsilo, target_dataset_name, ident["repoze.who.userid"]) response.status_int = 201 response.status = "201 Created" response.headers["Content-Location"] = url( controller="datasets", action="datasetview", silo=silo, id=target_dataset_name ) response_message = "201 Created" else: target_dataset = rdfsilo.get_item(target_dataset_name) response.status = "204 Updated" response.status_int = 204 response_message = None # step 2: Unpack zip item try: unpack_zip_item(target_dataset, dataset, params["filename"], rdfsilo, ident["repoze.who.userid"]) except BadZipfile: abort(400, "BadZipfile: Couldn't unpack zipfile") target_dataset.sync() target_dataset.sync() target_dataset.sync() if response.status_int == 201: try: ag.b.creation(silo, id, ident=ident["repoze.who.userid"]) except: pass else: try: ag.b.change(silo, id, ident=ident["repoze.who.userid"]) except: pass # conneg return accept_list = None if "HTTP_ACCEPT" in request.environ: try: accept_list = conneg_parse(request.environ["HTTP_ACCEPT"]) except: accept_list = [MT("text", "html")] if not accept_list: accept_list = [MT("text", "html")] mimetype = accept_list.pop(0) while mimetype: if str(mimetype).lower() in ["text/html", "text/xhtml"]: redirect(url(controller="datasets", action="datasetview", silo=silo, id=target_dataset_name)) elif str(mimetype).lower() in ["text/plain", "application/json"]: response.content_type = "text/plain" return response_message try: mimetype = accept_list.pop(0) except IndexError: mimetype = None # Whoops - nothing satisfies - return text/plain response.content_type = "text/plain" return response_message
def itemview(self, silo, id, path): """API call to GET - read the contents of a zip-file (without having to unpack) and POST- unpack a zip file into a new / existing dataset PUT - Add the zipfile and unpack it onto the existing dataset""" # tmpl_context variables needed: c.silo_name, c.zipfile_contents c.ident, c.id, c.path if not path: abort(400, "You must supply a filename to unpack") if not ag.granary.issilo(silo): abort(404) rdfsilo = ag.granary.get_rdf_silo(silo) if not rdfsilo.exists(id): abort(404) c.silo_name = silo c.id = id c.path = path ident = request.environ.get("repoze.who.identity") c.ident = ident dataset = rdfsilo.get_item(id) creator = None if ( dataset.manifest and dataset.manifest.state and "metadata" in dataset.manifest.state and dataset.manifest.state["metadata"] and "createdby" in dataset.manifest.state["metadata"] and dataset.manifest.state["metadata"]["createdby"] ): creator = dataset.manifest.state["metadata"]["createdby"] http_method = request.environ["REQUEST_METHOD"] if http_method == "GET": if dataset.metadata.get("embargoed") not in ["false", 0, False]: if not ident: abort(401, "Not Authorised") silos = ag.authz(ident) if silo not in silos: abort(403, "Forbidden") else: if not ident: abort(401, "Not Authorised") silos = ag.authz(ident) if silo not in silos: abort(403, "Forbidden") silos_admin = ag.authz(ident, permission="administrator") silos_manager = ag.authz(ident, permission="manager") # if not (ident['repoze.who.userid'] == creator or ident.get('role') in ["admin", "manager"]): if not (ident["repoze.who.userid"] == creator or silo in silos_admin or silo in silos_manager): abort(403, "Forbidden") item_real_filepath = dataset.to_dirpath() target_filepath = "%s/%s" % (item_real_filepath, path) # c.parts = dataset.list_parts(detailed=False) if http_method in ["GET", "POST"]: if not dataset.isfile(path): abort(404, "File not found") if not os.path.isfile(target_filepath): abort(404, "File not found") if not check_file_mimetype(target_filepath, "application/zip"): abort(415, "File is not of type application/zip") if http_method == "GET": try: c.zipfile_contents = read_zipfile(target_filepath) except BadZipfile: abort(400, "Could not read zipfile") # conneg return accept_list = None if "HTTP_ACCEPT" in request.environ: try: accept_list = conneg_parse(request.environ["HTTP_ACCEPT"]) except: accept_list = [MT("text", "html")] if not accept_list: accept_list = [MT("text", "html")] mimetype = accept_list.pop(0) while mimetype: if str(mimetype).lower() in ["text/html", "text/xhtml"]: return render("/zipfileview.html") elif str(mimetype).lower() in ["text/plain", "application/json"]: response.content_type = 'application/json; charset="UTF-8"' response.status_int = 200 response.status = "200 OK" return simplejson.dumps(c.zipfile_contents) try: mimetype = accept_list.pop(0) except IndexError: mimetype = None # Whoops - nothing satisfies - return text/html return render("/zipfileview.html") elif http_method == "POST": params = request.POST # if not (params.has_key("filename") and params['filename']): # abort(400, "You must supply a filename to unpack") if params.has_key("id") and params["id"]: target_dataset_name = params["id"] else: # (head, fn) = os.path.split(path) # (fn, ext) = os.path.splitext(fn) # target_dataset_name = "%s-%s"%(id,fn) target_dataset_name = id # step 1: Create / initialize target dataset if not rdfsilo.exists(target_dataset_name): if not allowable_id2(target_dataset_name): response.content_type = "text/plain" response.status_int = 400 response.status = "400 Bad request. Data package name not valid" return ( "Data package name can contain only the following characters - %s and has to be more than 1 character" % ag.naming_rule_humanized ) target_dataset = create_new(rdfsilo, target_dataset_name, ident["repoze.who.userid"]) response.status_int = 201 response.status = "201 Created" response.headers["Content-Location"] = url( controller="datasets", action="datasetview", silo=silo, id=target_dataset_name ) response_message = "201 Created" else: target_dataset = rdfsilo.get_item(target_dataset_name) response.status = "204 Updated" response.status_int = 204 response_message = None # step 2: Unpack zip item try: unpack_zip_item(target_dataset_name, dataset, path, rdfsilo, ident["repoze.who.userid"]) except BadZipfile: abort(400, "Couldn't unpack zipfile") target_dataset.sync() target_dataset.sync() target_dataset.sync() if response.status_int == 201: try: ag.b.creation(silo, id, ident=ident["repoze.who.userid"]) except: pass else: try: ag.b.change(silo, id, ident=ident["repoze.who.userid"]) except: pass # conneg return accept_list = None if "HTTP_ACCEPT" in request.environ: try: accept_list = conneg_parse(request.environ["HTTP_ACCEPT"]) except: accept_list = [MT("text", "html")] if not accept_list: accept_list = [MT("text", "html")] mimetype = accept_list.pop(0) while mimetype: if str(mimetype).lower() in ["text/html", "text/xhtml"]: redirect(url(controller="datasets", action="datasetview", silo=silo, id=target_dataset_name)) elif str(mimetype).lower() in ["text/plain", "application/json"]: response.content_type = "text/plain" return response_message try: mimetype = accept_list.pop(0) except IndexError: mimetype = None # Whoops - nothing satisfies - return text/plain response.content_type = "text/plain" return response_message elif http_method == "PUT": # Pylons loads the request body into request.body... # This is not going to work for large files... ah well # POST will handle large files as they are pushed to disc, # but this won't content = request.body if JAILBREAK.search(path) != None: abort(400, "'..' cannot be used in the path") # Step 1: Put zipfile in dataset if dataset.isdir(path): response.content_type = "text/plain" response.status_int = 403 response.status = "403 Forbidden" return "Cannot PUT a file on to an existing directory" if dataset.isfile(path): code = 204 else: code = 201 if code == 204: dataset.increment_version_delta(clone_previous_version=True, copy_filenames=["manifest.rdf", path]) else: dataset.increment_version_delta(clone_previous_version=True, copy_filenames=["manifest.rdf"]) dataset.put_stream(path, content) dataset.del_triple(dataset.uri, u"dcterms:modified") dataset.add_triple(dataset.uri, u"dcterms:modified", datetime.now()) dataset.del_triple(dataset.uri, u"oxds:currentVersion") dataset.add_triple(dataset.uri, u"oxds:currentVersion", dataset.currentversion) dataset.sync() target_dataset = rdfsilo.get_item(id) # step 2: Unpack zip item if not check_file_mimetype(target_filepath, "application/zip"): abort(415, "File is not of type application/zip") try: unpack_zip_item(target_dataset, dataset, path, rdfsilo, ident["repoze.who.userid"]) except BadZipfile: abort(400, "Couldn't unpack zipfile") target_dataset.sync() target_dataset.sync() target_dataset.sync() response.status = "204 Updated" response.status_int = 204 response_message = None try: ag.b.change(silo, id, path, ident=ident["repoze.who.userid"]) except: pass # conneg return accept_list = None if "HTTP_ACCEPT" in request.environ: try: accept_list = conneg_parse(request.environ["HTTP_ACCEPT"]) except: accept_list = [MT("text", "html")] if not accept_list: accept_list = [MT("text", "html")] mimetype = accept_list.pop(0) while mimetype: if str(mimetype).lower() in ["text/html", "text/xhtml"]: redirect(url(controller="datasets", action="datasetview", silo=silo, id=id)) elif str(mimetype).lower() in ["text/plain", "application/json"]: response.content_type = "text/plain" return response_message try: mimetype = accept_list.pop(0) except IndexError: mimetype = None # Whoops - nothing satisfies - return text/plain response.content_type = "text/plain" return response_message
def raw(self): ident = request.environ.get('repoze.who.identity') c.ident = ident silos = None if ag.metadata_embargoed: if not ident: abort(401, "Not Authorised") silos = ag.authz(ident) if silos and not isinstance(silos, basestring) and type(silos).__name__ == 'list': silos = ' '.join(silos) http_method = request.environ['REQUEST_METHOD'] if http_method == "GET": params = request.GET elif http_method == "POST": params = request.POST if not "q" in params: abort(400, "Parameter 'q' is not available") #If ag.metadata_embargoed, search only within your silos if params['q'] == '*': if silos: params['q'] = """silo:(%s)"""%silos else: params['q'] = "*:*" elif silos and not 'silo:' in params['q']: params['q'] = """%s AND silo:(%s)"""%(params['q'], silos) accept_list = None if 'wt' in params and params['wt'] == "json": accept_list = [MT("application", "json")] elif 'wt' in params and params['wt'] == "xml": accept_list = [MT("text", "xml")] else: if 'HTTP_ACCEPT' in request.environ: try: accept_list = conneg_parse(request.environ['HTTP_ACCEPT']) except: accept_list= [MT("text", "html")] if not accept_list: accept_list= [MT("text", "html")] mimetype = accept_list.pop(0) while(mimetype): if str(mimetype).lower() in ["text/html", "text/xhtml"]: params['wt'] = 'json' accept_list= [MT("text", "html")] break elif str(mimetype).lower() in ["text/plain", "application/json"]: params['wt'] = 'json' accept_list= [MT("application", "json")] break elif str(mimetype).lower() in ["application/rdf+xml", "text/xml"]: params['wt'] = 'xml' accept_list = [MT("text", "xml")] break # Whoops - nothing satisfies try: mimetype = accept_list.pop(0) except IndexError: mimetype = None if not 'wt' in params or not params['wt'] in ['json', 'xml']: params['wt'] = 'json' accept_list= [MT("text", "html")] if not 'fl' in params or not params['fl']: #Also include the following fields - date modified, publication year / publication date, embargo status, embargo date, version params['fl'] = "id,silo,mediator,creator,title,score" if not 'start' in params or not params['start']: params['start'] = '0' if not 'rows' in params or not params['rows']: params['rows'] = '100' try: result = ag.solr.raw_query(**params) except: result = {} mimetype = accept_list.pop(0) while(mimetype): if str(mimetype).lower() in ["text/html", "text/xhtml"]: c.result = result return render('/raw_search.html') elif str(mimetype).lower() in ["text/plain", "application/json"]: response.content_type = 'application/json; charset="UTF-8"' response.status_int = 200 response.status = "200 OK" return result elif str(mimetype).lower() in ["application/rdf+xml", "text/xml"]: response.content_type = 'text/xml; charset="UTF-8"' response.status_int = 200 response.status = "200 OK" return result # Whoops - nothing satisfies try: mimetype = accept_list.pop(0) except IndexError: mimetype = None #Whoops - nothing staisfies - default to text/html c.result = result return render('/raw_search.html')
def index(self): if not request.environ.get('repoze.who.identity'): abort(401, "Not Authorised") ident = request.environ.get('repoze.who.identity') c.ident = ident c.granary_list = ag.authz(ident, permission=['administrator', 'manager']) http_method = request.environ['REQUEST_METHOD'] if http_method == 'GET': if not 'administrator' in ident['permissions'] and not 'manager' in ident['permissions']: abort(403, "Do not have administrator or manager credentials") else: if not 'administrator' in ident['permissions']: abort(403, "Do not have administrator credentials") if http_method == "GET": #c.granary = ag.granary # conneg return accept_list = None if 'HTTP_ACCEPT' in request.environ: try: accept_list = conneg_parse(request.environ['HTTP_ACCEPT']) except: accept_list= [MT("text", "html")] if not accept_list: accept_list= [MT("text", "html")] mimetype = accept_list.pop(0) while(mimetype): if str(mimetype).lower() in ["text/html", "text/xhtml"]: return render("/admin_silos.html") elif str(mimetype).lower() in ["text/plain", "application/json"]: response.content_type = 'application/json; charset="UTF-8"' response.status_int = 200 response.status = "200 OK" return simplejson.dumps(list(c.granary_list)) try: mimetype = accept_list.pop(0) except IndexError: mimetype = None #Whoops nothing satisfies - return text/html return render("admin_silos.html") elif http_method == "POST": params = request.POST if 'silo' in params: if ag.granary.issilo(params['silo']): abort(403, "The silo %s exists"%params['silo']) if not allowable_id2(params['silo']): response.content_type = "text/plain" response.status_int = 400 response.status = "400 Bad request. Silo name not valid" return "Silo name can contain only the following characters - %s and has to be more than 1 character"%ag.naming_rule_humanized #NOTE: #If any userid in params['administrators']/params['managers']/params['submitters'] does not exist, return 403 #if administartor list is empty, append current user to administartor list #Owner is the superset of adminstrators, managers and submitters existing_users = list_usernames() owners = [] admins = [] managers = [] submitters = [] #if 'owners' in params and params['owners']: # owners = [x.strip() for x in kw['owners'].split(",") if x] if 'administrators' in params and params['administrators']: admins = [x.strip() for x in params['administrators'].split(",") if x] owners.extend(admins) if 'managers' in params and params['managers']: managers = [x.strip() for x in params['managers'].split(",") if x] owners.extend(managers) if 'submitters' in params and params['submitters']: submitters = [x.strip() for x in params['submitters'].split(",") if x] owners.extend(submitters) if not admins: owners.append(ident['user'].user_name) admins.append(ident['user'].user_name) owners = list(set(owners)) for o in owners: if not o in existing_users: abort (403, "User %s does not exist"%o) admins = list(set(admins)) managers = list(set(managers)) submitters = list(set(submitters)) # Create new silo silo = params['silo'] g_root = config.get("granary.uri_root", "info:") c.silo = ag.granary.get_rdf_silo(silo, uri_base="%s%s/datasets/" % (g_root, silo)) ag.granary._register_silos() kw = {} for term in accepted_params: if term in params: kw[term] = params[term] kw['owners'] = ','.join(owners) kw['administrators'] = ','.join(admins) kw['managers'] = ','.join(managers) kw['submitters'] = ','.join(submitters) du = ag.granary.disk_usage_silo(silo) kw['disk_usage'] = du ag.granary.describe_silo(silo, **kw) ag.granary.sync() # Add silo to database add_silo(silo) try: ag.b.silo_creation(silo, ident=ident['repoze.who.userid']) except: pass #Add users belonging to the silo, to the database all_silo_users = [] for a in admins: all_silo_users.append((a, 'administrator')) for a in managers: all_silo_users.append((a, 'manager')) for a in submitters: all_silo_users.append((a, 'submitter')) add_group_users(params['silo'], all_silo_users) ag.granary.state.revert() ag.granary._register_silos() # conneg return accept_list = None if 'HTTP_ACCEPT' in request.environ: try: accept_list = conneg_parse(request.environ['HTTP_ACCEPT']) except: accept_list= [MT("text", "html")] if not accept_list: accept_list= [MT("text", "html")] mimetype = accept_list.pop(0) while(mimetype): if str(mimetype).lower() in ["text/html", "text/xhtml"]: redirect(url(controller="datasets", action="siloview", silo=silo)) elif str(mimetype).lower() in ["text/plain", "application/json"]: response.content_type = "text/plain" response.status_int = 201 response.status = "201 Created" response.headers['Content-Location'] = url(controller="datasets", action="siloview", silo=silo) return "201 Created Silo %s" % silo try: mimetype = accept_list.pop(0) except IndexError: mimetype = None # Whoops - nothing satisfies - return text/plain response.content_type = "text/plain" response.status_int = 201 response.status = "201 Created" response.headers['Content-Location'] = url(controller="datasets", action="siloview", silo=silo) return "201 Created Silo %s" % silo else: response.content_type = "text/plain" response.status_int = 400 response.status = "400 Bad Request" return "400 Bad request. No valid parameters found."
def siloview(self, silo): if not request.environ.get('repoze.who.identity'): abort(401, "Not Authorised") if not ag.granary.issilo(silo): abort(404) ident = request.environ.get('repoze.who.identity') c.ident = ident c.silo = silo silos = ag.authz(ident, permission=['administrator', 'manager']) if not silo in silos: abort(403, "Do not have administrator or manager credentials for silo %s"%silo) user_groups = list_user_groups(ident['user'].user_name) if ('*', 'administrator') in user_groups: #User is super user c.roles = ["admin", "manager", "user"] elif (silo, 'administrator') in user_groups: c.roles = ["admin", "manager", "user"] elif (silo, 'manager') in user_groups: c.roles = ["manager", "user"] else: abort(403, "Do not have administrator or manager credentials for silo %s"%silo) http_method = request.environ['REQUEST_METHOD'] c.kw = ag.granary.describe_silo(silo) if http_method == "GET": accept_list = None if 'HTTP_ACCEPT' in request.environ: try: accept_list = conneg_parse(request.environ['HTTP_ACCEPT']) except: accept_list= [MT("text", "html")] if not accept_list: accept_list= [MT("text", "html")] mimetype = accept_list.pop(0) while(mimetype): if str(mimetype).lower() in ["text/html", "text/xhtml"]: return render("/admin_siloview.html") elif str(mimetype).lower() in ["text/plain", "application/json"]: response.content_type = 'application/json; charset="UTF-8"' response.status_int = 200 response.status = "200 OK" return simplejson.dumps(dict(c.kw)) try: mimetype = accept_list.pop(0) except IndexError: mimetype = None #Whoops nothing satisfies - return text/html return render("/admin_siloview.html") elif http_method == "POST": params = request.POST #Get existing owners, admins, managers and submitters owners = [] admins = [] managers = [] submitters = [] if 'owners' in c.kw and c.kw['owners']: owners = [x.strip() for x in c.kw['owners'].split(",") if x] if 'administrators' in c.kw and c.kw['administrators']: admins = [x.strip() for x in c.kw['administrators'].split(",") if x] if 'managers' in c.kw and c.kw['managers']: managers = [x.strip() for x in c.kw['managers'].split(",") if x] if 'submitters' in c.kw and c.kw['submitters']: submitters = [x.strip() for x in c.kw['submitters'].split(",") if x] #Get new members new_owners = [] #Get new admins new_admins = [] if 'administrators' in params and params['administrators']: returned_admins = [x.strip() for x in params['administrators'].split(",") if x] new_admins = [x for x in returned_admins if not x in admins] new_owners.extend(new_admins) #Get new managers new_managers = [] if 'managers' in params and params['managers']: returned_managers = [x.strip() for x in params['managers'].split(",") if x] new_managers = [x for x in returned_managers if not x in managers] new_owners.extend(new_managers) #Get new submitters new_submitters = [] if 'submitters' in params and params['submitters']: returned_submitters = [x.strip() for x in params['submitters'].split(",") if x] new_submitters = [x for x in returned_submitters if not x in submitters] new_owners.extend(new_submitters) #Check if the new members exist. If not return 403 existing_users = list_usernames() new_owners = list(set(new_owners)) for o in new_owners: if not o in existing_users: abort (403, "User %s does not exist"%o) if new_admins and not 'admin' in c.roles: abort (403, "Only administrators can assing users to role 'administrator'") owners.extend(new_owners) new_admins = list(set(new_admins)) admins.extend(new_admins) new_managers = list(set(new_managers)) managers.extend(new_managers) new_submitters = list(set(new_submitters)) submitters.extend(new_submitters) # Update silo info updateMetadata = False for term in accepted_params: if term in params and not term in ['owners', 'administrators', 'managers', 'submitters'] and params[term]: c.kw[term] = params[term] updateMetadata = True if new_owners or new_admins or new_managers or new_submitters or updateMetadata: new_silo_users = [] if new_owners: c.kw['owners'] = ','.join(owners) if new_admins: c.kw['administrators'] = ','.join(admins) for a in new_admins: new_silo_users.append((a, 'administrator')) if new_managers: c.kw['managers'] = ','.join(managers) for a in new_managers: new_silo_users.append((a, 'manager')) if new_submitters: c.kw['submitters'] = ','.join(submitters) for a in new_submitters: new_silo_users.append((a, 'submitter')) #Add metadat changes to the silo ag.granary.describe_silo(silo, **c.kw) ag.granary.sync() #Add new silo users into database if new_silo_users: add_group_users(silo, new_silo_users) if updateMetadata: try: ag.b.silo_change(silo, ident=ident['repoze.who.userid']) except: pass # conneg return accept_list = None if 'HTTP_ACCEPT' in request.environ: try: accept_list = conneg_parse(request.environ['HTTP_ACCEPT']) except: accept_list= [MT("text", "html")] if not accept_list: accept_list= [MT("text", "html")] mimetype = accept_list.pop(0) while(mimetype): if str(mimetype).lower() in ["text/html", "text/xhtml"]: c.message = "Metadata updated" c.kw = ag.granary.describe_silo(silo) return render("/admin_siloview.html") elif str(mimetype).lower() in ["text/plain", "application/json"]: response.content_type = "text/plain" response.status_int = 204 response.status = "204 Updated" #return "Updated Silo %s" % silo return try: mimetype = accept_list.pop(0) except IndexError: mimetype = None # Whoops - nothing satisfies - return text/plain response.content_type = "text/plain" response.status_int = 204 response.status = "204 Updated" return elif http_method == "DELETE": # Deletion of an entire Silo... # Serious consequences follow this action # Walk through all the items, emit a delete msg for each # and then remove the silo todelete_silo = ag.granary.get_rdf_silo(silo) #for item in todelete_silo.list_items(): # try: # ag.b.deletion(silo, item, ident=ident['repoze.who.userid']) # except: # pass ag.granary.delete_silo(silo) try: ag.b.silo_deletion(silo, ident=ident['repoze.who.userid']) except: pass try: del ag.granary.state[silo] except: pass ag.granary.sync() ag.granary._register_silos() #Delete silo from database delete_silo(silo) # conneg return accept_list = None response.content_type = "text/plain" response.status_int = 200 response.status = "200 OK" return "{'ok':'true'}"
def datasetview(self, silo, id): c.silo_name = silo c.id = id http_method = request.environ['REQUEST_METHOD'] granary_list = list_silos() if not silo in granary_list: abort(404) c_silo = ag.granary.get_rdf_silo(silo) if not c_silo.exists(id): abort(404) if ag.metadata_embargoed: abort(403, "DOIs cannot be issued to data packages whose metadata ia also under embargo") ident = request.environ.get('repoze.who.identity') c.ident = ident item = c_silo.get_item(id) creator = None if item.manifest and item.manifest.state and 'metadata' in item.manifest.state and item.manifest.state['metadata'] and \ 'createdby' in item.manifest.state['metadata'] and item.manifest.state['metadata']['createdby']: creator = item.manifest.state['metadata']['createdby'] c.version = item.currentversion c.version_doi = None c.editor = False #Get version number vnum = request.params.get('version', '') or "" if vnum: vnum = str(vnum) if not vnum in item.manifest['versions']: abort(404, "Version %s of data package %s not found"%(vnum, c.silo_name)) c.version = vnum if not (http_method == "GET"): #identity management of item if not request.environ.get('repoze.who.identity'): abort(401, "Not Authorised") silos = ag.authz(ident) if silo not in silos: abort(403, "Forbidden") silos_admin = ag.authz(ident, permission='administrator') silos_manager = ag.authz(ident, permission='manager') #if not (ident['repoze.who.userid'] == creator or ident.get('role') in ["admin", "manager"]): if not (ident['repoze.who.userid'] == creator or silo in silos_admin or silo in silos_manager): abort(403, "Forbidden") elif http_method == "GET": silos_admin = ag.authz(ident, permission='administrator') silos_manager = ag.authz(ident, permission='manager') #if ident['repoze.who.userid'] == creator or ident.get('role') in ["admin", "manager"]: if ident and ident['repoze.who.userid'] == creator or silo in silos_admin or silo in silos_manager: c.editor = True version_uri = "%s?version=%s"%(item.uri.rstrip('/'), c.version) c.version_doi = item.list_rdf_objects(URIRef(version_uri), u"http://purl.org/ontology/bibo/doi") if not c.version_doi or not c.version_doi[0]: c.version_doi = None else: c.version_doi = c.version_doi[0] doi_conf = OxDataciteDoi() doi_api = HTTPRequest(endpointhost=doi_conf.endpoint_host, secure=True) doi_api.setRequestUserPass(endpointuser=doi_conf.account, endpointpass=doi_conf.password) # conneg: accept_list = None if 'HTTP_ACCEPT' in request.environ: try: accept_list = conneg_parse(request.environ['HTTP_ACCEPT']) except: accept_list= [MT("text", "html")] if not accept_list: accept_list= [MT("text", "html")] c.message = None c.resp_status = None c.resp_reason = None c.metadata = None if http_method == "GET": #Get a list of all dois registered for this data package c.dois = {} for v in item.manifest['versions']: doi_ans = None doi_ans = item.list_rdf_objects(URIRef("%s/version%s"%(item.uri.rstrip('/'), v)), u"http://purl.org/ontology/bibo/doi") if doi_ans and doi_ans[0]: c.dois[v] = doi_ans[0] c.heading = "Doi metadata information from Datacite" if not c.version_doi: mimetype = accept_list.pop(0) while(mimetype): if str(mimetype).lower() in ["text/html", "text/xhtml"]: #Doint this to avoid displaying the erro page!!! response.status_int = 200 response.status = "200 OK" c.metadata = None return render('/doiview.html') try: mimetype = accept_list.pop(0) except IndexError: mimetype = None c.message = 'DOI not registered for version %s of data package %s'%(c.version, c.silo_name) return render('/doiview.html') resource = "%s?doi=%s"%(doi_conf.endpoint_path_metadata, c.version_doi) (resp, respdata) = doi_api.doHTTP_GET(resource=resource, expect_type='application/xml') c.resp_reason = resp.reason c.resp_status = resp.status if resp.status < 200 or resp.status >= 300: response.status_int = 400 response.status = "400 Bad Request" response_msg = '' c.metadata = '' if resp.status == 403: #TODO: Confirm 403 is not due to authorization msg = "403 Forbidden - login error with Datacite or data package belongs to another party at Datacite." elif resp.status == 404: msg = "404 Not Found - DOI does not exist in DatCite's database" elif resp.status == 410: msg = "410 Gone - the requested data package was marked inactive (using DELETE method) at Datacite" elif resp.status == 500: msg = "500 Internal Server Error - Error retreiving the metadata from Datacite." else: msg = "Error retreiving the metadata from Datacite. %s"%str(resp.status) c.message = msg else: response.status_int = 200 response.status = "200 OK" c.metadata = respdata response_msg = respdata # conneg: mimetype = accept_list.pop(0) while(mimetype): if str(mimetype).lower() in ["text/html", "text/xhtml"]: #Setting headers to 200 to avoid displaying the error page!!! response.status_int = 200 response.status = "200 OK" return render('/doiview.html') elif str(mimetype).lower() in ["text/plain", "application/json"]: response.content_type = 'text/plain; charset="UTF-8"' return str(respdata.decode('utf-8')) elif str(mimetype).lower() in ["application/rdf+xml", "text/xml"]: response.status_int = 200 response.status = "200 OK" response.content_type = 'text/xml; charset="UTF-8"' return response_msg try: mimetype = accept_list.pop(0) except IndexError: mimetype = None #Whoops - nothing staisfies - default to text/html #Setting headers to 200 to avoid displaying the error page!!! response.status_int = 200 response.status = "200 OK" return render('/doiview.html') if http_method == "POST": item.set_version_cursor(c.version) #1a. If doi doen not exist for this version, generate doi register_doi = False if not c.version_doi: cnt = doi_count() if not cnt: abort(400, "Error generating DOI") register_doi = True tiny_pid = short_pid.encode_url(cnt) c.version_doi = "%s/bodleian%s.%s"%(doi_conf.prefix, tiny_pid, c.version) #1b. Construct XML metadata if c.version_doi: xml_metadata = get_doi_metadata(c.version_doi, item) c.metadata = xml_metadata #FOR TEST PURPOSES ONLY #xml_metadata = False # Have commented out the sections below as we will only register a DOI if there is metadata """ if not xml_metadata and not register_doi: #2a. If the doi already exists and there is no xml metadata to update, return bad request c.message = "Coud not update metadata" response.status_int = 400 response.status = "Bad request" respdata = c.message c.metadata = '' elif not xml_metadata and register_doi: #2b. If the doi is not registered, but there is no xml metadata to update, register just the doi with datacite c.heading = "Registering new DOI with Datacite" resource = "%s"%doi_conf.endpoint_path_doi body = "%s\n%s"%(c.version_doi, version_uri) #body_unicode = unicode(body, "utf-8") body_unicode = unicode(body) (resp, respdata) = doi_api.doHTTP_POST(body_unicode, resource=resource, data_type='text/plain;charset=UTF-8') c.resp_reason = resp.reason c.resp_status = resp.status if resp.status < 200 or resp.status >= 300: response.status_int = 400 response.status = "400 Bad Request" response_msg = "DOI not registered" c.metadata = '' if resp.status == 400: msg = "400 Bad Request - Request body must be exactly two lines: DOI and URL" elif resp.status == 403: #TODO: Confirm 403 is not due to authorization msg = "403 Forbidden - From Datacite: login problem, quota excceded, wrong domain, wrong prefix" elif resp.status == 500: msg = "500 Internal Server Error - Error registering the DOI." else: msg = "Error retreiving the metadata from Datacite. %s"%str(resp.status) c.message = msg else: #3. Add the DOI to the rdf metadata item.add_namespace('bibo', "http://purl.org/ontology/bibo/") item.add_triple(URIRef(version_uri), u"bibo:doi", Literal(c.version_doi)) item.del_triple(item.uri, u"dcterms:modified") item.add_triple(item.uri, u"dcterms:modified", datetime.now()) item.sync() response.status_int = 200 response.status = "200 OK" response_msg = "DOI Registered. %s"%respdata c.metadata = '' c.message = "201 Created - DOI registered. %s"%respdata """ if not xml_metadata: #2a. If the doi already exists and there is no xml metadata to update, return bad request c.message = "Could not generate metadata" c.metadata = '' abort(400, "Error generating metadata") elif not register_doi: c.message = "Could not generate DOI" abort(400, "Error generating DOI") else: #register the DOI with Datacite resource = "%s"%doi_conf.endpoint_path_doi body = "doi=%s\nurl=%s"%(c.version_doi, version_uri) body_unicode = unicode(body) (resp, respdata) = doi_api.doHTTP_POST(body_unicode, resource=resource, data_type='text/plain;charset=UTF-8') c.resp_reason1 = resp.reason c.resp_status1 = resp.status #Add the metadata within Datacite c.heading = "Registering new DOI along with its metadata with Datacite" #body_unicode = unicode(xml_metadata, "utf-8") #body_unicode = unicode(xml_metadata) body_unicode = xml_metadata resource = "%s?doi=%s&url=%s"%(doi_conf.endpoint_path_metadata, c.version_doi, version_uri) (resp, respdata) = doi_api.doHTTP_POST(body_unicode, resource=resource, data_type='application/xml;charset=UTF-8') c.resp_reason = resp.reason c.resp_status = resp.status if (c.resp_status1>= 200 and c.resp_status1 < 300) or (resp.status >= 200 and resp.status < 300): #3. Add the DOI to the rdf metadata item.add_namespace('bibo', "http://purl.org/ontology/bibo/") item.add_triple(URIRef(version_uri), u"bibo:doi", Literal(c.version_doi)) item.del_triple(item.uri, u"dcterms:modified") item.add_triple(item.uri, u"dcterms:modified", datetime.now()) item.sync() #4. Broadcast changes to redis try: ag.b.change(silo, id, ident=ident['repoze.who.userid']) except: pass if resp.status < 200 or resp.status >= 300: response.status_int = 400 response.status = "400 Bad Request" response_msg = "DOI and metadata not registered" c.metadata = body_unicode if resp.status == 400: msg = "400 Bad Request - Invalid XML metadata" elif resp.status == 403: #TODO: Confirm 403 is not due to authorization msg = "403 Forbidden - From Datacite: login problem, quota excceded, wrong domain, wrong prefix" elif resp.status == 500: msg = "500 Internal Server Error - Error registering the DOI." else: msg = "Error retreiving the metadata from Datacite. %s"%str(resp.status) c.message = msg else: response.status_int = 200 response.status = "200 OK" response_msg = body_unicode c.metadata = body_unicode c.message = "201 Created - DOI registered. %s"%respdata # conneg: mimetype = accept_list.pop(0) while(mimetype): if str(mimetype).lower() in ["text/html", "text/xhtml"]: #Setting headers to 200 to avoid displaying the error page!!! response.status_int = 200 response.status = "200 OK" return render('/doiview.html') elif str(mimetype).lower() in ["text/plain", "application/json"]: response.content_type = 'text/plain' return str(respdata.decode('utf-8')) elif str(mimetype).lower() in ["application/rdf+xml", "text/xml"]: response.status_int = 200 response.status = "200 OK" response.content_type = 'text/xml; charset="UTF-8"' return response_msg try: mimetype = accept_list.pop(0) except IndexError: mimetype = None #Whoops - nothing staisfies - default to text/html #Setting headers to 200 to avoid displaying the error page!!! response.status_int = 200 response.status = "200 OK" return render('/doiview.html')
def silouserview(self, silo, username): if not request.environ.get('repoze.who.identity'): abort(401, "Not Authorised") if not ag.granary.issilo(silo): abort(404) ident = request.environ.get('repoze.who.identity') http_method = request.environ['REQUEST_METHOD'] if http_method == 'GET': silos = ag.authz(ident) if not silo in silos: abort(403, "User is not a member of the silo %s"%silo) if not ('administrator' in ident['permissions'] or \ 'manager' in ident['permissions'] or ident['user'].user_name == username): abort(403, "Do not have administrator or manager credentials to view profiles of other users") else: silos = ag.authz(ident, permission=['administrator', 'manager']) if not silo in silos: abort(403, "Do not have administrator or manager credentials for silo %s"%silo) if not ('administrator' in ident['permissions'] or 'manager' in ident['permissions']): abort(403, "Do not have administrator or manager credentials") existing_users = list_usernames() if not username in existing_users: abort(404, "User not found") c.ident = ident c.silo = silo c.username = username if http_method == "GET": a, m, s = list_group_usernames(silo) if not (username in a or username in m or username in s): abort(404, "User not found in silo") c.user = list_user(username) #if 'groups' in c.user and c.user['groups']: # for i in c.user['groups']: # if i[0] != silo: # c.user['groups'].remove(i) accept_list = None if 'HTTP_ACCEPT' in request.environ: try: accept_list = conneg_parse(request.environ['HTTP_ACCEPT']) except: accept_list= [MT("text", "html")] if not accept_list: accept_list= [MT("text", "html")] mimetype = accept_list.pop(0) while(mimetype): if str(mimetype).lower() in ["text/html", "text/xhtml"]: return render("/silo_user.html") elif str(mimetype).lower() in ["text/plain", "application/json"]: response.content_type = 'application/json; charset="UTF-8"' response.status_int = 200 response.status = "200 OK" return simplejson.dumps(c.user) try: mimetype = accept_list.pop(0) except IndexError: mimetype = None #Whoops nothing satisfies - return text/plain response.content_type = 'application/json; charset="UTF-8"' response.status_int = 200 response.status = "200 OK" return simplejson.dumps(c.user) elif http_method == "POST": params = request.POST if not ('role' in params and params['role'] and params['role'] in ['administrator', 'manager', 'submitter']): abort(400, "Parameters 'role' not found or is invalid") kw = ag.granary.describe_silo(silo) #Get existing owners, admins, managers and users owners = [] admins = [] managers = [] submitters = [] if 'owners' in kw and kw['owners']: owners = [x.strip() for x in kw['owners'].split(",") if x] if 'administrators' in kw and kw['administrators']: admins = [x.strip() for x in kw['administrators'].split(",") if x] if 'managers' in kw and kw['managers']: managers = [x.strip() for x in kw['managers'].split(",") if x] if 'submitters' in kw and kw['submitters']: submitters = [x.strip() for x in kw['submitters'].split(",") if x] to_remove = [] to_add = [] if params['role'] == 'administrator': if not 'administrator' in ident['permissions']: abort(403, "Need to be administrator to add user to role admin") if not username in admins: to_add.append((username, 'administrator')) admins.append(username) if not username in owners: owners.append(username) if username in managers: managers.remove(username) to_remove.append((username, 'manager')) if username in submitters: submitters.remove(username) to_remove.append((username, 'submitter')) elif params['role'] == 'manager': if not username in managers: to_add.append((username, 'manager')) managers.append(username) if not username in owners: owners.append(username) if username in admins: if not 'administrator' in ident['permissions']: abort(403, "Need to be admin to modify user of role admin") if len(admins) == 1: abort(403, "Add another administrator to silo before updating user role") admins.remove(username) to_remove.append((username, 'administrator')) if username in submitters: submitters.remove(username) to_remove.append((username, 'submitter')) elif params['role'] == 'submitter': if not username in submitters: to_add.append((username, 'submitter')) submitters.append(username) if not username in owners: owners.append(username) if username in admins: if not 'administrator' in ident['permissions']: abort(403, "Need to be admin to modify user of role admin") if len(admins) == 1: abort(403, "Add another administrator to silo before updating user role") admins.remove(username) to_remove.append((username, 'administrator')) if username in managers: if len(managers) == 1 and len(admins) == 0: abort(403, "Add another administrator or manager to silo before updating user role") managers.remove(username) to_remove.append((username, 'manager')) owners = list(set(owners)) admins = list(set(admins)) managers = list(set(managers)) submitters = list(set(submitters)) # Update silo info if to_remove or to_add: kw['owners'] = ','.join(owners) kw['administrators'] = ','.join(admins) kw['managers'] = ','.join(managers) kw['submitters'] = ','.join(submitters) ag.granary.describe_silo(silo, **kw) ag.granary.sync() #Add new silo users into database if to_add: add_group_users(silo, to_add) response.status_int = 201 response.status = "201 Created" response.headers['Content-Location'] = url(controller="users", action="silouserview", silo=silo, username=username) response_message = "201 Created" if to_remove: delete_group_users(silo, to_remove) response.status_int = 204 response.status = "204 Updated" response_message = None else: response.status_int = 400 response.status = "400 Bad Request" response_message = "No updates to user role" #Conneg return accept_list = None if 'HTTP_ACCEPT' in request.environ: try: accept_list = conneg_parse(request.environ['HTTP_ACCEPT']) except: accept_list= [MT("text", "html")] if not accept_list: accept_list= [MT("text", "html")] mimetype = accept_list.pop(0) while(mimetype): if str(mimetype).lower() in ["text/html", "text/xhtml"]: redirect(url(controller="users", action="silouserview", silo=silo, username=username)) elif str(mimetype).lower() in ["text/plain", "application/json"]: response.content_type = 'application/json; charset="UTF-8"' return response_message try: mimetype = accept_list.pop(0) except IndexError: mimetype = None #Whoops nothing satisfies - return text/plain response.content_type = 'application/json; charset="UTF-8"' return response_message elif http_method == "DELETE": kw = ag.granary.describe_silo(silo) #Get existing owners, admins, managers and users owners = [] admins = [] managers = [] submitters = [] if 'owners' in kw and kw['owners']: owners = [x.strip() for x in kw['owners'].split(",") if x] if 'administrators' in kw and kw['administrators']: admins = [x.strip() for x in kw['administrators'].split(",") if x] if 'managers' in kw and kw['managers']: managers = [x.strip() for x in kw['managers'].split(",") if x] if 'submitters' in kw and kw['submitters']: submitters = [x.strip() for x in kw['submitters'].split(",") if x] #Gather user roles to delete to_remove = [] if username in admins: if not 'administrator' in ident['permissions']: abort(403, "Need to be admin to modify user of role admin") if len(admins) == 1: abort(403, "Add another administrator to silo before deleting user") to_remove.append((username, 'administrator')) admins.remove(username) if username in managers: if len(managers) == 1 and len(admins) == 0: abort(403, "Add another administrator or manager to silo before deleting user") managers.remove(username) to_remove.append((username, 'manager')) if username in submitters: submitters.remove(username) to_remove.append((username, 'submitter')) if username in owners: owners.remove(username) owners = list(set(owners)) admins = list(set(admins)) managers = list(set(managers)) submitters = list(set(submitters)) if to_remove: # Update silo info kw['owners'] = ','.join(owners) kw['administrators'] = ','.join(admins) kw['managers'] = ','.join(managers) kw['submitters'] = ','.join(submitters) ag.granary.describe_silo(silo, **kw) ag.granary.sync() delete_group_users(silo, to_remove) else: abort(400, "No user to delete") accept_list = None response.content_type = "text/plain" response.status_int = 200 response.status = "200 OK" return "{'ok':'true'}"
def siloview(self, silo): """ Returns the state information of a silo. Only authorized users with role 'admin' or 'manager' can view this information The state information for a silo contains the following: Name of the silo (machine name, used in uris) - ans["silo"] Base URI for the silo - ans["uri_base"] Users who can access the silo (silo owners) - ans["owners"] Silo description - ans["description"] Title of the silo (human readable) - ans["title"] Disk allocation for the silo (in kB) - ans["disk_allocation"] List of datasets in the silo (ans["datasets"]) with embargo information for each of the datasets (ans["datasets"]["dataset_name"]["embargo_info"]) """ # Only authorized users can view state information. # Should this be restricted to admins and managers only, or shoud users too be able to see this information? # Going with restricting this information to admins and managers if not ag.granary.issilo(silo): abort(404) ident = request.environ.get('repoze.who.identity') if not ident: abort(401, "Not Authorised") silos = ag.authz(ident) if silo not in silos: abort(403, "Forbidden") silos_admin = ag.authz(ident, permission='administrator') silos_manager = ag.authz(ident, permission='manager') #if not ident.get('role') in ["admin", "manager"]: if not (silo in silos_admin or silo in silos_manager): abort(403, "Forbidden. You should be an administrator or manager to view this information") options = request.GET start = 0 if 'start' in options and options['start']: try: start = int(options['start']) except: start = 0 rows = 1000 if 'rows' in options and options['rows']: try: rows = int(options['rows']) except: rows = 1000 rdfsilo = ag.granary.get_rdf_silo(silo) state_info = ag.granary.describe_silo(silo) state_info['silo'] = silo state_info['uri_base'] = '' if rdfsilo.state and rdfsilo.state['uri_base']: state_info['uri_base'] = rdfsilo.state['uri_base'] state_info['number of data packages'] = get_datasets_count(silo) state_info['params'] = {'start':start, 'rows':rows} items = {} #for item in rdfsilo.list_items(): for item in get_datasets(silo, start=start, rows=rows): items[item] = {} try: items[item]['embargo_info'] = is_embargoed(rdfsilo, item) except: pass state_info['datasets'] = items # conneg return # Always return application/json response.content_type = 'application/json; charset="UTF-8"' response.status_int = 200 response.status = "200 OK" return simplejson.dumps(state_info)