Example #1
0
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
Example #2
0
    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)
Example #3
0
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
Example #5
0
 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 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
Example #7
0
 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
Example #8
0
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)
Example #9
0
    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
Example #10
0
    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
Example #11
0
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)
Example #12
0
    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)
Example #13
0
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
Example #14
0
    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)
Example #15
0
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
Example #16
0
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
Example #17
0
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
Example #18
0
 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
Example #19
0
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
Example #20
0
 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
Example #21
0
    """
    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')
Example #23
0
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)
Example #24
0
def project_create_repository(instance, vcs_alias=None):
    if get_config_value("CREATE_REPOSITORIES"):
        instance.create_repository(vcs_alias)
Example #25
0
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)
Example #26
0
 def setUp(self):
     self.sub = get_config_value('HIDDEN_EMAIL_SUBSTITUTION')
Example #27
0
    ``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',
Example #28
0
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,
Example #29
0
def project_create_repository(instance, vcs_alias=None):
    if get_config_value('CREATE_REPOSITORIES'):
        instance.create_repository(vcs_alias)
Example #30
0
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)