1 package com.atlassian.sal.api.features;
2
3 import com.atlassian.sal.api.user.UserKey;
4
5 import javax.annotation.Nullable;
6
7 /**
8 * <p>Provides a cross-product method for determining whether a dark feature is enabled.</p>
9 *
10 * <p>Implementing products can back these checks with their own internal dark feature management system, but must
11 * follow the enable and disable dark features on startup based on system properties and the contents of an optional
12 * properties file. To avoid clashes with other system properties all features specified as system property must be
13 * prefixed with {@link DarkFeatureManager#ATLASSIAN_DARKFEATURE_PREFIX}. The prefix is removed from the feature key
14 * when it is processed later. Values must be either true or false. The location of the dark features property file can
15 * be overridden with the {@link DarkFeatureManager#DARKFEATURES_PROPERTIES_FILE_PROPERTY} system property.</p>
16 *
17 * <p>See SystemDarkFeatureInitializer in sal-core for an implementation.</p>
18 *
19 * @since 2.10
20 */
21 public interface DarkFeatureManager {
22 /**
23 * Prefix for all dark feature specified as system property.
24 */
25 public static final String ATLASSIAN_DARKFEATURE_PREFIX = "atlassian.darkfeature.";
26
27 /**
28 * System property for disabling all dark features.
29 */
30 public static final String DISABLE_ALL_DARKFEATURES_PROPERTY = "atlassian.darkfeature.disabled";
31
32 /**
33 * System property for overriding location of dark features property file.
34 */
35 public static final String DARKFEATURES_PROPERTIES_FILE_PROPERTY = "darkfeatures.properties.file";
36
37 /**
38 * Default properties file name.
39 */
40 public static final String DARKFEATURES_PROPERTIES_FILE_PROPERTY_DEFAULT = "atlassian-darkfeatures.properties";
41
42 /**
43 * Checks if a dark feature is enabled for all users, regardless whether the feature can be changed during runtime
44 * or not.
45 *
46 * @param featureKey key of the feature to be checked
47 * @return <code>true</code> if the feature key is valid and enabled, false otherwise
48 * @see ValidFeatureKeyPredicate
49 */
50 boolean isFeatureEnabledForAllUsers(String featureKey);
51
52 /**
53 * Checks if a dark feature is enabled for all users or for the current user only (must be called within the context
54 * of a request). If the user couldn't be resolved or is anonymous, only features enabled for all users are
55 * considered.
56 *
57 * @param featureKey key of the feature to be checked
58 * @return <code>true</code> if the feature is valid and enabled, either for all users or the current user only;
59 * <code>false</code> otherwise.
60 * @see ValidFeatureKeyPredicate
61 */
62 boolean isFeatureEnabledForCurrentUser(String featureKey);
63
64 /**
65 * Checks if a dark feature is enabled for all users or just for the given user. In case the user is anonymous,
66 * only features enabled for all users are considered.
67 *
68 * @param userKey the key of the user being queried; <code>null</code> represents the anonymous user
69 * @param featureKey key of the feature to be checked
70 * @return <code>true</code> if the feature key is valid and enabled, either for all users or the current user only;
71 * <code>false</code> otherwise.
72 * @throws IllegalArgumentException if the user doesn't exist
73 * @see ValidFeatureKeyPredicate
74 */
75 boolean isFeatureEnabledForUser(@Nullable UserKey userKey, String featureKey);
76
77 /**
78 * Returns true if the current acting user has permission to change dark features for all users. This is a nothrow
79 * method and should return a value instead of throw an exception.
80 *
81 * @return <code>true</code> iff the current acting user has permission to change dark features for all users,
82 * <code>false</code> otherwise
83 */
84 boolean canManageFeaturesForAllUsers();
85
86 /**
87 * Enable the given dark feature all users. The acting user must have permission to change dark features for all
88 * users.
89 *
90 * @param featureKey key of the feature to be enabled
91 * @throws InvalidFeatureKeyException if the feature key is not valid
92 * @throws MissingPermissionException if the user has not the required permission
93 * @throws IllegalStateException if the update failed
94 * @see ValidFeatureKeyPredicate
95 * @see #canManageFeaturesForAllUsers()
96 */
97 void enableFeatureForAllUsers(String featureKey);
98
99 /**
100 * Disable the given dark feature for all users. The acting user must have permission to change dark features for
101 * all users.
102 *
103 * @param featureKey key of the feature to be disabled
104 * @throws InvalidFeatureKeyException if the feature key is not valid
105 * @throws MissingPermissionException if the user has not the required permission
106 * @throws IllegalStateException if the update failed
107 * @see ValidFeatureKeyPredicate
108 * @see #canManageFeaturesForAllUsers()
109 */
110 void disableFeatureForAllUsers(String featureKey);
111
112 /**
113 * Enable a dark feature for the current user only. Anonymous users are not supported. <strong>If the feature is
114 * already enabled for all users, the user will still be able to use it.</strong>
115 *
116 * @param featureKey key of the feature to enable
117 * @throws InvalidFeatureKeyException if the feature key is not valid
118 * @throws IllegalStateException if the current user could not be resolved, is anonymous or the update failed due to
119 * any other reason
120 * @see ValidFeatureKeyPredicate
121 */
122 void enableFeatureForCurrentUser(String featureKey);
123
124 /**
125 * Enable a dark feature for the given user only. Anonymous users are not supported. <strong>If the feature is
126 * already enabled for all users, the user will still be able to use it.</strong>
127 *
128 * @param userKey key of the user to enable the feature for; not <code>null</code>
129 * @param featureKey key of the feature to be enabled
130 * @throws IllegalArgumentException if the user does not exist or is anonymous
131 * @throws InvalidFeatureKeyException if the feature key is not valid
132 * @throws IllegalStateException if the update failed
133 * @see ValidFeatureKeyPredicate
134 */
135 void enableFeatureForUser(UserKey userKey, String featureKey);
136
137 /**
138 * Disable a dark feature for the current user only. Anonymous users are not supported. <strong>If the feature is
139 * enabled for all users, the current user will still be able to use it.</strong>
140 *
141 * @param featureKey key of the feature to be disabled
142 * @throws InvalidFeatureKeyException if the feature key is not valid
143 * @throws IllegalStateException if the current user could not be resolved, is anonymous or the update failed due to
144 * any other reason
145 * @see ValidFeatureKeyPredicate
146 */
147 void disableFeatureForCurrentUser(String featureKey);
148
149 /**
150 * Disable a dark feature for the given user only. Anonymous users are not supported. <strong>If the feature is
151 * enabled for all users, the user will still be able to use it.</strong>
152 *
153 * @param userKey key of the user to disable the feature for; not <code>null</code>
154 * @param featureKey key of the feature to be disabled
155 * @throws IllegalArgumentException if the user does not exist or is anonymous
156 * @throws InvalidFeatureKeyException if the feature key is not valid
157 * @throws IllegalStateException if the update failed
158 * @see ValidFeatureKeyPredicate
159 */
160 void disableFeatureForUser(UserKey userKey, String featureKey);
161
162 /**
163 * @return all dark features enabled for all users.
164 */
165 EnabledDarkFeatures getFeaturesEnabledForAllUsers();
166
167 /**
168 * Return features enabled for the current user (must be called within the context of a request). In case the
169 * current user could not be resolved or is anonymous, all dark features enabled for all users are returned instead.
170 *
171 * @return all dark features applicable for the current user.
172 */
173 EnabledDarkFeatures getFeaturesEnabledForCurrentUser();
174
175 /**
176 * Return enabled features for a given user. In case the current user is anonymous, all global enabled features are
177 * returned.
178 *
179 * @param userKey key of the user being queried; <code>null</code> represents the anonymous user
180 * @return all dark features applicable for the given user
181 * @throws IllegalArgumentException if the user doesn't exist
182 */
183 EnabledDarkFeatures getFeaturesEnabledForUser(@Nullable UserKey userKey);
184
185 }