async def create_user(self, organization_id: OrganizationID, user: User, first_device: Device) -> None: org = self._organizations[organization_id] active_users_limit = self._organization_component._organizations[ organization_id].active_users_limit active_users = (u for u in org.users.values() if u.revoked_on is None) if active_users_limit is not None and active_users_limit <= len( list(active_users)): raise UserActiveUsersLimitReached() if user.user_id in org.users: raise UserAlreadyExistsError( f"User `{user.user_id}` already exists") if user.human_handle and user.human_handle in org.human_handle_to_user_id: raise UserAlreadyExistsError( f"Human handle `{user.human_handle}` already corresponds to a non-revoked user" ) org.users[user.user_id] = user org.devices[first_device.user_id][ first_device.device_name] = first_device if user.human_handle: org.human_handle_to_user_id[user.human_handle] = user.user_id await self._send_event( BackendEvent.USER_CREATED, organization_id=organization_id, user_id=user.user_id, user_certificate=user.user_certificate, first_device_id=first_device.device_id, first_device_certificate=first_device.device_certificate, )
async def _create_device(conn, organization_id: OrganizationID, device: Device, first_device: bool = False) -> None: if not first_device: existing_devices = await conn.fetch(_q_get_user_devices, organization_id, device.user_id) if not existing_devices: raise UserNotFoundError(f"User `{device.user_id}` doesn't exists") if device.device_id in itertools.chain(*existing_devices): raise UserAlreadyExistsError( f"Device `{device.device_id}` already exists") try: result = await conn.execute( _q_insert_device, organization_id, device.user_id, device.device_id, device.device_certificate, device.device_certifier, device.created_on, ) except UniqueViolationError: raise UserAlreadyExistsError( f"Device `{device.device_id}` already exists") if result != "INSERT 0 1": raise UserError(f"Insertion error: {result}")
async def create_user(self, organization_id: OrganizationID, user: User, first_device: Device) -> None: org = self._organizations[organization_id] if user.user_id in org.users: raise UserAlreadyExistsError( f"User `{user.user_id}` already exists") if user.human_handle and user.human_handle in org.human_handle_to_user_id: raise UserAlreadyExistsError( f"Human handle `{user.human_handle}` already corresponds to a non-revoked user" ) org.users[user.user_id] = user org.devices[first_device.user_id][ first_device.device_name] = first_device if user.human_handle: org.human_handle_to_user_id[user.human_handle] = user.user_id await self._send_event( "user.created", organization_id=organization_id, user_id=user.user_id, user_certificate=user.user_certificate, first_device_id=first_device.device_id, first_device_certificate=first_device.device_certificate, )
async def _get_device_invitation(self, conn, organization_id: OrganizationID, device_id: DeviceID): if await self._device_exists(conn, organization_id, device_id): raise UserAlreadyExistsError( f"Device `{device_id}` already exists") result = await conn.fetchrow( """ SELECT device_invitations.device_id, devices.device_id, device_invitations.created_on FROM device_invitations LEFT JOIN devices ON device_invitations.creator = devices._id WHERE device_invitations.organization = ( SELECT _id from organizations WHERE organization_id = $1 ) AND device_invitations.device_id = $2 """, organization_id, device_id, ) if not result: raise UserNotFoundError(device_id) return DeviceInvitation(device_id=DeviceID(result[0]), creator=DeviceID(result[1]), created_on=result[2])
async def cancel_device_invitation(self, organization_id: OrganizationID, device_id: DeviceID) -> None: async with self.dbh.pool.acquire() as conn: async with conn.transaction(): if await self._device_exists(conn, organization_id, device_id): raise UserAlreadyExistsError( f"Device `{device_id}` already exists") result = await conn.execute( """ DELETE FROM device_invitations WHERE organization = ( SELECT _id from organizations WHERE organization_id = $1 ) AND device_id = $2 """, organization_id, device_id, ) if result not in ("DELETE 1", "DELETE 0"): raise UserError(f"Deletion error: {result}") await send_signal( conn, "device.invitation.cancelled", organization_id=organization_id, device_id=device_id, )
async def _create_user(conn, organization_id: OrganizationID, user: User, first_device: Device) -> None: try: result = await conn.execute( _q_insert_user, organization_id, user.user_id, user.is_admin, user.user_certificate, user.user_certifier, user.created_on, ) except UniqueViolationError: raise UserAlreadyExistsError(f"User `{user.user_id}` already exists") if result != "INSERT 0 1": raise UserError(f"Insertion error: {result}") await _create_device(conn, organization_id, first_device, first_device=True) await send_signal( conn, "user.created", organization_id=organization_id, user_id=user.user_id, user_certificate=user.user_certificate, first_device_id=first_device.device_id, first_device_certificate=first_device.device_certificate, )
async def _get_user_invitation(self, conn, organization_id: OrganizationID, user_id: UserID): if await self._user_exists(conn, organization_id, user_id): raise UserAlreadyExistsError(f"User `{user_id}` already exists") result = await conn.fetchrow( """ SELECT user_invitations.user_id, devices.device_id, user_invitations.created_on FROM user_invitations LEFT JOIN devices ON user_invitations.creator = devices._id WHERE user_invitations.organization = ( SELECT _id from organizations WHERE organization_id = $1 ) AND user_invitations.user_id = $2 """, organization_id, user_id, ) if not result: raise UserNotFoundError(user_id) return UserInvitation(user_id=UserID(result[0]), creator=DeviceID(result[1]), created_on=result[2])
async def create_user_invitation(self, organization_id: OrganizationID, invitation: UserInvitation) -> None: org = self._organizations[organization_id] if invitation.user_id in org.users: raise UserAlreadyExistsError( f"User `{invitation.user_id}` already exists") org.invitations[invitation.user_id] = invitation
async def query_cancel_user_invitation(conn, organization_id: OrganizationID, user_id: UserID) -> None: if await _user_exists(conn, organization_id, user_id): raise UserAlreadyExistsError(f"User `{user_id}` already exists") result = await conn.execute(_q_delete_invitation, organization_id, user_id) if result not in ("DELETE 1", "DELETE 0"): raise UserError(f"Deletion error: {result}")
async def create_device_invitation(self, organization_id: OrganizationID, invitation: DeviceInvitation) -> None: org = self._organizations[organization_id] user = await self.get_user(organization_id, invitation.device_id.user_id) if invitation.device_id.device_name in user.devices: raise UserAlreadyExistsError( f"Device `{invitation.device_id}` already exists") org._invitations[invitation.device_id] = invitation
async def get_user_invitation(self, organization_id: OrganizationID, user_id: UserID) -> UserInvitation: org = self._organizations[organization_id] if user_id in org.users: raise UserAlreadyExistsError(user_id) try: return org.invitations[user_id] except KeyError: raise UserNotFoundError(user_id)
async def _do_create_user_with_human_handle(conn, organization_id: OrganizationID, user: User, first_device: Device) -> None: # Create human handle if needed await conn.execute( _q_insert_human_if_not_exists, organization_id, user.human_handle.email, user.human_handle.label, ) # Now insert the new user try: result = await conn.execute( _q_insert_user_with_human_handle, organization_id, user.user_id, user.profile.value, user.user_certificate, user.redacted_user_certificate, user.user_certifier, user.created_on, user.human_handle.email, ) except UniqueViolationError: raise UserAlreadyExistsError(f"User `{user.user_id}` already exists") if result != "INSERT 0 1": raise UserError(f"Insertion error: {result}") # Finally make sure there is only one non-revoked user with this human handle now = pendulum_now() not_revoked_users = await conn.fetch(_q_get_not_revoked_users_for_human, organization_id, user.human_handle.email, now) if len(not_revoked_users ) != 1 or not_revoked_users[0]["user_id"] != user.user_id: # Exception cancels the transaction so the user insertion is automatically cancelled raise UserAlreadyExistsError( f"Human handle `{user.human_handle}` already corresponds to a non-revoked user" )
async def _get_device_invitation(conn, organization_id: OrganizationID, device_id: DeviceID) -> DeviceInvitation: if await _device_exists(conn, organization_id, device_id): raise UserAlreadyExistsError(f"Device `{device_id}` already exists") result = await conn.fetchrow(_q_get_invitation, organization_id, device_id) if not result: raise UserNotFoundError(device_id) return DeviceInvitation(device_id=DeviceID(result[0]), creator=DeviceID(result[1]), created_on=result[2])
async def _get_user_invitation(conn, organization_id: OrganizationID, user_id: UserID): if await _user_exists(conn, organization_id, user_id): raise UserAlreadyExistsError(f"User `{user_id}` already exists") result = await conn.fetchrow(_q_get_invitation, organization_id, user_id) if not result: raise UserNotFoundError(user_id) return UserInvitation(user_id=UserID(result[0]), creator=DeviceID(result[1]), created_on=result[2])
async def create_user(self, organization_id: OrganizationID, user: User) -> None: org = self._organizations[organization_id] if user.user_id in org._users: raise UserAlreadyExistsError( f"User `{user.user_id}` already exists") org._users[user.user_id] = user self.event_bus.send("user.created", organization_id=organization_id, user_id=user.user_id)
async def get_device_invitation(self, organization_id: OrganizationID, device_id: DeviceID) -> DeviceInvitation: org = self._organizations[organization_id] try: org._users[device_id.user_id].devices[device_id.device_name] raise UserAlreadyExistsError(device_id) except KeyError: pass try: return org._invitations[device_id] except KeyError: raise UserNotFoundError(device_id)
async def query_cancel_device_invitation(conn, organization_id: OrganizationID, device_id: DeviceID) -> None: if await _device_exists(conn, organization_id, device_id): raise UserAlreadyExistsError(f"Device `{device_id}` already exists") result = await conn.execute(_q_delete_invitation, organization_id, device_id) if result not in ("DELETE 1", "DELETE 0"): raise UserError(f"Deletion error: {result}") await send_signal(conn, "device.invitation.cancelled", organization_id=organization_id, device_id=device_id)
async def get_device_invitation(self, organization_id: OrganizationID, device_id: DeviceID) -> DeviceInvitation: org = self._organizations[organization_id] user_devices = self._get_user_devices(organization_id, device_id.user_id) if device_id.device_name in user_devices: raise UserAlreadyExistsError(device_id) try: return org.invitations[device_id] except KeyError: raise UserNotFoundError(device_id)
async def query_create_user_invitation(conn, organization_id: OrganizationID, invitation: UserInvitation) -> None: if await _user_exists(conn, organization_id, invitation.user_id): raise UserAlreadyExistsError( f"User `{invitation.user_id}` already exists") result = await conn.execute(*_q_insert_invitation( organization_id=organization_id, creator=invitation.creator, user_id=invitation.user_id, created_on=invitation.created_on, )) if result not in ("INSERT 0 1", "UPDATE 1"): raise UserError(f"Insertion error: {result}")
async def _create_device_invitation(conn, organization_id: OrganizationID, invitation: DeviceInvitation) -> None: if await _device_exists(conn, organization_id, invitation.device_id): raise UserAlreadyExistsError( f"Device `{invitation.device_id}` already exists") result = await conn.execute( _q_insert_invitation, organization_id, invitation.creator, invitation.device_id, invitation.created_on, ) if result not in ("INSERT 0 1", "UPDATE 1"): raise UserError(f"Insertion error: {result}")
async def query_cancel_device_invitation(conn, organization_id: OrganizationID, device_id: DeviceID) -> None: if await _device_exists(conn, organization_id, device_id): raise UserAlreadyExistsError(f"Device `{device_id}` already exists") result = await conn.execute(*_q_delete_invitation( organization_id=organization_id, device_id=device_id)) if result not in ("DELETE 1", "DELETE 0"): raise UserError(f"Deletion error: {result}") await send_signal( conn, BackendEvent.DEVICE_INVITATION_CANCELLED, organization_id=organization_id, device_id=device_id, )
async def _do_create_user_without_human_handle( conn, organization_id: OrganizationID, user: User, first_device: Device ) -> None: try: result = await conn.execute( _q_insert_user, organization_id, user.user_id, user.is_admin, user.user_certificate, user.user_certifier, user.created_on, ) except UniqueViolationError: raise UserAlreadyExistsError(f"User `{user.user_id}` already exists") if result != "INSERT 0 1": raise UserError(f"Insertion error: {result}")
async def create_device(self, organization_id: OrganizationID, device: Device, encrypted_answer: bytes = b"") -> None: org = self._organizations[organization_id] if device.user_id not in org._users: raise UserNotFoundError(f"User `{device.user_id}` doesn't exists") user = org._users[device.user_id] if device.device_name in user.devices: raise UserAlreadyExistsError( f"Device `{device.device_id}` already exists") org._users[device.user_id] = user.evolve( devices=DevicesMapping(*user.devices.values(), device)) self.event_bus.send( "device.created", organization_id=organization_id, device_id=device.device_id, encrypted_answer=encrypted_answer, )
async def create_device(self, organization_id: OrganizationID, device: Device, encrypted_answer: bytes = b"") -> None: org = self._organizations[organization_id] if device.user_id not in org.users: raise UserNotFoundError(f"User `{device.user_id}` doesn't exists") user_devices = org.devices[device.user_id] if device.device_name in user_devices: raise UserAlreadyExistsError( f"Device `{device.device_id}` already exists") user_devices[device.device_name] = device await self._send_event( "device.created", organization_id=organization_id, device_id=device.device_id, device_certificate=device.device_certificate, encrypted_answer=encrypted_answer, )
async def create_device_invitation(self, organization_id: OrganizationID, invitation: DeviceInvitation) -> None: async with self.dbh.pool.acquire() as conn: async with conn.transaction(): if await self._device_exists(conn, organization_id, invitation.device_id): raise UserAlreadyExistsError( f"Device `{invitation.device_id}` already exists") result = await conn.execute( """ INSERT INTO device_invitations ( organization, creator, device_id, created_on ) VALUES ( (SELECT _id FROM organizations WHERE organization_id = $1), (SELECT _id FROM devices WHERE device_id = $2), $3, $4 ) ON CONFLICT (device_id) DO UPDATE SET organization = excluded.organization, creator = excluded.creator, created_on = excluded.created_on """, organization_id, invitation.creator, invitation.device_id, invitation.created_on, ) if result not in ("INSERT 0 1", "UPDATE 1"): raise UserError(f"Insertion error: {result}")
async def _create_user(conn, organization_id: OrganizationID, user: User) -> None: try: result = await conn.execute( """ INSERT INTO users ( organization, user_id, is_admin, certified_user, user_certifier, created_on ) SELECT _id, $2, $3, $4, ( SELECT _id FROM devices WHERE device_id = $5 AND organization = organizations._id ), $6 FROM organizations WHERE organization_id = $1 """, organization_id, user.user_id, user.is_admin, user.certified_user, user.user_certifier, user.created_on, ) except UniqueViolationError: raise UserAlreadyExistsError( f"User `{user.user_id}` already exists") if result != "INSERT 0 1": raise UserError(f"Insertion error: {result}") await conn.executemany( """ INSERT INTO devices ( organization, user_, device_id, certified_device, device_certifier, created_on, revocated_on, certified_revocation, revocation_certifier ) SELECT _id, ( SELECT _id FROM users WHERE user_id = $2 AND organization = organizations._id ), $3, $4, ( SELECT _id FROM devices WHERE device_id = $5 AND organization = organizations._id ), $6, $7, $8, $9 FROM organizations WHERE organization_id = $1 """, [( organization_id, device.user_id, device.device_id, device.certified_device, device.device_certifier, device.created_on, device.revocated_on, device.certified_revocation, device.revocation_certifier, ) for device in user.devices.values()], )
async def _create_device(self, conn, organization_id: OrganizationID, device: Device) -> None: existing_devices = await conn.fetch( """ SELECT device_id FROM devices WHERE user_ = ( SELECT _id FROM users WHERE organization = ( SELECT _id from organizations WHERE organization_id = $1 ) AND user_id = $2 ) """, organization_id, device.user_id, ) if not existing_devices: raise UserNotFoundError(f"User `{device.user_id}` doesn't exists") if device.device_id in itertools.chain(*existing_devices): raise UserAlreadyExistsError( f"Device `{device.device_id}` already exists") result = await conn.execute( """ INSERT INTO devices ( organization, user_, device_id, certified_device, device_certifier, created_on, revocated_on, certified_revocation, revocation_certifier ) SELECT _id, ( SELECT _id FROM users WHERE user_id = $2 AND organization = organizations._id ), $3, $4, ( SELECT _id FROM devices WHERE device_id = $5 AND organization = organizations._id ), $6, $7, $8, $9 FROM organizations WHERE organization_id = $1 """, organization_id, device.user_id, device.device_id, device.certified_device, device.device_certifier, device.created_on, device.revocated_on, device.certified_revocation, device.revocation_certifier, ) if result != "INSERT 0 1": raise UserError(f"Insertion error: {result}")