def admin_login(): """ Login a user :return: """ # Pass the post details post = Utils.parse_json(request) # Check if email and password in the post if 'email' not in post or 'password' not in post: return Respond.error("Email password not found", error_code=422) # Find the user with that email user = User.query(User.email == post['email']).get() # If user not found if user is None: return Respond.error("User not found with the provided email", error_code=404) if user.type != "Admin" and user.type != "Creator": return Respond.error("Login with password not allowed", error_code=422) # If password not correct if not user.verify_password(post['password']): return Respond.error("Password incorrect") # Make token token = user.make_token() # Respond with user and token return Respond.success({"token": token, "user": user.as_dict()})
def mark_concept_important(user, concept_key): """ Mark a concept as important """ concept = Utils.urlsafe_to_key(concept_key).get() # Get the user data for the concept user_data = UserConcept.query(UserConcept.concept == concept.key, ancestor=user.key).get() if not user_data: subject = concept.key.parent().parent() user_data = UserConcept(subject=subject, concept=concept.key, important=True, parent=user.key) user_data.put() else: if user_data.important: return Respond.error('Concept already marked important') user_data.important = True user_data.put() return Respond.success('Concept marked important')
def subject_test(user, subject_key): """ Send test concepts """ subject_key = Utils.urlsafe_to_key(subject_key) session_data = user.getSession() if session_data['views'] < 5: return Respond.error("Not enough views left", error_code=400) # Find revised concepts concepts = UserConcept.query(UserConcept.subject == subject_key, ancestor=user.key).fetch() # select 5 randomly if len(concepts) < 5: return Respond.error("Less than 5 concepts read", error_code=400) # Unique indices random_nums = random.sample(range(1, len(concepts)), 5) test_concepts = [] for i in random_nums: test_concepts.append(concepts[i].concept.get().to_dict()) user.subtractSessionViews(5) return Respond.success({ "concepts": test_concepts, "session_data": user.getSession() })
def activate_pro(user): """ Activate pro usage for the user :param user: :return: Response """ # Perform checks if user.getPoints() < PRO_COST: return Respond.error('Low balance', error_code=420) if user.pro: return Respond.error('User already a pro', error_code=410) post = Utils.parse_json(request) users_with_device = User.query(User.device == post['device']).fetch() if len(users_with_device) > 0: return Respond.error('Device already registered by another user') # Activate Pro for user on this device user.subtractPoints(PRO_COST, 'Activated Pro') user.pro = True user.device = post['device'] user.put() return Respond.success('Activated pro for user')
def get(user): course = user.course.get() if not course: return Respond.error("User not subscribed to a course", error_code=400) subjects = map(Subject.dict_for_list, Subject.query(ancestor=course.key).fetch()) return Respond.success({"subjects": subjects})
def read_concept(user, concept_key): """ Send the concept to the user """ if not user_has_views(user, 1): return Respond.error('Not enough views left', error_code=420) concept = Utils.urlsafe_to_key(concept_key).get() return Respond.success({"concept": concept.to_dict()})
def wrapper_func(*args, **kwargs): token = request.headers.get('Authorization') if token is None: return Respond.error('Auth Required', 401) user = User.from_token(token) if user is None: return Respond.error('User not found', 400) else: return original_function(user, *args, **kwargs)
def social_login(): """ Login via google With the id token get user details, if the user does not exist then create it. If the user is coming back then just save the id token Then make a token and send it to the client """ post = Utils.parse_json(request) id_token = post['id_token'] url = 'https://www.googleapis.com/oauth2/v3/tokeninfo?id_token=%s' % id_token try: result = urlfetch.fetch(url) if result.status_code == 200: result = json.loads(result.content) name = result['name'] email = result['email'] picture = result['picture'] else: error = 'Status code: {} , Response: {}'.format( result.status_code, result.content) logging.error(error) return Respond.error('Error getting user info from google.') except urlfetch.Error: logging.exception('Caught exception fetching url') return Respond.error('Error getting user info from google.') users = User.query(User.email == email).fetch() if len(users) > 1: return Respond.error("There was an error", error_code=422) elif len(users) == 1: # User already exists. Just make a token and return user = users[0] # Make token token = user.make_token() # Respond with user and token return Respond.success({"token": token, "user": user.as_dict()}) else: # New User. Create and send token user = User(name=name, email=email, picture_uri=picture) user.put() # Make token token = user.make_token() # Respond with user and token return Respond.success({"token": token, "user": user.as_dict()})
def wrapper_func(*args, **kwargs): token = request.headers.get('Authorization') if token is None: return Respond.error('Auth Required', 401) user = User.from_token(token) if user is None: return Respond.error('User not found', 400) elif (user.type != 'Admin' and user.type != 'Creator'): return Respond.error("Permission Denied", 422) else: return original_function(user, *args, **kwargs)
def done_concept(user, concept_key): """ Mark a concept as done """ # get the concept data entity concept_data = UserConceptData.query( UserConceptData.concept == Utils.urlsafe_to_key(concept_key), ancestor=user.key).get() if not concept_data: return Respond.error(error="No data of user for this concept") # mark it as understood concept_data.done = True concept_data.put() # return return Respond.success("Marked done")
def reset_session(user): if user.getPoints() < RESET_COST: return Respond.error('User does not have enough points', error_code=400) user.subtractPoints(RESET_COST, "Skipped cooldown") session = UserSession(views=PER_SESSION_VIEWS, parent=user.key) session.put() return Respond.success({ "session": session.as_dict(), "balance": user.getPoints() })
def wrong_concept(user, concept_key): """ Mark a concept as wrong """ # get the concept data entity concept_data = UserConceptData.query( UserConceptData.concept == Utils.urlsafe_to_key(concept_key), ancestor=user.key).get() if not concept_data: return Respond.error(error="No data of user for this concept") # mark done as false concept_data.done = False concept_data.put() # return return Respond.success("Marked wrong")
def right_concept(user, concept_key): """ Mark a concept as right """ # get the concept data entity concept_data = UserConceptData.query( UserConceptData.concept == Utils.urlsafe_to_key(concept_key), ancestor=user.key).get() if not concept_data: return Respond.error(error="No data of user for this concept") # increase right count concept_data.right = concept_data.right + 1 concept_data.put() # return return Respond.success("Marked right")
def update(user, concept_key): """ Update a concept :param user: :param concept_key: :return: Updated concept """ concept = ndb.Key(urlsafe=concept_key).get() post = Utils.parse_json(request) if 'name' in post: concept.name = post['name'] if 'explanation' in post: concept.explanation = post['explanation'] if 'references' in post: references = [] for ref in post['references']: reference = References(title=ref['title'], source=ref['source']) references.append(reference) concept.references = references if 'tips' in post: concept.tips = post['tips'] if 'questions' in post: concept.questions = post['questions'] concept.put() return Respond.success({'concept': concept.to_dict()})
def get(user): """ Get all the available courses """ courses = map(Course.as_dict, Course.query().fetch()) return Respond.success({"courses": courses})
def payment_status(user, payment_key): payment_request = Utils.urlsafe_to_key(payment_key).get() return Respond.success({ 'status': payment_request.status, 'balance': user.getPoints() })
def test_result(user, subject_key): """ Save the result and calculate points """ # subject = Utils.urlsafe_to_key(subject_key).get() post = Utils.parse_json(request) points_counter = 0 for result in post['result']: if result['marked'] == "right": UserTests(concept=Utils.urlsafe_to_key(result['key']), right=True, parent=user.key).put() user.addPoints(1, "Answered correctly") points_counter += 1 if result['marked'] == "wrong": UserTests(concept=Utils.urlsafe_to_key(result['key']), right=False, parent=user.key).put() user.addPoints(1, "Answered incorrectly") points_counter += 1 return Respond.success({ "new_points": points_counter, "balance": user.getPoints() })
def revision_result(user, subject_key): """ Save the result and calculate points """ subject = Utils.urlsafe_to_key(subject_key).get() post = Utils.parse_json(request) points_counter = 0 for result in post['result']: if result['marked'] == "read": concept = Utils.urlsafe_to_key(result['key']).get() data = UserConcept.query(UserConcept.concept == concept.key, ancestor=user.key).get() if not data: data = UserConcept(parent=user.key, subject=subject.key, concept=concept.key) data.read += 1 data.put() user.addPoints(1, "Read concept") points_counter += 1 return Respond.success({ "new_points": points_counter, "balance": user.getPoints() })
def subject_index(user, subject_key): subject = Utils.urlsafe_to_key(subject_key).get() index = [] chapters = Chapter.query(ancestor=subject.key).order(Chapter.srno) # user_data = UserConcept.query( # UserConcept.subject == subject.key, # ancestor=user.key # ).fetch() for chapter in chapters: concepts = [] concepts_list = Concept.query(ancestor=chapter.key).order(Concept.srno) for concept in concepts_list: concepts.append({"key": concept.key, "name": concept.name}) for concept in concepts: # for data in user_data: # if data.concept == concept['key']: # concept['read'] = data.read # concept['important'] = data.important concept['key'] = concept['key'].urlsafe() index.append({ "key": chapter.key.urlsafe(), "name": chapter.name, "concepts": concepts }) return Respond.success({"index": index})
def subject_revise(user, subject_key): """ Send revision concepts """ # Find not read concepts # Fetch the first 5 from them # Send concepts subject = Utils.urlsafe_to_key(subject_key).get() session_data = user.getSession() if session_data['views'] < 5: return Respond.error("Not enough views left", error_code=420) user_concepts = UserConcept.query(UserConcept.subject == subject.key, ancestor=user.key).fetch() chapters = Chapter.query(ancestor=subject.key).order(Chapter.srno) revision_concepts = [] for chapter in chapters: concepts = Concept.query(ancestor=chapter.key).order( Concept.srno).fetch() for concept in concepts: if len(revision_concepts) < 5: if any(x.concept == concept.key for x in user_concepts): pass else: revision_concepts.append(concept.to_dict()) else: break if len(revision_concepts) is 0: return Respond.error("No concepts left to revise", error_code=400) user.subtractSessionViews(len(revision_concepts)) return Respond.success({ "concepts": revision_concepts, "session_data": user.getSession() })
def get_chapters(user, subject_key): subject = Utils.urlsafe_to_key(subject_key).get() chapters = map( Chapter.for_list, Chapter.query(ancestor=subject.key).order(Chapter.srno).fetch()) return Respond.success({"chapters": chapters})
def delete(user, concept_key): """ Delete the concept. Remove from chapter index """ concept = ndb.Key(urlsafe=concept_key).get() concept.key.delete() return Respond.success({"deleted_key": concept_key})
def save_data_offline(user, subject_key): """ Send a json file to download all concept data of the subject """ if not user.pro: return Respond.error('User not a pro', error_code=410) subject = Utils.urlsafe_to_key(subject_key).get() index = [] user_data_list = UserConcept.query(UserConcept.subject == subject.key, ancestor=user.key).fetch() user_data = {} for data in user_data_list: user_data[data.concept.urlsafe()] = { 'important': data.important, 'read': data.read } chapters = Chapter.query(ancestor=subject.key).order(Chapter.srno) for chapter in chapters: concepts = [] concept_list = Concept.query(ancestor=chapter.key).order(Concept.srno) for concept in concept_list: concept_data = concept.to_dict() key = concept_data['key'] if key in user_data: concept_data.update(user_data[key]) concepts.append(concept_data) index.append({ "name": chapter.name, "key": chapter.key.urlsafe(), "concepts": concepts }) return Respond.success(index)
def store(user): """ Store a course. :param user: :return: """ post = Utils.parse_json(request) course = Course(name=post['name']) course.put() return Respond.success(Course.as_dict(course))
def store(user): """ Store a concept. :param user: :return: """ post = Utils.parse_json(request) if 'name' not in post or 'chapter_key' not in post: return Respond.error("Input not valid", error_code=422) chapter_key = ndb.Key(urlsafe=post['chapter_key']) srno = Concept.query(ancestor=chapter_key).count() concept = Concept(name=post['name'], srno=srno, parent=chapter_key) concept.put() return Respond.success({'concept': concept.to_dict()})
def admin_register(user): """ Get the post variables and register the user :return: User token """ # parse the json request post = Utils.parse_json(request) # Check if basic account info is in the post if 'name' not in post or 'email' not in post or 'password' not in post: return Respond.error("Validation Error", error_code=422) # Check if email has not registered before if User.query(User.email == post['email']).count() > 0: return Respond.error("User account with this email already registered", 401) # Create a user model user = User(name=post['name'], email=post['email'], password=User.hash_password(post['password']), type=post['type']) # Add other properties of the user if sent if 'year' in post: user.year = post['year'] if 'course' in post: user.course = post['course'] if 'college' in post: user.college = post['college'] if 'picture_uri' in post: user.picture_uri = post['picture_uri'] # Save the user user.put() # Make a token for the user token = user.make_token() # Respond with the token return Respond.success({"token": token, "user": user.as_dict()})
def store(user): """ Store a subject. :param user: :return: """ post = Utils.parse_json(request) subject = Subject(name=post['name'], parent=user.course) subject.put() return Respond.success(subject.dict_for_list())
def add_code_for_user(user, user_key): """ Add a code for a user to user """ post = Utils.parse_json(request) UserCodes(parent=Utils.urlsafe_to_key(user_key), code=post['code'], points=post['points']).put() return Respond.success("Code added")
def get_batch_concepts(user): """ Send concepts required by in the request :param user: :return: """ post = Utils.parse_json(request) concepts = post['concepts'] if not user_has_views(user, len(concepts)): return Respond.error('Not enough views left', error_code=420) response = [] for concept in concepts: entity = Utils.urlsafe_to_key(concept).get() response.append(entity.to_dict()) return Respond.success({"concepts": response})
def subscribe(user, course_key): """ Subscribe a course :param user: :param course_key: :return: Response """ post = Utils.parse_json(request) user.course = Utils.urlsafe_to_key(course_key) user.college = post['college'] user.put() return Respond.success("Course subscribed by user")