Beispiel #1
0
def set_processor_profile(user_id, processor_profile):
    """ Set data processor profile. """
    session = db.get_db_session()
    result = {}
    result['success'] = False
    session = db.get_db_session()
    try:
        profile = session.query(Processor).filter_by(puid=user_id).one()
        if 'name' in processor_profile:
            profile.name = processor_profile['name']
        if 'address' in processor_profile:
            profile.address = processor_profile['address']
        if 'postcode' in processor_profile:
            profile.postcode = processor_profile['postcode']
        if 'city' in processor_profile:
            profile.city = processor_profile['city']
        if 'org_type' in processor_profile and processor_profile[
                'org_type'] in [x.value for x in enums.OrganizationType]:
            profile.org_type = processor_profile['org_type']
        if 'thumbnail_url' in processor_profile:
            profile.thumbnail_url = processor_profile['thumbnail_url']
        session.commit()
        result['success'] = True
        result['response'] = ""
        return result
    except Exception:
        if Configuration.test_mode:
            logging.exception("An error occured:")
        session.rollback()
        session.close()
        error = {}
        error['code'] = enums.Error.UNDEFINED
        error['message'] = "undefined"
        result['error'] = error
        return result
Beispiel #2
0
def check_login(user_id, passw):
    """ check password (internal)

    Args:
        - user_id (int): uid of the user

        - passw (str): password of the user

    Returns:
        - success (bool)
    """
    # FIXME: Add check for tokens
    session = db.get_db_session()
    try:
        # check if password was right
        account_to_check = session.query(User).filter_by(
            **{'user_id': user_id})
        if account_to_check.count() == 0:

            session.close()
            return False
        account_to_check = account_to_check.one()

        if account_to_check.password_hash == passw:
            session.close()
            return True
        session.close()
        return False
    except Exception:
        session.close()
        logging.exception("An error occured:")
        return False
Beispiel #3
0
def register(new_acc, db_query, pers_inf, param):
    """ Add new user to database. (internal)

    Args:
        - new_acc (object): User object to be added to database of type ``db_query``

        - db_query (class): User class, e.g. ``User``

        - pers_inf (object): Object of type personal_information.PersonalInformation

        - param (dict): Contains the user id, e.g. `` {'user_id': user_id} ``

    Returns:
        - success (bool)
        - error (dict):
            - code (int): one of
                - 6 -- Account already existing
                - 99 -- Undefined
            - message (str): error code meaning
        - response (empty dict)

        (returns error only if success == False and response otherwise)
    """

    session = db.get_db_session()
    result = {}
    result['success'] = False
    try:
        # account already registered
        if session.query(db_query).filter_by(**param).count():
            session.close()
            Configuration.print_config()
            error = {}
            error['code'] = enums.Error.USER_ALREADY_EXISTS
            error['message'] = "account already exists"
            result['error'] = error
            return result
        else:
            session.add(new_acc)
            if pers_inf is not None:
                session.add(pers_inf)
                for code in UserDataType:
                    session.add(
                        PrivacyDefault(code.value, new_acc.user_id, 0, True))
            session.commit()
            session.close()
    except Exception:
        if Configuration.test_mode:
            logging.exception("An error occured:")
        session.rollback()
        session.close()
        error = {}
        error['code'] = enums.Error.UNDEFINED
        error['message'] = "undefined"
        result['error'] = error
        return result
    result['success'] = True
    result['response'] = {}
    return result
Beispiel #4
0
def add_data_to_database(data):
    """ This function enables to commit data to the database
        without repeating the following three lines in every
        set-function. """
    session = db.get_db_session()
    session.add(data)
    session.commit()
    session.close()
