Commit c77db977 authored by Sofia Papagiannaki's avatar Sofia Papagiannaki

Progress VII

parent a3ac522a
......@@ -319,152 +319,4 @@ class DjangoBackend(BaseBackend):
g.policies = policies
# g.members = members
g.owners = owners
return self._details(g)
@safe
def submit_application(self, **kwargs):
app = self._create_object(ProjectApplication, **kwargs)
notification = build_notification(
settings.SERVER_EMAIL,
[settings.ADMINS],
_(GROUP_CREATION_SUBJECT) % {'group':app.definition.name},
_('An new project application identified by %(serial)s has been submitted.') % app.serial
)
notification.send()
@safe
def list_applications(self):
return self._list(ProjectAppication)
@safe
def approve_application(self, serial):
app = self._lookup_object(ProjectAppication, serial=serial)
notify = False
if not app.precursor_application:
kwargs = {
'application':app,
'creation_date':datetime.now(),
'last_approval_date':datetime.now(),
}
project = self._create_object(Project, **kwargs)
else:
project = app.precursor_application.project
last_approval_date = project.last_approval_date
if project.is_valid:
project.application = app
project.last_approval_date = datetime.now()
project.save()
else:
raise Exception(_(astakos_messages.INVALID_PROJECT) % project.__dict__)
r = _synchonize_project(project.serial)
if not r.is_success:
# revert to precursor
project.appication = app.precursor_application
if project.application:
project.last_approval_date = last_approval_date
project.save()
r = synchonize_project(project.serial)
if not r.is_success:
raise Exception(_(astakos_messages.QH_SYNC_ERROR))
else:
project.last_application_synced = app
project.save()
sender, recipients, subject, message
notification = build_notification(
settings.SERVER_EMAIL,
[project.owner.email],
_('Project application has been approved on %s alpha2 testing' % SITENAME),
_('Your application request %(serial)s has been apporved.')
)
notification.send()
@safe
def list_projects(self, filter_property=None):
if filter_property:
q = filter_queryset_by_property(
Project.objects.all(),
filter_property
)
return map(lambda o: self._details(o), q)
return self._list(Project)
@safe
def add_project_member(self, serial, user_id, request_user):
project = self._lookup_object(Project, serial=serial)
user = self.lookup_user(user_id)
if not project.owner == request_user:
raise Exception(_(astakos_messages.NOT_PROJECT_OWNER))
if not project.is_alive:
raise Exception(_(astakos_messages.NOT_ALIVE_PROJECT) % project.__dict__)
if len(project.members) + 1 > project.limit_on_members_number:
raise Exception(_(astakos_messages.MEMBER_NUMBER_LIMIT_REACHED))
m = self._lookup_object(ProjectMembership, person=user, project=project)
if m.is_accepted:
return
m.is_accepted = True
m.decision_date = datetime.now()
m.save()
notification = build_notification(
settings.SERVER_EMAIL,
[user.email],
_('Your membership on project %(name)s has been accepted.') % project.definition.__dict__,
_('Your membership on project %(name)s has been accepted.') % project.definition.__dict__,
)
notification.send()
@safe
def remove_project_member(self, serial, user_id, request_user):
project = self._lookup_object(Project, serial=serial)
if not project.is_alive:
raise Exception(_(astakos_messages.NOT_ALIVE_PROJECT) % project.__dict__)
if not project.owner == request_user:
raise Exception(_(astakos_messages.NOT_PROJECT_OWNER))
user = self.lookup_user(user_id)
m = self._lookup_object(ProjectMembership, person=user, project=project)
if not m.is_accepted:
return
m.is_accepted = False
m.decision_date = datetime.now()
m.save()
notification = build_notification(
settings.SERVER_EMAIL,
[user.email],
_('Your membership on project %(name)s has been removed.') % project.definition.__dict__,
_('Your membership on project %(name)s has been removed.') % project.definition.__dict__,
)
notification.send()
@safe
def suspend_project(self, serial):
project = self._lookup_object(Project, serial=serial)
project.suspend()
notification = build_notification(
settings.SERVER_EMAIL,
[project.owner.email],
_('Project %(name)s has been suspended on %s alpha2 testing' % SITENAME),
_('Project %(name)s has been suspended on %s alpha2 testing' % SITENAME)
)
notification.send()
@safe
def terminate_project(self, serial):
project = self._lookup_object(Project, serial=serial)
project.termination()
notification = build_notification(
settings.SERVER_EMAIL,
[project.owner.email],
_('Project %(name)s has been terminated on %s alpha2 testing' % SITENAME),
_('Project %(name)s has been terminated on %s alpha2 testing' % SITENAME)
)
notification.send()
@safe
def synchonize_project(self, serial):
project = self._lookup_object(Project, serial=serial)
project.sync()
\ No newline at end of file
return self._details(g)
\ No newline at end of file
[
{
"model": "im.memberleavepolicy",
"model": "im.memberjoinpolicy",
"pk": 1,
"fields": {
"policy": "auto_accept",
"description": "remove requests are automatically accepted by the system"
"description": "leave requests are automatically accepted by the system"
}
},
{
"model": "im.memberleavepolicy",
"model": "im.memberjoinpolicy",
"pk": 2,
"fields": {
"policy": "owner_accepts",
"description": "remove requests must be accepted by the owner of the project"
"description": "leave requests must be accepted by the owner of the project"
}
},
{
"model": "im.memberleavepolicy",
"model": "im.memberjoinpolicy",
"pk": 3,
"fields": {
"policy": "closed",
"description": "members can not leave the project"
"description": "no member can leave the project"
}
}
]
]
\ No newline at end of file
[
{
"model": "im.memberjoinpolicy",
"model": "im.memberleavepolicy",
"pk": 1,
"fields": {
"policy": "auto_accept",
"description": "leave requests are automatically accepted by the system"
"description": "remove requests are automatically accepted by the system"
}
},
{
"model": "im.memberjoinpolicy",
"model": "im.memberleavepolicy",
"pk": 2,
"fields": {
"policy": "owner_accepts",
"description": "leave requests must be accepted by the owner of the project"
"description": "remove requests must be accepted by the owner of the project"
}
},
{
"model": "im.memberjoinpolicy",
"model": "im.memberleavepolicy",
"pk": 3,
"fields": {
"policy": "closed",
"description": "no member can leave the project"
"description": "members can not leave the project"
}
}
]
......@@ -1019,4 +1019,17 @@ class AddProjectMembersForm(forms.Form):
try:
return self.valid_users
except:
return ()
\ No newline at end of file
return ()
class ProjectMembersSortForm(forms.Form):
sorting = forms.ChoiceField(
label='Sort by',
choices=(('person__email', 'User Id'),
('person__first_name', 'Name'),
('acceptance_date', 'Acceptance date')
),
required=True
)
class ProjectGroupSearchForm(forms.Form):
q = forms.CharField(max_length=200, label='Search project')
\ No newline at end of file
# Copyright 2012 GRNET S.A. All rights reserved.
#
# Redistribution and use in source and binary forms, with or
# without modification, are permitted provided that the following
# conditions are met:
#
# 1. Redistributions of source code must retain the above
# copyright notice, this list of conditions and the following
# disclaimer.
#
# 2. Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials
# provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# The views and conclusions contained in the software and
# documentation are those of the authors and should not be
# interpreted as representing official policies, either expressed
# or implied, of GRNET S.A.
from optparse import make_option
from django.core.management.base import BaseCommand, CommandError
from django.db import transaction
from django.views.generic.create_update import lookup_object
from django.http import Http404
from astakos.im.models import ProjectApplication
@transaction.commit_on_success
class Command(BaseCommand):
args = "<project application id>"
help = "Update project state"
def handle(self, *args, **options):
if len(args) < 1:
raise CommandError("Please provide a group identifier")
try:
id = int(args[0])
except ValueError:
raise CommandError('Invalid id')
else:
try:
# Is it a project application id?
app = lookup_object(ProjectApplication, id, None, None)
except Http404:
raise CommandError('Invalid id')
try:
app.approve()
except BaseException, e:
raise CommandError(e)
\ No newline at end of file
......@@ -52,7 +52,7 @@ class Command(NoArgsCommand):
def handle_noargs(self, **options):
apps = ProjectApplication.objects.select_related().all()
labels = ('id', 'name', 'status')
labels = ('id', 'name', 'state')
columns = (3, 40, 10)
if not options['csv']:
......@@ -65,7 +65,7 @@ class Command(NoArgsCommand):
fields = (
str(app.id),
app.definition.name,
app.status
app.state
)
if options['csv']:
......
......@@ -35,20 +35,19 @@ from optparse import make_option
from django.core.management.base import BaseCommand, CommandError
from django.db import transaction
from django.views.generic.create_update import lookup_object
from django.http import Http404
from astakos.im.models import _lookup_object, ProjectApplication, Project
from astakos.im.models import (
ProjectApplication, Project, PENDING
)
@transaction.commit_on_success
class Command(BaseCommand):
args = "<project application id>"
args = "<project id>"
help = "Update project state"
option_list = BaseCommand.option_list + (
make_option('--approve',
action='store_true',
dest='approve',
default=False,
help="Approve group"),
make_option('--terminate',
action='store_true',
dest='terminate',
......@@ -65,36 +64,20 @@ class Command(BaseCommand):
if len(args) < 1:
raise CommandError("Please provide a group identifier")
app = None
p = None
try:
id = int(args[0])
except ValueError:
raise CommandError('Invalid id')
else:
try:
# Is it a project application id?
app = _lookup_object(ProjectApplication, id=id)
except ProjectApplication.DoesNotExist:
try:
# Is it a project id?
p = _lookup_object(Project, id=id)
except Project.DoesNotExist:
raise CommandError('Invalid id')
try:
if options['approve']:
if not app:
raise CommandError('Project application id is required.')
app.approve()
if app and app.status != 'Pending':
p = app.project
# Is it a project id?
p = lookup_object(Project, id, None, None)
except Http404:
raise CommandError('Invalid id')
else:
if options['terminate']:
p.terminate()
if options['suspend']:
elif options['suspend']:
p.suspend()
except BaseException, e:
import traceback
traceback.print_exc()
raise CommandError(e)
......@@ -47,7 +47,9 @@ EMAIL_CHANGE_REGISTERED = 'Change email request has been regis
You are going to receive a verification email in the new address.'
OBJECT_CREATED = 'The %(verbose_name)s was created successfully.'
MEMBER_JOINED_GROUP = '%(realname)s has been successfully joined the group.'
USER_JOINED_GROUP = '%(realname)s has been successfully joined the group.'
USER_LEFT_GROUP = '%(realname)s has been successfully left the group.'
USER_MEMBERSHIP_REJECTED = '%(realname)s\'s request to join the group has been rejected.'
MEMBER_REMOVED = '%(realname)s has been successfully removed from the group.'
BILLING_ERROR = 'Service response status: %(status)d'
LOGOUT_SUCCESS = 'You have successfully logged out.'
......@@ -57,10 +59,12 @@ GENERIC_ERROR = 'Something wrong has happened. \
MAX_INVITATION_NUMBER_REACHED = 'There are no invitations left.'
GROUP_MAX_PARTICIPANT_NUMBER_REACHED = 'Group maximum participant number has been reached.'
PROJECT_MAX_PARTICIPANT_NUMBER_REACHED = 'Project maximum participant number has been reached.'
NO_APPROVAL_TERMS = 'There are no approval terms.'
PENDING_EMAIL_CHANGE_REQUEST = 'There is already a pending change email request.'
OBJECT_CREATED_FAILED = 'The %(verbose_name)s creation failed: %(reason)s.'
GROUP_JOIN_FAILURE = 'Failed to join group.'
PROJECT_JOIN_FAILURE = 'Failed to join project.'
GROUPKIND_UNKNOWN = 'There is no such a group kind'
NOT_MEMBER = 'User is not member of the group.'
NOT_OWNER = 'User is not a group owner.'
......@@ -136,5 +140,9 @@ MEMBER_NUMBER_LIMIT_REACHED = 'Maximum participant number has been
MEMBER_JOIN_POLICY_CLOSED = 'The project member join policy is cloesd.'
MEMBER_LEAVE_POLICY_CLOSED = 'The project member leave policy is cloesd.'
NOT_MEMBERSHIP_REQUEST = 'There is no such a membership request.'
MEMBERSHIP_REQUEST_EXISTS = 'There is alreary such a membership request.'
NO_APPLICANT = 'Project application requires an applicant. None found.'
ADD_PROJECT_MEMBERS_Q_HELP = 'Add comma separated user emails, eg. user1@user.com, user2@user.com'
\ No newline at end of file
ADD_PROJECT_MEMBERS_Q_HELP = 'Add comma separated user emails, eg. user1@user.com, user2@user.com'
MISSING_IDENTIFIER = 'Missing identifier.'
UNKNOWN_IDENTIFIER = 'Unknown identidier.'
PENDING_MEMBERSHIP_LEAVE = 'Your request is pending acceptio.'
\ No newline at end of file
......@@ -21,15 +21,12 @@ class Migration(SchemaMigration):
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('person', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['im.AstakosUser'])),
('project', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['im.Project'])),
('request_date', self.gf('django.db.models.fields.DateField')(default=datetime.datetime(2012, 12, 9, 11, 4, 41, 210148))),
('request_date', self.gf('django.db.models.fields.DateField')(default=datetime.datetime(2012, 12, 10, 13, 48, 24, 819868))),
('removal_date', self.gf('django.db.models.fields.DateField')(null=True)),
('rejection_date', self.gf('django.db.models.fields.DateField')(null=True)),
))
db.send_create_signal('im', ['ProjectMembershipHistory'])
# Adding unique constraint on 'ProjectMembershipHistory', fields ['person', 'project']
db.create_unique('im_projectmembershiphistory', ['person_id', 'project_id'])
# Adding model 'ProjectApplication'
db.create_table('im_projectapplication', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
......@@ -39,6 +36,7 @@ class Migration(SchemaMigration):
('definition', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['im.ProjectDefinition'], unique=True)),
('issue_date', self.gf('django.db.models.fields.DateTimeField')()),
('precursor_application', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['im.ProjectApplication'], unique=True, null=True, blank=True)),
('state', self.gf('django.db.models.fields.CharField')(default='Unknown', max_length=80)),
))
db.send_create_signal('im', ['ProjectApplication'])
......@@ -60,8 +58,9 @@ class Migration(SchemaMigration):
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('person', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['im.AstakosUser'])),
('project', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['im.Project'])),
('request_date', self.gf('django.db.models.fields.DateField')(default=datetime.datetime(2012, 12, 9, 11, 4, 41, 209391))),
('request_date', self.gf('django.db.models.fields.DateField')(default=datetime.datetime(2012, 12, 10, 13, 48, 24, 819045))),
('acceptance_date', self.gf('django.db.models.fields.DateField')(null=True, db_index=True)),
('leave_request_date', self.gf('django.db.models.fields.DateField')(null=True)),
))
db.send_create_signal('im', ['ProjectMembership'])
......@@ -112,9 +111,6 @@ class Migration(SchemaMigration):
# Removing unique constraint on 'ProjectMembership', fields ['person', 'project']
db.delete_unique('im_projectmembership', ['person_id', 'project_id'])
# Removing unique constraint on 'ProjectMembershipHistory', fields ['person', 'project']
db.delete_unique('im_projectmembershiphistory', ['person_id', 'project_id'])
# Deleting model 'MemberJoinPolicy'
db.delete_table('im_memberjoinpolicy')
......@@ -185,14 +181,14 @@ class Migration(SchemaMigration):
},
'im.approvalterms': {
'Meta': {'object_name': 'ApprovalTerms'},
'date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2012, 12, 9, 11, 4, 41, 198398)', 'db_index': 'True'}),
'date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2012, 12, 10, 13, 48, 24, 808772)', 'db_index': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'location': ('django.db.models.fields.CharField', [], {'max_length': '255'})
},
'im.astakosgroup': {
'Meta': {'object_name': 'AstakosGroup', '_ormbases': ['auth.Group']},
'approval_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
'creation_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2012, 12, 9, 11, 4, 41, 189261)'}),
'creation_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2012, 12, 10, 13, 48, 24, 801104)'}),
'desc': ('django.db.models.fields.TextField', [], {'null': 'True'}),
'estimated_participants': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True', 'blank': 'True'}),
'expiration_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
......@@ -258,7 +254,7 @@ class Migration(SchemaMigration):
'activation_key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40', 'db_index': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'new_email_address': ('django.db.models.fields.EmailField', [], {'max_length': '75'}),
'requested_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2012, 12, 9, 11, 4, 41, 200303)'}),
'requested_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2012, 12, 10, 13, 48, 24, 810599)'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'emailchange_user'", 'unique': 'True', 'to': "orm['im.AstakosUser']"})
},
'im.groupkind': {
......@@ -292,7 +288,7 @@ class Migration(SchemaMigration):
'im.membership': {
'Meta': {'unique_together': "(('person', 'group'),)", 'object_name': 'Membership'},
'date_joined': ('django.db.models.fields.DateField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
'date_requested': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2012, 12, 9, 11, 4, 41, 196071)', 'blank': 'True'}),
'date_requested': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2012, 12, 10, 13, 48, 24, 806557)', 'blank': 'True'}),
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['im.AstakosGroup']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['im.AstakosUser']"})
......@@ -330,7 +326,8 @@ class Migration(SchemaMigration):
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'issue_date': ('django.db.models.fields.DateTimeField', [], {}),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'own_project_applications'", 'to': "orm['im.AstakosUser']"}),
'precursor_application': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['im.ProjectApplication']", 'unique': 'True', 'null': 'True', 'blank': 'True'})
'precursor_application': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['im.ProjectApplication']", 'unique': 'True', 'null': 'True', 'blank': 'True'}),
'state': ('django.db.models.fields.CharField', [], {'default': "'Unknown'", 'max_length': '80'})
},
'im.projectdefinition': {
'Meta': {'object_name': 'ProjectDefinition'},
......@@ -349,18 +346,19 @@ class Migration(SchemaMigration):
'Meta': {'unique_together': "(('person', 'project'),)", 'object_name': 'ProjectMembership'},
'acceptance_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'db_index': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'leave_request_date': ('django.db.models.fields.DateField', [], {'null': 'True'}),
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['im.AstakosUser']"}),
'project': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['im.Project']"}),
'request_date': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2012, 12, 9, 11, 4, 41, 209391)'})
'request_date': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2012, 12, 10, 13, 48, 24, 819045)'})
},
'im.projectmembershiphistory': {
'Meta': {'unique_together': "(('person', 'project'),)", 'object_name': 'ProjectMembershipHistory'},
'Meta': {'object_name': 'ProjectMembershipHistory'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['im.AstakosUser']"}),
'project': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['im.Project']"}),
'rejection_date': ('django.db.models.fields.DateField', [], {'null': 'True'}),
'removal_date': ('django.db.models.fields.DateField', [], {'null': 'True'}),
'request_date': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2012, 12, 9, 11, 4, 41, 210148)'})
'request_date': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2012, 12, 10, 13, 48, 24, 819868)'})
},
'im.projectresourcegrant': {
'Meta': {'unique_together': "(('resource', 'project_definition'),)", 'object_name': 'ProjectResourceGrant'},
......
......@@ -61,6 +61,9 @@ from django.contrib.auth.tokens import default_token_generator
from django.conf import settings
from django.utils.importlib import import_module
from django.core.validators import email_re
from django.core.exceptions import PermissionDenied
from django.views.generic.create_update import lookup_object
from django.core.exceptions import ObjectDoesNotExist
from astakos.im.settings import (
DEFAULT_USER_LEVEL, INVITATIONS_PER_LEVEL,
......@@ -85,6 +88,8 @@ logger = logging.getLogger(__name__)
DEFAULT_CONTENT_TYPE = None
_content_type = None
PENDING, APPROVED, REPLACED, UNKNOWN = 'Pending', 'Approved', 'Replaced', 'Unknown'
def get_content_type():
global _content_type
if _content_type is not None:
......@@ -1030,28 +1035,52 @@ class MemberLeavePolicy(models.Model):
_auto_accept_join = False
def get_auto_accept_join():
global _auto_accept
if _auto_accept is not False:
return _auto_accept
global _auto_accept_join
if _auto_accept_join is not False:
return _auto_accept_join
try:
auto_accept = MemberJoinPolicy.objects.get(policy='auto_accept')
except:
auto_accept = None
_auto_accept = auto_accept
_auto_accept_join = auto_accept
return auto_accept
_closed_join = False
def get_closed_join():
global _closed_join
if _closed_join is not False:
return _closed_join
try:
closed = MemberJoinPolicy.objects.get(policy='closed')
except:
closed = None
_closed_join = closed
return closed
_auto_accept_leave = False
def get_auto_accept_leave():
global _auto_accept
if _auto_accept is not False:
return _auto_accept
global _auto_accept_leave