def direct_ccz(request, domain): """ You must specify an app_id, and you may specify either 'version' or 'latest' latest can be one of: release: Latest starred version build: Latest version regardless of star save: Latest saved version of the application (even without a build) If 'version' and 'latest' aren't specified it will default to latest save You may also set 'include_multimedia=true' if you need multimedia. """ def error(msg, code=400): return JsonResponse({'status': 'error', 'message': msg}, status=code) def get_app(app_id, version, latest): if version: return get_build_doc_by_version(domain, app_id, version) elif latest == 'build': return get_latest_build_doc(domain, app_id) elif latest == 'release': return get_latest_released_app_doc(domain, app_id) else: # either latest=='save' or they didn't specify return get_current_app(domain, app_id) app_id = request.GET.get('app_id', None) version = request.GET.get('version', None) latest = request.GET.get('latest', None) include_multimedia = request.GET.get('include_multimedia', 'false').lower() == 'true' # Make sure URL params make sense if not app_id: return error("You must specify `app_id` in your GET parameters") if version and latest: return error("You can't specify both 'version' and 'latest'") if latest not in ( None, 'release', 'build', 'save', ): return error("latest must be either 'release', 'build', or 'save'") if version: try: version = int(version) except ValueError: return error("'version' must be an integer") try: app = get_app(app_id, version, latest) if not app: raise ResourceNotFound() app = app if isinstance(app, Document) else wrap_app(app) except (ResourceNotFound, DocTypeError): return error("Application not found", code=404) lang, langs = get_langs(request, app) with report_build_time(domain, app._id, 'live_preview'): return get_direct_ccz(domain, app, langs, version, include_multimedia)
def fetch_attachment(self, name, stream=False): """Get named attachment :param stream: When true, return a file-like object that can be read at least once (streamers should not expect to seek within or read the contents of the returned file more than once). """ db = get_blob_db() try: try: key = self.external_blobs[name].key except KeyError: if self._migrating_blobs_from_couch: return super(BlobMixin, self) \ .fetch_attachment(name, stream=stream) raise NotFound(name) blob = db.get(key=key) except NotFound: raise ResourceNotFound( "{model} {model_id} attachment: {name!r}".format( model=type(self).__name__, model_id=self._id, name=name, )) if stream: return blob with blob: return blob.read()
def get_cloudcare_app(domain, app_name): apps = get_cloudcare_apps(domain) app = filter(lambda x: x['name'] == app_name, apps) if app: return look_up_app_json(domain, app[0]['_id']) else: raise ResourceNotFound(_("Not found application by name: %s") % app_name)
def fetch_attachment(self, name, stream=False): """Get named attachment :param stream: When true, return a file-like object that can be read at least once (streamers should not expect to seek within or read the contents of the returned file more than once). """ db = get_blob_db() try: try: meta = self.external_blobs[name] except KeyError: if self.migrating_blobs_from_couch: return super(BlobMixin, self) \ .fetch_attachment(name, stream=stream) raise NotFound blob = db.get(meta.id, self._blobdb_bucket()) except NotFound: raise ResourceNotFound(u"{model} attachment: {name!r}".format( model=type(self).__name__, name=name)) if stream: return blob with blob: body = blob.read() try: body = body.decode("utf-8", "strict") except UnicodeDecodeError: # Return bytes on decode failure, otherwise unicode. # Ugly, but consistent with restkit.wrappers.Response.body_string pass return body
def get_cloudcare_app(domain, app_name): apps = get_cloudcare_apps(domain) app = [x for x in apps if x['name'] == app_name] if app: return look_up_app_json(domain, app[0]['_id']) else: raise ResourceNotFound(_("Not found application by name: %s") % app_name)
def get(self, group_id): if group_id not in self.groups_by_id: group = Group.get(group_id) if group.domain != self.domain: raise ResourceNotFound() self.add_group(group) return self.groups_by_id[group_id]
def get_lite(cls, id): results = cls.get_db().view("case/get_lite", key=id, include_docs=False).one() if results is None: raise ResourceNotFound('no case with id %s exists' % id) return cls.wrap(results['value'])
def wrap(cls, data): if cls.__name__ == Repeater.__name__: cls_ = cls.get_class_from_doc_type(data['doc_type']) if cls_: return cls_.wrap(data) else: raise ResourceNotFound('Unknown repeater type: %s' % data) else: return super(Repeater, cls).wrap(data)
def get_lite(cls, id, wrap=True): from corehq.apps.hqcase.dbaccessors import get_lite_case_json results = get_lite_case_json(id) if results is None: raise ResourceNotFound('no case with id %s exists' % id) if wrap: return cls.wrap(results['value']) else: return results['value']
def wrap(cls, data): doc_type = data['doc_type'].replace(DELETED, '') if cls.__name__ == Repeater.__name__: if doc_type in repeater_types: return repeater_types[doc_type].wrap(data) else: raise ResourceNotFound('Unknown repeater type: %s', data) else: return super(Repeater, cls).wrap(data)
def put_attachment(self, content, name=None, content_type=None, content_length=None, domain=None, type_code=None): """Put attachment in blob database See `get_short_identifier()` for restrictions on the upper bound for number of attachments per object. :param content: String or file object. """ db = get_blob_db() if name is None: name = getattr(content, "name", None) if name is None: raise InvalidAttachment("cannot save attachment without name") if self._id is None: raise ResourceNotFound("cannot put attachment on unidentified document") if hasattr(self, "domain"): if domain is not None and self.domain != domain: raise ValueError("domain mismatch: %s != %s" % (self.domain, domain)) domain = self.domain elif domain is None: raise ValueError("domain attribute or argument is required") old_meta = self.blobs.get(name) if isinstance(content, str): content = BytesIO(content.encode("utf-8")) elif isinstance(content, bytes): content = BytesIO(content) # do we need to worry about BlobDB reading beyond content_length? meta = db.put( content, domain=domain or self.domain, parent_id=self._id, name=name, type_code=(self._blobdb_type_code if type_code is None else type_code), content_type=content_type, ) self.external_blobs[name] = BlobMetaRef( key=meta.key, blobmeta_id=meta.id, content_type=content_type, content_length=meta.content_length, ) if self._migrating_blobs_from_couch and self._attachments: self._attachments.pop(name, None) if self._atomic_blobs is None: self.save() if old_meta and old_meta.key: db.delete(key=old_meta.key) elif old_meta and old_meta.key: self._atomic_blobs[name].append(old_meta.key) return True
def wrap(self, data): if 'is_sensitive' not in data and data.get('transform', None): data['is_sensitive'] = True if 'doc_type' in data and \ self.__name__ == ExportColumn.__name__ and \ self.__name__ != data['doc_type']: if data['doc_type'] in column_types: return column_types[data['doc_type']].wrap(data) else: raise ResourceNotFound('Unknown column type: %s', data) else: return super(ExportColumn, self).wrap(data)
def fetch_attachment(self, name, stream=False): if self._deferred_blobs and name in self._deferred_blobs: if self._deferred_blobs[name] is None: raise ResourceNotFound( "{model} {model_id} attachment: {name!r}".format( model=type(self).__name__, model_id=self._id, name=name, )) body = self._deferred_blobs[name]["content"] if stream: return ClosingContextProxy(BytesIO(body)) return body return super(DeferredBlobMixin, self).fetch_attachment(name, stream)
def get_with_attachments(form_id): doc = XFormInstance.get_db().get(form_id) doc = doc_types()[doc['doc_type']].wrap(doc) if doc.external_blobs: for name, meta in doc.external_blobs.items(): with doc.fetch_attachment(name, stream=True) as content: doc.deferred_put_attachment( content, name, content_type=meta.content_type, content_length=meta.content_length, ) else: # xforms are expected to at least have the XML attachment raise ResourceNotFound("XForm attachment missing: {}".format(form_id)) return doc
def fetch_attachment(self, name, stream=False): if self._deferred_blobs and name in self._deferred_blobs: if self._deferred_blobs[name] is None: raise ResourceNotFound( u"{model} {model_id} attachment: {name!r}".format( model=type(self).__name__, model_id=self._id, name=name, )) body = self._deferred_blobs[name]["content"] if stream: return ClosingContextProxy(StringIO(body)) try: body = body.decode("utf-8", "strict") except UnicodeDecodeError: # Return bytes on decode failure, otherwise unicode. # Ugly, but consistent with restkit.wrappers.Response.body_string pass return body return super(DeferredBlobMixin, self).fetch_attachment(name, stream)
def direct_ccz(request, domain): """ You must specify an app_id, and you may specify either 'version' or 'latest' latest can be one of: release: Latest starred version build: Latest version regardless of star save: Latest saved version of the application (even without a build) If 'version' and 'latest' aren't specified it will default to latest save You may also set 'include_multimedia=true' if you need multimedia. """ def error(msg, code=400): return json_response({ 'status': 'error', 'message': msg }, status_code=code) def get_app(app_id, version, latest): if version: return get_build_doc_by_version(domain, app_id, version) elif latest == 'build': return get_latest_build_doc(domain, app_id) elif latest == 'release': return get_latest_released_app_doc(domain, app_id) else: # either latest=='save' or they didn't specify return get_current_app(domain, app_id) app_id = request.GET.get('app_id', None) version = request.GET.get('version', None) latest = request.GET.get('latest', None) include_multimedia = request.GET.get('include_multimedia', 'false').lower() == 'true' # Make sure URL params make sense if not app_id: return error("You must specify `app_id` in your GET parameters") if version and latest: return error("You can't specify both 'version' and 'latest'") if latest not in ( None, 'release', 'build', 'save', ): return error("latest must be either 'release', 'build', or 'save'") if version: try: version = int(version) except ValueError: return error("'version' must be an integer") try: app = get_app(app_id, version, latest) if not app: raise ResourceNotFound() app = app if isinstance(app, Document) else wrap_app(app) except (ResourceNotFound, DocTypeError): return error("Application not found", code=404) if not app.copy_of: errors = app.validate_app() else: errors = None if errors: lang, langs = get_langs(request, app) error_html = render_to_string( "app_manager/partials/build_errors.html", { 'request': request, 'app': app, 'build_errors': errors, 'domain': domain, 'langs': langs, 'lang': lang }) return json_response( {'error_html': error_html}, status_code=400, ) app.set_media_versions(None) download = FileDownload('application-{}-{}'.format(app_id, version)) errors = build_application_zip( include_multimedia_files=include_multimedia, include_index_files=True, app=app, download_id=download.download_id, compress_zip=True, filename='{}.ccz'.format(slugify(app.name)), ) if errors is not None and errors['errors']: return json_response( errors, status_code=400, ) return FileDownload.get(download.download_id).toHttpResponse()
def get_current_app_doc(domain, app_id): from .models import Application app = Application.get_db().get(app_id) if app.get('domain', None) != domain: raise ResourceNotFound() return app
def _blobdb_bucket(self): if self._id is None: raise ResourceNotFound( "cannot manipulate attachment on unidentified document") return join(_get_couchdb_name(type(self)), safe_id(self._id))