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

Fix broken image urls in Settings > Profile and Invite To Workspace Email #8942

Merged
merged 5 commits into from
Dec 7, 2024

Conversation

charlesBochet
Copy link
Member

Fixes #8601

We had 3 implementations of getImageAbsoluteURI: in twenty-front, in twenty-ui and in twenty-emails. I was able to remove the one in twenty-front but I could not remove it from twenty-emails as this is a standalone for now. The vision is to introduce shared utils in a twenty-shared package

@@ -20,7 +20,7 @@ type SendInviteLinkEmailProps = {
firstName: string;
lastName: string;
};
serverUrl?: string;
serverUrl: string;
Copy link
Member Author

Choose a reason for hiding this comment

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

Overall, I think we should stop authorizing undefined in our typings unless this is needed. The caller should handle the case. This will reduce code complexity

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

PR Summary

This PR consolidates image URL handling across packages and fixes broken image URLs in settings and email templates by centralizing the getImageAbsoluteURI utility.

  • Removed twenty-front's getImageAbsoluteURI implementation in favor of twenty-ui's version, though twenty-emails retains its copy due to architectural constraints
  • Added token-based authentication for workspace logos in workspace-invitation.resolver.ts using FileService
  • Added null/undefined checks before calling getImageAbsoluteURI in components like Avatar and Logo
  • Fixed "File not found" errors when users connect via Google by adding proper null checks for workspace.logo
  • Added FileModule to WorkspaceInvitationModule for handling authenticated logo URLs

💡 (5/5) You can turn off certain types of comments like style here!

16 file(s) reviewed, 11 comment(s)
Edit PR Review Bot Settings | Greptile

}

if (imageUrl?.startsWith('https:')) {
export const getImageAbsoluteURI = (imageUrl: string, serverUrl: string) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

logic: Removing optional parameters could break existing code that passes undefined/null. Consider keeping parameters optional with default values.

return imageUrl;
}

return serverUrl?.endsWith('/')
return serverUrl.endsWith('/')
? `${serverUrl.substring(0, serverUrl.length - 1)}/files/${imageUrl}`
: `${serverUrl || ''}/files/${imageUrl}`;
Copy link
Contributor

Choose a reason for hiding this comment

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

logic: Using serverUrl || '' is redundant since serverUrl is now required. This fallback should be removed.

Comment on lines 109 to 111
getImageAbsoluteURI(
workspace.logo === null ? DEFAULT_WORKSPACE_LOGO : workspace.logo,
isDefined(workspace.logo) ? workspace.logo : DEFAULT_WORKSPACE_LOGO,
) ?? '',
Copy link
Contributor

Choose a reason for hiding this comment

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

logic: This logic could still result in undefined being passed to getImageAbsoluteURI if workspace.logo is null. Consider using workspace.logo ?? DEFAULT_WORKSPACE_LOGO instead.

@@ -15,6 +15,7 @@ export class FilePathGuard implements CanActivate {
async canActivate(context: ExecutionContext): Promise<boolean> {
const request = context.switchToHttp().getRequest();
const query = request.query;
const urlParamsV2 = new URLSearchParams(request.originalUrl);
Copy link
Contributor

Choose a reason for hiding this comment

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

logic: urlParamsV2 is declared but never used

Copy link
Contributor

Choose a reason for hiding this comment

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

logic: Removing this file removes null/undefined handling and proper URL path construction. The twenty-ui version may need these features added back to maintain full functionality.

Copy link
Contributor

Choose a reason for hiding this comment

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

style: The URL construction using URL class was more robust than string concatenation. Consider keeping this approach for better URL handling.

Comment on lines +64 to +70
if (workspace.logo) {
const workspaceLogoToken = await this.fileService.encodeFileToken({
workspaceId: workspace.id,
});

workspaceLogoWithToken = `${workspace.logo}?token=${workspaceLogoToken}`;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

style: token generation should be wrapped in try/catch to handle potential encoding errors gracefully

return await this.workspaceInvitationService.sendInvitations(
sendInviteLinkInput.emails,
workspace,
{ ...workspace, logo: workspaceLogoWithToken },
Copy link
Contributor

Choose a reason for hiding this comment

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

logic: spreading workspace and overriding logo could cause issues if workspace is frozen/sealed object

Comment on lines +4 to 14
it('should return absolute url if the imageUrl is an absolute url', () => {
const imageUrl = 'https://XXX';
const result = getImageAbsoluteURI(imageUrl);
expect(result).toBeNull();
expect(result).toBe(imageUrl);
});

it('should return absolute url if the imageUrl is an absolute url', () => {
const imageUrl = 'https://XXX';
it('should return absolute url if the imageUrl is an absolute unsecure url', () => {
const imageUrl = 'http://XXX';
const result = getImageAbsoluteURI(imageUrl);
expect(result).toBe(imageUrl);
});
Copy link
Contributor

Choose a reason for hiding this comment

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

style: test cases for https and http are redundant since they test the same logic branch in the implementation

}

if (imageUrl?.startsWith('http')) {
export const getImageAbsoluteURI = (imageUrl: string) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

logic: Removing null/undefined handling could break existing code that passes undefined. Consider keeping parameter optional or adding runtime validation.

@charlesBochet charlesBochet merged commit 99f53a5 into main Dec 7, 2024
19 checks passed
@charlesBochet charlesBochet deleted the fix-images-missing branch December 7, 2024 13:57
charlesBochet added a commit that referenced this pull request Dec 17, 2024
PR Summary: 

1. Added `Twenty Shared` Package to centralize utilitiies as mentioned
in #8942
2. Optimization of `getImageAbsoluteURI.ts` to handle edge cases


![image](https://github.com/user-attachments/assets/c72a3061-6eba-46b8-85ac-869f06bf23c0)

---------

Co-authored-by: Antoine Moreaux <[email protected]>
Co-authored-by: Charles Bochet <[email protected]>
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.

Profile Picture - File not found in Settings
1 participant