Coverage for apps/integrations/models.py: 93%
44 statements
« prev ^ index » next coverage.py v7.17.0, created at 2026-11-04 17:24 +0000
« prev ^ index » next coverage.py v7.17.0, created at 2026-11-04 17:24 +0000
1"""Integration + credential models (design D1). Secrets are stored as Fernet blobs in
2``secret_enc`` and are never exposed over the API (design D2)."""
4from __future__ import annotations
6from django.conf import settings
7from django.db import models
10class OrgIntegration(models.Model):
11 """Per-org enablement + non-secret config + encrypted secret for a catalog provider."""
13 org_unit = models.ForeignKey(
14 "accounts.OrgUnit", on_delete=models.CASCADE, related_name="integrations"
15 )
16 provider = models.CharField(max_length=40) # catalog code
17 enabled = models.BooleanField(default=False)
18 config = models.JSONField(default=dict, blank=True)
19 secret_enc = models.BinaryField(null=True, blank=True)
20 created_at = models.DateTimeField(auto_now_add=True)
21 updated_at = models.DateTimeField(auto_now=True)
23 class Meta:
24 db_table = "org_integrations"
25 unique_together = ("org_unit", "provider")
27 def __str__(self) -> str:
28 return f"{self.org_unit_id}:{self.provider} ({'on' if self.enabled else 'off'})"
31class UserCredential(models.Model):
32 """Per-user credential (credit login, DU/LPA ownership accounts) — encrypted secret."""
34 user = models.ForeignKey(
35 settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="credentials"
36 )
37 provider = models.CharField(max_length=40) # catalog code
38 config = models.JSONField(default=dict, blank=True)
39 secret_enc = models.BinaryField(null=True, blank=True)
40 created_at = models.DateTimeField(auto_now_add=True)
41 updated_at = models.DateTimeField(auto_now=True)
43 class Meta:
44 db_table = "user_credentials"
45 unique_together = ("user", "provider")
47 def __str__(self) -> str:
48 return f"{self.user_id}:{self.provider}"
51class Lender(models.Model):
52 """Per-org approved lender with per-capability flags (spec §8.6 lender integrations)."""
54 org_unit = models.ForeignKey(
55 "accounts.OrgUnit", on_delete=models.CASCADE, related_name="lenders"
56 )
57 name = models.CharField(max_length=255)
58 pricing_ind = models.BooleanField(default=False)
59 registration_ind = models.BooleanField(default=False)
60 doc_submission_ind = models.BooleanField(default=False)
61 auto_sync_ind = models.BooleanField(default=False)
62 authorization_ind = models.BooleanField(default=False)
63 is_active = models.BooleanField(default=True)
64 created_at = models.DateTimeField(auto_now_add=True)
65 updated_at = models.DateTimeField(auto_now=True)
67 class Meta:
68 db_table = "lenders"
69 unique_together = ("org_unit", "name")
71 def __str__(self) -> str:
72 return f"{self.name} (org {self.org_unit_id})"