View Javadoc

1   package com.atlassian.sal.core.features;
2   
3   import com.atlassian.sal.api.features.DarkFeatureManager;
4   import com.atlassian.sal.api.features.EnabledDarkFeatures;
5   import com.atlassian.sal.api.features.EnabledDarkFeaturesBuilder;
6   import com.atlassian.sal.api.features.MissingPermissionException;
7   import com.atlassian.sal.api.features.SiteDarkFeaturesStorage;
8   import com.atlassian.sal.api.features.ValidFeatureKeyPredicate;
9   import com.atlassian.sal.api.user.UserKey;
10  import com.atlassian.sal.api.user.UserManager;
11  
12  import javax.annotation.Nullable;
13  
14  import static com.atlassian.sal.api.features.ValidFeatureKeyPredicate.checkFeatureKey;
15  
16  /**
17   * Default implementation of DarkFeatureManager - sufficient for any product which does not already have its own dark
18   * feature framework. Does not implement per-user enabling.
19   */
20  public class DefaultDarkFeatureManager implements DarkFeatureManager
21  {
22      private final UserManager userManager;
23      private final SiteDarkFeaturesStorage siteDarkFeaturesStorage;
24      private final SystemDarkFeatureInitializer.SystemDarkFeatures systemDarkFeatures;
25  
26      public DefaultDarkFeatureManager(final UserManager userManager, final SiteDarkFeaturesStorage siteDarkFeaturesStorage)
27      {
28          this.userManager = userManager;
29          this.siteDarkFeaturesStorage = siteDarkFeaturesStorage;
30          this.systemDarkFeatures = SystemDarkFeatureInitializer.getSystemStartupDarkFeatures();
31      }
32  
33      @Override
34      public boolean isFeatureEnabledForAllUsers(final String featureKey)
35      {
36          return ValidFeatureKeyPredicate.isValidFeatureKey(featureKey) && getFeaturesEnabledForAllUsers().isFeatureEnabled(featureKey);
37      }
38  
39      @Override
40      public boolean isFeatureEnabledForCurrentUser(final String featureKey)
41      {
42          return isFeatureEnabledForAllUsers(featureKey);
43      }
44  
45      @Override
46      public boolean isFeatureEnabledForUser(@Nullable final UserKey userKey, final String featureKey)
47      {
48          if (isUserAnonymous(userKey) || isUserExisting(userKey))
49          {
50              return isFeatureEnabledForAllUsers(featureKey);
51          }
52          else
53          {
54              throw new IllegalArgumentException("The user does not exist");
55          }
56      }
57  
58      @Override
59      public boolean canManageFeaturesForAllUsers()
60      {
61          try
62          {
63              final UserKey remoteUserKey = userManager.getRemoteUserKey();
64              return userManager.isSystemAdmin(remoteUserKey);
65          }
66          catch (RuntimeException e)
67          {
68              /**
69               * Applying the principle of least surprise here so the caller wouldn't have to deal with undeclared
70               * runtime exceptions. Determining that a user has the proper permissions is very unlikely to be successful
71               * when an exception is thrown.
72               */
73              return false;
74          }
75      }
76  
77      @Override
78      public void enableFeatureForAllUsers(final String featureKey)
79      {
80          checkFeatureKey(featureKey);
81          checkCurrentUserCanManageFeaturesForAllUsers();
82          siteDarkFeaturesStorage.enable(featureKey);
83      }
84  
85      @Override
86      public void disableFeatureForAllUsers(final String featureKey)
87      {
88          checkFeatureKey(featureKey);
89          checkCurrentUserCanManageFeaturesForAllUsers();
90          siteDarkFeaturesStorage.disable(featureKey);
91      }
92  
93      @Override
94      public void enableFeatureForCurrentUser(final String featureKey)
95      {
96          throwUnsupportedPerUserOperationException();
97      }
98  
99      @Override
100     public void enableFeatureForUser(final UserKey userKey, final String featureKey)
101     {
102         throwUnsupportedPerUserOperationException();
103     }
104 
105     @Override
106     public void disableFeatureForCurrentUser(final String featureKey)
107     {
108         throwUnsupportedPerUserOperationException();
109     }
110 
111     @Override
112     public void disableFeatureForUser(final UserKey userKey, final String featureKey)
113     {
114         throwUnsupportedPerUserOperationException();
115     }
116 
117     public EnabledDarkFeatures getFeaturesEnabledForAllUsers()
118     {
119         if (systemDarkFeatures.isDisableAll())
120         {
121             return EnabledDarkFeatures.NONE;
122         }
123         else
124         {
125             return new EnabledDarkFeaturesBuilder()
126                     .unmodifiableFeaturesEnabledForAllUsers(systemDarkFeatures.getEnabled())
127                     .featuresEnabledForAllUsers(siteDarkFeaturesStorage.getEnabledDarkFeatures())
128                     .build();
129         }
130     }
131 
132     @Override
133     public EnabledDarkFeatures getFeaturesEnabledForCurrentUser()
134     {
135         return getFeaturesEnabledForAllUsers();
136     }
137 
138     @Override
139     public EnabledDarkFeatures getFeaturesEnabledForUser(@Nullable final UserKey userKey)
140     {
141         if (isUserAnonymous(userKey) || isUserExisting(userKey))
142         {
143             return getFeaturesEnabledForAllUsers();
144         }
145         else
146         {
147             throw new IllegalArgumentException("The user does not exist");
148         }
149     }
150 
151     private boolean isUserExisting(@Nullable final UserKey userKey)
152     {
153         return (userKey != null) && userManager.getUserProfile(userKey) != null;
154     }
155 
156     private boolean isUserAnonymous(@Nullable final UserKey userKey)
157     {
158         return userKey == null;
159     }
160 
161     private void checkCurrentUserCanManageFeaturesForAllUsers()
162     {
163         if (!canManageFeaturesForAllUsers())
164         {
165             throw new MissingPermissionException("The current user is not allowed to change dark features affecting all users.");
166         }
167     }
168 
169     private void throwUnsupportedPerUserOperationException()
170     {
171         throw new UnsupportedOperationException("The default implementation doesn't support per-user dark features.");
172     }
173 }