Skip to content

Add custom Map Styles support#950

Open
FreshImmuc wants to merge 12 commits intodedicatedcode:mainfrom
FreshImmuc:main
Open

Add custom Map Styles support#950
FreshImmuc wants to merge 12 commits intodedicatedcode:mainfrom
FreshImmuc:main

Conversation

@FreshImmuc
Copy link
Copy Markdown

Hey, firstly, it's an honor to contribute to this project. I'm using it every day and love it! :)
I didn't upgrade because of the removed custom tiles support, so i added it back.

Now to the things added. Basically, added full custom map tiles support:

  • Vector styles (URL or pasted JSON) and raster styles (tile URL or TileJSON)
  • Style selection is saved per user and persists across sessions
  • Admins can share styles so everyone can use them
  • Map controls now have a style switcher but falls back to default if a style fails to load (removed or no permissions)
  • Satellite, buildings and terrain overlays work on any map style freely, no restrictions

Backend stuff:

  • Custom styles are served and proxied with signed URLs
  • private/local targets are blocked by default, with a config option to allow them for trusted setups (local tile urls, otherwise would be a security flaw)
  • Nginx tile cache extended to handle custom tiles
  • new DB tables for style definitions and active style per user (shouldn't break anything, i hope)

Hope everything looks good, tried to keep it as optimized as possible :)

Copy link
Copy Markdown
Contributor

@dgraf-gh dgraf-gh left a comment

Choose a reason for hiding this comment

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

First off, thank you @FreshImmuc for all the effort you put into this. It’s some awesome work! I really like the general idea and the way the core map styles are implemented.

However, I’m having a hard time with the SafeHttpClient and URLSignature and all the security related components. It feels like they might be over-complicating the solution. To be specific:

  • Maintenance: It adds a lot of complexity to the long-term management and maintenance of the code.
  • Contributor Friction: It makes adding new styles much more difficult because a user has to understand all these specific restrictions first.
  • Architecture: It feels like it’s trying to solve a problem that would be better handled at the network level rather than directly within the app.
  • Trust: It gives the impression that we’re trying to protect the app from its own users. If we’ve reached a point where we can’t trust them, we likely have bigger problems than this to solve.

In the end, I’m not comfortable pulling this in as it stands because it adds too much complexity to an already complicated problem. That said, the underlying solution for the map styles looks great! I’d be more than happy to review this again once the security-based elements are streamlined or resolved.

Thanks again for the hard work!

Comment thread docker/tiles-cache/nginx.conf Outdated
access_log /var/log/nginx/access.log main;

server_tokens off;
# Public fallback dns can leak internal hostnames if this proxy is ever used with untrusted upstream names.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I do not get this or do not understand the reasoning around this. Could you explain the threat level which shall be addressed here?

From my perspective, I would not leave this in since if you need this kind of protection (then 1.1.1.1 and 8.8.8.8 is also questionable - why should I trust them), maybe setting this on the docker level would be the better solution.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why does this exists? I do not get the usecase, this also applies to all the other security related stuff. The SafeHttpClient and the RemoteTileUrlValidator

return messageSource.getMessage(messageKey, null, defaultMessage, LocaleContextHolder.getLocale());
}

public String translateWithDefault(String messageKey, String defaultMessage, Object... args) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Lets remove this method, the default messages if nothing is found should be in messages.properties so it falls back to english


private URI parseHttpUrl(String value, String fieldName) {
if (!StringUtils.hasText(value)) {
throw new IllegalArgumentException(message("js.map.settings.dialog.map-styles.error-url-required", fieldName + " is required.", fieldName));
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Here you could define the error messages without the js. prefix. Since they are validated on the server.

Prefixing them with js. pulls them into the frontend automatically so the can be used by the t() function

return StringUtils.hasText(value) ? value.trim() : null;
}

private String label(String key) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This should not be done when persisting the value, since there is no way of reverting this when the user changes his language

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

In general here are my points:

  • do not validate input here in that class but rather in the calling class.
  • do not mangle with user input here like trimming, replacing stuff with default values. This leads to confusion since we store different data than the user expected.

}

byte[] bytes = address.getAddress();
if (bytes.length == 4) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

That is to clever for me. What does this block do exactly?

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