Beispiel #5
0
def list_default_privacy_levels(user_id, labels=None):
    """ Return current default privacy settings for all attribute catgeories if labels is None
        and only for the passed categories (=labels) otherwise.

    Args:
        - user_id (int): uid of the user

    Kwargs:
        - labels (list of int): if not ``None``, only the levels for the matching labels will be returned

    Returns:
        - success (bool)
        - error (dict):
            - code (int): one of
                - 1 -- Invalid token
                - 99 -- Undefined
            - message (str): error code meaning
        - response (list of dicts):
            - form of dicts: ``{"label":label, "level":level}``

        (returns error only if success == False and response otherwise)
    """
    result = {}
    result['success'] = False
    # check if user token was correct
    session = db.get_db_session()
    try:
        if labels is None:
            privacy_default_list = session.query(PrivacyDefault)\
                .filter(PrivacyDefault.user_id == user_id).all()
        else:
            privacy_default_list = session.query(PrivacyDefault).\
                filter(PrivacyDefault.user_id == user_id).\
                filter(PrivacyDefault.label.in_(labels)).all()
        session.close()
        response = [{
            "label": row.label,
            "level": row.level,
            "explicitconsent": row.explicitconsent
        } for row in privacy_default_list]
        result['success'] = True
        result['response'] = response
        return result
    except Exception:
        if Configuration.test_mode:
            logging.exception("An error occured:")
        session.rollback()
        session.close()
        error = {}
        error['code'] = enums.Error.UNDEFINED
        error['message'] = "undefined"
        result['error'] = error
        return result
Beispiel #6
0
def finish_login(user_id, is_processor=False):
    """ check password and create token. (internal)

    Args:
        - user_id (int): uid of the user

        - passw (str): password of the user

        - db_query (class): class of the user, e.g. ``User``

        - param (dict): Contains the user id, e.g. ``{'user_id': user_id}``

    Returns:
        - success (bool)
        - error (dict):
            - code (int): one of
                4  -- Invalid password
                99 -- Undefined
            - message (str): error code meaning
        - response (str): user session token

        (returns error only if success == False and response otherwise)
    """
    session = db.get_db_session()

    # Password check is performed in apicalls using check_login()
    token_scope = 'processor' if is_processor else 'user'
    try:
        loggedin = session.query(JwtToken).filter(JwtToken.user_id == user_id)
        if loggedin.count():
            response = loggedin.one()
            validity_check = JwtToken.check_token(response.token, user_id,
                                                  token_scope)
            if validity_check:
                return_token = response.token
                session.close()
            else:
                updated_token = JwtToken.generate_general_token(
                    user_id, scope=token_scope)
                loggedin.update({JwtToken.token: updated_token.token})
                return_token = updated_token.token
                session.commit()
                session.close()
            return return_token

        new_token = JwtToken.generate_general_token(user_id, scope=token_scope)
        session.add(new_token)
        response = new_token.token
        session.commit()
        session.close()
        return response
    except Exception as e:
        return None
Beispiel #7
0
def user_register(user_id, username, firstname, lastname, birthday, street,
                  postal, city, country, email, gender, password_hash,
                  btc_address, anon):
    """ Add new user to database.

    Args:
        - user_id (int): uid of the user

        - username (str): username of the user

        - firstname (str)

        - lastname (str)

        - birthday (str)

        - street (str)

        - postal (str)

        - city (str)

        - country (str)

        - email (str)

        - gender (str)

        - password_hash (str)

        -btc_address (str)

        -anon (bool)

    Returns:
        - success (bool)
        - error (dict):
            - code (int): one of
                6  -- Account already exists
                99 -- Undefined
            - message (str): error code meaning
        - response (empty dict)

        (returns error only if success == False and response otherwise)
    """
    new_user = User(user_id, username, password_hash, btc_address)
    session = db.get_db_session()
    new_personal_information = personal_information.PersonalInformation(
        user_id, int(round(time.time() * 1000)), username, firstname, lastname,
        street, city, postal, country, birthday, email, gender, anon)
    return register(new_user, User, new_personal_information,
                    {'user_id': user_id})
Beispiel #8
0
def update(db_query_acc, db_query_inf, pers_inf, param):
    """ Update existing user profile. (internal)
        We deliberately use over-expressive error messages for the sake of
        our research demonstrator. In real deployments, this approach will
        leak sensitive information to attackers.

    Args:
        - db_query_acc (class): class of the user, e.g. ``User``

        - db_query_inf (class): class of the personal information, e.g. ``personal_information.PersonalInformation``

        - pers_inf (object): Object of type ``db_query_inf``

        - param (dict): Contains the user id, e.g. ``{'user_id': user_id}``

    Returns:
        - success (bool)
        - error (dict):
            - code (int): one of
                - 1 -- Token error
                - 6 -- Account does not exist
            - message (str): error code meaning
        - response (empty dict)

        (returns error only if success == False and response otherwise)
    """
    session = db.get_db_session()
    result = {}
    result['success'] = False
    try:
        # check if user exists and correct password
        session.update(db_query_inf).where(
            db_query_acc.user_id == param['user_id']).values(pers_inf)
        session.commit()
        session.close()
        result['success'] = True
        result['response'] = {}
        return result
    except Exception:
        if Configuration.test_mode:
            logging.exception("An error occured:")
        session.rollback()
        session.close()
        error = {}
        error['code'] = enums.Error.USER_NOT_IN_DB
        error['message'] = "account does not exist yet"
        result['error'] = error
        return result
