Example #1
0
    def do_request(self, student, coach, redirect_to):
        if not UserData.current():
            self.redirect(url_util.create_login_url(self.request.uri))
            return

        if student and coach:
            self.remove_student_from_coach(student, coach)

        if not self.is_ajax_request():
            self.redirect(redirect_to)
Example #2
0
    def do_request(self, student, coach, redirect_to):
        if not UserData.current():
            self.redirect(url_util.create_login_url(self.request.uri))
            return

        if student and coach:
            self.remove_student_from_coach(student, coach)

        if not self.is_ajax_request():
            self.redirect(redirect_to)
Example #3
0
def user_info(user_data, continue_url=None):

    if not continue_url:
        continue_url = "/"

    context = {
        "user_data": user_data,
        "username": user_data.nickname or user_data.username,
        "login_url": url_util.create_login_url(continue_url),
        "logout_url": url_util.create_logout_url(continue_url),
    }
    return shared_jinja.get().render_template("user_info_only.html", **context)
Example #4
0
    def add_global_template_values(self, template_values):
        template_values['App'] = App
        template_values['None'] = None

        if not template_values.has_key('user_data'):
            user_data = user_models.UserData.current()
            template_values['user_data'] = user_data

        user_data = template_values['user_data']

        display_name = ""
        if user_data:
            display_name = user_data.nickname or user_data.username

        template_values['server_time'] = time.time()

        # TODO(marcia): Remove username, points, logged_in template values
        # since they should be encapsulated in this UserProfile object
        logged_in_user_profile = util_profile.UserProfile.from_user(user_data,
                                                                    user_data)
        template_values['logged_in_user_profile'] = logged_in_user_profile

        # TODO(benkomalo): rename this global template property from "username"
        #    as it's not really the user's username, but just a display name.
        template_values['username'] = display_name
        template_values['points'] = user_data.points if user_data else 0
        template_values['logged_in'] = not user_data.is_phantom if user_data else False
        template_values['http_host'] = os.environ["HTTP_HOST"]

        # Always insert a post-login request before our continue url
        template_values['continue'] = url_util.create_post_login_url(
            template_values.get('continue') or self.request.uri)
        template_values['login_url'] = ('%s&direct=1' %
                                        url_util.create_login_url(
                                            template_values['continue']))
        template_values['logout_url'] = url_util.create_logout_url(
            self.request.uri)

        # TODO(stephanie): these settings are temporary; for FB testing purposes only
        template_values['site_base_url'] = 'http://%s' % os.environ["HTTP_HOST"]

        template_values['is_mobile'] = False
        template_values['is_mobile_capable'] = False
        template_values['is_ipad'] = False

        if self.is_mobile_capable():
            template_values['is_mobile_capable'] = True
            template_values['is_ipad'] = self.is_ipad()

            if 'is_mobile_allowed' in template_values and template_values['is_mobile_allowed']:
                template_values['is_mobile'] = self.is_mobile()

        # overridable hide_analytics querystring that defaults to true in dev
        # mode but false for prod.
        hide_analytics = self.request_bool("hide_analytics", App.is_dev_server)
        template_values['hide_analytics'] = hide_analytics

        # client-side error logging
        template_values['include_errorception'] = gandalf('errorception')

        # Analytics
        template_values['mixpanel_enabled'] = gandalf('mixpanel_enabled')

        # Enable for Mixpanel testing only
        # You will need to ask Tom, Kitt, or Marcia to add you to the "Khan
        # Academy Test" project on Mixpanel so that you can see the results.
        if False:
            template_values['mixpanel_test'] = "70acc4fce4511b89477ac005639cfee1"
            template_values['mixpanel_enabled'] = True
            template_values['hide_analytics'] = False

        if template_values['mixpanel_enabled']:
            template_values['mixpanel_id'] = gae_bingo.identity.identity()

        if not template_values['hide_analytics']:
            superprops_list = user_models.UserData.get_analytics_properties(user_data)

            # Create a superprops dict for MixPanel with a version number
            # Bump the version number if changes are made to the client-side
            # analytics code and we want to be able to filter by version.
            template_values['mixpanel_superprops'] = dict(superprops_list)

            # Copy over first 4 per-user properties for GA
            # (The 5th is reserved for Bingo)
            template_values['ga_custom_vars'] = superprops_list[0:4]

        if user_data:
            user_goals = goals.models.GoalList.get_current_goals(user_data)
            goals_data = [g.get_visible_data() for g in user_goals]
            if goals_data:
                template_values['global_goals'] = jsonify(goals_data)

        badges_earned = badges.util_badges.get_badge_notifications_json()
        template_values['badges_earned'] = badges_earned

        # Disable topic browser in the header on mobile devices
        template_values['watch_topic_browser_enabled'] = not self.is_mobile_capable()

        template_values['show_topic_pages'] = True

        return template_values
    def get(self, username=None, subpath=None):

        """Render a student profile.

        Keyword arguments:
        email_or_username -- matches the first grouping in /profile/(.+?)/(.*)
        subpath -- matches the second grouping, and is ignored server-side,
        but is used to route client-side

        """
        current_user_data = UserData.current() or UserData.pre_phantom()

        if current_user_data.is_pre_phantom and username is None:
            # Pre-phantom users don't have any profiles - just redirect them
            # to the homepage if they try to view their own.
            self.redirect(url_util.create_login_url(self.request.uri))
            return

        if not current_user_data.is_phantom and username == 'nouser':
            # If anybody has bookmarked, or gets redirected to, or otherwise
            # finds their way to /profile/nouser while they're logged in, just
            # redirect them to their actual profile.
            #
            # /profile/nouser is only sensible for phantom users and is never
            # used to look at another user's profile.
            self.redirect(current_user_data.profile_root)
            return

        if not username:
            user_data = current_user_data
        elif username == 'nouser' and current_user_data.is_phantom:
            user_data = current_user_data
        else:
            user_data = UserData.get_from_url_segment(username)
            if (user_models.UniqueUsername.is_valid_username(username)
                    and user_data
                    and user_data.username
                    and user_data.username != username):
                # The path segment is a username and resolved to the user,
                # but is not actually their canonical name. Redirect to the
                # canonical version.
                if subpath:
                    self.redirect("/profile/%s/%s" % (user_data.username,
                                                      subpath))
                else:
                    self.redirect("/profile/%s" % user_data.username)
                return

        profile = util_profile.UserProfile.from_user(user_data,
                current_user_data)

        if profile is None:
            self.render_jinja2_template('noprofile.html', {})
            return

        is_self = user_data.user_id == current_user_data.user_id
        show_intro = False
        show_discussion_intro = False

        if is_self:
            promo_record = promo_record_model.PromoRecord.get_for_values(
                    "New Profile Promo", user_data.user_id)

            if promo_record is None:
                # The user has never seen the new profile page! Show a tour.
                if subpath:
                    # But if they're not on the root profile page, force them.
                    self.redirect("/profile")
                    return

                show_intro = True
                promo_record_model.PromoRecord.record_promo(
                    "New Profile Promo", user_data.user_id, skip_check=True)
                # We also mark the "new discussion promo" as having been seen,
                # because it is a sub-set of the full tour, and new users don't
                # need to see it twice.
                promo_record_model.PromoRecord.record_promo(
                    "New Discussion Promo", user_data.user_id, skip_check=True)
            else:
                # The user has already seen the original profile page tour, but
                # not necessarily the "new discussion tab" tour.
                discussion_promo_record = (
                    promo_record_model.PromoRecord.get_for_values(
                        "New Discussion Promo", user_data.user_id))

                if discussion_promo_record is None:
                    # The user hasn't seen the new discussion promo.
                    show_discussion_intro = True
                    promo_record_model.PromoRecord.record_promo(
                        "New Discussion Promo", user_data.user_id,
                            skip_check=True)

        # This is the main capability bit - it indicates whether or not the
        # actor can view exercise, video, and goals data on the site for the
        # current profile.
        is_activity_visible = user_data.is_visible_to(current_user_data)

        # Resolve any other miscellaneous capabilities. This may need to be
        # changed if ACLing gets signicantly more complicated.
        if is_self:
            is_settings_available = not user_data.is_child_account()
            is_discussion_available = not user_data.is_child_account()
            is_coach_list_readable = True
            is_coach_list_writable = user_data.can_modify_coaches()
        else:
            is_actor_parent = ParentChildPair.is_pair(
                    parent_user_data=current_user_data,
                    child_user_data=user_data)
            is_settings_available = is_actor_parent
            is_discussion_available = (is_activity_visible and
                                       not user_data.is_child_account())
            is_coach_list_readable = is_actor_parent
            is_coach_list_writable = False

        tz_offset = self.request_int("tz_offset", default=0)

        # If profile is public and / or activity is visible,
        # include all the relevant data.
        if profile.is_public or is_activity_visible:
            template_values = {
                'show_intro': show_intro,
                'show_discussion_intro': show_discussion_intro,
                'profile': profile,
                'tz_offset': tz_offset,
                'count_videos': setting_model.Setting.count_videos(),
                'count_exercises': exercise_models.Exercise.get_count(),
                'user_data_student':
                    user_data if is_activity_visible else None,
                'profile_root': user_data.profile_root,
                'is_settings_available': is_settings_available,
                'is_coach_list_readable': is_coach_list_readable,
                'is_coach_list_writable': is_coach_list_writable,
                'is_discussion_available': is_discussion_available,
                'view': self.request_string("view", default=""),
            }

        # For private profiles
        else:
            template_values = {
                'profile': profile,
                'profile_root': profile.profile_root,
                'user_data_student': None,
                'count_videos': 0,
                'count_exercises': 0
            }
        self.render_jinja2_template('viewprofile.html', template_values)