示例#1
0
    def _validate_and_update_version(self, obj):
        current_version = None
        if obj.id:
            current_version = type(obj).objects.model.objects.get(
                id=obj.id).version

            # Extract param version
            param_version = self._extract_param_version()
            if not self._validate_param_version(param_version,
                                                current_version):
                raise exc.WrongArguments(
                    {"version": _("The version parameter is not valid")})

            if current_version != param_version:
                diff_versions = current_version - param_version

                modifying_fields = set(self.request.DATA.keys())
                if "version" in modifying_fields:
                    modifying_fields.remove("version")

                modified_fields = set(get_modified_fields(obj, diff_versions))
                if "version" in modifying_fields:
                    modified_fields.remove("version")

                both_modified = modifying_fields & modified_fields

                if both_modified:
                    raise exc.WrongArguments({
                        "version":
                        _("The version doesn't match with the current one")
                    })

            obj.version = models.F('version') + 1
示例#2
0
    def cancel(self, request, pk=None):
        """
        Cancel an account via token
        """
        validator = validators.CancelAccountValidator(data=request.DATA,
                                                      many=False)
        if not validator.is_valid():
            raise exc.WrongArguments(
                _("Invalid, are you sure the token is correct?"))

        try:
            max_age_cancel_account = getattr(settings,
                                             "MAX_AGE_CANCEL_ACCOUNT", None)
            user = get_user_for_token(validator.data["cancel_token"],
                                      "cancel_account",
                                      max_age=max_age_cancel_account)

        except exc.NotAuthenticated:
            raise exc.WrongArguments(
                _("Invalid, are you sure the token is correct?"))

        if not user.is_active:
            raise exc.WrongArguments(
                _("Invalid, are you sure the token is correct?"))

        user.cancel()
        return response.NoContent()
示例#3
0
    def change_email(self, request, pk=None):
        """
        Verify the email change to current logged user.
        """
        validator = validators.ChangeEmailValidator(data=request.DATA,
                                                    many=False)
        if not validator.is_valid():
            raise exc.WrongArguments(
                _("Invalid, are you sure the token is correct and you "
                  "didn't use it before?"))

        try:
            user = models.User.objects.get(
                email_token=validator.data["email_token"])
        except models.User.DoesNotExist:
            raise exc.WrongArguments(
                _("Invalid, are you sure the token is correct and you "
                  "didn't use it before?"))

        self.check_permissions(request, "change_email", user)

        old_email = user.email
        new_email = user.new_email

        user.email = new_email
        user.new_email = None
        user.email_token = None
        user.save(update_fields=["email", "new_email", "email_token"])

        user_change_email_signal.send(sender=user.__class__,
                                      user=user,
                                      old_email=old_email,
                                      new_email=new_email)

        return response.NoContent()
示例#4
0
def private_register_for_new_user(token: str, username: str, email: str,
                                  full_name: str, password: str):
    """
    Given a inviation token, try register new user matching
    the invitation token.
    """
    is_registered, reason = is_user_already_registered(username=username,
                                                       email=email)
    if is_registered:
        raise exc.WrongArguments(reason)

    user_model = get_user_model()
    user = user_model(username=username, email=email, full_name=full_name)

    user.set_password(password)
    try:
        user.save()
    except IntegrityError:
        raise exc.WrongArguments(_("Error on creating new user."))

    membership = get_membership_by_token(token)
    membership.user = user
    membership.save(update_fields=["user"])
    send_register_email(user)
    user_registered_signal.send(sender=user.__class__, user=user)

    return user
示例#5
0
    def change_password(self, request, pk=None):
        """
        Change password to current logged user.
        """
        self.check_permissions(request, "change_password", None)

        current_password = request.DATA.get("current_password")
        password = request.DATA.get("password")

        # NOTE: GitHub users have no password yet (request.user.passwor == '') so
        #       current_password can be None
        if not current_password and request.user.password:
            raise exc.WrongArguments(_("Current password parameter needed"))

        if not password:
            raise exc.WrongArguments(_("New password parameter needed"))

        if len(password) < 6:
            raise exc.WrongArguments(
                _("Invalid password length at least 6 charaters needed"))

        if current_password and not request.user.check_password(
                current_password):
            raise exc.WrongArguments(_("Invalid current password"))

        request.user.set_password(password)
        request.user.save(update_fields=["password"])
        return response.NoContent()
