Example #1
0
    def test_make_unique_username(self):
        from pillar.api.utils import authentication as auth

        with self.app.test_request_context():
            # This user shouldn't exist yet.
            self.assertEqual(TEST_EMAIL_USER, auth.make_unique_username(TEST_EMAIL_ADDRESS))

            # Add a user, then test again.
            auth.create_new_user(TEST_EMAIL_ADDRESS, TEST_EMAIL_USER, 'test1234')
            self.assertEqual('%s1' % TEST_EMAIL_USER, auth.make_unique_username(TEST_EMAIL_ADDRESS))
Example #2
0
    def create_user(self, user_id='cafef00dc379cf10c4aaceaf', roles=('subscriber',),
                    groups=None, *, token: str = None, email: str = TEST_EMAIL_ADDRESS) -> ObjectId:
        from pillar.api.utils.authentication import make_unique_username
        import uuid

        with self.app.test_request_context():
            users = self.app.data.driver.db['users']
            assert isinstance(users, pymongo.collection.Collection)

            user = {'_id': ObjectId(user_id),
                    '_updated': datetime.datetime(2016, 4, 15, 13, 15, 11, tzinfo=tz_util.utc),
                    '_created': datetime.datetime(2016, 4, 15, 13, 15, 11, tzinfo=tz_util.utc),
                    '_etag': 'unittest-%s' % uuid.uuid4().hex,
                    'username': make_unique_username('tester'),
                    'groups': groups or [],
                    'settings': {'email_communications': 1},
                    'auth': [{'token': '',
                              'user_id': str(ctd.BLENDER_ID_TEST_USERID),
                              'provider': 'blender-id'}],
                    'full_name': 'คนรักของผัดไทย',
                    'email': email}
            if roles:
                user['roles'] = list(roles)

            result = users.insert_one(user)
            user_id = result.inserted_id

        if token:
            self.create_valid_auth_token(user_id, token)

        return user_id
Example #3
0
def create_local_user(email, password):
    """For internal user only. Given username and password, create a user."""
    # Hash the password
    hashed_password = hash_password(password, bcrypt.gensalt())
    db_user = create_new_user_document(email, '', email, provider='local',
                                       token=hashed_password)
    # Make username unique
    db_user['username'] = make_unique_username(email)
    # Create the user
    r, _, _, status = current_app.post_internal('users', db_user)
    if status != 201:
        log.error('internal response: %r %r', status, r)
        return abort(500)
    # Return user ID
    return r['_id']
Example #4
0
def insert_or_fetch_user(wh_payload: dict) -> typing.Optional[dict]:
    """Fetch the user from the DB or create it.

    Only creates it if the webhook payload indicates they could actually use
    Blender Cloud (i.e. demo or subscriber). This prevents us from creating
    Cloud accounts for Blender Network users.

    :returns the user document, or None when not created.
    """

    users_coll = current_app.db('users')
    my_log = log.getChild('insert_or_fetch_user')

    bid_str = str(wh_payload['id'])
    email = wh_payload['email']

    # Find the user by their Blender ID, or any of their email addresses.
    # We use one query to find all matching users. This is done as a
    # consistency check; if more than one user is returned, we know the
    # database is inconsistent with Blender ID and can emit a warning
    # about this.
    query = {'$or': [
        {'auth.provider': 'blender-id', 'auth.user_id': bid_str},
        {'email': {'$in': [wh_payload['old_email'], email]}},
    ]}
    db_users = list(users_coll.find(query))
    user_count = len(db_users)
    if user_count > 1:
        # Now we have to pay the price for finding users in one query; we
        # have to prioritise them and return the one we think is most reliable.
        calc_score = functools.partial(score, wh_payload)
        best_score = max(db_users, key=calc_score)

        my_log.error('%d users found for query %s, picking user %s (%s)',
                     user_count, query, best_score['_id'], best_score['email'])
        return best_score
    if user_count:
        db_user = db_users[0]
        my_log.debug('found user %s', db_user['email'])
        return db_user

    # Pretend to create the user, so that we can inspect the resulting
    # capabilities. This is more future-proof than looking at the list
    # of roles in the webhook payload.
    username = make_unique_username(email)
    user_doc = create_new_user_document(email, bid_str, username,
                                        provider='blender-id',
                                        full_name=wh_payload['full_name'])

    # Figure out the user's eventual roles. These aren't stored in the document yet,
    # because that's handled by the badger service.
    eventual_roles = [subscription.ROLES_BID_TO_PILLAR[r]
                      for r in wh_payload.get('roles', [])
                      if r in subscription.ROLES_BID_TO_PILLAR]
    user_ob = UserClass.construct('', user_doc)
    user_ob.roles = eventual_roles
    user_ob.collect_capabilities()
    create = (user_ob.has_cap('subscriber') or
              user_ob.has_cap('can-renew-subscription') or
              current_app.org_manager.user_is_unknown_member(email))
    if not create:
        my_log.info('Received update for unknown user %r without Cloud access (caps=%s)',
                    wh_payload['old_email'], user_ob.capabilities)
        return None

    # Actually create the user in the database.
    r, _, _, status = current_app.post_internal('users', user_doc)
    if status != 201:
        my_log.error('unable to create user %s: : %r %r', email, status, r)
        raise wz_exceptions.InternalServerError('unable to create user')

    user_doc.update(r)
    my_log.info('created user %r = %s to allow immediate Cloud access', email, user_doc['_id'])
    return user_doc