django-restit 4.1.60__py3-none-any.whl → 4.1.62__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- account/rpc/group.py +1 -0
- {django_restit-4.1.60.dist-info → django_restit-4.1.62.dist-info}/METADATA +1 -1
- {django_restit-4.1.60.dist-info → django_restit-4.1.62.dist-info}/RECORD +16 -13
- incident/migrations/0010_incident_category_incident_component_id.py +23 -0
- incident/migrations/0011_ticket.py +38 -0
- incident/models/__init__.py +1 -0
- incident/models/event.py +28 -2
- incident/models/incident.py +67 -36
- incident/models/ticket.py +65 -0
- incident/rpc.py +6 -0
- incident/templates/email/incident_change.html +347 -436
- incident/templates/email/incident_plain.html +27 -9
- incident/tq.py +14 -6
- rest/__init__.py +1 -1
- {django_restit-4.1.60.dist-info → django_restit-4.1.62.dist-info}/LICENSE.md +0 -0
- {django_restit-4.1.60.dist-info → django_restit-4.1.62.dist-info}/WHEEL +0 -0
account/rpc/group.py
CHANGED
@@ -33,7 +33,7 @@ account/periodic.py,sha256=imh9C-oQVhfw7GX3RRHYuC6DIreGbXrQM35A8C4UjOE,876
|
|
33
33
|
account/rpc/__init__.py,sha256=L_AqHC0WbgUgLoqvNz6pY0E34eqh7sRaX77I6TxhRZ4,152
|
34
34
|
account/rpc/auth.py,sha256=8CgXsbNZLeBcd5MHpdL29z9E8PYUcKX_zYpTPX_Pa-0,12516
|
35
35
|
account/rpc/device.py,sha256=fbbZFp3cUdhVXvD7gVFOqFWj4hKS3bjZKD_aF5fQxd8,2852
|
36
|
-
account/rpc/group.py,sha256=
|
36
|
+
account/rpc/group.py,sha256=dUIZGArPgnKafL7F44f7Qum5EAskWcjj64Haqlkbdb8,3448
|
37
37
|
account/rpc/member.py,sha256=oKdXSGhQ7AOPTwisZ5RvHhQ1SdZoXWlBQY0lIlDXJY0,1150
|
38
38
|
account/rpc/notify.py,sha256=Q2YWejP36egeF060Hih5uX4Psv_B8NWlLLPi7iDYlIw,3344
|
39
39
|
account/rpc/oauth.py,sha256=-BW38HjYwSQhOs31ubnBxO0yCKVpczEMoHq54NC9uOU,2610
|
@@ -89,20 +89,23 @@ incident/migrations/0006_delete_eventmetadata.py,sha256=buSEY_TmmXi9ShPFxB74Os2q
|
|
89
89
|
incident/migrations/0007_event_metadata.py,sha256=syxcM4gIcBwSjcpdU69CXq5dGS1Gu8OodZtPJFDpY5U,414
|
90
90
|
incident/migrations/0008_incident_action_sent_incident_hostname_and_more.py,sha256=N2D47E9k4PxOo-9C72gqYkb6K0GqVIO4PkvdnWlrSuA,903
|
91
91
|
incident/migrations/0009_incident_reporter_ip.py,sha256=JOrTGBPJw9g7cg--HH3zqnbsMowjNSgzxJTrKojcPJA,473
|
92
|
+
incident/migrations/0010_incident_category_incident_component_id.py,sha256=FGRHnWJOPeKl5ko17L7rkERrLeyGCWET7sFmZbTB-YQ,631
|
93
|
+
incident/migrations/0011_ticket.py,sha256=Ml5E_Qi4Z0MD89fetoOFOL3rPlVQdjaaDCcFBfOuwd4,2142
|
92
94
|
incident/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
93
|
-
incident/models/__init__.py,sha256=
|
94
|
-
incident/models/event.py,sha256=
|
95
|
-
incident/models/incident.py,sha256=
|
95
|
+
incident/models/__init__.py,sha256=NMphuhb0RTMf7Ov4QkNv7iv6_I8Wtr3xQ54yjX_a31M,209
|
96
|
+
incident/models/event.py,sha256=5cbtIQwY2DTBR9PkQX9jKIWtzbFb69BLMOUdWieMrVw,6772
|
97
|
+
incident/models/incident.py,sha256=xOtlGyc6TxOoCEtHU1bdSYFBnjfDGhzT2C0YFklfwmY,13059
|
96
98
|
incident/models/ossec.py,sha256=pWMqcuTRxPFTEF-OZQSMn7YpNEE9mfsI4GMhWWjJs5I,2187
|
97
99
|
incident/models/rules.py,sha256=67fbtEDfznxCYb-B89417lgYesN12PzmY25WBF_65a8,5300
|
100
|
+
incident/models/ticket.py,sha256=S3kqGQpYLE6Y4M9IKu_60sgW-f592xNr8uufqHnvDoU,2302
|
98
101
|
incident/parsers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
99
102
|
incident/parsers/ossec.py,sha256=4_7Tpr_XBK8HerGSbdrOrAOAtbRvRE7WZ2Xedo3kp8g,5724
|
100
103
|
incident/periodic.py,sha256=3YatKLLzoM9Q-3QXaIPtVIytLRCZt-7-IaD4tvKKGjg,723
|
101
|
-
incident/rpc.py,sha256=
|
102
|
-
incident/templates/email/incident_change.html,sha256=
|
104
|
+
incident/rpc.py,sha256=YkGXzE0AbrqRXlK9jZjE2VypT8mhcbVc49Yndr_c4BQ,5209
|
105
|
+
incident/templates/email/incident_change.html,sha256=O_5ocWTsnqmmOuQhAtXEiE4rWecnZnJjoKU4MwV6ILo,14178
|
103
106
|
incident/templates/email/incident_new.html,sha256=IPX3CqIrvdrZSn13_jlR6sEb0If8ftvUrUpkzC5G2Gc,15173
|
104
|
-
incident/templates/email/incident_plain.html,sha256=
|
105
|
-
incident/tq.py,sha256=
|
107
|
+
incident/templates/email/incident_plain.html,sha256=iTjdej6K9SO9Or5byX-0kc7c_BdSZWVgA301T03IyDk,14343
|
108
|
+
incident/tq.py,sha256=LYeOpHQ3sVEKtotZvbzscjB1Ror6HJtIceqate--Ibg,3820
|
106
109
|
location/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
107
110
|
location/admin.py,sha256=6S97Rlgjkk0jM15sbT1OJRPZbgvKn2rn7duCSazOXq4,297
|
108
111
|
location/geolocate.py,sha256=UgV129vmSxnqYFBYJD2RQVOcC1-lJJ1zUaxDqOJRbG4,1694
|
@@ -347,7 +350,7 @@ pushit/utils.py,sha256=IeTCGa-164nmB1jIsK1lu1O1QzUhS3BKfuXHGjCW-ck,2121
|
|
347
350
|
rest/.gitignore,sha256=TbEvWRMnAiajCTOdhiNrd9eeCAaIjRp9PRjE_VkMM5g,118
|
348
351
|
rest/README.md,sha256=V3ETc-cJu8PZIbKr9xSe_pA4JEUpC8Dhw4bQeVCDJPw,5460
|
349
352
|
rest/RemoteEvents.py,sha256=nL46U7AuxIrlw2JunphR1tsXyqi-ep_gD9CYGpYbNgE,72
|
350
|
-
rest/__init__.py,sha256=
|
353
|
+
rest/__init__.py,sha256=lB3bhQFmMA43cbx4GDWsoIIKZiruByPaff8EG57nMVM,121
|
351
354
|
rest/arc4.py,sha256=y644IbF1ec--e4cUJ3KEYsewTCITK0gmlwa5mJruFC0,1967
|
352
355
|
rest/cache.py,sha256=1Qg0rkaCJCaVP0-l5hZg2CIblTdeBSlj_0fP6vlKUpU,83
|
353
356
|
rest/crypto/__init__.py,sha256=Tl0U11rgj1eBYqd6OXJ2_XSdNLumW_JkBZnaJqI6Ldw,72
|
@@ -478,7 +481,7 @@ ws4redis/servers/uwsgi.py,sha256=VyhoCI1DnVFqBiJYHoxqn5Idlf6uJPHvfBKgkjs34mo,172
|
|
478
481
|
ws4redis/settings.py,sha256=K0yBiLUuY81iDM4Yr-k8hbvjn5VVHu5zQhmMK8Dtz0s,1536
|
479
482
|
ws4redis/utf8validator.py,sha256=S0OlfjeGRP75aO6CzZsF4oTjRQAgR17OWE9rgZdMBZA,5122
|
480
483
|
ws4redis/websocket.py,sha256=R0TUyPsoVRD7Y_oU7w2I6NL4fPwiz5Vl94-fUkZgLHA,14848
|
481
|
-
django_restit-4.1.
|
482
|
-
django_restit-4.1.
|
483
|
-
django_restit-4.1.
|
484
|
-
django_restit-4.1.
|
484
|
+
django_restit-4.1.62.dist-info/LICENSE.md,sha256=VHN4hhEeVOoFjtG-5fVv4jesA4SWi0Z-KgOzzN6a1ps,1068
|
485
|
+
django_restit-4.1.62.dist-info/METADATA,sha256=mdO3BNZQMo_z4xhhJdcVrlAaRCMaZ65wMh0uFwAEOv4,7573
|
486
|
+
django_restit-4.1.62.dist-info/WHEEL,sha256=Zb28QaM1gQi8f4VCBhsUklF61CTlNYfs9YAZn-TOGFk,88
|
487
|
+
django_restit-4.1.62.dist-info/RECORD,,
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# Generated by Django 4.1.4 on 2023-11-20 03:38
|
2
|
+
|
3
|
+
from django.db import migrations, models
|
4
|
+
|
5
|
+
|
6
|
+
class Migration(migrations.Migration):
|
7
|
+
|
8
|
+
dependencies = [
|
9
|
+
('incident', '0009_incident_reporter_ip'),
|
10
|
+
]
|
11
|
+
|
12
|
+
operations = [
|
13
|
+
migrations.AddField(
|
14
|
+
model_name='incident',
|
15
|
+
name='category',
|
16
|
+
field=models.CharField(db_index=True, default=None, max_length=124, null=True),
|
17
|
+
),
|
18
|
+
migrations.AddField(
|
19
|
+
model_name='incident',
|
20
|
+
name='component_id',
|
21
|
+
field=models.IntegerField(blank=True, db_index=True, default=None, null=True),
|
22
|
+
),
|
23
|
+
]
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# Generated by Django 4.1.4 on 2023-11-20 03:51
|
2
|
+
|
3
|
+
from django.db import migrations, models
|
4
|
+
import django.db.models.deletion
|
5
|
+
import rest.models.base
|
6
|
+
import rest.models.metadata
|
7
|
+
|
8
|
+
|
9
|
+
class Migration(migrations.Migration):
|
10
|
+
|
11
|
+
dependencies = [
|
12
|
+
('account', '0016_authsession_buid'),
|
13
|
+
('incident', '0010_incident_category_incident_component_id'),
|
14
|
+
]
|
15
|
+
|
16
|
+
operations = [
|
17
|
+
migrations.CreateModel(
|
18
|
+
name='Ticket',
|
19
|
+
fields=[
|
20
|
+
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
21
|
+
('created', models.DateTimeField(auto_now_add=True)),
|
22
|
+
('modified', models.DateTimeField(auto_now=True)),
|
23
|
+
('category', models.CharField(db_index=True, max_length=200)),
|
24
|
+
('priority', models.IntegerField(db_index=True, default=10)),
|
25
|
+
('title', models.CharField(max_length=200)),
|
26
|
+
('description', models.TextField()),
|
27
|
+
('status', models.CharField(db_index=True, default=None, max_length=32, null=True)),
|
28
|
+
('state', models.IntegerField(default=0)),
|
29
|
+
('component', models.CharField(db_index=True, default=None, max_length=200, null=True)),
|
30
|
+
('component_id', models.IntegerField(blank=True, db_index=True, default=None, null=True)),
|
31
|
+
('assigned_to', models.ForeignKey(default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='tickets', to='account.member')),
|
32
|
+
('created_by', models.ForeignKey(default=None, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='+', to='account.member')),
|
33
|
+
('group', models.ForeignKey(default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='tickets', to='account.group')),
|
34
|
+
('incident', models.ForeignKey(default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='tickets', to='incident.incident')),
|
35
|
+
],
|
36
|
+
bases=(models.Model, rest.models.base.RestModel, rest.models.metadata.MetaDataModel),
|
37
|
+
),
|
38
|
+
]
|
incident/models/__init__.py
CHANGED
incident/models/event.py
CHANGED
@@ -15,7 +15,13 @@ from .rules import Rule
|
|
15
15
|
INCIDENT_METRICS = settings.get("INCIDENT_METRICS", False)
|
16
16
|
INCIDENT_EVENT_METRICS = settings.get("INCIDENT_EVENT_METRICS", False)
|
17
17
|
EVENT_TO_INCIDENT_LEVEL = settings.get("EVENT_TO_INCIDENT_LEVEL", 4)
|
18
|
-
|
18
|
+
EVENT_DETAIL_TEMPLATES = settings.get("EVENT_DETAIL_TEMPLATES", None)
|
19
|
+
EVENT_META_KEYWORDS = settings.get("EVENT_META_KEYWORDS", [
|
20
|
+
"path", "ip", "reporter_ip", "code",
|
21
|
+
"reason", "buid", "merchant", "tid",
|
22
|
+
"group", "http_user_agent", "user_agent",
|
23
|
+
"app_url", "isp", "city", "state", "country"
|
24
|
+
])
|
19
25
|
|
20
26
|
logger = log.getLogger("incident", filename="incident.log")
|
21
27
|
|
@@ -80,6 +86,23 @@ class Event(JSONMetaData, rm.RestModel):
|
|
80
86
|
return rule
|
81
87
|
return None
|
82
88
|
|
89
|
+
@property
|
90
|
+
def details_by_category(self):
|
91
|
+
# returns detailed text based on the category settings
|
92
|
+
# if EVENT_DETAIL_TEMPLATES is None or self.category not in EVENT_DETAIL_TEMPLATES:
|
93
|
+
# return self.details
|
94
|
+
output = []
|
95
|
+
if self.component:
|
96
|
+
output.append(f"{self.component}({self.component_id})")
|
97
|
+
for key in EVENT_META_KEYWORDS:
|
98
|
+
if self.metadata.get(key, None) is not None:
|
99
|
+
output.append(f"{key}: {self.metadata[key]}")
|
100
|
+
if self.details:
|
101
|
+
output.append(self.details)
|
102
|
+
output.append("")
|
103
|
+
output.append("")
|
104
|
+
return "\n".join(output)
|
105
|
+
|
83
106
|
def lookupIP(self, ip):
|
84
107
|
GeoIP = rm.RestModel.getModel("location", "GeoIP")
|
85
108
|
gip = GeoIP.lookup(ip)
|
@@ -138,7 +161,10 @@ class Event(JSONMetaData, rm.RestModel):
|
|
138
161
|
incident = Incident(
|
139
162
|
rule=hit_rule, priority=priority,
|
140
163
|
reporter_ip=self.reporter_ip,
|
141
|
-
|
164
|
+
category=self.category,
|
165
|
+
component=self.component,
|
166
|
+
component_id=self.component_id,
|
167
|
+
hostname=self.hostname)
|
142
168
|
if hit_rule is not None:
|
143
169
|
incident.group = hit_rule.group
|
144
170
|
# TODO possibly make this smarter?
|
incident/models/incident.py
CHANGED
@@ -52,7 +52,12 @@ class Incident(models.Model, rm.RestModel, rm.MetaDataModel):
|
|
52
52
|
modified = models.DateTimeField(auto_now=True)
|
53
53
|
|
54
54
|
description = models.CharField(max_length=200)
|
55
|
+
|
56
|
+
category = models.CharField(max_length=124, null=True, default=None, db_index=True)
|
57
|
+
|
55
58
|
component = models.CharField(max_length=200, null=True, default=None, db_index=True)
|
59
|
+
component_id = models.IntegerField(null=True, blank=True, default=None, db_index=True)
|
60
|
+
|
56
61
|
hostname = models.CharField(max_length=200, null=True, default=None, db_index=True)
|
57
62
|
reporter_ip = models.CharField(max_length=16, blank=True, null=True, default=None, db_index=True)
|
58
63
|
|
@@ -68,7 +73,15 @@ class Incident(models.Model, rm.RestModel, rm.MetaDataModel):
|
|
68
73
|
@property
|
69
74
|
def first_event(self):
|
70
75
|
return self.events.first()
|
71
|
-
|
76
|
+
|
77
|
+
def shouldTriggerAction(self):
|
78
|
+
count = self.events.all().count()
|
79
|
+
aa = self.rule.action_after
|
80
|
+
if aa>= 0:
|
81
|
+
return aa == count-1
|
82
|
+
aa = abs(self.rule.action_after)
|
83
|
+
return (count % aa) == 0
|
84
|
+
|
72
85
|
def triggerAction(self, force=False):
|
73
86
|
if self.rule is None:
|
74
87
|
if self.action_sent is None:
|
@@ -82,7 +95,7 @@ class Incident(models.Model, rm.RestModel, rm.MetaDataModel):
|
|
82
95
|
# return
|
83
96
|
# only do query if not 0
|
84
97
|
logger.info("triggerAction", self.rule.action)
|
85
|
-
if force or self.
|
98
|
+
if force or self.shouldTriggerAction():
|
86
99
|
logger.info(f"triggering incident action: {self.rule.action}")
|
87
100
|
self.triggerAsyncNotify()
|
88
101
|
if self.rule.action is None or self.rule.action == "notify":
|
@@ -96,9 +109,12 @@ class Incident(models.Model, rm.RestModel, rm.MetaDataModel):
|
|
96
109
|
|
97
110
|
def triggerAsyncNotify(self):
|
98
111
|
msg = dict(
|
112
|
+
pk=self.pk,
|
99
113
|
created=time.mktime(self.created.timetuple()),
|
100
114
|
description=self.description,
|
115
|
+
category=self.category,
|
101
116
|
component=self.component,
|
117
|
+
component_id=self.component_id,
|
102
118
|
hostname=self.hostname)
|
103
119
|
if self.rule is not None:
|
104
120
|
msg["rule"] = self.rule.name
|
@@ -148,7 +164,7 @@ class Incident(models.Model, rm.RestModel, rm.MetaDataModel):
|
|
148
164
|
# logger.info("notifyWith", perm)
|
149
165
|
Member.notifyWith(
|
150
166
|
perm,
|
151
|
-
subject=F"Incident #{self.pk} {self.component}@{self.hostname}",
|
167
|
+
subject=F"New Incident #{self.pk} {self.component}@{self.hostname}",
|
152
168
|
template=settings.get("INCIDENT_TEMPLATE", "email/incident_plain.html"),
|
153
169
|
context=dict(incident=self, portal_url=settings.INCIDENT_PORTAL_URL),
|
154
170
|
email_only=True, from_email=INCIDENT_EMAIL_FROM)
|
@@ -176,7 +192,8 @@ class Incident(models.Model, rm.RestModel, rm.MetaDataModel):
|
|
176
192
|
if request != None and "DATA" in request and "note" in request.DATA:
|
177
193
|
self.logHistory(kind="note", note=request.DATA.get("note"), request=request)
|
178
194
|
|
179
|
-
def logHistory(self, kind="history", note=None, media=None,
|
195
|
+
def logHistory(self, kind="history", note=None, media=None,
|
196
|
+
request=None, member=None, notify=True):
|
180
197
|
if request is None:
|
181
198
|
request = self.getActiveRequest()
|
182
199
|
if member is None and request is not None and hasattr(request, "member"):
|
@@ -186,7 +203,7 @@ class Incident(models.Model, rm.RestModel, rm.MetaDataModel):
|
|
186
203
|
for k, v in self._changed__.items():
|
187
204
|
nv = self.getFieldValue(k)
|
188
205
|
notes.append(f"{k} changed from {v} to {nv}")
|
189
|
-
note = "\n".join(notes)
|
206
|
+
note = "\n<br>".join(notes)
|
190
207
|
|
191
208
|
h = IncidentHistory(
|
192
209
|
parent=self,
|
@@ -203,57 +220,71 @@ class Incident(models.Model, rm.RestModel, rm.MetaDataModel):
|
|
203
220
|
if media is not None:
|
204
221
|
h.saveMediaFile(media, "media", media.name)
|
205
222
|
h.save()
|
206
|
-
if h.state != INCIDENT_STATE_IGNORE:
|
223
|
+
if notify and h.state != INCIDENT_STATE_IGNORE:
|
207
224
|
self.notifyWatchers(
|
208
225
|
subject=F"Updated Incident #{self.id}",
|
209
226
|
history=h)
|
210
227
|
|
211
228
|
def notifyWatchers(self, subject, history=None):
|
229
|
+
action = None
|
230
|
+
perm = "notify.incident_alerts"
|
231
|
+
if self.rule is not None and (self.rule.action.startswith("email:") or self.rule.action.startswith("notify:")):
|
232
|
+
action, perm = self.rule.action.split(":")
|
233
|
+
context = dict(
|
234
|
+
incident=self,
|
235
|
+
portal_url=settings.INCIDENT_PORTAL_URL,
|
236
|
+
history=history)
|
237
|
+
template = "email/incident_plain.html"
|
238
|
+
|
212
239
|
# this should notify all users in our incident group of the change
|
213
240
|
if self.group is not None:
|
214
241
|
# all member of the group are notified because it is an incident group
|
215
242
|
self.group.notifyMembers(
|
216
243
|
subject=subject,
|
217
|
-
template=
|
218
|
-
context=
|
219
|
-
perms=[
|
220
|
-
email_only=True,
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
244
|
+
template=template,
|
245
|
+
context=context,
|
246
|
+
perms=[perm],
|
247
|
+
email_only=True,
|
248
|
+
from_email=INCIDENT_EMAIL_FROM)
|
249
|
+
elif history.by is None:
|
250
|
+
# notify everyone with the perm
|
251
|
+
Member.notifyWith(
|
252
|
+
perm,
|
253
|
+
subject,
|
254
|
+
template=template,
|
255
|
+
context=context,
|
256
|
+
email_only=True,
|
257
|
+
from_email=INCIDENT_EMAIL_FROM)
|
258
|
+
else:
|
259
|
+
# notitfy everyone but the sender
|
226
260
|
if history.by is None:
|
227
|
-
Member.notifyWith(
|
228
|
-
perm, subject,
|
229
|
-
message=history.note,
|
230
|
-
from_email=INCIDENT_EMAIL_FROM)
|
231
|
-
else:
|
232
261
|
members = Member.GetWithPermission(perm).exclude(pk=history.by.pk)
|
233
|
-
if members.count()
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
262
|
+
if members.count() == 0:
|
263
|
+
return
|
264
|
+
NotificationRecord = Incident.getModel("account", "NotificationRecord")
|
265
|
+
NotificationRecord.notify(
|
266
|
+
members,
|
267
|
+
subject,
|
268
|
+
template=template,
|
269
|
+
context=context,
|
270
|
+
email_only=True,
|
271
|
+
from_email=INCIDENT_EMAIL_FROM)
|
239
272
|
|
240
273
|
@classmethod
|
241
274
|
def getBundled(cls, rule, event):
|
242
275
|
# calculate our bundle start time
|
243
276
|
when = datetime.now() - timedelta(minutes=rule.bundle)
|
244
277
|
q = objict(rule=rule, created__gte=when)
|
245
|
-
if rule.bundle_by
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
278
|
+
if rule.bundle_by in [2, 3, 5]:
|
279
|
+
if event.component_id:
|
280
|
+
q.component = event.component
|
281
|
+
q.component_id = event.component_id
|
282
|
+
if rule.bundle_by in [1, 3, 7]:
|
250
283
|
q.hostname = event.hostname
|
251
|
-
|
252
|
-
elif rule.bundle_by == 4:
|
253
|
-
q.reporter_ip = event.reporter_ip
|
254
|
-
elif rule.bundle_by == 5:
|
284
|
+
elif rule.bundle_by in [4, 5, 8]:
|
255
285
|
q.reporter_ip = event.reporter_ip
|
256
|
-
|
286
|
+
elif rule.bundle_by in [6, 7, 8]:
|
287
|
+
q.category = event.category
|
257
288
|
return Incident.objects.filter(**q).last()
|
258
289
|
|
259
290
|
@classmethod
|
@@ -0,0 +1,65 @@
|
|
1
|
+
from django.db import models
|
2
|
+
from django.conf import settings
|
3
|
+
|
4
|
+
from rest import models as rm
|
5
|
+
from rest import helpers as rh
|
6
|
+
|
7
|
+
|
8
|
+
class Ticket(models.Model, rm.RestModel, rm.MetaDataModel):
|
9
|
+
class RestMeta:
|
10
|
+
SEARCH_FIELDS = ["title", "description"]
|
11
|
+
CAN_DELETE = True
|
12
|
+
VIEW_PERMS = ["view_tickets"]
|
13
|
+
GRAPHS = {
|
14
|
+
"default": {
|
15
|
+
"extra": ["metadata"],
|
16
|
+
"graphs": {
|
17
|
+
"group": "basic",
|
18
|
+
"created_by": "basic",
|
19
|
+
"assigned_to": "basic",
|
20
|
+
"incident": "basic"
|
21
|
+
},
|
22
|
+
},
|
23
|
+
"detailed": {
|
24
|
+
"graphs": {
|
25
|
+
"group": "basic",
|
26
|
+
"created_by": "basic",
|
27
|
+
"assigned_to": "basic",
|
28
|
+
"incident": "basic",
|
29
|
+
"generic__component": "basic"
|
30
|
+
},
|
31
|
+
},
|
32
|
+
}
|
33
|
+
|
34
|
+
created = models.DateTimeField(auto_now_add=True)
|
35
|
+
modified = models.DateTimeField(auto_now=True)
|
36
|
+
|
37
|
+
group = models.ForeignKey(
|
38
|
+
"account.Group", on_delete=models.SET_NULL,
|
39
|
+
related_name="tickets",
|
40
|
+
null=True, default=None)
|
41
|
+
assigned_to = models.ForeignKey(
|
42
|
+
"account.Member", on_delete=models.SET_NULL,
|
43
|
+
related_name="tickets",
|
44
|
+
null=True, default=None)
|
45
|
+
created_by = models.ForeignKey(
|
46
|
+
"account.Member", on_delete=models.CASCADE,
|
47
|
+
related_name="+",
|
48
|
+
null=True, default=None)
|
49
|
+
|
50
|
+
# if category is null then this will run on all events?
|
51
|
+
category = models.CharField(max_length=200, db_index=True)
|
52
|
+
priority = models.IntegerField(default=10, db_index=True) # 1-10, 1 being the highest
|
53
|
+
|
54
|
+
title = models.CharField(max_length=200)
|
55
|
+
description = models.TextField()
|
56
|
+
|
57
|
+
status = models.CharField(max_length=32, default=None, null=True, db_index=True)
|
58
|
+
state = models.IntegerField(default=0) # how many incidents before firing action
|
59
|
+
|
60
|
+
incident = models.ForeignKey(
|
61
|
+
"incident.Incident", null=True, default=None,
|
62
|
+
related_name="tickets", on_delete=models.SET_NULL)
|
63
|
+
|
64
|
+
component = models.CharField(max_length=200, null=True, default=None, db_index=True)
|
65
|
+
component_id = models.IntegerField(null=True, blank=True, default=None, db_index=True)
|
incident/rpc.py
CHANGED
@@ -158,3 +158,9 @@ def rest_firewall_block(request):
|
|
158
158
|
return rv.restPermissionDenied(request)
|
159
159
|
Task.Publish("incident", f"firewall_{action}", dict(ip=ip), channel="tq_broadcast")
|
160
160
|
return rv.restStatus(request, True)
|
161
|
+
|
162
|
+
|
163
|
+
@rd.url('ticket')
|
164
|
+
@rd.url('ticket/<int:pk>')
|
165
|
+
def rest_on_ticket(request, pk=None):
|
166
|
+
return am.Ticket.on_rest_request(request, pk)
|