示例#6
0
    def list_users(self, request, *args, **kwargs):
        self.check_permissions(request, "list_users", None)

        url = request.DATA.get('url', None)
        token = self._get_token(request)
        project_id = request.DATA.get('project', None)

        if not project_id:
            raise exc.WrongArguments(_("The project param is needed"))
        if not url:
            raise exc.WrongArguments(_("The url param is needed"))

        importer = JiraNormalImporter(request.user, url, token)
        users = importer.list_users()
        for user in users:
            user['user'] = None
            if not user['email']:
                continue

            try:
                Tina_user = User.objects.get(email=user['email'])
            except User.DoesNotExist:
                continue

            user['user'] = {
                'id': Tina_user.id,
                'full_name': Tina_user.get_full_name(),
                'gravatar_id': get_user_gravatar_id(Tina_user),
                'photo': get_user_photo_url(Tina_user),
            }
        return response.Ok(users)
示例#7
0
def public_register(username: str, password: str, email: str, full_name: str):
    """
    Given a parsed parameters, try register a new user
    knowing that it follows a public register flow.

    This can raise `exc.IntegrityError` exceptions in
    case of conflics found.

    :returns: User
    """

    is_registered, reason = is_user_already_registered(username=username,
                                                       email=email)
    if is_registered:
        raise exc.WrongArguments(reason)

    user_model = get_user_model()
    user = user_model(username=username,
                      email=email,
                      full_name=full_name,
                      read_new_terms=True)
    user.set_password(password)
    try:
        user.save()
    except IntegrityError:
        raise exc.WrongArguments(_("User is already registered."))

    send_register_email(user)
    user_registered_signal.send(sender=user.__class__, user=user)
    return user
示例#8
0
def validate_project_transfer_token(token, project, user):
    signer = signing.TimestampSigner()

    if project.transfer_token != token:
        raise exc.WrongArguments(_("Token is invalid"))

    try:
        value = signer.unsign(token, max_age=datetime.timedelta(days=7))
    except signing.SignatureExpired:
        raise exc.WrongArguments(_("Token has expired"))
    except signing.BadSignature:
        raise exc.WrongArguments(_("Token is invalid"))

    if str(value) != str(user.id):
        raise exc.WrongArguments(_("Token is invalid"))
示例#9
0
    def pre_save(self, obj):
        if not obj.id:
            obj.content_type = self.get_content_type()
            obj.owner = self.request.user
            obj.size = obj.attached_file.size
            obj.name = path.basename(obj.attached_file.name)

        if obj.content_object is None:
            raise exc.WrongArguments(_("Object id issue isn't exists"))

        if obj.project_id != obj.content_object.project_id:
            raise exc.WrongArguments(
                _("Project ID not matches between object and project"))

        super().pre_save(obj)
示例#10
0
    def import_project(self, request, *args, **kwargs):
        self.check_permissions(request, "import_project", None)

        token = request.DATA.get('token', None)
        project_id = request.DATA.get('project', None)
        if not project_id:
            raise exc.WrongArguments(_("The project param is needed"))

        options = {
            "name": request.DATA.get('name', None),
            "description": request.DATA.get('description', None),
            "template": request.DATA.get('template', "scrum"),
            "users_bindings": resolve_users_bindings(request.DATA.get("users_bindings", {})),
            "keep_external_reference": request.DATA.get("keep_external_reference", False),
            "is_private": request.DATA.get("is_private", False),
        }

        if settings.CELERY_ENABLED:
            task = tasks.import_project.delay(request.user.id, token, project_id, options)
            return response.Accepted({"task_id": task.id})

        importer = AsanaImporter(request.user, token)
        project = importer.import_project(project_id, options)
        project_data = {
            "slug": project.slug,
            "my_permissions": ["view_us"],
            "is_backlog_activated": project.is_backlog_activated,
            "is_kanban_activated": project.is_kanban_activated,
        }

        return response.Ok(project_data)
