Coverage for product_risk_suite/product_risk_suite/settings.py: 95%

37 statements  

« prev     ^ index     » next       coverage.py v7.15.2, created at 2026-07-16 14:44 +0000

1""" 

2Django settings for product_risk_suite project. 

3 

4Generated by 'django-admin startproject' using Django 6.0.3. 

5 

6For more information on this file, see 

7https://docs.djangoproject.com/en/6.0/topics/settings/ 

8 

9For the full list of settings and their values, see 

10https://docs.djangoproject.com/en/6.0/ref/settings/ 

11""" 

12 

13from pathlib import Path 

14import os 

15import logging 

16 

17# Build paths inside the project like this: BASE_DIR / 'subdir'. 

18BASE_DIR = Path(__file__).resolve().parent.parent 

19 

20# enforce it even if its true by default 

21APPEND_SLASH = True 

22 

23# Quick-start development settings - unsuitable for production 

24# See https://docs.djangoproject.com/en/6.0/howto/deployment/checklist/ 

25 

26# SECURITY WARNING: keep the secret key used in production secret! 

27SECRET_KEY = os.environ.get("DJANGO_SECRET_KEY", 'django-insecure-scwz(sj+*te-dbfuc)vnkju5y1=p1en^d#8mz5*keg2(fj^mn-dudi-bla%') 

28 

29# SECURITY WARNING: don't run with debug turned on in production! 

30DEBUG = bool(os.environ.get("DJANGO_DEBUG", default=False)) 

31IN_DOCKER = bool(os.environ.get("IN_DOCKER", default=False)) 

32 

33ALLOWED_HOSTS = os.environ.get("DJANGO_ALLOWED_HOSTS","127.0.0.1,localhost").split(",") 

34CSRF_TRUSTED_ORIGINS = os.environ.get("DJANGO_CSRF_TRUSTED_ORIGINS", "https://localhost:8443,http://localhost:80").split(",") 

35 

36# Application definition 

37INSTALLED_APPS = [ 

38 'django.contrib.admin', 

39 'django.contrib.auth', 

40 'django.contrib.contenttypes', 

41 'django.contrib.sessions', 

42 'django.contrib.messages', 

43 'django.contrib.staticfiles', 

44 'django_summernote', 

45 "graphene_django", 

46 'guardian', 

47 'product_risk_suite', 

48 'risk_assessment', 

49 'threat_model', 

50 'product', 

51 'api', 

52 'scraper', 

53] 

54 

55GRAPHENE = { 

56 "SCHEMA": "api.schema.schema", 

57} 

58 

59MIDDLEWARE = [ 

60 'django.middleware.security.SecurityMiddleware', 

61 'django.contrib.sessions.middleware.SessionMiddleware', 

62 'django.middleware.common.CommonMiddleware', 

63 'django.middleware.csrf.CsrfViewMiddleware', 

64 'django.contrib.auth.middleware.AuthenticationMiddleware', 

65 'api.middleware.APITokenAuthenticationMiddleware', 

66 'django.contrib.messages.middleware.MessageMiddleware', 

67 'django.middleware.clickjacking.XFrameOptionsMiddleware', 

68] 

69 

70ROOT_URLCONF = 'product_risk_suite.urls' 

71 

72TEMPLATES = [ 

73 { 

74 'BACKEND': 'django.template.backends.django.DjangoTemplates', 

75 'DIRS': [BASE_DIR / 'product_risk_suite' / 'templates'], 

76 'APP_DIRS': True, 

77 'OPTIONS': { 

78 'context_processors': [ 

79 'django.template.context_processors.request', 

80 'django.contrib.auth.context_processors.auth', 

81 'django.contrib.messages.context_processors.messages', 

82 ], 

83 }, 

84 }, 

85] 

86 

87WSGI_APPLICATION = 'product_risk_suite.wsgi.application' 

88 

89SUMMERNOTE_CONFIG = { 

90 # Using SummernoteWidget - iframe mode, default 

91 'iframe': True, 

92 'summernote': { 

93 'lang': 'en-US', 

94 

95 # Toolbar customization 

96 # https://summernote.org/deep-dive/#custom-toolbar-popover 

97 'toolbar': [ 

98 ['font', ['bold', 'italic', 'underline', 'clear']], 

99 ['para', ['ul', 'ol', 'paragraph']], 

100 ['insert', ['link']], 

101 ['view', ['fullscreen', 'codeview', 'help']], 

102 ], 

103 } 

104} 

