def get_achievement_level(request): """get all information about an achievement for a specific level""" try: achievement_id = int(request.matchdict.get("achievement_id", None)) level = int(request.matchdict.get("level", None)) except: raise APIError(400, "invalid_input", "invalid input") achievement = Achievement.get_achievement(achievement_id) if not achievement: raise APIError(404, "achievement_not_found", "achievement not found") level_output = Achievement.basic_output(achievement, True, level).get("levels").get( str(level), { "properties": {}, "rewards": {} }) if "goals" in level_output: del level_output["goals"] if "level" in level_output: del level_output["level"] return level_output
def get_progress(request): """get all relevant data concerning the subject's progress""" try: subject_id = int(request.matchdict["subject_id"]) except: raise APIError(400, "illegal_subject_id", "no valid subject_id given") subject = Subject.get_subject(subject_id) if not subject: raise APIError(404, "subject_not_found", "subject not found") try: achievement_id = int(request.GET["achievement_id"]) except: achievement_id = None try: achievement_history = int(request.GET["achievement_history"]) except: achievement_history = 2 output = _get_progress(achievements_for_subject=subject, requesting_subject=request.subject, achievement_id=achievement_id, achievement_history=achievement_history) output = copy.deepcopy(output) for i in range(len(output["achievements"])): if "new_levels" in output["achievements"][i]: del output["achievements"][i]["new_levels"] return output
def increase_multi_values(request): try: doc = request.json_body except: raise APIError(400, "invalid_json", "no valid json body") ret = {} for user_id, values in doc.items(): user = User.get_user(user_id) if not user: raise APIError(404, "user_not_found", "user %s not found" % (user_id, )) for variable_name, values_and_keys in values.items(): for value_and_key in values_and_keys: variable = Variable.get_variable_by_name(variable_name) if asbool(get_settings().get("enable_user_authentication", False)): if not Variable.may_increase(variable, request, user_id): raise APIError( 403, "forbidden", "You may not increase the variable %s for user %s." % (variable_name, user_id)) if not variable: raise APIError(404, "variable_not_found", "variable %s not found" % (variable_name, )) if not 'value' in value_and_key: raise APIError(400, "variable_not_found", "illegal value for %s" % (variable_name, )) value = value_and_key['value'] key = value_and_key.get('key', '') Value.increase_value(variable_name, user, value, key) output = _get_progress(achievements_for_user=user, requesting_user=request.user) output = copy.deepcopy(output) to_delete = list() for i in range(len(output["achievements"])): if len(output["achievements"][i]["new_levels"]) > 0: if "levels" in output["achievements"][i]: del output["achievements"][i]["levels"] if "priority" in output["achievements"][i]: del output["achievements"][i]["priority"] if "goals" in output["achievements"][i]: del output["achievements"][i]["goals"] else: to_delete.append(i) for i in sorted(to_delete, reverse=True): del output["achievements"][i] if len(output["achievements"]) > 0: ret[user_id] = output return ret
def increase_value(request): """increase a value for the user""" user_id = int(request.matchdict["user_id"]) try: value = float(request.POST["value"]) except: try: doc = request.json_body value = doc["value"] except: raise APIError(400, "invalid_value", "Invalid value provided") key = request.matchdict["key"] if ( "key" in request.matchdict and request.matchdict["key"] is not None) else "" variable_name = request.matchdict["variable_name"] user = User.get_user(user_id) if not user: raise APIError(404, "user_not_found", "user not found") variable = Variable.get_variable_by_name(variable_name) if not variable: raise APIError(404, "variable_not_found", "variable not found") if asbool(get_settings().get("enable_user_authentication", False)): if not Variable.may_increase(variable, request, user_id): raise APIError(403, "forbidden", "You may not increase the variable for this user.") Value.increase_value(variable_name, user, value, key) output = _get_progress(achievements_for_user=user, requesting_user=request.user) output = copy.deepcopy(output) to_delete = list() for i in range(len(output["achievements"])): if len(output["achievements"][i]["new_levels"]) > 0: if "levels" in output["achievements"][i]: del output["achievements"][i]["levels"] if "priority" in output["achievements"][i]: del output["achievements"][i]["priority"] if "goals" in output["achievements"][i]: del output["achievements"][i]["goals"] else: to_delete.append(i) for i in sorted(to_delete, reverse=True): del output["achievements"][i] return output
def get_leaderboard_achievement(request): try: achievement_id = int(request.matchdict["achievement_id"]) except: raise APIError(400, "illegal_achievement_id", "no valid achievement_id given") return Achievement.get_leaderbord_by_achievement(achievement_id)
def get_user(request): if not asbool(settings.get("enable_user_authentication",False)): return None token = request.headers.get('X-Auth-Token') if token is not None: from gengine.app.model import DBSession, AuthUser, AuthToken tokenObj = DBSession.query(AuthToken).filter(AuthToken.token==token).first() user = None if tokenObj and tokenObj.valid_until<datetime.datetime.utcnow(): tokenObj.extend() if tokenObj: user = tokenObj.user if not user: raise APIError(401, "invalid_token", "Invalid token provided.") if not user.active: raise APIError(404, "user_is_not_activated", "Your user is not activated.") return user return None
def register_device(request): try: doc = request.json_body except: raise APIError(400, "invalid_json", "no valid json body") subject_id = int(request.matchdict["subject_id"]) device_id = doc.get("device_id") push_id = doc.get("push_id") device_os = doc.get("device_os") app_version = doc.get("app_version") if not device_id \ or not push_id \ or not subject_id \ or not device_os \ or not app_version: raise APIError( 400, "register_device.required_fields", "Required fields: device_id, push_id, device_os, app_version") if asbool(get_settings().get("enable_user_authentication", False)): may_register = request.has_perm( perm_global_register_device ) or request.has_perm(perm_own_register_device) and str( request.subject.id) == str(subject_id) if not may_register: raise APIError(403, "forbidden", "You may not register devices for this subject.") if not exists_by_expr(t_subjects, t_subjects.c.id == subject_id): raise APIError(404, "register_device.subject_not_found", "There is no subject with this id.") SubjectDevice.add_or_update_device(subject_id=subject_id, device_id=device_id, push_id=push_id, device_os=device_os, app_version=app_version) return {"status": "ok"}
def get_position_user(request): """get all relevant data concerning the user's progress""" try: user_id = int(request.matchdict["user_id"]) except: raise APIError(400, "illegal_user_id", "no valid user_id given") user = User.get_user(user_id) if not user: raise APIError(404, "user_not_found", "user not found") output = _get_progress(achievements_for_user=user, requesting_user=request.user) output = copy.deepcopy(output) Achievements = [] for i in range(len(output["achievements"])): if "new_levels" in output["achievements"][i]: del output["achievements"][i]["new_levels"] achievement = {} achievement["achievement_name"] = output["achievements"][i][ "internal_name"] achievement["achievement_category"] = output["achievements"][i][ "achievementcategory"] achievement["maxlevel"] = output["achievements"][i]["maxlevel"] achievement["level"] = output["achievements"][i]["level"] goals = output["achievements"][i]["goals"] for goal in goals: if "leaderboard" in goals[goal]: del goals[goal]["leaderboard"] if "properties" in goals[goal]: del goals[goal]["properties"] if "priority" in goals[goal]: del goals[goal]["priority"] if "leaderboard_position" in goals[goal]: goals[goal]["leaderboard_position"] = goals[goal][ "leaderboard_position"] + 1 achievement["goals"] = goals Achievements.append(achievement) res = {'user': user["id"], 'achievements': Achievements} return res
def auth_login(request): try: doc = request.json_body except: raise APIError(400, "invalid_json", "no valid json body") user = request.user email = doc.get("email") password = doc.get("password") if user: #already logged in token = user.get_or_create_token().token else: if not email or not password: raise APIError(400, "login.email_and_password_required", "You need to send your email and password.") user = DBSession.query(AuthUser).filter_by(email=email).first() if not user or not user.verify_password(password): raise APIError( 401, "login.email_or_password_invalid", "Either the email address or the password is wrong.") if not user.active: raise APIError(400, "user_is_not_activated", "Your user is not activated.") if user.force_password_change: raise APIError(400, "user_has_to_change_password", "You have to change your password.") token = AuthToken.generate_token() tokenObj = AuthToken(auth_user_id=user.id, token=token) DBSession.add(tokenObj) return { "token": token, "subject": Subject.full_output(user.subject_id), }
def get_progress(request): """get all relevant data concerning the user's progress""" try: user_id = int(request.matchdict["user_id"]) except: raise APIError(400, "illegal_user_id", "no valid user_id given") user = User.get_user(user_id) if not user: raise APIError(404, "user_not_found", "user not found") output = _get_progress(achievements_for_user=user, requesting_user=request.user) output = copy.deepcopy(output) for i in range(len(output["achievements"])): if "new_levels" in output["achievements"][i]: del output["achievements"][i]["new_levels"] return output
def get_leaderboard_user(request): try: achievement_id = int(request.matchdict["achievement_id"]) except: raise APIError(400, "illegal_achievement_id", "no valid achievement_id given") try: user_id = int(request.matchdict["user_id"]) except: raise APIError(400, "illegal_user_id", "no valid user_id given") relevance = 'global' if len(request.matchdict["relevance"]) > 0: relevance = request.matchdict["relevance"] #relevance = request.matchdict["relevance"] #print('relevance',relevance) return Achievement.get_leaderbord_by_user(achievement_id, user_id, relevance)
def set_messages_read(request): try: doc = request.json_body except: raise APIError(400, "invalid_json", "no valid json body") subject_id = int(request.matchdict["subject_id"]) if asbool(get_settings().get("enable_user_authentication", False)): may_read_messages = request.has_perm( perm_global_read_messages ) or request.has_perm(perm_own_read_messages) and str( request.subject.id) == str(subject_id) if not may_read_messages: raise APIError(403, "forbidden", "You may not read the messages of this subject.") if not exists_by_expr(t_subjects, t_subjects.c.id == subject_id): raise APIError(404, "set_messages_read.subject_not_found", "There is no subject with this id.") message_id = doc.get("message_id") q = select([t_subject_messages.c.id, t_subject_messages.c.created_at], from_obj=t_subject_messages).where( and_(t_subject_messages.c.id == message_id, t_subject_messages.c.subject_id == subject_id)) msg = DBSession.execute(q).fetchone() if not msg: raise APIError(404, "set_messages_read.message_not_found", "There is no message with this id.") uS = update_connection() uS.execute(t_subject_messages.update().values({ "is_read": True }).where( and_(t_subject_messages.c.subject_id == subject_id, t_subject_messages.c.created_at <= msg["created_at"]))) return {"status": "ok"}
def get_messages(request): try: subject_id = int(request.matchdict["subject_id"]) except: subject_id = None try: offset = int(request.GET.get("offset", 0)) except: offset = 0 limit = 100 if asbool(get_settings().get("enable_user_authentication", False)): may_read_messages = request.has_perm( perm_global_read_messages ) or request.has_perm(perm_own_read_messages) and str( request.subject.id) == str(subject_id) if not may_read_messages: raise APIError(403, "forbidden", "You may not read the messages of this subject.") if not exists_by_expr(t_subjects, t_subjects.c.id == subject_id): raise APIError(404, "get_messages.subject_not_found", "There is no subject with this id.") q = t_subject_messages.select().where( t_subject_messages.c.subject_id == subject_id).order_by( t_subject_messages.c.created_at.desc()).limit(limit).offset(offset) rows = DBSession.execute(q).fetchall() return { "messages": [{ "id": message["id"], "text": SubjectMessage.get_text(message), "is_read": message["is_read"], "created_at": message["created_at"] } for message in rows] }
def delete_user(request): """delete a user completely""" user_id = int(request.matchdict["user_id"]) if asbool(get_settings().get("enable_user_authentication", False)): # ensure that the user exists and we have the permission to update it may_delete = request.has_perm( perm_global_delete_user) or request.has_perm( perm_own_delete_user) and request.user.id == user_id if not may_delete: raise APIError(403, "forbidden", "You may not delete this user.") User.delete_user(user_id) return {"status": "OK"}
def delete_subject(request): """delete a subject completely""" subject_id = int(request.matchdict["subject_id"]) if asbool(get_settings().get("enable_user_authentication", False)): # ensure that the subject exists and we have the permission to update it may_delete = request.has_perm( perm_global_delete_subject) or request.has_perm( perm_own_delete_subject) and request.subject.id == subject_id if not may_delete: raise APIError(403, "forbidden", "You may not delete this subject.") Subject.delete_subject(subject_id) return {"status": "OK"}
def change_password(request): try: doc = request.json_body except: raise APIError(400, "invalid_json", "no valid json body") email = doc.get("email") old_password = doc.get("old_password") new_password = doc.get("new_password") if not email or not old_password or not new_password: raise APIError( 400, "change_password.email_and_old_password_and_new_password_required", "You need to send your email, the old password and a new password." ) user = DBSession.query(AuthUser).filter_by(email=email).first() if not user or not user.verify_password(old_password): raise APIError( 401, "change_password.email_or_old_password_invalid", "Either the email address or the old password is wrong.") if not user.active: raise APIError(400, "user_is_not_activated", "Your user is not activated.") if new_password == old_password: raise APIError(400, "change_password.may_not_be_the_same", "The new password may not be the same as the old one.") if not AuthUser.check_password_strength(new_password): raise APIError( 400, "change_password.invalid_new_password", "The new password is too weak. Minimum length is 8 characters.") user.password = new_password user.force_password_change = False DBSession.add(user) token = AuthToken.generate_token() tokenObj = AuthToken(auth_user_id=user.id, token=token) DBSession.add(tokenObj) DBSession.flush() return { "token": token, "subject": Subject.full_output(user.subject_id), }
def add_or_update_subject(request): """add a subject and set its metadata""" subject_id = int(request.matchdict["subject_id"]) if asbool(get_settings().get("enable_user_authentication", False)): #ensure that the subject exists and we have the permission to update it may_update = request.has_perm( perm_global_manage_subjects ) or request.has_perm( perm_own_update_subject_infos) and request.subject.id == subject_id if not may_update: raise APIError(403, "forbidden", "You may not edit this subject.") #if not exists_by_expr(t_subjects,t_subjects.c.id==subject_id): # raise APIError(403, "forbidden", "The subject does not exist. As the user authentication is enabled, you need to create the AuthUser first.") lat = None if len(request.POST.get("lat", "")) > 0: lat = float(request.POST["lat"]) lon = None if len(request.POST.get("lon", "")) > 0: lon = float(request.POST["lon"]) friends = [] if len(request.POST.get("friends", "")) > 0: friends = [int(x) for x in request.POST["friends"].split(",")] groups = [] if len(request.POST.get("groups", "")) > 0: groups = [int(x) for x in request.POST["groups"].split(",")] timezone = "UTC" if len(request.POST.get("timezone", "")) > 0: timezone = request.POST["timezone"] if not valid_timezone(timezone): timezone = 'UTC' language = None if len(request.POST.get("language", "")) > 0: language = request.POST["language"] additional_public_data = {} if len(request.POST.get("additional_public_data", "")) > 0: try: additional_public_data = json.loads( request.POST["additional_public_data"]) except: additional_public_data = {} Subject.set_infos(subject_id=subject_id, lat=lat, lng=lon, timezone=timezone, language_id=language, additional_public_data=additional_public_data) Subject.set_relations(subject_id=subject_id, relation_ids=friends) Subject.set_parent_subjects(subject_id=subject_id, parent_subject_ids=groups) return {"status": "OK", "subject": Subject.full_output(subject_id)}
def increase_value(request): """increase a value for the subject""" subject_id = int(request.matchdict["subject_id"]) try: value = float(request.POST["value"]) except: try: doc = request.json_body value = doc["value"] except: raise APIError(400, "invalid_value", "Invalid value provided") key = request.matchdict["key"] if ( "key" in request.matchdict and request.matchdict["key"] is not None) else "" variable_name = request.matchdict["variable_name"] subject = Subject.get_subject(subject_id) if not subject: raise APIError(404, "subject_not_found", "subject not found") variable = Variable.get_variable_by_name(variable_name) if not variable: raise APIError(404, "variable_not_found", "variable not found") if asbool(get_settings().get("enable_user_authentication", False)): if not AuthUser.may_increase(variable, request, subject_id): raise APIError( 403, "forbidden", "You may not increase the variable for this subject.") Value.increase_value(variable_name, subject["id"], value, key, at_datetime=dt_now()) try: achievement_history = int(request.GET["achievement_history"]) except: achievement_history = 2 output = _get_progress(achievements_for_subject=subject, requesting_subject=request.subject, achievement_history=achievement_history) output = copy.deepcopy(output) to_delete = list() for i in range(len(output["achievements"])): if len(output["achievements"][i]["new_levels"]) > 0: if "levels" in output["achievements"][i]: del output["achievements"][i]["levels"] if "priority" in output["achievements"][i]: del output["achievements"][i]["priority"] if "goals" in output["achievements"][i]: del output["achievements"][i]["goals"] else: to_delete.append(i) for i in sorted(to_delete, reverse=True): del output["achievements"][i] return output
def add_or_update_user(request): """add a user and set its metadata""" user_id = int(request.matchdict["user_id"]) if asbool(get_settings().get("enable_user_authentication", False)): #ensure that the user exists and we have the permission to update it may_update = request.has_perm( perm_global_update_user_infos) or request.has_perm( perm_own_update_user_infos) and request.user.id == user_id if not may_update: raise APIError(403, "forbidden", "You may not edit this user.") #if not exists_by_expr(t_users,t_users.c.id==user_id): # raise APIError(403, "forbidden", "The user does not exist. As the user authentication is enabled, you need to create the AuthUser first.") lat = None if len(request.POST.get("lat", "")) > 0: lat = float(request.POST["lat"]) lon = None if len(request.POST.get("lon", "")) > 0: lon = float(request.POST["lon"]) friends = [] if len(request.POST.get("friends", "")) > 0: friends = [int(x) for x in request.POST["friends"].split(",")] groups = [] if len(request.POST.get("groups", "")) > 0: groups = [int(x) for x in request.POST["groups"].split(",")] timezone = "UTC" if len(request.POST.get("timezone", "")) > 0: timezone = request.POST["timezone"] if not valid_timezone(timezone): timezone = 'UTC' country = None if len(request.POST.get("country", "")) > 0: country = request.POST["country"] region = None if len(request.POST.get("region", "")) > 0: region = request.POST["region"] city = None if len(request.POST.get("city", "")) > 0: city = request.POST["city"] language = None if len(request.POST.get("language", "")) > 0: language = request.POST["language"] additional_public_data = {} if len(request.POST.get("additional_public_data", "")) > 0: try: additional_public_data = json.loads( request.POST["additional_public_data"]) except: additional_public_data = {} User.set_infos(user_id=user_id, lat=lat, lng=lon, timezone=timezone, country=country, region=region, city=city, language=language, friends=friends, groups=groups, additional_public_data=additional_public_data) return {"status": "OK", "user": User.full_output(user_id)}