aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAsk Solem <askh@modwheel.net>2009-03-21 21:59:34 +0100
committerAsk Solem Hoel <askh@opera.com>2009-03-21 21:59:34 +0100
commit9a3a947bf307b6bc167d7a761dca2f17e84aacdb (patch)
tree351eda90269921f44b5e0105dd424ea1402476b5
parent4335d5430fbcae6035f90495f1ce43d351e3927a (diff)
downloadchishop-9a3a947bf307b6bc167d7a761dca2f17e84aacdb.tar.bz2
chishop-9a3a947bf307b6bc167d7a761dca2f17e84aacdb.tar.xz
chishop-9a3a947bf307b6bc167d7a761dca2f17e84aacdb.zip
Added authentication for register+upload, and projects now has owners.
-rw-r--r--djangopypi/forms.py42
-rw-r--r--djangopypi/models.py2
-rw-r--r--djangopypi/views.py38
3 files changed, 69 insertions, 13 deletions
diff --git a/djangopypi/forms.py b/djangopypi/forms.py
index 3217e7c..90682e2 100644
--- a/djangopypi/forms.py
+++ b/djangopypi/forms.py
@@ -35,6 +35,10 @@ from django import forms
35from djangopypi.models import Project, Classifier, Release 35from djangopypi.models import Project, Classifier, Release
36 36
37 37
38class PermissionDeniedError(Exception):
39 """The user did not have the priveliges to execute an action."""
40
41
38class ProjectRegisterForm(forms.Form): 42class ProjectRegisterForm(forms.Form):
39 name = forms.CharField() 43 name = forms.CharField()
40 license = forms.CharField(required=False) 44 license = forms.CharField(required=False)
@@ -48,12 +52,30 @@ class ProjectRegisterForm(forms.Form):
48 version = forms.CharField() 52 version = forms.CharField()
49 platform = forms.CharField(required=False) 53 platform = forms.CharField(required=False)
50 54
51 def save(self, classifiers, file=None): 55 PermissionDeniedError = PermissionDeniedError
56
57 def save(self, classifiers, user, file=None):
52 values = dict(self.cleaned_data) 58 values = dict(self.cleaned_data)
53 name = values.pop("name") 59 name = values["name"]
54 version = values.pop("version") 60 version = values.pop("version")
55 platform = values.pop("platform") 61 platform = values.pop("platform", "UNKNOWN")
56 project, c = Project.objects.get_or_create(name=name, defaults=values) 62 values["owner"] = user
63
64 try:
65 project = Project.objects.get(name=name)
66 except Project.DoesNotExist:
67 project = Project.objects.create(**values)
68 else:
69 # If the project already exists,
70 # be sure that the current user owns this object.
71 if project.owner != user:
72 raise self.PermissionDeniedError(
73 "%s doesn't own that project." % user.username)
74 [setattr(project, field_name, field_value)
75 for field_name, field_value in values.items()]
76 project.save()
77
78
57 for classifier in classifiers: 79 for classifier in classifiers:
58 project.classifiers.add( 80 project.classifiers.add(
59 Classifier.objects.get_or_create(name=classifier)[0]) 81 Classifier.objects.get_or_create(name=classifier)[0])
@@ -62,17 +84,17 @@ class ProjectRegisterForm(forms.Form):
62 # filename, however with .tar.gz files django does the "wrong" thing 84 # filename, however with .tar.gz files django does the "wrong" thing
63 # and saves it as project-0.1.2.tar_.gz. So remove it before 85 # and saves it as project-0.1.2.tar_.gz. So remove it before
64 # django sees anything. 86 # django sees anything.
87
65 if file: 88 if file:
66 try: 89 try:
67 previous_entry = Release.objects.get(version=version, 90 release = Release.objects.get(version=version,
68 platform=platform, project=project) 91 platform=platform, project=project)
69 if os.path.exists(previous_entry.distribution.path): 92 if os.path.exists(release.distribution.path):
70 os.remove(previous_entry.distribution.path) 93 os.remove(release.distribution.path)
71 previous_entry.delete() 94 release.delete()
72 except Release.DoesNotExist: 95 except (Release.DoesNotExist, ValueError):
73 pass 96 pass
74 97
75
76 release, created = Release.objects.get_or_create(version=version, 98 release, created = Release.objects.get_or_create(version=version,
77 platform=platform, 99 platform=platform,
78 project=project) 100 project=project)
diff --git a/djangopypi/models.py b/djangopypi/models.py
index e94c19e..aa62703 100644
--- a/djangopypi/models.py
+++ b/djangopypi/models.py
@@ -33,6 +33,7 @@ POSSIBILITY OF SUCH DAMAGE.
33import os 33import os
34from django.db import models 34from django.db import models
35from django.utils.translation import ugettext_lazy as _ 35from django.utils.translation import ugettext_lazy as _
36from django.contrib.auth.models import User
36 37
37OS_NAMES = ( 38OS_NAMES = (
38 ("aix", "AIX"), 39 ("aix", "AIX"),
@@ -85,6 +86,7 @@ class Project(models.Model):
85 description = models.TextField(blank=True) 86 description = models.TextField(blank=True)
86 author_email = models.CharField(max_length=255, blank=True) 87 author_email = models.CharField(max_length=255, blank=True)
87 classifiers = models.ManyToManyField(Classifier) 88 classifiers = models.ManyToManyField(Classifier)
89 owner = models.ForeignKey(User, related_name="projects")
88 90
89 class Meta: 91 class Meta:
90 verbose_name = _(u"project") 92 verbose_name = _(u"project")
diff --git a/djangopypi/views.py b/djangopypi/views.py
index b1323fb..368aea4 100644
--- a/djangopypi/views.py
+++ b/djangopypi/views.py
@@ -31,13 +31,14 @@ POSSIBILITY OF SUCH DAMAGE.
31""" 31"""
32 32
33from django.http import Http404, HttpResponse, HttpResponseBadRequest 33from django.http import Http404, HttpResponse, HttpResponseBadRequest
34from django.http import QueryDict 34from django.http import QueryDict, HttpResponseForbidden
35from django.shortcuts import render_to_response 35from django.shortcuts import render_to_response
36from djangopypi.models import Project 36from djangopypi.models import Project
37from djangopypi.forms import ProjectRegisterForm 37from djangopypi.forms import ProjectRegisterForm
38from django.template import RequestContext 38from django.template import RequestContext
39from django.utils.datastructures import MultiValueDict 39from django.utils.datastructures import MultiValueDict
40from django.core.files.uploadedfile import SimpleUploadedFile 40from django.core.files.uploadedfile import SimpleUploadedFile
41from django.contrib.auth import authenticate, login
41 42
42 43
43def parse_weird_post_data(data): 44def parse_weird_post_data(data):
@@ -71,15 +72,46 @@ def parse_weird_post_data(data):
71 return MultiValueDict(post_data), files 72 return MultiValueDict(post_data), files
72 73
73 74
75def login_basic_auth(request):
76 authentication = request.META.get("HTTP_AUTHORIZATION")
77 if not authentication:
78 return
79 (authmeth, auth) = authentication.split(' ', 1)
80 if authmeth.lower() != "basic":
81 return
82 auth = auth.strip().decode("base64")
83 username, password = auth.split(":", 1)
84 return authenticate(username=username, password=password)
85
86
87def authorization_required_response():
88 response = HttpResponse("Authorization required",
89 mimetype="text/plain")
90 response['WWW-Authenticate'] = 'Basic realm="pypi"'
91 response.status_code = 401
92 return response
93
94
74def simple(request, template_name="djangopypi/simple.html"): 95def simple(request, template_name="djangopypi/simple.html"):
75 if request.method == "POST": 96 if request.method == "POST":
97 user = login_basic_auth(request)
98 if not user:
99 return authorization_required_response()
100 login(request, user)
101 if not request.user.is_authenticated():
102 return HttpResponseForbidden(
103 "Not logged in, or invalid username/password.")
76 post_data, files = parse_weird_post_data(request.raw_post_data) 104 post_data, files = parse_weird_post_data(request.raw_post_data)
77 action = post_data.get(":action") 105 action = post_data.get(":action")
78 classifiers = post_data.getlist("classifiers") 106 classifiers = post_data.getlist("classifiers")
79 register_form = ProjectRegisterForm(post_data.copy()) 107 register_form = ProjectRegisterForm(post_data.copy())
80 if register_form.is_valid(): 108 if register_form.is_valid():
81 return HttpResponse(register_form.save(classifiers, 109 try:
82 file=files.get("content"))) 110 register_form.save(classifiers, request.user,
111 file=files.get("content"))
112 except register_form.PermissionDeniedError:
113 return HttpResonseForbidden(
114 "That project is owned by someone else!")
83 return HttpResponse("Successfully registered.") 115 return HttpResponse("Successfully registered.")
84 return HttpResponse("ERRORS: %s" % register_form.errors) 116 return HttpResponse("ERRORS: %s" % register_form.errors)
85 117