Exemplo n.º 1
0
    def merge_profiles(cls,
                       app_id,
                       src_user_pk=None,
                       src_alias=None,
                       dst_user_pk=None,
                       dst_alias=None):
        src_profiles = cls.find_by_pk(app_id=app_id, user_pk=src_user_pk) \
            if src_user_pk else cls.query.filter_by(alias=src_alias).all()
        if not src_profiles:
            raise NotFoundError('Source User ID or Social ID not found')

        dst_profiles = cls.find_by_pk(app_id=app_id, user_pk=dst_user_pk) \
            if dst_user_pk else cls.query.filter_by(alias=dst_alias).all()
        if not dst_profiles:
            raise NotFoundError('Destination User ID or Social ID not found')

        associated_providers = []
        for p in dst_profiles:
            associated_providers.append(p.provider)
        for p in src_profiles:
            if p.provider in associated_providers:
                raise ConflictError(
                    msg='Unacceptable operation. '
                    'Source profile has associated with a provider same in destination profile',
                    data={
                        'conflict_provider': p.provider,
                        'associated_providers': ', '.join(associated_providers)
                    })
        dst_profile = dst_profiles[0]
        for p in src_profiles:
            p._merge_unsafe(dst_profile)
Exemplo n.º 2
0
    def link_with_user(cls, app_id, alias, user_pk, create_if_not_exist=True):
        profiles = cls.query.filter_by(alias=alias).all()
        if not profiles:
            raise NotFoundError('Social ID not found')
        if profiles[0].user_id:
            raise ConflictError(
                'Unacceptable operation. '
                'Social profile has linked with an exists user')
        num_user_same_pk = (db.session.query(func.count(
            SocialProfiles._id)).join(
                Users,
                and_(Users._id == SocialProfiles.user_id, Users.pk == user_pk,
                     Users.app_id == app_id)).scalar())
        if num_user_same_pk > 0:
            raise ConflictError('User has linked with another social profile')

        user = Users.query.filter_by(pk=user_pk, app_id=app_id).one_or_none()
        if not user:
            if not create_if_not_exist:
                raise NotFoundError('User not found')
            user = Users(pk=user_pk, app_id=app_id)
            db.session.add(user)
            db.session.flush()
        for p in profiles:
            p._link_unsafe(user._id)
Exemplo n.º 3
0
def get_associate_token(app_id: str, body: Dict[str, Any]):
    provider = body.get('provider')
    if not is_valid_provider(provider):
        raise BadRequestError('Invalid provider')
    user_pk, alias = _parse_and_validate_identifiers(body)

    profiles = SocialProfiles.find_by_pk(app_id=app_id, user_pk=user_pk)\
        if user_pk else SocialProfiles.query.filter_by(alias=alias).all()
    if not profiles:
        raise NotFoundError('User ID or Social ID not found')

    for p in profiles:
        if provider == p.provider:
            raise ConflictError(
                'User has linked with another social profile for this provider'
            )
    log = AssociateLogs(provider=provider,
                        app_id=app_id,
                        social_id=profiles[0].alias,
                        nonce=gen_random_token(nbytes=16, format='hex'))
    db.session.add(log)
    db.session.flush()

    associate_token = log.generate_associate_token()
    db.session.commit()
    return {'token': associate_token, 'target_provider': provider}
Exemplo n.º 4
0
 def unlink_from_user(cls, app_id, alias, user_pk):
     user_id = db.session.query(Users._id).filter_by(
         pk=user_pk, app_id=app_id).scalar()
     if not user_id:
         raise NotFoundError('User ID not found')
     return cls.query.filter_by(alias=alias, user_id=user_id).update(
         {
             'linked_at': None,
             'user_id': None
         }, synchronize_session=False)
Exemplo n.º 5
0
    def merge_with(self, user_pk=None, alias=None):
        if not user_pk and alias <= 0:
            raise BadRequestError('At least one parameter dst_user_id or '
                                  'dst_social_id must be provided')
        profiles = SocialProfiles.find_by_pk(app_id=self.app_id, user_pk=user_pk) \
            if user_pk else SocialProfiles.query.filter_by(alias=alias)
        if not profiles:
            raise NotFoundError('Destination User ID or Social ID not found')

        dst_profile = profiles[0]
        self._merge_unsafe(dst_profile)
Exemplo n.º 6
0
def convert_social_id(body):
    sub, _ = _validate_access_token(access_token=body['access_token'])
    app_id = body['app_id']
    owner_id = db.session.query(Apps.owner_id).filter_by(_id=app_id).scalar()
    if not owner_id or owner_id != sub:
        raise NotFoundError('App ID not found')

    social_ids = body['ids'].split(',')
    if len(social_ids) > 150:
        raise BadRequestError('Number of IDs cannot be larger than 150')

    scope_ids = SocialProfiles.social_id_to_scope_id(app_id=app_id, social_ids=social_ids)
    return [e[0] for e in scope_ids]
