def test_map_delete_private(app, db): m = Map('foo', bbox=[1, 1, 1, 1]) db.session.add(m) db.session.commit() token = m.gen_token() resp = _get_map(app, m.uuid, token) assert (resp.status_code == 200) with app.test_client() as client: point = GeoFeature(geometry=GeoPoint([1, 1])) f = Feature(point) m.features.append(f) db.session.add(m) db.session.commit() url = '/api/maps/{}'.format(m.uuid) resp = client.delete(url) assert (resp.status_code == 401 ) # TODO: should be 404 for private maps headers = {'X-MAP': m.uuid, 'X-TOKEN': token} resp = client.delete(url, headers=headers) assert (resp.status_code == 204) assert (not Map.get(m.uuid)) resp = _get_map(app, m.uuid, token) assert (resp.status_code == 404)
def save_new_game(game, result): """Save new game results to database""" game.start_at = datetime.fromtimestamp(result["startOfGame"]) game.password = result["password"] game.scenario = result["scenarioID"] game.ranked = result["ranked"] game.gold_round = result["goldRound"] game.ai_level = result["aiLevel"] game.country_selection = result["countrySelection"] game.time_scale = result["timeScale"] game.team_setting = result["teamSettings"] game.victory_points = result["victoryPoints"] game.research_days_offset = result["researchDaysOffset"] game.research_time_scale = result["researchTimeScale"] game.team_victory_points = result["teamVictoryPoints"] game_map = Map.query.filter(Map.map_id == result["mapID"]).first() if game_map is None: game_map = Map() game_map.map_id = result["mapID"] game_map.slots = result["openSlots"] + result["numberOfPlayers"] db.session.add(game_map) db.session.commit() game.map_id = game_map.id get_players(game.game_id) db.session.commit()
def setup_class(self): super().setup_class(self) self.student = User( email='*****@*****.**', password='******', full_name='Student', is_admin=False ) self.admin = User( email='*****@*****.**', password='******', full_name='Admin', is_admin=True ) db.session.add(self.student) db.session.add(self.admin) db.session.add(Map( name='Campus Centre Level 1', url='https://static.sutd-capstone.xyz/floorplan/level1', level=1, scale=0.025 )) db.session.add(Map( name='Campus Centre Level 2', url='https://static.sutd-capstone.xyz/floorplan/level2', level=1, scale=0.017 )) db.session.commit()
def map(): if request.method == 'POST': try: lats = request.form['lat'].strip().split(',') lons = request.form['lon'].strip().split(',') print(lats, len(lats)) print(lons, len(lons)) for i in range(len(lats)): new_map = Map() form = request.form.copy() form['lat'] = lats[i] form['lon'] = lons[i] new_map.populate(form) db.session.add(new_map) db.session.commit() return "True" except Exception as e: return str(e) elif request.method == 'GET': user_id = request.args.get('user_id') maps = Map.query.filter_by(user_id=user_id) ret = { 'timestamp': datetime.now(), 'data': [m.serialize() for m in maps] } return jsonify(ret)
def test_maps_list(app, db): assert (len(Map.all()) == 0) assert (_count_maps(app) == 0) db.session.add(Map('foo-list', published=True, bbox=[1, 1, 1, 1])) db.session.commit() assert (len(Map.all()) == 1) assert (_count_maps(app) == 1)
def new_game(game_id): """Save new game results to database""" game = Game() game.game_id = game_id game.game_host = 'https://xgs8.c.bytro.com/' supremacy = Supremacy(game.game_id, game.game_host) while True: try: result = supremacy.game() except ServerChangeError as exception: new_server = str(exception) game.game_host = new_server supremacy.url = new_server continue break _update_game(game, result) game.start_at = datetime.fromtimestamp(result["startOfGame"]) game.password = result["password"] game.scenario = result["scenarioID"] game.ranked = result["ranked"] game.gold_round = result["goldRound"] game.ai_level = result["aiLevel"] game.country_selection = result["countrySelection"] game.time_scale = result["timeScale"] # game.team_setting = result["teamSettings"] game.victory_points = result["victoryPoints"] game.research_days_offset = result["researchDaysOffset"] if "researchTimeScale" in result: game.research_time_scale = result["researchTimeScale"] else: game.research_time_scale = 1.0 game.team_victory_points = result["teamVictoryPoints"] game_map = Map.query.filter(Map.map_id == result["mapID"]).first() if game_map is None: game_map = Map() game_map.map_id = result["mapID"] game_map.name = result["mapID"] game_map.slots = result["openSlots"] + result["numberOfPlayers"] db.session.add(game_map) db.session.commit() game.map_id = game_map.id db.session.add(game) db.session.commit() return game
def test_live(app, db): with app.test_client() as client: m = Map('foo', bbox=[1, 1, 1, 1]) db.session.add(m) db.session.commit() uuid = m.uuid.hex from app.live import socketio socketio_client = socketio.test_client(app, flask_test_client=client) socketio_client.emit('join', uuid) assert socketio_client.is_connected() r = socketio_client.get_received() assert (len(r) == 1) assert (r[0]['name'] == 'message') assert (r[0]['args'] == 'user joined') m.name = 'bar' db.session.add(m) db.session.commit() r = socketio_client.get_received() assert (len(r) == 1) assert (r[0]['name'] == 'map-updated') point = GeoFeature(geometry=GeoPoint([1, 1])) f = Feature(point) db.session.add(m) m.features.append(f) db.session.commit() r = socketio_client.get_received() assert (len(r) == 1) assert (r[0]['name'] == 'feature-created') f.style = {'color': 'red'} db.session.add(f) db.session.commit() r = socketio_client.get_received() assert (len(r) == 1) assert (r[0]['name'] == 'feature-updated') db.session.delete(m) db.session.commit() r = socketio_client.get_received() assert (len(r) == 2) assert (r[0]['name'] == 'map-deleted') assert (r[1]['name'] == 'feature-deleted')
def test_maps_new_public(app, db): m = Map('foo-new-public', bbox=[1, 1, 1, 1]) db.session.add(m) db.session.commit() assert (not m.published) m.published = True db.session.add(m) db.session.commit() resp = _get_map(app, m.uuid) assert (resp.status_code == 200) resp = _get_map(app, m.uuid, m.gen_token()) assert (resp.status_code == 200)
def map_edit(map_id): m = Map.get(map_id) if not m: abort(404) json = request.json for key in [ 'name', 'bbox', 'description', 'place', 'attributes', 'published' ]: if key in json: setattr(m, key, json[key]) if 'theme' in json and json['theme'] in current_app.config['MAP_RENDERER']: m.theme = json['theme'] if 'datetime' in json: m.datetime = datetime_fromisoformat(request.json['datetime']) if 'lifespan' in json: m.lifespan = timedelta(days=request.json['lifespan']) db.session.add(m) db.session.commit() return jsonify(m.to_dict())
def create(): form = MapForm() form.submit.label.text = "Create Map" if form.validate_on_submit(): maps = Map.query.all() new_map = Map(name=form.name.data, no_wrap=form.no_wrap.data, external_provider=form.external_provider.data, tiles_path=form.tiles_path.data, min_zoom=form.min_zoom.data, max_zoom=form.max_zoom.data, default_zoom=form.default_zoom.data) db.session.add(new_map) if not maps: mset = MapSetting.query.get(1) mset.default_map = new_map.id flash( "This map was automatically selected as the default map. To change this, please visit the map settings.", "info") db.session.commit() flash("Map created.", "success") return redirect(url_for("map.view", id=new_map.id)) return render_template("map/create.html", form=form, title=page_title("Add Map"))
def map_features(map_id): m = Map.get(map_id) if not m or not (m.published or auth()): abort(404) features = [f.to_dict() for f in m.features] return jsonify(FeatureCollection(features))
def map_render(map_id, file_type): """Renders a map **Example request**: .. sourcecode:: bash $ curl -i -X POST -H "Content-Type: application/json" -d @tests/data/test_map.json http://localhost:5000/render/png **Example response**: .. sourcecode:: http HTTP/1.1 202 Accepted Content-Type: application/json { "file_type": "png", "job_id": "fce3b682-feaa-48b7-b945-ad243ce62df4", "map_id": "test123", "status": "queued", "version": "c8bbde29fa1cfd1109fae1835fcc1ea1f92f4e31292c1b3d338c782f18333605" } :param file_type: file type of rendered map. Either `pdf`, `svg` or `png:<size>` with size `small`, `medium` or `large` """ _map = Map.get(map_id) if not _map: abort(404) # TODO: merge with file_info exception UnsupportedFileType extension = file_type.split(':')[0] if '.' + extension not in mimetypes.types_map: abort(400) # if already rendered or enqueued, don't enqueue again version = _map.version force = request.args.get('force', default=False, type=bool) try: if not force: return status_by_map(map_id, file_type, version) except NotFound: pass data = _map.to_dict(grid_included=True, features_included=True) args = (data, file_type, force) queue = current_app.task_queue meta = { 'map_id': map_id, 'version': version, 'file_type': file_type, } job = queue.enqueue("app.tasks.render_map", *args, meta=meta) return status_by_job(job)
def test_map_lifespan(app, db): now = datetime.datetime.utcnow() m = Map('foo-lifespan', datetime=now, published=True, bbox=[1, 1, 1, 1]) db.session.add(m) db.session.commit() assert (not m.outdated) token = m.gen_token() resp = _get_map(app, m.uuid, token) assert (resp.status_code == 200) m.datetime = now - datetime.timedelta(days=31) db.session.add(m) db.session.commit() assert (m.outdated) resp = _get_map(app, m.uuid, token) assert (resp.status_code == 404)
def gen_auth_token(map_id): secret = request.headers.get('X-Secret', '') obj = Map.get(map_id) if not obj or not secret: abort(400) # bad request - invalid input if not safe_str_cmp(secret, obj.secret): abort(401) # forbidden - secrets do not match return jsonify(token=obj.gen_token())
def auth(): map_id = request.headers.get('X-Map') token = request.headers.get('X-Token') if not map_id or not token: return False obj = Map.get(map_id) if not obj or not obj.check_token(token): return False return True
def maps_new(): if ('name' not in request.json): abort(400) json = request.json name = json['name'] m = Map(name) for key in [ 'name', 'bbox', 'description', 'place', 'attributes', 'published', 'theme' ]: if key in json: setattr(m, key, json[key]) if 'theme' in json and json['theme'] in current_app.config['MAP_RENDERER']: m.theme = json['theme'] if 'datetime' in json: m.datetime = datetime_fromisoformat(request.json['datetime']) if 'lifespan' in json: m.lifespan = timedelta(days=request.json['lifspan']) db.session.add(m) db.session.commit() return make_response(jsonify(m.to_dict(secret_included=True)), 201)
def test_maps_new_datetime(app, db): name = 'foo-new-private' now = datetime.datetime.utcnow().replace(tzinfo=pytz.utc) uuid, token = _create_map(app, {'name': name, 'datetime': now.isoformat()}) m = Map.get(uuid) assert (m) assert (m.datetime == now) assert (not m.outdated) resp = _get_map(app, m.uuid, token) assert (resp.status_code == 200) assert (resp.json['datetime'] == now.isoformat())
def map_features_new(map_id): m = Map.get(map_id) if not m: abort(404) if not request.json or not Feature(request.json).is_valid: abort(400) # TODO: strip input data feature = MapFeature(request.json) m.features.append(feature) db.session.add(m) db.session.commit() return make_response(jsonify(feature.to_dict()), 201)
def test_maps_new_private(app, db): name = 'foo-new-private' uuid, token = _create_map(app, {'name': name}) m = Map.get(uuid) assert (m) assert (m.name == name) assert (m.check_token(token)) assert (not m.published) assert (not m.outdated) # FORBIDDEN is 404 not 403 (to prevent leak of sensitive data) resp = _get_map(app, uuid) assert (resp.status_code == 404) for t in ['WRONG_TOKEN', 'undefined', 'NULL', None, [], {}]: resp = _get_map(app, uuid, t) assert (resp.status_code == 404) resp = _get_map(app, uuid, token) assert (resp.status_code == 200)
def map_download(map_id, file_type, version=None): """ Download a map identified by map_id, file_type and optional version. Only already rendered maps can be downloaded. Each file format has to be rendered separately. If a map is not found you will get an 404 error statuscode. :param map_id: id of map :param file_type: `svg`, `pdf` or `png[:small|medium|large]` :status 200: sends content of map :status 404: map, version or file_type not found """ m = Map.get(map_id) if not m: abort(404) if not version: version = m.version dirname = sha256(map_id.encode()).hexdigest() extension, *args = file_type.split(':') mimetype = mimetypes.types_map['.' + extension] suffix = '' if len(args) > 0: suffix = '_' + args.pop() filename = '{}{}.{}'.format(version, suffix, extension) static_path = current_app.static_folder path = os.path.join(static_path, 'maps', dirname, filename) # map is already rendered if os.path.exists(path): return send_file(path, attachment_filename=filename, mimetype=mimetype) # map is not yet rendered return map_render(map_id, file_type)
def map_export_twitter(map_id): m = Map.get(map_id) if not m or not m.published: abort(404) url = "%s#/de/maps/%s/map" % (request.url_root, map_id) datetime = m.datetime.strftime("%d.%m.%Y %H:%M") data = { 'card': 'summary_large_image', 'site': '@aktionskarten_', 'title': 'Aktionskarten - ' + m.name, 'description': '%s @ %s' % (datetime, m.place), 'image': url_for('Renderer.map_download', map_id=map_id, file_type='png', _external=True) } return render_template('twitter.html', data=data, url=url)
def map_delete(map_id): Map.delete(map_id) return ('', 204)
def map_get(map_id): m = Map.get(map_id.hex) if not m or not (auth() or m.published) or m.outdated: abort(404) return jsonify(m.to_dict())
def maps(): return jsonify([m.to_dict() for m in Map.all()])
def on_join(map_id): #TODO: authenticated if Map.get(map_id): join_room(map_id) send('user joined', room=map_id)
def map_wait_until_finished(map_id, file_type, version=None): m = Map.get(map_id) if not m: abort(404) return render_template('rendering.html', m=m, file_type=file_type)
def render(mid, filename): m = Map.get(mid) data = m.to_dict(grid_included=True, features_included=True) renderer = SurfaceRenderer(data) with open(filename, 'wb') as f2: f2.write(renderer.render('application/pdf').read())
def map_get_grid(map_id): m = Map.get(map_id) if not m or not (m.published or auth()): abort(404) return jsonify(m.grid)
def uuid(app, db): rmtree(path.join(app.static_folder, 'maps'), ignore_errors=True) m = Map('my-new-map', bbox=[13.421731, 52.455879, 13.494473, 52.477631]) db.session.add(m) db.session.commit() yield m.uuid.hex
def map_export_geojson(map_id): m = Map.get(map_id) if not m or not (m.published or auth()): abort(404) features = [f.to_dict() for f in m.features] return jsonify(FeatureCollection(features, properties=m.to_dict(False)))