Ejemplo n.º 1
0
def uploadyum(request):
	if request.method != 'PUT':
		return HttpServerError(request, "Invalid method")
	if not request.META['REMOTE_ADDR'] in settings.FTP_MASTERS:
		return HttpServerError(request, "Invalid client address")
	# We have the data in request.body. Attempt to load it as
	# json to ensure correct format.
	json.loads(request.body)

	# Next, check if it's the same as the current file
	if os.path.isfile(settings.YUM_JSON):
		with open(settings.YUM_JSON, "r") as f:
			if f.read() == request.body:
				# Don't rewrite the file or purge any data if nothing changed
				return HttpResponse("NOT CHANGED", content_type="text/plain")

	# File has changed - let's write it!
	with open("%s.new" % settings.YUM_JSON, "w") as f:
		f.write(request.body)

	os.rename("%s.new" % settings.YUM_JSON, settings.YUM_JSON)

	# Purge it out of varnish so we start responding right away
	varnish_purge("/download/js/yum.js")

	# Finally, indicate to the client that we're happy
	return HttpResponse("OK", content_type="text/plain")
Ejemplo n.º 2
0
def uploadftp(request):
	if request.method != 'PUT':
		return HttpServerError(request, "Invalid method")
	if not request.META['REMOTE_ADDR'] in settings.FTP_MASTERS:
		return HttpServerError(request, "Invalid client address")
	# We have the data in request.body. Attempt to load it as
	# a pickle to make sure it's properly formatted
	pickle.loads(request.body)

	# Next, check if it's the same as the current file
	f = open(settings.FTP_PICKLE, "rb")
	x = f.read()
	f.close()
	if x == request.body:
		# Don't rewrite the file or purge any data if nothing changed
		return HttpResponse("NOT CHANGED", content_type="text/plain")

	# File has changed - let's write it!
	f = open("%s.new" % settings.FTP_PICKLE, "wb")
	f.write(request.body)
	f.close()
	os.rename("%s.new" % settings.FTP_PICKLE, settings.FTP_PICKLE)

	# Purge it out of varnish so we start responding right away
	varnish_purge("/ftp")

	# Finally, indicate to the client that we're happy
	return HttpResponse("OK", content_type="text/plain")
Ejemplo n.º 3
0
def api_varnish_purge(request):
	if not request.META['REMOTE_ADDR'] in settings.VARNISH_PURGERS:
		return HttpServerError("Invalid client address")
	if request.method != 'POST':
		return HttpServerError("Can't use this way")
	n = int(request.POST['n'])
	curs = connection.cursor()
	for i in range(0, n):
		expr = request.POST['p%s' % i]
		curs.execute("SELECT varnish_purge_expr(%s)", (expr, ))
	return HttpResponse("Purged %s entries\n" % n)
Ejemplo n.º 4
0
def resetpwd(request):
	# Basic django password reset feature is completely broken. For example, it does not support
	# resetting passwords for users with "old hashes", which means they have no way to ever
	# recover. So implement our own, since it's quite the trivial feature.
	if request.method == "POST":
		try:
			u = User.objects.get(email__iexact=request.POST['email'])
			if u.password == OAUTH_PASSWORD_STORE:
				return HttpServerError(request, "This account cannot change password as it's connected to a third party login site.")
		except User.DoesNotExist:
			log.info("Attempting to reset password of {0}, user not found".format(request.POST['email']))
			return HttpResponseRedirect('/account/reset/done/')

		form = PgwebPasswordResetForm(data=request.POST)
		if form.is_valid():
			log.info("Initiating password set from {0} for {1}".format(get_client_ip(request), form.cleaned_data['email']))
			token = default_token_generator.make_token(u)
			send_template_mail(settings.ACCOUNTS_NOREPLY_FROM,
							   form.cleaned_data['email'],
							   'Password reset for your postgresql.org account',
							   'account/password_reset_email.txt',
							   {
								   'user': u,
								   'uid': urlsafe_base64_encode(force_bytes(u.pk)),
								   'token': token,
							   },
			)
			return HttpResponseRedirect('/account/reset/done/')
	else:
		form = PgwebPasswordResetForm()

	return render_pgweb(request, 'account', 'account/password_reset.html', {
			'form': form,
	})
