diff options
| author | erdgeist <erdgeist@erdgeist.org> | 2026-08-04 21:11:25 +0200 |
|---|---|---|
| committer | erdgeist <erdgeist@erdgeist.org> | 2026-08-04 21:11:25 +0200 |
| commit | a0a495d804319c3f7ad179baba7b87b41f1dc1f3 (patch) | |
| tree | 2ab56641c32ca606b2423a1dfff1649c2208b1e3 /lib | |
| parent | ac01156d00b24d14225c8e75979fb59bba69640d (diff) | |
Rework the README/INSTALL documents and provide a bootstrap script (untested ;)
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/tasks/init.rake | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/lib/tasks/init.rake b/lib/tasks/init.rake new file mode 100644 index 00000000..7e3d8dcc --- /dev/null +++ b/lib/tasks/init.rake | |||
| @@ -0,0 +1,75 @@ | |||
| 1 | namespace :cccms do | ||
| 2 | desc "Bootstrap a fresh installation: the node skeleton and one admin " \ | ||
| 3 | "account. Idempotent -- every step finds before it creates, so " \ | ||
| 4 | "re-running after a new step is added is safe. " \ | ||
| 5 | "Requires ADMIN_PASS. ADMIN_LOGIN and ADMIN_EMAIL are optional. " \ | ||
| 6 | "The admin is created without the role and promoted with " \ | ||
| 7 | "update_column, because admin_needs_second_factor refuses a NEW " \ | ||
| 8 | "admin without an enrolled factor -- it exempts retention, not " \ | ||
| 9 | "creation. The account therefore cannot do user management until " \ | ||
| 10 | "it enrols a second factor and signs in again; see INSTALL.md." | ||
| 11 | task :init => :environment do | ||
| 12 | password = ENV["ADMIN_PASS"].to_s | ||
| 13 | abort "usage: ADMIN_PASS=secret bundle exec rake cccms:init" if password.empty? | ||
| 14 | abort "ADMIN_PASS must be at least 6 characters" if password.length < 6 | ||
| 15 | |||
| 16 | login = ENV.fetch("ADMIN_LOGIN", "admin") | ||
| 17 | email = ENV.fetch("ADMIN_EMAIL", "admin@example.org") | ||
| 18 | |||
| 19 | # publish_draft! is called with no user, which guard_live_change! treats | ||
| 20 | # as a trusted system context -- the documented nil-user path, and the | ||
| 21 | # reason a rake task can publish into /updates and /disclosure at all. | ||
| 22 | ensure_node = lambda do |parent, slug, title, body| | ||
| 23 | existing = parent ? parent.children.find_by(:slug => slug) : Node.root | ||
| 24 | if existing | ||
| 25 | puts format(" %-14s exists (%d)", slug || "root", existing.id) | ||
| 26 | next existing | ||
| 27 | end | ||
| 28 | |||
| 29 | node = parent ? parent.children.create!(:slug => slug) : Node.create! | ||
| 30 | Globalize.with_locale(I18n.default_locale) do | ||
| 31 | node.draft.update!(:title => title, :body => body.to_s) | ||
| 32 | end | ||
| 33 | node.publish_draft! | ||
| 34 | puts format(" %-14s created (%d)", slug || "root", node.id) | ||
| 35 | node | ||
| 36 | end | ||
| 37 | |||
| 38 | puts "Node skeleton:" | ||
| 39 | root = ensure_node.(nil, nil, "CCC", "") | ||
| 40 | |||
| 41 | # Referencing it is enough: Node.trash self-creates on first call. | ||
| 42 | puts format(" %-14s ready (%d)", "trash", Node.trash.id) | ||
| 43 | |||
| 44 | ensure_node.(root, "home", "Startseite", "") | ||
| 45 | |||
| 46 | ensure_node.(root, "updates", "Updates", | ||
| 47 | '[aggregate tags="update" limit="30" order_by="published_at" order_direction="DESC"]') | ||
| 48 | |||
| 49 | ensure_node.(root, "disclosure", "Disclosure", "") | ||
| 50 | |||
| 51 | club = ensure_node.(root, "club", "Chaos Computer Club", "") | ||
| 52 | ensure_node.(club, "erfas", "Erfa-Kreise", | ||
| 53 | '[aggregate children="direct" order_by="slug" partial="chapter"]') | ||
| 54 | ensure_node.(club, "chaostreffs", "Chaostreffs", | ||
| 55 | '[aggregate children="direct" order_by="slug" partial="chapter"]') | ||
| 56 | |||
| 57 | puts | ||
| 58 | if User.any? | ||
| 59 | puts "Accounts exist already; skipping admin creation." | ||
| 60 | else | ||
| 61 | user = User.create!(:login => login, :email => email, | ||
| 62 | :password => password, | ||
| 63 | :password_confirmation => password) | ||
| 64 | user.update_column(:roles, %w[admin redaktion]) | ||
| 65 | puts "Created #{user.login} <#{user.email}> as admin + redaktion." | ||
| 66 | puts | ||
| 67 | puts "This account has no second factor, so it cannot yet create" | ||
| 68 | puts "users, reset factors or deactivate accounts. To finish:" | ||
| 69 | puts " 1. sign in as #{user.login}" | ||
| 70 | puts " 2. Mein Konto -> enable second factor, scan the QR, confirm" | ||
| 71 | puts " 3. sign out and sign in again, entering the code" | ||
| 72 | puts "Elevation is granted at that login and user management unlocks." | ||
| 73 | end | ||
| 74 | end | ||
| 75 | end | ||
