geek-cafe-saas-sdk 0.6.0__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 geek-cafe-saas-sdk might be problematic. Click here for more details.
- geek_cafe_saas_sdk/__init__.py +9 -0
- geek_cafe_saas_sdk/core/__init__.py +11 -0
- geek_cafe_saas_sdk/core/audit_mixin.py +33 -0
- geek_cafe_saas_sdk/core/error_codes.py +132 -0
- geek_cafe_saas_sdk/core/service_errors.py +19 -0
- geek_cafe_saas_sdk/core/service_result.py +121 -0
- geek_cafe_saas_sdk/decorators/__init__.py +64 -0
- geek_cafe_saas_sdk/decorators/auth.py +373 -0
- geek_cafe_saas_sdk/decorators/core.py +358 -0
- geek_cafe_saas_sdk/domains/__init__.py +0 -0
- geek_cafe_saas_sdk/domains/analytics/__init__.py +0 -0
- geek_cafe_saas_sdk/domains/analytics/handlers/__init__.py +0 -0
- geek_cafe_saas_sdk/domains/analytics/models/__init__.py +9 -0
- geek_cafe_saas_sdk/domains/analytics/models/website_analytics.py +219 -0
- geek_cafe_saas_sdk/domains/analytics/models/website_analytics_summary.py +220 -0
- geek_cafe_saas_sdk/domains/analytics/services/__init__.py +11 -0
- geek_cafe_saas_sdk/domains/analytics/services/website_analytics_service.py +232 -0
- geek_cafe_saas_sdk/domains/analytics/services/website_analytics_summary_service.py +212 -0
- geek_cafe_saas_sdk/domains/analytics/services/website_analytics_tally_service.py +610 -0
- geek_cafe_saas_sdk/domains/auth/__init__.py +0 -0
- geek_cafe_saas_sdk/domains/auth/handlers/__init__.py +0 -0
- geek_cafe_saas_sdk/domains/auth/handlers/users/create/app.py +41 -0
- geek_cafe_saas_sdk/domains/auth/handlers/users/delete/app.py +41 -0
- geek_cafe_saas_sdk/domains/auth/handlers/users/get/app.py +39 -0
- geek_cafe_saas_sdk/domains/auth/handlers/users/list/app.py +36 -0
- geek_cafe_saas_sdk/domains/auth/handlers/users/update/app.py +44 -0
- geek_cafe_saas_sdk/domains/auth/models/__init__.py +13 -0
- geek_cafe_saas_sdk/domains/auth/models/permission.py +134 -0
- geek_cafe_saas_sdk/domains/auth/models/resource_permission.py +245 -0
- geek_cafe_saas_sdk/domains/auth/models/role.py +213 -0
- geek_cafe_saas_sdk/domains/auth/models/user.py +285 -0
- geek_cafe_saas_sdk/domains/auth/services/__init__.py +16 -0
- geek_cafe_saas_sdk/domains/auth/services/authorization_service.py +376 -0
- geek_cafe_saas_sdk/domains/auth/services/permission_registry.py +464 -0
- geek_cafe_saas_sdk/domains/auth/services/resource_permission_service.py +408 -0
- geek_cafe_saas_sdk/domains/auth/services/user_service.py +274 -0
- geek_cafe_saas_sdk/domains/communities/__init__.py +0 -0
- geek_cafe_saas_sdk/domains/communities/handlers/__init__.py +0 -0
- geek_cafe_saas_sdk/domains/communities/handlers/communities/create/app.py +41 -0
- geek_cafe_saas_sdk/domains/communities/handlers/communities/delete/app.py +41 -0
- geek_cafe_saas_sdk/domains/communities/handlers/communities/get/app.py +39 -0
- geek_cafe_saas_sdk/domains/communities/handlers/communities/list/app.py +36 -0
- geek_cafe_saas_sdk/domains/communities/handlers/communities/update/app.py +44 -0
- geek_cafe_saas_sdk/domains/communities/models/__init__.py +6 -0
- geek_cafe_saas_sdk/domains/communities/models/community.py +326 -0
- geek_cafe_saas_sdk/domains/communities/models/community_member.py +227 -0
- geek_cafe_saas_sdk/domains/communities/services/__init__.py +6 -0
- geek_cafe_saas_sdk/domains/communities/services/community_member_service.py +412 -0
- geek_cafe_saas_sdk/domains/communities/services/community_service.py +479 -0
- geek_cafe_saas_sdk/domains/events/__init__.py +0 -0
- geek_cafe_saas_sdk/domains/events/handlers/__init__.py +0 -0
- geek_cafe_saas_sdk/domains/events/handlers/attendees/app.py +67 -0
- geek_cafe_saas_sdk/domains/events/handlers/cancel/app.py +66 -0
- geek_cafe_saas_sdk/domains/events/handlers/check_in/app.py +60 -0
- geek_cafe_saas_sdk/domains/events/handlers/create/app.py +93 -0
- geek_cafe_saas_sdk/domains/events/handlers/delete/app.py +42 -0
- geek_cafe_saas_sdk/domains/events/handlers/get/app.py +39 -0
- geek_cafe_saas_sdk/domains/events/handlers/invite/app.py +98 -0
- geek_cafe_saas_sdk/domains/events/handlers/list/app.py +125 -0
- geek_cafe_saas_sdk/domains/events/handlers/publish/app.py +49 -0
- geek_cafe_saas_sdk/domains/events/handlers/rsvp/app.py +83 -0
- geek_cafe_saas_sdk/domains/events/handlers/update/app.py +44 -0
- geek_cafe_saas_sdk/domains/events/models/__init__.py +3 -0
- geek_cafe_saas_sdk/domains/events/models/event.py +681 -0
- geek_cafe_saas_sdk/domains/events/models/event_attendee.py +324 -0
- geek_cafe_saas_sdk/domains/events/services/__init__.py +9 -0
- geek_cafe_saas_sdk/domains/events/services/event_attendee_service.py +571 -0
- geek_cafe_saas_sdk/domains/events/services/event_service.py +684 -0
- geek_cafe_saas_sdk/domains/files/__init__.py +0 -0
- geek_cafe_saas_sdk/domains/files/models/__init__.py +0 -0
- geek_cafe_saas_sdk/domains/files/models/directory.py +258 -0
- geek_cafe_saas_sdk/domains/files/models/file.py +312 -0
- geek_cafe_saas_sdk/domains/files/models/file_share.py +268 -0
- geek_cafe_saas_sdk/domains/files/models/file_version.py +216 -0
- geek_cafe_saas_sdk/domains/files/services/__init__.py +0 -0
- geek_cafe_saas_sdk/domains/files/services/directory_service.py +701 -0
- geek_cafe_saas_sdk/domains/files/services/file_share_service.py +663 -0
- geek_cafe_saas_sdk/domains/files/services/file_system_service.py +575 -0
- geek_cafe_saas_sdk/domains/files/services/file_version_service.py +739 -0
- geek_cafe_saas_sdk/domains/files/services/s3_file_service.py +501 -0
- geek_cafe_saas_sdk/domains/messaging/__init__.py +0 -0
- geek_cafe_saas_sdk/domains/messaging/handlers/__init__.py +0 -0
- geek_cafe_saas_sdk/domains/messaging/handlers/chat_channels/create/app.py +86 -0
- geek_cafe_saas_sdk/domains/messaging/handlers/chat_channels/delete/app.py +65 -0
- geek_cafe_saas_sdk/domains/messaging/handlers/chat_channels/get/app.py +64 -0
- geek_cafe_saas_sdk/domains/messaging/handlers/chat_channels/list/app.py +97 -0
- geek_cafe_saas_sdk/domains/messaging/handlers/chat_channels/update/app.py +149 -0
- geek_cafe_saas_sdk/domains/messaging/handlers/chat_messages/create/app.py +67 -0
- geek_cafe_saas_sdk/domains/messaging/handlers/chat_messages/delete/app.py +65 -0
- geek_cafe_saas_sdk/domains/messaging/handlers/chat_messages/get/app.py +64 -0
- geek_cafe_saas_sdk/domains/messaging/handlers/chat_messages/list/app.py +102 -0
- geek_cafe_saas_sdk/domains/messaging/handlers/chat_messages/update/app.py +127 -0
- geek_cafe_saas_sdk/domains/messaging/handlers/contact_threads/create/app.py +94 -0
- geek_cafe_saas_sdk/domains/messaging/handlers/contact_threads/delete/app.py +66 -0
- geek_cafe_saas_sdk/domains/messaging/handlers/contact_threads/get/app.py +67 -0
- geek_cafe_saas_sdk/domains/messaging/handlers/contact_threads/list/app.py +95 -0
- geek_cafe_saas_sdk/domains/messaging/handlers/contact_threads/update/app.py +156 -0
- geek_cafe_saas_sdk/domains/messaging/models/__init__.py +13 -0
- geek_cafe_saas_sdk/domains/messaging/models/chat_channel.py +337 -0
- geek_cafe_saas_sdk/domains/messaging/models/chat_channel_member.py +180 -0
- geek_cafe_saas_sdk/domains/messaging/models/chat_message.py +426 -0
- geek_cafe_saas_sdk/domains/messaging/models/contact_thread.py +392 -0
- geek_cafe_saas_sdk/domains/messaging/services/__init__.py +11 -0
- geek_cafe_saas_sdk/domains/messaging/services/chat_channel_service.py +700 -0
- geek_cafe_saas_sdk/domains/messaging/services/chat_message_service.py +491 -0
- geek_cafe_saas_sdk/domains/messaging/services/contact_thread_service.py +497 -0
- geek_cafe_saas_sdk/domains/tenancy/__init__.py +0 -0
- geek_cafe_saas_sdk/domains/tenancy/handlers/__init__.py +0 -0
- geek_cafe_saas_sdk/domains/tenancy/handlers/subscriptions/activate/app.py +52 -0
- geek_cafe_saas_sdk/domains/tenancy/handlers/subscriptions/active/app.py +37 -0
- geek_cafe_saas_sdk/domains/tenancy/handlers/subscriptions/cancel/app.py +55 -0
- geek_cafe_saas_sdk/domains/tenancy/handlers/subscriptions/get/app.py +39 -0
- geek_cafe_saas_sdk/domains/tenancy/handlers/subscriptions/list/app.py +44 -0
- geek_cafe_saas_sdk/domains/tenancy/handlers/subscriptions/record_payment/app.py +56 -0
- geek_cafe_saas_sdk/domains/tenancy/handlers/tenants/get/app.py +39 -0
- geek_cafe_saas_sdk/domains/tenancy/handlers/tenants/me/app.py +37 -0
- geek_cafe_saas_sdk/domains/tenancy/handlers/tenants/signup/app.py +61 -0
- geek_cafe_saas_sdk/domains/tenancy/handlers/tenants/update/app.py +44 -0
- geek_cafe_saas_sdk/domains/tenancy/models/__init__.py +6 -0
- geek_cafe_saas_sdk/domains/tenancy/models/subscription.py +440 -0
- geek_cafe_saas_sdk/domains/tenancy/models/tenant.py +258 -0
- geek_cafe_saas_sdk/domains/tenancy/services/__init__.py +6 -0
- geek_cafe_saas_sdk/domains/tenancy/services/subscription_service.py +557 -0
- geek_cafe_saas_sdk/domains/tenancy/services/tenant_service.py +575 -0
- geek_cafe_saas_sdk/domains/voting/__init__.py +0 -0
- geek_cafe_saas_sdk/domains/voting/handlers/__init__.py +0 -0
- geek_cafe_saas_sdk/domains/voting/handlers/votes/create/app.py +128 -0
- geek_cafe_saas_sdk/domains/voting/handlers/votes/delete/app.py +41 -0
- geek_cafe_saas_sdk/domains/voting/handlers/votes/get/app.py +39 -0
- geek_cafe_saas_sdk/domains/voting/handlers/votes/list/app.py +38 -0
- geek_cafe_saas_sdk/domains/voting/handlers/votes/summerize/README.md +3 -0
- geek_cafe_saas_sdk/domains/voting/handlers/votes/update/app.py +44 -0
- geek_cafe_saas_sdk/domains/voting/models/__init__.py +9 -0
- geek_cafe_saas_sdk/domains/voting/models/vote.py +231 -0
- geek_cafe_saas_sdk/domains/voting/models/vote_summary.py +193 -0
- geek_cafe_saas_sdk/domains/voting/services/__init__.py +11 -0
- geek_cafe_saas_sdk/domains/voting/services/vote_service.py +264 -0
- geek_cafe_saas_sdk/domains/voting/services/vote_summary_service.py +198 -0
- geek_cafe_saas_sdk/domains/voting/services/vote_tally_service.py +533 -0
- geek_cafe_saas_sdk/lambda_handlers/README.md +404 -0
- geek_cafe_saas_sdk/lambda_handlers/__init__.py +67 -0
- geek_cafe_saas_sdk/lambda_handlers/_base/__init__.py +25 -0
- geek_cafe_saas_sdk/lambda_handlers/_base/api_key_handler.py +129 -0
- geek_cafe_saas_sdk/lambda_handlers/_base/authorized_secure_handler.py +218 -0
- geek_cafe_saas_sdk/lambda_handlers/_base/base_handler.py +185 -0
- geek_cafe_saas_sdk/lambda_handlers/_base/handler_factory.py +256 -0
- geek_cafe_saas_sdk/lambda_handlers/_base/public_handler.py +53 -0
- geek_cafe_saas_sdk/lambda_handlers/_base/secure_handler.py +89 -0
- geek_cafe_saas_sdk/lambda_handlers/_base/service_pool.py +94 -0
- geek_cafe_saas_sdk/lambda_handlers/directories/create/app.py +79 -0
- geek_cafe_saas_sdk/lambda_handlers/directories/delete/app.py +76 -0
- geek_cafe_saas_sdk/lambda_handlers/directories/get/app.py +74 -0
- geek_cafe_saas_sdk/lambda_handlers/directories/list/app.py +75 -0
- geek_cafe_saas_sdk/lambda_handlers/directories/move/app.py +79 -0
- geek_cafe_saas_sdk/lambda_handlers/files/delete/app.py +121 -0
- geek_cafe_saas_sdk/lambda_handlers/files/download/app.py +187 -0
- geek_cafe_saas_sdk/lambda_handlers/files/get/app.py +127 -0
- geek_cafe_saas_sdk/lambda_handlers/files/list/app.py +108 -0
- geek_cafe_saas_sdk/lambda_handlers/files/share/app.py +83 -0
- geek_cafe_saas_sdk/lambda_handlers/files/shares/list/app.py +84 -0
- geek_cafe_saas_sdk/lambda_handlers/files/shares/revoke/app.py +76 -0
- geek_cafe_saas_sdk/lambda_handlers/files/update/app.py +143 -0
- geek_cafe_saas_sdk/lambda_handlers/files/upload/app.py +151 -0
- geek_cafe_saas_sdk/middleware/__init__.py +36 -0
- geek_cafe_saas_sdk/middleware/auth.py +85 -0
- geek_cafe_saas_sdk/middleware/authorization.py +523 -0
- geek_cafe_saas_sdk/middleware/cors.py +63 -0
- geek_cafe_saas_sdk/middleware/error_handling.py +114 -0
- geek_cafe_saas_sdk/middleware/validation.py +80 -0
- geek_cafe_saas_sdk/models/__init__.py +20 -0
- geek_cafe_saas_sdk/models/base_model.py +233 -0
- geek_cafe_saas_sdk/services/__init__.py +18 -0
- geek_cafe_saas_sdk/services/database_service.py +441 -0
- geek_cafe_saas_sdk/utilities/__init__.py +88 -0
- geek_cafe_saas_sdk/utilities/cognito_utility.py +568 -0
- geek_cafe_saas_sdk/utilities/custom_exceptions.py +183 -0
- geek_cafe_saas_sdk/utilities/datetime_utility.py +410 -0
- geek_cafe_saas_sdk/utilities/dictionary_utility.py +78 -0
- geek_cafe_saas_sdk/utilities/dynamodb_utils.py +151 -0
- geek_cafe_saas_sdk/utilities/environment_loader.py +149 -0
- geek_cafe_saas_sdk/utilities/environment_variables.py +228 -0
- geek_cafe_saas_sdk/utilities/http_body_parameters.py +44 -0
- geek_cafe_saas_sdk/utilities/http_path_parameters.py +60 -0
- geek_cafe_saas_sdk/utilities/http_status_code.py +63 -0
- geek_cafe_saas_sdk/utilities/jwt_utility.py +234 -0
- geek_cafe_saas_sdk/utilities/lambda_event_utility.py +776 -0
- geek_cafe_saas_sdk/utilities/logging_utility.py +64 -0
- geek_cafe_saas_sdk/utilities/message_query_helper.py +340 -0
- geek_cafe_saas_sdk/utilities/response.py +209 -0
- geek_cafe_saas_sdk/utilities/string_functions.py +180 -0
- geek_cafe_saas_sdk-0.6.0.dist-info/METADATA +397 -0
- geek_cafe_saas_sdk-0.6.0.dist-info/RECORD +194 -0
- geek_cafe_saas_sdk-0.6.0.dist-info/WHEEL +4 -0
- geek_cafe_saas_sdk-0.6.0.dist-info/licenses/LICENSE +47 -0
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
# DynamoDB Utilities
|
|
2
|
+
|
|
3
|
+
from typing import Dict, Set
|
|
4
|
+
|
|
5
|
+
# DynamoDB Reserved Keywords (subset of common ones)
|
|
6
|
+
# Full list: https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ReservedWords.html
|
|
7
|
+
DYNAMODB_RESERVED_KEYWORDS: Set[str] = {
|
|
8
|
+
'ABORT', 'ABSOLUTE', 'ACTION', 'ADD', 'AFTER', 'AGENT', 'AGGREGATE', 'ALL', 'ALSO', 'ALTER',
|
|
9
|
+
'ANALYZE', 'AND', 'ANY', 'ARCHIVE', 'ARE', 'ARRAY', 'AS', 'ASC', 'ASSERT', 'AST', 'AT',
|
|
10
|
+
'AUTHORIZATION', 'BACKUP', 'BATCH', 'BEFORE', 'BEGIN', 'BETWEEN', 'BIGINT', 'BINARY', 'BIT',
|
|
11
|
+
'BLOB', 'BLOCK', 'BOOLEAN', 'BOTH', 'BREAK', 'BUCKET', 'BULK', 'BY', 'BYTE', 'CALL', 'CALLED',
|
|
12
|
+
'CALLING', 'CAPACITY', 'CASCADE', 'CASCADED', 'CASE', 'CAST', 'CATALOG', 'CHAIN', 'CHANGE',
|
|
13
|
+
'CHANGED', 'CHARACTER', 'CHECK', 'CLASS', 'CLOB', 'CLOSE', 'CLUSTER', 'CLUSTERED', 'CLUSTERING',
|
|
14
|
+
'CLUSTERS', 'COALESCE', 'COLLATE', 'COLLATION', 'COLUMN', 'COLUMNS', 'COMBINE', 'COMMENT',
|
|
15
|
+
'COMMIT', 'COMMITTED', 'COMPACT', 'COMPILE', 'COMPILED', 'CONCURRENTLY', 'CONDITION',
|
|
16
|
+
'CONDITIONAL', 'CONFLICT', 'CONNECT', 'CONNECTION', 'CONSTRAINT', 'CONTAINS', 'CONVERT',
|
|
17
|
+
'COPY', 'COST', 'CREATE', 'CROSS', 'CSV', 'CUBE', 'CURRENT', 'CURSOR', 'CYCLE', 'DATA',
|
|
18
|
+
'DATABASE', 'DATABASES', 'DATE', 'DATETIME', 'DAY', 'DEALLOCATE', 'DEC', 'DECIMAL', 'DECLARE',
|
|
19
|
+
'DEFAULT', 'DEFAULTS', 'DEFERRABLE', 'DEFERRED', 'DEFINE', 'DEFINED', 'DEFINITION', 'DELETE',
|
|
20
|
+
'DELIMITER', 'DELIMITERS', 'DENSE_RANK', 'DEREF', 'DESC', 'DETACH', 'DETERMINISTIC', 'DICTIONARY',
|
|
21
|
+
'DISABLE', 'DISCARD', 'DISTINCT', 'DO', 'DOCUMENT', 'DOMAIN', 'DOUBLE', 'DROP', 'EACH', 'ELEMENT',
|
|
22
|
+
'ELSE', 'EMPTY', 'ENABLE', 'ENCODING', 'ENCRYPTED', 'END', 'ENUM', 'EQUAL', 'EQUALS', 'ERROR',
|
|
23
|
+
'ERRORS', 'ESCAPE', 'EVENT', 'EXCEPT', 'EXCEPTION', 'EXCEPTIONS', 'EXCLUDE', 'EXCLUDING',
|
|
24
|
+
'EXCLUSIVE', 'EXECUTE', 'EXISTS', 'EXPLAIN', 'EXPRESSION', 'EXTENDED', 'EXTENDS', 'EXTERNAL',
|
|
25
|
+
'EXTRACT', 'FALSE', 'FAMILY', 'FETCH', 'FILTER', 'FIRST', 'FLOAT', 'FOLLOWING', 'FOR', 'FORCE',
|
|
26
|
+
'FOREIGN', 'FORMAT', 'FORWARD', 'FOUNDATION', 'FRAME', 'FREE', 'FROM', 'FULL', 'FUNCTION',
|
|
27
|
+
'FUNCTIONS', 'GENERAL', 'GENERATED', 'GET', 'GLOBAL', 'GO', 'GOTO', 'GRANT', 'GRANTED', 'GREATEST',
|
|
28
|
+
'GROUP', 'GROUPING', 'GROUPS', 'HANDLER', 'HAVING', 'HEADER', 'HOLD', 'HOUR', 'IDENTITY', 'IF',
|
|
29
|
+
'ILIKE', 'IMMEDIATE', 'IMMUTABLE', 'IMPLICIT', 'IMPORT', 'IN', 'INCLUDING', 'INCREMENT',
|
|
30
|
+
'INCREMENTAL', 'INDEX', 'INDEXED', 'INDEXES', 'INDICATE', 'INHERITS', 'INITIALLY', 'INLINE',
|
|
31
|
+
'INNER', 'INOUT', 'INPUT', 'INSENSITIVE', 'INSERT', 'INSTEAD', 'INT', 'INTEGER', 'INTERSECT',
|
|
32
|
+
'INTERVAL', 'INTO', 'INVOKER', 'IS', 'ISNULL', 'ISOLATION', 'ITEM', 'ITEMS', 'ITERATE', 'JOIN',
|
|
33
|
+
'KEY', 'KEYS', 'LABEL', 'LANGUAGE', 'LARGE', 'LAST', 'LATERAL', 'LEAD', 'LEADING', 'LEAKPROOF',
|
|
34
|
+
'LEAST', 'LEFT', 'LENGTH', 'LEVEL', 'LIKE', 'LIMIT', 'LISTEN', 'LOAD', 'LOCAL', 'LOCALTIME',
|
|
35
|
+
'LOCALTIMESTAMP', 'LOCATION', 'LOCK', 'LOCKS', 'LOGGED', 'MAPPING', 'MATCH', 'MATERIALIZED',
|
|
36
|
+
'MAXVALUE', 'MINUS', 'MINUTE', 'MINVALUE', 'MODE', 'MODIFIES', 'MODIFY', 'MONTH', 'MOVE',
|
|
37
|
+
'NAME', 'NAMES', 'NATIONAL', 'NATURAL', 'NCHAR', 'NCLOB', 'NESTED', 'NEW', 'NEXT', 'NO',
|
|
38
|
+
'NONE', 'NOT', 'NOTHING', 'NOTIFY', 'NOTNULL', 'NOWAIT', 'NULL', 'NULLIF', 'NULLS', 'NUMBER',
|
|
39
|
+
'NUMERIC', 'OBJECT', 'OF', 'OFF', 'OFFSET', 'OIDS', 'OLD', 'ON', 'ONLY', 'OPERATOR', 'OPTION',
|
|
40
|
+
'OPTIONS', 'OR', 'ORDER', 'ORDINALITY', 'OTHERS', 'OUT', 'OUTER', 'OVER', 'OVERLAPS', 'OVERLAY',
|
|
41
|
+
'OVERRIDING', 'OWNED', 'OWNER', 'PARSER', 'PARTIAL', 'PARTITION', 'PARTITIONED', 'PARTITIONS',
|
|
42
|
+
'PASSING', 'PASSWORD', 'PLACING', 'PLANS', 'POLICY', 'POSITION', 'PRECEDING', 'PRECISION',
|
|
43
|
+
'PREPARE', 'PREPARED', 'PRESERVE', 'PRIMARY', 'PRIOR', 'PRIVILEGES', 'PROCEDURAL', 'PROCEDURE',
|
|
44
|
+
'PROGRAM', 'QUOTE', 'RANGE', 'RANK', 'READ', 'READS', 'REAL', 'REASSIGN', 'RECHECK', 'RECURSIVE',
|
|
45
|
+
'REF', 'REFERENCES', 'REFERENCING', 'REFRESH', 'REINDEX', 'RELATIVE', 'RELEASE', 'RENAME',
|
|
46
|
+
'REPEATABLE', 'REPLACE', 'REPLICA', 'RESET', 'RESTART', 'RESTRICT', 'RETURNING', 'RETURNS',
|
|
47
|
+
'REVOKE', 'RIGHT', 'ROLE', 'ROLES', 'ROLLBACK', 'ROLLUP', 'ROUTINE', 'ROUTINES', 'ROW',
|
|
48
|
+
'ROWS', 'RULE', 'SAVEPOINT', 'SCALE', 'SCHEMA', 'SCHEMAS', 'SCROLL', 'SEARCH', 'SECOND',
|
|
49
|
+
'SECURITY', 'SELECT', 'SEQUENCE', 'SEQUENCES', 'SERIALIZABLE', 'SERVER', 'SESSION', 'SET',
|
|
50
|
+
'SETS', 'SHARE', 'SHOW', 'SIMILAR', 'SIMPLE', 'SMALLINT', 'SNAPSHOT', 'SOME', 'SQL', 'STABLE',
|
|
51
|
+
'STANDALONE', 'START', 'STATEMENT', 'STATISTICS', 'STDIN', 'STDOUT', 'STORAGE', 'STORED',
|
|
52
|
+
'STRICT', 'STRIP', 'SUBSTRING', 'SYMMETRIC', 'SYSID', 'SYSTEM', 'TABLE', 'TABLES', 'TABLESPACE',
|
|
53
|
+
'TEMP', 'TEMPLATE', 'TEMPORARY', 'TEXT', 'THEN', 'TIME', 'TIMESTAMP', 'TO', 'TRAILING',
|
|
54
|
+
'TRANSACTION', 'TRANSFORM', 'TREAT', 'TRIGGER', 'TRIM', 'TRUE', 'TRUNCATE', 'TRUSTED', 'TYPE',
|
|
55
|
+
'TYPES', 'UESCAPE', 'UNBOUNDED', 'UNCOMMITTED', 'UNENCRYPTED', 'UNION', 'UNIQUE', 'UNKNOWN',
|
|
56
|
+
'UNLISTEN', 'UNLOGGED', 'UNTIL', 'UPDATE', 'USER', 'USERS', 'USING', 'VACUUM', 'VALID',
|
|
57
|
+
'VALIDATE', 'VALIDATOR', 'VALUE', 'VALUES', 'VARCHAR', 'VARIADIC', 'VARYING', 'VERBOSE',
|
|
58
|
+
'VERSION', 'VIEW', 'VIEWS', 'VOLATILE', 'WHEN', 'WHERE', 'WHITESPACE', 'WINDOW', 'WITH',
|
|
59
|
+
'WITHIN', 'WITHOUT', 'WORK', 'WRAPPER', 'WRITE', 'XML', 'XMLATTRIBUTES', 'XMLCONCAT', 'XMLELEMENT',
|
|
60
|
+
'XMLEXISTS', 'XMLFOREST', 'XMLPARSE', 'XMLPI', 'XMLROOT', 'XMLSERIALIZE', 'YEAR', 'YES', 'ZONE'
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def build_expression_attribute_names(attributes: list[str]) -> Dict[str, str]:
|
|
65
|
+
"""
|
|
66
|
+
Build ExpressionAttributeNames mapping for DynamoDB reserved keywords.
|
|
67
|
+
|
|
68
|
+
Args:
|
|
69
|
+
attributes: List of attribute names that may contain reserved keywords
|
|
70
|
+
|
|
71
|
+
Returns:
|
|
72
|
+
Dictionary mapping attribute placeholders to actual attribute names
|
|
73
|
+
|
|
74
|
+
Example:
|
|
75
|
+
>>> build_expression_attribute_names(['email', 'roles', 'name'])
|
|
76
|
+
{'#email': 'email', '#roles': 'roles', '#name': 'name'}
|
|
77
|
+
"""
|
|
78
|
+
expression_attribute_names = {}
|
|
79
|
+
|
|
80
|
+
for attr in attributes:
|
|
81
|
+
if attr.upper() in DYNAMODB_RESERVED_KEYWORDS:
|
|
82
|
+
# Use placeholder for reserved keywords
|
|
83
|
+
placeholder = f"#{attr}"
|
|
84
|
+
expression_attribute_names[placeholder] = attr
|
|
85
|
+
else:
|
|
86
|
+
# For non-reserved keywords, we could still use placeholders for consistency
|
|
87
|
+
# but it's optional. For now, we'll only add placeholders for reserved keywords.
|
|
88
|
+
pass
|
|
89
|
+
|
|
90
|
+
return expression_attribute_names
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def replace_reserved_keywords_in_expression(expression: str, attribute_names: Dict[str, str]) -> str:
|
|
94
|
+
"""
|
|
95
|
+
Replace reserved keyword attribute names with placeholders in expressions.
|
|
96
|
+
|
|
97
|
+
Args:
|
|
98
|
+
expression: The expression string (e.g., ProjectionExpression)
|
|
99
|
+
attribute_names: The ExpressionAttributeNames mapping
|
|
100
|
+
|
|
101
|
+
Returns:
|
|
102
|
+
Expression with reserved keywords replaced by placeholders
|
|
103
|
+
|
|
104
|
+
Example:
|
|
105
|
+
>>> replace_reserved_keywords_in_expression(
|
|
106
|
+
... "pk, sk, email, roles, name",
|
|
107
|
+
... {'#email': 'email', '#roles': 'roles'}
|
|
108
|
+
... )
|
|
109
|
+
"pk, sk, #email, #roles, name"
|
|
110
|
+
"""
|
|
111
|
+
result = expression
|
|
112
|
+
|
|
113
|
+
# Replace each reserved keyword with its placeholder
|
|
114
|
+
for placeholder, attr_name in attribute_names.items():
|
|
115
|
+
result = result.replace(attr_name, placeholder)
|
|
116
|
+
|
|
117
|
+
return result
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def build_projection_with_reserved_keywords(attributes: list[str]) -> tuple[str, Dict[str, str]]:
|
|
121
|
+
"""
|
|
122
|
+
Convenience function to build projection expression and attribute names mapping.
|
|
123
|
+
|
|
124
|
+
Args:
|
|
125
|
+
attributes: List of attribute names for projection
|
|
126
|
+
|
|
127
|
+
Returns:
|
|
128
|
+
Tuple of (projection_expression, expression_attribute_names)
|
|
129
|
+
|
|
130
|
+
Example:
|
|
131
|
+
>>> projection, attr_names = build_projection_with_reserved_keywords(
|
|
132
|
+
... ['pk', 'sk', 'email', 'roles', 'name']
|
|
133
|
+
... )
|
|
134
|
+
>>> projection
|
|
135
|
+
"pk, sk, #email, #roles, name"
|
|
136
|
+
>>> attr_names
|
|
137
|
+
{'#email': 'email', '#roles': 'roles'}
|
|
138
|
+
"""
|
|
139
|
+
# Build the attribute names mapping
|
|
140
|
+
expression_attribute_names = build_expression_attribute_names(attributes)
|
|
141
|
+
|
|
142
|
+
# Create projection expression
|
|
143
|
+
projection_expression = ", ".join(attributes)
|
|
144
|
+
|
|
145
|
+
# Replace reserved keywords with placeholders
|
|
146
|
+
if expression_attribute_names:
|
|
147
|
+
projection_expression = replace_reserved_keywords_in_expression(
|
|
148
|
+
projection_expression, expression_attribute_names
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
return projection_expression, expression_attribute_names
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Geek Cafe SaaS Services Environment Services.
|
|
3
|
+
|
|
4
|
+
This module provides utilities for loading and accessing environment variables
|
|
5
|
+
used throughout the Geek Cafe SaaS Services application. It includes classes for
|
|
6
|
+
loading environment files and accessing specific environment variables in a
|
|
7
|
+
consistent manner.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import os
|
|
11
|
+
import json
|
|
12
|
+
from typing import Dict, List, Any, Optional
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
from dotenv import load_dotenv
|
|
15
|
+
from aws_lambda_powertools import Logger
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
logger = Logger(__name__)
|
|
19
|
+
|
|
20
|
+
DEBUGGING = os.getenv("DEBUGGING", "false").lower() == "true"
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class EnvironmentLoader:
|
|
24
|
+
"""Utility class for loading environment variables from files.
|
|
25
|
+
|
|
26
|
+
This class provides methods to load environment variables from .env files,
|
|
27
|
+
load event files for testing, and search for files in the project directory structure.
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
def load_environment(
|
|
31
|
+
self,
|
|
32
|
+
*,
|
|
33
|
+
starting_path: Optional[str] = None,
|
|
34
|
+
file_name: str = ".env.dev",
|
|
35
|
+
override_vars: bool = True,
|
|
36
|
+
raise_error_if_not_found: bool = True,
|
|
37
|
+
) -> None:
|
|
38
|
+
"""Load environment variables from a .env file.
|
|
39
|
+
|
|
40
|
+
Searches for the specified environment file starting from the given path
|
|
41
|
+
and loads the environment variables from it.
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
starting_path: Path to start searching from. If None, uses the current file's location.
|
|
45
|
+
file_name: Name of the environment file to load (default: ".env.dev").
|
|
46
|
+
override_vars: Whether to override existing environment variables (default: True).
|
|
47
|
+
raise_error_if_not_found: Whether to raise an error if the file is not found (default: True).
|
|
48
|
+
|
|
49
|
+
Raises:
|
|
50
|
+
RuntimeError: If the environment file is not found and raise_error_if_not_found is True.
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
if not starting_path:
|
|
54
|
+
starting_path = __file__
|
|
55
|
+
|
|
56
|
+
environment_file: str | None = self.find_file(
|
|
57
|
+
starting_path=starting_path,
|
|
58
|
+
file_name=file_name,
|
|
59
|
+
raise_error_if_not_found=raise_error_if_not_found,
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
if environment_file:
|
|
63
|
+
load_dotenv(dotenv_path=environment_file, override=override_vars)
|
|
64
|
+
|
|
65
|
+
if DEBUGGING:
|
|
66
|
+
env_vars = os.environ
|
|
67
|
+
logger.debug(f"Loaded environment file: {environment_file}")
|
|
68
|
+
# print(env_vars)
|
|
69
|
+
|
|
70
|
+
def load_event_file(self, full_path: str) -> Dict[str, Any]:
|
|
71
|
+
"""Load and parse a JSON event file.
|
|
72
|
+
|
|
73
|
+
Loads a JSON event file and handles common event structures by extracting
|
|
74
|
+
the actual event data from nested 'message' or 'event' fields if present.
|
|
75
|
+
|
|
76
|
+
Args:
|
|
77
|
+
full_path: The full path to the JSON event file.
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
The parsed event data as a dictionary.
|
|
81
|
+
|
|
82
|
+
Raises:
|
|
83
|
+
RuntimeError: If the event file does not exist.
|
|
84
|
+
"""
|
|
85
|
+
if not os.path.exists(full_path):
|
|
86
|
+
raise RuntimeError(f"Failed to locate event file: {full_path}")
|
|
87
|
+
|
|
88
|
+
event: Dict = {}
|
|
89
|
+
with open(full_path, mode="r", encoding="utf-8") as json_file:
|
|
90
|
+
event = json.load(json_file)
|
|
91
|
+
|
|
92
|
+
if "message" in event:
|
|
93
|
+
tmp = event.get("message")
|
|
94
|
+
if isinstance(tmp, Dict):
|
|
95
|
+
event = tmp
|
|
96
|
+
|
|
97
|
+
if "event" in event:
|
|
98
|
+
tmp = event.get("event")
|
|
99
|
+
if isinstance(tmp, Dict):
|
|
100
|
+
event = tmp
|
|
101
|
+
|
|
102
|
+
return event
|
|
103
|
+
|
|
104
|
+
def find_file(
|
|
105
|
+
self, starting_path: str, file_name: str, raise_error_if_not_found: bool = True, max_parent_directories: int = 25
|
|
106
|
+
) -> Optional[str]:
|
|
107
|
+
"""Search for a file in the project directory structure.
|
|
108
|
+
|
|
109
|
+
Searches for the specified file by traversing up the directory tree
|
|
110
|
+
starting from the given path, up to a maximum number of parent directories.
|
|
111
|
+
|
|
112
|
+
Args:
|
|
113
|
+
starting_path: Path to start searching from.
|
|
114
|
+
file_name: Name of the file to search for.
|
|
115
|
+
raise_error_if_not_found: Whether to raise an error if the file is not found (default: True).
|
|
116
|
+
max_parent_directories: Maximum number of parent directories to search (default: 25).
|
|
117
|
+
|
|
118
|
+
Returns:
|
|
119
|
+
The full path to the found file, or None if not found and raise_error_if_not_found is False.
|
|
120
|
+
|
|
121
|
+
Raises:
|
|
122
|
+
RuntimeError: If the file is not found and raise_error_if_not_found is True.
|
|
123
|
+
"""
|
|
124
|
+
parents = max_parent_directories
|
|
125
|
+
starting_path = starting_path or __file__
|
|
126
|
+
|
|
127
|
+
paths: List[str] = []
|
|
128
|
+
for parent in range(parents):
|
|
129
|
+
# Check if we have enough parent directories available
|
|
130
|
+
current_path = Path(starting_path)
|
|
131
|
+
if parent >= len(current_path.parents):
|
|
132
|
+
break
|
|
133
|
+
|
|
134
|
+
path = current_path.parents[parent].absolute()
|
|
135
|
+
print(f"searching: {path}")
|
|
136
|
+
tmp = os.path.join(path, file_name)
|
|
137
|
+
paths.append(tmp)
|
|
138
|
+
if os.path.exists(tmp):
|
|
139
|
+
return tmp
|
|
140
|
+
|
|
141
|
+
if raise_error_if_not_found:
|
|
142
|
+
searched_paths = "\n".join(paths)
|
|
143
|
+
raise RuntimeError(
|
|
144
|
+
f"Failed to locate environment file: {file_name} in: \n {searched_paths}"
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
return None
|
|
148
|
+
|
|
149
|
+
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Geek Cafe SaaS Services Environment Services.
|
|
3
|
+
|
|
4
|
+
This module provides utilities for loading and accessing environment variables
|
|
5
|
+
used throughout the Geek Cafe SaaS Services application. It includes classes for
|
|
6
|
+
loading environment files and accessing specific environment variables in a
|
|
7
|
+
consistent manner.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import os
|
|
11
|
+
from typing import Optional
|
|
12
|
+
from aws_lambda_powertools import Logger
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
logger = Logger(__name__)
|
|
16
|
+
|
|
17
|
+
DEBUGGING = os.getenv("DEBUGGING", "false").lower() == "true"
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class EnvironmentVariables:
|
|
24
|
+
"""
|
|
25
|
+
Centralized access to environment variables used throughout the application.
|
|
26
|
+
|
|
27
|
+
This class provides static methods to access environment variables in a consistent manner,
|
|
28
|
+
with proper typing and default values where appropriate. Using this class instead of direct
|
|
29
|
+
os.getenv calls helps track and manage all environment variables in one place, making
|
|
30
|
+
maintenance and documentation easier.
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
@staticmethod
|
|
34
|
+
def get_aws_region() -> Optional[str]:
|
|
35
|
+
"""
|
|
36
|
+
Get the AWS region from environment variables.
|
|
37
|
+
|
|
38
|
+
Returns:
|
|
39
|
+
The AWS region as a string, or None if not set.
|
|
40
|
+
"""
|
|
41
|
+
value = os.getenv("AWS_REGION")
|
|
42
|
+
return value
|
|
43
|
+
|
|
44
|
+
@staticmethod
|
|
45
|
+
def get_aws_profile() -> Optional[str]:
|
|
46
|
+
"""
|
|
47
|
+
Get the AWS profile used for CLI/boto3 commands.
|
|
48
|
+
|
|
49
|
+
This should only be set with temporary credentials and only for development purposes.
|
|
50
|
+
|
|
51
|
+
Returns:
|
|
52
|
+
The AWS profile name as a string, or None if not set.
|
|
53
|
+
"""
|
|
54
|
+
value = os.getenv("AWS_PROFILE")
|
|
55
|
+
return value
|
|
56
|
+
|
|
57
|
+
@staticmethod
|
|
58
|
+
def get_aws_account_id() -> Optional[str]:
|
|
59
|
+
"""
|
|
60
|
+
Get the AWS account ID from environment variables.
|
|
61
|
+
|
|
62
|
+
Returns:
|
|
63
|
+
The AWS account ID as a string, or None if not set.
|
|
64
|
+
"""
|
|
65
|
+
value = os.getenv("AWS_ACCOUNT_ID")
|
|
66
|
+
return value
|
|
67
|
+
|
|
68
|
+
@staticmethod
|
|
69
|
+
def get_auth_target_validation_level() -> Optional[str]:
|
|
70
|
+
"""
|
|
71
|
+
Get the authentication target validation level from environment variables.
|
|
72
|
+
|
|
73
|
+
Validation levels:
|
|
74
|
+
PASS_THROUGH: Allows the logged in user to be listed as the target
|
|
75
|
+
if the target user isn't explicitly listed. This provides backward compatibility
|
|
76
|
+
during conversion from short URLs to more detailed URL routes.
|
|
77
|
+
|
|
78
|
+
STRICT: Requires a target user/tenant to be explicitly specified in the path.
|
|
79
|
+
This will be required for all new endpoints. The endpoints have been created
|
|
80
|
+
but some UI and tests have not been updated yet.
|
|
81
|
+
|
|
82
|
+
Returns:
|
|
83
|
+
The validation level as a string ("PASS_THROUGH" or "STRICT"), or None if not set.
|
|
84
|
+
"""
|
|
85
|
+
value = os.getenv("AUTH_TARGET_VALIDATION_LEVEL")
|
|
86
|
+
return value
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
@staticmethod
|
|
91
|
+
def get_logging_level(default: str = "INFO") -> str:
|
|
92
|
+
"""
|
|
93
|
+
Get the logging level from environment variables.
|
|
94
|
+
|
|
95
|
+
Args:
|
|
96
|
+
default: Default logging level to use if not set in environment (default: "INFO").
|
|
97
|
+
|
|
98
|
+
Returns:
|
|
99
|
+
The logging level as a string.
|
|
100
|
+
"""
|
|
101
|
+
value = os.getenv("LOG_LEVEL", default)
|
|
102
|
+
return value
|
|
103
|
+
|
|
104
|
+
@staticmethod
|
|
105
|
+
def get_app_domain():
|
|
106
|
+
"""
|
|
107
|
+
gets the app domain name from an environment var
|
|
108
|
+
"""
|
|
109
|
+
value = os.getenv("APP_DOMAIN")
|
|
110
|
+
return value
|
|
111
|
+
|
|
112
|
+
@staticmethod
|
|
113
|
+
def get_ses_user_name():
|
|
114
|
+
"""
|
|
115
|
+
gets the ses user-name from an environment var
|
|
116
|
+
"""
|
|
117
|
+
value = os.getenv("SES_USER_NAME")
|
|
118
|
+
return value
|
|
119
|
+
|
|
120
|
+
@staticmethod
|
|
121
|
+
def get_ses_password():
|
|
122
|
+
"""
|
|
123
|
+
gets the ses password from an environment var
|
|
124
|
+
"""
|
|
125
|
+
value = os.getenv("SES_PASSWORD")
|
|
126
|
+
return value
|
|
127
|
+
|
|
128
|
+
@staticmethod
|
|
129
|
+
def get_ses_endpoint():
|
|
130
|
+
"""
|
|
131
|
+
gets the ses endpoint from an environment var
|
|
132
|
+
"""
|
|
133
|
+
value = os.getenv("SES_END_POINT")
|
|
134
|
+
return value
|
|
135
|
+
|
|
136
|
+
@staticmethod
|
|
137
|
+
def get_cognito_user_pool() -> str | None:
|
|
138
|
+
"""
|
|
139
|
+
gets the cognito user pool from an environment var
|
|
140
|
+
"""
|
|
141
|
+
value = os.getenv("COGNITO_USER_POOL")
|
|
142
|
+
return value
|
|
143
|
+
|
|
144
|
+
@staticmethod
|
|
145
|
+
def get_dynamodb_table_name():
|
|
146
|
+
"""
|
|
147
|
+
gets the dynamodb table name from an environment var
|
|
148
|
+
"""
|
|
149
|
+
value = os.getenv("APPLICATION_TABLE_NAME")
|
|
150
|
+
return value
|
|
151
|
+
|
|
152
|
+
@staticmethod
|
|
153
|
+
def get_dynamodb_raise_on_error_setting() -> bool:
|
|
154
|
+
"""
|
|
155
|
+
gets the dynamodb table name from an environment var
|
|
156
|
+
"""
|
|
157
|
+
value = str(os.getenv("RAISE_ON_DB_ERROR", "true")).lower() == "true"
|
|
158
|
+
|
|
159
|
+
return value
|
|
160
|
+
|
|
161
|
+
@staticmethod
|
|
162
|
+
def get_tenant_user_file_bucket_name():
|
|
163
|
+
"""
|
|
164
|
+
gets the tenant user file bucket name from an environment var
|
|
165
|
+
"""
|
|
166
|
+
value = os.getenv("TENANT_USER_FILE_BUCKET")
|
|
167
|
+
return value
|
|
168
|
+
|
|
169
|
+
@staticmethod
|
|
170
|
+
def get_tenant_user_upload_bucket_name():
|
|
171
|
+
"""
|
|
172
|
+
gets the tenant user upload bucket name from an environment var
|
|
173
|
+
"""
|
|
174
|
+
value = os.getenv("UPLOAD_BUCKET")
|
|
175
|
+
return value
|
|
176
|
+
|
|
177
|
+
@staticmethod
|
|
178
|
+
def get_lambda_function_to_invoke() -> str | None:
|
|
179
|
+
"""
|
|
180
|
+
gets the lambda function to invoke from an environment var
|
|
181
|
+
this is used by sync to async lambda invocation, or by the queue
|
|
182
|
+
"""
|
|
183
|
+
value = os.getenv("LAMBDA_FUNCTION_TO_INVOKE")
|
|
184
|
+
return value
|
|
185
|
+
|
|
186
|
+
@staticmethod
|
|
187
|
+
def get_amazon_trace_id():
|
|
188
|
+
"""
|
|
189
|
+
gets the amazon trace id from an environment var
|
|
190
|
+
"""
|
|
191
|
+
value = os.getenv("_X_AMZN_TRACE_ID", "NA")
|
|
192
|
+
return value
|
|
193
|
+
|
|
194
|
+
@staticmethod
|
|
195
|
+
def get_integration_tests_setting() -> bool:
|
|
196
|
+
"""
|
|
197
|
+
determine if integration tests are run from an environment var
|
|
198
|
+
"""
|
|
199
|
+
value = str(os.getenv("RUN_INTEGRATION_TESTS", "False")).lower() == "true"
|
|
200
|
+
env = EnvironmentVariables.get_environment_setting()
|
|
201
|
+
|
|
202
|
+
if env.lower().startswith("prod"):
|
|
203
|
+
value = False
|
|
204
|
+
|
|
205
|
+
return value
|
|
206
|
+
|
|
207
|
+
@staticmethod
|
|
208
|
+
def get_environment_setting() -> str:
|
|
209
|
+
"""
|
|
210
|
+
gets the environment name from an environment var
|
|
211
|
+
"""
|
|
212
|
+
value = os.getenv("ENVIRONMENT") or os.getenv("ENVIRONMENT_NAME")
|
|
213
|
+
|
|
214
|
+
if not value:
|
|
215
|
+
logger.warning(
|
|
216
|
+
"ENVIRONMENT var is not set. A future version will throw an error."
|
|
217
|
+
)
|
|
218
|
+
return ""
|
|
219
|
+
|
|
220
|
+
return value
|
|
221
|
+
|
|
222
|
+
@staticmethod
|
|
223
|
+
def is_development_environment() -> bool:
|
|
224
|
+
"""
|
|
225
|
+
determine if the environment is development
|
|
226
|
+
"""
|
|
227
|
+
env = EnvironmentVariables.get_environment_setting()
|
|
228
|
+
return env.lower().startswith("dev")
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
from geek_cafe_saas_sdk.utilities.lambda_event_utility import LambdaEventUtility
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class HttpBodyParameters:
|
|
5
|
+
"""Search Http QueryString Parameters"""
|
|
6
|
+
|
|
7
|
+
def start_date(self, event: dict) -> str | None:
|
|
8
|
+
"""A start date path parameter (start-date)"""
|
|
9
|
+
return self.find(event, "start-date")
|
|
10
|
+
|
|
11
|
+
def end_date(self, event: dict) -> str | None:
|
|
12
|
+
"""An end date path parameter (end-date)"""
|
|
13
|
+
return self.find(event, "end-date")
|
|
14
|
+
|
|
15
|
+
def user_id(self, event: dict) -> str | None:
|
|
16
|
+
"""The userId path parameter (user-id)"""
|
|
17
|
+
return self.find(event, "user-id")
|
|
18
|
+
|
|
19
|
+
def status(self, event: dict) -> str | None:
|
|
20
|
+
"""The status parameter"""
|
|
21
|
+
return self.find(event, "status")
|
|
22
|
+
|
|
23
|
+
def type(self, event: dict) -> str | None:
|
|
24
|
+
"""The type parameter"""
|
|
25
|
+
return self.find(event, "type")
|
|
26
|
+
|
|
27
|
+
def file_id(self, event: dict) -> str | None:
|
|
28
|
+
"""The file id parameter"""
|
|
29
|
+
return self.find(event, "file-id")
|
|
30
|
+
|
|
31
|
+
def tenant_id(self, event: dict) -> str | None:
|
|
32
|
+
"""The tenant id parameter"""
|
|
33
|
+
return self.find(event, "tenant-id")
|
|
34
|
+
|
|
35
|
+
def subscription_id(self, event: dict) -> str | None:
|
|
36
|
+
"""The subscription id parameter"""
|
|
37
|
+
return self.find(event, "subscription-id")
|
|
38
|
+
|
|
39
|
+
def find(self, event: dict, key: str) -> str | None:
|
|
40
|
+
"""Generic Search/Find a key in the path parameters"""
|
|
41
|
+
value = LambdaEventUtility.get_value_from_event(event, key)
|
|
42
|
+
if isinstance(value, str):
|
|
43
|
+
return value
|
|
44
|
+
return None
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Geek Cafe SaaS Services Http Path Parameters
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
from .lambda_event_utility import LambdaEventUtility
|
|
7
|
+
|
|
8
|
+
DEFAULT_RESPONSE_LIMIT = os.getenv("DEFAULT_RESPONSE_LIMIT")
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class HttpPathParameters:
|
|
12
|
+
"""Search Http Path Parameters"""
|
|
13
|
+
|
|
14
|
+
def start_date(self, event: dict) -> str | None:
|
|
15
|
+
"""A start date path parameter (start-date)"""
|
|
16
|
+
return self.find(event, "start-date")
|
|
17
|
+
|
|
18
|
+
def end_date(self, event: dict) -> str | None:
|
|
19
|
+
"""An end date path parameter (end-date)"""
|
|
20
|
+
return self.find(event, "end-date")
|
|
21
|
+
|
|
22
|
+
def user_id(self, event: dict) -> str | None:
|
|
23
|
+
"""The userId path parameter (user-id)"""
|
|
24
|
+
return self.find(event, "user-id")
|
|
25
|
+
|
|
26
|
+
def status(self, event: dict) -> str | None:
|
|
27
|
+
"""The status parameter"""
|
|
28
|
+
return self.find(event, "status")
|
|
29
|
+
|
|
30
|
+
def file_id(self, event: dict) -> str | None:
|
|
31
|
+
"""The file id parameter"""
|
|
32
|
+
return self.find(event, "file-id")
|
|
33
|
+
|
|
34
|
+
def tenant_id(self, event: dict) -> str | None:
|
|
35
|
+
"""The tenant id parameter"""
|
|
36
|
+
return self.find(event, "tenant-id")
|
|
37
|
+
|
|
38
|
+
def subscription_id(self, event: dict) -> str | None:
|
|
39
|
+
"""The subscription id parameter"""
|
|
40
|
+
return self.find(event, "subscription-id")
|
|
41
|
+
|
|
42
|
+
def find(self, event: dict, key: str) -> str | None:
|
|
43
|
+
"""Generic Search/Find a key in the path parameters"""
|
|
44
|
+
value = LambdaEventUtility.get_value_from_path_parameters(event, key)
|
|
45
|
+
if isinstance(value, str):
|
|
46
|
+
return value
|
|
47
|
+
return None
|
|
48
|
+
|
|
49
|
+
def limit(self, event: dict) -> int | None:
|
|
50
|
+
"""
|
|
51
|
+
Returns the limit if any. Used for response limits on datasets
|
|
52
|
+
responses from DynamoDB
|
|
53
|
+
"""
|
|
54
|
+
value = self.find(event, "limit")
|
|
55
|
+
if isinstance(value, str):
|
|
56
|
+
try:
|
|
57
|
+
return int(value)
|
|
58
|
+
except: # noqa: E722, pylint: disable=w0702
|
|
59
|
+
pass
|
|
60
|
+
return None
|