Ejemplo n.º 5
0
def signup(request):
    if request.user.is_authenticated():
        return HttpServerError(
            request,
            "You must log out before you can sign up for a new account")

    if request.method == 'POST':
        # Attempt to create user then, eh?
        form = SignupForm(get_client_ip(request), data=request.POST)
        if form.is_valid():
            # Attempt to create the user here
            # XXX: Do we need to validate something else?
            log.info("Creating user for {0} from {1}".format(
                form.cleaned_data['username'], get_client_ip(request)))

            user = User.objects.create_user(
                form.cleaned_data['username'].lower(),
                form.cleaned_data['email'].lower(),
                last_login=datetime.now())
            user.first_name = form.cleaned_data['first_name']
            user.last_name = form.cleaned_data['last_name']

            # generate a random value for password. It won't be possible to log in with it, but
            # it creates more entropy for the token generator (I think).
            user.password = generate_random_token()
            user.save()

            # Now generate a token
            token = default_token_generator.make_token(user)
            log.info("Generated token {0} for user {1} from {2}".format(
                token, form.cleaned_data['username'], get_client_ip(request)))

            # Generate an outgoing email
            send_template_mail(
                settings.ACCOUNTS_NOREPLY_FROM, form.cleaned_data['email'],
                'Your new postgresql.org community account',
                'account/new_account_email.txt', {
                    'uid': urlsafe_base64_encode(force_bytes(user.id)),
                    'token': token,
                    'user': user
                })

            return HttpResponseRedirect('/account/signup/complete/')
    else:
        form = SignupForm(get_client_ip(request))

    return render_pgweb(
        request, 'account', 'base/form.html', {
            'form': form,
            'formitemtype': 'Account',
            'form_intro': """
To sign up for a free community account, enter your preferred userid and email address.
Note that a community account is only needed if you want to submit information - all
content is available for reading without an account. A confirmation email will be sent
to the specified address, and once confirmed a password for the new account can be specified.
""",
            'savebutton': 'Sign up',
            'operation': 'New',
            'recaptcha': True,
        })
Ejemplo n.º 6
0
def changepwd(request):
	if hasattr(request.user, 'password') and request.user.password == OAUTH_PASSWORD_STORE:
		return HttpServerError(request, "This account cannot change password as it's connected to a third party login site.")

	log.info("Initiating password change from {0}".format(get_client_ip(request)))
	return authviews.password_change(request,
									 template_name='account/password_change.html',
									 post_change_redirect='/account/changepwd/done/')
Ejemplo n.º 7
0
def vote(request, surveyid):
    surv = get_object_or_404(Survey, pk=surveyid)

    # Check that we have a valid answer number
    try:
        ansnum = int(request.POST['answer'])
        if ansnum < 1 or ansnum > 8:
            return HttpServerError(request, "Invalid answer")
    except:
        # When no answer is given, redirect to results instead
        return HttpResponseRedirect("/community/survey/%s-%s" %
                                    (surv.id, slugify(surv.question)))
    attrname = "tot%s" % ansnum

    # Do IP based locking...
    addr = get_client_ip(request)

    # Clean out any old junk
    curs = connection.cursor()
    curs.execute(
        "DELETE FROM survey_surveylock WHERE (\"time\" + '15 minutes') < now()"
    )

    # Check if we are locked
    lock = SurveyLock.objects.filter(ipaddr=addr)
    if len(lock) > 0:
        return HttpServerError(
            request, "Too many requests from your IP in the past 15 minutes")

    # Generate a new lock item, and store it
    lock = SurveyLock(ipaddr=addr)
    lock.save()

    answers = SurveyAnswer.objects.get_or_create(survey=surv)[0]
    setattr(answers, attrname, getattr(answers, attrname) + 1)
    answers.save()

    # Do explicit varnish purge, since it seems that the model doesn't
    # do it properly. Possibly because of the cute stuff we do with
    # getattr/setattr above.
    varnish_purge("/community/survey/%s/" % surveyid)

    return HttpResponseRedirect("/community/survey/%s/" % surveyid)
Ejemplo n.º 8
0
def confirm_change_email(request, tokenhash):
	tokens = EmailChangeToken.objects.filter(user=request.user, token=tokenhash)
	token = len(tokens) and tokens[0] or None

	if request.user.password == OAUTH_PASSWORD_STORE:
		# Link shouldn't exist in this case, so just throw an unfriendly
		# error message.
		return HttpServerError(request, "This account cannot change email address as it's connected to a third party login site.")

	if token:
		# Valid token find, so change the email address
		request.user.email = token.email.lower()
		request.user.save()
		token.delete()

	return render_pgweb(request, 'account', 'account/emailchangecompleted.html', {
		'token': tokenhash,
		'success': token and True or False,
		})
