From 250d24ae37cd081f9f080dcd731dca243e986342 Mon Sep 17 00:00:00 2001 From: d278liu Date: Thu, 23 Dec 2021 17:00:27 -0500 Subject: [PATCH] use binary search when finding new uid (#39) closes #36 Co-authored-by: Daniel Liu Reviewed-on: https://git.csclub.uwaterloo.ca/public/pyceo/pulls/39 Co-authored-by: d278liu Co-committed-by: d278liu --- ceod/model/LDAPService.py | 32 +++++++++++--------------------- 1 file changed, 11 insertions(+), 21 deletions(-) diff --git a/ceod/model/LDAPService.py b/ceod/model/LDAPService.py index 6c30f00..272333b 100644 --- a/ceod/model/LDAPService.py +++ b/ceod/model/LDAPService.py @@ -1,6 +1,4 @@ import contextlib -import grp -import pwd from typing import Union, Dict, List from flask import g @@ -119,19 +117,6 @@ class LDAPService: def _get_next_uid(self, conn: ldap3.Connection, min_id: int, max_id: int) -> int: """Gets the next available UID number between min_id and max_id, inclusive.""" - def uid_exists(uid: int) -> bool: - try: - pwd.getpwuid(uid) - return True - except KeyError: - return False - - def gid_exists(gid: int) -> bool: - try: - grp.getgrgid(gid) - return True - except KeyError: - return False def ldap_uid_or_gid_exists(uid: int) -> bool: return conn.search( @@ -139,12 +124,17 @@ class LDAPService: f'(|(uidNumber={uid})(gidNumber={uid}))', size_limit=1) - # TODO: replace this with binary search - for uid in range(min_id, max_id + 1): - if uid_exists(uid) or gid_exists(uid) or ldap_uid_or_gid_exists(uid): - continue - return uid - raise Exception('no UIDs remaining') + while min_id != max_id: + cur_uid = (min_id + max_id) // 2 + if ldap_uid_or_gid_exists(cur_uid): + min_id = cur_uid + 1 + else: + max_id = cur_uid + + if ldap_uid_or_gid_exists(min_id): + raise Exception('no UIDs remaining') + else: + return min_id def add_sudo_role(self, uid: str): conn = self._get_ldap_conn()