Example #1
0
def insert_user(user: User, password=None):
    con = get_db()
    cur = con.cursor()
    cur.execute(
        '''insert into app_user values (default, %(email)s, 
            '', %(role)s, %(first_name)s, %(last_name)s, false, now(), now())
            returning id''', {
            'email': user.email,
            'role': user.role,
            'first_name': user.first_name,
            'last_name': user.last_name
        })

    row = cur.fetchone()
    if (not row):
        return None

    user_id = row[0]
    if (password):
        cur.execute(
            '''update app_user set pwd_hash = crypt(%(pas)s, gen_salt('bf'))
                        where id = %(id)s
                    ''', {
                'pas': password,
                'id': user_id
            })
    cur.close()
    con.commit()
    return user_id
Example #2
0
def login(email: str, password: str):
    '''User login'''
    # email = flask.request.args.get('email')
    # password = str(flask.request.args.get('password'))
    # print(email, password)

    con = get_db()
    cur = con.cursor()
    cur.execute(
        '''select id, (pwd_hash = crypt(%(password)s, pwd_hash)) as pwd_match from app_user 
                    where email = %(email)s''', {
            'password': password,
            'email': email
        })
    row = cur.fetchone()
    if (row and row[1]):
        token = encode_session_token(row[0])
        resp = flask.jsonify({'access_token': token.decode('utf-8')})
    else:
        status = 401
        data = {'mesage': 'Invalid password or user name.', 'status': status}
        resp = flask.jsonify(data)
        resp.status = str(status)

    return resp
Example #3
0
def update_user(user: User):
    con = get_db()
    cur = con.cursor()
    cur.execute(
        '''update app_user 
                        set role= %(role)s,
                        set first_name= %(first_name)s, set first_name= %(first_name)s
                    where id = %(id)sget_role_permitions_lookup
                ''', {
            'id': user.id,
            'role': user.role,
            'first_name': user.first_name,
            'last_name': user.last_name
        })
    rowcount = cur.rowcount

    # TODO this imitates trigger: Introduce trigger and remove this from part
    if (not rowcount):
        cur.close()
        return 0

    cur.execute('update app_user set updated_at = now() where id = %(id)s',
                {'id': user.id})
    cur.close()
    con.commit()
    return rowcount
Example #4
0
def get_users(user_id: int = None):
    '''List all users or one user depending on user_id parameter supplied and permitions'''
    perm = flask.g.user.permitions
    # print(bin(perm))
    # print(flask.g.user.id)

    if (user_id is None):
        # all
        if (not (perm & permits.read)):
            return unautorized_exit()

        con = get_db()
        cur = con.cursor()
        cur.execute(
            '''select id, email, active, role_id as role, first_name, last_name from app_user'''
        )
        columns = cur.description
        res = []
        for value in cur:
            res.append({
                columns[index][0]: column
                for index, column in enumerate(value)
            })
        cur.close()
        return flask.jsonify({'users': res})
    else:
        if ((perm & permits.read)
                or ((perm & permits.read_own) and flask.g.user.id == user_id)):
            user = get_user(user_id)
            return flask.jsonify({'user': vars(user)})
        else:
            return unautorized_exit()
Example #5
0
def activate_user(activation_token: str):
    ''' User activation 
    user registration->activation state tranitons:
    registered-> created-> pending_activation(<30min)->activated
    registered-> created-> pending_activation(>30min)->created (activation email has to be sent again manually by manager or admin not nedded in spec)

    user creation->registration->activation state tranitons:
    if created by admin user has to be invited the way it is done for manager 
    (this is not covered in specification and it is not implemented here)
    created-> invited (<30min)-> (registred->activated)
    invited(>30min)-> created
    invited(email refused invald address) -> created     
    '''
    # activation_token = flask.request.args.get('activation_token')
    # password = flask.request.args.get('password')

    try:
        payload = decode_email_token(activation_token, 'activation')
    except (jwt.DecodeError, jwt.InvalidTokenError) as err:
        print(err)
        return unautorized_exit()

    try:
        user_id = payload['user_id']
    except:
        return unautorized_exit()

    user = get_user(user_id)
    if (user.active):
        return flask.jsonify({
            'affected': 0,
            'msg': 'User has already been activated'
        })

    #TODO check if subjected user could be a e.g. does it have acivable role
    user = get_user(user_id)
    if (user.role != 'user'):
        return bad_request_400(
            'User can not be invited. Most probably user role has been changed'
        )

    con = get_db()
    cur = con.cursor()
    # print (password, user_id)
    cur.execute(
        '''update app_user set active=true, updated_at=now()
                    where id = %(id)s and not active
            ''', {'id': user_id})

    rowcount = cur.rowcount
    cur.close()
    con.commit()
    return flask.jsonify({'affected': rowcount})
