Skip to content

Commit 7c06c6a

Browse files
rishabhpoddarbhumilsarvaiyaRishabhsattvikc
authored
Next breaking change (#336)
* email delivery skeleton added for emailpasword, emailverification and passwordless recipes * changes name of type var and adds comment during normalising of email verification input in emailpassword * pr review changes * more simplification * fixes a bug * removes unnecessary type * fixes a bug with override * code review changes * typo fix for EmailDeliveryIngredient * email delivery ingredient changes for thirdparty and thirdpartyemailpassword and adding deprecated tag for createAndSendCustomEmail functions * creating backward compatibility service class * added deprecation description for createAndSendEmail functions * code review changes * import {STMPService} from "supertokens-node/recipe/emailpassword/emaildelivery" changed to import {STMPService} from "supertokens-node/recipe/emailpassword/emaildelivery/services" * refactor: email sending service code review changes (#280) * code review changes regarding pr #274 * refactors some code and adds builder param to override * adds derived impl of emailverification inside emailpassword emaildelivery * code refactoring: updated variables and file names Co-authored-by: Rishabh <[email protected]> * adding smtp class for thirdparty, thirdpartyemailpassword and passwordless recipes (#281) * refactor: email sending service, Email Delivery and SMTP class changes for thirdpartypasswordless (#282) * email delivery changes for thirdpartypasswordless recipe * code review changes * refactor: emaildelivery config and export (#284) * email delivery config and export refactored * code review changes * moving emailDelivery config in passwordless to be at root level (#287) * sms delivery skeleton added (#288) * sms delivery skeleton added * code review changes * TypeInputWithService changes for emailDelivery ingredient * feat: Twilio service (email and sms sending service) (#289) * twilio smsdelivery service added * email template update and default sms sending function changes * code review changes * changelog updated * code review changes (changelog update) * changelog updated * refactor: code review changes and ts playground updated (#302) * refactor: code review changes and ts playground updated * review changes: added TP, TPEP, EP emailDeliery example * code review changes * feat: supertokens sms delivery service (#301) * feat: supertokens sms delivery service * making apiKey compulsory for supertokens sms service * code review changes * fixes typo * test: email delivery ingredient tests added (#303) * test: added tests for sms delivery ingredient (#304) * test: added tests for sms delivery ingredient * fix in test * refactor: code review changes (#305) * refactor: BackwardCompatibilityService changes for TPEP (#312) * fix: additional logging for email and sms service (#317) * refactor: adding logs when email sending fails * fix: fixing log for general error * refactor: using debug log instead of console.log * refactor: adding logs when sms sending fails * fix: adding success logs * fix: adding logs when intentionally not sending email or sms * fix: adding missed throws * fix: PR comments * fix: PR comments * fix: Humanise time (#318) * refactor: adding logs when email sending fails * fix: fixing log for general error * refactor: using debug log instead of console.log * refactor: adding logs when sms sending fails * fix: adding success logs * fix: adding logs when intentionally not sending email or sms * fix: adding missed throws * feat: adding humaniseMilliseconds function * fix: using humaniseMilliseconds for codeLifetime * fix: fixing log messages * fix: PR comments * fix: PR comments * refactor: code review changes (#319) * refactor: code review changes for PR 274 * refactor: code review changes * code review changes * code review changes * refactor: code review changes (#321) * refactor: code review changes * code review changes * removes unneeded comment * feat!: General error from apis (#323) * sends general error on email verification email sending failure * changes to emailpassword recipe * changes to jwt and open id recipe * passwordless recipe change * changes all other recipes as well * removes sending general error from our APIs due to email failure and thirdparty profile info failure * adds frontend integration test for general API * changes supertokens sms service to take API key directly * bumps version * fixes a few tests * fixes a few tests * fixes more tests Co-authored-by: Bhumil Sarvaiya <[email protected]> Co-authored-by: Rishabh <[email protected]> Co-authored-by: Sattvik Chakravarthy <[email protected]>
1 parent f180063 commit 7c06c6a

File tree

76 files changed

+953
-618
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

76 files changed

+953
-618
lines changed

CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [unreleased]
99

10+
## [10.0.0] - 2022-06-2
11+
12+
### Breaking change
13+
14+
- https://github.com/supertokens/supertokens-node/issues/220
15+
- Adds `{status: "GENERAL_ERROR", message: string}` as a possible output to all the APIs.
16+
- Changes `FIELD_ERROR` output status in third party recipe API to be `GENERAL_ERROR`.
17+
- Replaced `FIELD_ERROR` status type in third party signinup API with `GENERAL_ERROR`.
18+
- Removed `FIELD_ERROR` status type from third party signinup recipe function.
19+
- If sms or email sending failed in passwordless recipe APIs, we now throw a regular JS error from the API as opposed to returning a `GENERAL_ERROR` to the client.
20+
- If there is an error whilst getting the profile info about a user from a third party provider (in /signinup POST API), then we throw a regular JS error instead of returning a `GENERAL_ERROR` to the client.
21+
- Changes SuperTokensSMS service to take an API key directly as opposed to take an object that takes an API key
22+
1023
### Changes
1124

1225
- Fixes Cookie sameSite config validation.
Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,2 @@
11
// @ts-nocheck
2-
export declare type SupertokensServiceConfig = {
3-
apiKey: string;
4-
};
52
export declare const SUPERTOKENS_SMS_SERVICE_URL = "https://api.supertokens.com/0/services/sms";

lib/build/recipe/emailpassword/api/signup.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ function signUpAPI(apiImplementation, options) {
6565
status: "OK",
6666
user: result.user,
6767
});
68+
} else if (result.status === "GENERAL_ERROR") {
69+
utils_1.send200Response(options.res, result);
6870
} else {
6971
throw new error_1.default({
7072
type: error_1.default.FIELD_ERROR,

lib/build/recipe/emailpassword/types.d.ts

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
} from "../../ingredients/emaildelivery/types";
1414
import { TypeEmailVerificationEmailDeliveryInput } from "../emailverification/types";
1515
import EmailDeliveryIngredient from "../../ingredients/emaildelivery";
16+
import { GeneralErrorResponse } from "../../types";
1617
export declare type TypeNormalisedInput = {
1718
signUpFeature: TypeNormalisedInputSignUp;
1819
signInFeature: TypeNormalisedInputSignIn;
@@ -194,10 +195,13 @@ export declare type APIInterface = {
194195
email: string;
195196
options: APIOptions;
196197
userContext: any;
197-
}) => Promise<{
198-
status: "OK";
199-
exists: boolean;
200-
}>);
198+
}) => Promise<
199+
| {
200+
status: "OK";
201+
exists: boolean;
202+
}
203+
| GeneralErrorResponse
204+
>);
201205
generatePasswordResetTokenPOST:
202206
| undefined
203207
| ((input: {
@@ -207,9 +211,12 @@ export declare type APIInterface = {
207211
}[];
208212
options: APIOptions;
209213
userContext: any;
210-
}) => Promise<{
211-
status: "OK";
212-
}>);
214+
}) => Promise<
215+
| {
216+
status: "OK";
217+
}
218+
| GeneralErrorResponse
219+
>);
213220
passwordResetPOST:
214221
| undefined
215222
| ((input: {
@@ -228,6 +235,7 @@ export declare type APIInterface = {
228235
| {
229236
status: "RESET_PASSWORD_INVALID_TOKEN_ERROR";
230237
}
238+
| GeneralErrorResponse
231239
>);
232240
signInPOST:
233241
| undefined
@@ -247,6 +255,7 @@ export declare type APIInterface = {
247255
| {
248256
status: "WRONG_CREDENTIALS_ERROR";
249257
}
258+
| GeneralErrorResponse
250259
>);
251260
signUpPOST:
252261
| undefined
@@ -266,6 +275,7 @@ export declare type APIInterface = {
266275
| {
267276
status: "EMAIL_ALREADY_EXISTS_ERROR";
268277
}
278+
| GeneralErrorResponse
269279
>);
270280
};
271281
export declare type TypeEmailPasswordPasswordResetEmailDeliveryInput = {

lib/build/recipe/emailverification/types.d.ts

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
TypeInputWithService as EmailDeliveryTypeInputWithService,
77
} from "../../ingredients/emaildelivery/types";
88
import EmailDeliveryIngredient from "../../ingredients/emaildelivery";
9+
import { GeneralErrorResponse } from "../../types";
910
export declare type TypeInput = {
1011
emailDelivery?: EmailDeliveryTypeInput<TypeEmailVerificationEmailDeliveryInput>;
1112
getEmailForUserId: (userId: string, userContext: any) => Promise<string>;
@@ -106,24 +107,31 @@ export declare type APIInterface = {
106107
| {
107108
status: "EMAIL_VERIFICATION_INVALID_TOKEN_ERROR";
108109
}
110+
| GeneralErrorResponse
109111
>);
110112
isEmailVerifiedGET:
111113
| undefined
112114
| ((input: {
113115
options: APIOptions;
114116
userContext: any;
115-
}) => Promise<{
116-
status: "OK";
117-
isVerified: boolean;
118-
}>);
117+
}) => Promise<
118+
| {
119+
status: "OK";
120+
isVerified: boolean;
121+
}
122+
| GeneralErrorResponse
123+
>);
119124
generateEmailVerifyTokenPOST:
120125
| undefined
121126
| ((input: {
122127
options: APIOptions;
123128
userContext: any;
124-
}) => Promise<{
125-
status: "EMAIL_ALREADY_VERIFIED_ERROR" | "OK";
126-
}>);
129+
}) => Promise<
130+
| {
131+
status: "EMAIL_ALREADY_VERIFIED_ERROR" | "OK";
132+
}
133+
| GeneralErrorResponse
134+
>);
127135
};
128136
export declare type TypeEmailVerificationEmailDeliveryInput = {
129137
type: "EMAIL_VERIFICATION";

lib/build/recipe/jwt/api/getJWKS.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,13 @@ function getJWKS(apiImplementation, options) {
5151
if (apiImplementation.getJWKSGET === undefined) {
5252
return false;
5353
}
54-
options.res.setHeader("Access-Control-Allow-Origin", "*", false);
5554
let result = yield apiImplementation.getJWKSGET({ options, userContext: {} });
56-
utils_1.send200Response(options.res, { keys: result.keys });
55+
if (result.status === "OK") {
56+
options.res.setHeader("Access-Control-Allow-Origin", "*", false);
57+
utils_1.send200Response(options.res, { keys: result.keys });
58+
} else {
59+
utils_1.send200Response(options.res, result);
60+
}
5761
return true;
5862
});
5963
}

