001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.juneau.console.views; 018 019import static org.apache.juneau.commons.utils.Shorts.*; 020 021import java.util.*; 022 023/** 024 * Serving-path allowlist of populator names that may be named on a region ({@link RegionDef#populate}). 025 * 026 * <p> 027 * This is an <b>authoring-discipline control, not a security boundary</b>, and the reason is structural, not a 028 * weaker policy choice. {@link SinkRenderAllowlist} is real defense: a named renderer's markup still has to pass 029 * through the closed {@code fillRenderSlot} copier, so an accepted id only ever gets to write what that copier lets 030 * it write. A populator has no such copier anywhere in its path — {@code JuneauViews.regions.resolve(name)} 031 * hands the resolved function the region's container element outright, and from that point the populator owns the 032 * container completely. This class therefore controls only <i>which name is resolved</i>; it says nothing whatever 033 * about what the resolved populator then does with the container it is handed. A reader who treats this allowlist 034 * as a security boundary equivalent to {@link SinkRenderAllowlist} will over-trust it. 035 * 036 * @since 10.0.0 037 */ 038public final class PopulatorAllowlist { 039 040 /** 041 * The reserved declarative-default populator name — the only Juneau-shipped populator today. 042 * 043 * <p> 044 * Unlike an ordinary {@code JuneauViews.regions.register(name, fn)} entry, which is last-write-wins and freely 045 * overridable by a later registration under the same name, the client registry refuses to let a consumer 046 * override the entry named <js>"default"</js>: that name is reserved for the framework's own declarative-default 047 * populator. 048 */ 049 public static final Set<String> BUILTIN_IDS = Set.of("default"); 050 051 private PopulatorAllowlist() {} 052 053 /** 054 * Accepts a reserved built-in name, or a name present in {@code allowedNames}. 055 * 056 * @param populatorName The populator name. Must not be <jk>null</jk> or blank. 057 * @param allowedNames Opt-in populator names (e.g. {@link RegionDef#allowedPopulators}). Can be <jk>null</jk>. 058 * @throws IllegalArgumentException If the name is neither a built-in nor an opted-in name. 059 */ 060 public static void assertAllowed(String populatorName, Collection<String> allowedNames) { 061 if (ib(populatorName)) 062 throw iaex("Populator name must not be null or blank."); 063 if (BUILTIN_IDS.contains(populatorName)) 064 return; 065 if (allowedNames != null && allowedNames.contains(populatorName)) 066 return; 067 throw iaex("Populator name '%s' is not an allowed region populator.", populatorName); 068 } 069}