constants.py 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. from jinja2 import ChainableUndefined, DebugUndefined, StrictUndefined, Undefined
  2. from core.events import *
  3. from extras.choices import LogLevelChoices
  4. # Custom fields
  5. CUSTOMFIELD_EMPTY_VALUES = (None, '', [])
  6. # Maximum number of objects to update per query when provisioning, removing, or renaming custom
  7. # field data. Bounding the number of rows touched by each statement prevents very large tables from
  8. # exceeding the database statement timeout (JSONB updates rewrite each affected row). This value
  9. # sits at the throughput "knee": benchmarking jsonb_set() across a 1M-row table showed throughput
  10. # plateaus by ~5K rows/statement (raising it further yields no meaningful speedup), while keeping
  11. # each statement orders of magnitude below a typical statement timeout.
  12. CUSTOMFIELD_DATA_BATCH_SIZE = 5000
  13. # ImageAttachment
  14. IMAGE_ATTACHMENT_IMAGE_FORMATS = {
  15. 'avif': 'image/avif',
  16. 'bmp': 'image/bmp',
  17. 'gif': 'image/gif',
  18. 'jpeg': 'image/jpeg',
  19. 'jpg': 'image/jpeg',
  20. 'png': 'image/png',
  21. 'webp': 'image/webp',
  22. }
  23. # Template Export
  24. DEFAULT_MIME_TYPE = 'text/plain; charset=utf-8'
  25. # Scripts
  26. # Prefix applied to dynamically-loaded script/report module names so that a script whose filename
  27. # matches a core app or package (e.g. "circuits.py") cannot shadow it in sys.modules.
  28. SCRIPT_MODULE_NAME_PREFIX = '_netbox_script_module_'
  29. # Webhooks
  30. HTTP_CONTENT_TYPE_JSON = 'application/json'
  31. WEBHOOK_EVENT_TYPES = {
  32. # Map registered event types to public webhook "event" equivalents
  33. OBJECT_CREATED: 'created',
  34. OBJECT_UPDATED: 'updated',
  35. OBJECT_DELETED: 'deleted',
  36. JOB_STARTED: 'job_started',
  37. JOB_COMPLETED: 'job_ended',
  38. JOB_FAILED: 'job_ended',
  39. JOB_ERRORED: 'job_ended',
  40. }
  41. # Allowed Jinja2 environment parameters and their permitted values.
  42. # Only keys listed here may appear in a template's environment_params.
  43. # None = any JSON-serializable value accepted (scalars, booleans, etc.)
  44. # dict = only dict keys accepted; dict values are the resolved Python objects
  45. #
  46. # Note: 'finalize' is intentionally absent. It is deprecated and handled as a
  47. # legacy carve-out in RenderTemplateMixin (blocked from new use, but existing
  48. # stored values continue to resolve via import_string at render time).
  49. JINJA_ENV_PARAMS_ALLOWED = {
  50. # Boolean / scalar params (accept any JSON-serializable value)
  51. 'auto_reload': None,
  52. 'autoescape': None,
  53. 'cache_size': None,
  54. 'enable_async': None,
  55. 'keep_trailing_newline': None,
  56. 'lstrip_blocks': None,
  57. 'optimized': None,
  58. 'trim_blocks': None,
  59. # String params (template syntax delimiters)
  60. 'block_start_string': None,
  61. 'block_end_string': None,
  62. 'comment_start_string': None,
  63. 'comment_end_string': None,
  64. 'line_comment_prefix': None,
  65. 'line_statement_prefix': None,
  66. 'newline_sequence': None,
  67. 'variable_start_string': None,
  68. 'variable_end_string': None,
  69. # Mapped params (value must be a key in the dict; resolved to the dict value)
  70. 'undefined': {
  71. 'jinja2.ChainableUndefined': ChainableUndefined,
  72. 'jinja2.DebugUndefined': DebugUndefined,
  73. 'jinja2.StrictUndefined': StrictUndefined,
  74. 'jinja2.Undefined': Undefined,
  75. },
  76. # Excluded (dangerous — accept callables or trigger imports):
  77. # 'bytecode_cache' — accepts arbitrary object
  78. # 'extensions' — Jinja2 internally calls import_string() on string entries
  79. # 'finalize' — deprecated; legacy carve-out in RenderTemplateMixin
  80. # 'loader' — accepts arbitrary object
  81. }
  82. # Dashboard
  83. DEFAULT_DASHBOARD = [
  84. {
  85. 'widget': 'extras.BookmarksWidget',
  86. 'width': 4,
  87. 'height': 5,
  88. 'title': 'Bookmarks',
  89. 'color': 'orange',
  90. },
  91. {
  92. 'widget': 'extras.ObjectCountsWidget',
  93. 'width': 4,
  94. 'height': 2,
  95. 'title': 'Organization',
  96. 'config': {
  97. 'models': [
  98. 'dcim.site',
  99. 'tenancy.tenant',
  100. 'tenancy.contact',
  101. ]
  102. }
  103. },
  104. {
  105. 'widget': 'extras.NoteWidget',
  106. 'width': 4,
  107. 'height': 2,
  108. 'title': 'Welcome!',
  109. 'color': 'green',
  110. 'config': {
  111. 'content': (
  112. 'This is your personal dashboard. Feel free to customize it by rearranging, resizing, or removing '
  113. 'widgets. You can also add new widgets using the "add widget" button below. Any changes affect only '
  114. '_your_ dashboard, so feel free to experiment!'
  115. )
  116. }
  117. },
  118. {
  119. 'widget': 'extras.ObjectCountsWidget',
  120. 'width': 4,
  121. 'height': 3,
  122. 'title': 'IPAM',
  123. 'config': {
  124. 'models': [
  125. 'ipam.vrf',
  126. 'ipam.aggregate',
  127. 'ipam.prefix',
  128. 'ipam.iprange',
  129. 'ipam.ipaddress',
  130. 'ipam.vlan',
  131. ]
  132. }
  133. },
  134. {
  135. 'widget': 'extras.RSSFeedWidget',
  136. 'width': 4,
  137. 'height': 4,
  138. 'title': 'NetBox News',
  139. 'config': {
  140. 'feed_url': 'https://api.netbox.oss.netboxlabs.com/v1/newsfeed/',
  141. 'max_entries': 10,
  142. 'cache_timeout': 14400,
  143. 'requires_internet': True,
  144. }
  145. },
  146. {
  147. 'widget': 'extras.ObjectCountsWidget',
  148. 'width': 4,
  149. 'height': 3,
  150. 'title': 'Circuits',
  151. 'config': {
  152. 'models': [
  153. 'circuits.provider',
  154. 'circuits.circuit',
  155. 'circuits.providernetwork',
  156. 'circuits.provideraccount',
  157. ]
  158. }
  159. },
  160. {
  161. 'widget': 'extras.ObjectCountsWidget',
  162. 'width': 4,
  163. 'height': 3,
  164. 'title': 'DCIM',
  165. 'config': {
  166. 'models': [
  167. 'dcim.site',
  168. 'dcim.rack',
  169. 'dcim.devicetype',
  170. 'dcim.device',
  171. 'dcim.cable',
  172. ],
  173. }
  174. },
  175. {
  176. 'widget': 'extras.ObjectCountsWidget',
  177. 'width': 4,
  178. 'height': 2,
  179. 'title': 'Virtualization',
  180. 'config': {
  181. 'models': [
  182. 'virtualization.cluster',
  183. 'virtualization.virtualmachine',
  184. ]
  185. }
  186. },
  187. {
  188. 'widget': 'extras.ObjectListWidget',
  189. 'width': 12,
  190. 'height': 5,
  191. 'title': 'Change Log',
  192. 'color': 'blue',
  193. 'config': {
  194. 'model': 'core.objectchange',
  195. 'page_size': 25,
  196. }
  197. },
  198. ]
  199. LOG_LEVEL_RANK = {
  200. LogLevelChoices.LOG_DEBUG: 0,
  201. LogLevelChoices.LOG_INFO: 1,
  202. LogLevelChoices.LOG_SUCCESS: 2,
  203. LogLevelChoices.LOG_WARNING: 3,
  204. LogLevelChoices.LOG_FAILURE: 4,
  205. }
  206. # Config context cache: fields whose modification on an object requires re-rendering its config
  207. # context cache, keyed by model label.
  208. CC_FIELDS_BY_MODEL = {
  209. 'dcim.device': (
  210. 'site_id', 'location_id', 'device_type_id', 'role_id', 'tenant_id', 'platform_id',
  211. 'cluster_id', 'local_context_data',
  212. ),
  213. 'virtualization.virtualmachine': (
  214. 'site_id', 'cluster_id', 'tenant_id', 'platform_id', 'role_id', 'local_context_data',
  215. ),
  216. }