Esempio n. 1
0
    def get_success_url(self):

        # Check if user is still eligible for bundle based on if they agreed to
        # the terms of use or not
        self.request.user.editor.wp_bundle_eligible = editor_bundle_eligible(
            self.request.user.editor)
        self.request.user.editor.save()
        self.request.user.editor.update_bundle_authorization()

        if self.get_object().terms_of_use:
            # If they agreed with the terms, awesome. Send them where they were
            # trying to go, if there's a meaningful `next` parameter in the URL;
            # if not, send them to their home page as a sensible default.
            # Also log the date they agreed.
            self.get_object().terms_of_use_date = datetime.date.today()
            self.get_object().save()

            return _redirect_to_next_param(self.request)

        else:
            # If they didn't agree, that's cool, but we should make sure they
            # know about the limits. Send them to their home page rather than
            # trying to parse the next parameter, because parsing next will
            # put them in an obnoxious redirect loop - send them to where
            # they were going, which promptly sends them back to the terms
            # page because they haven't agreed to the terms....
            # However, we will keep the terms_of_use_date as last updated date
            self.get_object().terms_of_use_date = datetime.date.today()
            self.get_object().save()

            return reverse_lazy("homepage")
Esempio n. 2
0
    def handle(self, *args, **options):
        wp_editcount_updated = now()
        if options["datetime"]:
            wp_editcount_updated = datetime.fromisoformat(options["datetime"])

        # Getting all editors that are currently eligible or are staff or are superusers
        editors = Editor.objects.filter(wp_bundle_eligible=True)
        for editor in editors:
            if options["global_userinfo"]:
                global_userinfo = options["global_userinfo"]
            else:
                global_userinfo = editor_global_userinfo(
                    editor.wp_username, editor.wp_sub, True)
            if global_userinfo:
                (
                    editor.wp_editcount_prev_updated,
                    editor.wp_editcount_prev,
                    editor.wp_editcount_recent,
                    editor.wp_enough_recent_edits,
                ) = editor_recent_edits(
                    global_userinfo["editcount"],
                    editor.wp_editcount_updated,
                    editor.wp_editcount_prev_updated,
                    editor.wp_editcount_prev,
                    editor.wp_editcount_recent,
                    editor.wp_enough_recent_edits,
                )
                editor.wp_editcount = global_userinfo["editcount"]
                editor.wp_editcount_updated = wp_editcount_updated
                editor.wp_enough_edits = editor_enough_edits(
                    editor.wp_editcount)
                editor.wp_not_blocked = editor_not_blocked(
                    global_userinfo["merged"])
                editor.wp_valid = editor_valid(
                    editor.wp_enough_edits,
                    # We could recalculate this, but we would only need to do that if upped the minimum required account age.
                    editor.wp_account_old_enough,
                    # editor.wp_not_blocked can only be rechecked on login, so we're going with the existing value.
                    editor.wp_not_blocked,
                    editor.ignore_wp_blocks,
                )
                editor.wp_bundle_eligible = editor_bundle_eligible(editor)

                editor.save()

                editor.update_bundle_authorization()
