Skip to content

Commit

Permalink
Merge pull request #1053 from supertokens/merge-latest
Browse files Browse the repository at this point in the history
fix: Merge latest
  • Loading branch information
sattvikc authored Oct 2, 2024
2 parents eedbc91 + 3547399 commit f1abf7f
Show file tree
Hide file tree
Showing 12 changed files with 306 additions and 226 deletions.
22 changes: 22 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,28 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

TODO: after plugin support

## [9.2.2] - 2024-09-04

- Adds index on `last_active_time` for `user_last_active` table to improve the performance of MAU computation.

### Migration

If using PostgreSQL, run the following SQL script:

```sql
CREATE INDEX IF NOT EXISTS user_last_active_last_active_time_index ON user_last_active (last_active_time DESC, app_id DESC);
```

If using MySQL, run the following SQL script:

```sql
CREATE INDEX user_last_active_last_active_time_index ON user_last_active (last_active_time DESC, app_id DESC);
```

## [9.2.1] - 2024-09-02

- Removes the stats that were resulting in high CPU consumption

## [9.2.0] - 2024-08-20

- Adds `SECURITY` feature in `EE_FEATURES`.
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ We also believe in the principle of least vendor lock-in. Your having full contr
can switch away from SuperTokens without forcing your existing users to logout, reset their passwords, or in the worst
case, sign up again.

### [Click here](https://thirdpartyemailpassword.demo.supertokens.io/) to see the demo app.
### [Click here](https://thirdpartyemailpassword.demo.supertokens.com/) to see the demo app.

- Please visit [our website](https://supertokens.io/pricing) to see the list of features.
- We want to make features as decoupled as possible. This means you can use SuperTokens for just login, or just session
Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ compileTestJava { options.encoding = "UTF-8" }
// }
//}

version = "9.2.0"
version = "9.2.2"


repositories {
Expand Down
Binary file modified cli/jar/cli.jar
Binary file not shown.
Binary file modified downloader/jar/downloader.jar
Binary file not shown.
Binary file modified ee/jar/ee.jar
Binary file not shown.
102 changes: 56 additions & 46 deletions ee/src/main/java/io/supertokens/ee/EEFeatureFlag.java
Original file line number Diff line number Diff line change
Expand Up @@ -202,29 +202,34 @@ private JsonObject getMFAStats() throws StorageQueryException, TenantOrAppNotFou
// TODO: Active users are present only on public tenant and MFA users may be
// present on different storages
JsonObject result = new JsonObject();
Storage[] storages = StorageLayer.getStoragesForApp(main, this.appIdentifier);

int totalUserCountWithMoreThanOneLoginMethod = 0;
int[] maus = new int[31];
// Commenting out these stats for now as they are very CPU intensive and reduces the performance
// of other API calls while this is running.
// Also, we are not currently using these stats.

long now = System.currentTimeMillis();
// Storage[] storages = StorageLayer.getStoragesForApp(main, this.appIdentifier);

for (Storage storage : storages) {
totalUserCountWithMoreThanOneLoginMethod += ((AuthRecipeStorage) storage)
.getUsersCountWithMoreThanOneLoginMethodOrTOTPEnabled(this.appIdentifier);
// int totalUserCountWithMoreThanOneLoginMethod = 0;
// int[] maus = new int[31];

for (int i = 1; i <= 31; i++) {
long timestamp = now - (i * 24 * 60 * 60 * 1000L);
// long now = System.currentTimeMillis();

// `maus[i-1]` since i starts from 1
maus[i - 1] += ((ActiveUsersStorage) storage)
.countUsersThatHaveMoreThanOneLoginMethodOrTOTPEnabledAndActiveSince(appIdentifier, timestamp);
}
}
// for (Storage storage : storages) {
// totalUserCountWithMoreThanOneLoginMethod += ((AuthRecipeStorage) storage)
// .getUsersCountWithMoreThanOneLoginMethodOrTOTPEnabled(this.appIdentifier);

result.addProperty("totalUserCountWithMoreThanOneLoginMethodOrTOTPEnabled",
totalUserCountWithMoreThanOneLoginMethod);
result.add("mauWithMoreThanOneLoginMethodOrTOTPEnabled", new Gson().toJsonTree(maus));
// for (int i = 1; i <= 31; i++) {
// long timestamp = now - (i * 24 * 60 * 60 * 1000L);

// // `maus[i-1]` since i starts from 1
// maus[i - 1] += ((ActiveUsersStorage) storage)
// .countUsersThatHaveMoreThanOneLoginMethodOrTOTPEnabledAndActiveSince(appIdentifier, timestamp);
// }
// }

// result.addProperty("totalUserCountWithMoreThanOneLoginMethodOrTOTPEnabled",
// totalUserCountWithMoreThanOneLoginMethod);
// result.add("mauWithMoreThanOneLoginMethodOrTOTPEnabled", new Gson().toJsonTree(maus));
return result;
}

Expand Down Expand Up @@ -307,36 +312,41 @@ private JsonObject getAccountLinkingStats() throws StorageQueryException, Tenant
}

