2024-12-29 03:44:52 +01:00
import uuid
from django . contrib . auth . models import User
from django . db import models
from localflavor . br . br_states import STATE_CHOICES
2025-02-06 11:24:19 +01:00
from django . contrib import admin
2025-02-13 17:55:46 +01:00
import yaml
2024-12-29 03:44:52 +01:00
class UuidModel ( models . Model ) :
uuid = models . UUIDField ( unique = True , editable = False , default = uuid . uuid4 )
class Meta :
abstract = True
class TimeStampedModel ( models . Model ) :
created = models . DateTimeField (
' criado em ' ,
auto_now_add = True ,
auto_now = False
)
modified = models . DateTimeField (
' modificado em ' ,
auto_now_add = False ,
auto_now = True
)
class Meta :
abstract = True
class CreatedBy ( models . Model ) :
created_by = models . ForeignKey (
User ,
verbose_name = ' criado por ' ,
on_delete = models . SET_NULL ,
null = True ,
blank = True ,
)
class Meta :
abstract = True
class Organization ( models . Model ) :
2025-03-19 13:48:52 +01:00
name = models . CharField ( max_length = 255 , unique = True , help_text = " What is the name of your organization? " )
email = models . EmailField ( unique = True , help_text = " What is your email? " )
2025-02-18 11:40:26 +01:00
employee_headcount = models . CharField ( max_length = 20 , help_text = " What is your organization ' s current employee headcount? " )
annual_revenue = models . CharField ( max_length = 20 , help_text = " What is your organization ' s annual revenue range? " )
critical_applications = models . CharField ( max_length = 20 , help_text = " How many critical business applications do your employees use daily? " )
compliance_frameworks = models . JSONField ( help_text = " Which regulatory frameworks is your organization required to comply with? " ) # Stores selected compliance frameworks as a list
industry_sector = models . CharField ( max_length = 255 , help_text = " What is your primary industry sector? " )
2025-04-24 12:53:26 +02:00
it_dependency = models . CharField ( max_length = 255 , help_text = " On a scale from 1-10, how dependent is your business operations on technology? " )
data_sensitivity = models . CharField ( max_length = 20 , help_text = " Overall Sensitivity Level of Data Processed: Subjective rating of the value and impact of the data your organization processes. " )
2025-02-18 11:40:26 +01:00
remote_workforce_percentage = models . CharField ( max_length = 20 , help_text = " What percentage of your workforce operates remotely? " )
third_party_vendor_access = models . CharField ( max_length = 20 , help_text = " How many third-party vendors have access to your systems? " )
internal_software_development = models . CharField ( max_length = 20 , help_text = " What is the extent of your internal software development activities? " )
geographic_scope = models . CharField ( max_length = 20 , null = True , blank = True , help_text = " What is your organization ' s geographic operational scope? " )
2025-05-06 18:59:29 +02:00
customer_base = models . CharField ( max_length = 255 , null = True , blank = True , help_text = " How would you characterize your customer base distribution? " )
2025-02-18 11:40:26 +01:00
customer_type = models . CharField ( max_length = 20 , null = True , blank = True , help_text = " What is your primary customer type? " )
product_portfolio = models . CharField ( max_length = 20 , null = True , blank = True , help_text = " How diversified is your product/service portfolio? " )
supplier_base = models . CharField ( max_length = 20 , null = True , blank = True , help_text = " What is your supplier base structure? " )
it_infrastructure = models . JSONField ( null = True , blank = True , help_text = " What is your primary IT infrastructure model? " ) # Stores selected IT infrastructure types as a list
integration_level = models . CharField ( max_length = 20 , null = True , blank = True , help_text = " How integrated are your critical business systems? " )
2025-04-24 12:53:26 +02:00
network_infrastructure = models . CharField ( max_length = 20 , null = True , blank = True , help_text = " What best describes your organization ' s network infrastructure model? " )
change_rate = models . CharField ( max_length = 20 , null = True , blank = True , help_text = " How frequently does your organization undergo significant technology or business changes? " )
threat_actors = models . JSONField ( null = True , blank = True , help_text = " Which types of threat actors are most relevant to your organization (e.g., cybercriminals, insiders, nation-states)? " )
2025-09-17 15:24:34 +02:00
sensitive_data_types = models . JSONField ( null = True , blank = True , help_text = " Stores applicable status and business impact rating (1-5) for each sensitive data type. Example: { ' personal ' : { ' applicable ' : True, ' impact ' : 4}, ...} " )
2025-02-12 13:46:19 +01:00
risks = models . ManyToManyField ( ' Risk ' , related_name = ' organizations ' , blank = True )
2025-08-17 18:43:55 +02:00
expert_analysis = models . BooleanField ( null = True , blank = True )
2025-02-12 13:46:19 +01:00
2024-12-29 03:44:52 +01:00
def __str__ ( self ) :
return self . name
2025-02-06 11:24:19 +01:00
class DocumentSegment ( models . Model ) :
SEGMENT_TYPES = (
( ' title ' , ' Title ' ) ,
( ' subtitle ' , ' Subtitle ' ) ,
( ' h1 ' , ' Header 1 ' ) ,
( ' h2 ' , ' Header 2 ' ) ,
( ' h3 ' , ' Header 3 ' ) ,
( ' body ' , ' Body Text ' ) ,
( ' quote ' , ' Quote ' )
)
document = models . ForeignKey ( ' Document ' , on_delete = models . CASCADE , related_name = ' segments ' )
segment_type = models . CharField ( max_length = 20 , choices = SEGMENT_TYPES )
content = models . TextField ( )
order = models . PositiveIntegerField ( )
modified_at = models . DateTimeField ( auto_now = True )
class Meta :
ordering = [ ' order ' ]
def __str__ ( self ) :
return f " { self . get_segment_type_display ( ) } - { self . content [ : 50 ] } "
class Document ( models . Model ) :
2025-02-12 13:46:19 +01:00
id = models . UUIDField ( primary_key = True , default = uuid . uuid4 , editable = False )
2025-02-06 11:24:19 +01:00
organization = models . ForeignKey ( Organization , on_delete = models . CASCADE , related_name = ' documents ' )
created_at = models . DateTimeField ( auto_now_add = True )
modified_at = models . DateTimeField ( auto_now = True )
2025-08-17 18:43:55 +02:00
STATUS_WAITING = ' waiting '
STATUS_DONE = ' done '
2025-08-26 19:32:03 +02:00
STATUS_INCOMPLETE = ' incomplete '
2025-08-17 18:43:55 +02:00
STATUS_CHOICES = (
( STATUS_WAITING , ' Waiting ' ) ,
( STATUS_DONE , ' Done ' ) ,
2025-08-26 19:32:03 +02:00
( STATUS_INCOMPLETE , ' Incomplete ' ) ,
2025-08-17 18:43:55 +02:00
)
status = models . CharField ( max_length = 16 , choices = STATUS_CHOICES , default = STATUS_WAITING )
2025-07-03 17:34:33 +02:00
key_findings = models . TextField ( blank = True , null = True , help_text = " Key findings " )
2025-08-11 21:51:21 +02:00
recomendations = models . TextField ( blank = True , null = True , help_text = " Recommendations " )
2025-02-06 11:24:19 +01:00
def __str__ ( self ) :
return f " Document for { self . organization . name } "
def add_segment ( self , segment_type , content , position = None ) :
"""
Add a new segment at the specified position .
If position is None , append to the end .
"""
if position is None :
# Get the highest order and add 1
last_order = self . segments . aggregate ( models . Max ( ' order ' ) ) [ ' order__max ' ]
new_order = 1 if last_order is None else last_order + 1
else :
# Move all segments at and after the position up by 1
self . segments . filter ( order__gte = position ) . update ( order = models . F ( ' order ' ) + 1 )
new_order = position
return self . segments . create (
segment_type = segment_type ,
content = content ,
order = new_order
)
2025-02-13 17:55:46 +01:00
class DocumentTemplate ( models . Model ) :
name = models . CharField ( max_length = 255 , unique = True )
content = models . TextField ( help_text = " YAML format content " )
created_at = models . DateTimeField ( auto_now_add = True )
updated_at = models . DateTimeField ( auto_now = True )
def to_dict ( self ) :
return yaml . safe_load ( self . content )
2025-02-06 11:24:19 +01:00
2025-02-07 17:05:03 +01:00
class Risk ( models . Model ) :
risk_id = models . IntegerField ( unique = True )
category = models . CharField ( max_length = 255 )
risk_name = models . CharField ( max_length = 255 )
primary_impact = models . TextField ( )
secondary_impact = models . TextField ( )
tretiary_impact = models . TextField ( )
detection_difficulty = models . CharField ( max_length = 255 )
recovery_complexity = models . CharField ( max_length = 255 )
businnes_impact_severity = models . CharField ( max_length = 255 )
def __str__ ( self ) :
return f " { self . risk_id } - { self . risk_name } "
2025-02-06 11:24:19 +01:00
2025-02-12 16:15:06 +01:00
class Control ( models . Model ) :
2025-02-13 18:29:54 +01:00
id = models . AutoField ( primary_key = True )
2025-08-14 14:08:34 +02:00
subcategory = models . CharField ( max_length = 64 , unique = True , null = False , blank = False , help_text = ' NIST Subcategory ' )
function = models . TextField ( null = True , blank = True , help_text = " Function " )
category = models . TextField ( null = True , blank = True , help_text = " Category " )
implementation_examples = models . TextField ( null = True , blank = True , help_text = " Implementation Examples " )
effectiveness_monitoring_examples = models . TextField ( null = True , blank = True , help_text = " Effectiveness Monitoring Examples " )
documentation_score = models . IntegerField ( null = True , blank = True , help_text = " Documentation Score " )
implementation_score = models . IntegerField ( null = True , blank = True , help_text = " Implementation Score " )
2025-02-12 16:15:06 +01:00
def __str__ ( self ) :
2025-08-14 14:08:34 +02:00
return f " { self . id } ( { self . subcategory } - { self . function or self . category or ' ' } ) " . rstrip ( " -() " )
2025-02-14 17:52:51 +01:00
class DocumentRiskControl ( models . Model ) :
document = models . ForeignKey ( Document , on_delete = models . CASCADE )
risk = models . ForeignKey ( Risk , on_delete = models . CASCADE )
control = models . ForeignKey ( Control , on_delete = models . CASCADE )
weight = models . IntegerField ( )
2025-03-27 23:57:31 +01:00
likelihood = models . IntegerField ( null = True , blank = True )
2025-02-14 17:52:51 +01:00
class Meta :
2025-06-20 00:56:57 +02:00
unique_together = ( ' document ' , ' risk ' , ' control ' )
2025-07-14 11:29:11 +02:00
class DemoCode ( models . Model ) :
2025-06-20 00:56:57 +02:00
code = models . CharField ( max_length = 10 , unique = True )
created_at = models . DateTimeField ( auto_now_add = True )
used = models . BooleanField ( default = False )
used_at = models . DateTimeField ( null = True , blank = True )
company = models . ForeignKey ( Organization , null = True , blank = True , on_delete = models . SET_NULL )
def __str__ ( self ) :
return ( f " { self . code } - { ' Used ' if self . used else ' Available ' } " )