Skip to content

Commit 2657a19

Browse files
committed
Form and views for EnvironmentVariable CRUD from Project's Admin
1 parent db73802 commit 2657a19

File tree

3 files changed

+119
-11
lines changed

3 files changed

+119
-11
lines changed

readthedocs/projects/forms.py

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# -*- coding: utf-8 -*-
2+
23
"""Project forms."""
34

45
from __future__ import (
@@ -27,19 +28,18 @@
2728
from readthedocs.integrations.models import Integration
2829
from readthedocs.oauth.models import RemoteRepository
2930
from readthedocs.projects import constants
30-
from readthedocs.projects.constants import PUBLIC
3131
from readthedocs.projects.exceptions import ProjectSpamError
3232
from readthedocs.projects.models import (
3333
Domain,
3434
EmailHook,
35+
EnvironmentVariable,
3536
Feature,
3637
Project,
3738
ProjectRelationship,
3839
WebHook,
3940
)
4041
from readthedocs.redirects.models import Redirect
4142

42-
4343
class ProjectForm(forms.ModelForm):
4444

4545
"""
@@ -760,3 +760,41 @@ class Meta(object):
760760
def __init__(self, *args, **kwargs):
761761
super(FeatureForm, self).__init__(*args, **kwargs)
762762
self.fields['feature_id'].choices = Feature.FEATURES
763+
764+
765+
class EnvironmentVariableForm(forms.ModelForm):
766+
767+
"""
768+
Form to add an EnvironmentVariable to a Project.
769+
770+
This limits the name of the variable.
771+
"""
772+
773+
project = forms.CharField(widget=forms.HiddenInput(), required=True)
774+
775+
class Meta(object):
776+
model = EnvironmentVariable
777+
fields = ('name', 'value', 'project')
778+
779+
def __init__(self, *args, **kwargs):
780+
self.project = kwargs.pop('project', None)
781+
super(EnvironmentVariableForm, self).__init__(*args, **kwargs)
782+
783+
def clean_project(self):
784+
return self.project
785+
786+
def clean_name(self):
787+
name = self.cleaned_data['name']
788+
if name.startswith('__'):
789+
raise forms.ValidationError(
790+
_("Variable name can't start with __ (double underscore)"),
791+
)
792+
elif name.startswith('READTHEDOCS'):
793+
raise forms.ValidationError(
794+
_("Variable name can't start with READTHEDOCS"),
795+
)
796+
elif self.project.environmentvariable_set.filter(name=name).exists():
797+
raise forms.ValidationError(
798+
_('There is already a variable with this name for this project'),
799+
)
800+
return name

readthedocs/projects/urls/private.py

Lines changed: 46 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,38 @@
1-
"""Project URLs for authenticated users"""
1+
"""Project URLs for authenticated users."""
2+
3+
from __future__ import (
4+
absolute_import,
5+
division,
6+
print_function,
7+
unicode_literals,
8+
)
29

3-
from __future__ import absolute_import
410
from django.conf.urls import url
511

612
from readthedocs.constants import pattern_opts
13+
from readthedocs.projects.backends.views import ImportDemoView, ImportWizardView
714
from readthedocs.projects.views import private
815
from readthedocs.projects.views.private import (
9-
ProjectDashboard, ImportView,
10-
ProjectUpdate, ProjectAdvancedUpdate,
11-
DomainList, DomainCreate, DomainDelete, DomainUpdate,
12-
IntegrationList, IntegrationCreate, IntegrationDetail, IntegrationDelete,
13-
IntegrationExchangeDetail, IntegrationWebhookSync, ProjectAdvertisingUpdate)
14-
from readthedocs.projects.backends.views import ImportWizardView, ImportDemoView
15-
16+
DomainCreate,
17+
DomainDelete,
18+
DomainList,
19+
DomainUpdate,
20+
EnvironmentVariableCreate,
21+
EnvironmentVariableDelete,
22+
EnvironmentVariableList,
23+
EnvironmentVariableUpdate,
24+
ImportView,
25+
IntegrationCreate,
26+
IntegrationDelete,
27+
IntegrationDetail,
28+
IntegrationExchangeDetail,
29+
IntegrationList,
30+
IntegrationWebhookSync,
31+
ProjectAdvancedUpdate,
32+
ProjectAdvertisingUpdate,
33+
ProjectDashboard,
34+
ProjectUpdate,
35+
)
1636

1737
urlpatterns = [
1838
url(r'^$',
@@ -171,3 +191,20 @@
171191
]
172192

173193
urlpatterns += subproject_urls
194+
195+
environmentvariable_urls = [
196+
url(r'^(?P<project_slug>[-\w]+)/environmentvariables/$',
197+
EnvironmentVariableList.as_view(),
198+
name='projects_environmentvariables'),
199+
url(r'^(?P<project_slug>[-\w]+)/environmentvariables/create/$',
200+
EnvironmentVariableCreate.as_view(),
201+
name='projects_environmentvariables_create'),
202+
url(r'^(?P<project_slug>[-\w]+)/environmentvariables/(?P<environmentvariable_pk>[-\w]+)/edit/$',
203+
EnvironmentVariableUpdate.as_view(),
204+
name='projects_environmentvariables_edit'),
205+
url(r'^(?P<project_slug>[-\w]+)/environmentvariables/(?P<environmentvariable_pk>[-\w]+)/delete/$',
206+
EnvironmentVariableDelete.as_view(),
207+
name='projects_environmentvariables_delete'),
208+
]
209+
210+
urlpatterns += environmentvariable_urls

readthedocs/projects/views/private.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
from readthedocs.projects.forms import (
4444
DomainForm,
4545
EmailHookForm,
46+
EnvironmentVariableForm,
4647
IntegrationForm,
4748
ProjectAdvancedForm,
4849
ProjectAdvertisingForm,
@@ -59,6 +60,7 @@
5960
from readthedocs.projects.models import (
6061
Domain,
6162
EmailHook,
63+
EnvironmentVariable,
6264
Project,
6365
ProjectRelationship,
6466
WebHook,
@@ -873,3 +875,34 @@ def get_queryset(self):
873875

874876
def get_success_url(self):
875877
return reverse('projects_advertising', args=[self.object.slug])
878+
879+
880+
class EnvironmentVariableMixin(ProjectAdminMixin, PrivateViewMixin):
881+
882+
"""Environment Variables to be added when building the Project."""
883+
884+
model = EnvironmentVariable
885+
form_class = EnvironmentVariableForm
886+
lookup_url_kwarg = 'environmentvariable_pk'
887+
888+
def get_success_url(self):
889+
return reverse(
890+
'projects_environment_variables',
891+
args=[self.get_project().slug],
892+
)
893+
894+
895+
class EnvironmentVariableList(EnvironmentVariableMixin, ListViewWithForm):
896+
pass
897+
898+
899+
class EnvironmentVariableCreate(EnvironmentVariableMixin, CreateView):
900+
pass
901+
902+
903+
class EnvironmentVariableUpdate(EnvironmentVariableMixin, UpdateView):
904+
pass
905+
906+
907+
class EnvironmentVariableDelete(EnvironmentVariableMixin, DeleteView):
908+
pass

0 commit comments

Comments
 (0)