result.addProperty("usesAccountLinking", usesAccountLinking);
if (!usesAccountLinking) {
result.addProperty("totalUserCountWithMoreThanOneLoginMethod", 0);
JsonArray mauArray = new JsonArray();
for (int i = 0; i < 31; i++) {
mauArray.add(new JsonPrimitive(0));
}
result.add("mauWithMoreThanOneLoginMethod", mauArray);
return result;
}

int totalUserCountWithMoreThanOneLoginMethod = 0;
int[] maus = new int[31];

long now = System.currentTimeMillis();

for (Storage storage : storages) {
totalUserCountWithMoreThanOneLoginMethod += ((AuthRecipeStorage) storage).getUsersCountWithMoreThanOneLoginMethod(
this.appIdentifier);

for (int i = 1; i <= 31; i++) {
long timestamp = now - (i * 24 * 60 * 60 * 1000L);

// `maus[i-1]` because i starts from 1
maus[i - 1] += ((ActiveUsersStorage) storage).countUsersThatHaveMoreThanOneLoginMethodAndActiveSince(
appIdentifier, timestamp);
}
}

result.addProperty("totalUserCountWithMoreThanOneLoginMethod", totalUserCountWithMoreThanOneLoginMethod);
result.add("mauWithMoreThanOneLoginMethod", new Gson().toJsonTree(maus));
// Commenting out these stats for now as they are very CPU intensive and reduces the performance
// of other API calls while this is running.
// Also, we are not currently using these stats.

// if (!usesAccountLinking) {
// result.addProperty("totalUserCountWithMoreThanOneLoginMethod", 0);
// JsonArray mauArray = new JsonArray();
// for (int i = 0; i < 31; i++) {
// mauArray.add(new JsonPrimitive(0));
// }
// result.add("mauWithMoreThanOneLoginMethod", mauArray);
// return result;
// }

// int totalUserCountWithMoreThanOneLoginMethod = 0;
// int[] maus = new int[31];

// long now = System.currentTimeMillis();

// for (Storage storage : storages) {
// totalUserCountWithMoreThanOneLoginMethod += ((AuthRecipeStorage) storage).getUsersCountWithMoreThanOneLoginMethod(
// this.appIdentifier);

// for (int i = 1; i <= 31; i++) {
// long timestamp = now - (i * 24 * 60 * 60 * 1000L);

// // `maus[i-1]` because i starts from 1
// maus[i - 1] += ((ActiveUsersStorage) storage).countUsersThatHaveMoreThanOneLoginMethodAndActiveSince(
// appIdentifier, timestamp);
// }
// }

// result.addProperty("totalUserCountWithMoreThanOneLoginMethod", totalUserCountWithMoreThanOneLoginMethod);
// result.add("mauWithMoreThanOneLoginMethod", new Gson().toJsonTree(maus));
return result;
}

Expand Down
Binary file renamed jar/core-9.2.0.jar → jar/core-9.2.2.jar
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ static String getQueryToCreateUserLastActiveTable(Start start) {
+ " );";
}

