-
-
Notifications
You must be signed in to change notification settings - Fork 720
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 input for api token in playground #5130
Conversation
Signed-off-by: andreas-unleash <[email protected]>
The latest updates on your projects. Learn more about Vercel for Git ↗︎
1 Ignored Deployment
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"If valid token, use the properties to populate the projects and environments inputs" - can we add a test that proves it?
Signed-off-by: andreas-unleash <[email protected]>
Signed-off-by: andreas-unleash <[email protected]>
Signed-off-by: andreas-unleash <[email protected]>
Signed-off-by: andreas-unleash <[email protected]>
Signed-off-by: andreas-unleash <[email protected]>
Signed-off-by: andreas-unleash <[email protected]>
Signed-off-by: andreas-unleash <[email protected]>
Signed-off-by: andreas-unleash <[email protected]>
|
||
const envValue = environmentOptions.filter(({ id }) => | ||
environments.includes(id), | ||
); | ||
|
||
const onSetToken: ComponentProps<typeof TextField>['onChange'] = async ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd suggest to break the algorithm into smaller focused functions so that a reader can figure out the high level algorithm w/o reading all the details
E.g.
const onSetToken: ComponentProps<typeof TextField>['onChange'] = async (event) => {
const tempToken = event.target.value;
setToken?.(tempToken);
if (tempToken === '') {
resetTokenState();
return;
}
try {
validateTokenFormat(tempToken);
const [tokenProject, tokenEnvironment] = extractProjectEnvironmentFromToken(tempToken);
handleTokenProcessing(tokenProject, tempToken);
} catch (e: any) {
setTokenError(e.message);
}
};
const resetTokenState = () => {
setTokenError(undefined);
}
const handleTokenProcessing = (tokenProject: string, tempToken: string) => {
setTokenError(undefined);
setEnvironments([tokenEnvironment]);
if (tokenProject === '[]') {
processTokenWithEmptyProject(tempToken);
return;
}
if (tokenProject === '*') {
setProjects([allOption.id]);
return;
}
validateTokenProject(tokenProject);
}
const processTokenWithEmptyProject = (tempToken: string) => {
const validToken = tokens.find(({ secret }) => secret === tempToken);
if (validToken) {
if (!validToken.projects) {
setProjects([allOption.id]);
} else if (typeof validToken.projects === 'string') {
setProjects([validToken.projects]);
} else if (Array.isArray(validToken.projects)) {
setProjects(validToken.projects);
}
} else {
setTokenError('Invalid token. Please make sure you are using a valid token from this Unleash instance');
}
}
const validateTokenProject = (tokenProject: string) => {
if (!projectsOptions.map((option) => option.id).includes(tokenProject)) {
setTokenError(`Invalid token. Project ${tokenProject} does not exist`);
} else {
setProjects([tokenProject]);
}
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sure thing. thanks
@@ -125,3 +125,20 @@ export const normalizeCustomContextProperties = ( | |||
|
|||
return output; | |||
}; | |||
|
|||
export const validateTokenFormat = (token: string): void => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lots of interesting things to unit test with a dedicated test w/o the UI.
E.g
it('should not throw an error for a valid token format', () => {
const validToken = 'project:environment.otherstuff';
expect(() => validateTokenFormat(validToken)).not.toThrow();
});
it('should throw an error if the token does not have a project or environment', () => {
const invalidToken1 = '.otherstuff'; // Missing project and environment
const invalidToken2 = 'project.otherstuff'; // Missing ':'
const invalidToken3 = 'project:.otherstuff'; // Missing environment
expect(() => validateTokenFormat(invalidToken1)).toThrow('Invalid token format');
expect(() => validateTokenFormat(invalidToken2)).toThrow('Invalid token format');
expect(() => validateTokenFormat(invalidToken3)).toThrow('Invalid token format');
});
it('should throw an error if the environment is an admin token', () => {
const adminToken = 'project:*.otherstuff';
expect(() => validateTokenFormat(adminToken)).toThrow('Admin tokens are not supported in the playground');
});
it('should not throw an error if the environment is not an admin token', () => {
const validToken = 'project:dev.otherstuff';
expect(() => validateTokenFormat(validToken)).not.toThrow();
});
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice work. Added some extra hints but non-blocking approve
Signed-off-by: andreas-unleash <[email protected]>
Signed-off-by: andreas-unleash <[email protected]>
Signed-off-by: andreas-unleash <[email protected]>
Adds a token input in playground.
In the case of tokens that span multiple projects ie
[]:development.etc
it will look into the token definitions to find the token and get the projectsOtherwise it will try to parse the project and environment from the token itself (without checking for it being a valid token)
Also, does not support admin tokens
*:*.etc
Closes # 1-1507