105 

106# Database 

107# https://docs.djangoproject.com/en/6.0/ref/settings/#databases 

108 

109DATABASES = { 

110 'default': { 

111 'ENGINE': f"django.db.backends.{os.getenv('DATABASE_ENGINE', 'sqlite3')}", 

112 'NAME': os.getenv('DATABASE_NAME', BASE_DIR / 'db.sqlite3'), 

113 'USER': os.getenv('DATABASE_USERNAME'), 

114 'PASSWORD': os.getenv('DATABASE_PASSWORD'), 

115 'HOST': os.getenv('DATABASE_HOST'), 

116 'PORT': os.getenv('DATABASE_PORT'), 

117 } 

118} 

119 

120# Password validation 

121# https://docs.djangoproject.com/en/6.0/ref/settings/#auth-password-validators 

122 

123AUTH_PASSWORD_VALIDATORS = [ 

124 { 

125 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', 

126 }, 

127 { 

128 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 

129 }, 

130 { 

131 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', 

132 }, 

133 { 

134 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', 

135 }, 

136] 

137 

138LOGGING = { 

139 'version': 1, 

140 'disable_existing_loggers': False, 

141 'formatters': { 

142 'verbose': { 

143 'format': '{levelname} {asctime} {module} {message}', 

144 'style': '{', 

145 }, 

146 }, 

147 'handlers': { 

148 'console': { 

149 'level': os.getenv("DJANGO_LOG_LEVEL", "INFO"), 

150 'class': 'logging.StreamHandler', 

151 'formatter': 'verbose', 

152 }, 

153 }, 

154 'root': { 

155 'handlers': ['console'], 

156 'level': os.getenv("DJANGO_LOG_LEVEL", "INFO"), 

157 }, 

158 'loggers': { 

159 'django': { 

160 'handlers': ['console'], 

161 'level': os.getenv("DJANGO_LOG_LEVEL", "INFO"), 

162 'propagate': True, 

163 }, 

164 # For your app-specific logs (e.g., `myapp`) 

165 'myapp': { 

166 'handlers': ['console'], 

167 'level': os.getenv("DJANGO_LOG_LEVEL", "INFO"), 

168 'propagate': True, 

169 }, 

170 }, 

171} 

172 

173AUTHENTICATION_BACKENDS = ( 

174 'django.contrib.auth.backends.ModelBackend', # Default backend 

175 'guardian.backends.ObjectPermissionBackend', # For object permissions 

176) 

177 

178# Internationalization 

179# https://docs.djangoproject.com/en/6.0/topics/i18n/ 

180 

181LANGUAGE_CODE = 'en-us' 

182 

183TIME_ZONE = 'UTC' 

184 

185USE_I18N = True 

186 

187USE_TZ = True 

188 

189LOGIN_URL = '/login' 

190 

191# Static files (CSS, JavaScript, Images) 

192# https://docs.djangoproject.com/en/6.0/howto/static-files/ 

193 

194STATIC_URL = '/static/' 

195if IN_DOCKER: 

196 STATIC_ROOT = "/app/staticfiles" 

197else: 

198 STATIC_ROOT = BASE_DIR / "staticfiles" 

199 

200STATICFILES_DIRS = [ 

201 BASE_DIR / "static", 

202] 

203 

204# uploaded files 

205MEDIA_URL = '/media/' 

206if IN_DOCKER: 

207 MEDIA_ROOT = "/data/media" 

208else: 

209 MEDIA_ROOT = BASE_DIR / "media" 

210 

211# Evidence scraper 

212# how often (in seconds) the `sync_evidence_scrapers --loop` command re-checks 

213# every Evidence that has a scraper assigned 

214EVIDENCE_SCRAPER_INTERVAL_SECONDS = int(os.environ.get("DJANGO_EVIDENCE_SCRAPER_INTERVAL_SECONDS", 3600)) 

215 

216# Fernet key used to encrypt RemoteCredential secrets at rest. 

217# SECURITY WARNING: this insecure default is for local development only, generate a 

218# real one for any other environment with: 

219# python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())" 

220EVIDENCE_SCRAPER_CREDENTIAL_KEY = os.environ.get( 

221 "DJANGO_SCRAPER_CREDENTIAL_KEY", "NWSGod1MU0KeNH-_eCPd7CDdHSFl95_YFp-fDN3vqJI=" 

222)