示例#1
0
async def test_list_users():
    list_users_length_before = 0

    test_creds = graph.extension_attr_name("testCredentials")
    test_user_filter = f"{test_creds} eq true"
    async for user in graph.list_users(filter=test_user_filter):
        list_users_length_before += 1

    # create two test phone numbers
    phone_numbers = ["+001234567", "+001010101"]
    users = []

    # check if phone_numbers are associated with existing test users. If yes, delete them and re-create two test users
    for phone_number in phone_numbers:
        existing_user = await graph.find_user_by_phone(phone_number)
        if not existing_user:
            users.append(await test_utils.create_test_user(phone_number))

    list_users_length_after = 0
    async for user in graph.list_users(filter=test_user_filter):
        list_users_length_after += 1
    assert list_users_length_after == list_users_length_before + len(users)

    # delete created test users
    for phone_number in phone_numbers:
        test_user_deleted = await graph.find_user_by_phone(phone_number)
        await test_utils.delete_test_user(test_user_deleted["id"])
async def collect_users():
    """yield all phone number, device group pairs"""

    async for user in list_users():
        if user.get(extension_attr_name("testCredentials")):
            continue
        yield user["displayName"]
示例#3
0
async def collect_devices():
    """yield all phone number, device group pairs"""

    sem = asyncio.Semaphore(64)

    async def process_one(user):
        results = []
        async with sem:
            async for device in device_groups_for_user(user):
                results.append((user["displayName"], device))
        return sorted(
            results, key=lambda user_device: user_device[1]["createdDateTime"]
        )

    pending = set()
    done = set()
    async for user in list_users():
        if user.get(extension_attr_name("testCredentials")):
            continue
        pending.add(asyncio.ensure_future(process_one(user)))
        done, pending = await asyncio.wait(pending, timeout=1e-3)
        for f in done:
            for phone, device in f.result():
                yield phone, device["displayName"], device["createdDateTime"]
    if pending:
        for results in await asyncio.gather(*pending):
            for phone, device in results:
                yield phone, device["displayName"], device["createdDateTime"]
async def collect_users():
    """yield all userPrincipalName fields for users

    Excluding:
    - test accounts
    - 'real' users who aren't phone numbers
    """

    async for user in list_users():
        if user.get(extension_attr_name("testCredentials")):
            # app_log.info(f"skipping {user['displayName']}")
            continue
        if not user["displayName"].startswith("+"):
            app_log.info(f"skipping {user['displayName']}")
            continue

        yield user["id"]
示例#5
0
async def find_users_to_delete(limit=None):
    """Find users whose devices should be deleted"""
    async for user in graph.list_users(filter=f"{consent_revoked} eq true"):
        if user.get(consent_revoked):
            app_log.warning(f"User {user['logName']} with consent revoked not removed!")
            yield user
        else:
            app_log.warning(
                f"User {user['logName']} without consent revoked shouldn't have been returned by query."
            )

    inactive = await find_inactive_devices()
    app_log.info(f"Found {len(inactive)} inactive devices")
    counts = defaultdict(int)

    async def process_one(uuid_activity):
        uuid, last_activity = uuid_activity
        group = await graph.get_group(uuid)
        if group is None:
            app_log.info(f"No group for inactive device {uuid}")
            counts["no_group"] += 1
            return
        if group.get(consent_revoked):
            app_log.info(f"Already marked for deletion: {uuid}")
            counts["deleted"] += 1
            return
        user = await graph.user_for_device(group)
        if user is None:
            app_log.info(f"No user for inactive device {uuid}")
            counts["no_user"] += 1
            # FIXME: something went wrong. Mark device id group for deletion?
            return

        # check other devices on the same user
        # in case of new device registrations,
        # don't delete data from a user's old phone
        other_device_activity = None
        device_ids = [uuid]
        async for group in graph.device_groups_for_user(user):
            device_id = group["displayName"]
            if device_id != uuid:
                device_ids.append(device_id)
            # First check for recent registration (cheap)
            if parse_date(group["createdDateTime"]) >= IDLE_CUTOFF:
                app_log.info(f"Recently registered device {device_id}")
                counts["new"] += 1
                if device_id == uuid:
                    app_log.warning(
                        f"WRONG activity: recently registered {device_id} not idle"
                    )
                    counts["wrong"] += 1
                other_device_activity = True
                break
            try:
                device = await devices.get_device(device_id)
            except Exception as e:
                app_log.warning(f"Failed to get device {device_id}: ({e})")
                counts["iot_err"] += 1
                pass
            else:
                if parse_date(device["lastActivityTime"]) >= IDLE_CUTOFF:
                    counts["iot"] += 1
                    app_log.info(f"Activity on {device_id} in IoTHub")
                    if device_id == uuid:
                        app_log.warning(
                            f"WRONG activity: iothub active {device_id} not idle"
                        )
                        counts["wrong"] += 1
                    other_device_activity = True
                    break
            if device_id != uuid:
                # if not registered since cutoff, check for activity in SQL
                if await check_sql_data(device_id, activity_cutoff=IDLE_CUTOFF):
                    counts["sql"] += 1
                    app_log.info(f"Activity on {device_id} in SQL")
                    other_device_activity = True
                    break
        if other_device_activity:
            app_log.info(f"{uuid} is associated with other more recent device activity")
            counts["active"] += 1
        else:
            app_log.info(f"User {user['logName']} is inactive since {last_activity}")
            app_log.info(f"Inactive devices: {','.join(device_ids)}")
            counts["idle"] += 1
            return user

    yielded = 0
    async for user in consume_concurrently(
        inactive, process_one, counts=counts, label="Inactive users"
    ):
        if user:
            yield user
            yielded += 1
            if limit and yielded >= limit:
                app_log.info(f"Reached idle user limit={limit}")
                return