示例#11
0
    def remove_user_from_all_my_projects(self, request, **kwargs):
        private_only = request.DATA.get('private_only', False)

        user_id = request.DATA.get('user', None)
        if user_id is None:
            raise exc.WrongArguments(_("Invalid user id"))

        user_model = apps.get_model("users", "User")
        try:
            user = user_model.objects.get(id=user_id)
        except user_model.DoesNotExist:
            return response.BadRequest(_("The user doesn't exist"))

        memberships = models.Membership.objects.filter(
            project__owner=request.user, user=user)
        if private_only:
            memberships = memberships.filter(project__is_private=True)

        errors = []
        for membership in memberships:
            if not services.can_user_leave_project(user, membership.project):
                errors.append(membership.project.name)

        if len(errors) > 0:
            error = _(
                "This user can't be removed from the following projects, because would "
                "leave them without any active admin: {}.".format(
                    ", ".join(errors)))
            return response.BadRequest(error)

        memberships.delete()

        return response.NoContent()
示例#12
0
    def pre_conditions_on_save(self, obj):
        super().pre_conditions_on_save(obj)

        if obj.status and obj.status.project != obj.project:
            raise exc.WrongArguments(
                _("You don't have permissions to set this status to this epic."
                  ))
示例#13
0
    def auth_url(self, request, *args, **kwargs):
        self.check_permissions(request, "auth_url", None)
        jira_url = request.QUERY_PARAMS.get('url', None)

        if not jira_url:
            raise exc.WrongArguments(_("The url param is needed"))

        try:
            (oauth_token, oauth_secret, url) = JiraNormalImporter.get_auth_url(
                jira_url,
                settings.IMPORTERS.get('jira', {}).get('consumer_key', None),
                settings.IMPORTERS.get('jira', {}).get('cert', None),
                True
            )
        except exceptions.InvalidServiceConfiguration:
            raise exc.BadRequest(_("Invalid Jira server configuration."))

        (auth_data, created) = AuthData.objects.get_or_create(
            user=request.user,
            key="jira-oauth",
            defaults={
                "value": uuid.uuid4().hex,
                "extra": {},
            }
        )
        auth_data.extra = {
            "oauth_token": oauth_token,
            "oauth_secret": oauth_secret,
            "url": jira_url,
        }
        auth_data.save()

        return response.Ok({"url": url})
示例#14
0
    def authorize(self, request, *args, **kwargs):
        self.check_permissions(request, "authorize", None)

        try:
            oauth_data = request.user.auth_data.get(key="jira-oauth")
            oauth_verifier = request.DATA.get("oauth_verifier", None)
            oauth_token = oauth_data.extra['oauth_token']
            oauth_secret = oauth_data.extra['oauth_secret']
            server_url = oauth_data.extra['url']
            oauth_data.delete()

            jira_token = JiraNormalImporter.get_access_token(
                server_url,
                settings.IMPORTERS.get('jira', {}).get('consumer_key', None),
                settings.IMPORTERS.get('jira', {}).get('cert', None),
                oauth_token,
                oauth_secret,
                oauth_verifier,
                False
            )
        except Exception as e:
            raise exc.WrongArguments(_("Invalid or expired auth token"))

        return response.Ok({
            "token": jira_token['access_token'] + "." + jira_token['access_token_secret'],
            "url": server_url
        })
示例#15
0
    def list_users(self, request, *args, **kwargs):
        self.check_permissions(request, "list_users", None)

        token = request.DATA.get('token', None)
        project_id = request.DATA.get('project', None)

        if not project_id:
            raise exc.WrongArguments(_("The project param is needed"))

        importer = AsanaImporter(request.user, token)

        try:
            users = importer.list_users(project_id)
        except exceptions.InvalidRequest:
            raise exc.BadRequest(_('Invalid Asana API request'))
        except exceptions.FailedRequest:
            raise exc.BadRequest(_('Failed to make the request to Asana API'))

        for user in users:
            if user['detected_user']:
                user['user'] = {
                    'id': user['detected_user'].id,
                    'full_name': user['detected_user'].get_full_name(),
                    'gravatar_id': get_user_gravatar_id(user['detected_user']),
                    'photo': get_user_photo_url(user['detected_user']),
                }
            del(user['detected_user'])
        return response.Ok(users)
示例#16
0
    def render(self, request, **kwargs):
        content = request.DATA.get("content", None)
        project_id = request.DATA.get("project_id", None)

        if not content:
            raise exc.WrongArguments(
                {"content": _("'content' parameter is mandatory")})

        if not project_id:
            raise exc.WrongArguments(
                {"project_id": _("'project_id' parameter is mandatory")})

        project = get_object_or_404(Project, pk=project_id)

        self.check_permissions(request, "render", project)

        data = mdrender(project, content)
        return response.Ok({"data": data})