Example #6
0
def get_user(user_id):
    con = get_db()
    cur = con.cursor()
    cur.execute(
        '''select id, email, active, role_id, first_name, last_name 
                    from app_user where id = %(id)s''', {'id': user_id})
    row = cur.fetchone()
    if (not row):
        return None
    user = User()
    user.id, user.email, user.active, user.role, user.first_name, user.last_name = row
    cur.close()
    return user
Example #7
0
File: app.py Project: pervlad/cope
def email_queue(email_id: int = None):
    '''List email queue to bypass email service functionality'''

    con = get_db()
    cur = con.cursor()
    cur.execute('''select * from email_queue order by id desc''')
    columns = cur.description
    res = []
    for value in cur:
        res.append(
            {columns[index][0]: column
             for index, column in enumerate(value)})
    cur.close()
    return flask.jsonify({'email_queue': res})
Example #8
0
def delete_user(user_id: int):
    con = get_db()
    cur = con.cursor()
    try:
        cur.execute('delete from table user_details where id = %(id)s',
                    id=user_id)
        cur.execute('delete from table user  where id = %(id)s', id=user_id)
    except (psycopg2.IntegrityError, psycopg2.DatabaseError) as err:
        con.rollback()
        cur.close()
        raise err
    rowcount = cur.rowcount
    cur.close()
    return rowcount
Example #9
0
 def wrap(*args, **kwargs):
     user = getattr(flask.g, 'user', None)
     assert (user is not None)
     # print('user ', user)
     con = get_db()
     cur = con.cursor()
     cur.execute('select permitions from role where id = %(id)s',
                 {'id': user.role})
     row = cur.fetchone()
     assert row is not None
     user.permitions = int(row[0], 2)
     if (required_permitions & user.permitions):
         return func(*args, **kwargs)
     else:
         return unautorized_exit()
Example #10
0
    def wrap(*args, **kwargs):
        token = flask.request.headers.get('Authorization')
        try:
            payload = decode_session_token(token)
        except (jwt.DecodeError, jwt.InvalidTokenError) as err:
            print(err)
            return unautorized_exit()

        con = get_db()
        cur = con.cursor()
        cur.execute(
            'select id, email, active, role_id from app_user where id = %(id)s',
            {'id': payload['user_id']})
        row = cur.fetchone()
        if (row):
            user = User()
            user.id, user.email, user.active, user.role = row
            if (user.active):
                flask.g.user = user
                return func(*args, **kwargs)
        return unautorized_exit()
Example #11
0
def create_user(email: str,
                role: str,
                first_name: str = None,
                last_name: str = None):
    '''Creation of user by user who has create permit e.g. adminitrator'''
    user = User()
    user.email = email  #flask.request.args.get('email')
    user.role = role  #flask.request.args.get('role')
    user.first_name = first_name  #flask.request.args.get('first_name')
    user.last_name = last_name  #flask.request.args.get('last_name')

    print('email', user.email)
    if (not validate_email(user.email)):
        return bad_request_400('Validation error: invalid email')

    if (not validate_role(user.role)):
        return bad_request_400(
            'Validation error: invalid role'
        )  #this is close to asert this is client app responsability

    # pwd = generate_password()
    con = get_db()
    cur = con.cursor()
    try:
        cur.execute(
            '''insert into app_user values (default, %(email)s, 
                '', %(role)s, %(first_name)s, %(last_name)s, false, now(), now())
                returning id''', {
                'email': user.email,
                'role': user.role,
                'first_name': user.first_name,
                'last_name': user.last_name
            })
    except psycopg2.IntegrityError as err:
        return bad_request_400(
            "User with email '{}' already registered".format(user.email))
    con.commit()
    id = cur.fetchone()[0]
    user.id = id
    return flask.jsonify({'user': vars(user)})
Example #12
0
def send_activation_email(user: User) -> int:
    atoken = encode_email_token(user.id, 'activation')
    url = flask.current_app.config['CLIENT_APP_URL'] + '/activate-account'
    message = build_activation_mail_body(url, atoken, user)
    sender_email = flask.current_app.config['ACTIVATION_SENDER']

    con = get_db()
    cur = con.cursor()
    cur.execute(
        '''insert into email_queue(id, status, sender, recipient, message, data)
            values(default, 'pending', %(sender)s, %(receiver)s, %(message)s, null)
            returning id
        ''', {
            'sender': sender_email,
            'receiver': user.email,
            'message': message
        })
    id = cur.fetchone()[0]
    cur.close()
    con.commit()

    #TODO add mail job into redis queue
    #TODO implement consumer service sender
    return {'email_queue_id': id}
