001/*
002 * PermissionsEx
003 * Copyright (C) zml and PermissionsEx contributors
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * 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 ca.stellardrift.permissionsex;
018
019import ca.stellardrift.permissionsex.context.ContextDefinitionProvider;
020import ca.stellardrift.permissionsex.context.ContextInheritance;
021import ca.stellardrift.permissionsex.datastore.DataStore;
022import ca.stellardrift.permissionsex.rank.RankLadderCollection;
023import ca.stellardrift.permissionsex.subject.CalculatedSubject;
024import ca.stellardrift.permissionsex.subject.SubjectRef;
025import ca.stellardrift.permissionsex.subject.SubjectType;
026import ca.stellardrift.permissionsex.subject.SubjectTypeCollection;
027import org.checkerframework.checker.nullness.qual.Nullable;
028
029import java.util.Collection;
030import java.util.Set;
031import java.util.concurrent.CompletableFuture;
032import java.util.function.Consumer;
033import java.util.function.Function;
034import java.util.regex.Pattern;
035
036/**
037 * A PermissionsEx engine.
038 *
039 * @since 2.0.0
040 */
041public interface PermissionsEngine extends ContextDefinitionProvider {
042    @Deprecated
043    String SUBJECTS_USER = "user";
044    @Deprecated
045    String SUBJECTS_GROUP = "group";
046
047    // TODO: make these SubjectType<?> values... somehow? will these need to become instance fields of the engine?
048    /**
049     * A subject type where subjects are
050     */
051    SubjectType<String> SUBJECTS_DEFAULTS = SubjectType.stringIdentBuilder("default")
052                        .transientHasPriority(false)
053                        .build();
054    SubjectType<String> SUBJECTS_FALLBACK = SubjectType.stringIdentBuilder("fallback").build();
055
056    // -- Working with subject types -- //
057
058    /**
059     * Get a subject type by name.
060     *
061     * <p>If this subject type has not been seen before, it will be registered.</p>
062     *
063     * @param type the type identifier
064     * @return a subject type instance, never null
065     * @since 2.0.0
066     */
067    <I> SubjectTypeCollection<I> subjects(final SubjectType<I> type);
068
069    /**
070     * Resolve a subject from a reference.
071     *
072     * @param reference the subject reference to resolve
073     * @param <I> identifier type
074     * @return a future providing the resolved subject
075     * @since 2.0.0
076     */
077    default <I> CompletableFuture<CalculatedSubject> subject(final SubjectRef<I> reference) {
078        return this.subjects(reference.type()).get(reference.identifier());
079    }
080
081    /**
082     * Get subject types with actively stored data.
083     *
084     * @return an unmodifiable view of the actively loaded subject types
085     */
086    Collection<? extends SubjectTypeCollection<?>> loadedSubjectTypes();
087
088    /**
089     * Get all registered subject types
090     *
091     * @return a stream producing all subject types
092     * @since 2.0.0
093     */
094    Set<SubjectType<?>> knownSubjectTypes();
095
096    /**
097     * Get a cache for rank ladders known by the engine.
098     *
099     * <p>Rank ladders allow for promotion and demotion of a subject among a
100     * set of ranked parents.</p>
101     *
102     * @return the ladder cache
103     * @since 2.0.0
104     */
105    RankLadderCollection ladders();
106
107    /**
108     * Perform a low-level bulk operation.
109     *
110     * <p>This can be used for transforming subjects if the subject type definition changes, and
111     * any large data changes that require information that may no longer be valid with current
112     * subject type options.</p>
113     *
114     * <p>When possible, higher-level bulk query API (not yet written) should be used instead.</p>
115     *
116     * @param actor the action to perform
117     * @param <V> the result type
118     * @return a future completing with the result of the action
119     */
120    <V> CompletableFuture<V> doBulkOperation(final Function<DataStore, CompletableFuture<V>> actor);
121
122    /**
123     * Get the current context inheritance.
124     *
125     * <p>No update listener will be registered</p>
126     *
127     * @return a future providing the current context inheritance data
128     * @see #contextInheritance(Consumer) for more details on context inheritance
129     * @since 2.0.0
130     */
131    default CompletableFuture<ContextInheritance> contextInheritance() {
132        return this.contextInheritance((Consumer<ContextInheritance>) null);
133    }
134
135    /**
136     * Get context inheritance data.
137     *
138     * <p>The result of the future is immutable -- to take effect, the object returned by any
139     * update methods in {@link ContextInheritance} must be passed to {@link #contextInheritance(ContextInheritance)}.
140     *  It follows that anybody else's changes will not appear in the returned inheritance object -- so if updates are
141     *  desired providing a callback function is important.</p>
142     *
143     * @param listener A callback function that will be triggered whenever there is a change to the context inheritance
144     * @return A future providing the current context inheritance data
145     * @since 2.0.0
146     */
147    CompletableFuture<ContextInheritance> contextInheritance(final @Nullable Consumer<ContextInheritance> listener);
148
149    /**
150     * Update the context inheritance when values have been changed
151     *
152     * @param newInheritance The modified inheritance object
153     * @return A future containing the latest context inheritance object
154     * @since 2.0.0
155     */
156    CompletableFuture<ContextInheritance> contextInheritance(ContextInheritance newInheritance);
157
158    // -- Engine state -- //
159
160    /**
161     * Get whether or not debug mode is enabled.
162     *
163     * <p>When debug mode is enabled, all permission queries will be logged to the engine's
164     *    active logger.</p>
165     *
166     * @return the debug mode state
167     * @since 2.0.0
168     */
169    boolean debugMode();
170
171    /**
172     * Set the active debug mode state.
173     *
174     * @param enabled whether debug mode is enabled
175     * @since 2.0.0
176     * @see #debugMode() for information on the consequences of debug mode
177     */
178    default void debugMode(final boolean enabled) {
179        this.debugMode(enabled, null);
180    }
181
182    /**
183     * Set the active debug mode state, and a filter.
184     *
185     * @param enabled whether debug mode is enabled
186     * @param filter a filter for values (permissions, options, and subject names) that will be
187     *               logged by debug mode.
188     * @since 2.0.0
189     * @see #debugMode() for information on the consequences of debug mode
190     */
191    void debugMode(final boolean enabled, final @Nullable Pattern filter);
192
193}