static String getQueryToCreateLastActiveTimeIndexForUserLastActiveTable(Start start) {
return "CREATE INDEX user_last_active_last_active_time_index ON "
+ Config.getConfig(start).getUserLastActiveTable() + "(last_active_time DESC, app_id DESC);";
}

public static int countUsersActiveSince(Start start, AppIdentifier appIdentifier, long sinceTime)
throws SQLException, StorageQueryException {
String QUERY = "SELECT COUNT(*) as total FROM " + Config.getConfig(start).getUserLastActiveTable()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,10 @@ public static void createTablesIfNotExists(Start start, Main main) throws SQLExc
if (!doesTableExists(start, Config.getConfig(start).getUserLastActiveTable())) {
getInstance(main).addState(CREATING_NEW_TABLE, null);
update(start, ActiveUsersQueries.getQueryToCreateUserLastActiveTable(start), NO_OP_SETTER);

// index
update(start, ActiveUsersQueries.getQueryToCreateLastActiveTimeIndexForUserLastActiveTable(start),
NO_OP_SETTER);
}

if (!doesTableExists(start, Config.getConfig(start).getAccessTokenSigningKeysTable())) {
Expand Down
80 changes: 40 additions & 40 deletions src/test/java/io/supertokens/test/FeatureFlagTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -193,14 +193,14 @@ public void testThatCallingGetFeatureFlagAPIReturnsMfaStats() throws Exception {
assert maus.get(29).getAsInt() == 0;

JsonObject mfaStats = usageStats.get("mfa").getAsJsonObject();
int totalMfaUsers = mfaStats.get("totalUserCountWithMoreThanOneLoginMethodOrTOTPEnabled").getAsInt();
JsonArray mfaMaus = mfaStats.get("mauWithMoreThanOneLoginMethodOrTOTPEnabled").getAsJsonArray();
// int totalMfaUsers = mfaStats.get("totalUserCountWithMoreThanOneLoginMethodOrTOTPEnabled").getAsInt();
// JsonArray mfaMaus = mfaStats.get("mauWithMoreThanOneLoginMethodOrTOTPEnabled").getAsJsonArray();
//
// assert mfaMaus.size() == 31;
// assert mfaMaus.get(0).getAsInt() == 0;
// assert mfaMaus.get(29).getAsInt() == 0;

assert mfaMaus.size() == 31;
assert mfaMaus.get(0).getAsInt() == 0;
assert mfaMaus.get(29).getAsInt() == 0;

assert totalMfaUsers == 0;
// assert totalMfaUsers == 0;
}

// First register 2 users for emailpassword recipe.
Expand Down Expand Up @@ -253,15 +253,15 @@ public void testThatCallingGetFeatureFlagAPIReturnsMfaStats() throws Exception {
assert maus.get(0).getAsInt() == 2; // 2 users have signed up
assert maus.get(29).getAsInt() == 2;

JsonObject mfaStats = usageStats.get("mfa").getAsJsonObject();
int totalMfaUsers = mfaStats.get("totalUserCountWithMoreThanOneLoginMethodOrTOTPEnabled").getAsInt();
JsonArray mfaMaus = mfaStats.get("mauWithMoreThanOneLoginMethodOrTOTPEnabled").getAsJsonArray();

assert mfaMaus.size() == 31;
assert mfaMaus.get(0).getAsInt() == 1; // only 1 user has TOTP enabled
assert mfaMaus.get(29).getAsInt() == 1;

assert totalMfaUsers == 1;
// JsonObject mfaStats = usageStats.get("mfa").getAsJsonObject();
// int totalMfaUsers = mfaStats.get("totalUserCountWithMoreThanOneLoginMethodOrTOTPEnabled").getAsInt();
// JsonArray mfaMaus = mfaStats.get("mauWithMoreThanOneLoginMethodOrTOTPEnabled").getAsJsonArray();
//
// assert mfaMaus.size() == 31;
// assert mfaMaus.get(0).getAsInt() == 1; // only 1 user has TOTP enabled
// assert mfaMaus.get(29).getAsInt() == 1;
//
// assert totalMfaUsers == 1;
}

{
Expand Down Expand Up @@ -299,14 +299,14 @@ public void testThatCallingGetFeatureFlagAPIReturnsMfaStats() throws Exception {

{
JsonObject mfaStats = usageStats.get("mfa").getAsJsonObject();
int totalMfaUsers = mfaStats.get("totalUserCountWithMoreThanOneLoginMethodOrTOTPEnabled").getAsInt();
JsonArray mfaMaus = mfaStats.get("mauWithMoreThanOneLoginMethodOrTOTPEnabled").getAsJsonArray();

assert mfaMaus.size() == 31;
assert mfaMaus.get(0).getAsInt() == 2; // 1 TOTP user + 1 account linked user
assert mfaMaus.get(29).getAsInt() == 2;

assert totalMfaUsers == 2;
// int totalMfaUsers = mfaStats.get("totalUserCountWithMoreThanOneLoginMethodOrTOTPEnabled").getAsInt();
// JsonArray mfaMaus = mfaStats.get("mauWithMoreThanOneLoginMethodOrTOTPEnabled").getAsJsonArray();
//
// assert mfaMaus.size() == 31;
// assert mfaMaus.get(0).getAsInt() == 2; // 1 TOTP user + 1 account linked user
// assert mfaMaus.get(29).getAsInt() == 2;
//
// assert totalMfaUsers == 2;
}

// Add TOTP to the linked user
Expand Down Expand Up @@ -342,14 +342,14 @@ public void testThatCallingGetFeatureFlagAPIReturnsMfaStats() throws Exception {

{ // MFA stats should still count 2 users
JsonObject mfaStats = usageStats.get("mfa").getAsJsonObject();
int totalMfaUsers = mfaStats.get("totalUserCountWithMoreThanOneLoginMethodOrTOTPEnabled").getAsInt();
JsonArray mfaMaus = mfaStats.get("mauWithMoreThanOneLoginMethodOrTOTPEnabled").getAsJsonArray();

assert mfaMaus.size() == 31;
assert mfaMaus.get(0).getAsInt() == 2; // 1 TOTP user + 1 account linked user
assert mfaMaus.get(29).getAsInt() == 2;

assert totalMfaUsers == 2;
// int totalMfaUsers = mfaStats.get("totalUserCountWithMoreThanOneLoginMethodOrTOTPEnabled").getAsInt();
// JsonArray mfaMaus = mfaStats.get("mauWithMoreThanOneLoginMethodOrTOTPEnabled").getAsJsonArray();
//
// assert mfaMaus.size() == 31;
// assert mfaMaus.get(0).getAsInt() == 2; // 1 TOTP user + 1 account linked user
// assert mfaMaus.get(29).getAsInt() == 2;
//
// assert totalMfaUsers == 2;
}
}

Expand Down Expand Up @@ -378,14 +378,14 @@ public void testThatCallingGetFeatureFlagAPIReturnsMfaStats() throws Exception {

{ // MFA stats should still count 2 users
JsonObject mfaStats = usageStats.get("mfa").getAsJsonObject();
int totalMfaUsers = mfaStats.get("totalUserCountWithMoreThanOneLoginMethodOrTOTPEnabled").getAsInt();
JsonArray mfaMaus = mfaStats.get("mauWithMoreThanOneLoginMethodOrTOTPEnabled").getAsJsonArray();

assert mfaMaus.size() == 31;
assert mfaMaus.get(0).getAsInt() == 2; // 1 TOTP user + 1 account linked user
assert mfaMaus.get(29).getAsInt() == 2;

assert totalMfaUsers == 2;
// int totalMfaUsers = mfaStats.get("totalUserCountWithMoreThanOneLoginMethodOrTOTPEnabled").getAsInt();
// JsonArray mfaMaus = mfaStats.get("mauWithMoreThanOneLoginMethodOrTOTPEnabled").getAsJsonArray();
//
// assert mfaMaus.size() == 31;
// assert mfaMaus.get(0).getAsInt() == 2; // 1 TOTP user + 1 account linked user
// assert mfaMaus.get(29).getAsInt() == 2;
//
// assert totalMfaUsers == 2;
}
}

Expand Down
Loading

0 comments on commit f1abf7f

Please sign in to comment.