Skip to content

Commit

Permalink
Merge pull request #408 from dfpc-coe/share-basemap
Browse files Browse the repository at this point in the history
Basemap Share
  • Loading branch information
ingalls authored Nov 1, 2024
2 parents c995901 + cb7b651 commit 8ad0b13
Show file tree
Hide file tree
Showing 9 changed files with 1,936 additions and 3,264 deletions.
1,424 changes: 263 additions & 1,161 deletions api/package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
"@openaddresses/batch-schema": "^10.9.0",
"@openaddresses/cloudfriend": "^7.0.0",
"@sinclair/typebox": "^0.33.0",
"@tak-ps/node-cot": "^12.0.0",
"@tak-ps/node-cot": "^12.11.0",
"@tak-ps/node-tak": "^8.0.0",
"@turf/bbox": "^7.1.0",
"@turf/bbox-polygon": "^7.1.0",
Expand Down
25 changes: 11 additions & 14 deletions api/routes/basemap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import Cacher from '../lib/cacher.js';
import busboy from 'busboy';
import Config from '../lib/config.js';
import { Response } from 'express';
import xml2js from 'xml2js';
import stream2buffer from '../lib/stream.js';
import bboxPolygon from '@turf/bbox-polygon';
import { Param } from '@openaddresses/batch-generic'
Expand All @@ -35,11 +34,11 @@ export default async function router(schema: Schema, config: Config) {
if (count === 0) {
try {
await fs.access(new URL('../data/', import.meta.url));

for (const file of await fs.readdir(new URL('../data/basemaps/', import.meta.url))) {
console.error(`ok - loading basemap ${file}`);
const b = (await BasemapParser.parse(String(await fs.readFile(new URL(`../data/basemaps/${file}`, import.meta.url))))).to_json();

await config.models.Basemap.generate({
name: b.name || 'Unknown',
url: b.url,
Expand Down Expand Up @@ -361,21 +360,19 @@ export default async function router(schema: Schema, config: Config) {
}

if (req.query.format === 'xml') {
const builder = new xml2js.Builder();

res.setHeader('Content-Type', 'text/xml');

const xml: string = builder.buildObject({
const xml: string = (new BasemapParser({
customMapSource: {
name: { _: basemap.name },
minZoom: { _: basemap.minzoom },
maxZoom: { _: basemap.maxzoom },
tileType: { _: basemap.format },
tileUpdate: { _: 'None' },
url: { _: basemap.url },
backgroundColor: { _: '#000000' },
name: { _text: basemap.name },
minZoom: { _text: basemap.minzoom },
maxZoom: { _text: basemap.maxzoom },
tileType: { _text: basemap.format },
tileUpdate: { _text: 'None' },
url: { _text: basemap.url },
backgroundColor: { _text: '#000000' },
}
});
})).to_xml();

res.send(xml);
} else {
Expand Down
42 changes: 37 additions & 5 deletions api/routes/marti-package.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import Schema from '@openaddresses/batch-schema';
import Err from '@openaddresses/batch-error';
import Auth, { AuthUserAccess } from '../lib/auth.js';
import Config from '../lib/config.js';
import { Basemap as BasemapParser } from '@tak-ps/node-cot';
import { Content } from '../lib/api/files.js';
import { Package } from '../lib/api/package.js';
import TAKAPI, {
Expand All @@ -30,11 +31,11 @@ export default async function router(schema: Schema, config: Config) {
const auth = profile.auth;
const creatorUid = profile.username;
const api = await TAKAPI.init(new URL(String(config.server.api)), new APIAuthCertificate(auth.cert, auth.key));

const id = crypto.randomUUID();
const pkg = new DataPackage(id, id);

if (req.headers['content-type'] && req.headers['content-type'].startsWith('multipart/form-data')) {
const pkg = new DataPackage(id, id);

const bb = busboy({
headers: req.headers,
limits: {
Expand Down Expand Up @@ -86,14 +87,19 @@ export default async function router(schema: Schema, config: Config) {
description: 'Helper API to create share package',
body: Type.Object({
type: Type.Literal('FeatureCollection'),
uids: Type.Optional(Type.Array(Type.String())),
uids: Type.Array(Type.String(), {
default: []
}),
basemaps: Type.Array(Type.Number(), {
default: []
}),
features: Type.Array(Type.Object({
id: Type.String(),
type: Type.Literal('Feature'),
properties: Type.Any(),
geometry: Type.Any()
}), {
minItems: 1
default: []
})
}),
res: Content
Expand All @@ -105,6 +111,10 @@ export default async function router(schema: Schema, config: Config) {
const auth = profile.auth;
const creatorUid = profile.username;

if (!req.body.basemaps.length && !req.body.features.length) {
throw new Err(400, null, 'Cannot share an empty package');
}

const api = await TAKAPI.init(new URL(String(config.server.api)), new APIAuthCertificate(auth.cert, auth.key));

const id = crypto.randomUUID();
Expand All @@ -124,6 +134,28 @@ export default async function router(schema: Schema, config: Config) {
await pkg.addCoT(CoT.from_geojson(feat))
}

for (const basemapid of req.body.basemaps) {
const basemap = await config.models.Basemap.from(basemapid);
if (basemap.username && basemap.username !== user.email && user.access === AuthUserAccess.USER) {
throw new Err(400, null, 'You don\'t have permission to access this resource');
}
const xml: string = (new BasemapParser({
customMapSource: {
name: { _text: basemap.name },
minZoom: { _text: basemap.minzoom },
maxZoom: { _text: basemap.maxzoom },
tileType: { _text: basemap.format },
tileUpdate: { _text: 'None' },
url: { _text: basemap.url },
backgroundColor: { _text: '#000000' },
}
})).to_xml();

await pkg.addFile(xml, {
name: `basemap-${basemap.id}.xml`
});
}

for (const hash of attachmentMap.keys()) {
const uid = attachmentMap.get(hash);
if (!uid) continue;
Expand Down Expand Up @@ -161,7 +193,7 @@ export default async function router(schema: Schema, config: Config) {
sizeInBytes: size
});

if (client && req.body.uids) {
if (client && req.body.uids.length) {
if (!cot.raw.event.detail) cot.raw.event.detail = {};
cot.raw.event.detail.marti = {
dest: req.body.uids.map((uid) => {
Expand Down
Loading

0 comments on commit 8ad0b13

Please sign in to comment.