Example #13
0
def invite_user(user_id: int = None):
    ''' Invite user with inviteable permition e.g. manager to register and activate account.
    
    User that has invite permit e.g. user with administrator role can invite manager by email.
    After clicking on link in the email manager creates password by submitting password 
    manager is registered and activated in atomic operation.  
    
    Invite proces sequence diagram
    client                          server                      email
    admin sends invitation
                                    invite_user
                                        sends mail 
                                                                user clicks on link in email
    client reg-act page openss
    client request user from token
                                    get_invited_user_data
                                        server returns user
    client allow usr to create pass
    clinet send regact request      
                                    register_and_activate_manager
                                        server validates request
                                        server activates user
                                        server returns status 
    redirect to login page  #(in this case direct login might be more appropriate)                            
    '''
    # user_id = flask.request.args.get('user_id')
    #validate user
    #although this should work only for manager I will allow it for all

    con = get_db()
    cur = con.cursor()
    cur.execute(
        '''select id, email, active, role_id, first_name, last_name 
                    from app_user where id = %(id)s''', {'id': user_id})
    row = cur.fetchone()
    if (not row):
        return bad_request_400('Invalid user.')

    user = User()
    user.id, user.email, user.active, user.role, user.first_name, user.last_name = row
    if (user.active):
        return flask.jsonify({'msg': 'User already activated', 'affected': 0})

    url = ''
    if (rolepermits[user.role] & permits.inivteable):
        url = flask.current_app.config[
            'SERVER_NAME'] + '/register-activate'  #this is client app path
    else:
        return bad_request_400('Invitation trough web api forbiden.')

    #email states and tranitions
    #pending->dispatched dipatched->sent dispatched->refused

    atoken = encode_email_token(user_id, 'invitation')
    message = build_invitation_mail_body(url, atoken, user)
    #put email into db
    sender_email = flask.current_app.config['INVITATION_SENDER']
    cur.execute(
        '''insert into email_queue(id, status, sender, recipient, message, data)
            values(default, 'pending', %(sender)s, %(receiver)s, %(message)s, null)
            returning id
        ''', {
            'sender': sender_email,
            'receiver': user.email,
            'message': message
        })
    id = cur.fetchone()[0]
    cur.close()
    con.commit()

    #TODO add mail job into redis queue
    #TODO implement consumer service sender

    return flask.jsonify({'email_queue_id': id})
Example #14
0
def register_and_activate_manager(invitation_token: str, password: str):
    ''' Registration and activation of a user witn invitable permition 
        e.g. user with manager role
    
    Registration - in this case adding password to already created user data
    and
    Activation  - performed upon user confirmation od email
    are one atomic process performed after clicking on manager activation link
    on restricted register page where manager has to create password and cant change his email name
    registration is followed by automatic activation

    manager state tranitons:
    created -> invited (30min)->(registred->activated)
    invited(>30min) -> created
    invited(email refused invald address) -> created     
    '''
    # invitation_token = flask.request.args.get('invitation_token')
    # password = str(flask.request.args.get('password'))

    try:
        payload = decode_email_token(invitation_token, 'invitation')
    except (jwt.DecodeError, jwt.InvalidTokenError) as err:
        print(err)
        return unautorized_exit()

    try:
        user_id = payload['user_id']
    except:
        return unautorized_exit()

    if (not validate_password(password)):
        return bad_request_400('Invalid password')

    # check if subjected user could be invited e.g. does it have invitable role
    user = get_user(user_id)
    if (user.role != 'manager'):
        return bad_request_400(
            'User can not be invited. Most probably users permition has been changed'
        )

    if (user.active):
        return flask.jsonify({
            'affected': 0,
            'msg': 'User has already been activated'
        })

    con = get_db()
    cur = con.cursor()
    # print (password, user_id)
    cur.execute(
        '''update app_user 
            set pwd_hash = crypt(%(pas)s, gen_salt('bf')), active=true, updated_at=now()
            where id = %(id)s and not active
            ''', {
            'pas': password,
            'id': user_id
        })

    rowcount = cur.rowcount
    cur.close()
    con.commit()
    return flask.jsonify({'affected': rowcount})