parse-stack-next 5.5.4 → 5.5.5

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 (99) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -6
  3. data/README.md +26 -13
  4. data/bin/parse-console +9 -1
  5. data/docs/TEST_SERVER.md +115 -238
  6. data/docs/mcp_guide.md +1 -1
  7. data/docs/mongodb_index_optimization_guide.md +3 -2
  8. data/docs/usage_guide.md +1 -1
  9. data/docs/yard-template/default/fulldoc/html/css/common.css +52 -9
  10. data/docs/yard-template/default/fulldoc/html/css/full_list.css +40 -13
  11. data/lib/parse/agent/constraint_translator.rb +18 -18
  12. data/lib/parse/agent/errors.rb +29 -7
  13. data/lib/parse/agent/metadata_dsl.rb +6 -6
  14. data/lib/parse/agent/tools.rb +250 -59
  15. data/lib/parse/agent.rb +42 -30
  16. data/lib/parse/api/aggregate.rb +3 -3
  17. data/lib/parse/api/cloud_functions.rb +19 -10
  18. data/lib/parse/api/objects.rb +8 -8
  19. data/lib/parse/api/users.rb +9 -9
  20. data/lib/parse/atlas_search/session.rb +34 -34
  21. data/lib/parse/atlas_search.rb +243 -110
  22. data/lib/parse/client/body_builder.rb +10 -10
  23. data/lib/parse/client/logging.rb +5 -2
  24. data/lib/parse/client/profiling.rb +5 -2
  25. data/lib/parse/client/protocol.rb +1 -1
  26. data/lib/parse/client/url_redaction.rb +94 -0
  27. data/lib/parse/client.rb +43 -28
  28. data/lib/parse/embeddings/image_fetch.rb +6 -1
  29. data/lib/parse/embeddings/voyage.rb +16 -17
  30. data/lib/parse/live_query/client.rb +7 -7
  31. data/lib/parse/live_query/subscription.rb +1 -1
  32. data/lib/parse/lock.rb +1 -1
  33. data/lib/parse/lock_backend.rb +118 -2
  34. data/lib/parse/model/acl.rb +24 -24
  35. data/lib/parse/model/classes/job_schedule.rb +8 -8
  36. data/lib/parse/model/classes/job_status.rb +9 -9
  37. data/lib/parse/model/classes/role.rb +49 -49
  38. data/lib/parse/model/classes/session.rb +2 -2
  39. data/lib/parse/model/classes/user.rb +66 -66
  40. data/lib/parse/model/core/builder.rb +7 -7
  41. data/lib/parse/model/core/create_lock.rb +1 -1
  42. data/lib/parse/model/core/properties.rb +4 -4
  43. data/lib/parse/model/file.rb +57 -16
  44. data/lib/parse/model/model.rb +19 -19
  45. data/lib/parse/model/object.rb +38 -38
  46. data/lib/parse/model/pointer.rb +4 -4
  47. data/lib/parse/model/push.rb +5 -5
  48. data/lib/parse/mongodb.rb +84 -26
  49. data/lib/parse/pipeline_security.rb +2 -2
  50. data/lib/parse/query/constraints.rb +38 -38
  51. data/lib/parse/query.rb +151 -75
  52. data/lib/parse/retrieval/reranker/cohere.rb +30 -0
  53. data/lib/parse/schema.rb +1 -1
  54. data/lib/parse/stack/version.rb +1 -1
  55. data/lib/parse/stack.rb +23 -10
  56. data/lib/parse/two_factor_auth/user_extension.rb +25 -25
  57. data/lib/parse/webhooks/payload.rb +35 -35
  58. data/lib/parse/webhooks/registration.rb +2 -2
  59. data/lib/parse/webhooks/replay_protection.rb +16 -16
  60. data/lib/parse/webhooks.rb +11 -11
  61. data/parse-stack-next.gemspec +19 -1
  62. metadata +2 -38
  63. data/.bundle/config +0 -5
  64. data/.env.sample +0 -138
  65. data/.env.test +0 -10
  66. data/.github/ISSUE_TEMPLATE/bug_report.yml +0 -105
  67. data/.github/ISSUE_TEMPLATE/feature_request.yml +0 -67
  68. data/.github/dependabot.yml +0 -13
  69. data/.github/workflows/codeql.yml +0 -44
  70. data/.github/workflows/docs.yml +0 -39
  71. data/.github/workflows/release.yml +0 -43
  72. data/.github/workflows/ruby.yml +0 -38
  73. data/.gitignore +0 -56
  74. data/.ruby-version +0 -1
  75. data/.solargraph.yml +0 -22
  76. data/.vscode/settings.json +0 -3
  77. data/.yardopts +0 -19
  78. data/Gemfile +0 -43
  79. data/Gemfile.lock +0 -198
  80. data/Makefile +0 -63
  81. data/Rakefile +0 -825
  82. data/config/parse-config.json +0 -12
  83. data/scripts/debug-ips.js +0 -35
  84. data/scripts/docker/Dockerfile.parse +0 -17
  85. data/scripts/docker/atlas-init.js +0 -284
  86. data/scripts/docker/docker-compose.atlas.yml +0 -80
  87. data/scripts/docker/docker-compose.test.yml +0 -159
  88. data/scripts/docker/docker-compose.verifyemail.yml +0 -4
  89. data/scripts/docker/mongo-init.js +0 -21
  90. data/scripts/docker/preflight.sh +0 -76
  91. data/scripts/eval_mcp_with_lm_studio.rb +0 -274
  92. data/scripts/start-parse.sh +0 -154
  93. data/scripts/start_mcp_server.rb +0 -78
  94. data/scripts/test_server_connection.rb +0 -82
  95. data/scripts/vector_prototype/create_vector_index.js +0 -105
  96. data/scripts/vector_prototype/fetch_embeddings.py +0 -241
  97. data/scripts/vector_prototype/fixture_manifest.json +0 -9
  98. data/scripts/vector_prototype/query_prototype.rb +0 -84
  99. data/scripts/vector_prototype/run.sh +0 -34
