Coverage for src / local_deep_research / database / models / settings.py: 95%

56 statements  

« prev     ^ index     » next       coverage.py v7.13.4, created at 2026-02-25 01:07 +0000

1""" 

2Settings and configuration models. 

3Stores user preferences and API keys in encrypted database. 

4""" 

5 

6import enum 

7 

8from sqlalchemy import ( 

9 JSON, 

10 Boolean, 

11 Column, 

12 Enum, 

13 Float, 

14 Integer, 

15 String, 

16 Text, 

17 UniqueConstraint, 

18) 

19from sqlalchemy_utc import UtcDateTime, utcnow 

20 

21from .base import Base 

22 

23 

24class UserSettings(Base): 

25 """ 

26 User-specific settings stored in their encrypted database. 

27 Replaces the need for config files or unencrypted storage. 

28 """ 

29 

30 __tablename__ = "user_settings" 

31 

32 id = Column(Integer, primary_key=True) 

33 key = Column(String(255), unique=True, nullable=False, index=True) 

34 value = Column(JSON) 

35 category = Column(String(100)) 

36 description = Column(Text) 

37 created_at = Column(UtcDateTime, default=utcnow()) 

38 updated_at = Column(UtcDateTime, default=utcnow(), onupdate=utcnow()) 

39 

40 def __repr__(self): 

41 return f"<UserSettings(key='{self.key}', category='{self.category}')>" 

42 

43 

44class APIKey(Base): 

45 """ 

46 Encrypted storage for API keys. 

47 These are especially sensitive and benefit from database encryption. 

48 """ 

49 

50 __tablename__ = "api_keys" 

51 

52 id = Column(Integer, primary_key=True) 

53 provider = Column(String(100), unique=True, nullable=False, index=True) 

54 key = Column(Text, nullable=False) # Encrypted by SQLCipher 

55 description = Column(Text) 

56 is_active = Column(Boolean, default=True) 

57 created_at = Column(UtcDateTime, default=utcnow()) 

58 updated_at = Column(UtcDateTime, default=utcnow(), onupdate=utcnow()) 

59 last_used = Column(UtcDateTime) 

60 usage_count = Column(Integer, default=0) 

61 

62 def __repr__(self): 

63 # Never show the actual key in repr 

64 return f"<APIKey(provider='{self.provider}', active={self.is_active})>" 

65 

66 

67class SettingType(str, enum.Enum): 

68 """Types of settings. 

69 

70 Inherits from ``str`` so that instances are JSON-serializable and work 

71 seamlessly with both SQLAlchemy columns and Pydantic models. 

72 """ 

73 

74 APP = "app" 

75 LLM = "llm" 

76 SEARCH = "search" 

77 REPORT = "report" 

78 DATABASE = "database" 

79 

80 

81class Setting(Base): 

82 """ 

83 Global application settings (shared across users). 

84 For user-specific settings, use UserSettings. 

85 """ 

86 

87 __tablename__ = "settings" 

88 

89 id = Column(Integer, primary_key=True, index=True) 

90 key = Column(String(255), nullable=False, unique=True, index=True) 

91 value = Column(JSON, nullable=True) 

92 type = Column(Enum(SettingType), nullable=False, index=True) 

93 name = Column(String(255), nullable=False) 

94 description = Column(Text, nullable=True) 

95 category = Column(String(100), nullable=True, index=True) 

96 ui_element = Column(String(50), default="text", nullable=False) 

97 options = Column(JSON, nullable=True) # For select elements 

98 min_value = Column(Float, nullable=True) # For numeric inputs 

99 max_value = Column(Float, nullable=True) # For numeric inputs 

100 step = Column(Float, nullable=True) # For sliders 

101 visible = Column(Boolean, default=True, nullable=False) 

102 editable = Column(Boolean, default=True, nullable=False) 

103 env_var = Column(String(255), nullable=True) # Environment variable name 

104 created_at = Column(UtcDateTime, server_default=utcnow(), nullable=False) 

105 updated_at = Column( 

106 UtcDateTime, server_default=utcnow(), onupdate=utcnow(), nullable=False 

107 ) 

108 

109 __table_args__ = (UniqueConstraint("key", name="uix_settings_key"),) 

110 

111 def __repr__(self): 

112 return f"<Setting(key='{self.key}', type={self.type.value})>"