-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathapps-disable.sh
More file actions
executable file
·254 lines (223 loc) · 8.15 KB
/
Copy pathapps-disable.sh
File metadata and controls
executable file
·254 lines (223 loc) · 8.15 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
#!/bin/sh
set -e
# SPDX-FileCopyrightText: 2025 STRATO GmbH
# SPDX-License-Identifier: AGPL-3.0-or-later
################################################################################
# Nextcloud Apps Configuration Script
################################################################################
#
# DESCRIPTION:
# This script manages Nextcloud app configurations by:
# 1. Removing specified apps from the shipped.json file (disabling them)
# 2. Adding specified apps to the alwaysEnabled array (forcing them enabled)
#
# It modifies the 'defaultEnabled' and 'alwaysEnabled' arrays in core/shipped.json
# to control which apps are shipped with the installation and which cannot be
# disabled by administrators.
#
# LOCATION:
# This script is located in /IONOS as a submodule within the Nextcloud
# server repository.
#
# EXECUTION CONTEXT:
# ⚠️ IMPORTANT: This script should be executed during the Docker image build
# process, NOT at runtime in Kubernetes pods. Since we do not use PVCs
# (Persistent Volume Claims), runtime execution would require applying
# changes to each nc-pod individually, which is inefficient and error-prone.
#
# USAGE:
# ./apps-disable.sh
#
# The script reads app names from:
# - disabled-apps.list: Apps to remove from shipped.json (one per line)
# - always-enabled-apps.list: Apps to add to alwaysEnabled array (one per line)
#
# PREREQUISITES:
# - jq (JSON processor) must be installed
# - disabled-apps.list must exist in the same directory
# - always-enabled-apps.list is optional but will be processed if present
# - ../core/shipped.json must exist and be valid JSON
#
# INPUT FILES:
# - disabled-apps.list: List of app names to disable (one per line)
# * Supports comments (lines starting with #)
# * Ignores empty lines and whitespace
# - always-enabled-apps.list: List of app names to force enable (one per line)
# * Same format as disabled-apps.list
# * Apps are added to alwaysEnabled array to prevent disabling
#
# OUTPUT:
# - Modifies ../core/shipped.json in place
# - Logs progress and results to stdout/stderr
#
# EXIT CODES:
# 0 - Success
# 1 - Fatal error (missing dependencies, invalid files, or processing errors)
#
# EXAMPLE disabled-apps.list:
# # Core apps to disable
# dashboard
# weather_status
#
# # Optional apps
# recommendations
#
# EXAMPLE always-enabled-apps.list:
# # Security apps that must remain enabled
# twofactor_totp
# encryption
#
# NOTES:
# - The 'alwaysEnabled' attribute is the critical one - it determines which
# apps cannot be disabled by administrators
# - The 'defaultEnabled' attribute only affects new installations, not updates
# - All changes are validated before and after processing
# - Apps in always-enabled-apps.list are only added if not already present
#
# AUTHOR: IONOS Nextcloud Customization Team
# LICENSE: See LICENSES/ directory
#
################################################################################
# Configuration: Base directory and file paths
BDIR="$(dirname "${0}")"
SHIPPED_JSON="${BDIR}/../core/shipped.json"
DISABLED_APPS_FILE="${BDIR}/disabled-apps.list"
ALWAYS_ENABLED_APPS_FILE="${BDIR}/always-enabled-apps.list"
################################################################################
# Logging Functions
################################################################################
log_info() {
printf "\033[0;32m[✓]\033[0m %s\n" "${*}"
}
log_warn() {
printf "\033[0;33m[!]\033[0m %s\n" "${*}" >&2
}
log_fatal() {
printf "\033[1;31m[✗]\033[0m Fatal Error: %s\n" "${*}" >&2
exit 1
}
################################################################################
# Utility Functions
################################################################################
command_exists() {
command -v "${1}" >/dev/null 2>&1
}
# Read app lists from .list files
read_app_list() {
# Read app list from file, ignoring comments and empty lines
# Usage: read_app_list <file_path>
_list_file="${1}"
if [ ! -f "${_list_file}" ]; then
echo ""
return
fi
grep -v '^[[:space:]]*#' "${_list_file}" | grep -v '^[[:space:]]*$' | tr '\n' ' '
}
################################################################################
# Core Functions
################################################################################
# Remove an app from shipped.json
# Removes the specified app from both defaultEnabled and alwaysEnabled arrays
# in the shipped.json file using jq for safe JSON manipulation
# Usage: unship_app <app_name>
# Arguments:
# $1 - Name of the app to remove from shipped.json
# Side Effects:
# - Creates a temporary file (shipped.json.tmp)
# - Modifies shipped.json in place
# - Logs success message
# Exit: Calls log_fatal on jq processing errors
unship_app() {
app="${1}"
temp_file="${SHIPPED_JSON}.tmp"
# Use jq to safely remove the app from both arrays
# The filter deletes matching entries from defaultEnabled and alwaysEnabled
if ! jq --arg app "${app}" \
'del(.defaultEnabled[] | select(. == $app)) | del(.alwaysEnabled[] | select(. == $app))' \
"${SHIPPED_JSON}" > "${temp_file}"; then
log_fatal "Failed to process ${app} with jq"
fi
# Atomically replace the original file
mv "${temp_file}" "${SHIPPED_JSON}"
log_info "Unshipped app '${app}'"
}
# Add an app to the alwaysEnabled array in shipped.json
# Adds the specified app to the alwaysEnabled array if it's not already present
# in the shipped.json file using jq for safe JSON manipulation
# Usage: ship_app <app_name>
# Arguments:
# $1 - Name of the app to add to the alwaysEnabled array
# Side Effects:
# - Creates a temporary file (shipped.json.tmp)
# - Modifies shipped.json in place
# - Logs success message
# Exit: Calls log_fatal on jq processing errors
ship_app() {
app="${1}"
temp_file="${SHIPPED_JSON}.tmp"
# Use jq to safely add the app to alwaysEnabled array if not already present
# The filter checks if the app is already in the array before adding
if ! jq --arg app "${app}" \
'if (.alwaysEnabled | index($app)) then . else .alwaysEnabled += [$app] end' \
"${SHIPPED_JSON}" > "${temp_file}"; then
log_fatal "Failed to process ${app} with jq"
fi
# Atomically replace the original file
mv "${temp_file}" "${SHIPPED_JSON}"
log_info "Shipped app '${app}' as always enabled"
}
# Validate that shipped.json is valid JSON
# Performs a validation check on shipped.json using jq
# Usage: validate_shipped_json
# Exit: Calls log_fatal if JSON is invalid
validate_shipped_json() {
if ! jq empty "${SHIPPED_JSON}" 2>/dev/null; then
log_fatal "Invalid JSON in ${SHIPPED_JSON}"
fi
}
main() {
# Check prerequisites
if ! command_exists jq; then
log_fatal "jq is required but not installed"
fi
if [ ! -f "${SHIPPED_JSON}" ]; then
log_fatal "Shipped JSON file not found: ${SHIPPED_JSON}"
fi
if [ ! -f "${DISABLED_APPS_FILE}" ]; then
log_fatal "Disabled apps file not found: ${DISABLED_APPS_FILE}"
fi
# Validate shipped.json before processing
validate_shipped_json
# NOTE: alwaysEnabled should be the only attribute in this json file which
# really matters, since it is the only attribute which is checked to
# determine which apps can be disabled or not.
# defaultEnabled is only used during installation, but not for updates.
log_info "Processing apps configuration..."
# Load disabled apps list
DISABLED_APPS=$(read_app_list "${DISABLED_APPS_FILE}")
# Load always-enabled apps list
ALWAYS_ENABLED_APPS=$(read_app_list "${ALWAYS_ENABLED_APPS_FILE}")
# Process disabled apps - remove from shipped list
disabled_count=0
if [ -n "${DISABLED_APPS}" ]; then
log_info "Removing apps from 'shipped' list..."
for app in ${DISABLED_APPS}; do
unship_app "${app}"
disabled_count=$((disabled_count + 1))
done
fi
# Process always-enabled apps - add to alwaysEnabled array
enabled_count=0
if [ -n "${ALWAYS_ENABLED_APPS}" ]; then
log_info "Adding apps to 'alwaysEnabled' list..."
for app in ${ALWAYS_ENABLED_APPS}; do
ship_app "${app}"
enabled_count=$((enabled_count + 1))
done
fi
# Validate shipped.json after processing to ensure we didn't corrupt it
validate_shipped_json
log_info "Successfully processed ${disabled_count} disabled apps and ${enabled_count} always-enabled apps"
}
# Execute main function
main