#!/usr/bin/env bash set -euo pipefail script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" repo_root="$(cd "${script_dir}/.." && pwd)" custom_apps_root="${NEXTCLOUD_CUSTOM_APPS_PATH:-${repo_root}/nextcloud/custom_apps}" app_path="${USER_OIDC_APP_PATH:-}" dry_run="0" usage() { cat < Path to user_oidc app directory --custom-apps-path Nextcloud custom_apps path --dry-run Check whether patch is needed without writing -h, --help Show this help USAGE } resolve_path() { local raw="${1:-}" if [[ -z "${raw}" ]]; then printf '%s' "" elif [[ "${raw}" == /* ]]; then printf '%s' "${raw}" else printf '%s' "${repo_root}/${raw}" fi } while [[ $# -gt 0 ]]; do case "$1" in --app-path) app_path="${2:-}" shift 2 ;; --app-path=*) app_path="${1#*=}" shift ;; --custom-apps-path) custom_apps_root="${2:-}" shift 2 ;; --custom-apps-path=*) custom_apps_root="${1#*=}" shift ;; --dry-run) dry_run="1" shift ;; -h|--help) usage exit 0 ;; *) echo "Unknown option: $1" >&2 usage exit 1 ;; esac done custom_apps_root="$(resolve_path "${custom_apps_root}")" if [[ -z "${app_path}" ]]; then app_path="${custom_apps_root}/user_oidc" else app_path="$(resolve_path "${app_path}")" fi login_controller="${app_path}/lib/Controller/LoginController.php" if [[ ! -f "${login_controller}" ]]; then echo "Missing user_oidc LoginController: ${login_controller}" >&2 exit 1 fi if grep -q "getParam('invite_token'" "${login_controller}" 2>/dev/null; then echo "user_oidc invite bridge already present: ${login_controller}" exit 0 fi if [[ "${dry_run}" == "1" ]]; then echo "user_oidc invite bridge would be applied: ${login_controller}" exit 0 fi tmp_file="$(mktemp)" cleanup() { rm -f "${tmp_file}" } trap cleanup EXIT if ! perl -0pe ' our $patched; my $pattern = qr{ \n([ \t]*)try[ \t]*\{\n ([ \t]*)\$discovery[ \t]*=[ \t]*\$this->discoveryService->obtainDiscovery\(\$provider\); }x; if ($_ =~ $pattern) { my ($indent, $inner) = ($1, $2); my $insert = "\n${indent}\$inviteToken = trim((string)\$this->request->getParam(\"invite_token\", \"\"));\n" . "${indent}if (\$inviteToken !== \"\" && preg_match(\"/^[A-Za-z0-9_-]{16,256}$/\", \$inviteToken) === 1) {\n" . "${inner}\$data[\"invite_token\"] = \$inviteToken;\n" . "${indent}}\n" . "${indent}\$inviteEmail = trim((string)\$this->request->getParam(\"invite_email\", \"\"));\n" . "${indent}if (\$inviteEmail !== \"\" && filter_var(\$inviteEmail, FILTER_VALIDATE_EMAIL) !== false) {\n" . "${inner}\$data[\"invite_email\"] = \$inviteEmail;\n" . "${indent}}\n"; my $replacement = $insert . "\n${indent}try {\n${inner}\$discovery = \$this->discoveryService->obtainDiscovery(\$provider);"; $_ =~ s/$pattern/$replacement/; $patched = 1; } END { exit($patched ? 0 : 3); } ' "${login_controller}" > "${tmp_file}"; then echo "Unable to patch user_oidc invite bridge; LoginController layout changed." >&2 exit 1 fi backup_path="${login_controller}.nuqloud-pre-invite-patch.$(date +%Y%m%d%H%M%S)" cp "${login_controller}" "${backup_path}" cat "${tmp_file}" > "${login_controller}" echo "Applied user_oidc invite bridge: ${login_controller}" echo "Backup written: ${backup_path}"