示例#17
0
    def _extract_param_version(self):
        param_version = self.request.DATA.get('version', None)
        try:
            param_version = param_version and int(param_version)
        except (ValueError, TypeError):
            raise exc.WrongArguments(
                {"version": _("The version must be an integer")})

        return param_version
示例#18
0
    def transfer_reject(self, request, pk=None):
        token = request.DATA.get('token', None)
        if token is None:
            raise exc.WrongArguments(_("Invalid token"))

        project = self.get_object()
        self.check_permissions(request, "transfer_reject", project)

        reason = request.DATA.get('reason', None)
        services.reject_project_transfer(project, request.user, token, reason)
        return response.Ok()
示例#19
0
    def change_avatar(self, request):
        """
        Change avatar to current logged user.
        """
        self.check_permissions(request, "change_avatar", None)

        avatar = request.FILES.get('avatar', None)

        if not avatar:
            raise exc.WrongArguments(_("Incomplete arguments"))

        try:
            pil_image(avatar)
        except Exception:
            raise exc.WrongArguments(_("Invalid image format"))

        request.user.photo = avatar
        request.user.save(update_fields=["photo"])
        user_data = self.admin_serializer_class(request.user).data

        return response.Ok(user_data)
示例#20
0
    def change_password_from_recovery(self, request, pk=None):
        """
        Change password with token (from password recovery step).
        """

        self.check_permissions(request, "change_password_from_recovery", None)

        validator = validators.RecoveryValidator(data=request.DATA, many=False)
        if not validator.is_valid():
            raise exc.WrongArguments(_("Token is invalid"))

        try:
            user = models.User.objects.get(token=validator.data["token"])
        except models.User.DoesNotExist:
            raise exc.WrongArguments(_("Token is invalid"))

        user.set_password(validator.data["password"])
        user.token = None
        user.save(update_fields=["password", "token"])

        return response.NoContent()
示例#21
0
    def list_projects(self, request, *args, **kwargs):
        self.check_permissions(request, "list_projects", None)
        url = request.DATA.get('url', None)
        if not url:
            raise exc.WrongArguments(_("The url param is needed"))

        token = self._get_token(request)
        importer = JiraNormalImporter(request.user, url, token)
        agile_importer = JiraAgileImporter(request.user, url, token)
        projects = importer.list_projects()
        boards = agile_importer.list_projects()
        return response.Ok(sorted(projects + boards, key=lambda x: x['name']))
示例#22
0
    def change_logo(self, request, *args, **kwargs):
        """
        Change logo to this project.
        """
        self.object = get_object_or_404(self.get_queryset(), **kwargs)
        self.check_permissions(request, "change_logo", self.object)

        logo = request.FILES.get('logo', None)
        if not logo:
            raise exc.WrongArguments(_("Incomplete arguments"))
        try:
            pil_image(logo)
        except Exception:
            raise exc.WrongArguments(_("Invalid image format"))

        self.pre_conditions_on_save(self.object)

        self.object.logo = logo
        self.object.save(update_fields=["logo"])

        serializer = self.get_serializer(self.object)
        return response.Ok(serializer.data)
示例#23
0
    def partial_update(self, request, *args, **kwargs):
        """
        We must detect if the user is trying to change his email so we can
        save that value and generate a token that allows him to validate it in
        the new email account
        """
        user = self.get_object()
        self.check_permissions(request, "update", user)

        new_email = request.DATA.pop('email', None)
        if new_email is not None:
            valid_new_email = True
            duplicated_email = models.User.objects.filter(
                email=new_email).exists()

            try:
                validate_email(new_email)
                validate_user_email_allowed_domains(new_email)
            except ValidationError:
                valid_new_email = False

            valid_new_email = valid_new_email and new_email != request.user.email

            if duplicated_email:
                raise exc.WrongArguments(_("Duplicated email"))
            elif not valid_new_email:
                raise exc.WrongArguments(_("Not valid email"))

            # We need to generate a token for the email
            request.user.email_token = str(uuid.uuid4())
            request.user.new_email = new_email
            request.user.save(update_fields=["email_token", "new_email"])
            email = mail_builder.change_email(request.user.new_email, {
                "user": request.user,
                "lang": request.user.lang
            })
            email.send()

        return super().partial_update(request, *args, **kwargs)
