Skip to content
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

feat: Add interfaces and types for bulk import #138

Closed
wants to merge 11 commits into from
Closed
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Copyright (c) 2024, VRAI Labs and/or its affiliates. All rights reserved.
*
* This software is licensed under the Apache License, Version 2.0 (the
* "License") as published by the Apache Software Foundation.
*
* You may not use this file except in compliance with the License. You may
* obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/

package io.supertokens.pluginInterface.bulkimport;

import java.util.List;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;


import io.supertokens.pluginInterface.exceptions.StorageQueryException;
import io.supertokens.pluginInterface.multitenancy.AppIdentifier;
import io.supertokens.pluginInterface.multitenancy.exceptions.TenantOrAppNotFoundException;
import io.supertokens.pluginInterface.nonAuthRecipe.NonAuthRecipeStorage;

public interface BulkImportStorage extends NonAuthRecipeStorage {
/**
* Add users to the bulk_import_users table
*/
void addBulkImportUsers(AppIdentifier appIdentifier, List<BulkImportUser> users)
throws StorageQueryException,
TenantOrAppNotFoundException,
io.supertokens.pluginInterface.bulkimport.exceptions.DuplicateUserIdException;

/**
* Get users from the bulk_import_users table
*/
List<BulkImportUserInfo> getBulkImportUsers(AppIdentifier appIdentifier, @Nonnull Integer limit, @Nullable BulkImportUserStatus status,
@Nullable String bulkImportUserId, @Nullable Long createdAt) throws StorageQueryException;

/**
* Delete users by id from the bulk_import_users table
*/
// void deleteBulkImportUsers(AppIdentifier appIdentifier, @Nullable
// ArrayList<String> bulkImportUserIds)
// throws StorageQueryException;

public enum BulkImportUserStatus {
NEW, PROCESSING, FAILED
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
/*
* Copyright (c) 2024, VRAI Labs and/or its affiliates. All rights reserved.
*
* This software is licensed under the Apache License, Version 2.0 (the
* "License") as published by the Apache Software Foundation.
*
* You may not use this file except in compliance with the License. You may
* obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/

package io.supertokens.pluginInterface.bulkimport;

import java.util.List;

import com.google.gson.Gson;
import com.google.gson.JsonObject;

public class BulkImportUser {
public String id;
public String externalUserId;
public JsonObject userMetadata;
public List<String> userRoles;
public List<TotpDevice> totpDevices;
public List<LoginMethod> loginMethods;

public BulkImportUser(String id, String externalUserId, JsonObject userMetadata, List<String> userRoles, List<TotpDevice> totpDevices, List<LoginMethod> loginMethods) {
this.id = id;
this.externalUserId = externalUserId;
this.userMetadata = userMetadata;
this.userRoles = userRoles;
this.totpDevices = totpDevices;
this.loginMethods = loginMethods;
}

public String toString() {
Gson gson = new Gson();
JsonObject json = new JsonObject();

json.addProperty("externalUserId", externalUserId);
json.add("userMetadata", userMetadata);
json.add("roles", gson.toJsonTree(userRoles));
json.add("totp", gson.toJsonTree(totpDevices));
json.add("loginMethods", gson.toJsonTree(loginMethods));

return json.toString();
}

public static class TotpDevice {
public String secretKey;
public int period;
public int skew;
public String deviceName;

public TotpDevice(String secretKey, int period, int skew, String deviceName) {
this.secretKey = secretKey;
this.period = period;
this.skew = skew;
this.deviceName = deviceName;
}
}

public static class LoginMethod {
public String tenantId;
public boolean isVerified;
public boolean isPrimary;
public long timeJoinedInMSSinceEpoch;
public String recipeId;

public EmailPasswordLoginMethod emailPasswordLoginMethod;
public ThirdPartyLoginMethod thirdPartyLoginMethod;
public PasswordlessLoginMethod passwordlessLoginMethod;

public LoginMethod(String tenantId, String recipeId, boolean isVerified, boolean isPrimary, long timeJoinedInMSSinceEpoch, EmailPasswordLoginMethod emailPasswordLoginMethod, ThirdPartyLoginMethod thirdPartyLoginMethod, PasswordlessLoginMethod passwordlessLoginMethod) {
this.tenantId = tenantId;
this.recipeId = recipeId;
this.isVerified = isVerified;
this.isPrimary = isPrimary;
this.timeJoinedInMSSinceEpoch = timeJoinedInMSSinceEpoch;
this.emailPasswordLoginMethod = emailPasswordLoginMethod;
this.thirdPartyLoginMethod = thirdPartyLoginMethod;
this.passwordlessLoginMethod = passwordlessLoginMethod;
}

public static class EmailPasswordLoginMethod {
public String email;
public String passwordHash;
public String hashingAlgorithm;

public EmailPasswordLoginMethod(String email, String passwordHash, String hashingAlgorithm) {
this.email = email;
this.passwordHash = passwordHash;
this.hashingAlgorithm = hashingAlgorithm;
}
}

public static class ThirdPartyLoginMethod {
public String email;
public String thirdPartyId;
public String thirdPartyUserId;

public ThirdPartyLoginMethod(String email, String thirdPartyId, String thirdPartyUserId) {
this.email = email;
this.thirdPartyId = thirdPartyId;
this.thirdPartyUserId = thirdPartyUserId;
}
}

public static class PasswordlessLoginMethod {
public String email;
public String phoneNumber;

public PasswordlessLoginMethod(String email, String phoneNumber) {
this.email = email;
this.phoneNumber = phoneNumber;
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* Copyright (c) 2024, VRAI Labs and/or its affiliates. All rights reserved.
*
* This software is licensed under the Apache License, Version 2.0 (the
* "License") as published by the Apache Software Foundation.
*
* You may not use this file except in compliance with the License. You may
* obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/

package io.supertokens.pluginInterface.bulkimport;

import com.google.gson.JsonObject;

import io.supertokens.pluginInterface.bulkimport.BulkImportStorage.BulkImportUserStatus;

public class BulkImportUserInfo {
rishabhpoddar marked this conversation as resolved.
Show resolved Hide resolved
public String id;
public String rawData;
public BulkImportUserStatus status;
public Long createdAt;
public Long updatedAt;
rishabhpoddar marked this conversation as resolved.
Show resolved Hide resolved

public BulkImportUserInfo(String id, String rawData, BulkImportUserStatus status, Long createdAt, Long updatedAt) {
this.id = id;
this.rawData = rawData;
this.status = status;
this.createdAt = createdAt;
this.updatedAt = updatedAt;
}

public JsonObject toJsonObject() {
JsonObject result = new JsonObject();
result.addProperty("id", id);
result.addProperty("rawData", rawData);
result.addProperty("status", status.toString());
result.addProperty("createdAt", createdAt);
result.addProperty("updatedAt", updatedAt);
return result;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* Copyright (c) 2024, VRAI Labs and/or its affiliates. All rights reserved.
*
* This software is licensed under the Apache License, Version 2.0 (the
* "License") as published by the Apache Software Foundation.
*
* You may not use this file except in compliance with the License. You may
* obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/

package io.supertokens.pluginInterface.bulkimport.exceptions;

public class DuplicateUserIdException extends Exception {
private static final long serialVersionUID = 6848053563771647272L;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright (c) 2024, VRAI Labs and/or its affiliates. All rights reserved.
*
* This software is licensed under the Apache License, Version 2.0 (the
* "License") as published by the Apache Software Foundation.
*
* You may not use this file except in compliance with the License. You may
* obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/

package io.supertokens.pluginInterface.bulkimport.sqlStorage;

import javax.annotation.Nonnull;

import io.supertokens.pluginInterface.bulkimport.BulkImportStorage;
import io.supertokens.pluginInterface.exceptions.StorageQueryException;
import io.supertokens.pluginInterface.multitenancy.AppIdentifier;
import io.supertokens.pluginInterface.sqlStorage.SQLStorage;
import io.supertokens.pluginInterface.sqlStorage.TransactionConnection;

public interface BulkImportSQLStorage extends BulkImportStorage, SQLStorage {

/**
* Update the status of the users in the bulk_import_users table
*/
void updateBulkImportUserStatus_Transaction(AppIdentifier appIdentifier,
TransactionConnection con, @Nonnull String[] bulkImportUserIds, @Nonnull BulkImportUserStatus status) throws StorageQueryException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import io.supertokens.pluginInterface.STORAGE_TYPE;
import io.supertokens.pluginInterface.Storage;
import io.supertokens.pluginInterface.authRecipe.AuthRecipeStorage;
import io.supertokens.pluginInterface.bulkimport.BulkImportStorage;
import io.supertokens.pluginInterface.dashboard.sqlStorage.DashboardSQLStorage;
import io.supertokens.pluginInterface.emailpassword.sqlStorage.EmailPasswordSQLStorage;
import io.supertokens.pluginInterface.emailverification.sqlStorage.EmailVerificationSQLStorage;
Expand Down Expand Up @@ -159,4 +160,12 @@ public ActiveUsersSQLStorage getActiveUsersStorage() {
}
return (ActiveUsersSQLStorage) this.storage;
}

public BulkImportStorage getBulkImportStorage() {
if (this.storage.getType() != STORAGE_TYPE.SQL) {
// we only support SQL for now
throw new UnsupportedOperationException("");
}
return (BulkImportStorage) this.storage;
}
rishabhpoddar marked this conversation as resolved.
Show resolved Hide resolved
}
Loading