Beispiel #9
0
def remove_default_privacy(db_query_privacy, param):
    """ Remove the default privacy settings for a user (internal)

    Args:
        - db_query_privacy (class): class of the privacy information, e.g. ``PrivacyDefault``

        - param (dict): Contains the user id, e.g. ``{'user_id': user_id}``

    Returns:
        - success (bool)
        - error (dict):
            - code (int):
                - 19 -- cannot remove default privacy information from Db
            - message (str): error code meaning
        - response (empty dict)

        (returns error only if success == False and response otherwise)
    """
    session = db.get_db_session()
    result = {}
    result['success'] = False
    try:
        # try to remove default privacy settings from db
        default_privacy_to_delete = session.query(db_query_privacy).filter_by(
            **param).all()
        session.delete(default_privacy_to_delete)
        session.commit()
        session.close()
    except Exception:
        if Configuration.test_mode:
            logging.exception("An error occured:")
        session.rollback()
        session.commit()
        session.close()
        error = {}
        error['code'] = enums.Error.CANNOT_REMOVE_PRIVACY_DEFAULTS
        error['message'] = "cannot remove default privacy information from Db"
        result['error'] = error
        return result
    result['success'] = True
    result['response'] = {}
    return result
Beispiel #10
0
def remove_personal_information(db_query_inf, param):
    """ Remove the personal infotmation (internal)

    Args:
        - db_query_inf (class): class of the personal information, e.g. ``personal_information.PersonalInformation``

        - param (dict): Contains the user id, e.g. ``{'user_id': user_id}``

    Returns:
        - success (bool)
        - error (dict):
            - code (int):
                - 17 -- Cannot remove personal information from database
            - message (str): error code meaning
        - response (empty dict)

        (returns error only if success == False and response otherwise)
    """
    session = db.get_db_session()
    result = {}
    result['success'] = False
    try:
        # try to remove personal information from db
        pers_inf_to_delete = session.query(db_query_inf).filter_by(
            **param).one()
        session.delete(pers_inf_to_delete)
        session.commit()
        session.close()
    except Exception:
        if Configuration.test_mode:
            logging.exception("An error occured:")
        session.rollback()
        session.commit()
        session.close()
        error = {}
        error['code'] = enums.Error.CANNOT_REMOVE_PERSONAL_INFORMATION
        error['message'] = "cannot remove personal information from Db"
        result['error'] = error
        return result
    result['success'] = True
    result['response'] = {}
    return result
Beispiel #11
0
def get_wizard_state(user_id):
    """ Get wizard state. """
    result = {}
    result['success'] = False
    session = db.get_db_session()
    try:
        profile = session.query(User). \
            filter_by(user_id=user_id).one()
        result['response'] = profile.wizard_state
        result['success'] = True
        return result
    except Exception:
        if Configuration.test_mode:
            logging.exception("An error occured:")
        session.rollback()
        session.close()
        error = {}
        error['code'] = enums.Error.UNDEFINED
        error['message'] = "undefined"
        result['error'] = error
        return result
Beispiel #12
0
def get_proc_profile(proc_id, is_user=True):
    """ Get data processor profile. """
    result = {}
    result['success'] = False
    session = db.get_db_session()
    try:
        profile = session.query(Processor).filter_by(puid=proc_id).one()
        response = {
            "name": profile.name,
            "address": profile.address,
            "postcode": profile.postcode,
            "city": profile.city,
            "org_type": profile.org_type,
            "thumbnail_url": profile.thumbnail_url
        }
        if profile == []:
            session.close()
            error = {}
            error['code'] = enums.Error.PROFILE_NOT_FOUND
            error[
                'message'] = "Error, Profile not found even though user is registered."
            result['error'] = error
            return result
        result['success'] = True
        result['response'] = response
        return result
    except Exception:
        if Configuration.test_mode:
            logging.exception("An error occured:")
        session.rollback()
        session.close()
        error = {}
        error['code'] = enums.Error.UNDEFINED
        error['message'] = "undefined"
        result['error'] = error
        return result
