#!/usr/bin/env bash # Seed the local instance with the upstream demo school. # # This is what the real deployment's init job does (dof_app_deploy # .../schulcloud-server-init/templates/configmap_file_init.yml.j2): it asks the # management app to load backup/setup/*.json, which ships inside the server # image. Safe to re-run — collections are replaced, not appended to. set -euo pipefail cd "$(dirname "$0")/.." MGMT=http://127.0.0.1:3333/api/management/database COMPOSE=(docker compose) echo "==> waiting for the management app" for _ in $(seq 1 60); do if curl -fsS -o /dev/null "$MGMT/../../docs" 2>/dev/null || curl -fsS -o /dev/null -X POST "$MGMT/sync-indexes" 2>/dev/null; then break fi sleep 5 done echo "==> seeding collections (this takes a minute or two)" curl -fsS --retry 30 --retry-all-errors --retry-delay 10 \ -X POST "$MGMT/seed?with-indexes=true" >/dev/null echo " done" # The legacy file service (course/topic attachments, as opposed to the newer # /api/v3/file API) reads its S3 credentials from a storageproviders document # rather than from the environment, and there is deliberately no seed data for # it. Without this, legacy uploads fail with a provider-not-found error. echo "==> registering MinIO as the legacy storage provider" S3_KEY=$(grep -E '^S3_KEY=' env/shared.env | cut -d= -f2-) SECRET=$(curl -fsS -X POST "$MGMT/encrypt-plain-text" \ -H 'Content-Type: application/json' \ -d "$(printf '{"plainText":"miniouser","key":"%s"}' "$S3_KEY")") "${COMPOSE[@]}" exec -T mongo mongosh schulcloud --quiet --eval " const id = ObjectId('62949a4003839b6162aa566b'); db.storageproviders.replaceOne({ _id: id }, { _id: id, isShared: true, region: 'eu-central-1', type: 'S3', endpointUrl: 'http://minio:9000', accessKeyId: 'miniouser', secretAccessKey: '$SECRET', maxBuckets: 150, freeBuckets: 138, createdAt: new Date(), updatedAt: new Date(), __v: 0, }, { upsert: true }); const r = db.schools.updateMany({}, { \$set: { storageProvider: id } }); print(' schools linked to the provider: ' + r.modifiedCount); " # The demo data is dated 2017-2018, and the v3 endpoints filter on those dates: # a course that has ended shows a student no tasks, and a task whose due date # passed years ago is in neither the open nor the finished list and has dropped # off the course page. The result is a student account that looks empty for # reasons that have nothing to do with whatever is being tested against it. # # So move the stale data into the present. Courses get a term around today. # Homework is shifted by one offset per date cluster, which keeps the relative # order — and so which tasks are past due, the ones carrying the graded # submissions — while landing the newest of them two weeks ago. echo "==> dating the demo data to the present" "${COMPOSE[@]}" exec -T mongo mongosh schulcloud --quiet --eval " const now = new Date(); const courses = db.courses.updateMany({ untilDate: { \$lt: now } }, { \$set: { startDate: new Date(now.getTime() - 180 * 86400000), untilDate: new Date(now.getTime() + 185 * 86400000), } }); print(' courses given a current term: ' + courses.modifiedCount); let moved = 0; for (let pass = 0; pass < 10; pass++) { const cutoff = new Date(Date.now() - 365 * 86400000); const newest = db.homeworks.find({ dueDate: { \$lt: cutoff } }).sort({ dueDate: -1 }).limit(1).toArray()[0]; if (!newest) break; const offset = (Date.now() - 14 * 86400000) - newest.dueDate.getTime(); db.homeworks.find({ dueDate: { \$lt: cutoff } }).forEach((h) => { const set = {}; for (const field of ['dueDate', 'availableDate', 'createdAt', 'updatedAt']) { if (h[field] instanceof Date) set[field] = new Date(h[field].getTime() + offset); } db.homeworks.updateOne({ _id: h._id }, { \$set: set }); moved++; }); } print(' homework brought forward: ' + moved); " cat <<'ACCOUNTS' ==> ready — http://localhost:4400 Seeded accounts (the demo password differs by account — upstream quirk): demo-schueler@schul-cloud.org student Fritz Schmidt schulcloud ^ has graded submissions, incl. a feedback-only and a 100% one demo-lehrer@schul-cloud.org teacher Erika Meier schulcloud klara.fall@schul-cloud.org teacher Klara Fall Schulcloud1! ^ owns Fritz's graded Biologie submissions lehrer@schul-cloud.org teacher Cord Carl Schulcloud1! admin@schul-cloud.org admin Thorsten Test Schulcloud1! *.qa@schul-cloud.org various Schulcloud1qa! Sign in as the teacher to grade, as the student to see what grading looks like from the side our MCP server reads. ACCOUNTS