Skip to content

Commit

Permalink
Merge pull request #375 from dfpc-coe/livestream-logs
Browse files Browse the repository at this point in the history
LiveStream logs
  • Loading branch information
ingalls authored Oct 14, 2024
2 parents 209df97 + ff6f4d7 commit 7c879c5
Show file tree
Hide file tree
Showing 14 changed files with 2,122 additions and 1,654 deletions.
70 changes: 63 additions & 7 deletions api/lib/api/mission-log.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import TAKAPI from '../tak-api.js';
import { Type, Static } from '@sinclair/typebox';
import type { TAKItem } from './types.js';
import type { MissionOptions } from './mission.js';

export const MissionLog = Type.Object({
Expand All @@ -14,6 +15,16 @@ export const MissionLog = Type.Object({
keywords: Type.Array(Type.Unknown())
});

export const CreateMissionLog = Type.Object({
content: Type.String(),
creatorUid: Type.String(),
contentHashes: Type.Optional(Type.Array(Type.Unknown())),
keywords: Type.Optional(Type.Array(Type.Unknown()))
});

export const UpdateMissionLog = Type.Composite([ CreateMissionLog, Type.Object({
id: Type.String()
})]);

export default class {
api: TAKAPI;
Expand All @@ -32,26 +43,48 @@ export default class {
}
}

/**
* Delete a log entry on a Mission Sync
*
* {@link https://docs.tak.gov/api/takserver/redoc#tag/mission-api/operation/deleteLogEntry TAK Server Docs}.
*/
async delete(
log: string,
opts?: Static<typeof MissionOptions>
) {
): Promise<void> {
const url = new URL(`/Marti/api/missions/logs/entries/${log}`, this.api.url);

return await this.api.fetch(url, {
await this.api.fetch(url, {
method: 'DELETE',
headers: this.#headers(opts),
});

return;
}

/**
* Get a log entry on a Mission Sync
*
* {@link https://docs.tak.gov/api/takserver/redoc#tag/mission-api/operation/getOneLogEntry TAK Server Docs}.
*/
async get(
id: string,
): Promise<TAKItem<Static<typeof MissionLog>>> {
const url = new URL(`/Marti/api/missions/logs/entries/${encodeURIComponent(id)}`, this.api.url);

return await this.api.fetch(url);
}

/**
* Create a log entry on a Mission Sync
*
* {@link https://docs.tak.gov/api/takserver/redoc#tag/mission-api/operation/postLogEntry TAK Server Docs}.
*/
async create(
mission: string,
body: {
content: string;
creatorUid: string;
},
body: Static<typeof CreateMissionLog>,
opts?: Static<typeof MissionOptions>
) {
): Promise<TAKItem<Static<typeof MissionLog>>> {
const url = new URL(`/Marti/api/missions/logs/entries`, this.api.url);

return await this.api.fetch(url, {
Expand All @@ -64,4 +97,27 @@ export default class {
}
});
}

/**
* Update a log entry on a Mission Sync
*
* {@link https://docs.tak.gov/api/takserver/redoc#tag/mission-api/operation/updateLogEntry TAK Server Docs}.
*/
async update(
mission: string,
body: Static<typeof UpdateMissionLog>,
opts?: Static<typeof MissionOptions>
): Promise<TAKItem<Static<typeof MissionLog>>> {
const url = new URL(`/Marti/api/missions/logs/entries`, this.api.url);

return await this.api.fetch(url, {
method: 'PUT',
headers: this.#headers(opts),
body: {
content: body.content,
creatorUid: body.creatorUid,
missionNames: [ mission ],
}
});
}
}
1,649 changes: 363 additions & 1,286 deletions api/package-lock.json

Large diffs are not rendered by default.

86 changes: 86 additions & 0 deletions api/routes/marti-mission-logs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,53 @@ import { StandardResponse, GenericMartiResponse } from '../lib/types.js';
import Schema from '@openaddresses/batch-schema';
import Err from '@openaddresses/batch-error';
import { MissionOptions } from '../lib/api/mission.js';
import { MissionLog } from '../lib/api/mission-log.js';
import Auth from '../lib/auth.js';
import Config from '../lib/config.js';
import TAKAPI, {
APIAuthCertificate,
} from '../lib/tak-api.js';

export default async function router(schema: Schema, config: Config) {
await schema.get('/marti/missions/:name/log', {
name: 'List Logs',
group: 'MartiMissionLog',
params: Type.Object({
name: Type.String(),
}),
description: 'Helper API to add a log to a mission',
res: Type.Object({
total: Type.Integer(),
items: Type.Array(MissionLog)
})
}, async (req, res) => {
try {
const user = await Auth.as_user(config, req);

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

const opts: Static<typeof MissionOptions> = req.headers['missionauthorization']
? { token: String(req.headers['missionauthorization']) }
: await config.conns.subscription(user.email, req.params.name)

const mission = await api.Mission.get(
req.params.name,
{
logs: true
},
opts
);

return res.json({
total: (mission.logs || []).length,
items: mission.logs || []
});
} catch (err) {
return Err.respond(err, res);
}
});

await schema.post('/marti/missions/:name/log', {
name: 'Create Log',
group: 'MartiMissionLog',
Expand Down Expand Up @@ -48,6 +88,52 @@ export default async function router(schema: Schema, config: Config) {
}
});

await schema.patch('/marti/missions/:name/log/:logid', {
name: 'Update Log',
group: 'MartiMissionLog',
params: Type.Object({
name: Type.String(),
logid: Type.String()
}),
description: 'Helper API to update a log on a mission',
body: Type.Object({
content: Type.String()
}),
res: Type.Object({
version: Type.String(),
type: Type.String(),
data: MissionLog,
messages: Type.Optional(Type.Array(Type.String())),
nodeId: Type.Optional(Type.String())
})
}, async (req, res) => {
try {
const user = await Auth.as_user(config, req);

const auth = (await config.models.Profile.from(user.email)).auth;
const creatorUid = user.email;
const api = await TAKAPI.init(new URL(String(config.server.api)), new APIAuthCertificate(auth.cert, auth.key));

const opts: Static<typeof MissionOptions> = req.headers['missionauthorization']
? { token: String(req.headers['missionauthorization']) }
: await config.conns.subscription(user.email, req.params.name)

const mission = await api.MissionLog.update(
req.params.name,
{
id: req.params.logid,
creatorUid: creatorUid,
content: req.body.content
},
opts
);

return res.json(mission);
} catch (err) {
return Err.respond(err, res);
}
});

await schema.delete('/marti/missions/:name/log/:log', {
name: 'Delete Log',
group: 'MartiMissionLog',
Expand Down
10 changes: 8 additions & 2 deletions api/routes/marti-mission.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,14 @@ export default async function router(schema: Schema, config: Config) {
description: 'Helper API to get a single mission',
query: Type.Object({
password: Type.Optional(Type.String()),
changes: Type.Optional(Type.Boolean()),
logs: Type.Optional(Type.Boolean()),
changes: Type.Boolean({
default: false,
description: 'If true, include changes array in the resulting Mission'
}),
logs: Type.Boolean({
default: false,
description: 'If true, include logs array in the resulting Mission'
}),
secago: Type.Optional(Type.Integer()),
start: Type.Optional(Type.String()),
end: Type.Optional(Type.String())
Expand Down
Loading

0 comments on commit 7c879c5

Please sign in to comment.