def save(self, force_insert=False, force_update=False, *args, **kwargs): """ Custom save method. When present, replace a special token string (configured in django settings as **PID_REPLACEMENT_TOKEN**) in the target uri with the noid. Also ensures that pid and noid stay synchronized, check that qualifier does not contain any invalid characters, and normalizes ARK qualifier so it will be resolved correctly. """ # a special token in target URI should be replaced with minted noid if (self.uri.find(settings.PID_REPLACEMENT_TOKEN) != -1): # Note: not using self.noid because it doesn't seem to be set yet self.uri = self.uri.replace(settings.PID_REPLACEMENT_TOKEN, self.pid.pid) #keep noid and pid in sync if (not self.noid): self.noid = self.pid.pid elif (self.noid != self.pid.pid): raise ValidationError("Target.noid(%s) and Pid(%s) do not match)" % (self.noid, self.pid.pid)) # if qualifier is not valid, it should not be saved if not (valid_qualifier(self.qualify)): raise ValidationError( "Qualifier '%s' contains invalid characters" % (self.qualify)) # normalize so qualifier will be found by the resolver self.qualify = normalize_ark(self.qualify) return super(Target, self).save(force_insert=force_insert, force_update=force_update, *args, **kwargs)
def save(self, force_insert=False, force_update=False, *args, **kwargs): """ Custom save method. When present, replace a special token string (configured in django settings as **PID_REPLACEMENT_TOKEN**) in the target uri with the noid. Also ensures that pid and noid stay synchronized, check that qualifier does not contain any invalid characters, and normalizes ARK qualifier so it will be resolved correctly. """ # a special token in target URI should be replaced with minted noid if (self.uri.find(settings.PID_REPLACEMENT_TOKEN) != -1): # Note: not using self.noid because it doesn't seem to be set yet self.uri = self.uri.replace(settings.PID_REPLACEMENT_TOKEN, self.pid.pid) #keep noid and pid in sync if(not self.noid): self.noid = self.pid.pid elif(self.noid != self.pid.pid): raise ValidationError("Target.noid(%s) and Pid(%s) do not match)"%(self.noid, self.pid.pid)) # if qualifier is not valid, it should not be saved if not(valid_qualifier(self.qualify)): raise ValidationError("Qualifier '%s' contains invalid characters"%(self.qualify)) # normalize so qualifier will be found by the resolver self.qualify = normalize_ark(self.qualify) return super(Target, self).save(force_insert=force_insert, force_update=force_update, *args, **kwargs)
def test_valid_qualifier(self): self.assertTrue(valid_qualifier("45ae%"), "'45ae%' is a valid qualifier") self.assertFalse(valid_qualifier("45ae^"), "'45ae^' is not a valid qualifier")
def characters_valid(self): for t in self.target_set.exclude(qualify=''): if not valid_qualifier(t.qualify): return "<span style='color:red'>NO</span>" return "<span style='color:green'>Yes</span>"
def create_pid(request, type): '''On POST, create a new ARK or PURL. On successful creation, returns a response with status code 201 (Created), and response content is the resolvables url for the newly minted ARK or PURL. If required parameters are missing or any parameters are invalid (e.g., referencing a Proxy or Policy that does not exist), the returned response will have a status code 400 (Bad Request), and the content of the response will be an explanatory message. Supported POST parameters: * domain - REQUIRED; domain should be in URI resource format, e.g. http://pid.emory.edu/domains/1/ * target_uri - REQUIRED; URL that the new ARK or PURL should resolve to * name - label or title for the new pid * external_system_id - external system name * external_system_key - key or identifier in the specified external system * policy - policy by name (if this pid needs a different policy from its domain) * proxy - proxy to use when resolving target url; specify by name * qualifier - target should be created with the specified target; **ARK only** :param type: type of pid to create - ark or purl Example create urls:: http://pid.emory.edu/ark/ - create a new ARK http://pid.emory.edu/purl/ - create a new PURL ''' if request.method == 'POST': # TODO: require ssl ? if not request.user.is_authenticated(): # 401 unauthorized - not logged in or invalid credentials return HttpResponseUnauthorized(BASIC_AUTH_REALM) elif not request.user.has_perm('pid.add_pid'): # 403 Forbidden - logged in but insufficient permissions return HttpResponseForbidden() try: # if required fields are not present, return an error message if 'domain' not in request.POST or 'target_uri' not in request.POST: raise BadRequest('domain and target_uri are required') # incompatible options - qualifier only makes sense for purls if 'qualifier' in request.POST and type == 'purl': raise BadRequest('Purl targets can not have qualifiers') # domain should be passed in as resource URI - resolve to model instance domain = _domain_from_uri(request.POST['domain']) # assemble the data for creating the new pid # - required fields pid_opts = { 'type': type.title(), # url uses lower case, model requires title case 'domain': domain, 'creator_id': request.user.id, 'editor_id': request.user.id } # - optional fields if 'name' in request.POST: pid_opts['name'] = request.POST['name'] # could you have an external system id and not a ext-sys key? or vice versa? if 'external_system_id' in request.POST: try: pid_opts['ext_system'] = ExtSystem.objects.get( name=request.POST['external_system_id']) except ObjectDoesNotExist: raise BadRequest("External System '%s' not found" % request.POST['external_system_id']) if 'external_system_key' in request.POST: pid_opts['ext_system_key'] = request.POST[ 'external_system_key'] if 'policy' in request.POST: try: pid_opts['policy'] = Policy.objects.get( title=request.POST['policy']) except ObjectDoesNotExist: raise BadRequest("Policy '%s' not found" % request.POST['policy']) # target can't be created until after the noid is minted # - init target options before creating pid to be sure they are valid # (i.e., if a proxy is specified, it exists) target_opts = {'uri': request.POST['target_uri']} if 'proxy' in request.POST: try: target_opts['proxy'] = Proxy.objects.get( name=request.POST['proxy']) except ObjectDoesNotExist: raise BadRequest("Proxy '%s' not found" % request.POST['proxy']) if 'qualifier' in request.POST: # an invalid qualifier would normally get caught when a target is saved # checking here to avoid creating a new Pid if the qualifier is invalid if not valid_qualifier(request.POST['qualifier']): raise BadRequest( "Qualifier '%s' contains invalid characters" % request.POST['qualifier']) target_opts['qualify'] = request.POST['qualifier'] # create the pid, and then save to mint the noid before target is created p = Pid(**pid_opts) p.save() _log_rest_action(request, p, ADDITION, 'Added pid:%s via rest api' % p.__unicode__()) t = p.target_set.create(**target_opts) _log_rest_action( request, t, ADDITION, 'Added target:%s for pid:%s via rest api' % (t.__unicode__(), p.__unicode__())) # return the resolvable url (purl/ark) for the new target return HttpResponse(t.get_resolvable_url(), status=201) # 201 Created except BadRequest as err: # return a response with status code 400, Bad Request return HttpResponseBadRequest('Error: %s' % err) # if request method is not POST, return 405 method not allowed return HttpResponseNotAllowed(['POST'])
def create_pid(request, type): """On POST, create a new ARK or PURL. On successful creation, returns a response with status code 201 (Created), and response content is the resolvables url for the newly minted ARK or PURL. If required parameters are missing or any parameters are invalid (e.g., referencing a Proxy or Policy that does not exist), the returned response will have a status code 400 (Bad Request), and the content of the response will be an explanatory message. Supported POST parameters: * domain - REQUIRED; domain should be in URI resource format, e.g. http://pid.emory.edu/domains/1/ * target_uri - REQUIRED; URL that the new ARK or PURL should resolve to * name - label or title for the new pid * external_system_id - external system name * external_system_key - key or identifier in the specified external system * policy - policy by name (if this pid needs a different policy from its domain) * proxy - proxy to use when resolving target url; specify by name * qualifier - target should be created with the specified target; **ARK only** :param type: type of pid to create - ark or purl Example create urls:: http://pid.emory.edu/ark/ - create a new ARK http://pid.emory.edu/purl/ - create a new PURL """ if request.method == "POST": # TODO: require ssl ? if not request.user.is_authenticated(): # 401 unauthorized - not logged in or invalid credentials return HttpResponseUnauthorized(BASIC_AUTH_REALM) elif not request.user.has_perm("pid.add_pid"): # 403 Forbidden - logged in but insufficient permissions return HttpResponseForbidden() try: # if required fields are not present, return an error message if "domain" not in request.POST or "target_uri" not in request.POST: raise BadRequest("domain and target_uri are required") # incompatible options - qualifier only makes sense for purls if "qualifier" in request.POST and type == "purl": raise BadRequest("Purl targets can not have qualifiers") # domain should be passed in as resource URI - resolve to model instance domain = _domain_from_uri(request.POST["domain"]) # assemble the data for creating the new pid # - required fields pid_opts = { "type": type.title(), # url uses lower case, model requires title case "domain": domain, "creator_id": request.user.id, "editor_id": request.user.id, } # - optional fields if "name" in request.POST: pid_opts["name"] = request.POST["name"] # could you have an external system id and not a ext-sys key? or vice versa? if "external_system_id" in request.POST: try: pid_opts["ext_system"] = ExtSystem.objects.get(name=request.POST["external_system_id"]) except ObjectDoesNotExist: raise BadRequest("External System '%s' not found" % request.POST["external_system_id"]) if "external_system_key" in request.POST: pid_opts["ext_system_key"] = request.POST["external_system_key"] if "policy" in request.POST: try: pid_opts["policy"] = Policy.objects.get(title=request.POST["policy"]) except ObjectDoesNotExist: raise BadRequest("Policy '%s' not found" % request.POST["policy"]) # target can't be created until after the noid is minted # - init target options before creating pid to be sure they are valid # (i.e., if a proxy is specified, it exists) target_opts = {"uri": request.POST["target_uri"]} if "proxy" in request.POST: try: target_opts["proxy"] = Proxy.objects.get(name=request.POST["proxy"]) except ObjectDoesNotExist: raise BadRequest("Proxy '%s' not found" % request.POST["proxy"]) if "qualifier" in request.POST: # an invalid qualifier would normally get caught when a target is saved # checking here to avoid creating a new Pid if the qualifier is invalid if not valid_qualifier(request.POST["qualifier"]): raise BadRequest("Qualifier '%s' contains invalid characters" % request.POST["qualifier"]) target_opts["qualify"] = request.POST["qualifier"] # create the pid, and then save to mint the noid before target is created p = Pid(**pid_opts) p.save() _log_rest_action(request, p, ADDITION, "Added pid:%s via rest api" % p.__unicode__()) t = p.target_set.create(**target_opts) _log_rest_action( request, t, ADDITION, "Added target:%s for pid:%s via rest api" % (t.__unicode__(), p.__unicode__()) ) # return the resolvable url (purl/ark) for the new target return HttpResponse(t.get_resolvable_url(), status=201) # 201 Created except BadRequest as err: # return a response with status code 400, Bad Request return HttpResponseBadRequest("Error: %s" % err) # if request method is not POST, return 405 method not allowed return HttpResponseNotAllowed(["POST"])