django-nativemojo 0.1.10__py3-none-any.whl → 0.1.15__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.
Files changed (120) hide show
  1. django_nativemojo-0.1.15.dist-info/METADATA +136 -0
  2. {django_nativemojo-0.1.10.dist-info → django_nativemojo-0.1.15.dist-info}/RECORD +105 -65
  3. mojo/__init__.py +1 -1
  4. mojo/apps/account/management/__init__.py +5 -0
  5. mojo/apps/account/management/commands/__init__.py +6 -0
  6. mojo/apps/account/management/commands/serializer_admin.py +531 -0
  7. mojo/apps/account/migrations/0004_user_avatar.py +20 -0
  8. mojo/apps/account/migrations/0005_group_last_activity.py +18 -0
  9. mojo/apps/account/models/group.py +25 -7
  10. mojo/apps/account/models/member.py +15 -4
  11. mojo/apps/account/models/user.py +197 -20
  12. mojo/apps/account/rest/group.py +1 -0
  13. mojo/apps/account/rest/user.py +6 -2
  14. mojo/apps/aws/rest/__init__.py +1 -0
  15. mojo/apps/aws/rest/s3.py +64 -0
  16. mojo/apps/fileman/README.md +8 -8
  17. mojo/apps/fileman/backends/base.py +76 -70
  18. mojo/apps/fileman/backends/filesystem.py +86 -86
  19. mojo/apps/fileman/backends/s3.py +200 -108
  20. mojo/apps/fileman/migrations/0001_initial.py +106 -0
  21. mojo/apps/fileman/migrations/0002_filemanager_parent_alter_filemanager_max_file_size.py +24 -0
  22. mojo/apps/fileman/migrations/0003_remove_file_fileman_fil_upload__c4bc35_idx_and_more.py +25 -0
  23. mojo/apps/fileman/migrations/0004_remove_file_original_filename_and_more.py +39 -0
  24. mojo/apps/fileman/migrations/0005_alter_file_upload_token.py +18 -0
  25. mojo/apps/fileman/migrations/0006_file_download_url_filemanager_forever_urls.py +23 -0
  26. mojo/apps/fileman/migrations/0007_remove_filemanager_forever_urls_and_more.py +22 -0
  27. mojo/apps/fileman/migrations/0008_file_category.py +18 -0
  28. mojo/apps/fileman/migrations/0009_rename_file_path_file_storage_file_path.py +18 -0
  29. mojo/apps/fileman/migrations/0010_filerendition.py +33 -0
  30. mojo/apps/fileman/migrations/0011_alter_filerendition_original_file.py +19 -0
  31. mojo/apps/fileman/models/__init__.py +1 -5
  32. mojo/apps/fileman/models/file.py +204 -58
  33. mojo/apps/fileman/models/manager.py +161 -31
  34. mojo/apps/fileman/models/rendition.py +118 -0
  35. mojo/apps/fileman/renderer/__init__.py +111 -0
  36. mojo/apps/fileman/renderer/audio.py +403 -0
  37. mojo/apps/fileman/renderer/base.py +205 -0
  38. mojo/apps/fileman/renderer/document.py +404 -0
  39. mojo/apps/fileman/renderer/image.py +222 -0
  40. mojo/apps/fileman/renderer/utils.py +297 -0
  41. mojo/apps/fileman/renderer/video.py +304 -0
  42. mojo/apps/fileman/rest/__init__.py +1 -18
  43. mojo/apps/fileman/rest/upload.py +22 -32
  44. mojo/apps/fileman/signals.py +58 -0
  45. mojo/apps/fileman/tasks.py +254 -0
  46. mojo/apps/fileman/utils/__init__.py +40 -16
  47. mojo/apps/incident/migrations/0005_incidenthistory.py +39 -0
  48. mojo/apps/incident/migrations/0006_alter_incident_state.py +18 -0
  49. mojo/apps/incident/models/__init__.py +1 -0
  50. mojo/apps/incident/models/history.py +36 -0
  51. mojo/apps/incident/models/incident.py +1 -1
  52. mojo/apps/incident/reporter.py +3 -1
  53. mojo/apps/incident/rest/event.py +7 -1
  54. mojo/apps/logit/migrations/0004_alter_log_level.py +18 -0
  55. mojo/apps/logit/models/log.py +4 -1
  56. mojo/apps/metrics/utils.py +2 -2
  57. mojo/apps/notify/handlers/ses/message.py +1 -1
  58. mojo/apps/notify/providers/aws.py +2 -2
  59. mojo/apps/tasks/__init__.py +34 -1
  60. mojo/apps/tasks/manager.py +200 -45
  61. mojo/apps/tasks/rest/tasks.py +24 -10
  62. mojo/apps/tasks/runner.py +283 -18
  63. mojo/apps/tasks/task.py +99 -0
  64. mojo/apps/tasks/tq_handlers.py +118 -0
  65. mojo/decorators/auth.py +6 -1
  66. mojo/decorators/http.py +7 -2
  67. mojo/helpers/aws/__init__.py +41 -0
  68. mojo/helpers/aws/ec2.py +804 -0
  69. mojo/helpers/aws/iam.py +748 -0
  70. mojo/helpers/aws/s3.py +451 -11
  71. mojo/helpers/aws/ses.py +483 -0
  72. mojo/helpers/aws/sns.py +461 -0
  73. mojo/helpers/crypto/__pycache__/hash.cpython-310.pyc +0 -0
  74. mojo/helpers/crypto/__pycache__/sign.cpython-310.pyc +0 -0
  75. mojo/helpers/crypto/__pycache__/utils.cpython-310.pyc +0 -0
  76. mojo/helpers/dates.py +18 -0
  77. mojo/helpers/response.py +6 -2
  78. mojo/helpers/settings/__init__.py +2 -0
  79. mojo/helpers/{settings.py → settings/helper.py} +1 -37
  80. mojo/helpers/settings/parser.py +132 -0
  81. mojo/middleware/logging.py +1 -1
  82. mojo/middleware/mojo.py +5 -0
  83. mojo/models/rest.py +261 -46
  84. mojo/models/secrets.py +13 -4
  85. mojo/serializers/__init__.py +100 -0
  86. mojo/serializers/advanced/README.md +363 -0
  87. mojo/serializers/advanced/__init__.py +247 -0
  88. mojo/serializers/advanced/formats/__init__.py +28 -0
  89. mojo/serializers/advanced/formats/csv.py +416 -0
  90. mojo/serializers/advanced/formats/excel.py +516 -0
  91. mojo/serializers/advanced/formats/json.py +239 -0
  92. mojo/serializers/advanced/formats/localizers.py +509 -0
  93. mojo/serializers/advanced/formats/response.py +485 -0
  94. mojo/serializers/advanced/serializer.py +568 -0
  95. mojo/serializers/manager.py +501 -0
  96. mojo/serializers/optimized.py +618 -0
  97. mojo/serializers/settings_example.py +322 -0
  98. mojo/serializers/{models.py → simple.py} +38 -15
  99. testit/helpers.py +21 -4
  100. django_nativemojo-0.1.10.dist-info/METADATA +0 -96
  101. mojo/apps/metrics/rest/db.py +0 -0
  102. mojo/helpers/aws/setup_email.py +0 -0
  103. mojo/ws4redis/README.md +0 -174
  104. mojo/ws4redis/__init__.py +0 -2
  105. mojo/ws4redis/client.py +0 -283
  106. mojo/ws4redis/connection.py +0 -327
  107. mojo/ws4redis/exceptions.py +0 -32
  108. mojo/ws4redis/redis.py +0 -183
  109. mojo/ws4redis/servers/base.py +0 -86
  110. mojo/ws4redis/servers/django.py +0 -171
  111. mojo/ws4redis/servers/uwsgi.py +0 -63
  112. mojo/ws4redis/settings.py +0 -45
  113. mojo/ws4redis/utf8validator.py +0 -128
  114. mojo/ws4redis/websocket.py +0 -403
  115. {django_nativemojo-0.1.10.dist-info → django_nativemojo-0.1.15.dist-info}/LICENSE +0 -0
  116. {django_nativemojo-0.1.10.dist-info → django_nativemojo-0.1.15.dist-info}/NOTICE +0 -0
  117. {django_nativemojo-0.1.10.dist-info → django_nativemojo-0.1.15.dist-info}/WHEEL +0 -0
  118. /mojo/{ws4redis/servers → apps/aws}/__init__.py +0 -0
  119. /mojo/apps/{fileman/models/render.py → aws/models/__init__.py} +0 -0
  120. /mojo/apps/fileman/{rest/__init__ → migrations/__init__.py} +0 -0
