django-restit 4.1.61__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 CHANGED
@@ -3,6 +3,7 @@ from rest import views as rv
3
3
  from account.models import Group, Membership, Member, GroupFeed, MemberFeed
4
4
  from taskqueue import models as tq
5
5
 
6
+
6
7
  @rd.url(r'^group$')
7
8
  @rd.url(r'^group/$') # required for legacy support
8
9
  @rd.url(r'^group/(?P<pk>\d+)$')
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: django-restit
3
- Version: 4.1.61
3
+ Version: 4.1.62
4
4
  Summary: A Rest Framework for DJANGO
5
5
  License: MIT
6
6
  Author: Ian Starnes
@@ -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=IHg0o4r0XcwsT8Ur5kTdjHc-91BNqk6atEeOpSd7cAc,3447
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,16 +89,19 @@ 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=adTSOSVrYJgHD4hZNJJjFj_M1QZbpwhZZQiIzanUKA8,167
94
- incident/models/event.py,sha256=OPrNMGxc19daM4tgAzZHK1FLcwWYUXHrXcENz8vb19U,6666
95
- incident/models/incident.py,sha256=O3uJSFqVWS0jVFDkYluw1OvmDqJhZ2_1Tl8tPTHtlKk,12652
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=kNUVrZDm_BoZQq3bVoOZJwMJX1nQJYLjkAy7EvPPLd4,5074
104
+ incident/rpc.py,sha256=YkGXzE0AbrqRXlK9jZjE2VypT8mhcbVc49Yndr_c4BQ,5209
102
105
  incident/templates/email/incident_change.html,sha256=O_5ocWTsnqmmOuQhAtXEiE4rWecnZnJjoKU4MwV6ILo,14178
103
106
  incident/templates/email/incident_new.html,sha256=IPX3CqIrvdrZSn13_jlR6sEb0If8ftvUrUpkzC5G2Gc,15173
104
107
  incident/templates/email/incident_plain.html,sha256=iTjdej6K9SO9Or5byX-0kc7c_BdSZWVgA301T03IyDk,14343
@@ -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=falbHeBLZY_QULrYiHkhBxH_L_JpUbZf34Jk8pD9Sss,121
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.61.dist-info/LICENSE.md,sha256=VHN4hhEeVOoFjtG-5fVv4jesA4SWi0Z-KgOzzN6a1ps,1068
482
- django_restit-4.1.61.dist-info/METADATA,sha256=7J6XsNZANcimd41J98qQ9AJ3AFtveMmQeljDE8ez0wc,7573
483
- django_restit-4.1.61.dist-info/WHEEL,sha256=Zb28QaM1gQi8f4VCBhsUklF61CTlNYfs9YAZn-TOGFk,88
484
- django_restit-4.1.61.dist-info/RECORD,,
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
+ ]
@@ -2,3 +2,4 @@ from .rules import * # noqa: F401, F403
2
2
  from .incident import * # noqa: F401, F403
3
3
  from .event import * # noqa: F401, F403
4
4
  from .ossec import * # noqa: F401, F403
5
+ from .ticket import * # noqa: F401, F403
incident/models/event.py CHANGED
@@ -161,7 +161,10 @@ class Event(JSONMetaData, rm.RestModel):
161
161
  incident = Incident(
162
162
  rule=hit_rule, priority=priority,
163
163
  reporter_ip=self.reporter_ip,
164
- component=self.category, hostname=self.hostname)
164
+ category=self.category,
165
+ component=self.component,
166
+ component_id=self.component_id,
167
+ hostname=self.hostname)
165
168
  if hit_rule is not None:
166
169
  incident.group = hit_rule.group
167
170
  # TODO possibly make this smarter?
@@ -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.rule.action_after == 0 or self.rule.action_after < self.events.all().count():
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":
@@ -99,7 +112,9 @@ class Incident(models.Model, rm.RestModel, rm.MetaDataModel):
99
112
  pk=self.pk,
100
113
  created=time.mktime(self.created.timetuple()),
101
114
  description=self.description,
115
+ category=self.category,
102
116
  component=self.component,
117
+ component_id=self.component_id,
103
118
  hostname=self.hostname)
104
119
  if self.rule is not None:
105
120
  msg["rule"] = self.rule.name
@@ -188,7 +203,7 @@ class Incident(models.Model, rm.RestModel, rm.MetaDataModel):
188
203
  for k, v in self._changed__.items():
189
204
  nv = self.getFieldValue(k)
190
205
  notes.append(f"{k} changed from {v} to {nv}")
191
- note = "\n".join(notes)
206
+ note = "\n<br>".join(notes)
192
207
 
193
208
  h = IncidentHistory(
194
209
  parent=self,
@@ -260,18 +275,16 @@ class Incident(models.Model, rm.RestModel, rm.MetaDataModel):
260
275
  # calculate our bundle start time
261
276
  when = datetime.now() - timedelta(minutes=rule.bundle)
262
277
  q = objict(rule=rule, created__gte=when)
263
- if rule.bundle_by == 1:
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]:
264
283
  q.hostname = event.hostname
265
- elif rule.bundle_by == 2:
266
- q.component = event.category
267
- elif rule.bundle_by == 3:
268
- q.hostname = event.hostname
269
- q.component = event.category
270
- elif rule.bundle_by == 4:
271
- q.reporter_ip = event.reporter_ip
272
- elif rule.bundle_by == 5:
284
+ elif rule.bundle_by in [4, 5, 8]:
273
285
  q.reporter_ip = event.reporter_ip
274
- q.component = event.category
286
+ elif rule.bundle_by in [6, 7, 8]:
287
+ q.category = event.category
275
288
  return Incident.objects.filter(**q).last()
276
289
 
277
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)
rest/__init__.py CHANGED
@@ -1,4 +1,4 @@
1
1
  from .uberdict import UberDict # noqa: F401
2
2
  from .settings_helper import settings # noqa: F401
3
3
 
4
- __version__ = "4.1.61"
4
+ __version__ = "4.1.62"