MCPcopy Index your code
hub / github.com/ether/etherpad / expressCreateServer

Function expressCreateServer

src/node/hooks/express/updateActions.ts:141–374  ·  view source on GitHub ↗
(
  _hookName: string,
  {app}: ArgsExpressType,
  cb: Function,
)

Source from the content-addressed store, hash-verified

139const tierAllowsActions = (): boolean => TIER2_TIERS.has(settings.updates.tier);
140
141export const expressCreateServer = (
142 _hookName: string,
143 {app}: ArgsExpressType,
144 cb: Function,
145): void => {
146 // Always register the routes; gate at request time so a runtime tier change
147 // takes effect on the next request rather than requiring a restart.
148 // The early 404 below preserves Qodo #1's "disabled path matches prior
149 // behaviour (no Tier 2 endpoints existed before this PR)" requirement.
150 const tierGate = (req: any, res: any, next: Function) => {
151 if (!tierAllowsActions()) return res.status(404).send('Not found');
152 next();
153 };
154 app.use(['/admin/update/apply', '/admin/update/cancel', '/admin/update/acknowledge', '/admin/update/log'], tierGate);
155
156 app.post('/admin/update/apply', wrapAsync(async (req: any, res: any) => {
157 if (!requireAdmin(req, res)) return;
158
159 // HTTP-specific pre-checks: produce structured 4xx error codes the UI
160 // localises. The pipeline duplicates these as safety, but mapping cleanly
161 // to status codes is easier when we know the failure kind up-front.
162 const state = await loadState(stateFilePath());
163 if (!state.latest) return res.status(409).json({error: 'no-known-latest'});
164 if (!isValidTag(state.latest.tag)) {
165 return res.status(409).json({error: 'invalid-tag-in-state'});
166 }
167 // Allowed entry statuses: idle / verified / preflight-failed / rolled-back / scheduled.
168 // `scheduled` lets the admin "Apply now" during the Tier 3 grace window.
169 const allowedEntry = ['idle', 'verified', 'preflight-failed', 'rolled-back', 'scheduled'];
170 if (!allowedEntry.includes(state.execution.status)) {
171 return res.status(409).json({error: `execution-busy:${state.execution.status}`});
172 }
173 const installMethod = getDetectedInstallMethod();
174 const policy = evaluatePolicy({
175 installMethod,
176 tier: settings.updates.tier,
177 current: getEpVersion(),
178 latest: state.latest.version,
179 executionStatus: state.execution.status,
180 });
181 if (!policy.canManual) {
182 return res.status(409).json({error: 'policy-denied', reason: policy.reason});
183 }
184
185 // Admin clicked "Apply now" during the Tier 3 grace window. Drop the
186 // pending scheduler timer so it doesn't later fire and attempt a second
187 // apply (Qodo #3). The pipeline will overwrite execution → preflight
188 // momentarily, but cancelling the timer is what guarantees we don't race.
189 if (state.execution.status === 'scheduled') cancelScheduler();
190
191 const targetTag = state.latest.tag;
192 let responded = false;
193
194 try {
195 const result = await applyUpdate({
196 targetTag,
197 deps: {
198 loadState: () => loadState(stateFilePath()),

Callers

nothing calls this directly

Calls 15

loadStateFunction · 0.90
stateFilePathFunction · 0.90
isValidTagFunction · 0.90
getDetectedInstallMethodFunction · 0.90
evaluatePolicyFunction · 0.90
getEpVersionFunction · 0.90
cancelSchedulerFunction · 0.90
applyUpdateFunction · 0.90
saveStateFunction · 0.90
acquireLockFunction · 0.90
releaseLockFunction · 0.90
runPreflightFunction · 0.90

Tested by

no test coverage detected