Exemplo n.º 1
0
    async def validate_and_save(self, context):
        data = context.get('data')
        db_session = context.get('db_session')
        save = context.get('save', True)

        is_new = await self.is_new()

        # USED
        used = data.get('used')
        if used is not None:
            self.used = used

        # TOKEN
        token = data.get('token')
        if token:
            self.token = token
        else:
            self.token = generate_token(20)

        # USER UID
        user_uid = data.get('user_uid')
        if user_uid:
            self.user_uid = user_uid
        else:
            if is_new:
                raise exceptions.InvalidRequestException('Missing user_uid')

        if save:
            db_session.save(self, safe=True)
Exemplo n.º 2
0
    async def post(self):
        try:
            data = await self.request.json()
        except:
            raise exceptions.InvalidRequestException('No json send')

        context = {
            'db_session': self.request.db_session,
            'ws_session': {'tz': data.get('user_timezone')},
            'method': 'create',
            'queue': self.request.app.queue
        }

        # INIT USER
        user = User()
        context['data'] = data
        sane_data = await user.sanitize_data(context)
        context['data'] = sane_data
        await user.validate_and_save(context)

        # SET SESSION
        await set_session(user, self.request)
        session = await get_session(self.request)
        session['tz'] = data.get('user_timezone')

        context['method'] = 'read'
        context['user'] = user
        context['ws_session'] = session
        resp_data = {
            'success': True,
            'user': await user.serialize(context),
            'token': session['csrf_token']
        }
        return web.json_response(resp_data)
    async def validate_and_save(self, context):
        data = context.get('data')
        db_session = context.get('db_session')
        save = context.get('save', True)

        is_new = await self.is_new()

        # USER UID
        user_uid = data.get('user_uid')
        if is_new and not user_uid:
            raise exceptions.InvalidRequestException(
                'Missing user_uid; cannot save Notification'
            )

        if user_uid:
            self.user_uid = user_uid

        # TARGET URL
        target_url = data.get('target_url')
        if target_url:
            self.target_url = target_url

        # SEEN
        seen = data.get('seen')
        if seen:
            self.seen_timestamp = datetime.now()
            self.seen = seen

        # MESSAGE
        message = data.get('message')
        if message:
            self.message = message
        else:
            if is_new:
                raise exceptions.InvalidRequestException(
                    'Missing message; cannot create Notification'
                )

        # TEMPLATE DATA
        template_data = data.get('template_data')
        if template_data:
            self.template_data = template_data

        if save:
            db_session.save(self, safe=True)
Exemplo n.º 4
0
async def api_check_email_disponibility(request):
    try:
        data = await request.json()
        email = data['email']
    except:
        raise exceptions.InvalidRequestException('Missing json data')

    available = not request.db_session.query(User)\
        .filter(User.email == email).count()

    resp_data = {'success': True, 'available': available}
    return web.json_response(resp_data)
Exemplo n.º 5
0
    async def get_json_data(self):
        try:
            req_data = await self.request.json()
            actions = req_data['actions']

            # Convert actions to list if necessary
            if not type(actions) == list:
                actions = [actions]

            logger.debug('actions = {actions}'.format(actions=actions))

            return actions
        except:
            raise exceptions.InvalidRequestException(
                'No json send or missing actions parameters')
Exemplo n.º 6
0
async def api_send_reset_password_token(request):
    logger.debug('send_reset_password_token')

    session = await get_session(request)

    try:
        data = await request.json()
        email = data['email']
    except:
        raise exceptions.InvalidRequestException('Missing json data')

    user_query = request.db_session.query(User)\
        .filter(User.email == email)
    if user_query.count():
        user = user_query.one()

        # NOTE disable user cannot reset their password
        if not user.enable:
            raise exceptions.EmailNotFound(
                '{email} belong to a disabled user'.format(email=email))

        context = {
            'user': user,
            'db_session': request.db_session,
            'ws_session': session,
            'method': 'create',
            'data': {
                'user_uid': user.get_uid()
            },
            'queue': request.app.queue
        }

        reset_password_token = Resetpasswordtoken()
        await reset_password_token.validate_and_save(context)

        resp_data = {'success': True}

        # TEST
        if config.get('env', 'production') in ['development', 'test']:
            resp_data['reset_password_token'] = reset_password_token.token

        return web.json_response(resp_data)

    # EMAIL NOT FOUND
    else:
        raise exceptions.EmailNotFound(email)