Exemplo n.º 7
0
def admin_authenticate(email, password):
    admin = Admins.query.filter_by(email=email).one_or_none()
    if not admin:
        raise NotFoundError('Email not found')
    if not django_pbkdf2_sha256.verify(secret=password, hash=admin.password):
        raise UnauthorizedError('Invalid authorization credentials')

    admin_attrs = admin.as_dict()
    return {
        'user': admin_attrs,
        'access_token': jwt_token_helper.generate(
            sub=admin._id,
            exp_in_seconds=86400 * 365,
            **admin_attrs,
        )
    }
Exemplo n.º 8
0
    def get_full_profile(cls, app_id, user_pk=None, alias=None, pretty=False):
        profiles = cls.find_by_pk(app_id=app_id, user_pk=user_pk) \
            if user_pk else SocialProfiles.query.filter_by(alias=alias).all()
        if not profiles:
            raise NotFoundError('User ID or Social ID not found')

        last_profile = None
        login_count = 0
        for p in profiles:
            login_count += p.login_count
            if not last_profile:
                last_profile = p
                continue
            if last_profile.last_authorized_at < p.last_authorized_at:
                last_profile = p
        user = Users.query.filter_by(_id=last_profile.user_id).one_or_none()
        user_attrs = user.as_dict() if user else {'user_id': None}
        user_attrs.update({
            'last_logged_in_provider':
            last_profile.provider,
            'last_logged_in_at':
            cls.to_isoformat(last_profile.last_authorized_at),
            'login_count':
            login_count,
            'social_id':
            str(last_profile.alias)
        })
        return {
            'user':
            user_attrs,
            'profiles': [
                p.as_dict(user_pk=user.pk if user else None,
                          fetch_user=False,
                          pretty=pretty) for p in profiles
            ]
        }
Exemplo n.º 9
0
def admin_info(access_token):
    sub, _ = _validate_access_token(access_token=access_token)
    admin = Admins.query.filter_by(_id=sub).one_or_none()
    if not admin:
        raise NotFoundError('Email not found')
    return {'user': admin.as_dict()}
Exemplo n.º 10
0
    def authorize(self, params: OAuthAuthorizeParams):
        # Verify request params and extract session data
        self.session = self._verify_and_parse_session(params=params)

        oauth_app = Apps.query.filter_by(_id=params.app_id,
                                         _deleted=0).one_or_none()
        self.channel = Channels.query.filter_by(
            app_id=params.app_id, provider=self.provider).one_or_none()
        if not oauth_app or not self.channel:
            raise NotFoundError(msg='Application or channel not found')

        if not self._is_mobile():
            allowed_uris = [
                up.unquote_plus(uri) for uri in oauth_app.get_callback_uris()
            ]
            logger.debug('Verify callback URI',
                         style='hybrid',
                         allowed_uris=allowed_uris,
                         succ_callback=params.success_callback,
                         fail_callback=params.failed_callback)

            illegal_callback_msg = (
                'Invalid callback_uri value. '
                'Check if it is registered in EasyLogin developer site')

            if not verify_callback_uri(allowed_uris, params.success_callback):
                raise PermissionDeniedError(msg=illegal_callback_msg)

            if params.failed_callback and not verify_callback_uri(
                    allowed_uris, params.failed_callback):
                raise PermissionDeniedError(msg=illegal_callback_msg)

        self.log = AuthLogs(provider=self.provider,
                            app_id=params.app_id,
                            nonce=gen_random_token(nbytes=32),
                            intent=params.intent,
                            platform=self.session.platform,
                            callback_uri=params.success_callback,
                            callback_if_failed=params.failed_callback)
        db.session.add(self.log)
        db.session.flush()
        db.session.add(
            JournalLogs(ua=request.headers.get('User-Agent'),
                        ip=get_remote_ip(request),
                        path=request.full_path,
                        ref_id=self.log._id))

        oauth_state = generate_oauth_state(self.log, **self.session.to_dict())
        if self._is_mobile():
            return jsonify({
                'channel': {
                    'client_id': self.channel.client_id,
                    'options': self.channel.get_options(),
                    'scopes': self.channel.get_permissions()
                },
                'state': oauth_state
            })
        else:
            url = self._build_authorize_uri(state=oauth_state)
            logger.debug('Authorize URL', url)
            return redirect(url)