Skip to content

Commit

Permalink
Issue mozilla#108: Progress on team application flow, various permiss…
Browse files Browse the repository at this point in the history
…ions fixes
  • Loading branch information
lmorchard committed Feb 19, 2015
1 parent 08f335b commit f976032
Show file tree
Hide file tree
Showing 16 changed files with 708 additions and 62 deletions.
7 changes: 7 additions & 0 deletions badgus/base/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@
base_url=UPLOADS_URL)


def make_random_code(length=7):
"""Generare a random code, using a set of alphanumeric characters that
attempts to avoid ambiguously similar shapes."""
s = '3479acefhjkmnprtuvwxy'
return ''.join([random.choice(s) for x in range(length)])


def show_unicode(obj):
return unicode(obj)
show_unicode.short_description = "Display"
Expand Down
19 changes: 11 additions & 8 deletions badgus/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -666,17 +666,20 @@ def JINJA_CONFIG():

TEAMWORK_BASE_POLICIES = {
"anonymous": (
'badgeteam.list_badgeteam',
'badgeteam.view_badgeteam',
'teams.list_badgeteam',
'teams.view_badgeteam',
),
"authenticated": (
'badgeteam.list_badgeteam',
'badgeteam.view_badgeteam',
'badgeteam.add_badgeteam',
'teams.list_badgeteam',
'teams.view_badgeteam',
'teams.add_badgeteam',
'teams.apply_badgeteam',
),
"apply_to_owners": (
'badgeteam.view_badgeteam',
'badgeteam.change_badgeteam',
'badgeteam.delete_badgeteam',
'teams.view_badgeteam',
'teams.change_badgeteam',
'teams.delete_badgeteam',
'teams.view_badgeteamapplication',
'teams.delete_badgeteamapplication',
)
}
91 changes: 91 additions & 0 deletions badgus/teams/migrations/0002_auto__add_badgeteamapplication.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# -*- coding: utf-8 -*-
from south.utils import datetime_utils as datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models


class Migration(SchemaMigration):