mojo/ws4redis/README.md DELETED
@@ -1,174 +0,0 @@
1
- # Websocket HOWTO
2
-
3
- ## Authentication
4
-
5
- ### JWT
6
-
7
- Requires an existing JWT token that has gone through authentication process via rest
8
-
9
- ```json
10
- {
11
- "action": "auth",
12
- "kind": "jwt",
13
- "token": "..."
14
- }
15
- ```
16
-
17
-
18
-
19
- ### Model Authentication
20
-
21
- You can implement custom authentication flows via a model by using the WS4REDIS_AUTHENTICATORS in your django settings.py.
22
-
23
- ##### WS4REDIS_AUTHENTICATORS
24
-
25
- ```python
26
- WS4REDIS_AUTHENTICATORS = {
27
- "mymodel": "myapp.MyModel"
28
- }
29
- ```
30
-
31
- In your Model you will need to add the following class methods.
32
-
33
- This method is used by the async/websocket service to authenticate.
34
- If the model can authenticate the connection it should return dict with kind and pk of the model that is authenticaed.
35
-
36
-
37
-
38
- ##### authWS4RedisConnection
39
-
40
- This method will authenticate the model, or return None if authentication failed.
41
-
42
- ```python
43
- @classmethod
44
- def authWS4RedisConnection(cls, auth_data):
45
- if auth_data and auth_data.token:
46
- terminal = cls.objects.filter(token=auth_data.token).last()
47
- if terminal is not None:
48
- # we now return the terminal credentials to the framework
49
- return UberDict(
50
- kind="terminal",
51
- pk=terminal.id,
52
- uuid=terminal.tid,
53
- token=auth_data.token,
54
- only_one=True, # only allows one connection at a time
55
- instance=terminal)
56
- return None
57
- ```
58
-
59
-
60
-
61
- ##### canPublishTo
62
-
63
- Add this to your Model to validate messages from this connection to be sent to this channel.
64
-
65
- ```python
66
- @classmethod
67
- def canPublishTo(cls, credentials, msg):
68
- if credentials:
69
- return True
70
- return False
71
- ```
72
-
73
-
74
-
75
- ##### WS4REDIS_CHANNELS
76
-
77
- Map channels to models
78
-
79
- ```python
80
- WS4REDIS_CHANNELS = {
81
- "group": "account.Group",
82
- "chat": "chat.Room",
83
- }
84
- ```
85
-
86
-
87
-
88
- ##### onWS4RedisMessage
89
-
90
- Add this to your Model to allow for handling of messages sent to this channel.
91
-
92
- ```python
93
- @classmethod
94
- def onWS4RedisMessage(cls, credentials, msg):
95
- if msg.action == "status":
96
- cls.createStatusRecord(msg)
97
-
98
- ```
99
-
100
-
101
-
102
- ### URL Params
103
-
104
- You can also use params in the url of the websocket.
105
-
106
- **THIS IS NOT RECOMMENDED as the url params are not encrypted and can be easily snooped.**
107
-
108
- Include something like the follow in your django settings.py:
109
-
110
- ```python
111
- def URL_AUTHENTICATOR(ws_con):
112
- from objict import objict
113
- token = ws_con.request.GET.get("token", None)
114
- session_key = ws_con.request.GET.get("session_key", None)
115
- if token is not None:
116
- # this example assume the token is used for terminal auth
117
- # you will still need to implement the Custom Auth flows to handle this
118
- ws_con.on_auth(objict(kind="terminal", token=token))
119
- elif session_key is not None:
120
- # or alternative is a session
121
- ws_con.on_auth(objict(kind="session", token=session_key))
122
-
123
- ```
124
-
125
-
126
-
127
- ## Subscribe
128
-
129
- ```json
130
- {
131
- "action": "subscribe",
132
- "channel": "group",
133
- "pk": 3,
134
- }
135
- ```
136
-
137
- ### Security
138
-
139
- In settins WS4REDIS_CHANNELS, map your channel to a model.
140
- The model should have a classmethod for canSubscribeTo that returns a list of pk they can subscribe to.
141
-
142
-
143
- ## UnSubscribe
144
-
145
- ```json
146
- {
147
- "action": "unsubscribe",
148
- "channel": "group",
149
- "pk": 3,
150
- }
151
- ```
152
-
153
-
154
- ## Publish / Send To
155
-
156
- ```json
157
- {
158
- "action": "publish",
159
- "channel": "group",
160
- "pk": 3,
161
- "message": "..."
162
- }
163
- ```
164
-
165
- ### Security
166
-
167
- In settins WS4REDIS_CHANNELS, map your channel to a model.
168
- The model should have a classmethod for canPublishTo that returns a list of pk they can publish to.
169
-
170
-
171
- ## Custom Messages
172
-
173
- If an unknown action is sent with a channel then the framework will call onWS4RedisMessage on the channel model.
174
-
mojo/ws4redis/__init__.py DELETED
@@ -1,2 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- __version__ = '1.1.8'
mojo/ws4redis/client.py DELETED
@@ -1,283 +0,0 @@
1
- import time
2
-
3
- from objict import objict
4
-
5
- from mojo.ws4redis.redis import RedisMessage, RedisStore, getRedisClient, getPoolStatus
6
-
7
-
8
- def buildEventMessage(name=None, message=None, priority=0, model=None, model_pk=None, custom=None):
9
- msg = objict(priority=priority)
10
- if name:
11
- msg["name"] = name
12
-
13
- if message:
14
- msg["message"] = message
15
-
16
- if model:
17
- msg["component"] = objict(pk=model_pk, model=model)
18
-
19
- if custom:
20
- msg.update(custom)
21
- return msg.toJSON(as_string=True)
22
-
23
-
24
- def ping():
25
- return getRedisClient().ping()
26
-
27
-
28
- def exists(key, default=None):
29
- c = getRedisClient()
30
- return c.exists(key)
31
-
32
-
33
- def keys(keys):
34
- c = getRedisClient()
35
- return [v.decode() for v in c.keys(keys)]
36
-
37
-
38
- def get(key, default=None, field_type=None):
39
- c = getRedisClient()
40
- v = c.get(key)
41
- if v is None:
42
- return default
43
- if field_type is not None:
44
- if field_type == "json":
45
- return objict.fromJSON(v, ignore_errors=True)
46
- if field_type in [str, "str"]:
47
- v = v.decode()
48
- return field_type(v)
49
- return v
50
-
51
-
52
- def set(key, value, expire=None):
53
- c = getRedisClient()
54
- v = c.set(key, value)
55
- if expire:
56
- c.expire(key, expire)
57
- return v
58
-
59
-
60
- def incr(key, amount=1, expire=None):
61
- c = getRedisClient()
62
- v = c.incr(key, amount)
63
- if expire:
64
- c.expire(key, expire)
65
- return v
66
-
67
-
68
- def expire(key, expire):
69
- c = getRedisClient()
70
- return c.expire(key, expire)
71
-
72
-
73
- def decr(key, amount=1):
74
- c = getRedisClient()
75
- return c.decr(key, amount)
76
-
77
-
78
- def delete(key):
79
- c = getRedisClient()
80
- return c.delete(key)
81
-
82
-
83
- # SET FUNCTIONS
84
- def sadd(name, *values):
85
- # add value to set
86
- c = getRedisClient()
87
- return c.sadd(name, *values)
88
-
89
-
90
- def srem(name, *values):
91
- # remove value from set
92
- c = getRedisClient()
93
- return c.srem(name, *values)
94
-
95
-
96
- def sismember(name, value):
97
- # return items in set
98
- c = getRedisClient()
99
- return c.sismember(name, value)
100
-
101
-
102
- def scard(name):
103
- # count items in set
104
- c = getRedisClient()
105
- return c.scard(name)
106
-
107
-
108
- def smembers(name):
109
- # return items in set
110
- c = getRedisClient()
111
- return c.smembers(name)
112
-
113
-
114
- # HASH FUNCTIONS
115
- def hget(name, field, default=None):
116
- c = getRedisClient()
117
- v = c.hget(name, field)
118
- if v is None:
119
- return default
120
- return v
121
-
122
-
123
- def hgetall(name):
124
- c = getRedisClient()
125
- return c.hgetall(name)
126
-
127
-
128
- def hset(name, field, value):
129
- c = getRedisClient()
130
- return c.hset(name, field, value)
131
-
132
-
133
- def hdel(name, field):
134
- c = getRedisClient()
135
- return c.hdel(name, field)
136
-
137
-
138
- def hincrby(name, field, inc=1):
139
- c = getRedisClient()
140
- return c.hincrby(name, field, inc)
141
-
142
-
143
- def lpush(name, value, unique=False):
144
- c = getRedisClient()
145
- if isinstance(value, list):
146
- for v in value:
147
- if unique and value.encode() in c.lrange(name, 0, -1):
148
- return 0
149
- c.lpush(name, v)
150
- return len(value)
151
- if unique and value.encode() in c.lrange(name, 0, -1):
152
- return 0
153
- return c.lpush(name, value)
154
-
155
-
156
- def rpush(name, value, unique=False):
157
- c = getRedisClient()
158
- if isinstance(value, list):
159
- for v in value:
160
- if unique and value.encode() in c.lrange(name, 0, -1):
161
- return 0
162
- c.rpush(name, v)
163
- return len(value)
164
- if unique and value.encode() in c.lrange(name, 0, -1):
165
- return 0
166
- return c.rpush(name, value)
167
-
168
-
169
- def lpop(name, timeout=None):
170
- c = getRedisClient()
171
- if timeout is None:
172
- return c.lpop(name)
173
- r = c.blpop(name, timeout=timeout)
174
- if isinstance(r, tuple):
175
- return r[1].decode()
176
-
177
-
178
- def rpop(name, timeout=None):
179
- c = getRedisClient()
180
- if timeout is None:
181
- return c.rpop(name)
182
- r = c.brpop(name, timeout=timeout)
183
- if isinstance(r, tuple):
184
- return r[1].decode()
185
-
186
-
187
- def lrem(name, value, occurences=1):
188
- c = getRedisClient()
189
- return c.lrem(name, occurences, value.encode())
190
-
191
-
192
- def vpop(name, value, timeout=None):
193
- c = getRedisClient()
194
- start = time.time()
195
- while c.lrem(name, 1, value) == 0:
196
- if timeout is None:
197
- return 0
198
- time.sleep(1.0)
199
- elapsed = time.time() - start
200
- if elapsed > timeout:
201
- return 0
202
- return 1
203
-
204
-
205
- def lrange(name, start, end):
206
- c = getRedisClient()
207
- return [v.decode() for v in c.lrange(name, start, end)]
208
-
209
-
210
- def sendToUser(user, name, message=None, priority=0, model=None, model_pk=None, custom=None):
211
- return sendMessageToUsers([user], buildEventMessage(name, message, priority, model, model_pk, custom))
212
-
213
-
214
- def sendToUsers(users, name, message=None, priority=0, model=None, model_pk=None, custom=None):
215
- return sendMessageToUsers(users, buildEventMessage(name, message, priority, model, model_pk, custom))
216
-
217
-
218
- def sendMessageToUsers(users, msg):
219
- return RedisStore().publish(RedisMessage(msg), channel="user", pk=[u.username for u in users])
220
-
221
-
222
- def sendToGroup(group, name, message=None, priority=0, model=None, model_pk=None, custom=None):
223
- return sendMessageToModels("group", [group], buildEventMessage(name, message, priority, model, model_pk, custom))
224
-
225
-
226
- def sendToGroups(groups, name, message=None, priority=0, model=None, model_pk=None, custom=None):
227
- return sendMessageToModels("group", groups, buildEventMessage(name, message, priority, model, model_pk, custom))
228
-
229
-
230
- def sendToModels(channel, models, name, message=None, priority=0, model=None, model_pk=None, custom=None):
231
- return sendMessageToModels(channel, models, buildEventMessage(name, message, priority, model, model_pk, custom))
232
-
233
-
234
- def sendMessageToModels(channel, models, msg):
235
- return RedisStore().publish(RedisMessage(msg), channel=channel, pk=[g.pk for g in models])
236
-
237
-
238
- def sendMessageToPK(channel, pk, msg):
239
- return RedisStore().publish(RedisMessage(msg), channel=channel, pk=pk)
240
-
241
-
242
- def broadcast(name, message=None, priority=0, model=None, model_pk=None, custom=None):
243
- return broadcastMessage(buildEventMessage(name, message, priority, model, model_pk, custom))
244
-
245
-
246
- def broadcastMessage(msg):
247
- return RedisStore().publish(RedisMessage(msg), channel="broadcast")
248
-
249
-
250
- def publish(key, data, c=None):
251
- if c is None:
252
- c = getRedisClient()
253
- if isinstance(data, dict):
254
- if not isinstance(data, objict):
255
- data = objict(data)
256
- data = data.toJSON(as_string=True)
257
- return c.publish(key, data)
258
-
259
-
260
- def subscribe(channel):
261
- c = getRedisClient()
262
- pubsub = c.pubsub()
263
- pubsub.subscribe(channel)
264
- return pubsub
265
-
266
-
267
- def waitForMessage(pubsub, msg_filter, timeout=55):
268
- timeout_at = time.time() + timeout
269
- while time.time() < timeout_at:
270
- message = pubsub.get_message()
271
- if message is not None:
272
- if message.get("type") == "message":
273
- msg = objict.fromJSON(message.get("data"))
274
- if msg_filter(msg):
275
- pubsub.unsubscribe()
276
- return msg
277
- time.sleep(1.0)
278
- pubsub.unsubscribe()
279
- return None
280
-
281
-
282
- def isOnline(name, pk):
283
- return sismember(f"{name}:online", pk)