Exemplo n.º 7
0
async def api_confirm_email(request):
    logger.debug('confirm_email')

    try:
        data = await request.json()
        email_confirmation_token = data['token']
    except:
        raise exceptions.InvalidRequestException('Missing json data')

    session = await get_session(request)
    user = get_user_from_session(session, request.db_session)

    context = {
        'user': user,
        'db_session': request.db_session,
        'ws_session': session,
        'method': 'update',
        'queue': request.app.queue
    }

    token_query = request.db_session.query(Emailconfirmationtoken)\
        .filter(Emailconfirmationtoken.token == email_confirmation_token)
    if token_query.count():
        email_confirmation_token = token_query.one()

        context['target'] = email_confirmation_token
        ret = email_confirmation_token.use(context)
        if ret:
            context['data'] = {'email_confirmed': True}
            del context['target']
            await user.validate_and_save(context)

            context['method'] = 'read'
            resp_data = {
                'success': True,
                'user': await user.serialize(context)
            }
            return web.json_response(resp_data)

    # TOKEN NOT FOUND
    else:
        raise exceptions.TokenInvalidException('token not found')
Exemplo n.º 8
0
    async def post(self):
        try:
            data = await self.request.json()
        except:
            raise exceptions.InvalidRequestException('No json send')

        context = {
            'db_session': self.request.db_session,
            'ws_session': {'tz': data.get('user_timezone')},
            'method': 'create',
            'queue': self.request.app.queue
        }

        {%- if cookiecutter.closed_registration == 'y' %}
        # ClOSED REGISTRATION
        registration_token = data.get('registration_token')
        if registration_token != \
                config.get('registration_token'):
            raise exceptions.InvalidRegistrationTokenException()
        {%- endif %}

        # INIT USER
        user = User()
        context['data'] = data
        sane_data = await user.sanitize_data(context)
        context['data'] = sane_data
        await user.validate_and_save(context)

        # SET SESSION
        await set_session(user, self.request)
        session = await get_session(self.request)
        session['tz'] = data.get('user_timezone')

        context['method'] = 'read'
        context['user'] = user
        context['ws_session'] = session
        resp_data = {
            'success': True,
            'user': await user.serialize(context),
            'token': session['csrf_token']
        }
        return web.json_response(resp_data)
Exemplo n.º 9
0
async def api_validate_reset_password_token(request):
    logger.debug('validate_reset_password_token')

    session = await get_session(request)

    try:
        data = await request.json()
        reset_password_token = data['reset_password_token']
    except:
        raise exceptions.InvalidRequestException('Missing json data')

    session['tz'] = data.get('user_timezone')

    token_query = request.db_session.query(Resetpasswordtoken)\
        .filter(Resetpasswordtoken.token == reset_password_token)
    if token_query.count():
        reset_password_token = token_query.one()
        user = request.db_session.query(User)\
            .filter(User.mongo_id == reset_password_token.user_uid).one()

        context = {
            'user': user,
            'db_session': request.db_session,
            'ws_session': session,
            'method': 'update',
            'target': reset_password_token,
            'queue': request.app.queue
        }

        ret = reset_password_token.use(context)
        if ret:
            await set_session(user, request)
            context['method'] = 'read'
            resp_data = {
                'success': True,
                'user': await user.serialize(context)
            }
            return web.json_response(resp_data)

    # TOKEN NOT FOUND
    else:
        raise exceptions.TokenInvalidException('Token not found')
Exemplo n.º 10
0
    async def post(self):
        try:
            data = await self.request.json()
            email = data['email']
            password = data['password']
        except:
            raise exceptions.InvalidRequestException('No json send')

        query = self.request.db_session.query(User)\
            .filter(User.email == email.lower())
        if query.count():
            user = query.one()
            is_password_valid = await user.check_password(password)
            is_enable = user.enable
            if is_password_valid and is_enable:
                await set_session(user, self.request)
                session = await get_session(self.request)
                session['tz'] = data.get('user_timezone')

                context = {
                    'db_session': self.request.db_session,
                    'ws_session': session,
                    'method': 'read',
                    'queue': self.request.app.queue
                }

                resp_data = {
                    'success': True,
                    'token': session['csrf_token'],
                    'user': await user.serialize(context)
                }
            else:
                raise exceptions.WrongEmailOrPasswordException()
        else:
            raise exceptions.WrongEmailOrPasswordException(
                "Wrong email: '{email}'".format(email=email)
            )

        return web.json_response(resp_data)
        async def wrapped(*args):
            logger.debug('csrf_protected')

            # Supports class based views see web.View
            if isinstance(args[0], AbstractView):
                request = args[0].request
                params = args[0]  # self
            else:
                request = args[-1]
                params = request  # request

            session = await get_session(request)
            try:
                data = await request.json()
            except:
                raise exceptions.InvalidRequestException('No json send')

            csrf_token_session = session.get('csrf_token')
            csrf_token_request = data.get('token')
            if csrf_token_request != csrf_token_session:
                raise exceptions.CSRFMismatch()

            return (await func(params))
