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

Starts defining multi-tenancy APIs. This includes: #526

Merged
merged 4 commits into from
May 23, 2019

Conversation

bojeil-google
Copy link
Contributor

  • Defining type definitions.
  • Adding tenantId to UserRecord and UserImportBuilder.
  • Adding new errors associated with tenant operations.
  • Defines the Tenant object.

As the changes are quite large. This will be split into multiple PRs.

- Defining type definitions.
- Adding tenantId to UserRecord and UserImportBuilder.
- Adding new errors associated with tenant operations.
- Defines the Tenant object.

As the changes are quite large. This will be split into multiple PRs.
Copy link
Contributor

@hiranya911 hiranya911 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't gone through the tests yet, but the implementation looks pretty good. Just a few suggestions to make the code more TypeScript idiomatic. In general:

  1. Reduce the use of any in method arguments, and use specific types/interfaces whenever possible. If you must use any, see {[key: string]: any} is a better alternative.
  2. Double check that the exported things really need to be exported.

'INTERNAL ASSERT FAILED: Invalid email sign-in configuration response');
}
utils.addReadonlyGetter(this, 'enabled', response.allowPasswordSignup);
utils.addReadonlyGetter(this, 'passwordRequired', !response.enableEmailLinkSignin);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assign to the attributes here.

this.enabled = response.allowPasswordSignup;
this.passwordRequired = !response.enableEmailLinkSignin;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

* EmailSignInConfig object.
* @constructor
*/
constructor(response: any) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use type {[key: string]: any}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

*
* @param {any} options The options object to validate.
*/
public static validate(options: any) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use type {[key: string]: any}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

* @param {any} options The options object to convert to a server request.
* @return {EmailSignInConfigServerRequest} The resulting server request.
*/
public static buildServerRequest(options: any): EmailSignInConfigServerRequest {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use type {[key: string]: any}

PS: Seeing how this get called, you can probably even annotate this with type EmailSignInProviderConfig. We still need to do the validations due to type erasure at runtime.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to EmailSignInProviderConfig

*
* @param {any} options The options object to validate.
*/
public static validate(options: any) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if this is getting called from elsewhere. If not lets make it private.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

* @param {any} request The tenant options object to validate.
* @param {boolean} createRequest Whether this is a create request.
*/
public static validate(request: any, createRequest: boolean) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can be private?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

'INTERNAL ASSERT FAILED: Invalid tenant response',
);
}
utils.addReadonlyGetter(this, 'tenantId', tenantId);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Directly assign to the readonly attributed you have defined above.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

src/auth/tenant.ts Show resolved Hide resolved

/** @return {object} The plain object representation of the tenant. */
public toJSON(): object {
const json: any = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inline with return:

return {
  ...
};

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@@ -187,6 +188,7 @@ export class UserRecord {
validAfterTime = parseDate(response.validSince * 1000);
}
utils.addReadonlyGetter(this, 'tokensValidAfterTime', validAfterTime || undefined);
utils.addReadonlyGetter(this, 'tenantId', response.tenantId);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can directly assign to this.tenantId here, but since we've already used the utils method in this constructor, it's ok to leave it as is.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's make the change in a separate PR.

Copy link
Contributor

@hiranya911 hiranya911 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks pretty good. Just a few nits.

try {
this.emailSignInConfig = new EmailSignInConfig(response);
} catch (e) {
this.emailSignInConfig = undefined;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might want to put a comment here to indicate why it's ok to ignore the error.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

`"${label}.displayName" must be a valid non-empty string.`,
);
}
// Validate type type if provided.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

extraneous type

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

public readonly tenantId: string;
public readonly type?: TenantType;
public readonly displayName?: string;
public readonly emailSignInConfig?: EmailSignInConfig | null;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this ever assigned null?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It used to but not anymore. Removed it.

});

it('should set readonly property "enabled" to false on allowPasswordSignup disabled', () => {
const validConfig2 = new EmailSignInConfig({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Give a more descriptive name to the variable that explains the context. Perhaps passwordSignupDisabledConfig?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

});

it('should set readonly property "passwordRequired" to true on email link sign in disabled', () => {
const validConfig2 = new EmailSignInConfig({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const emailLinkSignInDisabledConfig

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Switched to passwordSignupEnabledConfig.

}).to.throw('"EmailSignInConfig.enabled" must be a boolean.');
});

it('should throw when type is specified', () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should throw when type is specified in an update request

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

it('should throw when type is specified', () => {
const tenantOptionsClientRequest: TenantOptions = deepCopy(tenantOptions);
tenantOptionsClientRequest.type = 'lightweight';
expect(() => Tenant.buildServerRequest(tenantOptionsClientRequest, false))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Calls like this can be made more readable if you define a constant somewhere for false:

const createRequest = true;

Tenant.buildServerRequest(tenantOptionsClientRequest, !createRequest)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

});
});

it('should throw on update with specified type', () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like a duplicate.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed

.to.equal('TENANT_ID');
});

it('should return the expected tenant ID from resource name with multiple tenants substring', () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only difference from the previous test case is that this seems to use a different project ID. Was that intentional?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I updated the description. I am testing when the projectId contains the "tenants" substring.

* @return {object} A sample valid user response as returned from getAccountInfo
* endpoint.
*/
function getValidUserResponse(): object {
return {
function getValidUserResponse(tenantId?: string): any {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use {[key: string}: any} instead of any.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Copy link
Contributor

@hiranya911 hiranya911 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍

@hiranya911
Copy link
Contributor

I see one of the GCB triggers are stuck. Let me know if that's somehow preventing you from being able to merge this.

@bojeil-google
Copy link
Contributor Author

Yeah I am unable to squash and merge due to that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants