velocity-python 0.0.112__py3-none-any.whl → 0.0.115__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.

Potentially problematic release.


This version of velocity-python might be problematic. Click here for more details.

velocity/__init__.py CHANGED
@@ -1,4 +1,4 @@
1
- __version__ = version = "0.0.112"
1
+ __version__ = version = "0.0.115"
2
2
 
3
3
  from . import aws
4
4
  from . import db
@@ -1,4 +1,10 @@
1
+ import os
2
+ import boto3
3
+ import uuid
1
4
  import support.app
5
+ from velocity.misc.format import to_json
6
+ from velocity.misc.merge import deep_merge
7
+ from datetime import datetime
2
8
 
3
9
  engine = support.app.postgres()
4
10
 
@@ -68,3 +74,138 @@ class Context:
68
74
  print(f"{function}: {message}")
69
75
  else:
70
76
  print(f"{message}")
77
+
78
+ def updateJob(self, tx, data=None):
79
+ """Update job status and message in aws_job_activity table."""
80
+ if not data:
81
+ return
82
+ if self.postdata("job_id"):
83
+ # Sanitize data before storing in database
84
+ sanitized_data = self._sanitize_job_data(data)
85
+ tx.table("aws_job_activity").update(sanitized_data, {"job_id": self.postdata("job_id")})
86
+ tx.commit()
87
+
88
+ def _sanitize_job_data(self, data):
89
+ """Sanitize sensitive data before storing in aws_job_activity table."""
90
+ if not isinstance(data, dict):
91
+ return data
92
+
93
+ sanitized = {}
94
+
95
+ # List of sensitive field patterns to sanitize
96
+ sensitive_patterns = [
97
+ 'password', 'token', 'secret', 'key', 'credential', 'auth',
98
+ 'cognito_user', 'session', 'cookie', 'authorization'
99
+ ]
100
+
101
+ for key, value in data.items():
102
+ # Check if key contains sensitive patterns
103
+ if any(pattern in key.lower() for pattern in sensitive_patterns):
104
+ sanitized[key] = "[REDACTED]" if value else value
105
+ elif key == 'error' and value:
106
+ # Sanitize error messages - keep first 500 chars and remove potential sensitive info
107
+ error_str = str(value)[:500]
108
+ for pattern in sensitive_patterns:
109
+ if pattern in error_str.lower():
110
+ # Replace potential sensitive values with placeholder
111
+ import re
112
+ # Remove patterns like password=value, token=value, etc.
113
+ error_str = re.sub(
114
+ rf'{pattern}[=:]\s*[^\s,\]}}]+',
115
+ f'{pattern}=[REDACTED]',
116
+ error_str,
117
+ flags=re.IGNORECASE
118
+ )
119
+ sanitized[key] = error_str
120
+ elif key == 'traceback' and value:
121
+ # Sanitize traceback - keep structure but remove sensitive values
122
+ tb_str = str(value)
123
+ for pattern in sensitive_patterns:
124
+ if pattern in tb_str.lower():
125
+ import re
126
+ # Remove patterns like password=value, token=value, etc.
127
+ tb_str = re.sub(
128
+ rf'{pattern}[=:]\s*[^\s,\]}}]+',
129
+ f'{pattern}=[REDACTED]',
130
+ tb_str,
131
+ flags=re.IGNORECASE
132
+ )
133
+ # Limit traceback size to prevent DB bloat
134
+ sanitized[key] = tb_str[:2000]
135
+ elif key == 'message' and value:
136
+ # Sanitize message field
137
+ message_str = str(value)
138
+ for pattern in sensitive_patterns:
139
+ if pattern in message_str.lower():
140
+ import re
141
+ message_str = re.sub(
142
+ rf'{pattern}[=:]\s*[^\s,\]}}]+',
143
+ f'{pattern}=[REDACTED]',
144
+ message_str,
145
+ flags=re.IGNORECASE
146
+ )
147
+ sanitized[key] = message_str[:1000] # Limit message size
148
+ else:
149
+ # For other fields, copy as-is but check for nested dicts
150
+ if isinstance(value, dict):
151
+ sanitized[key] = self._sanitize_job_data(value)
152
+ elif isinstance(value, str) and len(value) > 5000:
153
+ # Limit very large string fields
154
+ sanitized[key] = value[:5000] + "...[TRUNCATED]"
155
+ else:
156
+ sanitized[key] = value
157
+
158
+ return sanitized
159
+
160
+ def enqueue(self, action, payload={}, user=None, suppress_job_activity=False):
161
+ """
162
+ Enqueue jobs to SQS with independent job activity tracking.
163
+
164
+ This method uses its own transaction for aws_job_activity updates to ensure
165
+ job tracking is never rolled back with other operations.
166
+ """
167
+ batch_id = str(uuid.uuid4())
168
+ results = {"batch_id": batch_id}
169
+ queue = boto3.resource("sqs").get_queue_by_name(
170
+ QueueName=os.environ["SqsWorkQueue"]
171
+ )
172
+ if isinstance(payload, dict):
173
+ payload = [payload]
174
+ messages = []
175
+ if user==None:
176
+ user = self.session.get("email_address") or "EnqueueTasks"
177
+ for item in payload:
178
+ message = {"action": action, "payload": item}
179
+ id = str(uuid.uuid4()).split("-")[0]
180
+ if suppress_job_activity:
181
+ messages.append({"Id": id, "MessageBody": to_json(message)})
182
+ else:
183
+ message["job_id"] = id
184
+ # Use separate transaction for job activity - this should never be rolled back
185
+ with engine.transaction as job_tx:
186
+ job_tx.table("aws_job_activity").insert(
187
+ {
188
+ "action": action,
189
+ "initial_timestamp": datetime.now(),
190
+ "created_by": user,
191
+ "sys_modified_by": user,
192
+ "payload": to_json(message),
193
+ "batch_id": str(batch_id),
194
+ "job_id": id,
195
+ "status": "Initialized",
196
+ "message": f"Job Initialized"
197
+ }
198
+ )
199
+ job_tx.commit()
200
+ messages.append({"Id": id, "MessageBody": to_json(message)})
201
+
202
+ if len(messages) == 10:
203
+ result = queue.send_messages(Entries=messages)
204
+ results = deep_merge(results, result)
205
+ messages.clear()
206
+
207
+ if messages:
208
+ result = queue.send_messages(Entries=messages)
209
+ results = deep_merge(results, result)
210
+
211
+ return results
@@ -4,7 +4,7 @@ import sys
4
4
  import os