lib/build/recipe/jwt/types.d.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// @ts-nocheck
22
import { BaseRequest, BaseResponse } from "../../framework";
33
import OverrideableBuilder from "supertokens-js-override";
4+
import { GeneralErrorResponse } from "../../types";
45
export declare type JsonWebKey = {
56
kty: string;
67
kid: string;
@@ -64,8 +65,11 @@ export declare type APIInterface = {
6465
| ((input: {
6566
options: APIOptions;
6667
userContext: any;
67-
}) => Promise<{
68-
status: "OK";
69-
keys: JsonWebKey[];
70-
}>);
68+
}) => Promise<
69+
| {
70+
status: "OK";
71+
keys: JsonWebKey[];
72+
}
73+
| GeneralErrorResponse
74+
>);
7175
};

lib/build/recipe/openid/api/getOpenIdDiscoveryConfiguration.js

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,16 @@ function getOpenIdDiscoveryConfiguration(apiImplementation, options) {
5151
if (apiImplementation.getOpenIdDiscoveryConfigurationGET === undefined) {
5252
return false;
5353
}
54-
options.res.setHeader("Access-Control-Allow-Origin", "*", false);
5554
let result = yield apiImplementation.getOpenIdDiscoveryConfigurationGET({ options, userContext: {} });
56-
utils_1.send200Response(options.res, {
57-
issuer: result.issuer,
58-
jwks_uri: result.jwks_uri,
59-
});
55+
if (result.status === "OK") {
56+
options.res.setHeader("Access-Control-Allow-Origin", "*", false);
57+
utils_1.send200Response(options.res, {
58+
issuer: result.issuer,
59+
jwks_uri: result.jwks_uri,
60+
});
61+
} else {
62+
utils_1.send200Response(options.res, result);
63+
}
6064
return true;
6165
});
6266
}

