def getMetadata(identifier, user=ezidapp.models.AnonymousUser, prefixMatch=False): """ Returns all metadata for a given qualified identifier, e.g., "doi:10.5060/FOO". 'user' is the requestor and should be an authenticated StoreUser object. The successful return is a pair (status, dictionary) where 'status' is a string that includes the canonical, qualified form of the identifier, as in: success: doi:10.5060/FOO and 'dictionary' contains element (name, value) pairs. Unsuccessful returns include the strings: error: forbidden error: bad request - subreason... error: internal server error error: concurrency limit exceeded If 'prefixMatch' is true, prefix matching is enabled and the returned identifier is the longest identifier that matches a (possibly proper) prefix of the requested identifier. In such a case, the status string resembles: success: doi:10.5060/FOO in_lieu_of doi:10.5060/FOOBAR """ nqidentifier = util.normalizeIdentifier(identifier) if nqidentifier == None: return "error: bad request - invalid identifier" tid = uuid.uuid1() if not _acquireIdentifierLock(nqidentifier, user.username): return "error: concurrency limit exceeded" try: log.begin(tid, "getMetadata", nqidentifier, user.username, user.pid, user.group.groupname, user.group.pid, str(prefixMatch)) si = ezidapp.models.getIdentifier(nqidentifier, prefixMatch) if not policy.authorizeView(user, si): log.forbidden(tid) return "error: forbidden" d = si.toLegacy() util2.convertLegacyToExternal(d) if si.isDoi: d["_shadowedby"] = si.arkAlias log.success(tid) if prefixMatch and si.identifier != nqidentifier: return ("success: %s in_lieu_of %s" % (si.identifier, nqidentifier), d) else: return ("success: " + nqidentifier, d) except ezidapp.models.StoreIdentifier.DoesNotExist: log.badRequest(tid) return "error: bad request - no such identifier" except Exception, e: log.error(tid, e) return "error: internal server error"
def deleteIdentifier(identifier, user, updateExternalServices=True): """ Deletes an identifier having the given qualified name, e.g., "doi:10.5060/FOO". 'user' is the requestor and should be an authenticated StoreUser object. The successful return is a string that includes the canonical, qualified form of the now-nonexistent identifier, as in: success: doi:/10.5060/FOO Unsuccessful returns include the strings: error: forbidden error: bad request - subreason... error: internal server error error: concurrency limit exceeded """ nqidentifier = util.normalizeIdentifier(identifier) if nqidentifier == None: return "error: bad request - invalid identifier" tid = uuid.uuid1() if not _acquireIdentifierLock(nqidentifier, user.username): return "error: concurrency limit exceeded" try: log.begin( tid, "deleteIdentifier", nqidentifier, user.username, user.pid, user.group.groupname, user.group.pid, ) si = ezidapp.models.getIdentifier(nqidentifier) if not policy.authorizeDelete(user, si): log.forbidden(tid) return "error: forbidden" if not si.isReserved and not user.isSuperuser: log.badRequest(tid) return "error: bad request - identifier status does not support deletion" with django.db.transaction.atomic(): si.delete() ezidapp.models.update_queue.enqueue(si, "delete", updateExternalServices) except ezidapp.models.StoreIdentifier.DoesNotExist: log.badRequest(tid) return "error: bad request - no such identifier" except Exception, e: log.error(tid, e) return "error: internal server error"
def setMetadata(identifier, user, metadata, updateExternalServices=True, internalCall=False): """ Sets metadata elements of a given qualified identifier, e.g., "doi:10.5060/FOO". 'user' is the requestor and should be an authenticated StoreUser object. 'metadata' should be a dictionary of element (name, value) pairs. If an element being set already exists, it is overwritten, if not, it is created; existing elements not set are left unchanged. Of the reserved metadata elements, only "_owner", "_target", "_profile", "_status", and "_export" may be set (unless the user is the EZID administrator). The "_crossref" element may be set only in certain situations. The successful return is a string that includes the canonical, qualified form of the identifier, as in: success: doi:10.5060/FOO Unsuccessful returns include the strings: error: forbidden error: bad request - subreason... error: internal server error error: concurrency limit exceeded """ nqidentifier = util.normalizeIdentifier(identifier) if nqidentifier == None: return "error: bad request - invalid identifier" tid = uuid.uuid1() if not internalCall: if not _acquireIdentifierLock(nqidentifier, user.username): return "error: concurrency limit exceeded" try: log.begin(tid, "setMetadata", nqidentifier, user.username, user.pid, user.group.groupname, user.group.pid, *[a for p in metadata.items() for a in p]) si = ezidapp.models.getIdentifier(nqidentifier) if not policy.authorizeUpdate(user, si): log.forbidden(tid) return "error: forbidden" previousOwner = si.owner si.updateFromUntrustedLegacy(metadata, allowRestrictedSettings=user.isSuperuser) if si.isCrossref and not si.isReserved and updateExternalServices: si.crossrefStatus = ezidapp.models.StoreIdentifier.CR_WORKING si.crossrefMessage = "" if "_updated" not in metadata: si.updateTime = "" si.my_full_clean() if si.owner != previousOwner: if not policy.authorizeOwnershipChange(user, previousOwner, si.owner): log.badRequest(tid) return "error: bad request - ownership change prohibited" with django.db.transaction.atomic(): si.save() ezidapp.models.update_queue.enqueue(si, "update", updateExternalServices) except ezidapp.models.StoreIdentifier.DoesNotExist: log.badRequest(tid) return "error: bad request - no such identifier" except django.core.exceptions.ValidationError, e: log.badRequest(tid) return "error: bad request - " + util.formatValidationError(e)
def createIdentifier(identifier, user, metadata={}, updateIfExists=False): """ Creates an identifier having the given qualified name, e.g., "doi:10.5060/FOO". 'user' is the requestor and should be an authenticated StoreUser object. 'metadata' should be a dictionary of element (name, value) pairs. If an initial target URL is not supplied, the identifier is given a self-referential target URL. The successful return is a string that includes the canonical, qualified form of the new identifier, as in: success: ark:/95060/foo For DOI identifiers, the string also includes the qualified shadow ARK, as in: success: doi:10.5060/FOO | ark:/b5060/foo Unsuccessful returns include the strings: error: forbidden error: bad request - subreason... error: internal server error error: concurrency limit exceeded If 'updateIfExists' is true, an "identifier already exists" error falls through to a 'setMetadata' call. """ nqidentifier = util.normalizeIdentifier(identifier) if nqidentifier == None: return "error: bad request - invalid identifier" tid = uuid.uuid1() if not _acquireIdentifierLock(nqidentifier, user.username): return "error: concurrency limit exceeded" try: log.begin(tid, "createIdentifier", nqidentifier, user.username, user.pid, user.group.groupname, user.group.pid, *[a for p in metadata.items() for a in p]) if not policy.authorizeCreate(user, nqidentifier): log.forbidden(tid) return "error: forbidden" si = ezidapp.models.StoreIdentifier( identifier=nqidentifier, owner=(None if user == ezidapp.models.AnonymousUser else user)) si.updateFromUntrustedLegacy(metadata, allowRestrictedSettings=user.isSuperuser) if si.isDoi: s = ezidapp.models.getLongestShoulderMatch(si.identifier) # Should never happen. assert s != None, "no matching shoulder found" if s.isDatacite: if si.datacenter == None: si.datacenter = s.datacenter elif s.isCrossref: if not si.isCrossref: if si.isReserved: si.crossrefStatus = ezidapp.models.StoreIdentifier.CR_RESERVED else: si.crossrefStatus = ezidapp.models.StoreIdentifier.CR_WORKING else: assert False, "unhandled case" si.my_full_clean() if si.owner != user: if not policy.authorizeOwnershipChange(user, user, si.owner): log.badRequest(tid) return "error: bad request - ownership change prohibited" with django.db.transaction.atomic(): si.save() ezidapp.models.update_queue.enqueue(si, "create") except django.core.exceptions.ValidationError, e: log.badRequest(tid) return "error: bad request - " + util.formatValidationError(e)