def _create_summary(self, request): # TODO: Should we fail if they don't provide the previous summary? # Or just grab the last paper summary created and set it to previous? user = request.user summary = request.data.get('summary') paper_id = request.data.get('paper') summary_plain_text = request.data.get('summary_plain_text', '') previous_summary_id = request.data.get('previousSummaryId', None) created_location = None if request.query_params.get('created_location') == 'progress': created_location = Summary.CREATED_LOCATION_PROGRESS previous_summary = None if previous_summary_id is not None: previous_summary = Summary.objects.get(id=previous_summary_id) new_summary = Summary.objects.create( summary=summary, summary_plain_text=summary_plain_text, proposed_by=user, paper_id=paper_id, previous=previous_summary, created_location=created_location) tracked_summary = events_api.track_content_summary( user, new_summary, request, update=bool(previous_summary)) update_user_risk_score(user, tracked_summary) return new_summary
def sift_track_update_content_comment( self, request, response, model, is_thread=False ): item = model.objects.get(pk=response.data["id"]) tracked_comment = events_api.track_content_comment( item.created_by, item, request, is_thread=is_thread, update=True ) update_user_risk_score(item.created_by, tracked_comment)
def save_user(self, request, sociallogin, form=None): # Saves new user if sociallogin.account.provider == OrcidProvider.id: sociallogin.user.username = self._generate_temporary_username( sociallogin) saved_user = super().save_user(request, sociallogin, form) self._merge_or_update_orcid_author(saved_user, sociallogin) else: saved_user = super().save_user(request, sociallogin, form) tracked_account = events_api.track_account(saved_user, request) update_user_risk_score(saved_user, tracked_account) return saved_user
def create(self, request, *args, **kwargs): # Do not allow user to manually set created_by try: del request.data['created_by'] except KeyError: pass paper = request.data.get('paper', None) if paper is None: paper = get_document_id_from_path(request) if paper is None: return Response('Missing required field `paper`', status=400) request.data['paper'] = paper context = self.get_serializer_context() response = super().create(request, *args, **kwargs) bullet_id = response.data['id'] bullet_point = BulletPoint.objects.get(pk=response.data['id']) update_or_create_vote(request, request.user, bullet_point, Vote.UPVOTE) response.data = BulletPointSerializer( bullet_point, context=context ).data tracked_bullet_point = events_api.track_content_bullet_point( bullet_point.created_by, bullet_point, request, ) update_user_risk_score(bullet_point.created_by, tracked_bullet_point) # Deprecating bulletpoint contributions until(?) # we bring bulletpoints back # create_contribution.apply_async( # ( # Contribution.CURATOR, # {'app_label': 'bullet_point', 'model': 'bulletpoint'}, # request.user.id, # paper, # bullet_id # ), # priority=2, # countdown=10 # ) return response
def edit(self, request, pk=None): bullet_point = self.get_object() user = request.user paper_id = request.data.get('paper', None) if paper_id is None: paper_id = get_document_id_from_path(request) if paper_id is None: return Response( 'Missing required field `paper`', status=status.HTTP_400_BAD_REQUEST ) text = request.data.get('text') plain_text = request.data.get('plain_text') tail = bullet_point.tail if tail is None: tail = bullet_point with transaction.atomic(): head_bullet_point = BulletPoint.objects.create( bullet_type=bullet_point.bullet_type, paper_id=paper_id, tail=tail, previous=bullet_point, created_by=user, text=text, plain_text=plain_text, ordinal=bullet_point.ordinal, ordinal_is_locked=bullet_point.ordinal_is_locked, is_head=True, is_tail=False ) bullet_point.remove_from_head() bullet_point.save() tracked_bullet_point = events_api.track_content_bullet_point( head_bullet_point.created_by, head_bullet_point, request, update=True ) update_user_risk_score(head_bullet_point.created_by, tracked_bullet_point) serialized = self.get_serializer(instance=head_bullet_point) return Response(serialized.data, status=status.HTTP_201_CREATED)
def update(self, instance, validated_data): request = self.context.get("request", None) authors = validated_data.pop("authors", [None]) hubs = validated_data.pop("hubs", [None]) raw_authors = validated_data.pop("raw_authors", []) file = validated_data.get("file", None) try: with transaction.atomic(): # Temporary fix for updating read only fields # Not including file, pdf_url, and url because # those fields are processed read_only_fields = (self.Meta.read_only_fields + self.Meta.patch_read_only_fields) for read_only_field in read_only_fields: if read_only_field in validated_data: validated_data.pop(read_only_field, None) self._add_url(file, validated_data) self._clean_abstract(validated_data) paper = super(PaperSerializer, self).update(instance, validated_data) paper.full_clean(exclude=["paper_type"]) unified_doc = paper.unified_document paper_title = paper.paper_title or "" file = paper.file self._check_pdf_title(paper, paper_title, file) new_hubs = [] remove_hubs = [] if hubs: current_hubs = paper.hubs.all() for current_hub in current_hubs: if current_hub not in hubs: remove_hubs.append(current_hub) for hub in hubs: if hub not in current_hubs: new_hubs.append(hub) paper.hubs.remove(*remove_hubs) paper.hubs.add(*hubs) unified_doc.hubs.remove(*remove_hubs) unified_doc.hubs.add(*hubs) for hub in remove_hubs: hub.paper_count = hub.get_paper_count() hub.save(update_fields=["paper_count"]) for hub in new_hubs: hub.paper_count = hub.get_paper_count() hub.save(update_fields=["paper_count"]) if authors: current_authors = paper.authors.all() remove_authors = [] for author in current_authors: if author not in authors: remove_authors.append(author) new_authors = [] for author in authors: if author not in current_authors: new_authors.append(author) paper.authors.remove(*remove_authors) paper.authors.add(*new_authors) paper.set_paper_completeness() if file: self._add_file(paper, file) updated_hub_ids = list( map(lambda hub: hub.id, remove_hubs + new_hubs)) if len(updated_hub_ids) > 0: reset_unified_document_cache( hub_ids=updated_hub_ids, document_type=["paper", "all"], filters=[NEWEST, TOP, TRENDING, DISCUSSED], with_default_hub=True, ) if request: tracked_paper = events_api.track_content_paper( request.user, paper, request, update=True) update_user_risk_score(request.user, tracked_paper) return paper except Exception as e: error = PaperSerializerError(e, "Failed to update paper") sentry.log_error(e, base_error=error.trigger) raise error
def create(self, validated_data): request = self.context.get("request", None) if request: user = request.user else: user = None validated_data["uploaded_by"] = user if "url" in validated_data or "pdf_url" in validated_data: error = Exception("URL uploading is deprecated") sentry.log_error(error) raise error # Prepare validated_data by removing m2m authors = validated_data.pop("authors") hubs = validated_data.pop("hubs") hypothesis_id = validated_data.pop("hypothesis_id", None) citation_type = validated_data.pop("citation_type", None) file = validated_data.get("file") try: with transaction.atomic(): # Temporary fix for updating read only fields # Not including file, pdf_url, and url because # those fields are processed for read_only_field in self.Meta.read_only_fields: if read_only_field in validated_data: validated_data.pop(read_only_field, None) # valid_doi = self._check_valid_doi(validated_data) # if not valid_doi: # raise IntegrityError('DETAIL: Invalid DOI') self._add_url(file, validated_data) self._clean_abstract(validated_data) self._add_raw_authors(validated_data) paper = None if paper is None: # It is important to note that paper signals # are ran after call to super paper = super(PaperSerializer, self).create(validated_data) paper.full_clean(exclude=["paper_type"]) unified_doc = paper.unified_document unified_doc_id = paper.unified_document.id if hypothesis_id: self._add_citation(user, hypothesis_id, unified_doc, citation_type) paper_id = paper.id paper_title = paper.paper_title or "" file = paper.file self._check_pdf_title(paper, paper_title, file) # NOTE: calvinhlee - This is an antipattern. Look into changing Vote.objects.create(paper=paper, created_by=user, vote_type=Vote.UPVOTE) # Now add m2m values properly if validated_data["paper_type"] == Paper.PRE_REGISTRATION: paper.authors.add(user.author_profile) # TODO: Do we still need add authors from the request content? paper.authors.add(*authors) self._add_orcid_authors(paper) paper.hubs.add(*hubs) for hub in hubs: hub.paper_count = hub.get_paper_count() hub.save(update_fields=["paper_count"]) try: self._add_file(paper, file) except Exception as e: sentry.log_error(e, ) paper.set_paper_completeness() # Fix adding references # self._add_references(paper) paper.pdf_license = paper.get_license(save=False) update_unified_document_to_paper(paper) tracked_paper = events_api.track_content_paper( user, paper, request) update_user_risk_score(user, tracked_paper) create_contribution.apply_async( ( Contribution.SUBMITTER, { "app_label": "paper", "model": "paper" }, user.id, unified_doc_id, paper_id, ), priority=3, countdown=10, ) celery_calculate_paper_twitter_score.apply_async((paper_id, ), priority=5, countdown=10) hub_ids = unified_doc.hubs.values_list("id", flat=True) if hub_ids.exists(): reset_unified_document_cache( hub_ids, document_type=["paper", "all"], filters=[NEWEST], with_default_hub=True, ) return paper except IntegrityError as e: sentry.log_error(e) raise e except Exception as e: error = PaperSerializerError(e, "Failed to create paper") sentry.log_error(error, base_error=error.trigger) raise error
def validate(self, attrs, retry=0): view = self.context.get('view') request = self._get_request() if not view: error = serializers.ValidationError( _("View is not defined, pass it as a context variable")) sentry.log_error(error) raise error adapter_class = getattr(view, 'adapter_class', None) if not adapter_class: error = serializers.ValidationError( _("Define adapter_class in view")) sentry.log_error(error) raise error adapter = adapter_class(request) app = adapter.get_provider().get_app(request) # More info on code vs access_token # http://stackoverflow.com/questions/8666316/facebook-oauth-2-0-code-and-token credential = attrs.get('credential') # Case 1: We received the access_token if attrs.get('access_token') or credential: access_token = attrs.get('access_token') if credential: access_token = credential # Case 2: We received the authorization code elif attrs.get('code'): self.callback_url = getattr(view, 'callback_url', None) self.client_class = getattr(view, 'client_class', None) if not self.callback_url: error = serializers.ValidationError( _("Define callback_url in view")) sentry.log_error(error) raise error if not self.client_class: error = serializers.ValidationError( _("Define client_class in view")) sentry.log_error(error) raise error code = attrs.get('code') provider = adapter.get_provider() scope = provider.get_scope(request) client = self.client_class( request, app.client_id, app.secret, adapter.access_token_method, adapter.access_token_url, 'postmessage', # This is the callback url scope) token = client.get_access_token(code) access_token = token['access_token'] else: error = serializers.ValidationError( _("Incorrect input. access_token or code is required.")) sentry.log_error(error) raise serializers.ValidationError( _("Incorrect input. access_token or code is required.")) social_token = adapter.parse_token({'access_token': access_token}) social_token.app = app login = None try: login = self.get_social_login(adapter, app, social_token, access_token) complete_social_login(request, login) except ConnectionTimeout: pass except NoReverseMatch as e: if 'account_inactive' in str(e): login_user = login.account.user tracked_login = events_api.track_login(login_user, '$failure', request) update_user_risk_score(login_user, tracked_login) raise LoginError(None, 'Account is suspended') except Exception as e: error = LoginError(e, 'Login failed') sentry.log_info(error, error=e) if login: deleted = self._delete_user_account(login.user, error=e) if deleted and retry < 3: return self.validate(attrs, retry=retry + 1) sentry.log_error(error, base_error=e) raise serializers.ValidationError(_("Incorrect value")) if login and not login.is_existing: # We have an account already signed up in a different flow # with the same email address: raise an exception. # This needs to be handled in the frontend. We can not just # link up the accounts due to security constraints if app_settings.UNIQUE_EMAIL: # Do we have an account already with this email address? account_exists = get_user_model().objects.filter( email=login.user.email, ).exists() if account_exists: sentry.log_info('User already registered with this e-mail') deleted = self._delete_user_account(login.user) if deleted and retry < 3: return self.validate(attrs, retry=retry + 1) raise serializers.ValidationError( _("User already registered with this e-mail address.")) login.lookup() login.save(request, connect=True) login_user = login.account.user attrs['user'] = login_user tracked_login = events_api.track_login(login_user, '$success', request) update_user_risk_score(login_user, tracked_login) try: visits = WebsiteVisits.objects.get(uuid=attrs['uuid']) visits.user = attrs['user'] visits.save() except Exception as e: print(e) pass try: referral_code = attrs.get('referral_code') if referral_code: referral_user = User.objects.get(referral_code=referral_code) user = attrs['user'] if referral_code and not user.invited_by and referral_user.id != user.id: user.invited_by = referral_user user.save() except Exception as e: print(e) sentry.log_error(e) pass request = self._get_request() x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR') if x_forwarded_for: ip = x_forwarded_for.split(',')[0] else: ip = request.META.get('REMOTE_ADDR') user = attrs['user'] check_user_risk(user) if user.is_authenticated and not user.probable_spammer: try: country = geo.country(ip) user.country_code = country.get('country_code') user.save() except Exception as e: print(e) sentry.log_error(e) return attrs