def forwards(self, orm):
# Adding model 'BadgeTeamApplication'
db.create_table(u'teams_badgeteamapplication', (
(u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('comment', self.gf('django.db.models.fields.TextField')()),
('team', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['teamwork.Team'])),
('creator', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'], null=True)),
('created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
('modified', self.gf('django.db.models.fields.DateTimeField')(auto_now=True, blank=True)),
))
db.send_create_signal(u'teams', ['BadgeTeamApplication'])


def backwards(self, orm):
# Deleting model 'BadgeTeamApplication'
db.delete_table(u'teams_badgeteamapplication')


models = {
u'auth.group': {
'Meta': {'object_name': 'Group'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
u'auth.permission': {
'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
u'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
u'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
u'teams.badgeteam': {
'Meta': {'object_name': 'BadgeTeam', '_ormbases': [u'teamwork.Team']},
'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '50'}),
u'team_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['teamwork.Team']", 'unique': 'True', 'primary_key': 'True'})
},
u'teams.badgeteamapplication': {
'Meta': {'object_name': 'BadgeTeamApplication'},
'comment': ('django.db.models.fields.TextField', [], {}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'creator': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'null': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'team': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['teamwork.Team']"})
},
u'teamwork.team': {
'Meta': {'object_name': 'Team'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'founder': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'null': 'True', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'null': 'True', 'db_index': 'True', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128', 'db_index': 'True'})
}
}

complete_apps = ['teams']
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# -*- coding: utf-8 -*-
from south.utils import datetime_utils as datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models


class Migration(SchemaMigration):

def forwards(self, orm):

# Changing field 'BadgeTeamApplication.team'
db.alter_column(u'teams_badgeteamapplication', 'team_id', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['teams.BadgeTeam']))

def backwards(self, orm):

# Changing field 'BadgeTeamApplication.team'
db.alter_column(u'teams_badgeteamapplication', 'team_id', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['teamwork.Team']))

models = {
u'auth.group': {
'Meta': {'object_name': 'Group'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
u'auth.permission': {
'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
u'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
u'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
u'teams.badgeteam': {
'Meta': {'object_name': 'BadgeTeam', '_ormbases': [u'teamwork.Team']},
'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '50'}),
u'team_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['teamwork.Team']", 'unique': 'True', 'primary_key': 'True'})
},
u'teams.badgeteamapplication': {
'Meta': {'object_name': 'BadgeTeamApplication'},
'comment': ('django.db.models.fields.TextField', [], {}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'creator': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'null': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'team': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['teams.BadgeTeam']"})
},
u'teamwork.team': {
'Meta': {'object_name': 'Team'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'founder': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'null': 'True', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'null': 'True', 'db_index': 'True', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128', 'db_index': 'True'})
}
}

complete_apps = ['teams']
118 changes: 92 additions & 26 deletions badgus/teams/models.py
Original file line number Diff line number Diff line change
@@ -1,45 +1,59 @@
from teamwork.models import Team
from badgus.base.utils import slugify, scale_image, mk_upload_to, UPLOADS_FS

from tower import ugettext_lazy as _
import logging
import random

from django.conf import settings
from django.db import models
from django.core.exceptions import ValidationError
from django.core.urlresolvers import reverse

from django.contrib.auth.models import User, Group, Permission
from teamwork.models import TeamManager, Team, Role

from badgus.base.utils import (make_random_code, slugify, scale_image,
mk_upload_to, UPLOADS_FS)

from tower import ugettext_lazy as _


IMG_MAX_SIZE = getattr(settings, "TEAM_IMG_MAX_SIZE", (256, 256))

BADGETEAM_INVALID_NAMES = ('new',)

BADGETEAM_DEFAULT_ROLES = {
"leader": (
'badge.change_badge',
'badge.delete_badge',
'badge.award_badge',
'badge.nominate_badge',
'badge.manage_deferredawards',
'award.change_award',
'award.delete_award',
'nomination.change_nomination',
'nomination.delete_nomination',
'nomination.approve_nomination',
'nomination.reject_nomination',
'deferredaward.grant_deferredaward',
'teams.change_badgeteam',
'teams.invite_badgeteam',
'teams.list_badgeteamapplication',
'teams.view_badgeteamapplication',
'badger.change_badge',
'badger.delete_badge',
'badger.award_badge',
'badger.nominate_badge',
'badger.manage_deferredawards',
'badger.change_award',
'badger.delete_award',
'badger.change_nomination',
'badger.delete_nomination',
'badger.approve_nomination',
'badger.reject_nomination',
'badger.grant_deferredaward',
),
"awarder": (
'badge.award_badge',
'badge.nominate_badge',
'badge.manage_deferredawards',
'award.delete_award',
'nomination.approve_nomination',
'nomination.reject_nomination',
'deferredaward.grant_deferredaward',
'badger.award_badge',
'badger.nominate_badge',
'badger.manage_deferredawards',
'badger.delete_award',
'badger.approve_nomination',
'badger.reject_nomination',
'badger.grant_deferredaward',
)
}


class BadgeTeamManager(TeamManager):
pass


class BadgeTeam(Team):
"""Expansions to the teamwork Team model for user-created teams"""

Expand All @@ -50,10 +64,17 @@ class BadgeTeam(Team):
storage=UPLOADS_FS, upload_to=mk_upload_to('team.png'),
help_text='Image representing this team')

objects = BadgeTeamManager()

class Meta:
permissions = (
('list_badgeteam', 'Can list badge teams'),
('view_badgeteam', 'Can view badge team'),
('invite_badgeteam', 'Can issue invitations join to badge team'),
('apply_badgeteam', 'Can apply to join to badge team'),

('list_badgeteamapplication', 'Can list badge team applications'),
('view_badgeteamapplication', 'Can view badge team applications'),
)

def filter_permissions(self, user, permissions):
Expand All @@ -79,11 +100,56 @@ def save(self, **kwargs):
"""Save the submission, updating slug"""
self.slug = slugify(self.name)

is_new = not self.pk

super(BadgeTeam, self).save(**kwargs)

if is_new:
self.create_default_roles()

def create_default_roles(self):
"""For a new team, create all the Roles from defaults"""
for role_name, perm_names in BADGETEAM_DEFAULT_ROLES.items():
role = Role(name=role_name, team=self)
role.save()
role.add_permissions_by_name(perm_names)

class BadgeTeamInvitation(models.Model):
pass

class BadgeTeamApplication(models.Model):
pass

comment = models.TextField(blank=False)
team = models.ForeignKey(BadgeTeam, blank=False, null=False)
creator = models.ForeignKey(User, blank=False, null=True)
created = models.DateTimeField(auto_now_add=True, blank=False)
modified = models.DateTimeField(auto_now=True, blank=False)

def get_permission_parents(self):
return [ self.team, ]

def get_owner_user(self):
return self.creator

def get_absolute_url(self):
return reverse('teams.team_application_detail', kwargs=dict(
team_slug=self.team.slug, pk=self.pk))


"""
class BadgeTeamInvitation(models.Model):
invitee = models.ForeignKey(User, blank=True, null=True,
related_name='invitee')
claim_code = models.CharField(max_length=32,
default=make_random_code, unique=True, db_index=True)
comment = models.TextField(blank=True)
role = models.ForeignKey(Role, blank=False, null=False)
creator = models.ForeignKey(User, blank=True, null=True)
created = models.DateTimeField(auto_now_add=True, blank=False)
modified = models.DateTimeField(auto_now=True, blank=False)
def get_permission_parents(self):
return [ this.role.team, ]
def get_owner_user(self):
return self.creator
"""
Loading

0 comments on commit f976032

Please sign in to comment.