def load_dump(self, request): throttle = throttling.ImportDumpModeRateThrottle() if not throttle.allow_request(request, self): self.throttled(request, throttle.wait()) self.check_permissions(request, "load_dump", None) dump = request.FILES.get('dump', None) if not dump: raise exc.WrongArguments(_("Needed dump file")) reader = codecs.getreader("utf-8") try: dump = json.load(reader(dump)) is_private = dump.get("is_private", False) except Exception: raise exc.WrongArguments(_("Invalid dump format")) user = request.user slug = dump.get('slug', None) if slug is not None and Project.objects.filter(slug=slug).exists(): del dump['slug'] members = len(dump.get("memberships", [])) (enough_slots, not_enough_slots_error ) = users_service.has_available_slot_for_project( user, project=Project(is_private=is_private, id=None), members=max(members, 1)) if not enough_slots: raise exc.NotEnoughSlotsForProject(is_private, max(members, 1), not_enough_slots_error) if settings.CELERY_ENABLED: task = tasks.load_project_dump.delay(user, dump) return response.Accepted({"import_id": task.id}) project = dump_service.dict_to_project(dump, request.user) response_data = ProjectSerializer(project).data return response.Created(response_data)
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) ret = super(UsersViewSet, self).partial_update(request, *args, **kwargs) new_email = request.DATA.get('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) 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.uuid1()) request.user.new_email = new_email request.user.save(update_fields=["email_token", "new_email"]) mbuilder = MagicMailBuilder( template_mail_cls=InlineCSSTemplateMail) email = mbuilder.change_email(request.user.new_email, { "user": request.user, "lang": request.user.lang }) email.send() return ret
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_model = apps.get_model("users", "User") qs = user_model.objects.filter(Q(username=username) | Q(email=username)) if len(qs) == 0: raise exc.WrongArguments("Username or password does not matches user.") user = qs[0] if not user.check_password(password): raise exc.WrongArguments("Username or password does not matches user.") return user
def change_is_agent(self, request): try: user = models.User.objects.get(id=request.DATA.get("id")) except models.User.DoesNotExist: raise exc.WrongArguments( "Invalid, cannot find the user with given id") user.is_agent = request.DATA.get("is_agent") user.save(update_fields=["is_agent"]) return response.NoContent()
def change_email(self, request, pk=None): """ Verify the email change to current logged user. """ serializer = serializers.ChangeEmailSerializer(data=request.DATA, many=False) if not serializer.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=serializer.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) user.email = user.new_email user.new_email = None user.email_token = None user.save(update_fields=["email", "new_email", "email_token"]) return Response(status=status.HTTP_204_NO_CONTENT)
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.project_id != obj.content_object.project_id: raise exc.WrongArguments(_("Project ID not matches between object and project")) super().pre_save(obj)
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()
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"]))
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)
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) serializer = serializers.RecoverySerializer(data=request.DATA, many=False) if not serializer.is_valid(): raise exc.WrongArguments(_("Token is invalid")) try: user = models.User.objects.get(token=serializer.data["token"]) except models.User.DoesNotExist: raise exc.WrongArguments(_("Token is invalid")) user.set_password(serializer.data["password"]) user.token = None user.save(update_fields=["password", "token"]) return response.NoContent()
def cancel(self, request, pk=None): """ Cancel an account via token """ serializer = serializers.CancelAccountSerializer(data=request.DATA, many=False) if not serializer.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(serializer.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()
def password_recovery(self, request, pk=None): username_or_email = request.DATA.get('username', None) if not username_or_email: raise exc.WrongArguments(_("Invalid username or email")) try: queryset = User.objects.all() user = queryset.get(Q(username=username_or_email) | Q(email=username_or_email)) except User.DoesNotExist: raise exc.WrongArguments(_("Invalid username or email")) user.token = str(uuid.uuid1()) user.save(update_fields=["token"]) mbuilder = MagicMailBuilder() email = mbuilder.password_recovery(user.email, {"user": user}) email.send() return Response({"detail": _("Mail sended successful!")})
def pre_save(self, obj): current_version = obj.version param_version = self.request.DATA.get('version', None) if obj.id is not None and current_version != param_version: raise exc.WrongArguments( {"version": "The version doesn't match with the current one"}) if obj.id: obj.version = models.F('version') + 1 super().pre_save(obj)
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")) try: queryset = models.User.objects.all() user = queryset.get( Q(username=username_or_email) | Q(email=username_or_email)) except models.User.DoesNotExist: raise exc.WrongArguments(_("Invalid username or email")) user.token = str(uuid.uuid1()) user.save(update_fields=["token"]) email = mail_builder.password_recovery(user, {"user": user}) email.send() return response.Ok({"detail": _("Mail sended successful!")})
def test_import_trello_list_users_with_problem_on_request(client, settings): user = f.UserFactory.create() client.login(user) url = reverse("importers-trello-list-users") with mock.patch('taiga.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", "project": 1})) assert response.status_code == 400
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) try: users = importer.list_users() except Exception as e: # common error due to modern Jira versions which are unsupported by Taiga raise exc.BadRequest( _(""" There was an error; probably due to an unsupported Jira version. Taiga does not support Jira releases from 8.6.""")) for user in users: user['user'] = None if not user['email']: continue try: taiga_user = User.objects.get(email=user['email']) except User.DoesNotExist: continue user['user'] = { 'id': taiga_user.id, 'full_name': taiga_user.get_full_name(), 'gravatar_id': get_user_gravatar_id(taiga_user), 'photo': get_user_photo_url(taiga_user), } return response.Ok(users)
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." ))
def test_import_github_list_projects_with_problem_on_request(client): user = f.UserFactory.create() client.login(user) url = reverse("importers-github-list-projects") with mock.patch('taiga.importers.github.importer.GithubClient') as GithubClientMock: instance = mock.Mock() instance.get.side_effect = exc.WrongArguments("Invalid Request") GithubClientMock.return_value = instance response = client.post(url, content_type="application/json", data=json.dumps({"token": "token"})) assert response.status_code == 400
def test_import_asana_list_projects_with_problem_on_request(client): user = f.UserFactory.create() client.login(user) url = reverse("importers-asana-list-projects") with mock.patch('taiga.importers.asana.importer.AsanaClient') as AsanaClientMock: instance = mock.Mock() instance.workspaces.find_all.side_effect = exc.WrongArguments("Invalid Request") AsanaClientMock.oauth.return_value = instance response = client.post(url, content_type="application/json", data=json.dumps({"token": "token"})) assert response.status_code == 400
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)
def change_facebookinfo(self, request): user = models.User.objects.get(id=request.DATA.get("id")) facebookid = request.DATA.get("photo") #create folder facebook if not exist filepath = os.path.join(settings.MEDIA_ROOT,'user','facebook',facebookid) #filepath = settings.MEDIA_ROOT + "user/facebook/" + facebookid if not os.path.isdir(filepath): os.makedirs(filepath) filename_photo_download = filepath + "/photo_download" filename_photo = filepath + "/photo" facebookurl = "http://graph.facebook.com/" + facebookid + "/picture?width=9999" try: #urlretrieve("http://graph.facebook.com/100010961041067/picture", filename) urlretrieve(facebookurl, filename_photo_download) if not os.path.exists(filename_photo): shutil.copy2(filename_photo_download,filename_photo) else : if not os.path.getsize(filename_photo_download) == os.path.getsize(filename_photo): filenames_blob = filepath + "/*_crop.*" files_removed = glob.glob(filenames_blob) for f in files_removed: os.remove(f) avatar = "user/facebook/" + facebookid + "/photo" user.photo = avatar # user.full_name = request.DATA.get("full_name") user.save(update_fields=["photo","full_name"]) except Exception as e: # raise exc.WrongArguments(_(e)) raise e # facebookid = '100010961041067' # url = "http://graph.facebook.com/%s/picture?type=large" % facebookid #try: # response = request('GET', url, params={'type': 'large'}) #except Exception: raise exc.WrongArguments(_("Invalid image format")) #else: #make sure we have crop images user_data = self.admin_serializer_class(user) return response.NoContent()
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.verified_email = True user.save(update_fields=[ "email", "new_email", "email_token", "verified_email" ]) user_change_email_signal.send(sender=user.__class__, user=user, old_email=old_email, new_email=new_email) return response.NoContent()
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()
def remove_invitation_from_all_my_projects(self, request, **kwargs): private_only = request.DATA.get('private_only', False) email = request.DATA.get('email', None) if email is None: raise exc.WrongArguments(_("Email is required")) memberships = models.Membership.objects.filter( project__owner=request.user, email=email, user__isnull=True) if private_only: memberships = memberships.filter(project__is_private=True) memberships.delete() return response.NoContent()
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
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
def change_password_from_recovery(self, request, pk=None): """ Change password with token (from password recovery step). """ serializer = RecoverySerializer(data=request.DATA, many=False) if not serializer.is_valid(): raise exc.WrongArguments(_("Token is invalid")) user = User.objects.get(token=serializer.data["token"]) user.set_password(serializer.data["password"]) user.token = None user.save(update_fields=["password", "token"]) return Response(status=status.HTTP_204_NO_CONTENT)
def ldap_login_func(request): username = request.DATA.get('username', None) password = request.DATA.get('password', None) user = get_user_by_username_or_email(username) if user and user.check_password(password): print('Login!!') elif user and not user.check_password(password): raise exc.WrongArguments(_("Username or password does not matches user.")) else: email, full_name = connector.login(username=username, password=password) user = ldap_register(username=username, email=email, full_name=full_name) data = make_auth_response_data(user) return data
def authorize(self, request, *args, **kwargs): self.check_permissions(request, "authorize", None) try: oauth_data = request.user.auth_data.get(key="pivotal-oauth") oauth_token = oauth_data.extra['oauth_token'] oauth_secret = oauth_data.extra['oauth_secret'] oauth_verifier = request.DATA.get('code') oauth_data.delete() pivotal_token = PivotalImporter.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": pivotal_token})
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") if not current_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 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(status=status.HTTP_204_NO_CONTENT)