-
Notifications
You must be signed in to change notification settings - Fork 219
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix #468 by implementing short-time cache for authorization middleware #502
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,9 +8,15 @@ | |
import com.slack.api.bolt.request.Request; | ||
import com.slack.api.bolt.response.Response; | ||
import com.slack.api.bolt.service.InstallationService; | ||
import com.slack.api.methods.MethodsClient; | ||
import com.slack.api.methods.SlackApiException; | ||
import com.slack.api.methods.response.auth.AuthTestResponse; | ||
import lombok.extern.slf4j.Slf4j; | ||
|
||
import java.io.IOException; | ||
import java.util.Optional; | ||
import java.util.concurrent.atomic.AtomicLong; | ||
|
||
import static com.slack.api.bolt.middleware.MiddlewareOps.isNoAuthRequiredRequest; | ||
|
||
/** | ||
|
@@ -22,6 +28,9 @@ public class SingleTeamAuthorization implements Middleware { | |
private final AppConfig appConfig; | ||
private final InstallationService installationService; | ||
|
||
private Optional<AuthTestResponse> cachedAuthTestResponse = Optional.empty(); | ||
private AtomicLong lastCachedMillis = new AtomicLong(0L); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks to @aoberoi 's suggestion here: #468 (comment), we can remove this TTL and store the response when booting a Bolt app as with Bolt for JS. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I came to think removing TTL from only single team auth may be confusing. I decided to add a "permanent" option by giving a negative TTL value instead. |
||
|
||
public SingleTeamAuthorization(AppConfig appConfig, InstallationService installationService) { | ||
this.appConfig = appConfig; | ||
this.installationService = installationService; | ||
|
@@ -34,7 +43,7 @@ public Response apply(Request req, Response resp, MiddlewareChain chain) throws | |
} | ||
|
||
Context context = req.getContext(); | ||
AuthTestResponse authResult = context.client().authTest(r -> r.token(appConfig.getSingleTeamBotToken())); | ||
AuthTestResponse authResult = callAuthTest(appConfig, context.client()); | ||
if (authResult.isOk()) { | ||
if (context.getBotToken() == null) { | ||
context.setBotToken(appConfig.getSingleTeamBotToken()); | ||
|
@@ -72,4 +81,27 @@ public Response apply(Request req, Response resp, MiddlewareChain chain) throws | |
.build(); | ||
} | ||
} | ||
|
||
protected AuthTestResponse callAuthTest(AppConfig config, MethodsClient client) throws IOException, SlackApiException { | ||
if (config.isAuthTestCacheEnabled()) { | ||
if (cachedAuthTestResponse.isPresent()) { | ||
boolean permanentCacheEnabled = config.getAuthTestCacheExpirationMillis() < 0; | ||
if (permanentCacheEnabled) { | ||
return cachedAuthTestResponse.get(); | ||
} | ||
long millisToExpire = lastCachedMillis.get() + config.getAuthTestCacheExpirationMillis(); | ||
long currentMillis = System.currentTimeMillis(); | ||
if (millisToExpire > currentMillis) { | ||
return cachedAuthTestResponse.get(); | ||
} | ||
} | ||
AuthTestResponse response = client.authTest(r -> r.token(config.getSingleTeamBotToken())); | ||
cachedAuthTestResponse = Optional.of(response); // response here is not null for sure | ||
lastCachedMillis.set(System.currentTimeMillis()); | ||
return response; | ||
} else { | ||
return client.authTest(r -> r.token(config.getSingleTeamBotToken())); | ||
} | ||
} | ||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We may want to clean up very old cache data to avoid excessive memory usage in extreme cases. As I don't want to add any dependencies only for this, we can implement a simple mechanism on our own.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done