def check_access(): """Global decorator for each view. Checks permissions to access app resources by each user's request. Gets dynamic user info(user role, url, request method)from request context. :return: nested function returns true or 403 """ if 'access_control' not in session: session['access_control'] = permission_control.get_dct() logger.debug(jsonify(session['access_control'])) access_rules = session['access_control'] route = '/' + '/'.join(request.url.split('/')[3:]) access_result = check_permissions(current_user.role, route, request.method, access_rules) if not access_result['error']: access_status = access_result['status'] logger.info('ACCESS STATUS: %s DETAILS:(url= %s[%s], user ID:%s (%s))', access_status, route, request.method, current_user.uid, current_user.role) else: logger.debug('ACCESS: FORBIDDEN! DETAILS:(url= %s[%s], ' 'user ID:%s (%s), errors=%s)' % (route, request.method, current_user.uid, current_user.role, access_result['error'])) abort(403)
def delete_user(): """Controller for handling deletion of user profile by profile owner. :return: json object with success message or message with error """ data = request.get_json() valid = validator.hash_check(data['hash_sum']) if valid['status']: user_id = db.get_user_id_by_hash(data['hash_sum']) logger.warning(user_id) tuple_of_problems = db.get_problem_id_for_del(user_id) problem_list = [] for tuple_with_problem_id in tuple_of_problems: problem_list.append(tuple_with_problem_id[0]) if db.get_user_comments_count(user_id)[0]: db.change_comments_to_anon(user_id) if problem_list: for problem_id in problem_list: db.change_problem_to_anon(problem_id) db.change_activity_to_anon(problem_id) db.delete_user(user_id[0]) logger.info('User with id %s has been deleted' % user_id[0]) response = jsonify(msg='success', deleted_user=user_id[0]) else: db.delete_user(user_id[0]) logger.info('User with id %s has been deleted' % user_id[0]) response = jsonify(msg='success', deleted_user=user_id[0]) else: response = Response(json.dumps(valid), mimetype='application/json'), 400 return response
def post_problem(): """Function which adds data from problem form to DB. :return: If request data is invalid: {'status': False, 'error': [list of errors]}, 400 If all ok: {'added_problem': 'problem_title' 'problem_id': 'problem_id'} """ if request.method == 'POST' and request.form: data = request.form logger.warning(json.dumps(request.form)) logger.info(data) valid = validator.problem_post(data) if valid['status']: logger.debug('Checks problem post validation. %s', valid) user_id = current_user.uid posted_date = int(time.time()) last_id = db.problem_post(data['title'], data['content'], data['proposal'], data['latitude'], data['longitude'], data['type'], posted_date, user_id) if last_id: db.problem_activity_post(last_id, posted_date, user_id) logger.debug('New problem post was created with id %s', last_id) response = jsonify(added_problem=data['title'], problem_id=last_id) else: response = Response(json.dumps(valid), mimetype='application/json'), 400 return response
def get_user_problems(user_id): """This method retrieves all user's problem from db. :returns list of user's problem represented with next objects: {"id": 190, "title": "name", "latitude": 51.419765, "longitude": 29.520264, "problem_type_id": 1, "status": 0, "date": "2015-02-24T14:27:22.000Z", "severity": '3', "is_enabled": 1 } """ problems_list = [] problem_tuple = db.get_user_problems(user_id) logger.info(problem_tuple) for problem in problem_tuple: problems_list.append({ 'id': problem[0], 'title': problem[1], 'latitude': problem[2], 'logitude': problem[3], 'problem_type_id': problem[4], 'status': problem[5], 'date': problem[6] * 1000, 'severity': problem[8], 'is_enabled': problem[7] }) return Response(json.dumps(problems_list), mimetype='application/json')
def check_access(): """Global decorator for each view. Checks user permission to access application resources before each request. Gets dynamic request params(user role, url, request method) from each request context and compares it with admin permissions stored in db. :return: nested function returns true or 403 status and denies access. """ if 'access_control' not in session: session['access_control'] = permission_control.get_dct() access_rules = session['access_control'] route = parse_url(request.url) access_result = check_permissions(current_user.role, route, request.method, access_rules) if not access_result['error']: access_status = access_result['status'] logger.info('ACCESS STATUS: %s DETAILS:(url= %s[%s], user ID:%s (%s))', access_status, route, request.method, current_user.uid, current_user.role) else: logger.info('ACCESS: FORBIDDEN! DETAILS:(url= %s[%s],' 'user ID:%s (%s), errors=%s)' % (route, request.method, current_user.uid, current_user.role, access_result['error'])) abort(403)
def get_user_problems(user_id): """This method retrieves all user's problem from db and shows it in user profile page on `my problems` tab. :param user_id: id of user (int). :query filtr: name of column for filtration. :query order: 0 or 1. 0 - asc and 1 - desc. :query limit: limit number. default is 5. :query offset: offset number. default is 0. :rtype: JSON. :return: - If user has problems: ``[{'id': 190, 'title': 'name', 'latitude': 51.419765, 'longitude': 29.520264, 'problem_type_id': 1, 'status': 0, 'date': "2015-02-24T14:27:22.000Z", 'severity': '3', 'is_enabled': 1, 'name': 'problem with forest' },{...}]`` - If user haven't: ``{}`` :statuscode 200: no errors. """ filtr = request.args.get('filtr') or None order = int(request.args.get('order')) or 0 nickname = request.args.get('nickname').encode('utf-8') offset = int(request.args.get('offset')) or 0 per_page = int(request.args.get('per_page')) or 5 show_role = int(request.args.get('showRole')) or 0 order_desc = 'asc' if order else 'desc' if show_role: problem_tuple = db.get_filter_user_by_nickname(nickname, filtr, order_desc, offset, per_page) count = db.count_user_by_nickname(nickname) else: problem_tuple = db.get_filter_user_nickname(user_id, nickname, filtr, order_desc, offset, per_page) count = db.count_user_by_nickname_for_user(nickname, user_id) problems_list = [{ 'id': problem[0], 'title': problem[1], 'status': problem[2], 'date': problem[3] * 1000, 'is_enabled': problem[4], 'severity': problem[5], 'nickname': problem[6], 'user_id': problem[7], 'last_name': problem[8], 'first_name': problem[9], 'name': problem[10] } for problem in problem_tuple] if problem_tuple else [] logger.info(problem_tuple) total_count = {'total_problem_count': count[0]} if count else {} return Response(json.dumps([problems_list, [total_count]]), mimetype='application/json')
def oauth_login(provider): """Provides facebook authorization. Retrieves user info from facebook, check if there is user with retrieved from facebook user id, :param provider: Oauth provider (Facebook by default) - if yes: skips to next step - if not: checks if there is user with retrieved email - if yes: adds oauth credentials to this user - if not: creates new user After all function logging in user into app and return it's params """ access_token_url = 'https://graph.facebook.com/oauth/access_token' graph_api_url = 'https://graph.facebook.com/v2.5/me?fields=email,'\ 'first_name,last_name,id,picture.type(large)' params = { 'client_id': request.json['clientId'], 'redirect_uri': request.json['redirectUri'], 'client_secret': app.config['OAUTH_CREDENTIALS']['facebook']['secret'], 'code': request.json['code'] } resource = requests.get(access_token_url, params=params) access_token = dict(parse_qsl(resource.text)) resource = requests.get(graph_api_url, params=access_token) profile = json.loads(resource.text) nickname = '{}{}'.format(profile['last_name'], int(time.time())) logger.info(profile['picture']['data']['url']) user, is_registered = ecomap_user.facebook_register( profile['first_name'], profile['last_name'], nickname, profile['email'], provider, profile['id']) if not db.get_user_avatar(user.uid)[0]: db.insert_user_avatar(user.uid, profile['picture']['data']['url']) login_user(user, remember=True) response = jsonify(iat="???", token=user.get_auth_token(), email=user.email, name=user.first_name, surname=user.last_name, registered=is_registered) response.set_cookie('id', bytes(user.uid), max_age=COOKIE_MAX_AGE) response.set_cookie('role', bytes(user.role), max_age=COOKIE_MAX_AGE) return response
def load_users(): """Function to check if user is authenticated, else creates Anonymous user. Launches before requests. """ if current_user.is_authenticated: g.user = current_user else: anon = ecomap_user.Anonymous() g.user = anon logger.info('current user is %s, %s', g.user.role, g.user)
def create_dct(self): """Creates initial instance of permission rules. Call sql query and transform it into a json-like object. :return: """ parsed_data = {} logger.info('<<<Permission Control Initialization>>>') all_perms_list = db.get_permission_control_data() if all_perms_list: parsed_data = [x for x in all_perms_list] self.permissions_dict = make_json(parsed_data) return self.permissions_dict
def load_users(): """Function-decorator checks if user is authenticated, else creates Anonymous user instance. Launches before requests. """ if current_user.is_authenticated: g.user = current_user else: anon = ecomap_user.Anonymous() g.user = anon logger.info('Current user is (%s), role(%s)' % (unicode(g.user), g.user.role))
def oauth_login(provider): """Provides facebook authorization. Retrieves user info from facebook, check if there is user with retrieved from facebook user id, if yes: skips to next step if not: checks if there is user with retrieved email if yes: adds oauth credentials to this user if not: creates new user After all function loggins user and return it's params """ access_token_url = 'https://graph.facebook.com/oauth/access_token' graph_api_url = 'https://graph.facebook.com/v2.5/me?fields=email,'\ 'first_name,last_name,id,picture.type(large)' params = { 'client_id': request.json['clientId'], 'redirect_uri': request.json['redirectUri'], 'client_secret': app.config['OAUTH_CREDENTIALS']['facebook']['secret'], 'code': request.json['code'] } resource = requests.get(access_token_url, params=params) access_token = dict(parse_qsl(resource.text)) resource = requests.get(graph_api_url, params=access_token) profile = json.loads(resource.text) logger.info(profile['picture']['data']['url']) user = ecomap_user.facebook_register(profile['first_name'], profile['last_name'], profile['email'], provider, profile['id']) db.insert_user_avatar(user.uid, profile['picture']['data']['url']) login_user(user, remember=True) response = jsonify(id=user.uid, name=user.first_name, surname=user.last_name, role=user.role, iat="???", token=user.get_auth_token(), email=user.email) return response
def subscription_delete(): """Function deletes data of subscription from DB. :type: JSON :return: response """ if request.method == 'DELETE': logger.info(request.args.get('problem_id')) problem_id = int(request.args.get('problem_id')) user_id = current_user.uid logger.info(problem_id) last_id = db.subscription_delete(user_id, problem_id) logger.debug('Subscription post was deleted with id %s', last_id) response = jsonify(subscription_id=last_id) return response
def role_permission_put(): """Function which sets list of permission to role. Before sets removes all permissions from role. :return: If request data is not invalid': {'status': False, 'error': [list of errors]} If all ok: {'msg': 'edited permission'} """ data = request.get_json() logger.info('Role permission has been changed.') db.delete_permissions_by_role_id(data['role_id']) for perm_id in data['permission_id']: db.add_role_permission(data['role_id'], perm_id) response = jsonify(msg='edited permission') session['access_control'] = permission_control.reload_dct() return response
def post_problem(): """Function which adds data about created problem into DB. :content-type: multipart/form-data :fparam title: Title of problem ('problem with rivers') :fparam type: id of problem type (2) :fparam lat: lat coordinates (49.8256101) :fparam longitude: lon coordinates (24.0600542) :fparam content: description of problem ('some text') :fparam proposal: proposition for solving problem ('text') :rtype: JSON :return: - If request data is invalid: ``{'status': False, 'error': [list of errors]}`` - If all ok: ``{"added_problem": "problem title", "problem_id": 83}`` :statuscode 400: request is invalid :statuscode 200: problem was successfully posted """ if request.method == 'POST' and request.form: data = request.form logger.warning(json.dumps(request.form)) logger.info(data) valid = validator.problem_post(data) if valid['status']: logger.debug('Checks problem post validation. %s', valid) user_id = current_user.uid posted_date = int(time.time()) last_id = db.problem_post(data['title'], data['content'], data['proposal'], data['latitude'], data['longitude'], data['type'], posted_date, user_id) if last_id: db.problem_activity_post(last_id, posted_date, user_id, 'Added') logger.debug('New problem post was created with id %s', last_id) response = jsonify(added_problem=data['title'], problem_id=last_id) else: response = Response(json.dumps(valid), mimetype='application/json'), 400 return response
def subscription_post(): """Function adds data about subscription into DB. :param problem_id: id of problem (int) :param user_id: id of user (int) :param subscr date: date when user subscribed to a problem :return: response :type: JSON """ if request.method == 'POST': data = request.get_json() logger.warning(request.get_json()) logger.info(data) user_id = current_user.uid subscr_date = int(time.time()) last_id = db.subscription_post(data['problem_id'], user_id, subscr_date) logger.debug('New subscription post was created with id %s', last_id) response = jsonify(subscription_id=last_id) return response
def get_user_subscriptions_nickname(): """Function retrieves all user's subscriptions by nickname from db and shows it using search field on `my subscriptios` tab. :query per_page: limit number. default is 5. :query offset: offset number. default is 0. :param id: id of subscription (int). :param title: title of problem (str). :param problem_type_id: id of problem type (int). :param status: status of problem (solved or unsolved). :param date: date when problem was creared. :param date_subscription: date when user subscribed to a problem. :param name: name of problem type. :last_name: user last name. :first_name: user first name. :nickname: user nickname. :type: JSON """ nickname = request.args.get('nickname').encode('utf-8') filtr = request.args.get('filtr') order = int(request.args.get('order')) or 0 offset = int(request.args.get('offset')) or 0 per_page = int(request.args.get('per_page')) or 5 order_desc = 'desc' if order else 'asc' subscription_tuple = db.get_subscriptions_by_nickname( filtr, order_desc, nickname, offset, per_page) count = db.count_subscriptions_by_nickname(nickname) subscriptions_list = [{ 'id': subscription[0], 'title': subscription[1], 'problem_type_id': subscription[2], 'status': subscription[3], 'date': subscription[4] * 1000, 'date_subscription': subscription[5] * 1000, 'name': subscription[6], 'last_name': subscription[7], 'first_name': subscription[8], 'nickname': subscription[9] } for subscription in subscription_tuple] logger.info(subscription_tuple) total_count = {'total_problem_count': count[0]} if count else {} return Response(json.dumps([subscriptions_list, [total_count]]), mimetype='application/json')
def get_count_subscriptions(): """Function retrieves all user's subscriptions from db and shows them in `top 10 of the most popular subscriptions` tab. :param count: count of subscriptions to every problem (int) :param title: title of problem (str) :type: JSON """ subscription_tuple = db.count_subscriptions_by_problem_id() subscriptions_list = [] total_count = {} logger.info(subscription_tuple) for subscription in subscription_tuple: subscriptions_list.append({ 'count': subscription[0], 'id': subscription[1], 'title': subscription[2] }) sorted_json = sorted(subscriptions_list, key=lambda k: (k['count']), reverse=True)[:10] return Response(json.dumps([sorted_json]), mimetype='application/json')
def get_user_subscriptions(user_id): """Function retrieves all user's subscriptions from db and shows it in user profile page on `my subscriptions` tab. :param id: id of subscription (int) :param title: title of problem (str) :param problem_type_id: id of problem type (int) :param status: status of problem (solved or unsolved) :param date: date when problem was creared :param date_subscription: date when user subscribed to a problem :param name: name of problem type :type: JSON """ filtr = request.args.get('filtr') order = int(request.args.get('order')) or 0 offset = int(request.args.get('offset')) or 0 per_page = int(request.args.get('per_page')) or 5 order_desc = 'desc' if order else 'asc' subscription_tuple = db.get_subscriptions(user_id, filtr, order_desc, offset, per_page) count = db.count_user_subscriptions(user_id) subscriptions_list = [] total_count = {} logger.info(subscription_tuple) for subscription in subscription_tuple: subscriptions_list.append({ 'id': subscription[0], 'title': subscription[1], 'problem_type_id': subscription[2], 'status': subscription[3], 'date': subscription[4] * 1000, 'date_subscription': subscription[5] * 1000, 'name': subscription[6] }) if count: total_count = {'total_problem_count': count[0]} return Response(json.dumps([subscriptions_list, [total_count]]), mimetype='application/json')