forked from Orcpub/orcpub
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdocker-user.sh
More file actions
executable file
·279 lines (234 loc) · 8.01 KB
/
docker-user.sh
File metadata and controls
executable file
·279 lines (234 loc) · 8.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
#!/usr/bin/env bash
#
# OrcPub Docker User Management
#
# Injects and verifies users in the Datomic database running inside Docker.
# Works by executing Clojure code inside the orcpub container, using the
# uberjar classpath (which already has datomic.api and buddy.hashers).
#
# Usage:
# ./docker-user.sh create <username> <email> <password>
# ./docker-user.sh verify <username-or-email>
# ./docker-user.sh check <username-or-email>
# ./docker-user.sh list
#
# The script auto-detects the orcpub container name from docker-compose.
#
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
MANAGE_SCRIPT="${SCRIPT_DIR}/docker/scripts/manage-user.clj"
# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------
color_green='\033[0;32m'
color_red='\033[0;31m'
color_yellow='\033[1;33m'
color_reset='\033[0m'
info() { printf '%s[OK]%s %s\n' "$color_green" "$color_reset" "$*"; }
error() { printf '%s[ERROR]%s %s\n' "$color_red" "$color_reset" "$*" >&2; }
warn() { printf '%s[WARN]%s %s\n' "$color_yellow" "$color_reset" "$*"; }
usage() {
cat <<'USAGE'
OrcPub Docker User Management
Usage:
./docker-user.sh init
Create the initial admin user from INIT_ADMIN_* variables in .env
Safe to run multiple times — duplicates are skipped.
./docker-user.sh create <username> <email> <password>
Create a new user (auto-verified, skips email)
./docker-user.sh batch <file>
Create multiple users from a file (one JVM startup).
File format: one user per line — username email password
Lines starting with # and blank lines are skipped.
Duplicates are logged and skipped (not treated as errors).
./docker-user.sh verify <username-or-email>
Verify an existing unverified user
./docker-user.sh check <username-or-email>
Check if a user exists and show their status
./docker-user.sh list
List all users in the database
Options:
--container <name> Override container name detection
--help Show this help
Examples:
./docker-user.sh init
./docker-user.sh create admin admin@example.com MySecurePass123
./docker-user.sh batch users.txt
./docker-user.sh check admin
./docker-user.sh list
USAGE
}
# ---------------------------------------------------------------------------
# Find the orcpub container
# ---------------------------------------------------------------------------
find_container() {
local container=""
# Try docker-compose/docker compose service name first
if command -v docker-compose &>/dev/null; then
container=$(docker-compose ps -q orcpub 2>/dev/null || true)
fi
if [ -z "$container" ] && docker compose version &>/dev/null 2>&1; then
container=$(docker compose ps -q orcpub 2>/dev/null || true)
fi
# Fallback: search by image name
if [ -z "$container" ]; then
container=$(docker ps -q --filter "ancestor=orcpub/orcpub:latest" 2>/dev/null | head -1 || true)
fi
# Fallback: search by container name pattern
if [ -z "$container" ]; then
container=$(docker ps -q --filter "name=orcpub" 2>/dev/null | head -1 || true)
fi
echo "$container"
}
# ---------------------------------------------------------------------------
# Wait for container and Datomic to be ready
# ---------------------------------------------------------------------------
wait_for_ready() {
local container="$1"
local max_wait=120
local waited=0
# Check container is running
if ! docker inspect --format='{{.State.Running}}' "$container" 2>/dev/null | grep -q true; then
error "Container $container is not running."
error "Start it first: docker-compose up -d"
exit 1
fi
# Wait for Docker's native healthcheck (defined in docker-compose.yaml)
# to report the container as healthy. This avoids spawning a JVM per check.
local health
health=$(docker inspect --format='{{if .State.Health}}yes{{end}}' "$container" 2>/dev/null || true)
if [ "$health" = "yes" ]; then
printf "Waiting for container health check"
while [ $waited -lt $max_wait ]; do
local status
status=$(docker inspect --format='{{.State.Health.Status}}' "$container" 2>/dev/null || true)
if [ "$status" = "healthy" ]; then
echo ""
info "Container is healthy"
return 0
fi
if [ "$status" = "unhealthy" ]; then
echo ""
error "Container reported unhealthy"
exit 1
fi
printf "."
sleep 2
waited=$((waited + 2))
done
echo ""
error "Timed out waiting for healthy status (${max_wait}s)."
exit 1
fi
# Fallback: no healthcheck defined — check HTTP readiness directly
warn "No Docker healthcheck found; polling HTTP on container port..."
printf "Waiting for app"
while [ $waited -lt $max_wait ]; do
# BusyBox wget (Alpine): only -q and --spider are supported
if docker exec "$container" wget -q --spider \
"http://localhost:${PORT:-8890}/" 2>/dev/null; then
echo ""
return 0
fi
printf "."
sleep 2
waited=$((waited + 2))
done
echo ""
error "Timed out waiting for app (${max_wait}s). Is the datomic container running?"
exit 1
}
# ---------------------------------------------------------------------------
# Run the management script inside the container
# ---------------------------------------------------------------------------
run_in_container() {
local container="$1"
shift
# Copy the management script into the container
docker cp "$MANAGE_SCRIPT" "${container}:/tmp/manage-user.clj"
# Run it with the uberjar classpath
docker exec "$container" \
java -cp /orcpub.jar clojure.main /tmp/manage-user.clj "$@"
}
# ---------------------------------------------------------------------------
# Parse args and dispatch
# ---------------------------------------------------------------------------
CONTAINER_OVERRIDE=""
# Extract --container flag if present
ARGS=()
while [[ $# -gt 0 ]]; do
case "$1" in
--container)
CONTAINER_OVERRIDE="$2"
shift 2
;;
--help|-h)
usage
exit 0
;;
*)
ARGS+=("$1")
shift
;;
esac
done
set -- "${ARGS[@]+"${ARGS[@]}"}"
if [ $# -eq 0 ]; then
usage
exit 1
fi
# Verify manage-user.clj exists
if [ ! -f "$MANAGE_SCRIPT" ]; then
error "Management script not found at: $MANAGE_SCRIPT"
exit 1
fi
# Find or use specified container
if [ -n "$CONTAINER_OVERRIDE" ]; then
CONTAINER="$CONTAINER_OVERRIDE"
else
CONTAINER=$(find_container)
fi
if [ -z "$CONTAINER" ]; then
error "Cannot find the orcpub container."
error "Make sure the containers are running: docker-compose up -d"
exit 1
fi
# Wait for Datomic to be reachable, then run the command
wait_for_ready "$CONTAINER"
# For init: read INIT_ADMIN_* from .env and create the user
if [ "${1:-}" = "init" ]; then
ENV_FILE="${SCRIPT_DIR}/.env"
if [ ! -f "$ENV_FILE" ]; then
error "No .env file found. Run ./docker-setup.sh first."
exit 1
fi
# Source .env to get INIT_ADMIN_* variables
# shellcheck disable=SC1090
. "$ENV_FILE"
if [ -z "${INIT_ADMIN_USER:-}" ]; then
error "INIT_ADMIN_USER is not set in .env"
error "Run ./docker-setup.sh to configure, or set it manually in .env"
exit 1
fi
if [ -z "${INIT_ADMIN_EMAIL:-}" ] || [ -z "${INIT_ADMIN_PASSWORD:-}" ]; then
error "INIT_ADMIN_EMAIL and INIT_ADMIN_PASSWORD must also be set in .env"
exit 1
fi
info "Creating initial admin user: ${INIT_ADMIN_USER} <${INIT_ADMIN_EMAIL}>"
run_in_container "$CONTAINER" create "$INIT_ADMIN_USER" "$INIT_ADMIN_EMAIL" "$INIT_ADMIN_PASSWORD"
# For batch: copy the user file into the container and rewrite the path
elif [ "${1:-}" = "batch" ]; then
USER_FILE="${2:-}"
if [ -z "$USER_FILE" ]; then
error "Usage: ./docker-user.sh batch <file>"
exit 1
fi
if [ ! -f "$USER_FILE" ]; then
error "File not found: $USER_FILE"
exit 1
fi
docker cp "$USER_FILE" "${CONTAINER}:/tmp/batch-users.txt"
run_in_container "$CONTAINER" batch /tmp/batch-users.txt
else
run_in_container "$CONTAINER" "$@"
fi