Added authentication for register+upload, and projects now has owners.

This commit is contained in:
Ask Solem
2009-03-21 21:59:34 +01:00
committed by Ask Solem Hoel
parent 4335d5430f
commit 9a3a947bf3
3 changed files with 69 additions and 13 deletions
+32 -10
View File
@@ -35,6 +35,10 @@ from django import forms
from djangopypi.models import Project, Classifier, Release
class PermissionDeniedError(Exception):
"""The user did not have the priveliges to execute an action."""
class ProjectRegisterForm(forms.Form):
name = forms.CharField()
license = forms.CharField(required=False)
@@ -48,12 +52,30 @@ class ProjectRegisterForm(forms.Form):
version = forms.CharField()
platform = forms.CharField(required=False)
def save(self, classifiers, file=None):
PermissionDeniedError = PermissionDeniedError
def save(self, classifiers, user, file=None):
values = dict(self.cleaned_data)
name = values.pop("name")
name = values["name"]
version = values.pop("version")
platform = values.pop("platform")
project, c = Project.objects.get_or_create(name=name, defaults=values)
platform = values.pop("platform", "UNKNOWN")
values["owner"] = user
try:
project = Project.objects.get(name=name)
except Project.DoesNotExist:
project = Project.objects.create(**values)
else:
# If the project already exists,
# be sure that the current user owns this object.
if project.owner != user:
raise self.PermissionDeniedError(
"%s doesn't own that project." % user.username)
[setattr(project, field_name, field_value)
for field_name, field_value in values.items()]
project.save()
for classifier in classifiers:
project.classifiers.add(
Classifier.objects.get_or_create(name=classifier)[0])
@@ -62,17 +84,17 @@ class ProjectRegisterForm(forms.Form):
# filename, however with .tar.gz files django does the "wrong" thing
# and saves it as project-0.1.2.tar_.gz. So remove it before
# django sees anything.
if file:
try:
previous_entry = Release.objects.get(version=version,
release = Release.objects.get(version=version,
platform=platform, project=project)
if os.path.exists(previous_entry.distribution.path):
os.remove(previous_entry.distribution.path)
previous_entry.delete()
except Release.DoesNotExist:
if os.path.exists(release.distribution.path):
os.remove(release.distribution.path)
release.delete()
except (Release.DoesNotExist, ValueError):
pass
release, created = Release.objects.get_or_create(version=version,
platform=platform,
project=project)
+2
View File
@@ -33,6 +33,7 @@ POSSIBILITY OF SUCH DAMAGE.
import os
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.contrib.auth.models import User
OS_NAMES = (
("aix", "AIX"),
@@ -85,6 +86,7 @@ class Project(models.Model):
description = models.TextField(blank=True)
author_email = models.CharField(max_length=255, blank=True)
classifiers = models.ManyToManyField(Classifier)
owner = models.ForeignKey(User, related_name="projects")
class Meta:
verbose_name = _(u"project")
+35 -3
View File
@@ -31,13 +31,14 @@ POSSIBILITY OF SUCH DAMAGE.
"""
from django.http import Http404, HttpResponse, HttpResponseBadRequest
from django.http import QueryDict
from django.http import QueryDict, HttpResponseForbidden
from django.shortcuts import render_to_response
from djangopypi.models import Project
from djangopypi.forms import ProjectRegisterForm
from django.template import RequestContext
from django.utils.datastructures import MultiValueDict
from django.core.files.uploadedfile import SimpleUploadedFile
from django.contrib.auth import authenticate, login
def parse_weird_post_data(data):
@@ -71,15 +72,46 @@ def parse_weird_post_data(data):
return MultiValueDict(post_data), files
def login_basic_auth(request):
authentication = request.META.get("HTTP_AUTHORIZATION")
if not authentication:
return
(authmeth, auth) = authentication.split(' ', 1)
if authmeth.lower() != "basic":
return
auth = auth.strip().decode("base64")
username, password = auth.split(":", 1)
return authenticate(username=username, password=password)
def authorization_required_response():
response = HttpResponse("Authorization required",
mimetype="text/plain")
response['WWW-Authenticate'] = 'Basic realm="pypi"'
response.status_code = 401
return response
def simple(request, template_name="djangopypi/simple.html"):
if request.method == "POST":
user = login_basic_auth(request)
if not user:
return authorization_required_response()
login(request, user)
if not request.user.is_authenticated():
return HttpResponseForbidden(
"Not logged in, or invalid username/password.")
post_data, files = parse_weird_post_data(request.raw_post_data)
action = post_data.get(":action")
classifiers = post_data.getlist("classifiers")
register_form = ProjectRegisterForm(post_data.copy())
if register_form.is_valid():
return HttpResponse(register_form.save(classifiers,
file=files.get("content")))
try:
register_form.save(classifiers, request.user,
file=files.get("content"))
except register_form.PermissionDeniedError:
return HttpResonseForbidden(
"That project is owned by someone else!")
return HttpResponse("Successfully registered.")
return HttpResponse("ERRORS: %s" % register_form.errors)