5
5
  import traceback
6
6
  from support.app import DEBUG
7
- from support.app import helpers, AlertError, enqueue
7
+ from support.app import helpers, AlertError
8
8
 
9
9
  from velocity.aws.handlers import Response
10
10
 
@@ -164,6 +164,3 @@ class LambdaHandler:
164
164
 
165
165
  def OnActionTracking(self, tx, context):
166
166
  self.track(tx, context.payload().get("data", {}))
167
-
168
- def enqueue(self, tx, action, payload={}):
169
- enqueue(tx, action, payload, self.session["email_address"])
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: velocity-python
3
- Version: 0.0.112
3
+ Version: 0.0.115
4
4
  Summary: A rapid application development library for interfacing with data storage
5
5
  Author-email: Velocity Team <info@codeclubs.org>
6
6
  License-Expression: MIT
@@ -1,4 +1,4 @@
1
- velocity/__init__.py,sha256=iH2m31ZNvp-oPV3zuzJRMhEbgHm_d-Gs5k6ljPudBlg,107
1
+ velocity/__init__.py,sha256=89oRDLFlR3tlSTcYrvhfokSBF3tLPmP4nt_p9ayIScY,107
2
2
  velocity/app/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
3
  velocity/app/invoices.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  velocity/app/orders.py,sha256=W-HAXEwY8-IFXbKh82HnMeRVZM7P-TWGEQOWtkLIzI4,6298