Esempio n. 3
0
    def update_from_wikipedia(self, identity, lang):
        """
        Given the dict returned from the Wikipedia OAuth /identify endpoint,
        update the instance accordingly.

        This assumes that we have used wp_sub to match the Editor and the
        Wikipedia info.

        Expected identity data:

        {
            'username': identity['username'],       # wikipedia username
            'sub': identity['sub'],                 # wikipedia ID
            'rights': identity['rights'],           # user rights on-wiki
            'groups': identity['groups'],           # user groups on-wiki
            'editcount': identity['editcount'],
            'email': identity['email'],

            # Date registered: YYYYMMDDHHMMSS
            'registered': identity['registered']
        }

        We could attempt to harvest real name, but we won't; we'll let
        users enter it if required by partners, and avoid knowing the
        data otherwise.
        """

        try:
            assert self.wp_sub == identity["sub"]
        except AssertionError:
            logger.exception(
                "Was asked to update Editor data, but the "
                "WP sub in the identity passed in did not match the wp_sub on "
                "the instance. Not updating.")
            raise

        global_userinfo = self.get_global_userinfo(identity)

        self.wp_username = identity["username"]
        self.wp_rights = json.dumps(identity["rights"])
        self.wp_groups = json.dumps(identity["groups"])
        if global_userinfo:
            (
                self.wp_editcount_prev_updated,
                self.wp_editcount_prev,
                self.wp_editcount_recent,
                self.wp_enough_recent_edits,
            ) = editor_recent_edits(
                global_userinfo["editcount"],
                self.wp_editcount_updated,
                self.wp_editcount_prev_updated,
                self.wp_editcount_prev,
                self.wp_editcount_recent,
                self.wp_enough_recent_edits,
            )
            self.wp_editcount = global_userinfo["editcount"]
            self.wp_not_blocked = editor_not_blocked(global_userinfo["merged"])
            self.wp_editcount_updated = now()

        self.wp_registered = editor_reg_date(identity, global_userinfo)
        self.wp_account_old_enough = editor_account_old_enough(
            self.wp_registered)
        self.wp_enough_edits = editor_enough_edits(self.wp_editcount)
        self.wp_valid = editor_valid(
            self.wp_enough_edits,
            self.wp_account_old_enough,
            self.wp_not_blocked,
            self.ignore_wp_blocks,
        )

        self.wp_bundle_eligible = editor_bundle_eligible(self)

        self.save()

        self.update_bundle_authorization()

        # This will be True the first time the user logs in, since use_wp_email
        # defaults to True. Therefore we will initialize the email field if
        # they have an email at WP for us to initialize it with.
        if self.user.userprofile.use_wp_email:
            try:
                self.user.email = identity["email"]
            except KeyError:
                # Email isn't guaranteed to be present in identity - don't do
                # anything if we can't find it.
                logger.exception(
                    "Unable to get Editor email address from Wikipedia.")

        self.user.save()

        # Add language if the user hasn't selected one
        if not self.user.userprofile.lang:
            self.user.userprofile.lang = lang
            self.user.userprofile.save()
Esempio n. 4
0
    def update_from_wikipedia(
        self,
        identity: dict,
        lang: str,
        global_userinfo: dict = None,
        current_datetime: timezone = None,
    ):
        """
        Given the dict returned from the Wikipedia OAuth /identify endpoint,
        update the instance accordingly.

        This assumes that we have used wp_sub to match the Editor and the
        Wikipedia info.

        Parameters
        ----------
        identity : dict
            {
                'username': identity['username'],       # wikipedia username
                'sub': identity['sub'],                 # wikipedia ID
                'rights': identity['rights'],           # user rights on-wiki
                'groups': identity['groups'],           # user groups on-wiki
                'editcount': identity['editcount'],
                'email': identity['email'],

                # Date registered: YYYYMMDDHHMMSS
                'registered': identity['registered']
            }

            We could attempt to harvest real name, but we won't; we'll let
            users enter it if required by partners, and avoid knowing the
            data otherwise.
        lang : str
        global_userinfo : dict
            Optional override currently used for tests only. Defaults to fetching from global_userinfo API.
            {
                "home": str,                            # SUL home wiki
                "id": int,                              # Same as identity['sub']
                "registration": datetime.datetime,      # Wikipedia account registration date.
                "name": str,                            # Same as identity['username']
                "editcount": int,                       # Same as identity['editcount']
                "merged": [                             # List of wiki accounts attached to the SUL account
                    {
                        "wiki": str,                        # Wiki name
                        "url": str,                         # Wiki URL
                        "timestamp": datetime.datetime,
                        "method": str,
                        "editcount": int,
                        "registration": datetime.datetime,  # Wiki registration date.
                        "groups": list,                     # user groups on-wiki.
                    },
                    ...
                ],
            }
        current_datetime : timezone
            optional timezone-aware timestamp override that represents now()
        Returns
        -------
        None
        """
        if not current_datetime:
            current_datetime = timezone.now()

        if global_userinfo:
            self.check_sub(global_userinfo["id"])
        else:
            global_userinfo = self.get_global_userinfo(identity)

        self.wp_username = identity["username"]
        self.wp_rights = json.dumps(identity["rights"])
        self.wp_groups = json.dumps(identity["groups"])
        if global_userinfo:
            self.update_editcount(global_userinfo["editcount"],
                                  current_datetime=current_datetime)
            self.wp_not_blocked = editor_not_blocked(global_userinfo["merged"])

        if self.wp_registered is None:
            self.wp_registered = editor_reg_date(identity, global_userinfo)
        # if the account is already old enough, we shouldn't run this check everytime
        # since this flag should never return back to False
        if not self.wp_account_old_enough:
            self.wp_account_old_enough = editor_account_old_enough(
                self.wp_registered)

        self.wp_enough_edits = editor_enough_edits(self.wp_editcount)
        self.wp_valid = editor_valid(
            self.wp_enough_edits,
            self.wp_account_old_enough,
            self.wp_not_blocked,
            self.ignore_wp_blocks,
        )

        self.wp_bundle_eligible = editor_bundle_eligible(self)

        self.save()

        self.update_bundle_authorization()

        # This will be True the first time the user logs in, since use_wp_email
        # defaults to True. Therefore we will initialize the email field if
        # they have an email at WP for us to initialize it with.
        if self.user.userprofile.use_wp_email:
            try:
                self.user.email = identity["email"]
            except KeyError:
                # Email isn't guaranteed to be present in identity - don't do
                # anything if we can't find it.
                logger.exception(
                    "Unable to get Editor email address from Wikipedia.")

        self.user.save()

        # Add language if the user hasn't selected one
        if not self.user.userprofile.lang:
            self.user.userprofile.lang = lang
            self.user.userprofile.save()
