def test_user_exercise_preserved_after_consuming(self): # A user goes on as a phantom... phantom = UserData.insert_for("phantom", "phantom") exercises = [ self.make_exercise("Adding 1"), self.make_exercise("Multiplication yo"), self.make_exercise("All about chickens"), ] # Does some exercises.... for e in exercises: ue = phantom.get_or_insert_exercise(e) ue.total_done = 7 ue.put() # Signs up! jimmy = UserData.insert_for("*****@*****.**", email="*****@*****.**") phantom.consume_identity(jimmy) # Make sure we can still see the old user exercises shouldbejimmy = UserData.get_from_user_id("*****@*****.**") user_exercises = (exercise_models.UserExercise.get_for_user_data( shouldbejimmy).fetch(100)) self.assertEqual(len(exercises), len(user_exercises)) for ue in user_exercises: self.assertEqual(7, ue.total_done)
def test_url_segment_generation(self): # Pre-phantom users can't have profile URL's prephantom = UserData.pre_phantom() self.assertTrue(self.from_url(self.to_url(prephantom)) is None) # Phantom users can't have profile URL's phantom = self.create_phantom() self.assertTrue(self.from_url(self.to_url(phantom)) is None) # Normal users are cool, though. bob = UserData.insert_for( "http://googleid.khanacademy.org/1234", "*****@*****.**") bob.put() self.assertEqual( self.from_url(self.to_url(bob)).user_id, bob.user_id) sally = UserData.insert_for( "http://facebookid.khanacademy.org/1234", "http://facebookid.khanacademy.org/1234") sally.put() self.assertEqual( self.from_url(self.to_url(sally)).user_id, sally.user_id)
def test_user_identity_consumption(self): superman = UserData.insert_for( "*****@*****.**", email="*****@*****.**", username="******", password="******", gender="male", ) clark = UserData.insert_for( "*****@*****.**", email="*****@*****.**", username=None, password=None, ) clark.consume_identity(superman) self.assertEqual("*****@*****.**", clark.user_id) self.assertEqual("*****@*****.**", clark.email) self.assertEqual(clark.key(), UserData.get_from_username("superman").key()) self.assertEqual( clark.key(), UserData.get_from_user_id("*****@*****.**").key()) self.assertTrue(clark.validate_password("Password1"))
def test_user_exercise_preserved_after_consuming(self): # A user goes on as a phantom... phantom = UserData.insert_for("phantom", "phantom") exercises = [ self.make_exercise("Adding 1"), self.make_exercise("Multiplication yo"), self.make_exercise("All about chickens"), ] # Does some exercises.... for e in exercises: ue = phantom.get_or_insert_exercise(e) ue.total_done = 7 ue.put() # Signs up! jimmy = UserData.insert_for("*****@*****.**", email="*****@*****.**") phantom.consume_identity(jimmy) # Make sure we can still see the old user exercises shouldbejimmy = UserData.get_from_user_id("*****@*****.**") user_exercises = (exercise_models.UserExercise. get_for_user_data(shouldbejimmy).fetch(100)) self.assertEqual(len(exercises), len(user_exercises)) for ue in user_exercises: self.assertEqual(7, ue.total_done)
def get(self): coach = UserData.current() user_override = self.request_user_data("coach_email") if user_override and user_override.are_students_visible_to(coach): # Only allow looking at a student list other than your own # if you are a dev, admin, or coworker. coach = user_override student_lists = StudentList.get_for_coach(coach.key()) student_lists_list = [{ 'key': 'allstudents', 'name': 'All students', }] for student_list in student_lists: student_lists_list.append({ 'key': str(student_list.key()), 'name': student_list.name, }) list_id, _ = get_last_student_list(self, student_lists, coach == UserData.current()) current_list = None for student_list in student_lists_list: if student_list['key'] == list_id: current_list = student_list selected_graph_type = self.request_string( "selected_graph_type") or ClassProgressReportGraph.GRAPH_TYPE if selected_graph_type == 'progressreport' or selected_graph_type == 'goals': # TomY This is temporary until all the graphs are API calls initial_graph_url = "/api/v1/user/students/%s?coach_email=%s&%s" % ( selected_graph_type, urllib.quote(coach.email), urllib.unquote( self.request_string("graph_query_params", default=""))) else: initial_graph_url = "/profile/graph/%s?coach_email=%s&%s" % ( selected_graph_type, urllib.quote(coach.email), urllib.unquote( self.request_string("graph_query_params", default=""))) initial_graph_url += 'list_id=%s' % list_id template_values = { 'user_data_coach': coach, 'coach_email': coach.email, 'list_id': list_id, 'student_list': current_list, 'student_lists': student_lists_list, 'student_lists_json': json.dumps(student_lists_list), 'coach_nickname': coach.nickname, 'selected_graph_type': selected_graph_type, 'initial_graph_url': initial_graph_url, 'exercises': exercise_models.Exercise.get_all_use_cache(), 'is_profile_empty': not coach.has_students(), 'selected_nav_link': 'coach', "view": self.request_string("view", default=""), 'stats_charts_class': 'coach-view', } self.render_jinja2_template('viewclassprofile.html', template_values)
def test_creation_with_existing_username(self): self.flush([self.insert_user("larry", "*****@*****.**", "larry")]) self.assertEqual(1, UserData.all().count()) self.assertEqual("larry", UserData.all()[0].user_id) self.assertEqual("larry", UserData.all()[0].username) self.assertTrue(self.insert_user("larry2", "*****@*****.**", "larry") is None)
def test_creation_with_existing_username(self): self.flush([self.insert_user("larry", "*****@*****.**", "larry")]) self.assertEqual(1, UserData.all().count()) self.assertEqual("larry", UserData.all()[0].user_id) self.assertEqual("larry", UserData.all()[0].username) self.assertTrue( self.insert_user("larry2", "*****@*****.**", "larry") is None)
def test_creation_with_password(self): self.flush([ self.insert_user("larry", "*****@*****.**", "larry", "Password1") ]) self.assertEqual(1, UserData.all().count()) retrieved = UserData.all()[0] self.assertEqual("larry", retrieved.user_id) self.assertTrue(retrieved.validate_password("Password1")) self.assertFalse(retrieved.validate_password("Password2"))
def test_creation_with_password(self): self.flush([self.insert_user("larry", "*****@*****.**", "larry", "Password1")]) self.assertEqual(1, UserData.all().count()) retrieved = UserData.all()[0] self.assertEqual("larry", retrieved.user_id) self.assertTrue(retrieved.validate_password("Password1")) self.assertFalse(retrieved.validate_password("Password2"))
def get(self): coach = UserData.current() user_override = self.request_user_data("coach_email") if user_override and user_override.are_students_visible_to(coach): # Only allow looking at a student list other than your own # if you are a dev, admin, or coworker. coach = user_override student_lists = StudentList.get_for_coach(coach.key()) student_lists_list = [{ 'key': 'allstudents', 'name': 'All students', }]; for student_list in student_lists: student_lists_list.append({ 'key': str(student_list.key()), 'name': student_list.name, }) list_id, _ = get_last_student_list(self, student_lists, coach==UserData.current()) current_list = None for student_list in student_lists_list: if student_list['key'] == list_id: current_list = student_list selected_graph_type = self.request_string("selected_graph_type") or ClassProgressReportGraph.GRAPH_TYPE if selected_graph_type == 'progressreport' or selected_graph_type == 'goals': # TomY This is temporary until all the graphs are API calls initial_graph_url = "/api/v1/user/students/%s?coach_email=%s&%s" % (selected_graph_type, urllib.quote(coach.email), urllib.unquote(self.request_string("graph_query_params", default=""))) else: initial_graph_url = "/profile/graph/%s?coach_email=%s&%s" % (selected_graph_type, urllib.quote(coach.email), urllib.unquote(self.request_string("graph_query_params", default=""))) initial_graph_url += 'list_id=%s' % list_id template_values = { 'user_data_coach': coach, 'coach_email': coach.email, 'list_id': list_id, 'student_list': current_list, 'student_lists': student_lists_list, 'student_lists_json': json.dumps(student_lists_list), 'coach_nickname': coach.nickname, 'selected_graph_type': selected_graph_type, 'initial_graph_url': initial_graph_url, 'exercises': exercise_models.Exercise.get_all_use_cache(), 'is_profile_empty': not coach.has_students(), 'selected_nav_link': 'coach', "view": self.request_string("view", default=""), 'stats_charts_class': 'coach-view', } self.render_jinja2_template('viewclassprofile.html', template_values)
def create_scratchpad(): """Create a new Scratchpad and associated ScratchpadRevision. The POST data should be a JSON-encoded dict, which is passed verbatim to Scratchpad.create as keyword arguments. """ if not gandalf.bridge.gandalf("scratchpads"): return api_forbidden_response( "Forbidden: You don't have permission to do this") if not request.json: return api_invalid_param_response("Bad data supplied: Not JSON") # TODO(jlfwong): Support phantom users user = UserData.current() if not (user and user.developer): # Certain fields are only modifiable by developers for field in scratchpad_models.Scratchpad._developer_only_fields: if request.json.get(field): return api_forbidden_response( "Forbidden: Only developers can change the %s" % field) try: # Convert unicode encoded JSON keys to strings create_args = dict_keys_to_strings(request.json) if user: create_args['user_id'] = user.user_id return scratchpad_models.Scratchpad.create(**create_args) except (db.BadValueError, db.BadKeyError), e: return api_invalid_param_response("Bad data supplied: " + e.message)
def post(self): user_data = UserData.current() if not user_data: return if user_data.is_child_account(): self.render_json({"error": "You cannot vote yet."}) return vote_type = self.request_int( "vote_type", default=discussion_models.FeedbackVote.ABSTAIN) if (vote_type == discussion_models.FeedbackVote.UP and not Privileges.can_up_vote(user_data)): self.render_json({ "error": Privileges.need_points_desc(Privileges.UP_VOTE_THRESHOLD, "up vote") }) return elif (vote_type == discussion_models.FeedbackVote.DOWN and not Privileges.can_down_vote(user_data)): self.render_json({ "error": Privileges.need_points_desc(Privileges.DOWN_VOTE_THRESHOLD, "down vote") }) return entity_key = self.request_string("entity_key", default="") if entity_key: entity = db.get(entity_key) if entity and entity.authored_by(user_data): self.render_json( {"error": "You cannot vote for your own posts."}) return if vote_type != discussion_models.FeedbackVote.ABSTAIN: limiter = VoteRateLimiter(user_data) if not limiter.increment(): self.render_json({"error": limiter.denied_desc()}) return # We kick off a taskqueue item to perform the actual vote insertion # so we don't have to worry about fast writes to the entity group # causing contention problems for the HR datastore, because # the taskqueue will just retry w/ exponential backoff. # TODO(marcia): user_data.email may change. user_id is preferred taskqueue.add(url='/admin/discussion/finishvoteentity', queue_name='voting-queue', params={ "email": user_data.email, "vote_type": self.request_int( "vote_type", default=discussion_models.FeedbackVote.ABSTAIN), "entity_key": entity_key })
def test_request_video(self): exs = exercise_models.Exercise.all().fetch(1000) user = UserData.current() self.assertFalse(exs[0].video_requested) exs[0].request_video() self.assertTrue(exs[0].video_requested) self.assertEqual(exs[0].video_requests_count, 1)
def post(self): template_values = {} user_data = UserData.current() status_file = StringIO.StringIO(self.request_string('status_file')) reader = csv.reader(status_file) student_list = [] for line in reader: student_email = line[0] student_status = line[1] student_comment = line[2] student = SummerStudent.all().filter('email =', student_email).get() if student is None: logging.error("Student %s not found" % student_email) continue student.application_status = student_status student.comment = student_comment if student_status == "Accepted": student.accepted = True student_list.append(student) db.put(student_list) self.response.out.write("OK") self.response.set_status(200)
def test_creation_without_username(self): added = [ self.insert_user("larry", "*****@*****.**"), self.insert_user("curly", "*****@*****.**"), self.insert_user("moe", "*****@*****.**"), ] # We don't care about consistency policy issues - we just want proper # counts and such. self.flush(added) self.assertEqual(3, UserData.all().count()) self.assertEqual(set(["larry", "curly", "moe"]), set(user.user_id for user in UserData.all())) # "Re-adding" moe doesn't duplicate. self.flush([self.insert_user("moe", "*****@*****.**")]) self.assertEqual(3, UserData.all().count())
def update_coaches(user_data, coaches_json): """ Add as coaches those in coaches_json with isCoachingLoggedInUser value True, and remove any old coaches not in coaches_json. Return a list of requesters' emails. """ updated_coach_key_emails = [] current_coaches_data = user_data.get_coaches_data() outstanding_coaches_dict = dict([(coach.email, coach.key_email) for coach in current_coaches_data]) requester_emails = [] for coach_json in coaches_json: email = coach_json['email'] is_coaching_logged_in_user = coach_json['isCoachingLoggedInUser'] if is_coaching_logged_in_user: if email in outstanding_coaches_dict: # Email corresponds to a current coach updated_coach_key_emails.append(outstanding_coaches_dict[email]) del outstanding_coaches_dict[email] else: # Look up this new coach's key_email coach_user_data = UserData.get_from_username_or_email(email) if coach_user_data is not None: updated_coach_key_emails.append(coach_user_data.key_email) else: raise custom_exceptions.InvalidEmailException() else: requester_emails.append(email) user_data.remove_student_lists(outstanding_coaches_dict.keys()) user_data.coaches = updated_coach_key_emails user_data.put() return requester_emails
def delete_scratchpad(scratchpad_id): """Mark a pre-existing Scratchpad as deleted. An empty request body is expected.""" if not gandalf.bridge.gandalf("scratchpads"): return api_forbidden_response( "Forbidden: You don't have permission to do this") user = UserData.current() scratchpad = scratchpad_models.Scratchpad.get_by_id(scratchpad_id) if not scratchpad or scratchpad.deleted: return api_not_found_response("No scratchpad with id %s" % scratchpad_id) # Users can only delete scratchpad they created # EXCEPTION: Developres can delete any scratchpad if not user.developer and scratchpad.user_id != user.user_id: return api_forbidden_response( "Forbidden: Scratchpad owned by different user") scratchpad.deleted = True scratchpad.put() return api_success_no_content_response()
def delete_scratchpad(scratchpad_id): """Mark a pre-existing Scratchpad as deleted. An empty request body is expected.""" if not gandalf.bridge.gandalf("scratchpads"): return api_forbidden_response( "Forbidden: You don't have permission to do this") user = UserData.current() scratchpad = scratchpad_models.Scratchpad.get_by_id(scratchpad_id) if not scratchpad or scratchpad.deleted: return api_not_found_response( "No scratchpad with id %s" % scratchpad_id) # Users can only delete scratchpad they created # EXCEPTION: Developres can delete any scratchpad if not user.developer and scratchpad.user_id != user.user_id: return api_forbidden_response( "Forbidden: Scratchpad owned by different user") scratchpad.deleted = True scratchpad.put() return api_success_no_content_response()
def test_return_key_in_profile_root_for_users_without_username(self): bob = UserData.insert_for( "http://googleid.khanacademy.org/1234", "*****@*****.**") desired_profile_root = ("/profile/" + _USER_KEY_PREFIX + str(bob.key()) + "/") self.assertEquals(desired_profile_root, bob.profile_root)
def post(self): user_data = UserData.current() if not user_data: return if user_data.is_child_account(): self.render_json({"error": "Je kan nog niet stemmen."}) return vote_type = self.request_int( "vote_type", default=discussion_models.FeedbackVote.ABSTAIN) if (vote_type == discussion_models.FeedbackVote.UP and not Privileges.can_up_vote(user_data)): self.render_json({ "error": Privileges.need_points_desc( Privileges.UP_VOTE_THRESHOLD, "up vote") }) return elif (vote_type == discussion_models.FeedbackVote.DOWN and not Privileges.can_down_vote(user_data)): self.render_json({ "error": Privileges.need_points_desc( Privileges.DOWN_VOTE_THRESHOLD, "down vote") }) return entity_key = self.request_string("entity_key", default="") if entity_key: entity = db.get(entity_key) if entity and entity.authored_by(user_data): self.render_json({ "error": "Je kan niet op je eigen opmerking stemmen." }) return if vote_type != discussion_models.FeedbackVote.ABSTAIN: limiter = VoteRateLimiter(user_data) if not limiter.increment(): self.render_json({"error": limiter.denied_desc()}) return # We kick off a taskqueue item to perform the actual vote insertion # so we don't have to worry about fast writes to the entity group # causing contention problems for the HR datastore, because # the taskqueue will just retry w/ exponential backoff. # TODO(marcia): user_data.email may change. user_id is preferred taskqueue.add( url='/admin/discussion/finishvoteentity', queue_name='voting-queue', params={ "email": user_data.email, "vote_type": self.request_int( "vote_type", default=discussion_models.FeedbackVote.ABSTAIN), "entity_key": entity_key } )
def get(self): developers = UserData.all() developers.filter('developer = ', True).fetch(1000) template_values = { "developers": developers, "selected_id": "devs", } self.render_jinja2_template('devpanel/devs.html', template_values)
def get(self): user_data = UserData.current() user_data_override = self.request_user_data("coach_email") if user_util.is_current_user_developer() and user_data_override: user_data = user_data_override invalid_student = self.request_bool("invalid_student", default=False) coach_requests = [req.student_requested_identifier for req in CoachRequest.get_for_coach(user_data) if req.student_requested_data] student_lists_models = StudentList.get_for_coach(user_data.key()) student_lists_list = [] for student_list in student_lists_models: student_lists_list.append({ 'key': str(student_list.key()), 'name': student_list.name, }) student_lists_dict = dict((g['key'], g) for g in student_lists_list) def student_to_dict(s): """Convert the UserData s to a dictionary for rendering.""" return { 'key': str(s.key()), 'email': s.email, 'username': s.username, # Note that child users don't have an email. 'identifier': s.username or s.email, 'nickname': s.nickname, 'profile_root': s.profile_root, 'can_modify_coaches': s.can_modify_coaches(), 'studentLists': [l for l in [student_lists_dict.get(str(list_id)) for list_id in s.student_lists] if l], } students_data = user_data.get_students_data() students = map(student_to_dict, students_data) students.sort(key=lambda s: s['nickname']) child_accounts = map(student_to_dict, user_data.get_child_users()) template_values = { 'students': students, 'child_accounts': child_accounts, 'child_account_keyset': set([c['key'] for c in child_accounts]), 'students_json': json.dumps(students), 'student_lists': student_lists_list, 'student_lists_json': json.dumps(student_lists_list), 'invalid_student': invalid_student, 'coach_requests': coach_requests, 'coach_requests_json': json.dumps(coach_requests), 'selected_nav_link': 'coach', 'email': user_data.email, } self.render_jinja2_template('viewstudentlists.html', template_values)
def get_coaches_all_students(): users = UserData.all() coaches_dict = {} for user in users: for coach in user.coaches: if not coach in coaches_dict: coaches_dict[coach] = [user.user_email] else: coaches_dict[coach].append(user.user_email) return coaches_dict
def do_request(self, student, coach, redirect_to): if not UserData.current(): self.redirect(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)
def get_user_scratchpads(): if not gandalf.bridge.gandalf("scratchpads"): return api_forbidden_response( "Forbidden: You don't have permission to do this") user_data = (get_visible_user_data_from_request() or UserData.pre_phantom()) return list(scratchpad_models.Scratchpad .get_for_user_data(user_data) .run(batch_size=1000))
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)
def get(self): user_data = UserData.current() user_video_css = video_models.UserVideoCss.get_for_user_data(user_data) self.response.headers['Content-Type'] = 'text/css' if user_video_css.version == user_data.uservideocss_version: # Don't cache if there's a version mismatch and update isn't finished self.response.headers['Cache-Control'] = 'public,max-age=1000000' self.response.out.write(user_video_css.video_css)
def get(self): coach = UserData.current() self.render_jinja2_template('coach_resources/view_demo.html', { "selected_id": "demo", "base_url": "/toolkit", "not_in_toolkit_format": 1, "is_logged_in": json.dumps(not coach.is_phantom if coach else False), })
def get_user_scratchpads(): if not gandalf.bridge.gandalf("scratchpads"): return api_forbidden_response( "Forbidden: You don't have permission to do this") user_data = (get_visible_user_data_from_request() or UserData.pre_phantom()) return list( scratchpad_models.Scratchpad.get_for_user_data(user_data).run( batch_size=1000))
def get_profile_target_user_data(self): coach = UserData.current() if coach: user_override = self.request_user_data("coach_email") if user_override and user_override.are_students_visible_to(coach): # Only allow looking at a student list other than your own # if you are a dev, admin, or coworker. coach = user_override return coach
def test_return_username_in_profile_root_if_exists(self): bob = UserData.insert_for( "http://googleid.khanacademy.org/1234", "*****@*****.**") username = "******" bob.claim_username(username) desired_profile_root = "/profile/" + username + "/" self.assertEquals(desired_profile_root, bob.profile_root)
def test_url_segment_generation(self): # Pre-phantom users can't have profile URL's prephantom = UserData.pre_phantom() self.assertTrue(self.from_url(self.to_url(prephantom)) is None) # Phantom users can't have profile URL's phantom = self.create_phantom() self.assertTrue(self.from_url(self.to_url(phantom)) is None) # Normal users are cool, though. bob = UserData.insert_for("http://googleid.khanacademy.org/1234", "*****@*****.**") bob.put() self.assertEqual(self.from_url(self.to_url(bob)).user_id, bob.user_id) sally = UserData.insert_for("http://facebookid.khanacademy.org/1234", "http://facebookid.khanacademy.org/1234") sally.put() self.assertEqual( self.from_url(self.to_url(sally)).user_id, sally.user_id)
def test_releasing_usernames(self): clock = testutil.MockDatetime() u1 = self.make_user("bob") u2 = self.make_user("robert") # u1 gets "superbob", but changes his mind. self.assertTrue(u1.claim_username("superbob", clock)) self.assertEqual("superbob", u1.username) self.assertTrue(u1.claim_username("ultrabob", clock)) self.assertEqual("ultrabob", u1.username) # TOTAL HACK - for some reason without this read (which shouldn't # actually have any side effect), the following assert fails because # there's no strong consistency ensured on the HRD. db.get([u1.key()]) self.assertEqual( u1.user_id, UserData.get_from_username("ultrabob").user_id) self.assertEqual( None, UserData.get_from_username("superbob")) # Usernames go into a holding pool, even after they're released self.assertFalse(u2.claim_username("superbob", clock)) # Note that the original owner can't even have it back self.assertFalse(u1.claim_username("superbob", clock)) # Still no good at the border of the holding period clock.advance(UniqueUsername.HOLDING_PERIOD_DELTA) self.assertFalse(u2.claim_username("superbob", clock)) # OK - now u2 can have it. clock.advance_days(1) self.assertTrue(u2.claim_username("superbob", clock)) self.assertEqual("superbob", u2.username) db.get([u2.key()]) self.assertEqual( u2.user_id, UserData.get_from_username("superbob").user_id)
def get(self): template_values = {} user_data = UserData.current() if user_data is not None: return self.authenticated_response() else: template_values = { "authenticated" : False, } self.add_global_template_values(template_values) self.render_jinja2_template('summer/summer_process.html', template_values)
def get(self): coach = UserData.current() self.render_jinja2_template( 'coach_resources/view_demo.html', { "selected_id": "demo", "base_url": "/toolkit", "not_in_toolkit_format": 1, "is_logged_in": json.dumps(not coach.is_phantom if coach else False), })
def get_coaches_students_count(): coaches_dict = get_coaches_all_students() coaches_list = [] for coach_email, students_list in coaches_dict.items(): coach = UserData.all().filter("user_email = ", coach_email).get() if coach: coach_dict = { "joined": str(coach.joined), "last_activity": str(coach.last_activity), "coach_email": coach_email, "number_of_students": len(students_list) } coaches_list.append(coach_dict) return coaches_list
def test_releasing_usernames(self): clock = testutil.MockDatetime() u1 = self.make_user("bob") u2 = self.make_user("robert") # u1 gets "superbob", but changes his mind. self.assertTrue(u1.claim_username("superbob", clock)) self.assertEqual("superbob", u1.username) self.assertTrue(u1.claim_username("ultrabob", clock)) self.assertEqual("ultrabob", u1.username) # TOTAL HACK - for some reason without this read (which shouldn't # actually have any side effect), the following assert fails because # there's no strong consistency ensured on the HRD. db.get([u1.key()]) self.assertEqual(u1.user_id, UserData.get_from_username("ultrabob").user_id) self.assertEqual(None, UserData.get_from_username("superbob")) # Usernames go into a holding pool, even after they're released self.assertFalse(u2.claim_username("superbob", clock)) # Note that the original owner can't even have it back self.assertFalse(u1.claim_username("superbob", clock)) # Still no good at the border of the holding period clock.advance(UniqueUsername.HOLDING_PERIOD_DELTA) self.assertFalse(u2.claim_username("superbob", clock)) # OK - now u2 can have it. clock.advance_days(1) self.assertTrue(u2.claim_username("superbob", clock)) self.assertEqual("superbob", u2.username) db.get([u2.key()]) self.assertEqual(u2.user_id, UserData.get_from_username("superbob").user_id)
def get(self): coach = UserData.current() if coach is not None: coach_email = coach.email is_profile_empty = not coach.has_students() else: coach_email = None is_profile_empty = True self.render_jinja2_template('coach_resources/view_resources.html', { 'selected_id': 'coach-resources', 'coach_email': coach_email, 'is_profile_empty': is_profile_empty, })
def test_user_identity_consumption(self): superman = UserData.insert_for( "*****@*****.**", email="*****@*****.**", username="******", password="******", gender="male", ) clark = UserData.insert_for( "*****@*****.**", email="*****@*****.**", username=None, password=None, ) clark.consume_identity(superman) self.assertEqual("*****@*****.**", clark.user_id) self.assertEqual("*****@*****.**", clark.email) self.assertEqual(clark.key(), UserData.get_from_username("superman").key()) self.assertEqual(clark.key(), UserData.get_from_user_id("*****@*****.**").key()) self.assertTrue(clark.validate_password("Password1"))
def get(self): coach = UserData.current() if coach is not None: coach_email = coach.email is_profile_empty = not coach.has_students() else: coach_email = None is_profile_empty = True self.render_jinja2_template( 'coach_resources/view_resources.html', { 'selected_id': 'coach-resources', 'coach_email': coach_email, 'is_profile_empty': is_profile_empty, })
def get(self): user_data = UserData.current() from exercises.exercise_util import exercise_graph_dict_json context = { 'graph_dict_data': exercise_graph_dict_json(user_data), 'user_data': user_data, 'map_coords': json.dumps(deserializeMapCoords(user_data.map_coords)), # Get pregenerated library content from our in-memory/memcache # two-layer cache 'library_content': library_content_html(), } self.render_jinja2_template("goals/creategoal.html", context)
def post(self): user_data = UserData.current() user_data_student = self.request_student_user_data() if user_data_student: if not user_data_student.is_coached_by(user_data): coach_request = CoachRequest.get_or_insert_for(user_data, user_data_student) if coach_request: if not self.is_ajax_request(): self.redirect("/students") return if self.is_ajax_request(): self.response.set_status(404) else: self.redirect("/students?invalid_student=1")
def get(self): user_data = UserData.current() sort = self.request_int("sort", default=VotingSortOrder.HighestPointsFirst) if user_data: user_data.question_sort_order = sort user_data.put() readable_id = self.request_string("readable_id", default="") topic_title = self.request_string("topic_title", default="") if readable_id and topic_title: self.redirect("/video/%s?topic=%s&sort=%s" % ( urllib.quote(readable_id), urllib.quote(topic_title), sort)) else: self.redirect("/")
def get(self): template_values = {} user_data = UserData.current() if user_data is not None: template_values = self.authenticated_response() if template_values is None: self.redirect("/summer/application") return else: template_values = { "authenticated" : False, } self.add_global_template_values(template_values) self.render_jinja2_template('summer/summer_status.html', template_values)
def update_scratchpad(scratchpad_id): """Update a pre-existing Scratchpad and create a new ScratchpadRevision. The POST data should be a JSON-encoded dict, which is passsed verbatim to Scratchpad.update as keyword arguments. """ if not gandalf.bridge.gandalf("scratchpads"): return api_forbidden_response( "Forbidden: You don't have permission to do this") if not request.json: return api_invalid_param_response("Bad data supplied: Not JSON") user = UserData.current() scratchpad = scratchpad_models.Scratchpad.get_by_id(scratchpad_id) if not scratchpad or scratchpad.deleted: return api_not_found_response("No scratchpad with id %s" % scratchpad_id) if not user.developer: # Certain fields are only modifiable by developers for field in scratchpad_models.Scratchpad._developer_only_fields: if request.json.get(field): return api_forbidden_response( "Forbidden: Only developers can change the %s" % field) # The user can update the scratchpad if any of the following are true: # 1. The scratchpad is tutorial/official and the user is a developer # 2. The scratchpad was created by the user if scratchpad.category in ("tutorial", "official") and user.developer: pass elif scratchpad.user_id != user.user_id: # Only the creator of a scratchpad can update it return api_forbidden_response( "Forbidden: Scratchpad owned by different user") try: # Convert unicode encoded JSON keys to strings update_args = dict_keys_to_strings(request.json) if 'id' in update_args: # Backbone passes the id in update calls - ignore it del update_args['id'] return scratchpad.update(**update_args) except (db.BadValueError, db.BadKeyError), e: return api_invalid_param_response("Bad data supplied: " + e.message)
def update_scratchpad(scratchpad_id): """Update a pre-existing Scratchpad and create a new ScratchpadRevision. The POST data should be a JSON-encoded dict, which is passsed verbatim to Scratchpad.update as keyword arguments. """ if not gandalf.bridge.gandalf("scratchpads"): return api_forbidden_response( "Forbidden: You don't have permission to do this") if not request.json: return api_invalid_param_response("Bad data supplied: Not JSON") user = UserData.current() scratchpad = scratchpad_models.Scratchpad.get_by_id(scratchpad_id) if not scratchpad or scratchpad.deleted: return api_not_found_response( "No scratchpad with id %s" % scratchpad_id) if not user.developer: # Certain fields are only modifiable by developers for field in scratchpad_models.Scratchpad._developer_only_fields: if request.json.get(field): return api_forbidden_response( "Forbidden: Only developers can change the %s" % field) # The user can update the scratchpad if any of the following are true: # 1. The scratchpad is tutorial/official and the user is a developer # 2. The scratchpad was created by the user if scratchpad.category in ("tutorial", "official") and user.developer: pass elif scratchpad.user_id != user.user_id: # Only the creator of a scratchpad can update it return api_forbidden_response( "Forbidden: Scratchpad owned by different user") try: # Convert unicode encoded JSON keys to strings update_args = dict_keys_to_strings(request.json) if 'id' in update_args: # Backbone passes the id in update calls - ignore it del update_args['id'] return scratchpad.update(**update_args) except (db.BadValueError, db.BadKeyError), e: return api_invalid_param_response("Bad data supplied: " + e.message)
def award_author_badges(self, entity): user_data_author = UserData.get_from_db_key_email(entity.author.email()) if not user_data_author: return possible_badges = badges_with_context_type(BadgeContextType.FEEDBACK) awarded = False for badge in possible_badges: if not badge.is_already_owned_by(user_data=user_data_author, feedback=entity): if badge.is_satisfied_by(user_data=user_data_author, feedback=entity): badge.award_to(user_data=user_data_author, feedback=entity) awarded = True if awarded: user_data_author.put()
def authenticated_response(self): user_data = UserData.current() user_email = user_data.user_email nickname = "" if facebook_util.is_facebook_user_id(user_email): nickname = facebook_util.get_facebook_nickname(user_email) query = SummerStudent.all() query.filter('email = ', user_email) student = query.get() students = [] is_parent = False if student is None: query = SummerParentData.all() query.filter('email = ', user_email) parent = query.get() if parent is None: return None is_parent = True number_of_students = 0 for student_key in parent.students: student = SummerStudent.get(student_key) students.append(student) if student.accepted and not student.tuition_paid: number_of_students += 1 else: number_of_students = 1 students.append(student) template_values = { "authenticated" : True, "is_parent" : is_parent, "students" : students, "number_of_students": json.dumps(number_of_students), "student" : students[0], "user_email" : user_email, "nickname" : nickname, } return template_values