Exemplo n.º 12
0
    async def post(self):
        actions = await self.get_json_data()

        session = await get_session(self.request)
        author = get_user_from_session(session, self.request.db_session)

        read_context = {
            'author': author,
            'db_session': self.request.db_session,
            'ws_session': session,
            'method': 'read',
            'queue': self.request.app.queue,
        }
        action_context = {
            'author': author,
            'db_session': self.request.db_session,
            'ws_session': session,
            'queue': self.request.app.queue
        }

        success = True
        response_data = []
        error = []
        for index, action in enumerate(actions):
            try:
                # RESPONSE
                response_data.append(dict())
                response_data[index]['success'] = True
                response_data[index]['results'] = []

                # ACTION
                action_name = action.get('action')
                if not action_name:
                    raise exceptions.InvalidRequestException(
                        'Missing action in actions[{index}]'.format(
                            index=index))
                elif action_name not in self.action_list:
                    raise exceptions.InvalidRequestException(
                        'Invalid action name: "{action_name}"'.format(
                            action_name=action_name))

                action_context['method'] = action_name

                # IMPORT MODEL
                model_name = action.get('model')
                if not model_name:
                    raise exceptions.InvalidRequestException(
                        'Missing model in action')

                model_class = self.import_model(model_name)

                # CREATE
                if action_name == 'create':
                    results = [model_class()]
                    response_data[index]['total'] = 1

                # QUERY
                else:
                    # READ SPECIFIC RECORD
                    uid = action.get('uid')
                    if uid:
                        base_query = self.request.db_session\
                            .query(model_class)\
                            .filter(model_class.mongo_id == uid)

                    # BATCH
                    elif action.get('uids'):
                        uids = action.get('uids')
                        base_query = self.request.db_session.query(model_class)
                        response_data[index]['total'] = len(uids)
                        base_query = base_query.in_('mongo_id', *uids)
                        results = base_query.all()

                    else:
                        filters = action.get('filters')
                        filters_wildcard = action.get('filters_wildcard')
                        limit = action.get('limit')
                        skip = action.get('skip')
                        descending = action.get('descending')
                        ascending = action.get('ascending')

                        base_query = self.request.db_session.query(model_class)

                        if limit:
                            base_query = base_query.limit(limit)

                        if skip:
                            base_query = base_query.skip(skip)

                        if descending:
                            base_query = base_query.descending(descending)

                        if ascending:
                            base_query = base_query.ascending(ascending)

                        if filters:
                            if 'uid' in filters:
                                filters['mongo_id'] = filters['uid']
                                del filters['uid']

                            base_query = base_query.filter_by(**filters)

                        if filters_wildcard:
                            wildcard = []
                            for key, value in iter(filters_wildcard.items()):
                                wildcard.append(
                                    getattr(model_class,
                                            key).regex('.*%s.*' % value,
                                                       ignore_case=True))

                            base_query = base_query.or_(*wildcard)

                    response_data[index]['total'] = base_query.count()
                    results = base_query.all()

                # PROCESSING RESULTS
                for result in results:
                    # AUTHORIZATION CHECK
                    """
                    logger.debug(
                        'action_context = {action_context}'
                        .format(
                            action_context=action_context
                        )
                    )
                    """
                    if not await result.method_autorized(action_context):
                        raise exceptions.NotAuthorizedException(
                            '{author} not authorized to {action_name} {result}'
                            .format(author=author,
                                    action_name=action_name,
                                    result=result))

                    # APPLY ACTION
                    # CREATE & UPDATE
                    if action_name in ['create', 'update']:
                        data = action.get('data')
                        if not data:
                            raise exceptions.InvalidRequestException(
                                'Missing data in action')

                        action_context['data'] = data
                        sane_data = await result.sanitize_data(action_context)
                        action_context['data'] = sane_data

                        # BEFORE HOOK
                        await getattr(
                            result, 'before_{action_name}'.format(
                                action_name=action_name))(action_context)

                        await result.validate_and_save(action_context)

                        # AFTER HOOK
                        await getattr(
                            result, 'after_{action_name}'.format(
                                action_name=action_name))(action_context)

                    # DELETE
                    elif action_name == 'delete':
                        await result.before_delete(action_context)
                        self.request.db_session.remove(result, safe=True)
                        await result.after_delete(action_context)

                    if not action.get('total_only', False) \
                            and not action_name == 'delete':

                        # READ
                        # NOTE the authorization check has already
                        # been performed for the read
                        if not action_name == 'read':
                            """
                            logger.debug(
                                'read_context = {read_context}'
                                .format(
                                    read_context=read_context
                                )
                            )
                            """
                            if not await result.method_autorized(read_context):
                                raise exceptions.NotAuthorizedException(
                                    '{author} not authorized to {action_name} {result}'  # noqa
                                    .format(
                                        author=author,
                                        action_name=read_context.get('method'),
                                        result=result))
                        response_data[index]['results'].append(
                            await result.serialize(read_context))
            except Exception as e:
                success = False
                tb = traceback.format_exc()
                logger.error('Request HandledException<{exception}>'.format(
                    exception=str(tb)))
                if isinstance(e, exceptions.ServerBaseException):
                    error_msg = e.get_name()
                else:
                    error_msg = 'ServerSideError'

                response_data[index] = {'success': False, 'error': error_msg}
                error.append(error_msg)

        # RESPONSE
        trimmed_response_data = self.trim_response_data(
            success, response_data, error)
        return web.json_response(trimmed_response_data)