Beispiel #13
0
def select_query_data(users, start_time, end_time, passed_session=None):
    """ Return a dict with the user_id and relevant data needed for calculating the query result.

    Args:
        - users (dict): output of select_users()
        - start_time (int): user should have data with timestamps above this value (in milliseconds)
        - start_time (int): user should have data with timestamps below this value (in milliseconds)
        - passed_session (db_session): already existing session passed for consistency

    Returns:
        - dict of int : dict of the form: { user_id1 : {'v': [], 't': [], 'a': '', 'fg': '', 'cg': ''}, user_id2 : {'v': [], 't': [], 'a': '', 'fg': '', 'cg': ''}, ... }
            - v = list of values of single data points
            - t = list of timestamps belonging to the data point values in v
            - a = privacy level
            - fg = finest granularity = minimum distance between the timestamps of two succeeding values
            - cg = coarsest granularity = maximum distance between the timestamps of two succeeding values

        Example:
            {   839923732067498363: {'random_one': {'v':[40.29, 50.52, 56.68, 67.73],
                                    't':[1539122760000, 1539122940000, 1539123120000, 1539123300000],
                                    'a':1,
                                    'fg':180000,
                                    'cg':180000}},
                391676021478103493: {'random_one': {'v':[35.19, 84.48, 61.24, 76.92, 82.56, 49.59, 40.78],
                                    't':[1539122640000, 1539122760000, 1539122880000, 1539123000000, 1539123120000, 1539123240000, 1539123360000],
                                    'a':3,
                                    'fg':120000,
                                    'cg':120000}}
            }
    """

    if passed_session is None:
        session = db.get_db_session()
    else:
        session = passed_session
    try:
        # for every data source
        attributes = users[list(users.keys())[0]]
        for attribute in attributes:
            cur_source = HelperMethods.classname_to_source(attribute[0])
            # get entries for user_ids contained in user list and the given time interval
            query_data = session.query(cur_source).\
                filter(cur_source.timestamp.between(start_time, end_time - 1), cur_source.user_id.in_(users)).\
                order_by(cur_source.user_id.asc(), cur_source.timestamp.asc())
            # sort data for every user and every attribute into values dict
            values_dict = {}
            # collect attributes of first user's first data source
            for user in users:
                settings = users[user]
                attributes_dict = {}
                for setting in settings:
                    if setting[0] == attribute[0]:
                        a = setting[1]
                        vals = create_values_dict()
                        vals['v'] = [
                            round(HelperMethods.str_to_attr(a, row), 2)
                            for row in (r for r in query_data
                                        if r.user_id == user)
                        ]
                        vals['t'] = [
                            row.timestamp for row in (r for r in query_data
                                                      if r.user_id == user)
                        ]
                        vals['a'] = setting[2]
                        vals['fg'] = setting[3]
                        vals['cg'] = setting[4]
                        attributes_dict[a] = vals
                    else:
                        break
                if len(attributes_dict) > 0:
                    values_dict[user] = attributes_dict
        if passed_session is None:
            session.close()
        return values_dict
    except Exception:
        if Configuration.test_mode:
            logging.exception("An error occured:")
        session.rollback()
        raise
    finally:
        if passed_session is None:
            session.close()