示例#24
0
    def pre_conditions_on_save(self, obj):
        super().pre_conditions_on_save(obj)

        if obj.milestone and obj.milestone.project != obj.project:
            raise exc.WrongArguments(
                _("You don't have permissions to set this sprint to this task."
                  ))

        if obj.user_story and obj.user_story.project != obj.project:
            raise exc.WrongArguments(
                _("You don't have permissions to set this user story to this task."
                  ))

        if obj.status and obj.status.project != obj.project:
            raise exc.WrongArguments(
                _("You don't have permissions to set this status to this task."
                  ))

        if obj.milestone and obj.user_story and obj.milestone != obj.user_story.milestone:
            raise exc.WrongArguments(
                _("You don't have permissions to set this sprint to this task."
                  ))
示例#25
0
def test_import_trello_list_projects_with_problem_on_request(client, settings):
    user = f.UserFactory.create()
    client.login(user)

    url = reverse("importers-trello-list-projects")

    with mock.patch('tina.importers.trello.importer.TrelloClient') as TrelloClientMock:
        instance = mock.Mock()
        instance.get.side_effect = exc.WrongArguments("Invalid Request")
        TrelloClientMock.return_value = instance
        response = client.post(url, content_type="application/json", data=json.dumps({"token": "token"}))

    assert response.status_code == 400
示例#26
0
    def get(self, uri_path, query_params=None):
        headers = {'Accept': 'application/json'}
        if query_params is None:
            query_params = {}

        if uri_path[0] == '/':
            uri_path = uri_path[1:]
        url = 'https://api.trello.com/1/%s' % uri_path

        response = requests.get(url, params=query_params, headers=headers, auth=self.oauth)

        if response.status_code == 400:
            raise exc.WrongArguments(_("Invalid Request: %s at %s") % (response.text, url))
        if response.status_code == 401:
            raise exc.AuthenticationFailed(_("Unauthorized: %s at %s") % (response.text, url))
        if response.status_code == 403:
            raise exc.PermissionDenied(_("Unauthorized: %s at %s") % (response.text, url))
        if response.status_code == 404:
            raise exc.NotFound(_("Resource Unavailable: %s at %s") % (response.text, url))
        if response.status_code != 200:
            raise exc.WrongArguments(_("Resource Unavailable: %s at %s") % (response.text, url))

        return response.json()
示例#27
0
def get_and_validate_user(*, username: str, password: str) -> bool:
    """
    Check if user with username/email exists and specified
    password matchs well with existing user password.

    if user is valid,  user is returned else, corresponding
    exception is raised.
    """

    user = get_user_by_username_or_email(username)
    if not user.check_password(password):
        raise exc.WrongArguments(
            _("Username or password does not matches user."))

    return user
示例#28
0
    def authorize(self, request, *args, **kwargs):
        self.check_permissions(request, "authorize", None)

        try:
            oauth_data = request.user.auth_data.get(key="trello-oauth")
            oauth_token = oauth_data.extra['oauth_token']
            oauth_secret = oauth_data.extra['oauth_secret']
            oauth_verifier = request.DATA.get('code')
            oauth_data.delete()
            trello_token = TrelloImporter.get_access_token(
                oauth_token, oauth_secret, oauth_verifier)['oauth_token']
        except Exception as e:
            raise exc.WrongArguments(_("Invalid or expired auth token"))

        return response.Ok({"token": trello_token})
示例#29
0
    def password_recovery(self, request, pk=None):
        username_or_email = request.DATA.get('username', None)

        self.check_permissions(request, "password_recovery", None)

        if not username_or_email:
            raise exc.WrongArguments(_("Invalid username or email"))

        user = get_user_by_username_or_email(username_or_email)
        user.token = str(uuid.uuid4())
        user.save(update_fields=["token"])

        email = mail_builder.password_recovery(user, {"user": user})
        email.send()

        return response.Ok({"detail": _("Mail sended successful!")})
示例#30
0
def get_user_by_username_or_email(username_or_email):
    user_model = get_user_model()
    qs = user_model.objects.filter(
        Q(username__iexact=username_or_email)
        | Q(email__iexact=username_or_email))

    if len(qs) > 1:
        qs = qs.filter(
            Q(username=username_or_email) | Q(email=username_or_email))

    if len(qs) == 0:
        raise exc.WrongArguments(
            _("Username or password does not matches user."))

    user = qs[0]
    return user