@@ -7,8 +7,8 @@ velocity/app/purchase_orders.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSu
7
7
  velocity/aws/__init__.py,sha256=tj9-NliYxRVPYLnnDuA4FMwBHbbH4ed8gtHgwRskNgY,647
8
8
  velocity/aws/amplify.py,sha256=n6ttzHmbF8tc0ZDN8LIA6s_fnkZ3ylu3AAUAYyD9MzE,15048
9
9
  velocity/aws/handlers/__init__.py,sha256=xnpFZJVlC2uoeeFW4zuPST8wA8ajaQDky5Y6iXZzi3A,172
10
- velocity/aws/handlers/context.py,sha256=UIjNR83y2NSIyK8HMPX8t5tpJHFNabiZvNgmmdQL3HA,1822
11
- velocity/aws/handlers/lambda_handler.py,sha256=0KrT6UIxDILzBRpoRSvwDgHpQ-vWfubcZFOCbJsewDc,6516
10
+ velocity/aws/handlers/context.py,sha256=saeK-2hpfbuOZvA76C1_2ZJSblPO_tDuKeaeDVfli1w,8052
11
+ velocity/aws/handlers/lambda_handler.py,sha256=k8ZTj4vhuDbB9xinQ1-s7hKgx5JznldTNT3-udfMw04,6391
12
12
  velocity/aws/handlers/response.py,sha256=LXhtizLKnVBWjtHyE0h0bk-NYDrRpj7CHa7tRz9KkC4,9324
13
13
  velocity/aws/handlers/sqs_handler.py,sha256=nqt8NMOc5yO-L6CZo7NjgR8Q4KPKTDFBO-0eHu6oxkY,7149
14
14
  velocity/db/__init__.py,sha256=t7YJT42U19Vkd4MMz5MhU8IFryKfblNPLJcPqzpb4HQ,566
@@ -49,8 +49,8 @@ velocity/misc/tools.py,sha256=_bGneHHA_BV-kUonzw5H3hdJ5AOJRCKfzhgpkFbGqIo,1502
49
49
  velocity/misc/conv/__init__.py,sha256=MLYF58QHjzfDSxb1rdnmLnuEQCa3gnhzzZ30CwZVvQo,40
50
50
  velocity/misc/conv/iconv.py,sha256=d4_BucW8HTIkGNurJ7GWrtuptqUf-9t79ObzjJ5N76U,10603
51
51
  velocity/misc/conv/oconv.py,sha256=h5Lo05DqOQnxoD3y6Px_MQP_V-pBbWf8Hkgkb9Xp1jk,6032
52
- velocity_python-0.0.112.dist-info/licenses/LICENSE,sha256=aoN245GG8s9oRUU89KNiGTU4_4OtnNmVi4hQeChg6rM,1076
53
- velocity_python-0.0.112.dist-info/METADATA,sha256=LEPElQOJU4yBn0Zwdw4VzpLRNhC4M6MM1_6Qa28VBDU,34262
54
- velocity_python-0.0.112.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
55
- velocity_python-0.0.112.dist-info/top_level.txt,sha256=JW2vJPmodgdgSz7H6yoZvnxF8S3fTMIv-YJWCT1sNW0,9
56
- velocity_python-0.0.112.dist-info/RECORD,,
52
+ velocity_python-0.0.115.dist-info/licenses/LICENSE,sha256=aoN245GG8s9oRUU89KNiGTU4_4OtnNmVi4hQeChg6rM,1076
53
+ velocity_python-0.0.115.dist-info/METADATA,sha256=mH47xoUtbkjBSArI6QU7Mtx9qLjyPguYdAcVbPwtSLw,34262
54
+ velocity_python-0.0.115.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
55
+ velocity_python-0.0.115.dist-info/top_level.txt,sha256=JW2vJPmodgdgSz7H6yoZvnxF8S3fTMIv-YJWCT1sNW0,9
56
+ velocity_python-0.0.115.dist-info/RECORD,,