implement level permissions in tileserver/cachepackage
This commit is contained in:
parent
9d77707cc5
commit
6167c92e98
4 changed files with 37 additions and 9 deletions
|
@ -358,7 +358,9 @@ class LevelRenderData:
|
|||
|
||||
map_history.save_level(render_level.pk, 'composite')
|
||||
|
||||
package.add_level(render_level.pk, theme, map_history, access_restriction_affected)
|
||||
package.add_level(level_id=render_level.pk, theme_id=theme, history=map_history,
|
||||
restrictions=access_restriction_affected,
|
||||
level_restriction=render_level.access_restriction_id)
|
||||
|
||||
render_data.save(update_cache_key, render_level.pk, theme)
|
||||
|
||||
|
|
28
src/c3nav/mapdata/utils/cache/package.py
vendored
28
src/c3nav/mapdata/utils/cache/package.py
vendored
|
@ -4,7 +4,7 @@ from collections import namedtuple
|
|||
from io import BytesIO
|
||||
from pathlib import Path
|
||||
from tarfile import TarFile, TarInfo
|
||||
from typing import BinaryIO, Optional, Self
|
||||
from typing import BinaryIO, Optional, Self, NamedTuple
|
||||
|
||||
from pyzstd import CParameter, ZstdError, ZstdFile
|
||||
|
||||
|
@ -16,7 +16,12 @@ except ImportError:
|
|||
from threading import local as LocalContext
|
||||
|
||||
ZSTD_MAGIC_NUMBER = b"\x28\xb5\x2f\xfd"
|
||||
CachePackageLevel = namedtuple('CachePackageLevel', ('history', 'restrictions'))
|
||||
|
||||
|
||||
class CachePackageLevel(NamedTuple):
|
||||
history: MapHistory
|
||||
restrictions: AccessRestrictionAffected
|
||||
global_restrictions: frozenset[int]
|
||||
|
||||
|
||||
class CachePackage:
|
||||
|
@ -25,8 +30,13 @@ class CachePackage:
|
|||
self.levels = {} if levels is None else levels
|
||||
self.theme_ids = []
|
||||
|
||||
def add_level(self, level_id: int, theme_id, history: MapHistory, restrictions: AccessRestrictionAffected):
|
||||
self.levels[(level_id, theme_id)] = CachePackageLevel(history, restrictions)
|
||||
def add_level(self, level_id: int, theme_id, history: MapHistory, restrictions: AccessRestrictionAffected,
|
||||
level_restriction: int | None):
|
||||
self.levels[(level_id, theme_id)] = CachePackageLevel(
|
||||
history=history,
|
||||
restrictions=restrictions,
|
||||
global_restrictions=frozenset() if level_restriction is None else frozenset((level_restriction, ))
|
||||
)
|
||||
if theme_id not in self.theme_ids:
|
||||
self.theme_ids.append(theme_id)
|
||||
|
||||
|
@ -62,6 +72,10 @@ class CachePackage:
|
|||
key = '%d' % level_id
|
||||
else:
|
||||
key = '%d_%d' % (level_id, theme_id)
|
||||
self._add_bytesio(f, 'global_restrictions_%s' % key,
|
||||
BytesIO(struct.pack('<B'+('I'*len(level_data.global_restrictions)),
|
||||
len(level_data.global_restrictions),
|
||||
*level_data.global_restrictions)))
|
||||
self._add_geometryindexed(f, 'history_%s' % key, level_data.history)
|
||||
self._add_geometryindexed(f, 'restrictions_%s' % key, level_data.restrictions)
|
||||
finally:
|
||||
|
@ -116,9 +130,13 @@ class CachePackage:
|
|||
else:
|
||||
level_id = int(key)
|
||||
theme_id = None
|
||||
global_restrictions_data = f.extractfile(files['global_restrictions_%s' % key]).read()
|
||||
levels[(level_id, theme_id)] = CachePackageLevel(
|
||||
history=MapHistory.read(f.extractfile(files['history_%s' % key])),
|
||||
restrictions=AccessRestrictionAffected.read(f.extractfile(files['restrictions_%s' % key]))
|
||||
restrictions=AccessRestrictionAffected.read(f.extractfile(files['restrictions_%s' % key])),
|
||||
global_restrictions=frozenset(
|
||||
struct.unpack('<'+('I'*global_restrictions_data[0]), global_restrictions_data[1:])
|
||||
)
|
||||
)
|
||||
|
||||
return cls(bounds, levels)
|
||||
|
|
|
@ -370,10 +370,13 @@ def tile(request, level, zoom, x, y, theme, access_permissions: Optional[set] =
|
|||
access_permissions = set()
|
||||
else:
|
||||
access_permissions = parse_tile_access_cookie(cookie, settings.SECRET_TILE_KEY)
|
||||
access_permissions &= set(level_data.restrictions[minx:maxx, miny:maxy])
|
||||
access_permissions &= set(level_data.restrictions[minx:maxx, miny:maxy]) | level_data.global_restrictions
|
||||
else:
|
||||
access_permissions = access_permissions - {0}
|
||||
|
||||
if not all((r in access_permissions) for r in level_data.global_restrictions):
|
||||
raise Http404
|
||||
|
||||
# build cache keys
|
||||
last_update = level_data.history.last_update(minx, miny, maxx, maxy)
|
||||
base_cache_key = build_base_cache_key(last_update)
|
||||
|
|
|
@ -285,10 +285,15 @@ class TileServer:
|
|||
cookie = self.cookie_regex.search(cookie)
|
||||
if cookie:
|
||||
cookie = cookie.group(2)
|
||||
access_permissions = (parse_tile_access_cookie(cookie, self.tile_secret) &
|
||||
set(level_data.restrictions[minx:maxx, miny:maxy]))
|
||||
access_permissions = (
|
||||
parse_tile_access_cookie(cookie, self.tile_secret) &
|
||||
(set(level_data.restrictions[minx:maxx, miny:maxy]) | level_data.global_restrictions)
|
||||
)
|
||||
access_cache_key = build_access_cache_key(access_permissions)
|
||||
|
||||
if not all((r in access_permissions) for r in level_data.global_restrictions):
|
||||
return self.not_found(start_response, b'invalid level or theme.')
|
||||
|
||||
# check browser cache
|
||||
if_none_match = env.get('HTTP_IF_NONE_MATCH')
|
||||
tile_etag = build_tile_etag(level, zoom, x, y, theme_id, base_cache_key, access_cache_key, self.tile_secret)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue