def upload_attachments(request, id_number, type_id, revision_number=None, version_name=None): """ Upload new attachments to the PackageRevision """ revision = get_package_revision(None, id_number, type_id, revision_number, version_name) if request.user.pk != revision.author.pk: log_msg = ("[security] Attempt to upload attachment to package (%s) " "by non-owner (%s)" % (id_number, request.user)) log.warning(log_msg) return HttpResponseForbidden('You are not the author of this %s' % escape(revision.package.get_type_name())) content = request.raw_post_data filename = request.META.get('HTTP_X_FILE_NAME') if not filename: log_msg = 'Path not found: %s, package: %s.' % (filename, id_number) log.error(log_msg) return HttpResponseServerError('Path not found.') try: attachment = revision.attachment_create_by_filename( request.user, filename, content) except ValidationError, e: return HttpResponseForbidden('Validation errors.\n%s' % parse_validation_messages(e))
def add_empty_attachment(request, id_number, type_id, revision_number=None, version_name=None): """ Add new empty attachment to the PackageRevision """ revision = get_package_revision(None, id_number, type_id, revision_number, version_name) if request.user.pk != revision.author.pk: log_msg = ("[security] Attempt to add attachment to package (%s) by " "non-owner (%s)" % (id_number, request.user)) log.warning(log_msg) return HttpResponseForbidden('You are not the author of this %s' % escape(revision.package.get_type_name())) filename = request.POST.get('filename', False) if not filename: log_msg = 'Path not found: %s, package: %s.' % (filename, id_number) log.error(log_msg) return HttpResponseServerError('Path not found.') try: attachment = revision.attachment_create_by_filename( request.user, filename, '') except ValidationError, e: return HttpResponseForbidden('Validation errors.\n%s' % parse_validation_messages(e))
def remove_module(request, revision_id): """ Remove module from PackageRevision """ revision = get_object_with_related_or_404(PackageRevision, pk=revision_id) if request.user.pk != revision.author.pk: log_msg = ("[security] Attempt to remove a module from package (%s) " "by non-owner (%s)" % (revision_id, request.user)) log.warning(log_msg) return HttpResponseForbidden('You are not the author of this Package') filenames = request.POST.get('filename').split(',') revision.add_commit_message('module removed') try: removed_modules, removed_dirs = revision.modules_remove_by_path( filenames) except Module.DoesNotExist: log_msg = 'Attempt to delete a non existing module(s) %s from %s.' % ( str(filenames), revision_id) log.warning(log_msg) return HttpResponseForbidden('There is no such module in %s' % escape(revision.package.full_name)) return render_json( request, "json/module_removed.json", { 'revision': revision, 'removed_modules': simplejson.dumps(removed_modules), 'removed_dirs': simplejson.dumps(removed_dirs) })
def upload_attachment(request, revision_id): """ Upload new attachment to the PackageRevision """ revision = get_object_with_related_or_404(PackageRevision, pk=revision_id) log.debug(revision) if request.user.pk != revision.author.pk: log_msg = ("[security] Attempt to upload attachment to package (%s) " "by non-owner (%s)" % (revision_id, request.user)) log.warning(log_msg) return HttpResponseForbidden('You are not the author of this %s' % escape(revision.package.get_type_name())) f = request.FILES.get('upload_attachment') filename = request.META.get('HTTP_X_FILE_NAME') if not f: log_msg = 'Path not found: %s, revision: %s.' % (filename, revision_id) log.error(log_msg) return HttpResponseServerError('Path not found.') content = f.read() # try to force UTF-8 code, on error continue with original data try: content = unicode(content, 'utf-8') except: pass try: attachment = revision.attachment_create_by_filename( request.user, filename, content) except ValidationError, e: return HttpResponseForbidden('Validation errors.\n%s' % parse_validation_messages(e))
def vouchify(): """Synchronizes LDAP vouch info into database. This queries LDAP for users who's corresponding ``UserProfile`` has ``is_vouched`` as ``False``. It then updates ``is_vouched`` and ``vouched_by`` with up-to-date data. """ users = UserProfile.objects.filter(is_vouched=False) for user in users: person = user.get_ldap_person() if person and 'mozilliansVouchedBy' in person[1]: user.is_vouched = True voucher = (person[1]['mozilliansVouchedBy'][0].split(',')[0] .split('=')[1]) by = larper.get_user_by_uid(voucher) if by: email = by[1]['mail'][0] try: user.vouched_by = (User.objects.get(email=email) .get_profile()) except User.DoesNotExist: log.warning('No matching user for %s' % email) except UserProfile.DoesNotExist: log.warning('No matching user_profile for %s' % email) user.save() log.info('Data copied for %s' % user.user.username) log.debug('%s is still unvouched... skipping' % user.user.username)
def add_module(request, revision_id): """ Add new module to the PackageRevision """ revision = get_object_with_related_or_404(PackageRevision, pk=revision_id) if request.user.pk != revision.author.pk: log_msg = ("[security] Attempt to add a module to package (%s) by " "non-owner (%s)" % (id_number, request.user)) log.warning(log_msg) return HttpResponseForbidden('You are not the author of this %s' % escape(revision.package.get_type_name())) filename = request.POST.get('filename') mod = Module( filename=filename, author=request.user, code="""// %s.js - %s's module // author: %s""" % (filename, revision.package.full_name, request.user.get_profile())) try: mod.save() revision.module_add(mod) except FilenameExistException, err: mod.delete() return HttpResponseForbidden(escape(str(err)))
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 _migrate_approvals(items, **kw): log.info('[%s@%s] Migrating approval items starting with id: %s' % (len(items), _migrate_approvals.rate_limit, items[0])) for item in Approval.objects.filter(pk__in=items): try: args = (item.addon, item.file.version) except File.DoesNotExist: log.warning("Couldn't find file for approval %d" % item.id) continue kw = dict(user=item.user, created=item.created, details=dict(comments=item.comments, reviewtype=item.reviewtype, source=item.pk)) if item.action == amo.STATUS_PUBLIC: amo.log(amo.LOG.APPROVE_VERSION, *args, **kw) elif item.action == amo.STATUS_LITE: amo.log(amo.LOG.PRELIMINARY_VERSION, *args, **kw) elif item.action == amo.STATUS_NULL: amo.log(amo.LOG.REJECT_VERSION, *args, **kw) elif item.action in (amo.STATUS_PENDING, amo.STATUS_NOMINATED): amo.log(amo.LOG.ESCALATE_VERSION, *args, **kw) elif item.action == amo.STATUS_UNREVIEWED: amo.log(amo.LOG.RETAIN_VERSION, *args, **kw) else: log.warning('Unknown action: %d' % item.action)
def call_signing(file_obj): """Get the jar signature and send it to the signing server to be signed.""" endpoint = get_endpoint(file_obj) if not endpoint: log.warning('Not signing: no active endpoint') return timeout = settings.SIGNING_SERVER_TIMEOUT # We only want the (unique) temporary file name. with tempfile.NamedTemporaryFile() as temp_file: temp_filename = temp_file.name # Extract jar signature. try: jar = JarExtractor(path=storage.open(file_obj.file_path), outpath=temp_filename, omit_signature_sections=True) except: msg = 'Archive extraction failed. Bad archive?' log.error(msg, exc_info=True) raise SigningError(msg) log.info('File signature contents: %s' % jar.signatures) addon_id = file_obj.version.addon.guid log.info('Calling signing service: %s' % endpoint) try: with statsd.timer('services.sign.addon'): response = requests.post(endpoint, timeout=timeout, data={'addon_id': addon_id}, files={'file': ('mozilla.sf', str(jar.signatures))}) except requests.exceptions.HTTPError as error: # Will occur when a 3xx or greater code is returned. msg = 'Posting to add-on signing failed: %s, %s' % ( error.response.status, error) log.error(msg) raise SigningError(msg) except: # Will occur when some other error occurs. msg = 'Posting to add-on signing failed' log.error(msg, exc_info=True) raise SigningError(msg) if response.status_code != 200: msg = 'Posting to add-on signing failed: %s' % response.reason log.error(msg) raise SigningError(msg) pkcs7 = b64decode(json.loads(response.content)['mozilla.rsa']) try: cert_serial_num = get_signature_serial_number(pkcs7) jar.make_signed(pkcs7, sigpath='mozilla') except: msg = 'Addon signing failed' log.error(msg, exc_info=True) raise SigningError(msg) shutil.move(temp_filename, file_obj.file_path) return cert_serial_num
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 browserid_login(request): """Multi-mode BrowserID authentication form processor. Handles login and register browserid verification. If the mode is login, we are done. If the mode is register then we start new profile flow. Also handles corner cases. Login and register sasl-browserid verification steps are very similar and the corner cases blur the lines, so this is best as one url. We use the form from django-browserid, but since the LDAP server does the BrowserID auth behind the scenes, we don't use it's auth code nor it's views. """ form = ModalBrowserIdForm(data=request.POST) if form.is_valid(): assertion = form.cleaned_data['assertion'] store_assertion(request, assertion) mode = form.cleaned_data['mode'] user = auth.authenticate(request=request, assertion=assertion) if user: auth.login(request, user) return redirect('profile', request.user.unique_id) else: url = absolutify("%s?link=%s" % (reverse('register'), mode)) return redirect(url) else: msg = _('Sorry, but there were problems with the info you submitted. ' 'Please review the form, correct any errors, and try again.') messages.warning(request, msg) log.warning("Form didn't validate %s" % str(request.POST)) return redirect('home')
def vouchify(): """Synchronizes LDAP vouch info into database. This queries LDAP for users who's corresponding ``UserProfile`` has ``is_vouched`` as ``False``. It then updates ``is_vouched`` and ``vouched_by`` with up-to-date data. """ users = UserProfile.objects.filter(is_vouched=False) for user in users: person = user.get_ldap_person() if person and 'mozilliansVouchedBy' in person[1]: user.is_vouched = True voucher = (person[1]['mozilliansVouchedBy'][0].split(',')[0].split( '=')[1]) by = larper.get_user_by_uid(voucher) if by: email = by[1]['mail'][0] try: user.vouched_by = (User.objects.get( email=email).get_profile()) except User.DoesNotExist: log.warning('No matching user for %s' % email) except UserProfile.DoesNotExist: log.warning('No matching user_profile for %s' % email) user.save() log.info('Data copied for %s' % user.user.username) log.debug('%s is still unvouched... skipping' % user.user.username)
def list(self, request, *args, **kwargs): if (not settings.RECOMMENDATIONS_ENABLED or not settings.RECOMMENDATIONS_API_URL or not self.request.user.is_authenticated()): return self._popular() else: app_ids = [] url = '{base_url}/api/v2/recommend/{limit}/{user_hash}/'.format( base_url=settings.RECOMMENDATIONS_API_URL, limit=20, user_hash=self.request.user.recommendation_hash) try: with statsd.timer('recommendation.get'): resp = requests.get( url, timeout=settings.RECOMMENDATIONS_API_TIMEOUT) if resp.status_code == 200: app_ids = resp.json()['recommendations'] except Timeout as e: log.warning(u'Recommendation timeout: {error}'.format(error=e)) except RequestException as e: # On recommendation API exceptions we return popular. log.error(u'Recommendation exception: {error}'.format(error=e)) if not app_ids: # Fall back to a popularity search. return self._popular() sq = WebappIndexer.get_app_filter(self.request, app_ids=app_ids) return Response( self.serializer_class(sq.execute().hits, many=True, context={ 'request': self.request }).data)
def rename_attachment(request, revision_id): """ Rename an attachment in a PackageRevision """ revision = get_object_with_related_or_404(PackageRevision, pk=revision_id) if request.user.pk != revision.author.pk: log_msg = ("[security] Attempt to rename attachment in revision (%s) " "by non-owner (%s)" % (revision_id, request.user)) log.warning(log_msg) return HttpResponseForbidden('You are not the author of this Package') uid = request.POST.get('uid', '').strip() try: attachment = revision.attachments.get(pk=uid) except: log_msg = ('Attempt to rename a non existing attachment. attachment: ' '%s, revision: %s.' % (uid, revision)) log.warning(log_msg) return HttpResponseForbidden('There is no such attachment in %s' % escape(revision.package.full_name)) new_name = request.POST.get('new_filename') new_ext = request.POST.get('new_ext') or attachment.ext if not revision.validate_attachment_filename(new_name, new_ext): return HttpResponseForbidden( ('Sorry, there is already an attachment in your add-on ' 'with the name "%s.%s". Each attachment in your add-on ' 'needs to have a unique name.') % (new_name, attachment.ext)) attachment.filename = new_name attachment.ext = new_ext try: attachment = revision.update(attachment) except ValidationError, err: return HttpResponseForbidden(str(err))
def emailchange(request, user, token, hash): try: _uid, newemail = EmailResetCode.parse(token, hash) except ValueError: return http.HttpResponse(status=400) if _uid != user.id: # I'm calling this a warning because invalid hashes up to this point # could be any number of things, but this is a targeted attack from # one user account to another log.warning((u"[Tampering] Valid email reset code for UID (%s) " u"attempted to change email address for user (%s)") % (_uid, user)) return http.HttpResponse(status=400) if UserProfile.objects.filter(email=newemail).exists(): log.warning((u"[Tampering] User (%s) tries to change his email to " u"an existing account with the same email address (%s)") % (user, newemail)) return http.HttpResponse(status=400) user.email = newemail user.save() l = {'user': user, 'newemail': newemail} log.info(u"User (%(user)s) confirmed new email address (%(newemail)s)" % l) messages.success( request, _('Your email address was changed successfully'), _(u'From now on, please use {0} to log in.').format(newemail)) return http.HttpResponseRedirect(reverse('users.edit'))
def remove_attachment(request, revision_id): """ Remove attachment from PackageRevision """ revision = get_object_with_related_or_404(PackageRevision, pk=revision_id) if request.user.pk != revision.author.pk: log_msg = ('[security] Attempt to remove attachment from revision ' '(%s) by non-owner (%s)' % (revision_id, request.user)) log.warning(log_msg) return HttpResponseForbidden('You are not the author of this Package') uid = request.POST.get('uid', '').strip() attachment = get_object_with_related_or_404(Attachment, pk=uid, revisions=revision) if not attachment: log_msg = ('Attempt to remove a non existing attachment. attachment: ' '%s, revision: %s.' % (uid, revision_id)) log.warning(log_msg) return HttpResponseForbidden('There is no such attachment in %s' % escape(revision.package.full_name)) revision.attachment_remove(attachment) return render_json(request, "json/attachment_removed.json", { 'revision': revision, 'attachment': attachment })
def add_empty_attachment(request, id_number, type_id, revision_number=None, version_name=None): """ Add new empty attachment to the PackageRevision """ revision = get_package_revision(None, id_number, type_id, revision_number, version_name) if request.user.pk != revision.author.pk: log_msg = ("[security] Attempt to add attachment to package (%s) by " "non-owner (%s)" % (id_number, request.user)) log.warning(log_msg) return HttpResponseForbidden( 'You are not the author of this %s' % escape( revision.package.get_type_name())) filename = request.POST.get('filename', False) if not filename: log_msg = 'Path not found: %s, package: %s.' % ( filename, id_number) log.error(log_msg) return HttpResponseServerError('Path not found.') try: attachment = revision.attachment_create_by_filename(request.user, filename, '') except ValidationError, e: return HttpResponseForbidden( 'Validation errors.\n%s' % parse_validation_messages(e))
def add_module(request, revision_id): """ Add new module to the PackageRevision """ revision = get_object_with_related_or_404(PackageRevision, pk=revision_id) if request.user.pk != revision.author.pk: log_msg = ("[security] Attempt to add a module to package (%s) by " "non-owner (%s)" % (id_number, request.user)) log.warning(log_msg) return HttpResponseForbidden( 'You are not the author of this %s' % escape( revision.package.get_type_name())) filename = request.POST.get('filename') mod = Module( filename=filename, author=request.user, code="""// %s.js - %s's module // author: %s""" % (filename, revision.package.full_name, request.user.get_profile()) ) try: mod.save() revision.module_add(mod) except FilenameExistException, err: mod.delete() return HttpResponseForbidden(escape(str(err)))
def remove_module(request, revision_id): """ Remove module from PackageRevision """ revision = get_object_with_related_or_404(PackageRevision, pk=revision_id) if request.user.pk != revision.author.pk: log_msg = ("[security] Attempt to remove a module from package (%s) " "by non-owner (%s)" % (revision_id, request.user)) log.warning(log_msg) return HttpResponseForbidden('You are not the author of this Package') filenames = request.POST.get('filename').split(',') revision.add_commit_message('module removed') try: removed_modules, removed_dirs = revision.modules_remove_by_path( filenames) except Module.DoesNotExist: log_msg = 'Attempt to delete a non existing module(s) %s from %s.' % ( str(filenames), revision_id) log.warning(log_msg) return HttpResponseForbidden( 'There is no such module in %s' % escape( revision.package.full_name)) return render_json(request, "json/module_removed.json", {'revision': revision, 'removed_modules': simplejson.dumps(removed_modules), 'removed_dirs': simplejson.dumps(removed_dirs)})
def register(request): if request.user.is_authenticated(): return redirect(reverse('profile', args=[request.user.unique_id])) initial = {} if 'code' in request.GET: code = request.GET['code'] try: invite = get_invite(code) initial['email'] = invite.recipient initial['code'] = invite.code except Invite.DoesNotExist: log.warning('Bad register code [%s], skipping invite' % code) form = forms.RegistrationForm(request.POST or None, initial=initial) if request.method == 'POST': if form.is_valid(): try: _save_new_user(request, form) _send_confirmation_email(request.user) msg = _(u'Your account has been created but needs to be ' 'verified. Please check your email to verify ' 'your account.') messages.info(request, msg) auth.logout(request) return redirect(reverse('login')) except ldap.CONSTRAINT_VIOLATION: _set_already_exists_error(form) return render(request, 'registration/register.html', dict(form=form))
def clean(self): amouser = self.request.user.get_profile() if amouser.is_developer: # This is tampering because the form isn't shown on the page if the # user is a developer log.warning(u"[Tampering] Attempt to delete developer account (%s)" % self.request.user) raise forms.ValidationError("")
def upload(request): """Video upload page.""" if request.method == 'POST': form = UploadForm(request.POST) if form.is_valid(): video = form.save(commit=False) video.user = request.user video.save() # Celery times out sometimes; we'll catch orphaned # videos with a cron job. try: send_video_to_vidly.delay(video) except socket.timeout: log.warning('Timeout connecting to celery to convert video ' 'id: %s' % video.id) # Update statsd graph for uploads statsd.incr('video_uploads') return render(request, 'videos/upload_complete.html') else: form = UploadForm() d = dict(upload_form=form, page_type='secondary form') return render(request, 'videos/upload.html', d)
def get_profile(self): """Retrieve the Django UserProfile for this Person. This is full of hacks because all the Mozillians servers are throwing ObjectDoesNotExist errors (even in production) if we try a straight-up `User.objects.get(email=self.username)`. This method now exhaustively tries to get a User object from the database. If it doesn't find one, or finds one without a UserProfile, we make one on the spot, trying our best to fill things in sanely. FML. See: https://bugzilla.mozilla.org/show_bug.cgi?id=698699 TODO: Remove this as soon as possible. It's insane. """ user = (User.objects.filter(Q(email=self.username) | Q(username=self.username)))[:1] if user: # Yes, sometimes the User exists but the UserProfile doesn't. # See: https://bugzilla.mozilla.org/show_bug.cgi?id=699234 try: profile = user[0].get_profile() except ObjectDoesNotExist, e: statsd.incr("user.errors.profile_doesnotexist") log.warning(e) profile = UserProfile.objects.create(user=user[0])
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 get_profile(self): """Retrieve the Django UserProfile for this Person. This is full of hacks because all the Mozillians servers are throwing ObjectDoesNotExist errors (even in production) if we try a straight-up `User.objects.get(email=self.username)`. This method now exhaustively tries to get a User object from the database. If it doesn't find one, or finds one without a UserProfile, we make one on the spot, trying our best to fill things in sanely. FML. See: https://bugzilla.mozilla.org/show_bug.cgi?id=698699 TODO: Remove this as soon as possible. It's insane. """ user = (User.objects.filter( Q(email=self.username) | Q(username=self.username)))[:1] if user: # Yes, sometimes the User exists but the UserProfile doesn't. # See: https://bugzilla.mozilla.org/show_bug.cgi?id=699234 try: profile = user[0].get_profile() except ObjectDoesNotExist, e: statsd.incr('user.errors.profile_doesnotexist') log.warning(e) profile = UserProfile.objects.create(user=user[0])
def emailchange(request, user_id, token, hash): user = get_object_or_404(UserProfile, id=user_id) try: _uid, newemail = EmailResetCode.parse(token, hash) except ValueError: return http.HttpResponse(status=400) if _uid != user.id: # I'm calling this a warning because invalid hashes up to this point # could be any number of things, but this is a targeted attack from # one user account to another log.warning((u"[Tampering] Valid email reset code for UID (%s) " "attempted to change email address for user (%s)") % (_uid, user)) return http.HttpResponse(status=400) user.email = newemail user.save() l = {'user': user, 'newemail': newemail} log.info(u"User (%(user)s) confirmed new email address (%(newemail)s)" % l) messages.success(request, _('Your email address was changed successfully'), _(u'From now on, please use {0} to log in.').format(newemail)) return http.HttpResponseRedirect(reverse('users.edit'))
def upvote(request, video_shortlink): """Add an upvote to a video.""" response = HttpResponse(mimetype='application/json') if video_shortlink in request.COOKIES: response.status_code = 403 response.content = json.dumps({'error': 'already voted'}) return response video = get_object_or_none(Video, shortlink=video_shortlink) if video is not None: try: video.upvote() except socket.timeout: log.warning('Timeout connecting to celery to upvote video ' 'shortlink: %s' % video_shortlink) response.status_code = 500 response.content = json.dumps({'error': 'celery timeout'}) else: response.set_cookie(str(video_shortlink), value='1', httponly=False, max_age=settings.VOTE_COOKIE_AGE) response.content = json.dumps({'success': 'success'}) else: response.status_code = 404 response.content = json.dumps({'error': 'video not found'}) return response
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 to_string(self, type_=None): log_type = amo.LOG_BY_ID[self.action] if type_ and hasattr(log_type, '%s_format' % type_): format = getattr(log_type, '%s_format' % type_) else: format = log_type.format # We need to copy arguments so we can remove elements from it # while we loop over self.arguments. arguments = copy(self.arguments) addon = None review = None version = None collection = None tag = None group = None for arg in self.arguments: if isinstance(arg, Addon) and not addon: if arg.is_listed: addon = self.f(u'<a href="{0}">{1}</a>', arg.get_url_path(), arg.name) else: addon = self.f(u'{0}', arg.name) arguments.remove(arg) if isinstance(arg, Review) and not review: review = self.f(u'<a href="{0}">{1}</a>', arg.get_url_path(), _('Review')) arguments.remove(arg) if isinstance(arg, Version) and not version: text = _('Version {0}') if arg.is_listed: version = self.f(u'<a href="{1}">%s</a>' % text, arg.version, arg.get_url_path()) else: version = self.f(text, arg.version) arguments.remove(arg) if isinstance(arg, Collection) and not collection: collection = self.f(u'<a href="{0}">{1}</a>', arg.get_url_path(), arg.name) arguments.remove(arg) if isinstance(arg, Tag) and not tag: if arg.can_reverse(): tag = self.f(u'<a href="{0}">{1}</a>', arg.get_url_path(), arg.tag_text) else: tag = self.f('{0}', arg.tag_text) if isinstance(arg, Group) and not group: group = arg.name arguments.remove(arg) user = user_link(self.user) try: kw = dict(addon=addon, review=review, version=version, collection=collection, tag=tag, user=user, group=group) return self.f(format, *arguments, **kw) except (AttributeError, KeyError, IndexError): log.warning('%d contains garbage data' % (self.id or 0)) return 'Something magical happened.'
def package_remove_attachment(r, id_number, type_id, revision_number): """ Remove attachment from PackageRevision """ revision = get_package_revision(id_number, type_id, revision_number) if r.user.pk != revision.author.pk: log_msg = ("[security] Attempt to remove attachment from package (%s) " "by non-owner (%s)" % (id_number, r.user)) log.warning(log_msg) return HttpResponseForbidden('You are not the author of this Package') uid = r.POST.get('uid', '').strip() attachment = get_object_with_related_or_404(Attachment, pk=uid, revisions=revision) if not attachment: log_msg = ('Attempt to remove a non existing attachment. attachment: ' '%s, package: %s.' % (uid, id_number)) log.warning(log_msg) return HttpResponseForbidden( 'There is no such attachment in %s' % escape( revision.package.full_name)) revision.attachment_remove(attachment) return render_to_response("json/attachment_removed.json", {'revision': revision, 'attachment': attachment}, context_instance=RequestContext(r), mimetype='application/json')
def package_add_module(r, id_number, type_id, revision_number=None, version_name=None): """ Add new module to the PackageRevision """ revision = get_package_revision(id_number, type_id, revision_number, version_name) if r.user.pk != revision.author.pk: log_msg = ("[security] Attempt to add a module to package (%s) by " "non-owner (%s)" % (id_number, r.user)) log.warning(log_msg) return HttpResponseForbidden( 'You are not the author of this %s' % escape( revision.package.get_type_name())) filename = pathify(r.POST.get('filename')) mod = Module( filename=filename, author=r.user, code="""// %s.js - %s's module // author: %s""" % (filename, revision.package.full_name, r.user.get_profile()) ) try: mod.save() revision.module_add(mod) except FilenameExistException, err: mod.delete() return HttpResponseForbidden(escape(str(err)))
def package_remove_module(r, id_number, type_id, revision_number): """ Remove module from PackageRevision """ revision = get_package_revision(id_number, type_id, revision_number) if r.user.pk != revision.author.pk: log_msg = ("[security] Attempt to remove a module from package (%s) " "by non-owner (%s)" % (id_number, r.user)) log.warning(log_msg) return HttpResponseForbidden('You are not the author of this Package') filenames = r.POST.get('filename').split(',') revision.add_commit_message('module removed') try: removed_modules, removed_dirs = revision.modules_remove_by_path( filenames) except Module.DoesNotExist: log_msg = 'Attempt to delete a non existing module(s) %s from %s.' % ( str(filenames), id_number) log.warning(log_msg) return HttpResponseForbidden( 'There is no such module in %s' % escape( revision.package.full_name)) return render_to_response("json/module_removed.json", {'revision': revision, 'removed_modules': simplejson.dumps(removed_modules), 'removed_dirs': simplejson.dumps(removed_dirs)}, context_instance=RequestContext(r), mimetype='application/json')
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 revision_add_attachment(request, pk): """Add attachment, download if necessary """ revision = get_object_or_404(PackageRevision, pk=pk) if request.user.pk != revision.author.pk: log_msg = ("[security] Attempt to add attachment to package (%s) by " "non-owner (%s)" % (revision.package, request.user)) log.warning(log_msg) return HttpResponseForbidden( 'You are not the author of this %s' % escape( revision.package.get_type_name())) url = request.POST.get('url', None) filename = request.POST.get('filename', None) log.debug(filename) if not filename or filename == "": log.error('Trying to create an attachment without name') return HttpResponseForbidden('Path not found.') content = '' if url: # validate url field = URLField(verify_exists=True) try: url = field.clean(url) except ValidationError, err: log.debug('Invalid url provided (%s)\n%s' % (url, '\n'.join(err.messages))) return HttpResponseForbidden(("Loading attachment failed<br/>" "%s") % '<br/>'.join(err.messages)) except Exception, err: return HttpResponseForbidden(str(err))
def upload_attachments(request, id_number, type_id, revision_number=None, version_name=None): """ Upload new attachments to the PackageRevision """ revision = get_package_revision(None, id_number, type_id, revision_number, version_name) if request.user.pk != revision.author.pk: log_msg = ("[security] Attempt to upload attachment to package (%s) " "by non-owner (%s)" % (id_number, request.user)) log.warning(log_msg) return HttpResponseForbidden( 'You are not the author of this %s' % escape( revision.package.get_type_name())) content = request.raw_post_data filename = request.META.get('HTTP_X_FILE_NAME') if not filename: log_msg = 'Path not found: %s, package: %s.' % ( filename, id_number) log.error(log_msg) return HttpResponseServerError('Path not found.') try: attachment = revision.attachment_create_by_filename( request.user, filename, content) except ValidationError, e: return HttpResponseForbidden( 'Validation errors.\n%s' % parse_validation_messages(e))
def remove_attachment(request, revision_id): """ Remove attachment from PackageRevision """ revision = get_object_with_related_or_404(PackageRevision, pk=revision_id) if request.user.pk != revision.author.pk: log_msg = ('[security] Attempt to remove attachment from revision ' '(%s) by non-owner (%s)' % (revision_id, request.user)) log.warning(log_msg) return HttpResponseForbidden('You are not the author of this Package') uid = request.POST.get('uid', '').strip() attachment = get_object_with_related_or_404(Attachment, pk=uid, revisions=revision) if not attachment: log_msg = ('Attempt to remove a non existing attachment. attachment: ' '%s, revision: %s.' % (uid, revision_id)) log.warning(log_msg) return HttpResponseForbidden( 'There is no such attachment in %s' % escape( revision.package.full_name)) revision.attachment_remove(attachment) return render_json(request, "json/attachment_removed.json", {'revision': revision, 'attachment': attachment})
def request(action, params, notify_url, user_id=VIDLY_USER_ID, user_key=VIDLY_USER_KEY, api_url=VIDLY_API_URL): """Call the vid.ly API with the supplied parameters.""" if user_id is None or user_key is None: log.warning('You are missing a user id and/or key for vidly. You ' 'should pass these to the function you called or specify ' 'them in settings.VIDLY_USER_ID and ' 'settings.VIDLY_USER_KEY.') return None # Build XML Query query = ET.Element('Query') ET.SubElement(query, 'Action').text = action ET.SubElement(query, 'UserID').text = user_id ET.SubElement(query, 'UserKey').text = user_key ET.SubElement(query, 'Notify').text = notify_url _build_param_xml(query, params) # Getting an xml version header out of ElementTree is tough. # It's easier for our use case to just prepend it. xml_str = '<?xml version="1.0"?>%s' % ET.tostring(query) log.error('Vidly Request: %s' % xml_str) try: res = requests.post(api_url, data={'xml': xml_str}) except RequestException, e: log.error('Error connecting to Vidly: %s' % e) return None
def add_email_to_group(cls, email, group_id): constituent_id = BSDClient.register_email_address_as_constituent(email) result = BSDClient.add_constituent_id_to_group(constituent_id, group_id) if not result: log.warning('Failed to add email to group') return result
def list(self, request, *args, **kwargs): if (not settings.RECOMMENDATIONS_ENABLED or not settings.RECOMMENDATIONS_API_URL or not self.request.user.is_authenticated()): return self._popular() else: app_ids = [] url = '{base_url}/api/v2/recommend/{limit}/{user_hash}/'.format( base_url=settings.RECOMMENDATIONS_API_URL, limit=20, user_hash=self.request.user.recommendation_hash) try: with statsd.timer('recommendation.get'): resp = requests.get( url, timeout=settings.RECOMMENDATIONS_API_TIMEOUT) if resp.status_code == 200: app_ids = resp.json()['recommendations'] except Timeout as e: log.warning(u'Recommendation timeout: {error}'.format(error=e)) except RequestException as e: # On recommendation API exceptions we return popular. log.error(u'Recommendation exception: {error}'.format(error=e)) if not app_ids: # Fall back to a popularity search. return self._popular() sq = WebappIndexer.get_app_filter(self.request, app_ids=app_ids) return Response({ 'objects': self.serializer_class( sq.execute().hits, many=True, context={'request': self.request}).data})
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 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 upload_attachment(request, revision_id): """ Upload new attachment to the PackageRevision """ revision = get_object_with_related_or_404(PackageRevision, pk=revision_id) log.debug(revision) if request.user.pk != revision.author.pk: log_msg = ("[security] Attempt to upload attachment to package (%s) " "by non-owner (%s)" % (revision_id, request.user)) log.warning(log_msg) return HttpResponseForbidden( 'You are not the author of this %s' % escape( revision.package.get_type_name())) f = request.FILES.get('upload_attachment') filename = request.META.get('HTTP_X_FILE_NAME') if not f: log_msg = 'Path not found: %s, revision: %s.' % ( filename, revision_id) log.error(log_msg) return HttpResponseServerError('Path not found.') content = f.read() # try to force UTF-8 code, on error continue with original data try: content = unicode(content, 'utf-8') except: pass try: attachment = revision.attachment_create_by_filename( request.user, filename, content) except ValidationError, e: return HttpResponseForbidden( 'Validation errors.\n%s' % parse_validation_messages(e))
def package_upload_attachment(r, id_number, type_id, revision_number=None, version_name=None): """ Upload new attachment to the PackageRevision """ revision = get_package_revision(id_number, type_id, revision_number, version_name) if r.user.pk != revision.author.pk: log_msg = ("[security] Attempt to upload attachment to package (%s) " "by non-owner (%s)" % (id_number, r.user)) log.warning(log_msg) return HttpResponseForbidden( 'You are not the author of this %s' \ % escape(revision.package.get_type_name())) file = r.FILES.get('upload_attachment') filename = r.META.get('HTTP_X_FILE_NAME') if not file: log_msg = 'Path not found: %s, package: %s.' % ( filename, id_number) log.error(log_msg) return HttpResponseServerError('Path not found.') content = file.read() try: attachment = revision.attachment_create_by_filename( r.user, filename, content) except ValidationError, e: return HttpResponseForbidden('Validation errors.')
def to_string(self, type_=None): log_type = amo.LOG_BY_ID[self.action] if type_ and hasattr(log_type, '%s_format' % type_): format = getattr(log_type, '%s_format' % type_) else: format = log_type.format # We need to copy arguments so we can remove elements from it # while we loop over self.arguments. arguments = copy(self.arguments) addon = None review = None version = None collection = None tag = None group = None for arg in self.arguments: if isinstance(arg, Addon) and not addon: addon = self.f(u'<a href="{0}">{1}</a>', arg.get_url_path(), arg.name) arguments.remove(arg) if isinstance(arg, Review) and not review: review = self.f(u'<a href="{0}">{1}</a>', arg.get_url_path(), _('Review')) arguments.remove(arg) if isinstance(arg, Version) and not version: text = _('Version {0}') version = self.f(u'<a href="{1}">%s</a>' % text, arg.version, arg.get_url_path()) arguments.remove(arg) if isinstance(arg, Collection) and not collection: collection = self.f(u'<a href="{0}">{1}</a>', arg.get_url_path(), arg.name) arguments.remove(arg) if isinstance(arg, Tag) and not tag: if arg.can_reverse(): tag = self.f(u'<a href="{0}">{1}</a>', arg.get_url_path(), arg.tag_text) else: tag = self.f('{0}', arg.tag_text) if isinstance(arg, Group) and not group: group = arg.name arguments.remove(arg) user = user_link(self.user) try: kw = dict(addon=addon, review=review, version=version, collection=collection, tag=tag, user=user, group=group) return self.f(format, *arguments, **kw) except (AttributeError, KeyError, IndexError): log.warning('%d contains garbage data' % (self.id or 0)) return 'Something magical happened.'
def clean(self): amouser = self.request.user.get_profile() if amouser.is_developer: # This is tampering because the form isn't shown on the page if the # user is a developer log.warning(u'[Tampering] Attempt to delete developer account (%s)' % self.request.user) raise forms.ValidationError("")
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 register(request): """Multi-purpose registration view. Uses: legacy email url with invite code, first time edit profile after browserid_login. Process POST and create new users. """ # Legacy URL shenanigans - A GET to register with invite code # is a legal way to start the BrowserID registration flow. if 'code' in request.GET: request.session['invite-code'] = request.GET['code'] return redirect('home') if request.user.is_authenticated(): return redirect(reverse('profile', args=[request.user.unique_id])) if not 'verified_email' in request.session: log.error('Browserid registration, but no verified email in session') return redirect('home') email = request.session['verified_email'] intent = 'register' # Check for optional invite code initial = {} if 'invite-code' in request.session: code = request.session['invite-code'] try: invite = get_invite(code) initial['email'] = invite.recipient initial['code'] = invite.code except Invite.DoesNotExist: log.warning('Bad register code [%s], skipping invite' % code) form = forms.RegistrationForm(request.POST or None, initial=initial) if request.method == 'POST': if form.is_valid(): try: uniq_id = _save_new_user(request, form) messages.info(request, _(u'Your account has been created.')) return redirect('profile', uniq_id) except ldap.CONSTRAINT_VIOLATION: log.error("User already exists") _set_already_exists_error(form) else: if 'link' in request.GET: intent = request.GET['link'] anonymous = Anonymous() return render( request, 'phonebook/edit_profile.html', dict(form=form, edit_form_action=reverse('register'), person=anonymous, mode='new', email=email, intent=intent))
def monitor(request): status = True data = {} # Check Read/Write filepaths = [ (settings.UPLOAD_DIR, os.R_OK | os.W_OK, 'We want read + write.'), ] if hasattr(settings, 'XPI_TARGETDIR'): filepaths.append((settings.XPI_TARGETDIR, os.R_OK | os.W_OK, 'We want read + write. Should be a shared directory ' 'on multiserver installations')) for sdk in SDK.objects.all(): filepaths.append((sdk.get_source_dir(), os.R_OK, 'We want read on %s' % sdk.version), ) filepath_results = [] filepath_status = True for path, perms, notes in filepaths: path_exists = os.path.isdir(path) path_perms = os.access(path, perms) filepath_status = filepath_status and path_exists and path_perms if not filepath_status and status: status = False filepath_results.append((path, path_exists, path_perms, notes)) # free space on XPI_TARGETDIR disk x_path = '%s/' % settings.XPI_TARGETDIR s_path = '%s/' % settings.SDKDIR_PREFIX x = os.statvfs(x_path) s = os.statvfs(s_path) data['free'] = [('xpi_targetdir %s' % x_path, x.f_bavail * x.f_frsize), ('sdkdir_prefix %s' % s_path, s.f_bavail * s.f_frsize)] data['filepaths'] = filepath_results # Check celery try: data['celery_responses'] = CeleryResponse.objects.all() except: status = False # Check ElasticSearch try: es = get_es() data['es_health'] = es.cluster_health() data['es_health']['version'] = es.collect_info( )['server']['version']['number'] if data['es_health']['status'] == 'red': status = False log.warning('ElasticSearch cluster health was red.') except Exception, e: status = False log.critical('Failed to connect to ElasticSearch: %s' % e)
def _login(request, template=None, data=None, dont_redirect=False): data = data or {} data['webapp'] = True # In case we need it later. See below. get_copy = request.GET.copy() if 'to' in request.GET: request = _clean_next_url(request) if request.user.is_authenticated(): return http.HttpResponseRedirect( request.GET.get('to', settings.LOGIN_REDIRECT_URL)) user = None login_status = None r = auth_login(request, template_name=template, redirect_field_name='to', extra_context=data) if isinstance(r, http.HttpResponseRedirect): # Django's auth.views.login has security checks to prevent someone from # redirecting to another domain. Since we want to allow this in # certain cases, we have to make a new response object here to replace # the above. if 'domain' in request.GET: request.GET = get_copy request = _clean_next_url(request) r = http.HttpResponseRedirect(request.GET['to']) # Succsesful log in according to django. Now we do our checks. I do # the checks here instead of the form's clean() because I want to use # the messages framework and it's not available in the request there. if user.deleted: logout(request) log.warning(u'Attempt to log in with deleted account (%s)' % user) messages.error(request, _('Wrong email address or password!')) user.log_login_attempt(False) log_cef('Authentication Failure', 5, request, username=request.user, signature='AUTHFAIL', msg='Account is deactivated') return render(request, template, data) login_status = True if dont_redirect: # We're recalling the middleware to re-initialize amo_user ACLMiddleware().process_request(request) r = render(request, template, data) if login_status is not None: user.log_login_attempt(login_status) log_cef('Authentication Failure', 5, request, username=request.POST['username'], signature='AUTHFAIL', msg='The password was incorrect') return r
def login(request): logout(request) if 'to' in request.GET: request = _clean_next_url(request) r = auth.views.login(request, template_name='users/login.html', redirect_field_name='to', authentication_form=forms.AuthenticationForm) if isinstance(r, http.HttpResponseRedirect): # Succsesful log in according to django. Now we do our checks. I do # the checks here instead of the form's clean() because I want to use # the messages framework and it's not available in the request there user = request.user.get_profile() if user.deleted: logout(request) log.warning(u'Attempt to log in with deleted account (%s)' % user) messages.error(request, _('Wrong email address or password!')) return jingo.render(request, 'users/login.html', {'form': forms.AuthenticationForm()}) if user.confirmationcode: logout(request) log.info(u'Attempt to log in with unconfirmed account (%s)' % user) msg1 = _(('A link to activate your user account was sent by email ' 'to your address {0}. You have to click it before you ' 'can log in.').format(user.email)) url = "%s%s" % (settings.SITE_URL, reverse('users.confirm.resend', args=[user.id])) msg2 = _(('If you did not receive the confirmation email, make ' 'sure your email service did not mark it as "junk ' 'mail" or "spam". If you need to, you can have us ' '<a href="%s">resend the confirmation message</a> ' 'to your email address mentioned above.') % url) messages.error(request, _('Activation Email Sent'), msg1) messages.info(request, _('Having Trouble?'), msg2, title_safe=True) return jingo.render(request, 'users/login.html', {'form': forms.AuthenticationForm()}) rememberme = request.POST.get('rememberme', None) if rememberme: request.session.set_expiry(settings.SESSION_COOKIE_AGE) log.debug((u'User (%s) logged in successfully with ' '"remember me" set') % user) else: user.log_login_attempt(request, True) elif 'username' in request.POST: # Hitting POST directly because cleaned_data doesn't exist user = UserProfile.objects.filter(email=request.POST['username']) if user: user.get().log_login_attempt(request, False) return r
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 handle_user(self, request, user): profile, created = UserProfile.objects.get_or_create(user=user) if created: log.warning('Created profile for user with email %s' % user.email) if profile.is_complete(): auth.login(request, user) return redirect(reverse('profile', args=[user.username])) request.session['authenticated_email'] = user.email return redirect(reverse('register'))
def download_module(request, pk): """ return a JSON with all module info """ module = get_object_with_related_or_404(Module, pk=pk) if not module.can_view(request.user): log_msg = ("[security] Attempt to download private module (%s) by " "non-owner (%s)" % (pk, request.user)) log.warning(log_msg) return HttpResponseForbidden('You are not the author of this module.') return HttpResponse(module.get_json())
def login_success(self): user = self.user profile, created = UserProfile.objects.get_or_create(user=user) if created: log.warning('Created profile for user with email %s' % user.email) if profile.is_complete(): return super(BrowserID, self).login_success() self.request.session['authenticated_email'] = user.email return redirect(reverse('register'))
def _save_new_user(request, form): """ form - must be a valid form We persist account to LDAP. If all goes well, we log the user in and persist their BID assertion to the session. """ # Email in the form is the "username" we'll use. email = request.session['verified_email'] username = email registrar = RegistrarSession.connect(request) code = request.session.get('invite-code') d = form.cleaned_data d['email'] = email uniq_id = registrar.create_person(d) voucher = None if code: try: invite = get_invite(code) voucher = invite.inviter except Invite.DoesNotExist: msg = 'Bad code in form [%s], skipping pre-vouch' % d['code'] log.warning(msg) # we need to authenticate them... with their assertion assertion_hash, assertion = get_assertion(request) for i in range(1, 10): try: user = auth.authenticate(request=request, assertion=assertion) # Should never happen if not user or not user.is_authenticated(): msg = 'Authentication for new user (%s) failed' % username # TODO: make this a unique exception. raise Exception(msg) statsd.incr('user.successful_registration') statsd.incr('user.successful_registration_attempt_%s' % i) break except Exception, e: statsd.incr('user.errors.registration_failed') statsd.incr('user.errors.registration_failed_attempt_%s' % i) log.warning(e) # All hope is lost. if i == 10: statsd.incr('user.errors.user_record_never_created') raise Exception(e)
def profile_uid(request, unique_id): """View a profile by unique_id, which is a stable, random user id.""" needs_master = (request.user.unique_id == unique_id) ldap = UserSession.connect(request) try: # Stale data okay when viewing others person = ldap.get_by_unique_id(unique_id, needs_master) if person.last_name: return _profile(request, person, needs_master) except NO_SUCH_PERSON: log.warning('profile_uid Sending 404 for [%s]' % unique_id) raise Http404
class SessionBackend: supports_anonymous_user = False supports_object_permissions = False def authenticate(self, session): """ Given a CakeSession object we'll authenticate it to an actual user. """ if (time() > session.expires or not session.data.startswith('User|')): session.delete() return None try: serialized_data = smart_str(session.data[5:]) php_user = phpserialize.loads(serialized_data) except ValueError, e: # Bug 553397 log.warning("Found corrupt session (%s): %s" % (session.pk, e)) session.delete() return None user_id = int(php_user.get('id')) try: profile = UserProfile.objects.get(pk=user_id) except UserProfile.DoesNotExist: session.delete() return None def retrieve_from_master(pk): return UserProfile.objects.using('default').no_cache().get(pk=pk) # User will hit this if they are new to zamboni. try: if profile.user is None: # This will catch replication lags in case we created a user. profile = retrieve_from_master(user_id) if profile.user is None: profile.create_django_user() except User.DoesNotExist: log.warning('Bad user_id {0} on UserProfile {1}.'.format( profile.id, profile.user_id)) # Chances are we are suffering from replication lag, but # let's play it safe and just not authenticate. return None except IntegrityError, e: # Typically a duplicate key. log.warning('DB Error for UserProfile {0}: {1}'.format(user_id, e)) return None