user_service.py
Overview
The user_service.py file provides service-layer classes that manage database operations related to users, tenants, and their relationships within the InfiniFlow application. It abstracts common CRUD and business logic for user authentication, tenant management, and user-tenant role assignments by building upon a base CommonService class and using the Peewee ORM for database interaction.
This file contains three main service classes:
UserService: Handles user account management, authentication, creation, updates, and deletion.
TenantService: Manages tenants, tenant info retrieval, credit management, and tenant-related utilities.
UserTenantService: Manages the many-to-many relationship between users and tenants, including user roles within tenants.
Each class uses database models (User, Tenant, UserTenant) and integrates with the database connection context managed by Peewee.
Classes and Methods
Class: UserService
Service class focused on operations related to the User model.
Attributes:
model: Reference to theUserORM model class.
Methods:
query(cls, cols=None, reverse=None, order_by=None, **kwargs)
Purpose: Customized query method to retrieve users with additional validation when querying by access_token.
Parameters:
cols(optional): Columns to select.reverse(optional): Whether to reverse the order.order_by(optional): Column(s) to order by.**kwargs: Filter parameters; special handling if access_token is present.
Returns: Peewee
Selectquery object with filtered user records.Usage:
Rejects invalid access_token values such as empty, too short, or tokens starting with "INVALID_" to prevent unauthorized queries.
Otherwise delegates to the parent class
CommonService.query.
filter_by_id(cls, user_id)
Purpose: Fetch a user by their unique ID.
Parameters:
user_id(str): The user's unique identifier.
Returns:
Userinstance if found;Noneif not.Example:
user = UserService.filter_by_id("user-uuid-1234") if user: print(user.email)
query_user(cls, email, password)
Purpose: Authenticate user credentials.
Parameters:
email(str): User's email.password(str): Plain-text password.
Returns: Authenticated
Userobject if credentials are valid; otherwise,None.Implementation Details:
Uses
werkzeug.security.check_password_hashto verify hashed password.Only users with a valid status (
StatusEnum.VALID) are considered.
Example:
user = UserService.query_user("[email protected]", "my_password") if user: print("Authentication successful") else: print("Invalid email or password")
save(cls, **kwargs)
Purpose: Create and save a new user record.
Parameters: Arbitrary keyword arguments for user fields.
Returns: Result of the save operation.
Implementation Details:
Automatically generates a UUID if
idis not provided.Hashes the
passwordwithgenerate_password_hashbefore saving.Sets creation and update timestamps and formatted dates.
Example:
UserService.save(email="[email protected]", password="secret", nickname="Bob")
delete_user(cls, user_ids, update_user_dict)
Purpose: Soft-delete users by setting their
statusto 0.Parameters:
user_ids(list): List of user IDs to delete.update_user_dict: (Unused parameter in current implementation; possibly for audit or future use.)
Returns: None.
Implementation Details: Uses a transaction (
DB.atomic()) for atomic updates.
update_user(cls, user_id, user_dict)
Purpose: Update user fields for a given user ID.
Parameters:
user_id(str): User's ID.user_dict(dict): Fields to update.
Returns: None.
Implementation Details: Updates timestamps and performs an atomic update.
is_admin(cls, user_id)
Purpose: Check if a given user has superuser/admin privileges.
Parameters:
user_id(str): User's ID.
Returns:
Trueif user is a superuser,Falseotherwise.
Class: TenantService
Service class managing tenant-related operations.
Attributes:
model: Reference to theTenantORM model.
Methods:
get_info_by(cls, user_id)
Purpose: Retrieve tenant information where the user is the owner.
Parameters:
user_id(str): User ID.
Returns: List of dictionaries with tenant info and user role.
Implementation Details: Joins
TenantwithUserTenantfiltered by owner role and valid statuses.
get_joined_tenants_by_user_id(cls, user_id)
Purpose: Retrieve tenants where the user has a normal membership.
Parameters:
user_id(str): User ID.
Returns: List of tenant info dicts.
Implementation Details: Similar to
get_info_bybut filters for normal user roles.
decrease(cls, user_id, num)
Purpose: Decrease tenant credit by a specified amount.
Parameters:
user_id(str): Tenant ID.num(int): Credit amount to subtract.
Returns: None.
Raises:
LookupErrorif no tenant was found and updated.Implementation Details: Performs an atomic update of the credit field.
user_gateway(cls, tenant_id)
Purpose: Compute a consistent gateway index for a tenant based on its ID.
Parameters:
tenant_id(str): Tenant ID.
Returns: Integer index within the range of configured MINIO gateways.
Implementation Details: Uses SHA-256 hash of tenant ID mod length of
MINIOlist.
Class: UserTenantService
Service class for managing user-tenant relationships.
Attributes:
model: Reference to theUserTenantORM model.
Methods:
filter_by_id(cls, user_tenant_id)
Purpose: Retrieve a user-tenant association by its ID if valid.
Parameters:
user_tenant_id(str): Relationship ID.
Returns:
UserTenantinstance orNone.
save(cls, **kwargs)
Purpose: Create a new user-tenant association.
Parameters: Arbitrary keyword arguments for fields.
Returns: Result of save operation.
Implementation Details: Generates UUID if
idmissing.
get_by_tenant_id(cls, tenant_id)
Purpose: Get all users related to a tenant except owners.
Parameters:
tenant_id(str)
Returns: List of dicts with detailed user info and roles.
Implementation Details: Joins with
Userfiltering out owners and inactive entries.
get_tenants_by_user_id(cls, user_id)
Purpose: Get tenants associated with a user.
Parameters:
user_id(str)
Returns: List of tenant and role info dicts.
get_num_members(cls, user_id)
Purpose: Count number of members in a tenant.
Parameters:
user_id(str): Tenant ID (likely a naming inconsistency; better named tenant_id).
Returns: Integer count.
filter_by_tenant_and_user_id(cls, tenant_id, user_id)
Purpose: Fetch the user-tenant relationship record for a given user and tenant.
Parameters:
tenant_id(str)user_id(str)
Returns:
UserTenantinstance orNone.
Important Implementation Details
Database Context Management: All database operations are wrapped with
@DB.connection_context()decorator to ensure proper connection lifecycle handling.Password Security: User passwords are stored hashed using
werkzeug.security.generate_password_hashand checked withcheck_password_hash.Soft Deletes: Users are soft-deleted by setting their
statusto0, preserving data integrity.Role Management: User roles in tenants are managed with enums and checked when fetching tenant or user info.
Hash-based Gateway Selection: Tenant gateway selection uses SHA-256 hashing of tenant ID for consistent routing to MinIO gateways.
Atomic Transactions: Updates and deletions are performed inside atomic transactions to ensure data consistency.
Interaction with Other Parts of the System
Database Models: Interacts heavily with ORM models
User,Tenant,UserTenant.CommonService: Inherits from
CommonServicefor base query and CRUD functionality.StatusEnum & Roles: Uses
StatusEnumandUserTenantRoleenums for filtering and role checks.Utilities: Uses utility functions like
get_uuid,current_timestamp, anddatetime_formatfor ID generation and timestamp formatting.Settings: Reads MinIO gateway configuration from
rag.settings.MINIO.
This file acts as the service layer between API endpoints/controllers and the database, encapsulating domain logic for user and tenant management.
Visual Diagram
classDiagram
class UserService {
+model: User
+query(cols, reverse, order_by, **kwargs)
+filter_by_id(user_id)
+query_user(email, password)
+save(**kwargs)
+delete_user(user_ids, update_user_dict)
+update_user(user_id, user_dict)
+is_admin(user_id)
}
class TenantService {
+model: Tenant
+get_info_by(user_id)
+get_joined_tenants_by_user_id(user_id)
+decrease(user_id, num)
+user_gateway(tenant_id)
}
class UserTenantService {
+model: UserTenant
+filter_by_id(user_tenant_id)
+save(**kwargs)
+get_by_tenant_id(tenant_id)
+get_tenants_by_user_id(user_id)
+get_num_members(user_id)
+filter_by_tenant_and_user_id(tenant_id, user_id)
}
UserService --|> CommonService
TenantService --|> CommonService
UserTenantService --|> CommonService
Summary
The user_service.py file is a critical service layer module in InfiniFlow that encapsulates user and tenant management logic, including authentication, role management, tenant credit operations, and user-tenant associations. It leverages Peewee ORM with transactional safety and integrates security best practices for password handling and user session validation. This modular design supports scalable and maintainable code for core identity and access management functionalities.