Skip to content

Commit 5983f8c

Browse files
porcellusMihaly LengyelSiddharth MudgalRishabh
authored
Passwordless (#27)
* Adding passwordless * Updated changelog * Combined functions for phone/email + removed unnecessary non-transaction methods * Re-added get querys to use withouth locking + removed EmptyContactInfoException We should throw IllegalArgumentException instead * Reverted renaming failedAttempts * Re-added exceptions into combined methods * Lint fix * Updated based on review in supertokens-core * Removed no longer necessary method * Consolidated arguments into objects for create operations * Removed transaction parts from updateUser * Update user moved into transaction * Added auto-generated hashCode & equals to PWLessCode * Removed unnecessary locking getUserById * Cleaned up generated equals a bit * Salting linkCodes * Fixed param naming * changes version * rebuilds jar * adds jar * Adding delete user for pwless Co-authored-by: Mihaly Lengyel <[email protected]> Co-authored-by: Siddharth Mudgal <[email protected]> Co-authored-by: Rishabh <[email protected]>
1 parent 9ccde8a commit 5983f8c

15 files changed

+425
-4
lines changed

CHANGELOG.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
66

77
## [Unreleased]
88

9-
## [2.10.0] - 2021-12-16
9+
## [2.10.0] - 2021-11-16
1010

11-
### Added
11+
# Added
1212

13+
- Passwordless interface
1314
- User deletion methods
1415

1516
## [2.9.0] - 2021-08-08

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ plugins {
22
id 'java-library'
33
}
44

5-
version = "2.10.0"
5+
version = "2.11.0"
66

77
repositories {
88
mavenCentral()
Binary file not shown.

src/main/java/io/supertokens/pluginInterface/RECIPE_ID.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
public enum RECIPE_ID {
2121

2222
EMAIL_PASSWORD("emailpassword"), THIRD_PARTY("thirdparty"), SESSION("session"),
23-
EMAIL_VERIFICATION("emailverification"), JWT("jwt");
23+
EMAIL_VERIFICATION("emailverification"), JWT("jwt"), PASSWORDLESS("passwordless");
2424

2525
private final String name;
2626

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package io.supertokens.pluginInterface.passwordless;
2+
3+
public class PasswordlessCode {
4+
public final String id;
5+
public final String deviceIdHash;
6+
public final String linkCodeHash;
7+
public final Long createdAt;
8+
9+
public PasswordlessCode(String id, String deviceIdHash, String linkCodeHash, Long createdAt) {
10+
this.id = id;
11+
this.deviceIdHash = deviceIdHash;
12+
this.linkCodeHash = linkCodeHash;
13+
this.createdAt = createdAt;
14+
}
15+
16+
@Override
17+
public int hashCode() {
18+
final int prime = 31;
19+
int result = 1;
20+
result = prime * result + ((createdAt == null) ? 0 : createdAt.hashCode());
21+
result = prime * result + ((deviceIdHash == null) ? 0 : deviceIdHash.hashCode());
22+
result = prime * result + ((id == null) ? 0 : id.hashCode());
23+
result = prime * result + ((linkCodeHash == null) ? 0 : linkCodeHash.hashCode());
24+
return result;
25+
}
26+
27+
@Override
28+
public boolean equals(Object obj) {
29+
if (this == obj) {
30+
return true;
31+
}
32+
if (obj == null) {
33+
return false;
34+
}
35+
if (!(obj instanceof PasswordlessCode)) {
36+
return false;
37+
}
38+
PasswordlessCode other = (PasswordlessCode) obj;
39+
if (createdAt == null) {
40+
if (other.createdAt != null) {
41+
return false;
42+
}
43+
} else if (!createdAt.equals(other.createdAt)) {
44+
return false;
45+
}
46+
if (deviceIdHash == null) {
47+
if (other.deviceIdHash != null) {
48+
return false;
49+
}
50+
} else if (!deviceIdHash.equals(other.deviceIdHash)) {
51+
return false;
52+
}
53+
if (id == null) {
54+
if (other.id != null) {
55+
return false;
56+
}
57+
} else if (!id.equals(other.id)) {
58+
return false;
59+
}
60+
if (linkCodeHash == null) {
61+
if (other.linkCodeHash != null) {
62+
return false;
63+
}
64+
} else if (!linkCodeHash.equals(other.linkCodeHash)) {
65+
return false;
66+
}
67+
return true;
68+
}
69+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Copyright (c) 2020, VRAI Labs and/or its affiliates. All rights reserved.
3+
*
4+
* This software is licensed under the Apache License, Version 2.0 (the
5+
* "License") as published by the Apache Software Foundation.
6+
*
7+
* You may not use this file except in compliance with the License. You may
8+
* obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
* License for the specific language governing permissions and limitations
14+
* under the License.
15+
*/
16+
17+
package io.supertokens.pluginInterface.passwordless;
18+
19+
public class PasswordlessDevice {
20+
public final String deviceIdHash;
21+
public final String email;
22+
public final String phoneNumber;
23+
public final String linkCodeSalt;
24+
public final int failedAttempts;
25+
26+
public PasswordlessDevice(String deviceIdHash, String email, String phoneNumber, String linkCodeSalt,
27+
int failedAttempts) {
28+
this.deviceIdHash = deviceIdHash;
29+
this.email = email;
30+
this.phoneNumber = phoneNumber;
31+
this.failedAttempts = failedAttempts;
32+
this.linkCodeSalt = linkCodeSalt;
33+
}
34+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* Copyright (c) 2020, VRAI Labs and/or its affiliates. All rights reserved.
3+
*
4+
* This software is licensed under the Apache License, Version 2.0 (the
5+
* "License") as published by the Apache Software Foundation.
6+
*
7+
* You may not use this file except in compliance with the License. You may
8+
* obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
* License for the specific language governing permissions and limitations
14+
* under the License.
15+
*/
16+
17+
package io.supertokens.pluginInterface.passwordless;
18+
19+
import io.supertokens.pluginInterface.authRecipe.AuthRecipeStorage;
20+
import io.supertokens.pluginInterface.emailpassword.exceptions.DuplicateEmailException;
21+
import io.supertokens.pluginInterface.emailpassword.exceptions.DuplicateUserIdException;
22+
import io.supertokens.pluginInterface.exceptions.StorageQueryException;
23+
import io.supertokens.pluginInterface.passwordless.exception.DuplicateCodeIdException;
24+
import io.supertokens.pluginInterface.passwordless.exception.DuplicateDeviceIdHashException;
25+
import io.supertokens.pluginInterface.passwordless.exception.DuplicateLinkCodeHashException;
26+
import io.supertokens.pluginInterface.passwordless.exception.DuplicatePhoneNumberException;
27+
import io.supertokens.pluginInterface.passwordless.exception.UnknownDeviceIdHash;
28+
29+
import javax.annotation.Nonnull;
30+
import javax.annotation.Nullable;
31+
32+
public interface PasswordlessStorage extends AuthRecipeStorage {
33+
void createDeviceWithCode(@Nullable String email, @Nullable String phoneNumber, @Nonnull String linkCodeSalt,
34+
PasswordlessCode code) throws StorageQueryException, DuplicateDeviceIdHashException,
35+
DuplicateCodeIdException, DuplicateLinkCodeHashException;
36+
37+
void createCode(PasswordlessCode code)
38+
throws StorageQueryException, UnknownDeviceIdHash, DuplicateCodeIdException, DuplicateLinkCodeHashException;
39+
40+
void createUser(UserInfo user) throws StorageQueryException, DuplicateEmailException, DuplicatePhoneNumberException,
41+
DuplicateUserIdException;
42+
43+
void deletePasswordlessUser(String userId) throws StorageQueryException;
44+
45+
PasswordlessDevice getDevice(String deviceIdHash) throws StorageQueryException;
46+
47+
PasswordlessDevice[] getDevicesByEmail(@Nonnull String email) throws StorageQueryException;
48+
49+
PasswordlessDevice[] getDevicesByPhoneNumber(@Nonnull String phoneNumber) throws StorageQueryException;
50+
51+
PasswordlessCode[] getCodesOfDevice(String deviceIdHash) throws StorageQueryException;
52+
53+
PasswordlessCode[] getCodesBefore(long time) throws StorageQueryException;
54+
55+
PasswordlessCode getCode(String codeId) throws StorageQueryException;
56+
57+
PasswordlessCode getCodeByLinkCodeHash(String linkCode) throws StorageQueryException;
58+
59+
UserInfo getUserById(String userId) throws StorageQueryException;
60+
61+
UserInfo getUserByEmail(@Nonnull String email) throws StorageQueryException;
62+
63+
UserInfo getUserByPhoneNumber(@Nonnull String phoneNumber) throws StorageQueryException;
64+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* Copyright (c) 2020, VRAI Labs and/or its affiliates. All rights reserved.
3+
*
4+
* This software is licensed under the Apache License, Version 2.0 (the
5+
* "License") as published by the Apache Software Foundation.
6+
*
7+
* You may not use this file except in compliance with the License. You may
8+
* obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
* License for the specific language governing permissions and limitations
14+
* under the License.
15+
*/
16+
17+
package io.supertokens.pluginInterface.passwordless;
18+
19+
import javax.annotation.Nullable;
20+
21+
import io.supertokens.pluginInterface.RECIPE_ID;
22+
import io.supertokens.pluginInterface.authRecipe.AuthRecipeUserInfo;
23+
24+
public class UserInfo extends AuthRecipeUserInfo {
25+
public final String email;
26+
public final String phoneNumber;
27+
28+
public UserInfo(String id, @Nullable String email, @Nullable String phoneNumber, long timeJoined) {
29+
super(id, timeJoined);
30+
31+
if (email == null && phoneNumber == null) {
32+
throw new IllegalArgumentException("Both email and phoneNumber cannot be null");
33+
}
34+
35+
this.email = email;
36+
this.phoneNumber = phoneNumber;
37+
}
38+
39+
@Override
40+
public RECIPE_ID getRecipeId() {
41+
return RECIPE_ID.PASSWORDLESS;
42+
}
43+
44+
@Override
45+
public boolean equals(Object other) {
46+
if (other instanceof UserInfo) {
47+
UserInfo otherUserInfo = (UserInfo) other;
48+
return ((otherUserInfo.email == null && this.email == null) || otherUserInfo.email.equals(this.email))
49+
&& ((otherUserInfo.phoneNumber == null && this.phoneNumber == null)
50+
|| otherUserInfo.phoneNumber.equals(this.phoneNumber))
51+
&& otherUserInfo.id.equals(this.id) && otherUserInfo.timeJoined == this.timeJoined;
52+
}
53+
return false;
54+
}
55+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*
2+
* Copyright (c) 2020, VRAI Labs and/or its affiliates. All rights reserved.
3+
*
4+
* This software is licensed under the Apache License, Version 2.0 (the
5+
* "License") as published by the Apache Software Foundation.
6+
*
7+
* You may not use this file except in compliance with the License. You may
8+
* obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
* License for the specific language governing permissions and limitations
14+
* under the License.
15+
*/
16+
17+
package io.supertokens.pluginInterface.passwordless.exception;
18+
19+
import io.supertokens.pluginInterface.emailpassword.exceptions.EmailPasswordException;
20+
21+
public class DuplicateCodeIdException extends EmailPasswordException {
22+
private static final long serialVersionUID = 6848053563771647272L;
23+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*
2+
* Copyright (c) 2020, VRAI Labs and/or its affiliates. All rights reserved.
3+
*
4+
* This software is licensed under the Apache License, Version 2.0 (the
5+
* "License") as published by the Apache Software Foundation.
6+
*
7+
* You may not use this file except in compliance with the License. You may
8+
* obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
* License for the specific language governing permissions and limitations
14+
* under the License.
15+
*/
16+
17+
package io.supertokens.pluginInterface.passwordless.exception;
18+
19+
import io.supertokens.pluginInterface.emailpassword.exceptions.EmailPasswordException;
20+
21+
public class DuplicateDeviceIdHashException extends EmailPasswordException {
22+
private static final long serialVersionUID = 6848053563771647272L;
23+
}

0 commit comments

Comments
 (0)