Esempio n. 5
0
    def handle(self, *args, **options):
        """
        Updates editor info and Bundle eligibility for currently-eligible Editors.
        Parameters
        ----------
        args
        options

        Returns
        -------
        None
        """

        # Default behavior is to use current datetime for timestamps to check all editors.
        now_or_datetime = now()
        datetime_override = None
        timedelta_days = 0
        wp_username = None
        editors = Editor.objects.all()

        # This may be overridden so that values may be treated as if they were valid for an arbitrary datetime.
        # This is also passed to the model method.
        if options["datetime"]:
            datetime_override = now_or_datetime.fromisoformat(
                options["datetime"])
            now_or_datetime = datetime_override

        # These are used to limit the set of editors updated by the command.
        # Nothing is passed to the model method.
        if options["timedelta_days"]:
            timedelta_days = int(options["timedelta_days"])

        # Get editors that haven't been updated in the specified time range, with an option to limit on wp_username.
        if timedelta_days:
            editors = editors.exclude(
                editorlogs__timestamp__gt=now_or_datetime -
                timedelta(days=timedelta_days), )

        # Optional wp_username filter.
        if options["wp_username"]:
            editors = editors.filter(wp_username=str(options["wp_username"]))

        for editor in editors:
            # `global_userinfo` data may be overridden.
            if options["global_userinfo"]:
                global_userinfo = options["global_userinfo"]
                editor.check_sub(global_userinfo["id"])
            # Default behavior is to fetch live `global_userinfo`
            else:
                global_userinfo = editor_global_userinfo(editor.wp_sub)
            if global_userinfo:
                editor.update_editcount(global_userinfo["editcount"],
                                        datetime_override)
                # Determine editor validity.
                editor.wp_enough_edits = editor_enough_edits(
                    editor.wp_editcount)
                editor.wp_not_blocked = editor_not_blocked(
                    global_userinfo["merged"])
                editor.wp_valid = editor_valid(
                    editor.wp_enough_edits,
                    # We could recalculate this, but we would only need to do that if upped the minimum required account age.
                    editor.wp_account_old_enough,
                    # editor.wp_not_blocked can only be rechecked on login, so we're going with the existing value.
                    editor.wp_not_blocked,
                    editor.ignore_wp_blocks,
                )
                # Determine Bundle eligibility.
                editor.wp_bundle_eligible = editor_bundle_eligible(editor)
                # Save editor.
                editor.save()
                # Prune EditorLogs, with daily_prune_range set to only check the previous day to improve performance.
                editor.prune_editcount(current_datetime=datetime_override,
                                       daily_prune_range=2)
                # Update bundle authorizations.
                editor.update_bundle_authorization()