lib/build/recipe/openid/types.d.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { BaseRequest, BaseResponse } from "../../framework";
44
import NormalisedURLDomain from "../../normalisedURLDomain";
55
import NormalisedURLPath from "../../normalisedURLPath";
66
import { RecipeInterface as JWTRecipeInterface, APIInterface as JWTAPIInterface, JsonWebKey } from "../jwt/types";
7+
import { GeneralErrorResponse } from "../../types";
78
export declare type TypeInput = {
89
issuer?: string;
910
jwtValiditySeconds?: number;
@@ -60,11 +61,14 @@ export declare type APIInterface = {
6061
| ((input: {
6162
options: APIOptions;
6263
userContext: any;
63-
}) => Promise<{
64-
status: "OK";
65-
issuer: string;
66-
jwks_uri: string;
67-
}>);
64+
}) => Promise<
65+
| {
66+
status: "OK";
67+
issuer: string;
68+
jwks_uri: string;
69+
}
70+
| GeneralErrorResponse
71+
>);
6872
};
6973
export declare type RecipeInterface = {
7074
getOpenIdDiscoveryConfiguration(input: {

lib/build/recipe/passwordless/api/implementation.js

Lines changed: 57 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -117,41 +117,34 @@ function getAPIImplementation() {
117117
if (flowType === "USER_INPUT_CODE" || flowType === "USER_INPUT_CODE_AND_MAGIC_LINK") {
118118
userInputCode = response.userInputCode;
119119
}
120-
try {
121-
// we don't do something special for serverless env here
122-
// cause we want to wait for service's reply since it can show
123-
// a UI error message for if sending an SMS / email failed or not.
124-
if (
125-
input.options.config.contactMethod === "PHONE" ||
126-
(input.options.config.contactMethod === "EMAIL_OR_PHONE" && "phoneNumber" in input)
127-
) {
128-
logger_1.logDebugMessage(`Sending passwordless login SMS to ${input.phoneNumber}`);
129-
yield input.options.smsDelivery.ingredientInterfaceImpl.sendSms({
130-
type: "PASSWORDLESS_LOGIN",
131-
codeLifetime: response.codeLifetime,
132-
phoneNumber: input.phoneNumber,
133-
preAuthSessionId: response.preAuthSessionId,
134-
urlWithLinkCode: magicLink,
135-
userInputCode,
136-
userContext: input.userContext,
137-
});
138-
} else {
139-
logger_1.logDebugMessage(`Sending passwordless login email to ${input.email}`);
140-
yield input.options.emailDelivery.ingredientInterfaceImpl.sendEmail({
141-
type: "PASSWORDLESS_LOGIN",
142-
email: input.email,
143-
codeLifetime: response.codeLifetime,
144-
preAuthSessionId: response.preAuthSessionId,
145-
urlWithLinkCode: magicLink,
146-
userInputCode,
147-
userContext: input.userContext,
148-
});
149-
}
150-
} catch (err) {
151-
return {
152-
status: "GENERAL_ERROR",
153-
message: err.message,
154-
};
120+
// we don't do something special for serverless env here
121+
// cause we want to wait for service's reply since it can show
122+
// a UI error message for if sending an SMS / email failed or not.
123+
if (
124+
input.options.config.contactMethod === "PHONE" ||
125+
(input.options.config.contactMethod === "EMAIL_OR_PHONE" && "phoneNumber" in input)
126+
) {
127+
logger_1.logDebugMessage(`Sending passwordless login SMS to ${input.phoneNumber}`);
128+
yield input.options.smsDelivery.ingredientInterfaceImpl.sendSms({
129+
type: "PASSWORDLESS_LOGIN",
130+
codeLifetime: response.codeLifetime,
131+
phoneNumber: input.phoneNumber,
132+
preAuthSessionId: response.preAuthSessionId,
133+
urlWithLinkCode: magicLink,
134+
userInputCode,
135+
userContext: input.userContext,
136+
});
137+
} else {
138+
logger_1.logDebugMessage(`Sending passwordless login email to ${input.email}`);
139+
yield input.options.emailDelivery.ingredientInterfaceImpl.sendEmail({
140+
type: "PASSWORDLESS_LOGIN",
141+
email: input.email,
142+
codeLifetime: response.codeLifetime,
143+
preAuthSessionId: response.preAuthSessionId,
144+
urlWithLinkCode: magicLink,
145+
userInputCode,
146+
userContext: input.userContext,
147+
});
155148
}
156149
return {
157150
status: "OK",
@@ -251,42 +244,35 @@ function getAPIImplementation() {
251244
if (flowType === "USER_INPUT_CODE" || flowType === "USER_INPUT_CODE_AND_MAGIC_LINK") {
252245
userInputCode = response.userInputCode;
253246
}
254-
try {
255-
// we don't do something special for serverless env here
256-
// cause we want to wait for service's reply since it can show
257-
// a UI error message for if sending an SMS / email failed or not.
258-
if (
259-
input.options.config.contactMethod === "PHONE" ||
260-
(input.options.config.contactMethod === "EMAIL_OR_PHONE" &&
261-
deviceInfo.phoneNumber !== undefined)
262-
) {
263-
logger_1.logDebugMessage(`Sending passwordless login SMS to ${input.phoneNumber}`);
264-
yield input.options.smsDelivery.ingredientInterfaceImpl.sendSms({
265-
type: "PASSWORDLESS_LOGIN",
266-
codeLifetime: response.codeLifetime,
267-
phoneNumber: deviceInfo.phoneNumber,
268-
preAuthSessionId: response.preAuthSessionId,
269-
urlWithLinkCode: magicLink,
270-
userInputCode,
271-
userContext: input.userContext,
272-
});
273-
} else {
274-
logger_1.logDebugMessage(`Sending passwordless login email to ${input.email}`);
275-
yield input.options.emailDelivery.ingredientInterfaceImpl.sendEmail({
276-
type: "PASSWORDLESS_LOGIN",
277-
email: input.email,
278-
codeLifetime: response.codeLifetime,
279-
preAuthSessionId: response.preAuthSessionId,
280-
urlWithLinkCode: magicLink,
281-
userInputCode,
282-
userContext: input.userContext,
283-
});
284-
}
285-
} catch (err) {
286-
return {
287-
status: "GENERAL_ERROR",
288-
message: err.message,
289-
};
247+
// we don't do something special for serverless env here
248+
// cause we want to wait for service's reply since it can show
249+
// a UI error message for if sending an SMS / email failed or not.
250+
if (
251+
input.options.config.contactMethod === "PHONE" ||
252+
(input.options.config.contactMethod === "EMAIL_OR_PHONE" &&
253+
deviceInfo.phoneNumber !== undefined)
254+
) {
255+
logger_1.logDebugMessage(`Sending passwordless login SMS to ${input.phoneNumber}`);
256+
yield input.options.smsDelivery.ingredientInterfaceImpl.sendSms({
257+
type: "PASSWORDLESS_LOGIN",
258+
codeLifetime: response.codeLifetime,
259+
phoneNumber: deviceInfo.phoneNumber,
260+
preAuthSessionId: response.preAuthSessionId,
261+
urlWithLinkCode: magicLink,
262+
userInputCode,
263+
userContext: input.userContext,
264+
});
265+
} else {
266+
logger_1.logDebugMessage(`Sending passwordless login email to ${input.email}`);
267+
yield input.options.emailDelivery.ingredientInterfaceImpl.sendEmail({
268+
type: "PASSWORDLESS_LOGIN",
269+
email: input.email,
270+
codeLifetime: response.codeLifetime,
271+
preAuthSessionId: response.preAuthSessionId,
272+
urlWithLinkCode: magicLink,
273+
userInputCode,
274+
userContext: input.userContext,
275+
});
290276
}
291277
}
292278
return {

0 commit comments

Comments
 (0)