This repository has been archived on 2025-03-02. You can view files and clone it, but cannot push or open issues or pull requests.
identity/identity-api/src/index.js
2024-06-29 19:12:12 +02:00

304 lines
8.1 KiB
JavaScript

// Identity. Store your memories and mental belongings
// Copyright (C) 2024 Sofía Aritz
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import app from "./app.js"
import { ASSET_API_ENDPOINT, IDENTITY_API_LANDING_MESSAGE, LISTEN_PORT } from "./consts.js"
import { contentFromSigned, verifySignature } from "./m2m.js";
import { startAuth } from "./auth.js";
import { randomUUID } from "node:crypto";
import cors from "@fastify/cors";
let auth = await startAuth();
app.register(cors, {
origin: true,
})
app.get("/", async () => {
return IDENTITY_API_LANDING_MESSAGE;
});
app.put("/m2m/asset", {
async handler(request, reply) {
if (!verifySignature(request.body)) {
reply.statusCode(401);
return;
}
let body = JSON.parse(contentFromSigned(request.body));
let user = await auth.findUserBySessionKey(body.session_key)
user.assets.push(body.asset_id);
await auth.updateUser(user.uid, user);
app.log.info((await auth.findUserBySessionKey(body.session_key)).assets);
},
});
app.post("/m2m/account", {
async handler(request, reply) {
if (!verifySignature(request.body)) {
reply.statusCode(401);
return;
}
let body = JSON.parse(contentFromSigned(request.body));
let user = await auth.findUserBySessionKey(body.session_key)
user.password = undefined;
user.entries = undefined;
return user;
},
});
app.get("/asset/endpoint", {
async handler() {
return ASSET_API_ENDPOINT
}
})
app.delete("/entry", {
async handler(request, reply) {
let jwt = request.headers["authorization"].replace("Bearer", "").trim();
let { payload } = await auth.verifyJwt(jwt);
let user = await auth.user(payload.uid);
user.entries = user.entries.filter(v => v.id !== request.query.entry_id);
await auth.updateUser(payload.uid, user);
},
schema: {
headers: {
type: "object",
properties: {
authorization: { type: "string" },
},
required: ["authorization"],
},
query: {
type: "object",
properties: {
entry_id: { type: "string" },
},
required: ["entry_id"],
},
},
})
app.put("/entry", {
async handler(request, reply) {
let jwt = request.headers["authorization"].replace("Bearer", "").trim();
let { payload } = await auth.verifyJwt(jwt);
let user = await auth.user(payload.uid);
request.body.entry.id = randomUUID().toString();
user.entries = [request.body.entry, ...user.entries];
await auth.updateUser(payload.uid, user);
},
schema: {
headers: {
type: "object",
properties: {
authorization: { type: "string" },
},
required: ["authorization"],
},
body: {
type: "object",
properties: {
entry: { type: "object" },
},
required: ["entry"],
},
},
})
app.get("/entry/list", {
async handler(request, reply) {
if (request.query.offset < 0 || request.query.limit <= 0) {
reply.status(400);
return [];
}
let jwt = request.headers["authorization"].replace("Bearer", "").trim();
let { payload } = await auth.verifyJwt(jwt);
let user = await auth.user(payload.uid);
return user.entries.slice(request.query.offset, request.query.offset + request.query.limit);
},
schema: {
headers: {
type: "object",
properties: {
authorization: { type: "string" },
},
required: ["authorization"],
},
query: {
type: "object",
properties: {
limit: { type: "number" },
offset: { type: "number" },
},
required: ["limit", "offset"],
},
},
})
app.post("/auth/heirs", {
async handler(request, reply) {
let jwt = request.headers["authorization"].replace("Bearer", "").trim();
let { payload } = await auth.verifyJwt(jwt);
if (payload.uid == null) {
reply.status(401);
return;
}
let user = await auth.user(payload.uid);
user.heirs = request.body;
await auth.updateUser(payload.uid, user);
},
schema: {
headers: {
type: "object",
properties: {
authorization: { type: "string" },
},
required: ["authorization"],
},
body: {
type: "array",
}
}
})
app.get("/auth/genkey", {
async handler(request) {
let jwt = request.headers["authorization"].replace("Bearer", "").trim();
let { payload } = await auth.verifyJwt(jwt);
let session_key = await auth.createSessionKey(payload.uid);
return {
session_key,
};
},
schema: {
headers: {
type: "object",
properties: {
authorization: { type: "string" },
},
required: ["authorization"],
},
},
});
app.get("/auth/account", {
async handler(request, reply) {
let jwt = request.headers["authorization"].replace("Bearer", "").trim();
let { payload } = await auth.verifyJwt(jwt);
if (payload.uid == null) {
reply.status(401);
return;
}
let user = await auth.user(payload.uid);
user.password = undefined;
user.entries = undefined;
return user;
},
schema: {
headers: {
type: "object",
properties: {
authorization: { type: "string" },
},
required: ["authorization"],
},
},
});
app.post("/auth/login", {
async handler(request, reply) {
let user = await auth.findUserByEmail(request.body.email);
if (user != null && user.password == request.body.password) {
let token = await auth.createJwt(user.uid);
return {
token,
};
}
reply.code(400);
return {
error: "invalid credentials",
};
},
schema: {
body: {
type: "object",
properties: {
email: { type: "string" },
password: { type: "string" },
},
},
required: ["email", "password"],
},
});
app.post("/auth/register", {
async handler(request, reply) {
if (await auth.findUserByEmail(request.body.email) == null) {
let user = await auth.addUser({
email: request.body.email,
password: request.body.password,
name: request.body.name,
assets: [],
limits: {
assetCount: 5,
},
entries: [],
});
return { token: await auth.createJwt(user.uid) };
}
reply.code(400);
return {
error: "invalid data",
};
},
schema: {
body: {
type: "object",
properties: {
name: { type: "string" },
email: { type: "string" },
password: { type: "string" },
},
required: ["name", "email", "password"],
},
},
});
app.listen({ port: LISTEN_PORT });