Beispiel #14
0
def select_users(data_sources, attributes, constraints, max_granularity,
                 max_privacy_level, start_time, end_time):
    """Return an dict of user_ids (int) which are relevant for the current query and their settings for the relevant attributes

    Args:
        - data_sources (list of str): list containing strings with the data source class names, e.g. 'RandomData'
        - attributes (list of str): list attribute names, e.g. 'random_one'
        - constraints (list of lists): each list contains the data source name, the attribute name and the value/bounds which should be matched
            in the form [data_source_class, attribute_name, bounds]

            bounds is a string of the form a) "x:y" or b) "z" where
                a) x and y are integers or dates (of the form 'year/month/day') with x being a lower bound and y being an upper bound for the attribute value
                b) z can be string or integer and is compared to the attribute value
        - start_time (int): user should have data with timestamps above this value (in milliseconds)
        - end_time (int): user should have data with timestamps below this value (in milliseconds)
        - max_privacy_level (int): maximum privacy the attributes should require (because higher privacy lowers accuracy of the data)
        - max_granularity (int): maximum distance between timestamps of succeeding data points in milliseconds (because higher granularities lower the accuracy of the data)

    Returns:
        - dict of int : list of lists
            - content: { user_id1: [[data_source_name, attribute_name, a, fg, cg]], user_id2: [[data_source_name, attribute_name, a, fg, cg]], ... }
                - a = privacy level
                - fg = finest granularity = minimum distance between the timestamps of two succeeding values
                - cg = coarsest granularity = maximum distance between the timestamps of two succeeding values

            Example:
                { 97546848572549905: [['RandomData', 'random_one', 2, 60000, 60000]] }

    """
    session = db.get_db_session()
    try:
        # Get internal row IDs of data sources that appear in the query
        unified_data_sources = list(set(data_sources))
        data_source_tablenames = [
            HelperMethods.classname_to_tablename(ds)
            for ds in unified_data_sources
        ]
        available_sources = session.query(
            AvailableDataSource.data_source_id,
            AvailableDataSource.data_source_name).filter(
                AvailableDataSource.data_source_name.in_(
                    data_source_tablenames)).order_by(
                        AvailableDataSource.data_source_id).all()

        source_mapping = dict()
        for i, name in enumerate(unified_data_sources):
            source_mapping[name] = available_sources[i][0]

        relevant_data_sources = list(
            filter(lambda avs: avs[1] in data_source_tablenames,
                   available_sources))
        relevant_data_source_ids = list(
            map(lambda avs: avs[0], relevant_data_sources))

        # Determine users who registered all relevant data sources and
        # who have compatible privacy settings
        user_ids_with_data_sources = session.query(
            RegisteredDataSource, PrivacySetting).filter(
                and_(
                    RegisteredDataSource.user_id == PrivacySetting.user_id,
                    RegisteredDataSource.data_source_id ==
                    PrivacySetting.data_source_id,
                    RegisteredDataSource.data_source_id.in_(
                        relevant_data_source_ids),
                    RegisteredDataSource.timestamp <= start_time,
                    PrivacySetting.attribute.in_(attributes),
                    PrivacySetting.level.between(1, max_privacy_level))).all()
        potential_user_ids = [u[0].user_id for u in user_ids_with_data_sources]

        # Get update history of granularities for potentially interesting users
        # restricted to their relevant data sources.
        relevant_upload_granularity_histories = session.query(
            UploadGranularity).filter(
                and_(
                    UploadGranularity.user_id.in_(potential_user_ids),
                    UploadGranularity.data_source_id.in_(
                        relevant_data_source_ids),
                    UploadGranularity.timestamp <= end_time)).group_by(
                        UploadGranularity.user_id,
                        UploadGranularity.data_source_id).all()

        granularity_updates_per_user = dict()
        for g in relevant_upload_granularity_histories:
            if g.user_id not in granularity_updates_per_user.keys():
                granularity_updates_per_user[g.user_id] = dict()
            if g.data_source_id not in granularity_updates_per_user[
                    g.user_id].keys():
                granularity_updates_per_user[g.user_id][
                    g.data_source_id] = list()
            granularity_updates_per_user[g.user_id][g.data_source_id].append(
                (g.timestamp, g.interval))

        # Filter out users with granularities during the query interval that are too coarse
        potential_users_granularities = dict()
        for u, srcs in granularity_updates_per_user.items():
            # Only keep user if he has no granularity updates violating the data processor's requirements
            exclude_user = False
            user_granularities = dict()
            for data_source_id, gs in srcs.items():
                granularities = [g[1] for g in gs]
                if max(granularities) <= max_granularity:
                    user_granularities[data_source_id] = (min(granularities),
                                                          max(granularities))
                else:
                    exclude_user = True
            if not exclude_user:
                potential_users_granularities[u] = user_granularities
        potential_user_ids = [u for u in potential_users_granularities.keys()]

        # additional constraints (attributes with lower and/or upper bounds)
        for constraint in constraints:
            data_source_class = HelperMethods.classname_to_source(
                constraint[0])
            attr = HelperMethods.str_to_attr(constraint[1], data_source_class)
            bounds = constraint[2].split(':')
            # upper and/or lower bounds
            if len(bounds) == 2:
                lower = bounds[0]
                upper = bounds[1]
                if lower != '' and upper != '':  # Check for values outside the boundaries
                    exclusion_check = session.query(
                        data_source_class.user_id, func.count(attr)).filter(
                            data_source_class.user_id.in_(potential_user_ids),
                            or_(attr < lower, attr > upper))
                elif lower != '':  # We have only a lower bound (exclude all smaller values)
                    exclusion_check = session.query(
                        data_source_class.user_id, func.count(attr)).filter(
                            data_source_class.user_id.in_(potential_user_ids),
                            attr < lower)
                else:  # We have only an upper bound (exclude all larger values)
                    exclusion_check = session.query(
                        data_source_class.user_id, func.count(attr)).filter(
                            data_source_class.user_id.in_(potential_user_ids),
                            attr > upper)
            # check quality
            elif len(bounds) == 1 and bounds[0] != '':
                comparator = bounds[0]
                exclusion_check = session.query(
                    data_source_class.user_id,
                    # func.count(attr)
                    attr).filter(
                        data_source_class.user_id.in_(potential_user_ids),
                        attr != comparator)
            elif len(bounds) > 2:
                raise AssertionError(
                    "Constraint value interval contains too many values: {}".
                    format(len(bounds)))
        excluded_user_ids = exclusion_check.all()

        # Finally build set of user IDs that will remain after preselection
        user_ids = list(set(potential_user_ids) - set(excluded_user_ids))

        # Bundle required information for selected users
        """
            Example:
                { 97546848572549905: [['RandomData', 'random_one', 2, 60000, 60000]] }
        """
        result_users = dict()
        for user_id in user_ids:
            user_result = list()
            for i, data_source in enumerate(data_sources):
                data_source_id = source_mapping[data_source]
                attr = attributes[i]
                privacy_setting = [
                    u[1].level for u in user_ids_with_data_sources
                    if u[1].user_id == user_id and u[1].attribute == attr
                ][0]
                user_result.append([
                    data_source,
                    attr,
                    privacy_setting,
                    potential_users_granularities[user_id][data_source_id][0],
                    potential_users_granularities[user_id][data_source_id][1],
                ])
            result_users[user_id] = user_result
        session.close()
        return result_users
    except Exception:
        if Configuration.test_mode:
            logging.exception("An error occured:")
        session.rollback()
        raise
    finally:
        session.close()
