Skip to content

Commit c500a6d

Browse files
committed
Add signUp API method for auth-next (#2892)
* User should be an interface for now we can make an implementation class later * Add API call to signUp * [AUTOMATED]: Prettier Code Styling * [AUTOMATED]: License Headers * Update tests to test a little more * [AUTOMATED]: Prettier Code Styling
1 parent 8fdceeb commit c500a6d

File tree

10 files changed

+555
-5
lines changed

10 files changed

+555
-5
lines changed

packages-exp/auth-exp/package.json

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,14 @@
3030
},
3131
"dependencies": {
3232
"@firebase/util": "^0.2.44",
33-
"mocha": "^7.1.1",
3433
"tslib": "1.11.1"
3534
},
3635
"license": "Apache-2.0",
3736
"devDependencies": {
3837
"rollup": "1.32.1",
3938
"rollup-plugin-json": "4.0.0",
4039
"rollup-plugin-replace": "2.2.0",
41-
"rollup-plugin-typescript2": "0.26.0",
42-
"typescript": "3.8.3"
40+
"rollup-plugin-typescript2": "0.26.0"
4341
},
4442
"repository": {
4543
"directory": "packages-exp/auth-exp",
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/**
2+
* @license
3+
* Copyright 2020 Google LLC
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
import { expect, use } from 'chai';
19+
import * as chaiAsPromised from 'chai-as-promised';
20+
import { signUp, SignUpRequest } from './sign_up';
21+
import { Endpoint } from '..';
22+
import { ServerError } from '../errors';
23+
import { FirebaseError } from '@firebase/util';
24+
import * as mockFetch from '../../../test/mock_fetch';
25+
import { mockEndpoint, mockAuth } from '../../../test/api/helper';
26+
27+
use(chaiAsPromised);
28+
29+
describe('signUp', () => {
30+
const request: SignUpRequest = {
31+
returnSecureToken: true,
32+
33+
password: 'my-password'
34+
};
35+
36+
beforeEach(mockFetch.setUp);
37+
afterEach(mockFetch.tearDown);
38+
39+
it('should POST to the correct endpoint', async () => {
40+
const mock = mockEndpoint(Endpoint.SIGN_UP, {
41+
displayName: 'my-name',
42+
43+
});
44+
45+
const response = await signUp(mockAuth, request);
46+
expect(response.displayName).to.eq('my-name');
47+
expect(response.email).to.eq('[email protected]');
48+
expect(mock.calls[0].request).to.eql(request);
49+
expect(mock.calls[0].method).to.eq('POST');
50+
expect(mock.calls[0].headers).to.eql({
51+
'Content-Type': 'application/json'
52+
});
53+
});
54+
55+
it('should handle errors', async () => {
56+
const mock = mockEndpoint(
57+
Endpoint.SIGN_UP,
58+
{
59+
error: {
60+
code: 400,
61+
message: ServerError.EMAIL_EXISTS,
62+
errors: [
63+
{
64+
message: ServerError.EMAIL_EXISTS
65+
}
66+
]
67+
}
68+
},
69+
400
70+
);
71+
72+
await expect(signUp(mockAuth, request)).to.be.rejectedWith(
73+
FirebaseError,
74+
'Firebase: The email address is already in use by another account. (auth/email-already-in-use).'
75+
);
76+
expect(mock.calls[0].request).to.eql(request);
77+
});
78+
});
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/**
2+
* @license
3+
* Copyright 2020 Google LLC
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
import { Auth } from '../../model/auth';
19+
import { IdTokenResponse } from '../../model/id_token';
20+
import { performSignInRequest, HttpMethod, Endpoint } from '..';
21+
22+
export interface SignUpRequest {
23+
returnSecureToken?: boolean;
24+
email?: string;
25+
password?: string;
26+
}
27+
28+
export interface SignUpResponse extends IdTokenResponse {
29+
displayName?: string;
30+
email?: string;
31+
}
32+
33+
export async function signUp(
34+
auth: Auth,
35+
request: SignUpRequest
36+
): Promise<SignUpResponse> {
37+
return performSignInRequest<SignUpRequest, SignUpResponse>(
38+
auth,
39+
HttpMethod.POST,
40+
Endpoint.SIGN_UP,
41+
request
42+
);
43+
}
Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,228 @@
1+
/**
2+
* @license
3+
* Copyright 2020 Google LLC
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
import { AuthErrorCode } from '../core/errors';
19+
20+
/**
21+
* Errors that can be returned by the backend
22+
*/
23+
export enum ServerError {
24+
ADMIN_ONLY_OPERATION = 'ADMIN_ONLY_OPERATION',
25+
CAPTCHA_CHECK_FAILED = 'CAPTCHA_CHECK_FAILED',
26+
CORS_UNSUPPORTED = 'CORS_UNSUPPORTED',
27+
CREDENTIAL_MISMATCH = 'CREDENTIAL_MISMATCH',
28+
CREDENTIAL_TOO_OLD_LOGIN_AGAIN = 'CREDENTIAL_TOO_OLD_LOGIN_AGAIN',
29+
DYNAMIC_LINK_NOT_ACTIVATED = 'DYNAMIC_LINK_NOT_ACTIVATED',
30+
EMAIL_EXISTS = 'EMAIL_EXISTS',
31+
EMAIL_NOT_FOUND = 'EMAIL_NOT_FOUND',
32+
EXPIRED_OOB_CODE = 'EXPIRED_OOB_CODE',
33+
FEDERATED_USER_ID_ALREADY_LINKED = 'FEDERATED_USER_ID_ALREADY_LINKED',
34+
INVALID_APP_CREDENTIAL = 'INVALID_APP_CREDENTIAL',
35+
INVALID_APP_ID = 'INVALID_APP_ID',
36+
INVALID_CERT_HASH = 'INVALID_CERT_HASH',
37+
INVALID_CODE = 'INVALID_CODE',
38+
INVALID_CONTINUE_URI = 'INVALID_CONTINUE_URI',
39+
INVALID_CUSTOM_TOKEN = 'INVALID_CUSTOM_TOKEN',
40+
INVALID_DYNAMIC_LINK_DOMAIN = 'INVALID_DYNAMIC_LINK_DOMAIN',
41+
INVALID_EMAIL = 'INVALID_EMAIL',
42+
INVALID_ID_TOKEN = 'INVALID_ID_TOKEN',
43+
INVALID_IDP_RESPONSE = 'INVALID_IDP_RESPONSE',
44+
INVALID_IDENTIFIER = 'INVALID_IDENTIFIER',
45+
INVALID_MESSAGE_PAYLOAD = 'INVALID_MESSAGE_PAYLOAD',
46+
INVALID_OAUTH_CLIENT_ID = 'INVALID_OAUTH_CLIENT_ID',
47+
INVALID_OOB_CODE = 'INVALID_OOB_CODE',
48+
INVALID_PASSWORD = 'INVALID_PASSWORD',
49+
INVALID_PENDING_TOKEN = 'INVALID_PENDING_TOKEN',
50+
INVALID_PHONE_NUMBER = 'INVALID_PHONE_NUMBER',
51+
INVALID_PROVIDER_ID = 'INVALID_PROVIDER_ID',
52+
INVALID_RECIPIENT_EMAIL = 'INVALID_RECIPIENT_EMAIL',
53+
INVALID_SENDER = 'INVALID_SENDER',
54+
INVALID_SESSION_INFO = 'INVALID_SESSION_INFO',
55+
INVALID_TEMPORARY_PROOF = 'INVALID_TEMPORARY_PROOF',
56+
INVALID_TENANT_ID = 'INVALID_TENANT_ID',
57+
MISSING_ANDROID_PACKAGE_NAME = 'MISSING_ANDROID_PACKAGE_NAME',
58+
MISSING_APP_CREDENTIAL = 'MISSING_APP_CREDENTIAL',
59+
MISSING_CODE = 'MISSING_CODE',
60+
MISSING_CONTINUE_URI = 'MISSING_CONTINUE_URI',
61+
MISSING_CUSTOM_TOKEN = 'MISSING_CUSTOM_TOKEN',
62+
MISSING_IOS_BUNDLE_ID = 'MISSING_IOS_BUNDLE_ID',
63+
MISSING_OOB_CODE = 'MISSING_OOB_CODE',
64+
MISSING_OR_INVALID_NONCE = 'MISSING_OR_INVALID_NONCE',
65+
MISSING_PASSWORD = 'MISSING_PASSWORD',
66+
MISSING_REQ_TYPE = 'MISSING_REQ_TYPE',
67+
MISSING_PHONE_NUMBER = 'MISSING_PHONE_NUMBER',
68+
MISSING_SESSION_INFO = 'MISSING_SESSION_INFO',
69+
OPERATION_NOT_ALLOWED = 'OPERATION_NOT_ALLOWED',
70+
PASSWORD_LOGIN_DISABLED = 'PASSWORD_LOGIN_DISABLED',
71+
QUOTA_EXCEEDED = 'QUOTA_EXCEEDED',
72+
RESET_PASSWORD_EXCEED_LIMIT = 'RESET_PASSWORD_EXCEED_LIMIT',
73+
REJECTED_CREDENTIAL = 'REJECTED_CREDENTIAL',
74+
SESSION_EXPIRED = 'SESSION_EXPIRED',
75+
TENANT_ID_MISMATCH = 'TENANT_ID_MISMATCH',
76+
TOKEN_EXPIRED = 'TOKEN_EXPIRED',
77+
TOO_MANY_ATTEMPTS_TRY_LATER = 'TOO_MANY_ATTEMPTS_TRY_LATER',
78+
UNSUPPORTED_TENANT_OPERATION = 'UNSUPPORTED_TENANT_OPERATION',
79+
UNAUTHORIZED_DOMAIN = 'UNAUTHORIZED_DOMAIN',
80+
USER_CANCELLED = 'USER_CANCELLED',
81+
USER_DISABLED = 'USER_DISABLED',
82+
USER_NOT_FOUND = 'USER_NOT_FOUND',
83+
WEAK_PASSWORD = 'WEAK_PASSWORD'
84+
}
85+
86+
/**
87+
* API Response in the event of an error
88+
*/
89+
export interface JsonError {
90+
error: {
91+
code: number;
92+
message: ServerError;
93+
errors: [
94+
{
95+
message: ServerError;
96+
domain: string;
97+
reason: string;
98+
}
99+
];
100+
};
101+
}
102+
103+
/**
104+
* Type definition for a map from server errors to developer visible errors
105+
*/
106+
export declare type ServerErrorMap<ApiError extends string> = {
107+
readonly [K in ApiError]: AuthErrorCode;
108+
};
109+
110+
/**
111+
* Map from errors returned by the server to errors to developer visible errors
112+
*/
113+
export const SERVER_ERROR_MAP: ServerErrorMap<ServerError> = {
114+
// Custom token errors.
115+
[ServerError.INVALID_CUSTOM_TOKEN]: AuthErrorCode.INVALID_CUSTOM_TOKEN,
116+
[ServerError.CREDENTIAL_MISMATCH]: AuthErrorCode.CREDENTIAL_MISMATCH,
117+
// This can only happen if the SDK sends a bad request.
118+
[ServerError.MISSING_CUSTOM_TOKEN]: AuthErrorCode.INTERNAL_ERROR,
119+
120+
// Create Auth URI errors.
121+
[ServerError.INVALID_IDENTIFIER]: AuthErrorCode.INVALID_EMAIL,
122+
// This can only happen if the SDK sends a bad request.
123+
[ServerError.MISSING_CONTINUE_URI]: AuthErrorCode.INTERNAL_ERROR,
124+
125+
// Sign in with email and password errors (some apply to sign up too).
126+
[ServerError.INVALID_EMAIL]: AuthErrorCode.INVALID_EMAIL,
127+
[ServerError.INVALID_PASSWORD]: AuthErrorCode.INVALID_PASSWORD,
128+
[ServerError.USER_DISABLED]: AuthErrorCode.USER_DISABLED,
129+
// This can only happen if the SDK sends a bad request.
130+
[ServerError.MISSING_PASSWORD]: AuthErrorCode.INTERNAL_ERROR,
131+
132+
// Sign up with email and password errors.
133+
[ServerError.EMAIL_EXISTS]: AuthErrorCode.EMAIL_EXISTS,
134+
[ServerError.PASSWORD_LOGIN_DISABLED]: AuthErrorCode.OPERATION_NOT_ALLOWED,
135+
136+
// Verify assertion for sign in with credential errors:
137+
[ServerError.INVALID_IDP_RESPONSE]: AuthErrorCode.INVALID_IDP_RESPONSE,
138+
[ServerError.INVALID_PENDING_TOKEN]: AuthErrorCode.INVALID_IDP_RESPONSE,
139+
[ServerError.FEDERATED_USER_ID_ALREADY_LINKED]:
140+
AuthErrorCode.CREDENTIAL_ALREADY_IN_USE,
141+
[ServerError.MISSING_OR_INVALID_NONCE]:
142+
AuthErrorCode.MISSING_OR_INVALID_NONCE,
143+
144+
// Email template errors while sending emails:
145+
[ServerError.INVALID_MESSAGE_PAYLOAD]: AuthErrorCode.INVALID_MESSAGE_PAYLOAD,
146+
[ServerError.INVALID_RECIPIENT_EMAIL]: AuthErrorCode.INVALID_RECIPIENT_EMAIL,
147+
[ServerError.INVALID_SENDER]: AuthErrorCode.INVALID_SENDER,
148+
// This can only happen if the SDK sends a bad request.
149+
[ServerError.MISSING_REQ_TYPE]: AuthErrorCode.INTERNAL_ERROR,
150+
151+
// Send Password reset email errors:
152+
[ServerError.EMAIL_NOT_FOUND]: AuthErrorCode.USER_DELETED,
153+
[ServerError.RESET_PASSWORD_EXCEED_LIMIT]:
154+
AuthErrorCode.TOO_MANY_ATTEMPTS_TRY_LATER,
155+
156+
// Reset password errors:
157+
[ServerError.EXPIRED_OOB_CODE]: AuthErrorCode.EXPIRED_OOB_CODE,
158+
[ServerError.INVALID_OOB_CODE]: AuthErrorCode.INVALID_OOB_CODE,
159+
// This can only happen if the SDK sends a bad request.
160+
[ServerError.MISSING_OOB_CODE]: AuthErrorCode.INTERNAL_ERROR,
161+
162+
// Get Auth URI errors:
163+
[ServerError.INVALID_PROVIDER_ID]: AuthErrorCode.INVALID_PROVIDER_ID,
164+
165+
// Operations that require ID token in request:
166+
[ServerError.CREDENTIAL_TOO_OLD_LOGIN_AGAIN]:
167+
AuthErrorCode.CREDENTIAL_TOO_OLD_LOGIN_AGAIN,
168+
[ServerError.INVALID_ID_TOKEN]: AuthErrorCode.INVALID_AUTH,
169+
[ServerError.TOKEN_EXPIRED]: AuthErrorCode.TOKEN_EXPIRED,
170+
[ServerError.USER_NOT_FOUND]: AuthErrorCode.TOKEN_EXPIRED,
171+
172+
// CORS issues.
173+
[ServerError.CORS_UNSUPPORTED]: AuthErrorCode.CORS_UNSUPPORTED,
174+
175+
// Dynamic link not activated.
176+
[ServerError.DYNAMIC_LINK_NOT_ACTIVATED]:
177+
AuthErrorCode.DYNAMIC_LINK_NOT_ACTIVATED,
178+
179+
// iosBundleId or androidPackageName not valid error.
180+
[ServerError.INVALID_APP_ID]: AuthErrorCode.INVALID_APP_ID,
181+
182+
// Other errors.
183+
[ServerError.TOO_MANY_ATTEMPTS_TRY_LATER]:
184+
AuthErrorCode.TOO_MANY_ATTEMPTS_TRY_LATER,
185+
[ServerError.WEAK_PASSWORD]: AuthErrorCode.WEAK_PASSWORD,
186+
[ServerError.OPERATION_NOT_ALLOWED]: AuthErrorCode.OPERATION_NOT_ALLOWED,
187+
[ServerError.USER_CANCELLED]: AuthErrorCode.USER_CANCELLED,
188+
189+
// Phone Auth related errors.
190+
[ServerError.CAPTCHA_CHECK_FAILED]: AuthErrorCode.CAPTCHA_CHECK_FAILED,
191+
[ServerError.INVALID_APP_CREDENTIAL]: AuthErrorCode.INVALID_APP_CREDENTIAL,
192+
[ServerError.INVALID_CODE]: AuthErrorCode.INVALID_CODE,
193+
[ServerError.INVALID_PHONE_NUMBER]: AuthErrorCode.INVALID_PHONE_NUMBER,
194+
[ServerError.INVALID_SESSION_INFO]: AuthErrorCode.INVALID_SESSION_INFO,
195+
[ServerError.INVALID_TEMPORARY_PROOF]: AuthErrorCode.INVALID_IDP_RESPONSE,
196+
[ServerError.MISSING_APP_CREDENTIAL]: AuthErrorCode.MISSING_APP_CREDENTIAL,
197+
[ServerError.MISSING_CODE]: AuthErrorCode.MISSING_CODE,
198+
[ServerError.MISSING_PHONE_NUMBER]: AuthErrorCode.MISSING_PHONE_NUMBER,
199+
[ServerError.MISSING_SESSION_INFO]: AuthErrorCode.MISSING_SESSION_INFO,
200+
[ServerError.QUOTA_EXCEEDED]: AuthErrorCode.QUOTA_EXCEEDED,
201+
[ServerError.SESSION_EXPIRED]: AuthErrorCode.CODE_EXPIRED,
202+
[ServerError.REJECTED_CREDENTIAL]: AuthErrorCode.REJECTED_CREDENTIAL,
203+
204+
// Other action code errors when additional settings passed.
205+
[ServerError.INVALID_CONTINUE_URI]: AuthErrorCode.INVALID_CONTINUE_URI,
206+
// MISSING_CONTINUE_URI is getting mapped to INTERNAL_ERROR above.
207+
// This is OK as this error will be caught by client side validation.
208+
[ServerError.MISSING_ANDROID_PACKAGE_NAME]:
209+
AuthErrorCode.MISSING_ANDROID_PACKAGE_NAME,
210+
[ServerError.MISSING_IOS_BUNDLE_ID]: AuthErrorCode.MISSING_IOS_BUNDLE_ID,
211+
[ServerError.UNAUTHORIZED_DOMAIN]: AuthErrorCode.UNAUTHORIZED_DOMAIN,
212+
[ServerError.INVALID_DYNAMIC_LINK_DOMAIN]:
213+
AuthErrorCode.INVALID_DYNAMIC_LINK_DOMAIN,
214+
215+
// getProjectConfig errors when clientId is passed.
216+
[ServerError.INVALID_OAUTH_CLIENT_ID]: AuthErrorCode.INVALID_OAUTH_CLIENT_ID,
217+
// getProjectConfig errors when sha1Cert is passed.
218+
[ServerError.INVALID_CERT_HASH]: AuthErrorCode.INVALID_CERT_HASH,
219+
220+
// Multi-tenant related errors.
221+
[ServerError.UNSUPPORTED_TENANT_OPERATION]:
222+
AuthErrorCode.UNSUPPORTED_TENANT_OPERATION,
223+
[ServerError.INVALID_TENANT_ID]: AuthErrorCode.INVALID_TENANT_ID,
224+
[ServerError.TENANT_ID_MISMATCH]: AuthErrorCode.TENANT_ID_MISMATCH,
225+
226+
// User actions (sign-up or deletion) disabled errors.
227+
[ServerError.ADMIN_ONLY_OPERATION]: AuthErrorCode.ADMIN_ONLY_OPERATION
228+
};

0 commit comments

Comments
 (0)