Ejemplo n.º 9
0
def ftpbrowser(request, subpath):
	if subpath:
		# An actual path has been selected. Fancy!

		if subpath.find('..') > -1:
			# Just claim it doesn't exist if the user tries to do this
			# type of bad thing
			raise Http404
		subpath = subpath.strip('/')
	else:
		subpath=""

	# Pickle up the list of things we need
	try:
		f = open(settings.FTP_PICKLE, "rb")
		allnodes = pickle.load(f)
		f.close()
	except Exception, e:
		return HttpServerError(request, "Failed to load ftp site information: %s" % e)
Ejemplo n.º 10
0
def change_email(request):
    tokens = EmailChangeToken.objects.filter(user=request.user)
    token = len(tokens) and tokens[0] or None

    if request.user.password == OAUTH_PASSWORD_STORE:
        # Link shouldn't exist in this case, so just throw an unfriendly
        # error message.
        return HttpServerError(
            request,
            "This account cannot change email address as it's connected to a third party login site."
        )

    if request.method == 'POST':
        form = ChangeEmailForm(request.user, data=request.POST)
        if form.is_valid():
            # If there is an existing token, delete it
            if token:
                token.delete()

            # Create a new token
            token = EmailChangeToken(user=request.user,
                                     email=form.cleaned_data['email'].lower(),
                                     token=generate_random_token())
            token.save()

            send_template_mail(settings.ACCOUNTS_NOREPLY_FROM,
                               form.cleaned_data['email'],
                               'Your postgresql.org community account',
                               'account/email_change_email.txt', {
                                   'token': token,
                                   'user': request.user,
                               })
            return HttpResponseRedirect('done/')
    else:
        form = ChangeEmailForm(request.user)

    return render_pgweb(request, 'account', 'account/emailchangeform.html', {
        'form': form,
        'token': token,
    })
Ejemplo n.º 11
0
def api_repo_updated(request):
	if not get_client_ip(request) in settings.SITE_UPDATE_HOSTS:
		return HttpServerError("Invalid client address")
	# Ignore methods and contents, just drop the trigger
	open(settings.SITE_UPDATE_TRIGGER_FILE, 'a').close()
	return HttpResponse("OK")
Ejemplo n.º 12
0
def signup_oauth(request):
	if not request.session.has_key('oauth_email') \
	   or not request.session.has_key('oauth_firstname') \
	   or not request.session.has_key('oauth_lastname'):
		return HttpServerError(request, 'Invalid redirect received')

	if request.method == 'POST':
		# Second stage, so create the account. But verify that the
		# nonce matches.
		data = request.POST.copy()
		data['email'] = request.session['oauth_email'].lower()
		data['first_name'] = request.session['oauth_firstname']
		data['last_name'] = request.session['oauth_lastname']
		form = SignupOauthForm(data=data)
		if form.is_valid():
			log.info("Creating user for {0} from {1} from oauth signin of email {2}".format(form.cleaned_data['username'], get_client_ip(request), request.session['oauth_email']))

			user = User.objects.create_user(form.cleaned_data['username'].lower(),
											request.session['oauth_email'].lower(),
											last_login=datetime.now())
			user.first_name = request.session['oauth_firstname']
			user.last_name = request.session['oauth_lastname']
			user.password = OAUTH_PASSWORD_STORE
			user.save()

			# Clean up our session
			del request.session['oauth_email']
			del request.session['oauth_firstname']
			del request.session['oauth_lastname']
			request.session.modified = True

			# We can immediately log the user in because their email
			# is confirmed.
			user.backend = settings.AUTHENTICATION_BACKENDS[0]
			django_login(request, user)

			# Redirect to the sessions page, or to the account page
			# if none was given.
			return HttpResponseRedirect(request.session.pop('login_next', '/account/'))
	elif request.GET.has_key('do_abort'):
		del request.session['oauth_email']
		del request.session['oauth_firstname']
		del request.session['oauth_lastname']
		request.session.modified = True
		return HttpResponseRedirect(request.session.pop('login_next', '/'))
	else:
		# Generate possible new username
		suggested_username = request.session['oauth_email'].replace('@', '.')[:30]

		# Auto generation requires firstnamea and lastname to be specified
		f = request.session['oauth_firstname'].lower()
		l = request.session['oauth_lastname'].lower()
		if f and l:
			for u in itertools.chain([
					u"{0}{1}".format(f, l[0]),
					u"{0}{1}".format(f[0], l),
			], (u"{0}{1}{2}".format(f, l[0], n) for n in xrange(100))):
				if not User.objects.filter(username=u[:30]).exists():
					suggested_username = u[:30]
					break

		form = SignupOauthForm(initial={
			'username': suggested_username,
			'email': request.session['oauth_email'].lower(),
			'first_name': request.session['oauth_firstname'][:30],
			'last_name': request.session['oauth_lastname'][:30],
		})

	return render_pgweb(request, 'account', 'account/signup_oauth.html', {
		'form': form,
		'operation': 'New account',
		'savebutton': 'Sign up for new account',
		'recaptcha': True,
		})