Beispiel #15
0
def get_user_profile(user_id):
    """ Returns the user profile

    Args:
        - user_id (int): uid of the user

    Returns:
        - success (bool)
        - error (dict):
            - code (int): one of
                21 -- Error, Profile not found even though user is registered
                99 -- Undefined
            - message (str): error code meaning
        - response (dict)
            - username (str)
            - firstname (str)
            - lastname (str)
            - birthday (str)
            - street (str)
            - postal (str)
            - city (str)
            - country (str)
            - email (str)
            - gender (str)
            -anon (bool)

        (returns error only if success == False and response otherwise)
    """

    result = {}
    result['success'] = False
    session = db.get_db_session()
    try:
        profile = session.query(personal_information.PersonalInformation). \
            filter_by(user_id=user_id).one()
        response = {}
        response['username'] = profile.user_name
        response['firstname'] = profile.first_name
        response['lastname'] = profile.last_name
        response['birthday'] = profile.birthday
        response['street'] = profile.street
        response['postal'] = profile.zip_code
        response['city'] = profile.city
        response['country'] = profile.country
        response['email'] = profile.email
        response['gender'] = profile.gender
        response['anon'] = profile.anon
        if profile == []:
            session.close()
            error = {}
            error['code'] = enums.Error.PROFILE_NOT_FOUND
            error[
                'message'] = "Error, Profile not found even though user is registered."
            result['error'] = error
            return result
        result['success'] = True
        result['response'] = response
        return result
    except Exception:
        if Configuration.test_mode:
            logging.exception("An error occured:")
        session.rollback()
        session.close()
        error = {}
        error['code'] = enums.Error.UNDEFINED
        error['message'] = "undefined"
        result['error'] = error
        return result
