From 26cff59ef08f1c117ba6fb37245b13e3eb76f572 Mon Sep 17 00:00:00 2001 From: Michael DeHaan Date: Sun, 7 Apr 2013 22:17:33 -0400 Subject: [PATCH] Use of validate() method on serializer to implement write-once fields. --- lib/main/models/__init__.py | 9 +++------ lib/main/serializers.py | 26 ++++++++++++++++++-------- lib/main/tests/projects.py | 23 +++++++++++------------ 3 files changed, 32 insertions(+), 26 deletions(-) diff --git a/lib/main/models/__init__.py b/lib/main/models/__init__.py index e663524f60..9c4932c636 100644 --- a/lib/main/models/__init__.py +++ b/lib/main/models/__init__.py @@ -538,14 +538,11 @@ class Credential(CommonModelNameNotUnique): return True if user == obj.user: return True - + if obj.user: - print "user orgs = " , obj.user.organizations.all() - print "user org admins = " , [ x.admins.all() for x in obj.user.organizations.all() ] if (obj.user.organizations.filter(admins__in = [user]).count()): return True if obj.team: - print "ADMINS OF TEAM=%s" % obj.team.organization.admins.all() if user in obj.team.organization.admins.all(): return True return False @@ -554,7 +551,7 @@ class Credential(CommonModelNameNotUnique): def can_user_read(cls, user, obj): ''' a user can be read if they are on the same team or can be administrated ''' return cls.can_user_administrate(user, obj) - + @classmethod def can_user_add(cls, user, data): if user.is_superuser: @@ -815,7 +812,7 @@ class LaunchJobStatusEvent(models.Model): event = models.CharField(max_length=100, choices=EVENT_TYPES) event_data = JSONField(blank=True, default='') host = models.ForeignKey('Host', blank=True, null=True, default=None, on_delete=SET_NULL, related_name='launch_job_status_events') - + # FIXME: Connect host based on event_data. # TODO: reporting (MPD) diff --git a/lib/main/serializers.py b/lib/main/serializers.py index bcab1b9208..441ccd22a4 100644 --- a/lib/main/serializers.py +++ b/lib/main/serializers.py @@ -49,14 +49,14 @@ class OrganizationSerializer(BaseSerializer): users = reverse(lib.urls.views_OrganizationsUsersList, args=(obj.pk,)), admins = reverse(lib.urls.views_OrganizationsAdminsList, args=(obj.pk,)), tags = reverse(lib.urls.views_OrganizationsTagsList, args=(obj.pk,)) - ) + ) class AuditTrailSerializer(BaseSerializer): - + # add the URL and related resources url = serializers.CharField(source='get_absolute_url', read_only=True) related = serializers.SerializerMethodField('get_related') - + class Meta: model = AuditTrail fields = ('url', 'id', 'modified_by', 'delta', 'detail', 'comment') @@ -80,7 +80,7 @@ class ProjectSerializer(BaseSerializer): class InventorySerializer(BaseSerializer): - + # add the URL and related resources url = serializers.CharField(source='get_absolute_url', read_only=True) related = serializers.SerializerMethodField('get_related') @@ -145,7 +145,7 @@ class CredentialSerializer(BaseSerializer): class Meta: model = Credential fields = ( - 'url', 'id', 'related', 'name', 'description', 'creation_date', + 'url', 'id', 'related', 'name', 'description', 'creation_date', 'default_username', 'ssh_key_data', 'ssh_key_unlock', 'ssh_password', 'sudo_password', 'user', 'team' ) @@ -154,12 +154,22 @@ class CredentialSerializer(BaseSerializer): # FIXME: add related resources: projects, users, organizations return dict() + def validate(self, attrs): + ''' some fields cannot be changed once written ''' + if self.object is not None: + # this is an update + if self.object.user != attrs['user']: + raise serializers.ValidationError("user cannot be changed") + if self.object.team != attrs['team']: + raise serializers.ValidationError("team cannot be changed") + return attrs + class UserSerializer(BaseSerializer): - + # add the URL and related resources url = serializers.SerializerMethodField('get_absolute_url_override') related = serializers.SerializerMethodField('get_related') - + class Meta: model = User fields = ('url', 'id', 'username', 'first_name', 'last_name', 'email', 'is_active', 'is_superuser', 'related') @@ -177,7 +187,7 @@ class UserSerializer(BaseSerializer): class TagSerializer(BaseSerializer): - + # add the URL and related resources url = serializers.CharField(source='get_absolute_url', read_only=True) related = serializers.SerializerMethodField('get_related') diff --git a/lib/main/tests/projects.py b/lib/main/tests/projects.py index 54ae0765c0..345770f511 100644 --- a/lib/main/tests/projects.py +++ b/lib/main/tests/projects.py @@ -282,9 +282,6 @@ class ProjectsTest(BaseTest): other_creds = '/api/v1/users/%s/credentials/' % other.pk team_creds = '/api/v1/teams/%s/credentials/' % team.pk - #for x in other.organizations.all(): - # print x.admins.all() - new_credentials = dict( name = 'credential', project = Project.objects.all()[0].pk, @@ -333,24 +330,26 @@ class ProjectsTest(BaseTest): # can edit a credential cred_user = Credential.objects.get(pk=cred_user) cred_team = Credential.objects.get(pk=cred_team) - d_cred_user = dict(id=cred_user.pk, name='x', sudo_password='blippy') - #print "user of cred_user = %s" % cred_user.user - d_cred_team = dict(id=cred_team.pk, name='x', sudo_password='blippy') + d_cred_user = dict(id=cred_user.pk, name='x', sudo_password='blippy', user=cred_user.pk) + d_cred_user2 = dict(id=cred_user.pk, name='x', sudo_password='blippy', user=User.objects.get(pk=1).pk) + d_cred_team = dict(id=cred_team.pk, name='x', sudo_password='blippy', team=cred_team.pk) edit_creds1 = '/api/v1/credentials/%s/' % cred_user.pk edit_creds2 = '/api/v1/credentials/%s/' % cred_team.pk - #print "TEST ORG = %s" % cred_team.organization - #print "TEST ADMINS = %s" % cred_team.organization.admins.all() self.put(edit_creds1, data=d_cred_user, expect=401) self.put(edit_creds1, data=d_cred_user, expect=401, auth=self.get_invalid_credentials()) self.put(edit_creds1, data=d_cred_user, expect=200, auth=self.get_super_credentials()) - # org admin should NOT be able to get at user credentials. superuser can. - self.put(edit_creds1, data=d_cred_user, expect=403, auth=self.get_normal_credentials()) - self.put(edit_creds1, data=d_cred_user, expect=403, auth=self.get_other_credentials()) + self.put(edit_creds1, data=d_cred_user, expect=200, auth=self.get_normal_credentials()) + # editing a credential to edit the user record is not legal, this is a test of the .validate + # method on the serializer to allow 'write once' fields + self.put(edit_creds1, data=d_cred_user2, expect=400, auth=self.get_normal_credentials()) + self.put(edit_creds1, data=d_cred_user, expect=200, auth=self.get_other_credentials()) + self.put(edit_creds2, data=d_cred_team, expect=401) self.put(edit_creds2, data=d_cred_team, expect=401, auth=self.get_invalid_credentials()) + cred_team = Credential.objects.get(pk=cred_team.pk) self.put(edit_creds2, data=d_cred_team, expect=200, auth=self.get_super_credentials()) - #print "TEST NOW" + cred_team = Credential.objects.get(pk=cred_team.pk) self.put(edit_creds2, data=d_cred_team, expect=200, auth=self.get_normal_credentials()) self.put(edit_creds2, data=d_cred_team, expect=403, auth=self.get_other_credentials())