Exemplo n.º 13
0
    async def validate_and_save(self, context):
        queue = context.get('queue')
        data = context.get('data')
        db_session = context.get('db_session')
        save = context.get('save', True)

        is_new = await self.is_new()

        # EMAIL CONFIRMED
        email_confirmed = data.get('email_confirmed')
        if email_confirmed is not None:
            self.email_confirmed = email_confirmed
            if email_confirmed:
                notification_data = {
                    'message': 'notification.YourEmailHasBeenConfirmed'
                }
                await self.add_notification(db_session, notification_data)

        # NAME
        name = data.get('name')
        if name:
            if len(name) < NAME_MIN_LEN or len(name) > NAME_MAX_LEN:
                raise exceptions.InvalidNameException(name)

            self.name = name
        else:
            if is_new:
                raise exceptions.InvalidNameException('empty name')

        # ROLE
        role = data.get('role')
        if role:
            self.role = role

        # LOCALE
        locale = data.get('locale')
        if locale:
            self.locale = locale

        # ENABLE
        enable = data.get('enable')
        if enable is not None:
            self.enable = enable

        # PASSWORD
        password = data.get('password')
        if password:
            await self.set_password(password)
        else:
            if is_new:
                raise exceptions.InvalidPasswordException('empty password')

        # NEW PASSWORD
        new_password = data.get('new_password')
        if new_password:
            old_password = data.get('old_password')
            if old_password:
                is_password_valid = await self.check_password(old_password)
                if is_password_valid:
                    await self.set_password(new_password)
                else:
                    raise exceptions.WrongPasswordException()
            else:
                raise exceptions.InvalidRequestException(
                    'Missing old password')

        # EMAIL
        email = data.get('email')
        if email:
            email = email.lower()
            if is_new or self.email != email:
                is_email_valid = validate_email(email)
                if not is_email_valid:
                    raise exceptions.InvalidEmailException(email)

                email_uniqueness_query = db_session.query(User)\
                    .filter(User.email == email)
                if not is_new:
                    email_uniqueness_query = email_uniqueness_query\
                        .filter(User.mongo_id != self.get_uid())

                if email_uniqueness_query.count():
                    raise exceptions.EmailAlreadyExistsException(email)

                self.email = email
                self.email_confirmed = False

                # NOTIFICATON FOR CONFIRMATION EMAIL
                if not is_new:
                    notification_data = {
                        'message': 'notification.PleaseConfirmYourEmail',
                        'template_data': {
                            'email': email
                        }
                    }
                    await self.add_notification(db_session, notification_data)

                # GRAVATAR
                gravatar_url = "{base_url}{md5_hash}?{params}".format(
                    base_url="https://www.gravatar.com/avatar/",
                    md5_hash=hashlib.md5(
                        email.lower().encode('utf')).hexdigest(),
                    params=urllib.parse.urlencode({
                        'd': "identicon",
                        's': '40'
                    }))
                self.gravatar_url = gravatar_url

        else:
            if is_new:
                raise exceptions.InvalidEmailException('empty email')

        if save:
            db_session.save(self, safe=True)

        if not self.email_confirmed:
            email_confirmation_token = Emailconfirmationtoken()
            context['data']['user_uid'] = self.get_uid()
            await email_confirmation_token.validate_and_save(context)
            if config.get('env', 'production') == 'production' \
                    and hasattr(queue, 'enqueue'):
                self.send_email_confirmation_email(queue,
                                                   email_confirmation_token)