Beispiel #16
0
def set_default_privacy_levels(user_id, privacy_levels):
    """ Set the default privacy levels for a user

    Args:
        - user_id (int): uid of the user

        - privacy_levels (list of str : dict): Of form ``{"label":label, "level":level}``

    Returns:
        - success (bool)
        - error (dict):
            - code (int): one of
                - 1 -- Invalid token
                - 91 -- Privacy level out of bounds
                - 99 -- Undefined
            - message (str): error code meaning
        - response (empty dict)

        (returns error only if success == False and response otherwise)
    """
    result = {}
    result['success'] = False
    session = db.get_db_session()
    try:
        registered_data_sources = session.query(AvailableDataSource).filter(
            AvailableDataSource.data_source_id ==
            RegisteredDataSource.data_source_id).filter(
                RegisteredDataSource.user_id == user_id).all()
        for privacy_level in privacy_levels:
            # Only allow privacy levels between 0 and 3 for now
            if 0 <= privacy_level.get("level") <= 3:
                # set level in default table
                cur = session.query(PrivacyDefault).filter_by(
                    user_id=user_id, label=privacy_level.get("label")).one()
                cur.level = privacy_level.get("level")
                cur.explicitconsent = privacy_level.get("explicitconsent")
                # check for every registered data source if some attribute has the same label and needs to be
                # updated
                for source in registered_data_sources:
                    source_class = HelperMethods.tablename_to_source(
                        source.data_source_name)
                    for key in source_class.label:
                        if source_class.label.get(key) == privacy_level.get(
                                "label"):
                            privacy_setting = session.query(
                                PrivacySetting).filter_by(
                                    data_source_id=source.data_source_id,
                                    user_id=user_id,
                                    attribute=key).one()
                            privacy_setting.level = privacy_level.get("level")
                            privacy_setting.explicitconsent = privacy_level.get(
                                "explicitconsent")
            else:
                session.rollback()
                session.close()
                error = {}
                error['code'] = enums.Error.INVALID_PRIVACY_LEVEL
                error['message'] = "Privacy level out of bounds"
                result['error'] = error
                return result
        session.commit()
        session.close()
        result['success'] = True
        result['response'] = {}
        return result
    except Exception:
        if Configuration.test_mode:
            logging.exception("An error occured:")
        session.rollback()
        session.close()
        error = {}
        error['code'] = enums.Error.UNDEFINED
        error['message'] = "undefined"
        result['error'] = error
        return result