Ejemplo n.º 13
0
def ftpbrowser(request, subpath):
    if subpath:
        # An actual path has been selected. Fancy!

        if subpath.find('..') > -1:
            # Just claim it doesn't exist if the user tries to do this
            # type of bad thing
            raise Http404
        subpath = subpath.strip('/')
    else:
        subpath = ""

    # Pickle up the list of things we need
    try:
        f = open(settings.FTP_PICKLE, "rb")
        allnodes = pickle.load(f)
        f.close()
    except Exception as e:
        return HttpServerError(request,
                               "Failed to load ftp site information: %s" % e)

    # An incoming subpath may either be canonical, or have one or more elements
    # present that are actually symlinks. For each element of the path, test to
    # see if it is present in the pickle. If not, look for a symlink entry with
    # and if present, replace the original entry with the symlink target.
    canonpath = ''
    if subpath != '':
        parent = ''
        for d in subpath.split('/'):
            # Check if allnodes contains a node matching the path
            if d in allnodes[parent]:
                if allnodes[parent][d]['t'] == 'd':
                    canonpath = os.path.join(canonpath, d)
                elif allnodes[parent][d]['t'] == 'l':
                    canonpath = os.path.join(
                        canonpath, allnodes[parent][d]['d']).strip('/')
                else:
                    # There's a matching node, but it's not a link or a directory
                    raise Http404

                parent = canonpath
            else:
                # There's no matching node
                raise Http404

    # If we wound up with a canonical path that doesn't match the original request,
    # redirect the user
    canonpath = canonpath.strip('/')
    if subpath != canonpath:
        return HttpResponseRedirect('/ftp/' + canonpath)

    node = allnodes[subpath]
    del allnodes

    # Add all directories
    directories = [{
        'link': k,
        'url': k,
        'type': 'd'
    } for k, v in list(node.items()) if v['t'] == 'd']
    # Add all symlinks (only directories supported)
    directories.extend([{
        'link': k,
        'url': v['d'],
        'type': 'l'
    } for k, v in list(node.items()) if v['t'] == 'l'])

    # A little early sorting wouldn't go amiss, so .. ends up at the top
    directories.sort(key=version_sort, reverse=True)

    # Add a link to the parent directory
    if subpath:
        directories.insert(0, {'link': '[Parent Directory]', 'url': '..'})

    # Fetch files
    files = [{
        'name': k,
        'mtime': v['d'],
        'size': v['s']
    } for k, v in list(node.items()) if v['t'] == 'f']

    breadcrumbs = []
    if subpath:
        breadroot = ""
        for pathpiece in subpath.split('/'):
            if not pathpiece:
                # Trailing slash will give out an empty pathpiece
                continue
            if breadroot:
                breadroot = "%s/%s" % (breadroot, pathpiece)
            else:
                breadroot = pathpiece
            breadcrumbs.append({'name': pathpiece, 'path': breadroot})

    # Check if there are any "content files" we should render directly on the webpage
    file_readme = ('README' in node and node['README']['t']
                   == 'f') and node['README']['c'] or None
    file_message = ('.message' in node and node['.message']['t']
                    == 'f') and node['.message']['c'] or None
    file_maintainer = ('CURRENT_MAINTAINER' in node
                       and node['CURRENT_MAINTAINER']['t']
                       == 'f') and node['CURRENT_MAINTAINER']['c'] or None

    del node

    return render_pgweb(
        request, 'download', 'downloads/ftpbrowser.html', {
            'basepath': subpath.rstrip('/'),
            'directories': directories,
            'files': sorted(files, key=lambda f: f['name']),
            'breadcrumbs': breadcrumbs,
            'readme': file_readme,
            'messagefile': file_message,
            'maintainer': file_maintainer,
        })