def can_fork_external(): """ External fork is available if ``FORK_EXTERNAL_MAP`` is set to ``True`` **AND** ``FORK_EXTERNAL_MAP`` is not empty dict. """ if get_config_value('FORK_EXTERNAL_ENABLED') is True and \ get_config_value('FORK_EXTERNAL_MAP'): return True return False
def response(self, request): if get_config_value('FORK_EXTERNAL_ENABLED') is not True: messages.warning(request, _("External forks are disabled")) return redirect(reverse('projector_dashboard')) elif not get_config_value('FORK_EXTERNAL_MAP'): messages.warning(request, _("No external fork forms available")) return redirect(reverse('projector_dashboard')) # Zero at forms list parameter of wizard is only a placeholder - we # change form_list dynamically at wizard's ``process_step`` method wizard = ExternalForkWizard([ExternalForkSourcesForm, 0]) wizard.extra_context['profile'] = request.user.get_profile() return wizard(request)
def create_missing_repositories(sender, **kwargs): """ If :setting:`CREATE_REPOSITORIES` is set to ``True`` and we found :model:`Project` instances without repository we need to create them. """ projects = Project.objects.filter(repository=None) if projects.count() > 0: if kwargs['interactive'] is True: msg = "There are %d projects without repos" % projects.count() logging.info(msg) answer = '' while answer.lower() not in ('yes', 'y', 'no', 'n'): prompt = ('Create missing repos [yes/no, default=yes] ' '[default vcs backend is: %s]' % get_config_value('DEFAULT_VCS_BACKEND')) try: answer = raw_input(prompt).lower() except (KeyboardInterrupt, EOFError): sys.stderr.write('\nInterrupted by user - taken as "no"\n') answer = 'no' if answer == '': answer = 'yes' if answer in ('y', 'yes'): for project in projects: repo = project.create_repository() msg = "[INFO] Created %s" % repo if kwargs['verbosity'] >= 1: print msg elif answer in ('n', 'no'): sys.stderr.write("Answered 'no'. There are still %d missing" " repositories" % projects.count())
def hide_email(value, sub=None): """ Hide all emails founded within given value and replace them with given ``sub``stitution. If no ``sub`` is given, :setting:`PROJECTOR_HIDDEN_EMAIL_SUBSTITUTION` would be used. """ if sub is None: sub = get_config_value('HIDDEN_EMAIL_SUBSTITUTION') value = EMAIL_RE.sub(sub, value) return value
def clean_name(self): name = self.cleaned_data['name'] if name.strip().lower() in get_config_value('BANNED_PROJECT_NAMES'): raise forms.ValidationError(_("This name is restricted")) if Project.objects\ .filter(name=name, author=self.instance.author)\ .exclude(pk=self.instance.pk).exists(): msg = _("You have project with same name already") raise forms.ValidationError(msg) return name
def setup_project_listener(sender, instance, vcs_alias=None, workflow=None, **kwargs): """ Task ``setup_project`` for signals framework. """ if get_config_value('CREATE_PROJECT_ASYNCHRONOUSLY'): func = setup_project_task.delay else: func = setup_project_task logging.info("Calling setup_project task for instance %s" % instance) return func(instance, vcs_alias, workflow)
def can_create(user, request=None): """ Checks if given user can create project. Note that this function will not validate project itself. If :setting:`PROJECTOR_MILIS_BETWEEN_PROJECT_CREATION` is greater than miliseconds since last time this user has created a project then he or she is allowed to create new one. If user is trying to create more project than specified by :setting:`PROJECTOR_MAX_PROJECTS_PER_USER` configuration value then we disallow. If request is given, sends messages. """ def send_error(request, message): if request: messages.error(request, message) try: date = Project.objects.filter(author=user)\ .only('name', 'created_at')\ .order_by('-created_at')[0].created_at delta = datetime.datetime.now() - date milis = delta.seconds * 1000 need_to_wait = get_config_value('MILIS_BETWEEN_PROJECT_CREATION')\ - milis need_to_wait /= 1000 if need_to_wait > 0: send_error( request, _("You would be allowed to create a new " "project in %s seconds" % need_to_wait)) return False except IndexError: pass count = user.project_set.count() too_many = count - get_config_value('MAX_PROJECTS_PER_USER') if too_many > 0: send_error(request, _("You cannot create more projects")) return False return True
def can_create(user, request=None): """ Checks if given user can create project. Note that this function will not validate project itself. If :setting:`PROJECTOR_MILIS_BETWEEN_PROJECT_CREATION` is greater than miliseconds since last time this user has created a project then he or she is allowed to create new one. If user is trying to create more project than specified by :setting:`PROJECTOR_MAX_PROJECTS_PER_USER` configuration value then we disallow. If request is given, sends messages. """ def send_error(request, message): if request: messages.error(request, message) try: date = Project.objects.filter(author=user)\ .only('name', 'created_at')\ .order_by('-created_at')[0].created_at delta = datetime.datetime.now() - date milis = delta.seconds * 1000 need_to_wait = get_config_value('MILIS_BETWEEN_PROJECT_CREATION')\ - milis need_to_wait /= 1000 if need_to_wait > 0: send_error(request, _("You would be allowed to create a new " "project in %s seconds" % need_to_wait)) return False except IndexError: pass count = user.project_set.count() too_many = count - get_config_value('MAX_PROJECTS_PER_USER') if too_many > 0: send_error(request, _("You cannot create more projects")) return False return True
def test_EDITABLE_PERMISSIONS(self): all_perms = set([p.codename for p in get_perms_for_model(Project)]) editable_perms = set(settings.get_config_value('EDITABLE_PERMISSIONS')) self.assertTrue(editable_perms.issubset(all_perms)) self.assertTrue('add_project' not in editable_perms, "EDITABLE_PERMISSIONS cannot contain add_project permission as " "it is global, not object-specific") form = ProjectMembershipPermissionsForm() form_perms = set((c[0] for c in form.fields['permissions'].choices)) self.assertTrue(form_perms == editable_perms) form = ProjectTeamPermissionsForm() form_perms = set((c[0] for c in form.fields['permissions'].choices)) self.assertTrue(form_perms == editable_perms)
def _project_detail_hg(request, project): """ Wrapper for vcs.web.simplevcs.views.hgserve view as before we go any further we need to check permissions. TODO: Should use higher level simplevcs method """ if not is_mercurial(request): msg = "_project_detail_hg called for non mercurial request" logging.error(msg) raise NotMercurialRequest(msg) if request.method not in ('GET', 'POST'): raise NotMercurialRequest("Only GET/POST methods are allowed, got %s" % request.method) PUSH_SSL = get_config_value('HG_PUSH_SSL') and 'true' or 'false' # Allow to read from public projects if project.is_public() and request.method == 'GET': mercurial_info = { 'repo_path': project._get_repo_path(), 'push_ssl': PUSH_SSL, } return get_mercurial_response(request, **mercurial_info) # Check if user have been already authorized or ask to request.user = basic_auth(request) if request.user is None: return ask_basic_auth(request, realm=project.config.basic_realm) if project.is_private() and request.method == 'GET' and\ not request.user.has_perm('can_read_repository', project): raise PermissionDenied("User %s cannot read repository for " "project %s" % (request.user, project)) elif request.method == 'POST' and\ not request.user.has_perm('can_write_to_repository',project): raise PermissionDenied("User %s cannot write to repository " "for project %s" % (request.user, project)) mercurial_info = { 'repo_path': project._get_repo_path(), 'push_ssl': PUSH_SSL, } if request.user and request.user.is_active: mercurial_info['allow_push'] = request.user.username response = get_mercurial_response(request, **mercurial_info) return response
def test_EDITABLE_PERMISSIONS(self): all_perms = set([p.codename for p in get_perms_for_model(Project)]) editable_perms = set(settings.get_config_value('EDITABLE_PERMISSIONS')) self.assertTrue(editable_perms.issubset(all_perms)) self.assertTrue( 'add_project' not in editable_perms, "EDITABLE_PERMISSIONS cannot contain add_project permission as " "it is global, not object-specific") form = ProjectMembershipPermissionsForm() form_perms = set((c[0] for c in form.fields['permissions'].choices)) self.assertTrue(form_perms == editable_perms) form = ProjectTeamPermissionsForm() form_perms = set((c[0] for c in form.fields['permissions'].choices)) self.assertTrue(form_perms == editable_perms)
class ProjectCreateForm(ProjectBaseForm): vcs_alias = forms.ChoiceField( choices=VCS_BACKENDS_CHOICES, label=_('Version Control Backend'), initial=get_config_value('DEFAULT_VCS_BACKEND')) def save(self, commit=True): instance = super(ProjectCreateForm, self).save(commit=False) if commit: instance.save() setup_project.send(sender=Project, instance=instance, vcs_alias=self.cleaned_data.get( 'vcs_alias', None)) for team in self.cleaned_data.get('teams', ()): team.project = instance team.save() return instance
def get_editable_perms(): editable_perms = get_config_value('EDITABLE_PERMISSIONS') perms = [(p.codename, p.name) for p in get_perms_for_model(Project) if p.codename in editable_perms] perms.sort(key=lambda pair: pair[0]) return perms
def __init__(self, *args, **kwargs): form = super(ProjectBaseForm, self).__init__(*args, **kwargs) # Update ``status`` field while creating new task if get_config_value('PRIVATE_ONLY'): self.fields['public'].choices = PUBLIC_RADIO_CHOICES[1:] return form
""" Can be used for forms with model which is related with Project and has ``name`` field which should be unique per project. """ def clean_name(self): name = self.cleaned_data['name'] if self._meta.model.objects\ .filter(project=self.instance.project)\ .filter(name__iexact=name)\ .exists(): raise forms.ValidationError(_("%(class)s with same name already " "defined for this project" % { 'class': self._meta.model.__name__})) return name enabled_backends = get_config_value('ENABLED_VCS_BACKENDS') supported_backends = get_supported_backends() if not set(enabled_backends).issubset(set(supported_backends)): raise ImproperlyConfigured("VCS supports only following backends: %s" % ', '.join(supported_backends)) VCS_BACKENDS_CHOICES = ((key, key) for key in enabled_backends) class ProjectBaseForm(forms.ModelForm): name = forms.CharField(min_length=2, max_length=64, label=_('Name')) public = forms.ChoiceField(label=_("Visibility"), choices=PUBLIC_RADIO_CHOICES, widget=forms.RadioSelect(), initial=u'private', ) class Meta:
def setUp(self): self.sub = get_config_value('HIDDEN_EMAIL_SUBSTITUTION')
def setup_project(instance, vcs_alias=None, workflow=None): """ Creates all necessary related objects like statuses with transitions etc. It simply calls setup and we do this here as in a production it would most probably be called asynchronously (if :setting:`PROJECTOR_CREATE_PROJECT_ASYNCHRONOUSLY` is set to ``True``) :param instance: instance of :model:`Project` :param vcs_alias: alias of vcs backend :param workflow: object or string representing project workflow """ logging.debug("Task setup_project called for instance %s" % instance) if isinstance(workflow, str): workflow = str2obj(workflow) # instance.setup(vcs_alias=vcs_alias, workflow=workflow) # Prepare if parametrs are given. Otherwise assume that preparation # methods have been called already if vcs_alias: instance.set_vcs_alias(vcs_alias) if workflow: instance.set_workflow(workflow) current_state = instance.state # Fire up sub-actions try: # Membership & Team instance.set_memberships() current_state = State.MEMBERSHIPS_CREATED Project.objects.filter(pk=instance.pk).update(state=current_state) # Author permissions instance.set_author_permissions() current_state = State.AUTHOR_PERMISSIONS_CREATED Project.objects.filter(pk=instance.pk).update(state=current_state) instance.create_workflow() current_state = State.WORKFLOW_CREATED Project.objects.filter(pk=instance.pk).update(state=current_state) instance.create_config() current_state = State.CONFIG_CREATED Project.objects.filter(pk=instance.pk).update(state=current_state) if get_config_value("CREATE_REPOSITORIES"): # We spawn sub task here as creating repositories is most crucial # task durgin project setup instance.create_repository(vcs_alias=vcs_alias) current_state = State.REPOSITORY_CREATED Project.objects.filter(pk=instance.pk).update(state=current_state) current_state = State.READY Project.objects.filter(pk=instance.pk).update(state=current_state) except (MemoryError, KeyboardInterrupt): raise except Exception: try: from djangodblog.models import Error Error.objects.create_from_exception() except ImportError: pass Project.objects.filter(pk=instance.pk).update(state=State.ERROR) user_error_text = _("There were some crazy error during project setup " "process") stack = StringIO.StringIO() traceback.print_exc(file=stack) stacktrace = stack.getvalue() logging.error("Error during project setup. Last state was: %s\n" "Stack:\n%s\n" % (current_state, stacktrace)) Project.objects.filter(pk=instance.pk).update(error_text=user_error_text)
def project_create_repository(instance, vcs_alias=None): if get_config_value("CREATE_REPOSITORIES"): instance.create_repository(vcs_alias)
def setup_project(instance, vcs_alias=None, workflow=None): """ Creates all necessary related objects like statuses with transitions etc. It simply calls setup and we do this here as in a production it would most probably be called asynchronously (if :setting:`PROJECTOR_CREATE_PROJECT_ASYNCHRONOUSLY` is set to ``True``) :param instance: instance of :model:`Project` :param vcs_alias: alias of vcs backend :param workflow: object or string representing project workflow """ logging.debug("Task setup_project called for instance %s" % instance) if isinstance(workflow, str): workflow = str2obj(workflow) #instance.setup(vcs_alias=vcs_alias, workflow=workflow) # Prepare if parametrs are given. Otherwise assume that preparation # methods have been called already if vcs_alias: instance.set_vcs_alias(vcs_alias) if workflow: instance.set_workflow(workflow) current_state = instance.state # Fire up sub-actions try: # Membership & Team instance.set_memberships() current_state = State.MEMBERSHIPS_CREATED Project.objects.filter(pk=instance.pk).update(state=current_state) # Author permissions instance.set_author_permissions() current_state = State.AUTHOR_PERMISSIONS_CREATED Project.objects.filter(pk=instance.pk).update(state=current_state) instance.create_workflow() current_state = State.WORKFLOW_CREATED Project.objects.filter(pk=instance.pk).update(state=current_state) instance.create_config() current_state = State.CONFIG_CREATED Project.objects.filter(pk=instance.pk).update(state=current_state) if get_config_value('CREATE_REPOSITORIES'): # We spawn sub task here as creating repositories is most crucial # task durgin project setup instance.create_repository(vcs_alias=vcs_alias) current_state = State.REPOSITORY_CREATED Project.objects.filter(pk=instance.pk).update(state=current_state) current_state = State.READY Project.objects.filter(pk=instance.pk).update(state=current_state) except (MemoryError, KeyboardInterrupt): raise except Exception: try: from djangodblog.models import Error Error.objects.create_from_exception() except ImportError: pass Project.objects.filter(pk=instance.pk).update(state=State.ERROR) user_error_text = _("There were some crazy error during project setup " "process") stack = StringIO.StringIO() traceback.print_exc(file=stack) stacktrace = stack.getvalue() logging.error("Error during project setup. Last state was: %s\n" "Stack:\n%s\n" % (current_state, stacktrace)) Project.objects.filter(pk=instance.pk).update( error_text=user_error_text)
``name`` field which should be unique per project. """ def clean_name(self): name = self.cleaned_data['name'] if self._meta.model.objects\ .filter(project=self.instance.project)\ .filter(name__iexact=name)\ .exists(): raise forms.ValidationError( _("%(class)s with same name already " "defined for this project" % {'class': self._meta.model.__name__})) return name enabled_backends = get_config_value('ENABLED_VCS_BACKENDS') supported_backends = get_supported_backends() if not set(enabled_backends).issubset(set(supported_backends)): raise ImproperlyConfigured("VCS supports only following backends: %s" % ', '.join(supported_backends)) VCS_BACKENDS_CHOICES = ((key, key) for key in enabled_backends) class ProjectBaseForm(forms.ModelForm): name = forms.CharField(min_length=2, max_length=64, label=_('Name')) public = forms.ChoiceField( label=_("Visibility"), choices=PUBLIC_RADIO_CHOICES, widget=forms.RadioSelect(), initial=u'private',
from django.test.client import Client from django.contrib.auth.models import User from projector.tests.base import ProjectorTestCase from projector.models import Project from projector.utils import str2obj from projector.settings import get_config_value statuses = str2obj(get_config_value('DEFAULT_PROJECT_WORKFLOW')).statuses class StatusTest(ProjectorTestCase): def setUp(self): self.client = Client() cred = 'statuser' self.user = User.objects.create( username = cred, email = '*****@*****.**', is_superuser = True, is_active = True) self.user.set_password(cred) self.user.save() self.user._plain_password = cred self.project = Project.objects.create_project( name = 'status-test-project', slug = 'status-test-project', author = self.user, ) def test_name_uniqueness(self): self.client.login(username = self.user.username,
def project_create_repository(instance, vcs_alias=None): if get_config_value('CREATE_REPOSITORIES'): instance.create_repository(vcs_alias)
from django.test.client import Client from django.contrib.auth.models import User from projector.tests.base import ProjectorTestCase from projector.models import Project from projector.utils import str2obj from projector.settings import get_config_value statuses = str2obj(get_config_value('DEFAULT_PROJECT_WORKFLOW')).statuses class StatusTest(ProjectorTestCase): def setUp(self): self.client = Client() cred = 'statuser' self.user = User.objects.create(username=cred, email='*****@*****.**', is_superuser=True, is_active=True) self.user.set_password(cred) self.user.save() self.user._plain_password = cred self.project = Project.objects.create_project( name='status-test-project', slug='status-test-project', author=self.user, ) def test_name_uniqueness(self): self.client.login(username=self.user.username, password=self.user._plain_password)