Beispiel #17
0
def remove(user_id, passw, db_query_inf, db_query_privacy, db_query_queries,
           is_user, param):
    """ Remove account by its ID. (internal)

    Args:
        - user_id (int): uid of the user

        - passw (str): password hash of the user

        - db_query_inf (class): class of the personal information, e.g. ``personal_information.PersonalInformation``

        - db_query_privacy (class): class of the privacy information, e.g. ``PrivacyDefault``

        - db_query_queries (class): class of the query db, e.g. ``Query_Db``

        - db_query_pin_queries (class): class of the pin query db, e.g., ``Pin_Query_Db``

        - is_user (bool): if ``True``, get list of registered data sources and remove them

        - param (dict): Contains the user id, e.g. ``{'user_id': user_id}``

    Returns:
        - success (bool)
        - error (dict):
            - code (int): one of
                6  -- Account does not exists yet
                1  -- Token not found, user not logged in
                17 -- cannot remove personal information from Db
                19 -- cannot remove default privacy settings from Db
                22 -- cannot remove queries associated with user from Db
                23 -- cannot remove queries associated with processor from Db
                3 -- cannot remove account from Db
                4 -- invalid password
                5 -- account not in db
            - message (str): error code meaning
        - response (empty dict)

        (returns error only if success == False and response otherwise)
    """

    session = db.get_db_session()
    result = {}
    result['success'] = False
    try:
        # check if user exists and correct password
        db_query_acc = User if is_user else Processor
        account_to_check = session.query(db_query_acc).filter_by(**param).one()
        if account_to_check.password_hash == passw:
            # if user, get list of registered data sources and remove them
            if is_user:
                try:
                    # try to remove personal information & default privacy settings from db
                    pers_inf_to_delete = session.query(db_query_inf).filter_by(
                        **param).one()
                    session.delete(pers_inf_to_delete)
                except Exception:
                    if Configuration.test_mode:
                        logging.exception("An error occured:")
                    session.rollback()
                    session.commit()
                    session.close()
                    error = {}
                    error[
                        'code'] = enums.Error.CANNOT_REMOVE_PERSONAL_INFORMATION
                    error[
                        'message'] = "cannot remove personal information from Db"
                    result['error'] = error
                    return result
                try:
                    # try to remove personal information & default privacy settings from db
                    default_privacy_to_delete = session.query(
                        db_query_privacy).filter_by(**param).all()
                    for setting in default_privacy_to_delete:
                        session.delete(setting)
                except Exception:
                    if Configuration.test_mode:
                        logging.exception("An error occured:")
                    session.rollback()
                    session.commit()
                    session.close()
                    error = {}
                    error['code'] = enums.Error.CANNOT_REMOVE_PRIVACY_DEFAULTS
                    error[
                        'message'] = "cannot remove default privacy settings from Db"
                    result['error'] = error
                    return result
                try:
                    # try to remove associated queries
                    queries_to_delete = session.query(
                        db_query_queries).filter_by(**param).all()
                    for query in queries_to_delete:
                        session.delete(query)
                except Exception:
                    if Configuration.test_mode:
                        logging.exception("An error occured:")
                    session.rollback()
                    session.commit()
                    session.close()
                    error = {}
                    error['code'] = enums.Error.CANNOT_REMOVE_USER_QUERIES
                    error[
                        'message'] = "cannot remove queries associated with user from Db"
                    result['error'] = error
                    return result
                session.commit()
                session.close()
                result['success'] = True
                result['response'] = {}
                data_sources = data_source_tasks.get_data_source_list(
                    user_id, False)
                remove_result = data_source_tasks.remove_data_sources(
                    user_id, data_sources['response'])
                if remove_result['success'] is False:
                    error = {}
                    error['code'] = enums.Error.UNDEFINED
                    error[
                        'message'] = "Undefined error while trying to remove data for user"
                    result['error'] = error
                    return result
            # log user/proc out
            else:
                logout_result = proc_logout(user_id)
                if not logout_result["success"]:
                    session.rollback()
                    session.close()
                    return logout_result
                try:
                    # change status of associated queries
                    queries_to_modify = session.query(
                        db_query_queries).filter_by(
                            processor_id=param['puid']).all()
                    for query in queries_to_modify:
                        query.state = QueryState.ABANDONED
                        query.result = ""
                except Exception:
                    if Configuration.test_mode:
                        logging.exception("An error occured:")
                    session.rollback()
                    session.commit()
                    session.close()
                    error = {}
                    error['code'] = enums.Error.CANNOT_REMOVE_PROC_QUERIES
                    error[
                        'message'] = "cannot remove queries associated with processor from Db"
                    result['error'] = error
                    return result
            try:
                # try to remove user from db
                account_to_delete = session.query(db_query_acc).filter_by(
                    **param).one()
                session.delete(account_to_delete)
                session.commit()
                session.close()
                result['success'] = True
                result['response'] = {}
            except Exception:
                if Configuration.test_mode:
                    logging.exception("An error occured:")
                session.rollback()
                session.close()
                error = {}
                error['code'] = enums.Error.CANNOT_REMOVE_USER
                error['message'] = "cannot remove account from Db"
                result['error'] = error
            return result
        else:
            error = {}
            error['code'] = enums.Error.INVALID_PASSWORD
            error['message'] = "invalid password"
            result['error'] = error
            return result
    except Exception:
        if Configuration.test_mode:
            logging.exception("An error occured:")
        error = {}
        error['code'] = enums.Error.USER_NOT_IN_DB
        error['message'] = "account not in db"
        result['error'] = error
        return result
Beispiel #18
0
def is_user(username):
    session = db.get_db_session()
    res = session.query(User).filter_by(**{'username': username}).one_or_none()
    session.close()
    return res is not None