def get_zip(request, hashtag, filename): """ Download zip (it has to be ready) """ if not validator.is_valid("alphanum", hashtag): log.warning("[security] Wrong hashtag provided") return HttpResponseForbidden("{'error': 'Wrong hashtag'}") path = os.path.join(settings.XPI_TARGETDIR, "%s.zip" % hashtag) log.info("[zip:%s] Downloading Addon from %s" % (filename, path)) tend = time.time() tkey = _get_zip_cache_key(request, hashtag) tqueued = cache.get(tkey) if tqueued: ttotal = (tend - tqueued) * 1000 statsd.timing("zip.total", ttotal) total = "%dms" % ttotal else: total = "n/a" log.info("[zip:%s] Downloading Add-on (%s)" % (hashtag, total)) response = serve(request, path, "/", show_indexes=False) response["Content-Disposition"] = "attachment; " 'filename="%s.zip"' % filename return response
def prepare_test(r, id_number, revision_number=None): """ Test XPI from data saved in the database """ revision = get_object_with_related_or_404(PackageRevision, package__id_number=id_number, package__type='a', revision_number=revision_number) hashtag = r.POST.get('hashtag') if not hashtag: log.warning('[security] No hashtag provided') return HttpResponseForbidden('{"error": "No hashtag"}') if not validator.is_valid('alphanum', hashtag): log.warning('[security] Wrong hashtag provided') return HttpResponseForbidden("{'error': 'Wrong hashtag'}") # prepare codes to be sent to the task mod_codes = {} att_codes = {} if r.POST.get('live_data_testing', False): for mod in revision.modules.all(): if r.POST.get(mod.filename, False): code = r.POST.get(mod.filename, '') if mod.code != code: mod_codes[str(mod.pk)] = code for att in revision.attachments.all(): if r.POST.get(str(att.pk), False): code = r.POST.get(str(att.pk)) att_codes[str(att.pk)] = code tasks.xpi_build_from_model.delay(revision.pk, mod_codes=mod_codes, att_codes=att_codes, hashtag=hashtag) return HttpResponse('{"delayed": true}')
def prepare_test(r, id_number, revision_number=None): """ Test XPI from data saved in the database """ revision = get_object_with_related_or_404( PackageRevision, package__id_number=id_number, package__type="a", revision_number=revision_number ) hashtag = r.POST.get("hashtag") if not hashtag: log.warning("[security] No hashtag provided") return HttpResponseForbidden('{"error": "No hashtag"}') if not validator.is_valid("alphanum", hashtag): log.warning("[security] Wrong hashtag provided") return HttpResponseForbidden("{'error': 'Wrong hashtag'}") if r.POST.get("live_data_testing", False): modules = [] for mod in revision.modules.all(): if r.POST.get(mod.filename, False): code = r.POST.get(mod.filename, "") if mod.code != code: mod.code = code modules.append(mod) attachments = [] for att in revision.attachments.all(): if r.POST.get(str(att.pk), False): code = r.POST.get(str(att.pk)) att.code = code attachments.append(att) response, rm_xpi_url = revision.build_xpi(modules, attachments, hashtag=hashtag) else: response, rm_xpi_url = revision.build_xpi(hashtag=hashtag) return HttpResponse('{"delayed": true, "rm_xpi_url": "%s"}' % rm_xpi_url)
def remove_xpi(r, sdk_name): " remove whole temporary SDK on request " # Validate sdk_name if not validator.is_valid("alphanum_plus", sdk_name): return HttpResponseForbidden("{'error': 'Wrong name'}") xpi_remove("%s-%s" % (settings.SDKDIR_PREFIX, sdk_name)) return HttpResponse("{}", mimetype="application/json")
def _get_package_overrides(container, sdk_version=None): """ Prepare package overrides (from POST) sdk_version is used to override the version if {sdk_version} provided in optional container['version'] :attr: container (dict) list of overrides :attr: sdk_version (string) """ version = container.get('version', None) if version and sdk_version: version = version.format(sdk_version=sdk_version) package_overrides = { 'version': version, 'type': container.get('type', None), 'fullName': container.get('fullName', None), 'url': container.get('url', None), 'description': container.get('description', None), 'author': container.get('author', None), 'license': container.get('license', None), 'lib': container.get('lib', None), 'data': container.get('data', None), 'tests': container.get('tests', None), 'main': container.get('main', None) } if version and not validator.is_valid('alphanum_plus', version): log.error("Wrong version format provided (%s)" % version) raise BadManifestFieldException("Wrong version format") return package_overrides
def prepare_zip(request, revision_id): """ Prepare download zip This package is built asynchronously and we assume it works. It will be downloaded in %``get_zip`` """ revision = get_object_with_related_or_404(PackageRevision, pk=revision_id) if not revision.package.active and request.user != revision.package.author: # pretend package doesn't exist as it's private raise Http404() hashtag = request.POST.get("hashtag") if not hashtag: return HttpResponseForbidden( "Add-on Builder has been updated!" "We have updated this part of the application. Please " "empty your cache and reload to get changes." ) if not validator.is_valid("alphanum", hashtag): log.warning("[security] Wrong hashtag provided") return HttpResponseBadRequest("{'error': 'Wrong hashtag'}") log.info("[zip:%s] Addon added to queue" % hashtag) # caching tqueued = time.time() tkey = _get_zip_cache_key(request, hashtag) cache.set(tkey, tqueued, 120) # create zip file zip_source(pk=revision.pk, hashtag=hashtag, tqueued=tqueued) return HttpResponse('{"delayed": true}')
def get_zip(request, hashtag, filename): """ Download zip (it has to be ready) """ if not validator.is_valid('alphanum', hashtag): log.warning('[security] Wrong hashtag provided') return HttpResponseForbidden("{'error': 'Wrong hashtag'}") path = os.path.join(settings.XPI_TARGETDIR, '%s.zip' % hashtag) log.info('[zip:%s] Downloading Addon from %s' % (filename, path)) tend = time.time() tkey = _get_zip_cache_key(request, hashtag) tqueued = cache.get(tkey) if tqueued: ttotal = (tend - tqueued) * 1000 statsd.timing('zip.total', ttotal) total = '%dms' % ttotal else: total = 'n/a' log.info('[zip:%s] Downloading Add-on (%s)' % (hashtag, total)) response = serve(request, path, '/', show_indexes=False) response['Content-Disposition'] = ('attachment; ' 'filename="%s.zip"' % filename) return response
def get_download(r, hashtag, filename): """ Download XPI (it has to be ready) """ if not validator.is_valid('alphanum', hashtag): log.warning('[security] Wrong hashtag provided') return HttpResponseForbidden("{'error': 'Wrong hashtag'}") path = os.path.join(settings.XPI_TARGETDIR, '%s.xpi' % hashtag) log.info('[xpi:%s] Downloading Addon from %s' % (filename, path)) tend = time.time() tkey = xpi_utils.get_queued_cache_key(hashtag, r) tqueued = cache.get(tkey) if tqueued: ttotal = (tend - tqueued) * 1000 statsd.timing('xpi.build.total', ttotal) total = '%dms' % ttotal else: total = 'n/a' log.info('[xpi:%s] Downloading Add-on (%s)' % (hashtag, total)) response = serve(r, path, '/', show_indexes=False) response['Content-Disposition'] = ('attachment; ' 'filename="%s.xpi"' % filename) return response
def prepare_zip(request, revision_id): """ Prepare download zip This package is built asynchronously and we assume it works. It will be downloaded in %``get_zip`` """ revision = get_object_with_related_or_404(PackageRevision, pk=revision_id) if (not revision.package.active and request.user != revision.package.author): # pretend package doesn't exist as it's private raise Http404() hashtag = request.POST.get('hashtag') if not hashtag: return HttpResponseForbidden( 'Add-on Builder has been updated!' 'We have updated this part of the application. Please ' 'empty your cache and reload to get changes.') if not validator.is_valid('alphanum', hashtag): log.warning('[security] Wrong hashtag provided') return HttpResponseBadRequest("{'error': 'Wrong hashtag'}") log.info('[zip:%s] Addon added to queue' % hashtag) # caching tqueued = time.time() tkey = _get_zip_cache_key(request, hashtag) cache.set(tkey, tqueued, 120) # create zip file zip_source(pk=revision.pk, hashtag=hashtag, tqueued=tqueued) return HttpResponse('{"delayed": true}')
def prepare_test(r, revision_id): """ Test XPI from data saved in the database """ revision = _get_addon(r.user, revision_id) hashtag = r.POST.get('hashtag') if not hashtag: log.warning('[security] No hashtag provided') return HttpResponseBadRequest('{"error": "No hashtag"}') if not validator.is_valid('alphanum', hashtag): log.warning('[security] Wrong hashtag provided') return HttpResponseBadRequest("{'error': 'Wrong hashtag'}") # prepare codes to be sent to the task mod_codes = {} att_codes = {} if r.POST.get('live_data_testing', False): for mod in revision.modules.all(): if r.POST.get(mod.filename, False): code = r.POST.get(mod.filename, '') if mod.code != code: mod_codes[str(mod.pk)] = code for att in revision.attachments.all(): if r.POST.get(str(att.pk), False): code = r.POST.get(str(att.pk)) att_codes[str(att.pk)] = code if mod_codes or att_codes or not os.path.exists('%s.xpi' % os.path.join(settings.XPI_TARGETDIR, hashtag)): log.info('[xpi:%s] Addon added to queue' % hashtag) tqueued = time.time() tkey = xpi_utils.get_queued_cache_key(hashtag, r) cache.set(tkey, tqueued, 120) tasks.xpi_build_task(rev_pk=revision.pk, mod_codes=mod_codes, att_codes=att_codes, hashtag=hashtag, tqueued=tqueued) return HttpResponse('{"delayed": true}')
def clean(r, path): " remove whole temporary SDK on request " # Validate sdk_name if not validator.is_valid('alphanum', path): log.warning('[security] Wrong hashtag provided') return HttpResponseForbidden("{'error': 'Wrong hashtag'}") xpi_utils.remove(os.path.join(settings.XPI_TARGETDIR, '%s.xpi' % path)) return HttpResponse('{"success": true}', mimetype='application/json')
def check_zip(r, hashtag): """Check if zip file is prepared.""" if not validator.is_valid("alphanum", hashtag): log.warning("[security] Wrong hashtag provided") return HttpResponseForbidden("{'error': 'Wrong hashtag'}") path = os.path.join(settings.XPI_TARGETDIR, "%s.zip" % hashtag) # Check file if it exists if os.path.isfile(path): return HttpResponse('{"ready": true}') return HttpResponse('{"ready": false}')
def check_zip(r, hashtag): """Check if zip file is prepared.""" if not validator.is_valid('alphanum', hashtag): log.warning('[security] Wrong hashtag provided') return HttpResponseForbidden("{'error': 'Wrong hashtag'}") path = os.path.join(settings.XPI_TARGETDIR, '%s.zip' % hashtag) # Check file if it exists if os.path.isfile(path): return HttpResponse('{"ready": true}') return HttpResponse('{"ready": false}')
def check_download(r, hashtag): """Check if XPI file is prepared.""" if not validator.is_valid('alphanum', hashtag): log.warning('[security] Wrong hashtag provided') return HttpResponseForbidden("{'error': 'Wrong hashtag'}") path = os.path.join(settings.XPI_TARGETDIR, '%s.xpi' % hashtag) # Check file if it exists if os.path.isfile(path): return HttpResponse('{"ready": true}') return HttpResponse('{"ready": false}')
def get_download(r, hashtag, filename): """ Download XPI (it has to be ready) """ if not validator.is_valid("alphanum", hashtag): log.warning("[security] Wrong hashtag provided") return HttpResponseForbidden("{'error': 'Wrong hashtag'}") path = os.path.join(settings.XPI_TARGETDIR, "%s.xpi" % hashtag) log.info("Downloading %s.xpi from %s" % (filename, path)) response = serve(r, path, "/", show_indexes=False) response["Content-Disposition"] = "attachment; " 'filename="%s.xpi"' % filename return response
def get_download(r, hashtag, filename): """ Download XPI (it has to be ready) """ if not validator.is_valid('alphanum', hashtag): log.warning('[security] Wrong hashtag provided') return HttpResponseForbidden("{'error': 'Wrong hashtag'}") path = os.path.join(settings.XPI_TARGETDIR, '%s.xpi' % hashtag) log.info('Downloading %s.xpi from %s' % (filename, path)) response = serve(r, path, '/', show_indexes=False) response['Content-Disposition'] = ('attachment; ' 'filename="%s.xpi"' % filename) return response
def get_test(r, hashtag): """ return XPI file for testing """ if not validator.is_valid('alphanum', hashtag): log.warning('[security] Wrong hashtag provided') return HttpResponseForbidden("{'error': 'Wrong hashtag'}") path = os.path.join(settings.XPI_TARGETDIR, '%s.xpi' % hashtag) mimetype = 'text/plain; charset=x-user-defined' try: xpi = codecs.open(path, mode='rb').read() except Exception, err: log.debug('Add-on not yet created: %s' % str(err)) return HttpResponse('')
def prepare_download(r, id_number, revision_number=None): """ Prepare download XPI. This package is built asynchronously and we assume it works. It will be downloaded in ``get_download`` """ revision = get_object_with_related_or_404(PackageRevision, package__id_number=id_number, package__type='a', revision_number=revision_number) hashtag = r.POST.get('hashtag') if not hashtag: return HttpResponseForbidden('Add-on Builder has been updated!' 'We have updated this part of the application. Please ' 'empty your cache and reload to get changes.') if not validator.is_valid('alphanum', hashtag): log.warning('[security] Wrong hashtag provided') return HttpResponseForbidden("{'error': 'Wrong hashtag'}") tasks.xpi_build_from_model.delay(revision.pk, hashtag=hashtag) return HttpResponse('{"delayed": true}')
def prepare_download(r, id_number, revision_number=None): """ Prepare download XPI. This package is built asynchronously and we assume it works. It will be downloaded in ``get_download`` """ revision = get_object_with_related_or_404( PackageRevision, package__id_number=id_number, package__type="a", revision_number=revision_number ) hashtag = r.POST.get("hashtag") if not hashtag: return HttpResponseForbidden( "Add-on Builder has been updated!" "We have updated this part of the pplication, please " "empty your cache and reload to get changes." ) if not validator.is_valid("alphanum", hashtag): log.warning("[security] Wrong hashtag provided") return HttpResponseForbidden("{'error': 'Wrong hashtag'}") revision.build_xpi(hashtag=hashtag) return HttpResponse('{"delayed": true}')
def prepare_download(r, revision_id): """ Prepare download XPI. This package is built asynchronously and we assume it works. It will be downloaded in %``get_download`` """ revision = _get_addon(r.user, revision_id) hashtag = r.POST.get('hashtag') if not hashtag: return HttpResponseForbidden( 'Add-on Builder has been updated!' 'We have updated this part of the application. Please ' 'empty your cache and reload to get changes.') if not validator.is_valid('alphanum', hashtag): log.warning('[security] Wrong hashtag provided') return HttpResponseBadRequest("{'error': 'Wrong hashtag'}") log.info('[xpi:%s] Addon added to queue' % hashtag) tqueued = time.time() tkey = xpi_utils.get_queued_cache_key(hashtag, r) cache.set(tkey, tqueued, 120) tasks.xpi_build_task(rev_pk=revision.pk, hashtag=hashtag, tqueued=tqueued) return HttpResponse('{"delayed": true}')
def prepare_download(r, revision_id): """ Prepare download XPI. This package is built asynchronously and we assume it works. It will be downloaded in %``get_download`` """ revision = _get_addon(r.user, revision_id) hashtag = r.POST.get('hashtag') if not hashtag: return HttpResponseForbidden('Add-on Builder has been updated!' 'We have updated this part of the application. Please ' 'empty your cache and reload to get changes.') if not validator.is_valid('alphanum', hashtag): log.warning('[security] Wrong hashtag provided') return HttpResponseBadRequest("{'error': 'Wrong hashtag'}") log.info('[xpi:%s] Addon added to queue' % hashtag) tqueued = time.time() tkey = xpi_utils.get_queued_cache_key(hashtag, r) cache.set(tkey, tqueued, 120) tasks.xpi_build_task(rev_pk=revision.pk, hashtag=hashtag, tqueued=tqueued) return HttpResponse('{"delayed": true}')
def _get_package_overrides(container, sdk_version=None): version = container.get('version', None) if version and sdk_version: version = version.format(sdk_version=sdk_version) package_overrides = { 'version': version, 'type': container.get('type', None), 'fullName': container.get('fullName', None), 'url': container.get('url', None), 'description': container.get('description', None), 'author': container.get('author', None), 'license': container.get('license', None), 'lib': container.get('lib', None), 'data': container.get('data', None), 'tests': container.get('tests', None), 'main': container.get('main', None) } if version and not validator.is_valid('alphanum_plus', version): log.error("Wrong version format provided (%s)" % version) raise BadManifestFieldException("Wrong version format") return package_overrides
def get_test(r, hashtag): """ return XPI file for testing """ if not validator.is_valid('alphanum', hashtag): log.warning('[security] Wrong hashtag provided') return HttpResponseForbidden("{'error': 'Wrong hashtag'}") base = os.path.join(settings.XPI_TARGETDIR, hashtag) mimetype = 'text/plain; charset=x-user-defined' tfile = time.time() try: xpi = codecs.open('%s.xpi' % base, mode='rb').read() except Exception, err: if os.path.exists('%s.json' % base): with open('%s.json' % base) as error_file: error_json = simplejson.loads(error_file.read()) os.remove('%s.json' % base) if error_json['status'] == 'error': log.warning('Error creating xpi (%s)' % error_json['message']) return HttpResponseNotFound(error_json['message']) log.debug('[xpi:%s] Add-on not yet created: %s' % (hashtag, str(err))) return HttpResponse('')
def prepare_test(r, revision_id): """ Test XPI from data saved in the database """ revision = _get_addon(r.user, revision_id) hashtag = r.POST.get('hashtag') if not hashtag: log.warning('[security] No hashtag provided') return HttpResponseBadRequest('{"error": "No hashtag"}') if not validator.is_valid('alphanum', hashtag): log.warning('[security] Wrong hashtag provided') return HttpResponseBadRequest("{'error': 'Wrong hashtag'}") # prepare codes to be sent to the task mod_codes = {} att_codes = {} if r.POST.get('live_data_testing', False): for mod in revision.modules.all(): if r.POST.get(mod.filename, False): code = r.POST.get(mod.filename, '') if mod.code != code: mod_codes[str(mod.pk)] = code for att in revision.attachments.all(): if r.POST.get(str(att.pk), False): code = r.POST.get(str(att.pk)) att_codes[str(att.pk)] = code if mod_codes or att_codes or not os.path.exists( '%s.xpi' % os.path.join(settings.XPI_TARGETDIR, hashtag)): log.info('[xpi:%s] Addon added to queue' % hashtag) tqueued = time.time() tkey = xpi_utils.get_queued_cache_key(hashtag, r) cache.set(tkey, tqueued, 120) tasks.xpi_build_task(rev_pk=revision.pk, mod_codes=mod_codes, att_codes=att_codes, hashtag=hashtag, tqueued=tqueued) return HttpResponse('{"delayed": true}')
def get_test(r, hashtag): """ return XPI file for testing """ if not validator.is_valid('alphanum', hashtag): log.warning('[security] Wrong hashtag provided') return HttpResponseForbidden("{'error': 'Wrong hashtag'}") base = os.path.join(settings.XPI_TARGETDIR, hashtag) mimetype = 'text/plain; charset=x-user-defined' tfile = time.time() try: xpi = codecs.open('%s.xpi' % base, mode='rb').read() except Exception, err: if os.path.exists('%s.json' % base): with open('%s.json' % base) as error_file: error_json = simplejson.loads(error_file.read()) os.remove('%s.json' % base) if error_json['status'] == 'error': log.warning('Error creating xpi (%s)' % error_json['message'] ) return HttpResponseNotFound(error_json['message']) log.debug('[xpi:%s] Add-on not yet created: %s' % (hashtag, str(err))) return HttpResponse('')
def save(request, revision_id, type_id=None): """ Save package and modules @TODO: check how dynamic module loading affects save """ revision = get_object_with_related_or_404(PackageRevision, pk=revision_id) if request.user.pk != revision.author.pk: log_msg = ("[security] Attempt to save package (%s) by " "non-owner (%s)" % (revision.pk, request.user)) log.warning(log_msg) return HttpResponseForbidden('You are not the author of this Package') save_revision = False save_package = False start_version_name = revision.version_name start_revision_message = revision.message response_data = {} package_full_name = request.POST.get('full_name', False) jid = request.POST.get('jid', None) version_name = request.POST.get('version_name', False) if jid and not validator.is_valid( 'alphanum_plus', jid): return HttpResponseForbidden(escape( validator.get_validation_message('alphanum_plus'))) # validate package_full_name and version_name if version_name and not validator.is_valid( 'alphanum_plus', version_name): return HttpResponseForbidden(escape( validator.get_validation_message('alphanum_plus'))) # here we're checking if the *current* full_name is different than the # revision's full_name if package_full_name and package_full_name != revision.package.full_name: try: revision.set_full_name(package_full_name) except ValidationError: return HttpResponseForbidden(escape( validator.get_validation_message('alphanum_plus_space'))) except IntegrityError: return HttpResponseForbidden( 'You already have a %s with that name' % escape( revision.package.get_type_name()) ) else: save_package = True save_revision = True response_data['full_name'] = package_full_name package_description = request.POST.get('package_description', False) if package_description: save_package = True revision.package.description = package_description response_data['package_description'] = package_description extra_json = request.POST.get('package_extra_json') if extra_json is not None: # None means it wasn't submitted. We want to accept blank strings. save_revision = True try: revision.set_extra_json(extra_json, save=False) except JSONDecodeError: return HttpResponseBadRequest( 'Extra package properties were invalid JSON.') except IllegalFilenameException, e: return HttpResponseBadRequest(str(e)) response_data['package_extra_json'] = extra_json
def test_cached_hashtag(self): assert validator.is_valid('alphanum', self.addon.latest.get_cache_hashtag())
def package_save(r, id_number, type_id, revision_number=None, version_name=None): """ Save package and modules @TODO: check how dynamic module loading affects save """ revision = get_package_revision(id_number, type_id, revision_number, version_name) if r.user.pk != revision.author.pk: log_msg = ("[security] Attempt to save package (%s) by " "non-owner (%s)" % (id_number, r.user)) log.warning(log_msg) return HttpResponseForbidden('You are not the author of this Package') save_revision = False save_package = False start_version_name = revision.version_name start_revision_message = revision.message response_data = {} package_full_name = r.POST.get('full_name', False) version_name = r.POST.get('version_name', False) # validate package_full_name and version_name if package_full_name and not validator.is_valid( 'alphanum_plus_space', package_full_name): return HttpResponseNotAllowed(escape( validator.get_validation_message('alphanum_plus_space'))) if version_name and not validator.is_valid( 'alphanum_plus', version_name): return HttpResponseNotAllowed(escape( validator.get_validation_message('alphanum_plus'))) if package_full_name and package_full_name != revision.package.full_name: revision.package.full_name = package_full_name # in FlightDeck, libraries can have the same name, by different authors try: Package.objects.get(author=revision.package.author, name=revision.package.make_name()) return HttpResponseForbidden( 'You already have a %s with that name' % escape( revision.package.get_type_name()) ) except Package.DoesNotExist: save_package = True response_data['full_name'] = package_full_name package_description = r.POST.get('package_description', False) if package_description: save_package = True revision.package.description = package_description response_data['package_description'] = package_description changes = [] for mod in revision.modules.all(): if r.POST.get(mod.filename, False): code = r.POST[mod.filename] if mod.code != code: mod.code = code changes.append(mod) for att in revision.attachments.all(): uid = str(att.pk) if r.POST.get(uid): att.data = r.POST[uid] if att.changed(): changes.append(att) attachments_changed = {} if save_revision or changes: revision.save() if changes: attachments_changed = simplejson.dumps( revision.updates(changes, save=False)) revision_message = r.POST.get('revision_message', False) if revision_message and revision_message != start_revision_message: revision.message = revision_message # save revision message without changeing the revision super(PackageRevision, revision).save() response_data['revision_message'] = revision_message if version_name and version_name != start_version_name \ and version_name != revision.package.version_name: save_package = False try: revision.set_version(version_name) except Exception, err: return HttpResponseForbidden(escape(err.__str__()))
def save(request, id_number, type_id, revision_number=None, version_name=None): """ Save package and modules @TODO: check how dynamic module loading affects save """ revision = get_package_revision(id_number, type_id, revision_number, version_name) if request.user.pk != revision.author.pk: log_msg = ("[security] Attempt to save package (%s) by " "non-owner (%s)" % (id_number, request.user)) log.warning(log_msg) return HttpResponseForbidden('You are not the author of this Package') save_revision = False save_package = False start_version_name = revision.version_name start_revision_message = revision.message response_data = {} package_full_name = request.POST.get('full_name', False) version_name = request.POST.get('version_name', False) # validate package_full_name and version_name if version_name and not validator.is_valid( 'alphanum_plus', version_name): return HttpResponseNotAllowed(escape( validator.get_validation_message('alphanum_plus'))) # here we're checking if the *current* full_name is different than the # revision's full_name if package_full_name and package_full_name != revision.package.full_name: try: revision.set_full_name(package_full_name) except ValidationError: return HttpResponseNotAllowed(escape( validator.get_validation_message('alphanum_plus_space'))) except IntegrityError: return HttpResponseForbidden( 'You already have a %s with that name' % escape( revision.package.get_type_name()) ) else: save_package = True save_revision = True response_data['full_name'] = package_full_name package_description = request.POST.get('package_description', False) if package_description: save_package = True revision.package.description = package_description response_data['package_description'] = package_description changes = [] for mod in revision.modules.all(): if request.POST.get(mod.filename, False): code = request.POST[mod.filename] if mod.code != code: mod.code = code changes.append(mod) for att in revision.attachments.all(): uid = str(att.pk) if request.POST.get(uid): att.data = request.POST[uid] if att.changed(): changes.append(att) attachments_changed = {} if save_revision or changes: try: revision.save() except ValidationError, err: return HttpResponseForbidden(escape(err.__str__()))
def save(request, revision_id, type_id=None): """ Save package and modules @TODO: check how dynamic module loading affects save """ revision = get_object_with_related_or_404(PackageRevision, pk=revision_id) if request.user.pk != revision.author.pk: log_msg = ("[security] Attempt to save package (%s) by " "non-owner (%s)" % (revision.pk, request.user)) log.warning(log_msg) return HttpResponseForbidden('You are not the author of this Package') save_revision = False save_package = False start_version_name = revision.version_name start_revision_message = revision.message response_data = {} package_full_name = request.POST.get('full_name', False) jid = request.POST.get('jid', None) version_name = request.POST.get('version_name', False) if jid and not validator.is_valid('alphanum_plus', jid): return HttpResponseForbidden( escape(validator.get_validation_message('alphanum_plus'))) # validate package_full_name and version_name if version_name and not validator.is_valid('alphanum_plus', version_name): return HttpResponseForbidden( escape(validator.get_validation_message('alphanum_plus'))) # here we're checking if the *current* full_name is different than the # revision's full_name if package_full_name and package_full_name != revision.package.full_name: try: revision.set_full_name(package_full_name) except ValidationError: return HttpResponseForbidden( escape( validator.get_validation_message('alphanum_plus_space'))) except IntegrityError: return HttpResponseForbidden( 'You already have a %s with that name' % escape(revision.package.get_type_name())) else: save_package = True save_revision = True response_data['full_name'] = package_full_name package_description = request.POST.get('package_description', False) if package_description: save_package = True revision.package.description = package_description response_data['package_description'] = package_description extra_json = request.POST.get('package_extra_json') if extra_json is not None: # None means it wasn't submitted. We want to accept blank strings. save_revision = True try: revision.set_extra_json(extra_json, save=False) except JSONDecodeError: return HttpResponseBadRequest( 'Extra package properties were invalid JSON.') except IllegalFilenameException, e: return HttpResponseBadRequest(str(e)) except KeyNotAllowed, e: return HttpResponseForbidden(str(e))
def package_save(r, id_number, type_id, revision_number=None, version_name=None): """ Save package and modules @TODO: check how dynamic module loading affects save """ revision = get_package_revision(id_number, type_id, revision_number, version_name) if r.user.pk != revision.author.pk: log_msg = "Unauthorised attempt to save package. user: %s, package: %s." % (r.user, id_number) log = commonware.log.getLogger("f.jetpack") log.debug(log_msg) return HttpResponseForbidden("You are not the author of this Package") should_reload = False save_revision = False save_package = False start_version_name = revision.version_name start_revision_message = revision.message start_revision_number = revision.revision_number response_data = {} package_full_name = r.POST.get("full_name", False) version_name = r.POST.get("version_name", False) # validate package_full_name and version_name if package_full_name and not validator.is_valid("alphanum_plus_space", package_full_name): return HttpResponseNotAllowed(escape(validator.get_validation_message("alphanum_plus_space"))) if version_name and not validator.is_valid("alphanum_plus", version_name): return HttpResponseNotAllowed(escape(validator.get_validation_message("alphanum_plus"))) if package_full_name and package_full_name != revision.package.full_name: try: # it was erroring as pk=package.pk # I changed it to pk=revision.package.pk # TODO: Check if not redundant as it is in model as well package = Package.objects.exclude(pk=revision.package.pk).get( full_name=package_full_name, type=revision.package.type, author__username=r.user.username ) return HttpResponseForbidden( "You already have a %s with that name" % escape(revision.package.get_type_name()) ) except: save_package = True should_reload = True revision.package.full_name = package_full_name revision.package.name = None package_description = r.POST.get("package_description", False) if package_description: save_package = True revision.package.description = package_description response_data["package_description"] = package_description modules = [] for mod in revision.modules.all(): if r.POST.get(mod.filename, False): code = r.POST[mod.filename] if mod.code != code: mod.code = code modules.append(mod) if modules: revision.modules_update(modules) save_revision = False if save_revision: revision.save() revision_message = r.POST.get("revision_message", False) if revision_message and revision_message != start_revision_message: revision.message = revision_message # save revision message without changeing the revision super(PackageRevision, revision).save() response_data["revision_message"] = revision_message if version_name and version_name != start_version_name and version_name != revision.package.version_name: save_package = False try: revision.set_version(version_name) except Exception, err: return HttpResponseForbidden(escape(err.__str__()))