@@ -1,12 +0,0 @@
1
- {
2
- "appId": "myAppId",
3
- "masterKey": "myMasterKey",
4
- "restAPIKey": "test-rest-key",
5
- "databaseURI": "mongodb://admin:password@mongo:27017/parse?authSource=admin",
6
- "serverURL": "http://localhost:1337/parse",
7
- "mountPath": "/parse",
8
- "cloud": "/parse-server/cloud/main.js",
9
- "logLevel": "info",
10
- "allowClientClassCreation": true,
11
- "allowCustomObjectId": true
12
- }
data/scripts/debug-ips.js DELETED
@@ -1,35 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- // Debug script to check Parse Server IP configuration
4
- console.log('=== Parse Server IP Debug ===');
5
- console.log('Environment variables:');
6
- console.log('PARSE_SERVER_MASTER_KEY_IPS:', process.env.PARSE_SERVER_MASTER_KEY_IPS);
7
-
8
- // Try to load the config file
9
- try {
10
- const fs = require('fs');
11
- const config = JSON.parse(fs.readFileSync('/parse-server/config/parse-config.json', 'utf8'));
12
- console.log('\nConfig file masterKeyIps:', config.masterKeyIps);
13
- } catch (e) {
14
- console.log('\nConfig file error:', e.message);
15
- }
16
-
17
- // Check what Parse Server would use as default
18
- const defaultIps = ['127.0.0.1', '::1'];
19
- console.log('\nDefault masterKeyIps:', defaultIps);
20
-
21
- // Test IP parsing
22
- const envIps = process.env.PARSE_SERVER_MASTER_KEY_IPS;
23
- if (envIps) {
24
- const parsedIps = envIps.split(',');
25
- console.log('\nParsed environment IPs:', parsedIps);
26
-
27
- const net = require('net');
28
- parsedIps.forEach(ip => {
29
- const cleanIp = ip.includes('/') ? ip.split('/')[0] : ip;
30
- console.log(`IP "${ip}" -> clean: "${cleanIp}" -> isIP: ${net.isIP(cleanIp)}`);
31
- });
32
- }
33
-
34
- console.log('\nRequest IP that Parse Server sees: (this would be logged in Parse Server)');
35
- console.log('Expected request IP: 172.18.0.1 (Docker container network)');
@@ -1,17 +0,0 @@
1
- # Pinned to a specific patch release (was the floating `:9` tag, which had
2
- # cached to a pre-patch 8.4.0 build). 9.9.0 includes the MFA / authData security
3
- # fixes — GHSA-pfj7-wv7c-22pr (auth-provider validation bypass on login) and
4
- # GHSA-37mj-c2wf-cx96 / CVE-2026-33627 (TOTP secret leak via /users/me).
5
- FROM parseplatform/parse-server:9.9.0
6
-
7
- # Switch to root to copy and set permissions
8
- USER root
9
-
10
- # Copy our custom startup script with execute permissions
11
- COPY --chmod=755 start-parse.sh /start-parse.sh
12
-
13
- # Switch back to node user (if needed)
14
- USER node
15
-
16
- # Set the entrypoint to our script
17
- ENTRYPOINT ["/bin/sh", "/start-parse.sh"]
@@ -1,284 +0,0 @@
1
- // Atlas Local initialization script for Atlas Search integration tests
2
- // This script runs after the Atlas Local container is ready
3
- // It seeds test data and creates the Atlas Search index
4
- //
5
- // TEST-FIXTURE BANNER (ATLAS-9):
6
- // The seed data below uses `_rperm: ["U1"]` to exercise the SDK's
7
- // ACL injection layer (see `Parse::ACLScope` and the ACL `$match`
8
- // stage Parse::AtlasSearch.search builds). "U1" is a literal Parse
9
- // objectId string chosen for test convenience — it is NOT a
10
- // pattern any production deployment should use.
11
- //
12
- // In Parse Server, `_rperm` entries are either the special public
13
- // token "*", a role token like "role:Admin", or a real Parse User
14
- // objectId (24-char Mongo-style id). The seed rows here ship with
15
- // "U1" because the SDK unit/integration tests stub a Session that
16
- // reports `user_id == "U1"`, and the test assertions are easier
17
- // to read when the perm string matches the test fixture's user_id.
18
- //
19
- // Do NOT copy this fixture pattern into production seeds, schema
20
- // migrations, or examples — a real `_rperm` entry must be a real
21
- // Parse User objectId. Treat this file as test-only.
22
-
23
- print("=== Atlas Search Test Setup ===");
24
- print("Database: " + db.getName());
25
-
26
- // Clear existing data
27
- print("\n1. Clearing existing data...");
28
- db.Song.drop();
29
-
30
- // Insert test data
31
- print("\n2. Inserting test song data...");
32
- const songs = [
33
- {
34
- _id: "song1",
35
- title: "Love Story",
36
- artist: "Taylor Swift",
37
- genre: "Pop",
38
- plays: 5000000,
39
- _created_at: new Date(),
40
- _updated_at: new Date()
41
- },
42
- {
43
- _id: "song2",
44
- title: "Lovely Day",
45
- artist: "Bill Withers",
46
- genre: "Soul",
47
- plays: 3000000,
48
- _created_at: new Date(),
49
- _updated_at: new Date()
50
- },
51
- {
52
- _id: "song3",
53
- title: "Bohemian Rhapsody",
54
- artist: "Queen",
55
- genre: "Rock",
56
- plays: 10000000,
57
- _created_at: new Date(),
58
- _updated_at: new Date()
59
- },
60
- {
61
- _id: "song4",
62
- title: "Rock and Roll",
63
- artist: "Led Zeppelin",
64
- genre: "Rock",
65
- plays: 4000000,
66
- _created_at: new Date(),
67
- _updated_at: new Date()
68
- },
69
- {
70
- _id: "song5",
71
- title: "What Is Love",
72
- artist: "Haddaway",
73
- genre: "Dance",
74
- plays: 2500000,
75
- _created_at: new Date(),
76
- _updated_at: new Date()
77
- },
78
- {
79
- _id: "song6",
80
- title: "I Will Always Love You",
81
- artist: "Whitney Houston",
82
- genre: "Pop",
83
- plays: 8000000,
84
- _created_at: new Date(),
85
- _updated_at: new Date()
86
- },
87
- {
88
- _id: "song7",
89
- title: "Crazy Little Thing Called Love",
90
- artist: "Queen",
91
- genre: "Rock",
92
- plays: 3500000,
93
- _created_at: new Date(),
94
- _updated_at: new Date()
95
- },
96
- {
97
- _id: "song8",
98
- title: "Shape of You",
99
- artist: "Ed Sheeran",
100
- genre: "Pop",
101
- plays: 12000000,
102
- _created_at: new Date(),
103
- _updated_at: new Date()
104
- },
105
- // Songs 9-11 exercise the ACL injection path of the Atlas Search
106
- // integration tests. They omit _rperm (public — matched by the
107
- // $exists: false branch of the ACL predicate), include a role-
108
- // restricted _rperm, and include an owner-restricted _rperm.
109
- // The Atlas Search ACL integration test asserts which sessions
110
- // see which subset of these rows.
111
- {
112
- _id: "song9",
113
- title: "Restricted Anthem",
114
- artist: "Member Band",
115
- genre: "Rock",
116
- plays: 1500000,
117
- _rperm: ["role:Member"],
118
- _wperm: ["role:Admin"],
119
- _created_at: new Date(),
120
- _updated_at: new Date()
121
- },
122
- {
123
- _id: "song10",
124
- title: "Owner Only Ballad",
125
- artist: "U1 Personal",
126
- genre: "Acoustic",
127
- plays: 100,
128
- _rperm: ["U1"],
129
- _wperm: ["U1"],
130
- _created_at: new Date(),
131
- _updated_at: new Date()
132
- },
133
- {
134
- _id: "song11",
135
- title: "Master Key Vault Track",
136
- artist: "Locked Down",
137
- genre: "Vault",
138
- plays: 0,
139
- _rperm: [],
140
- _wperm: [],
141
- _created_at: new Date(),
142
- _updated_at: new Date()
143
- }
144
- ];
145
-
146
- db.Song.insertMany(songs);
147
- print("Inserted " + db.Song.countDocuments() + " songs (8 public, 1 role-restricted, 1 owner-restricted, 1 master-only)");
148
-
149
- // Create Atlas Search index
150
- print("\n3. Creating Atlas Search index...");
151
-
152
- // Drop existing search indexes first
153
- try {
154
- const existingIndexes = db.Song.getSearchIndexes();
155
- existingIndexes.forEach(function(idx) {
156
- print("Dropping existing index: " + idx.name);
157
- db.Song.dropSearchIndex(idx.name);
158
- });
159
- } catch (e) {
160
- print("No existing search indexes to drop (or error checking): " + e.message);
161
- }
162
-
163
- // Wait a moment for any dropped indexes to be fully removed
164
- sleep(1000);
165
-
166
- // Create the search index with autocomplete support
167
- const indexDefinition = {
168
- mappings: {
169
- dynamic: true,
170
- fields: {
171
- title: [
172
- {
173
- type: "string",
174
- analyzer: "lucene.standard"
175
- },
176
- {
177
- type: "autocomplete",
178
- analyzer: "lucene.standard",
179
- tokenization: "edgeGram",
180
- minGrams: 2,
181
- maxGrams: 15,
182
- foldDiacritics: true
183
- }
184
- ],
185
- artist: {
186
- type: "string",
187
- analyzer: "lucene.standard"
188
- },
189
- genre: [
190
- {
191
- type: "string",
192
- analyzer: "lucene.standard"
193
- },
194
- {
195
- type: "stringFacet"
196
- }
197
- ],
198
- plays: [
199
- {
200
- type: "number"
201
- },
202
- {
203
- type: "numberFacet"
204
- }
205
- ]
206
- }
207
- }
208
- };
209
-
210
- try {
211
- db.Song.createSearchIndex("default", indexDefinition);
212
- print("Search index 'default' created successfully");
213
- } catch (e) {
214
- print("Error creating search index: " + e.message);
215
- // Try alternative method
216
- try {
217
- db.runCommand({
218
- createSearchIndexes: "Song",
219
- indexes: [{ name: "default", definition: indexDefinition }]
220
- });
221
- print("Search index created via runCommand");
222
- } catch (e2) {
223
- print("Alternative method also failed: " + e2.message);
224
- }
225
- }
226
-
227
- // Wait for index to become queryable
228
- print("\n4. Waiting for index to become ready...");
229
- let attempts = 0;
230
- const maxAttempts = 30;
231
- let indexReady = false;
232
-
233
- while (attempts < maxAttempts && !indexReady) {
234
- try {
235
- const indexes = db.Song.getSearchIndexes();
236
- const defaultIndex = indexes.find(idx => idx.name === "default");
237
- if (defaultIndex && defaultIndex.queryable === true) {
238
- indexReady = true;
239
- print("Index is ready and queryable!");
240
- } else {
241
- print("Waiting for index... (attempt " + (attempts + 1) + "/" + maxAttempts + ")");
242
- sleep(2000);
243
- }
244
- } catch (e) {
245
- print("Error checking index status: " + e.message);
246
- sleep(2000);
247
- }
248
- attempts++;
249
- }
250
-
251
- if (!indexReady) {
252
- print("WARNING: Index may not be ready yet. Tests might fail initially.");
253
- }
254
-
255
- // Verify setup
256
- print("\n5. Verification:");
257
- print(" Songs in collection: " + db.Song.countDocuments());
258
-
259
- try {
260
- const searchIndexes = db.Song.getSearchIndexes();
261
- print(" Search indexes: " + searchIndexes.length);
262
- searchIndexes.forEach(function(idx) {
263
- print(" - " + idx.name + " (queryable: " + idx.queryable + ")");
264
- });
265
- } catch (e) {
266
- print(" Could not list search indexes: " + e.message);
267
- }
268
-
269
- // Test a simple search to verify it works
270
- print("\n6. Testing search...");
271
- try {
272
- const testResult = db.Song.aggregate([
273
- { $search: { index: "default", text: { query: "love", path: { wildcard: "*" } } } },
274
- { $limit: 3 }
275
- ]).toArray();
276
- print(" Test search found " + testResult.length + " results for 'love'");
277
- if (testResult.length > 0) {
278
- print(" First result: " + testResult[0].title + " by " + testResult[0].artist);
279
- }
280
- } catch (e) {
281
- print(" Search test failed (index may still be building): " + e.message);
282
- }
283
-
284
- print("\n=== Atlas Search Setup Complete ===\n");
@@ -1,80 +0,0 @@
1
- # Docker Compose configuration for Atlas Search integration tests
2
- # Uses the official mongodb/mongodb-atlas-local image which supports Atlas Search
3
- #
4
- # Usage:
5
- # Start: docker-compose -f scripts/docker/docker-compose.atlas.yml up -d
6
- # Stop: docker-compose -f scripts/docker/docker-compose.atlas.yml down
7
- # Logs: docker-compose -f scripts/docker/docker-compose.atlas.yml logs -f atlas-init
8
- # Reset: docker-compose -f scripts/docker/docker-compose.atlas.yml down -v && docker-compose -f scripts/docker/docker-compose.atlas.yml up -d
9
- #
10
- # Run tests:
11
- # ATLAS_URI="mongodb://localhost:29020/parse_atlas_test?directConnection=true" ruby -Ilib:test test/lib/parse/atlas_search_integration_test.rb
12
- #
13
- # Stability notes (see commit history for context):
14
- # The mongodb-atlas-local image runs a supervisor ("runner") that intentionally
15
- # restarts mongod 1-2 times during startup to enable the replica set and wire
16
- # in mongot (Atlas Search). Those startup SIGTERMs are NORMAL and visible in
17
- # `docker logs` — do not interpret them as crashes. The container is "ready"
18
- # when the runner's built-in healthcheck (`runner healthcheck`) reports healthy,
19
- # which checks both mongod AND mongot. We rely on that built-in healthcheck
20
- # rather than overriding it with a faster mongosh probe.
21
-
22
- # Distinct Compose project name — kept separate from the main test stack
23
- # (psnext-it) so `down` on one never tears down the other.
24
- name: ${PSNEXT_PREFIX:-psnext-it}-atlas
25
-
26
- services:
27
- atlas-local:
28
- # Pinned patch tag rather than the floating :8.0 — mongodb-atlas-local has
29
- # known per-patch start-up flakiness (see testcontainers/testcontainers-java#10267
30
- # and MongoDB community forum 321179). Bump deliberately, not by drift.
31
- image: mongodb/mongodb-atlas-local:8.0.10
32
- container_name: ${PSNEXT_PREFIX:-psnext-it}-atlas
33
- # `hostname` is called out by the official compose example — the embedded
34
- # single-node replica set advertises this name, and a stable value makes
35
- # restart-after-down work cleanly.
36
- hostname: atlas-local
37
- # Surface runner + mongot logs through `docker logs` so failures during the
38
- # supervisor's bring-up phase are visible. Pure visibility, no behavior change.
39
- environment:
40
- RUNNER_LOG_FILE: /dev/stderr
41
- MONGOT_LOG_FILE: /dev/stderr
42
- # Loopback-only by default — Atlas Local has no auth configured.
43
- ports:
44
- - "${ATLAS_BIND:-127.0.0.1}:${ATLAS_HOST_PORT:-29020}:27017"
45
- volumes:
46
- # Persist mongod data, replset config, and — critically — the mongot
47
- # Lucene index directory. Without /data/mongot persistence, every restart
48
- # forces a full search re-index, which lengthens "ready" time and is a
49
- # real source of test flakiness. Matches the official compose example.
50
- - psnext-it-atlas-data:/data/db
51
- - psnext-it-atlas-configdb:/data/configdb
52
- - psnext-it-atlas-mongot:/data/mongot
53
- # Recover from genuine crashes automatically. Test runs `docker compose down`
54
- # explicitly, so this does not interfere with teardown.
55
- restart: unless-stopped
56
- # NOTE: We deliberately do NOT override `healthcheck:` here. The image ships
57
- # a built-in `runner healthcheck` (interval 30s, timeout 60s, start_period
58
- # 60s, retries 3) that verifies BOTH mongod and mongot are ready. The
59
- # previous mongosh ping at 5s interval was both noisier (spawns a mongosh
60
- # process every 5s) and incorrect (it returned healthy as soon as mongod
61
- # accepted connections, before mongot was wired in, so atlas-init could
62
- # race the search-index subsystem).
63
-
64
- atlas-init:
65
- image: mongodb/mongodb-atlas-local:8.0.10
66
- container_name: ${PSNEXT_PREFIX:-psnext-it}-atlas-init
67
- depends_on:
68
- atlas-local:
69
- # Uses the image's built-in healthcheck (see above), so this now waits
70
- # for mongot readiness too — not just mongod accepting connections.
71
- condition: service_healthy
72
- volumes:
73
- - ./atlas-init.js:/atlas-init.js:ro
74
- entrypoint: ["mongosh", "--quiet", "mongodb://atlas-local:27017/parse_atlas_test", "/atlas-init.js"]
75
- restart: "no"
76
-
77
- volumes:
78
- psnext-it-atlas-data:
79
- psnext-it-atlas-configdb:
80
- psnext-it-atlas-mongot:
@@ -1,159 +0,0 @@
1
- version: '3.8'
2
-
3
- # Distinct Compose project name so this stack never shares containers,
4
- # networks, or volumes with another Parse test system on the same host.
5
- name: ${PSNEXT_PREFIX:-psnext-it}
6
-
7
- services:
8
- # Security preflight — TEST STACK ONLY. Runs to completion before any
9
- # real service starts (each gates on it via
10
- # `service_completed_successfully`). Fails the stack closed when a
11
- # `*_BIND` override would expose the stack on the LAN while privileged
12
- # credentials are still the committed defaults. Invisible to the normal
13
- # loopback run. See scripts/docker/preflight.sh for the rationale and
14
- # escape hatches (ALLOW_INSECURE_BIND=1, or set real credentials).
15
- preflight:
16
- image: busybox:1.36
17
- container_name: ${PSNEXT_PREFIX:-psnext-it}-preflight
18
- environment:
19
- # Resolved binds (compose applies the 127.0.0.1 default here).
20
- PARSE_BIND: ${PARSE_BIND:-127.0.0.1}
21
- MONGO_BIND: ${MONGO_BIND:-127.0.0.1}
22
- REDIS_BIND: ${REDIS_BIND:-127.0.0.1}
23
- DASHBOARD_BIND: ${DASHBOARD_BIND:-127.0.0.1}
24
- # "1" only when the operator supplied a non-empty override; empty
25
- # means the committed default credential is still in force.
26
- PARSE_MASTER_KEY_SET: ${PARSE_MASTER_KEY:+1}
27
- MONGO_ROOT_PASSWORD_SET: ${MONGO_ROOT_PASSWORD:+1}
28
- ALLOW_INSECURE_BIND: ${ALLOW_INSECURE_BIND:-}
29
- volumes:
30
- - ./preflight.sh:/preflight.sh:ro
31
- command: ["sh", "/preflight.sh"]
32
-
33
- mongo:
34
- image: mongo:8
35
- container_name: ${PSNEXT_PREFIX:-psnext-it}-mongo
36
- depends_on:
37
- preflight:
38
- condition: service_completed_successfully
39
- # Bind to loopback so the test database isn't reachable from the LAN
40
- # when a developer runs `docker-compose up`. Override with
41
- # `MONGO_BIND=0.0.0.0` if you really want it exposed.
42
- ports:
43
- - "${MONGO_BIND:-127.0.0.1}:${MONGO_HOST_PORT:-29017}:27017"
44
- environment:
45
- MONGO_INITDB_ROOT_USERNAME: ${MONGO_ROOT_USER:-admin}
46
- MONGO_INITDB_ROOT_PASSWORD: ${MONGO_ROOT_PASSWORD:-password}
47
- MONGO_INITDB_DATABASE: admin
48
- volumes:
49
- - psnext-it-mongo-data:/data/db
50
- - ./mongo-init.js:/docker-entrypoint-initdb.d/mongo-init.js:ro
51
-
52
- parse:
53
- build:
54
- context: ..
55
- dockerfile: docker/Dockerfile.parse
56
- container_name: ${PSNEXT_PREFIX:-psnext-it}-server
57
- # Bind to loopback by default — Parse Server with the test master key
58
- # has no business being reachable on a developer's LAN.
59
- ports:
60
- - "${PARSE_BIND:-127.0.0.1}:${PARSE_HOST_PORT:-29337}:1337"
61
- # `host.docker.internal` is needed so Parse Server can POST to the
62
- # in-process WEBrick that backs webhook integration tests. Docker
63
- # Desktop on Mac/Windows resolves this natively; on Linux we map it
64
- # to host-gateway. Without this, end-to-end webhook tests are skipped.
65
- extra_hosts:
66
- - "host.docker.internal:host-gateway"
67
- depends_on:
68
- mongo:
69
- condition: service_started
70
- volumes:
71
- - ../../test/cloud:/parse-server/cloud
72
- - ../../config:/parse-server/config
73
- - ../start-parse.sh:/start-parse.sh:ro
74
- environment:
75
- # Application id / master key / database URI are provided to the
76
- # container so `start-parse.sh` doesn't have to invent fallbacks.
77
- # `start-parse.sh` will abort if any of these is unset, so any
78
- # name drift here surfaces immediately rather than booting Parse
79
- # Server with whatever placeholder default the SDK README documents.
80
- PARSE_SERVER_APPLICATION_ID: ${PARSE_APP_ID:-psnextItAppId}
81
- PARSE_SERVER_MASTER_KEY: ${PARSE_MASTER_KEY:-psnextItMasterKey}
82
- PARSE_SERVER_REST_API_KEY: ${PARSE_API_KEY:-psnext-it-rest-key}
83
- PARSE_SERVER_DATABASE_URI: mongodb://${MONGO_ROOT_USER:-admin}:${MONGO_ROOT_PASSWORD:-password}@mongo:27017/parse_stack_next_it?authSource=admin
84
- # Accept client-supplied objectId on create. Required by the
85
- # `parse_reference precompute: true` DSL. The SDK only forwards
86
- # client objectIds under master-key authority; for non-master
87
- # enforcement across other SDKs, see the Cloud Code hook documented
88
- # in lib/parse/model/core/parse_reference.rb.
89
- PARSE_SERVER_ALLOW_CUSTOM_OBJECT_ID: "true"
90
- # Tests connect from the docker bridge gateway (typically
91
- # 172.16.0.0/12 or 192.168.x.x), not loopback. Widen the master-key
92
- # allowlist accordingly. DO NOT mirror this into a deployed
93
- # environment — production should keep the allowlist tight to the
94
- # subnets that actually host the Ruby app.
95
- PARSE_SERVER_MASTER_KEY_IPS: "127.0.0.1/32,::1/128,172.16.0.0/12,192.168.0.0/16,10.0.0.0/8"
96
- # Round-trip Parse.track_event through a real adapter so the v5.0
97
- # integration test can drain the captured events back. The default
98
- # adapter is a no-op, which would make the integration test
99
- # indistinguishable from the wire-stub regression guard in
100
- # test/lib/parse/track_event_wire_shape_test.rb. See
101
- # test/cloud/analytics-adapter.js for the in-process recorder.
102
- PARSE_SERVER_ANALYTICS_ADAPTER: "/parse-server/cloud/analytics-adapter.js"
103
- # Remove health check for now since it's causing startup delays
104
- # healthcheck:
105
- # test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:1337/parse/health"]
106
- # interval: 10s
107
- # timeout: 5s
108
- # retries: 5
109
- # start_period: 30s
110
-
111
- redis:
112
- image: redis:7-alpine
113
- container_name: ${PSNEXT_PREFIX:-psnext-it}-redis
114
- depends_on:
115
- preflight:
116
- condition: service_completed_successfully
117
- # Loopback-only by default. Used by the cache integration test
118
- # (cache_redis_integration_test.rb) and the synchronize-create lock
119
- # tests. Override with `REDIS_BIND=0.0.0.0` if you need to point a
120
- # remote client at it during debugging.
121
- ports:
122
- - "${REDIS_BIND:-127.0.0.1}:${REDIS_HOST_PORT:-29379}:6379"
123
- command: ["redis-server", "--save", "", "--appendonly", "no"]
124
-
125
- parse-dashboard:
126
- image: parseplatform/parse-dashboard:9
127
- container_name: ${PSNEXT_PREFIX:-psnext-it}-dashboard
128
- # Loopback-only by default. This compose is for `rake test:integration`
129
- # and local debugging; do not expose to the network.
130
- ports:
131
- - "${DASHBOARD_BIND:-127.0.0.1}:${DASHBOARD_HOST_PORT:-29040}:4040"
132
- environment:
133
- # `allowInsecureHTTP` and `useEncryptedPasswords: false` are kept
134
- # because this stack runs over plain HTTP on loopback. Do NOT copy
135
- # these settings to a deployed environment.
136
- PARSE_DASHBOARD_ALLOW_INSECURE_HTTP: "1"
137
- PARSE_SERVER_MASTER_KEY: ${PARSE_MASTER_KEY:-psnextItMasterKey}
138
- PARSE_SERVER_APPLICATION_ID: ${PARSE_APP_ID:-psnextItAppId}
139
- PARSE_SERVER_URL: http://localhost:${PARSE_HOST_PORT:-29337}/parse
140
- PARSE_DASHBOARD_CONFIG: |
141
- {
142
- "apps": [{
143
- "serverURL": "http://localhost:${PARSE_HOST_PORT:-29337}/parse",
144
- "appId": "${PARSE_APP_ID:-psnextItAppId}",
145
- "masterKey": "${PARSE_MASTER_KEY:-psnextItMasterKey}",
146
- "appName": "ParseStackTest"
147
- }],
148
- "users": [{
149
- "user": "${DASHBOARD_USER:-admin}",
150
- "pass": "${DASHBOARD_PASS:-admin}"
151
- }],
152
- "useEncryptedPasswords": false,
153
- "allowInsecureHTTP": true
154
- }
155
- depends_on:
156
- - parse
157
-
158
- volumes:
159
- psnext-it-mongo-data:
@@ -1,4 +0,0 @@
1
- services:
2
- parse:
3
- environment:
4
- PARSE_SERVER_VERIFY_USER_EMAILS: "true"
@@ -1,21 +0,0 @@
1
- // MongoDB initialization script
2
- // This script runs when the MongoDB container is first created
3
- // It grants the admin user access to the parse_stack_next_it database for direct queries
4
-
5
- // The admin user needs readWriteAnyDatabase role to access all databases
6
- db = db.getSiblingDB('admin');
7
-
8
- // Grant admin user roles needed for all database access
9
- db.grantRolesToUser('admin', [
10
- { role: 'readWriteAnyDatabase', db: 'admin' },
11
- { role: 'dbAdminAnyDatabase', db: 'admin' }
12
- ]);
13
-
14
- // Initialize the parse_stack_next_it database
15
- db = db.getSiblingDB('parse_stack_next_it');
16
-
17
- // Create a placeholder collection to ensure the database exists
18
- db.createCollection('_init');
19
- db.getCollection('_init').drop();
20
-
21
- print('MongoDB initialization completed - admin user granted full database access');