From 9157d247eafadc7ab933a881d4aec632a5990e9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sof=C3=ADa=20Aritz?= Date: Sat, 29 Jun 2024 20:11:53 +0200 Subject: [PATCH] filesystem routing --- identity-api/src/app.js | 8 +- identity-api/src/auth.js | 20 +- identity-api/src/consts.js | 20 +- identity-api/src/index.js | 297 ++-------------------- identity-api/src/m2m.js | 22 +- identity-api/src/routes/asset/endpoint.js | 9 + identity-api/src/routes/asset/index.js | 5 + identity-api/src/routes/auth/account.js | 21 ++ identity-api/src/routes/auth/genkey.js | 17 ++ identity-api/src/routes/auth/heirs.js | 24 ++ identity-api/src/routes/auth/index.js | 13 + identity-api/src/routes/auth/login.js | 30 +++ identity-api/src/routes/auth/register.js | 36 +++ identity-api/src/routes/entry/index.js | 51 ++++ identity-api/src/routes/entry/list.js | 27 ++ identity-api/src/routes/index.js | 11 + identity-api/src/routes/m2m/account.js | 20 ++ identity-api/src/routes/m2m/asset.js | 20 ++ identity-api/src/routes/m2m/index.js | 7 + 19 files changed, 348 insertions(+), 310 deletions(-) create mode 100644 identity-api/src/routes/asset/endpoint.js create mode 100644 identity-api/src/routes/asset/index.js create mode 100644 identity-api/src/routes/auth/account.js create mode 100644 identity-api/src/routes/auth/genkey.js create mode 100644 identity-api/src/routes/auth/heirs.js create mode 100644 identity-api/src/routes/auth/index.js create mode 100644 identity-api/src/routes/auth/login.js create mode 100644 identity-api/src/routes/auth/register.js create mode 100644 identity-api/src/routes/entry/index.js create mode 100644 identity-api/src/routes/entry/list.js create mode 100644 identity-api/src/routes/index.js create mode 100644 identity-api/src/routes/m2m/account.js create mode 100644 identity-api/src/routes/m2m/asset.js create mode 100644 identity-api/src/routes/m2m/index.js diff --git a/identity-api/src/app.js b/identity-api/src/app.js index 8a34739..6044e24 100644 --- a/identity-api/src/app.js +++ b/identity-api/src/app.js @@ -1,16 +1,16 @@ // 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 . @@ -18,4 +18,4 @@ import Fastify from "fastify"; export default Fastify({ logger: true, -}); \ No newline at end of file +}); diff --git a/identity-api/src/auth.js b/identity-api/src/auth.js index 4dae7de..6610b15 100644 --- a/identity-api/src/auth.js +++ b/identity-api/src/auth.js @@ -1,16 +1,16 @@ // 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 . @@ -24,7 +24,7 @@ export async function startAuth() { "uid:005d6417-a23c-48bd-b348-eafeae649b94": "e381ba8c-e18a-4bca-afce-b212b37bc26b", "key:e381ba8c-e18a-4bca-afce-b212b37bc26b": "005d6417-a23c-48bd-b348-eafeae649b94", }; - + let users = { "jane@identity.net": { uid: "005d6417-a23c-48bd-b348-eafeae649b94", @@ -42,7 +42,9 @@ export async function startAuth() { value: "sofi@sofiaritz.com", }, ], - entries: JSON.parse(`[{"id":"0","creationDate":"2024-04-13T00:00:00.000Z","feelings":["active","happy"],"base":{"kind":"song","id":[{"provider":"spotify","id":"53mChDyESfwn9Dz8poHRf6"}],"link":["https://open.spotify.com/track/53mChDyESfwn9Dz8poHRf6"],"title":"Taking What's Not Yours","artist":"TV Girl"},"assets":[]},{"id":"1","creationDate":"2024-04-13T00:00:00.000Z","feelings":[],"base":{"kind":"album","id":[{"provider":"spotify","id":"1d2PspdXmwrBEcOtquCvzT"}],"link":["https://open.spotify.com/album/1d2PspdXmwrBEcOtquCvzT"],"title":"CHASER","artist":"femtanyl"},"assets":[]},{"id":"2","creationDate":"2024-04-26T00:00:00.000Z","feelings":["excited"],"title":"SalmorejoTech 2024","description":"SalmorejoTech is a great tech-event. I met some people and everything went great! :)","base":{"kind":"event"},"assets":[]},{"id":"3","creationDate":"2024-06-26T00:00:00.000Z","feelings":["happy","relaxed"],"title":"Playing Minecraft with Mr. Pablo","description":"Mr. Pablo is my friend, she is a great friend. We spent a good time playing Minecraft. I am lucky to have a friend like him.","base":{"kind":"memory"},"assets":[]},{"id":"4","creationDate":"2024-01-01T00:00:00.000Z","feelings":["excited","nervous"],"description":"New Year, New me! I'm really excited about what's going to happen this year, lots of changes. Changes may be scary, but they usually are for good!","base":{"kind":"feeling"},"assets":["f9d040d6-598c-4483-952f-08e7d35d5420.jpg"]},{"id":"5","creationDate":"2024-04-28T00:00:00.000Z","feelings":["happy","relaxed"],"title":"The park","description":"The park is a really chill place where I can go and relax for a bit before going to work.","base":{"kind":"environment"},"assets":[]},{"id":"6","creationDate":"2024-04-28T00:00:00.000Z","feelings":["happy"],"description":"This day has been a great day! I've talked with my friends.","base":{"kind":"date","referencedDate":"2024-04-27T00:00:00.000Z"},"assets":[]},{"id":"0a","creationDate":"2024-04-13T00:00:00.000Z","feelings":["active","happy"],"base":{"kind":"song","id":[{"provider":"spotify","id":"53mChDyESfwn9Dz8poHRf6"}],"link":["https://open.spotify.com/track/53mChDyESfwn9Dz8poHRf6"],"title":"Taking What's Not Yours","artist":"TV Girl"},"assets":[]},{"id":"1a","creationDate":"2024-04-13T00:00:00.000Z","feelings":[],"base":{"kind":"album","id":[{"provider":"spotify","id":"1d2PspdXmwrBEcOtquCvzT"}],"link":["https://open.spotify.com/album/1d2PspdXmwrBEcOtquCvzT"],"title":"CHASER","artist":"femtanyl"},"assets":[]},{"id":"2a","creationDate":"2024-04-26T00:00:00.000Z","feelings":["excited"],"title":"SalmorejoTech 2024","description":"SalmorejoTech is a great tech-event. I met some people and everything went great! :)","base":{"kind":"event"},"assets":[]},{"id":"3a","creationDate":"2024-06-26T00:00:00.000Z","feelings":["happy","relaxed"],"title":"Playing Minecraft with Mr. Pablo","description":"Mr. Pablo is my friend, she is a great friend. We spent a good time playing Minecraft. I am lucky to have a friend like him.","base":{"kind":"memory"},"assets":[]},{"id":"4a","creationDate":"2024-01-01T00:00:00.000Z","feelings":["excited","nervous"],"description":"New Year, New me! I'm really excited about what's going to happen this year, lots of changes. Changes may be scary, but they usually are for good!","base":{"kind":"feeling"},"assets":["f9d040d6-598c-4483-952f-08e7d35d5420.jpg"]},{"id":"5a","creationDate":"2024-04-28T00:00:00.000Z","feelings":["happy","relaxed"],"title":"The park","description":"The park is a really chill place where I can go and relax for a bit before going to work.","base":{"kind":"environment"},"assets":[]},{"id":"6a","creationDate":"2024-04-28T00:00:00.000Z","feelings":["happy"],"description":"This day has been a great day! I've talked with my friends.","base":{"kind":"date","referencedDate":"2024-04-27T00:00:00.000Z"},"assets":[]},{"id":"0b","creationDate":"2024-04-13T00:00:00.000Z","feelings":["active","happy"],"base":{"kind":"song","id":[{"provider":"spotify","id":"53mChDyESfwn9Dz8poHRf6"}],"link":["https://open.spotify.com/track/53mChDyESfwn9Dz8poHRf6"],"title":"Taking What's Not Yours","artist":"TV Girl"},"assets":[]},{"id":"1b","creationDate":"2024-04-13T00:00:00.000Z","feelings":[],"base":{"kind":"album","id":[{"provider":"spotify","id":"1d2PspdXmwrBEcOtquCvzT"}],"link":["https://open.spotify.com/album/1d2PspdXmwrBEcOtquCvzT"],"title":"CHASER","artist":"femtanyl"},"assets":[]},{"id":"2b","creationDate":"2024-04-26T00:00:00.000Z","feelings":["excited"],"title":"SalmorejoTech 2024","description":"SalmorejoTech is a great tech-event. I met some people and everything went great! :)","base":{"kind":"event"},"assets":[]},{"id":"3b","creationDate":"2024-06-26T00:00:00.000Z","feelings":["happy","relaxed"],"title":"Playing Minecraft with Mr. Pablo","description":"Mr. Pablo is my friend, she is a great friend. We spent a good time playing Minecraft. I am lucky to have a friend like him.","base":{"kind":"memory"},"assets":[]},{"id":"4b","creationDate":"2024-01-01T00:00:00.000Z","feelings":["excited","nervous"],"description":"New Year, New me! I'm really excited about what's going to happen this year, lots of changes. Changes may be scary, but they usually are for good!","base":{"kind":"feeling"},"assets":["f9d040d6-598c-4483-952f-08e7d35d5420.jpg"]},{"id":"5b","creationDate":"2024-04-28T00:00:00.000Z","feelings":["happy","relaxed"],"title":"The park","description":"The park is a really chill place where I can go and relax for a bit before going to work.","base":{"kind":"environment"},"assets":[]},{"id":"6b","creationDate":"2024-04-28T00:00:00.000Z","feelings":["happy"],"description":"This day has been a great day! I've talked with my friends.","base":{"kind":"date","referencedDate":"2024-04-27T00:00:00.000Z"},"assets":[]},{"id":"0c","creationDate":"2024-04-13T00:00:00.000Z","feelings":["active","happy"],"base":{"kind":"song","id":[{"provider":"spotify","id":"53mChDyESfwn9Dz8poHRf6"}],"link":["https://open.spotify.com/track/53mChDyESfwn9Dz8poHRf6"],"title":"Taking What's Not Yours","artist":"TV Girl"},"assets":[]},{"id":"1c","creationDate":"2024-04-13T00:00:00.000Z","feelings":[],"base":{"kind":"album","id":[{"provider":"spotify","id":"1d2PspdXmwrBEcOtquCvzT"}],"link":["https://open.spotify.com/album/1d2PspdXmwrBEcOtquCvzT"],"title":"CHASER","artist":"femtanyl"},"assets":[]},{"id":"2c","creationDate":"2024-04-26T00:00:00.000Z","feelings":["excited"],"title":"SalmorejoTech 2024","description":"SalmorejoTech is a great tech-event. I met some people and everything went great! :)","base":{"kind":"event"},"assets":[]},{"id":"3c","creationDate":"2024-06-26T00:00:00.000Z","feelings":["happy","relaxed"],"title":"Playing Minecraft with Mr. Pablo","description":"Mr. Pablo is my friend, she is a great friend. We spent a good time playing Minecraft. I am lucky to have a friend like him.","base":{"kind":"memory"},"assets":[]},{"id":"4c","creationDate":"2024-01-01T00:00:00.000Z","feelings":["excited","nervous"],"description":"New Year, New me! I'm really excited about what's going to happen this year, lots of changes. Changes may be scary, but they usually are for good!","base":{"kind":"feeling"},"assets":["f9d040d6-598c-4483-952f-08e7d35d5420.jpg"]},{"id":"5c","creationDate":"2024-04-28T00:00:00.000Z","feelings":["happy","relaxed"],"title":"The park","description":"The park is a really chill place where I can go and relax for a bit before going to work.","base":{"kind":"environment"},"assets":[]},{"id":"6c","creationDate":"2024-04-28T00:00:00.000Z","feelings":["happy"],"description":"This day has been a great day! I've talked with my friends.","base":{"kind":"date","referencedDate":"2024-04-27T00:00:00.000Z"},"assets":[]},{"id":"0d","creationDate":"2024-04-13T00:00:00.000Z","feelings":["active","happy"],"base":{"kind":"song","id":[{"provider":"spotify","id":"53mChDyESfwn9Dz8poHRf6"}],"link":["https://open.spotify.com/track/53mChDyESfwn9Dz8poHRf6"],"title":"Taking What's Not Yours","artist":"TV Girl"},"assets":[]},{"id":"1d","creationDate":"2024-04-13T00:00:00.000Z","feelings":[],"base":{"kind":"album","id":[{"provider":"spotify","id":"1d2PspdXmwrBEcOtquCvzT"}],"link":["https://open.spotify.com/album/1d2PspdXmwrBEcOtquCvzT"],"title":"CHASER","artist":"femtanyl"},"assets":[]},{"id":"2d","creationDate":"2024-04-26T00:00:00.000Z","feelings":["excited"],"title":"SalmorejoTech 2024","description":"SalmorejoTech is a great tech-event. I met some people and everything went great! :)","base":{"kind":"event"},"assets":[]},{"id":"3d","creationDate":"2024-06-26T00:00:00.000Z","feelings":["happy","relaxed"],"title":"Playing Minecraft with Mr. Pablo","description":"Mr. Pablo is my friend, she is a great friend. We spent a good time playing Minecraft. I am lucky to have a friend like him.","base":{"kind":"memory"},"assets":[]},{"id":"4d","creationDate":"2024-01-01T00:00:00.000Z","feelings":["excited","nervous"],"description":"New Year, New me! I'm really excited about what's going to happen this year, lots of changes. Changes may be scary, but they usually are for good!","base":{"kind":"feeling"},"assets":["f9d040d6-598c-4483-952f-08e7d35d5420.jpg"]},{"id":"5d","creationDate":"2024-04-28T00:00:00.000Z","feelings":["happy","relaxed"],"title":"The park","description":"The park is a really chill place where I can go and relax for a bit before going to work.","base":{"kind":"environment"},"assets":[]},{"id":"6d","creationDate":"2024-04-28T00:00:00.000Z","feelings":["happy"],"description":"This day has been a great day! I've talked with my friends.","base":{"kind":"date","referencedDate":"2024-04-27T00:00:00.000Z"},"assets":[]},{"id":"0e","creationDate":"2024-04-13T00:00:00.000Z","feelings":["active","happy"],"base":{"kind":"song","id":[{"provider":"spotify","id":"53mChDyESfwn9Dz8poHRf6"}],"link":["https://open.spotify.com/track/53mChDyESfwn9Dz8poHRf6"],"title":"Taking What's Not Yours","artist":"TV Girl"},"assets":[]},{"id":"1e","creationDate":"2024-04-13T00:00:00.000Z","feelings":[],"base":{"kind":"album","id":[{"provider":"spotify","id":"1d2PspdXmwrBEcOtquCvzT"}],"link":["https://open.spotify.com/album/1d2PspdXmwrBEcOtquCvzT"],"title":"CHASER","artist":"femtanyl"},"assets":[]},{"id":"2e","creationDate":"2024-04-26T00:00:00.000Z","feelings":["excited"],"title":"SalmorejoTech 2024","description":"SalmorejoTech is a great tech-event. I met some people and everything went great! :)","base":{"kind":"event"},"assets":[]},{"id":"3e","creationDate":"2024-06-26T00:00:00.000Z","feelings":["happy","relaxed"],"title":"Playing Minecraft with Mr. Pablo","description":"Mr. Pablo is my friend, she is a great friend. We spent a good time playing Minecraft. I am lucky to have a friend like him.","base":{"kind":"memory"},"assets":[]},{"id":"4e","creationDate":"2024-01-01T00:00:00.000Z","feelings":["excited","nervous"],"description":"New Year, New me! I'm really excited about what's going to happen this year, lots of changes. Changes may be scary, but they usually are for good!","base":{"kind":"feeling"},"assets":["f9d040d6-598c-4483-952f-08e7d35d5420.jpg"]},{"id":"5e","creationDate":"2024-04-28T00:00:00.000Z","feelings":["happy","relaxed"],"title":"The park","description":"The park is a really chill place where I can go and relax for a bit before going to work.","base":{"kind":"environment"},"assets":[]},{"id":"6e","creationDate":"2024-04-28T00:00:00.000Z","feelings":["happy"],"description":"This day has been a great day! I've talked with my friends.","base":{"kind":"date","referencedDate":"2024-04-27T00:00:00.000Z"},"assets":[]},{"id":"0f","creationDate":"2024-04-13T00:00:00.000Z","feelings":["active","happy"],"base":{"kind":"song","id":[{"provider":"spotify","id":"53mChDyESfwn9Dz8poHRf6"}],"link":["https://open.spotify.com/track/53mChDyESfwn9Dz8poHRf6"],"title":"Taking What's Not Yours","artist":"TV Girl"},"assets":[]},{"id":"1f","creationDate":"2024-04-13T00:00:00.000Z","feelings":[],"base":{"kind":"album","id":[{"provider":"spotify","id":"1d2PspdXmwrBEcOtquCvzT"}],"link":["https://open.spotify.com/album/1d2PspdXmwrBEcOtquCvzT"],"title":"CHASER","artist":"femtanyl"},"assets":[]},{"id":"2f","creationDate":"2024-04-26T00:00:00.000Z","feelings":["excited"],"title":"SalmorejoTech 2024","description":"SalmorejoTech is a great tech-event. I met some people and everything went great! :)","base":{"kind":"event"},"assets":[]},{"id":"3f","creationDate":"2024-06-26T00:00:00.000Z","feelings":["happy","relaxed"],"title":"Playing Minecraft with Mr. Pablo","description":"Mr. Pablo is my friend, she is a great friend. We spent a good time playing Minecraft. I am lucky to have a friend like him.","base":{"kind":"memory"},"assets":[]},{"id":"4f","creationDate":"2024-01-01T00:00:00.000Z","feelings":["excited","nervous"],"description":"New Year, New me! I'm really excited about what's going to happen this year, lots of changes. Changes may be scary, but they usually are for good!","base":{"kind":"feeling"},"assets":["f9d040d6-598c-4483-952f-08e7d35d5420.jpg"]},{"id":"5f","creationDate":"2024-04-28T00:00:00.000Z","feelings":["happy","relaxed"],"title":"The park","description":"The park is a really chill place where I can go and relax for a bit before going to work.","base":{"kind":"environment"},"assets":[]},{"id":"6f","creationDate":"2024-04-28T00:00:00.000Z","feelings":["happy"],"description":"This day has been a great day! I've talked with my friends.","base":{"kind":"date","referencedDate":"2024-04-27T00:00:00.000Z"},"assets":[]},{"id":"0g","creationDate":"2024-04-13T00:00:00.000Z","feelings":["active","happy"],"base":{"kind":"song","id":[{"provider":"spotify","id":"53mChDyESfwn9Dz8poHRf6"}],"link":["https://open.spotify.com/track/53mChDyESfwn9Dz8poHRf6"],"title":"Taking What's Not Yours","artist":"TV Girl"},"assets":[]},{"id":"1g","creationDate":"2024-04-13T00:00:00.000Z","feelings":[],"base":{"kind":"album","id":[{"provider":"spotify","id":"1d2PspdXmwrBEcOtquCvzT"}],"link":["https://open.spotify.com/album/1d2PspdXmwrBEcOtquCvzT"],"title":"CHASER","artist":"femtanyl"},"assets":[]},{"id":"2g","creationDate":"2024-04-26T00:00:00.000Z","feelings":["excited"],"title":"SalmorejoTech 2024","description":"SalmorejoTech is a great tech-event. I met some people and everything went great! :)","base":{"kind":"event"},"assets":[]},{"id":"3g","creationDate":"2024-06-26T00:00:00.000Z","feelings":["happy","relaxed"],"title":"Playing Minecraft with Mr. Pablo","description":"Mr. Pablo is my friend, she is a great friend. We spent a good time playing Minecraft. I am lucky to have a friend like him.","base":{"kind":"memory"},"assets":[]},{"id":"4g","creationDate":"2024-01-01T00:00:00.000Z","feelings":["excited","nervous"],"description":"New Year, New me! I'm really excited about what's going to happen this year, lots of changes. Changes may be scary, but they usually are for good!","base":{"kind":"feeling"},"assets":["f9d040d6-598c-4483-952f-08e7d35d5420.jpg"]},{"id":"5g","creationDate":"2024-04-28T00:00:00.000Z","feelings":["happy","relaxed"],"title":"The park","description":"The park is a really chill place where I can go and relax for a bit before going to work.","base":{"kind":"environment"},"assets":[]},{"id":"6g","creationDate":"2024-04-28T00:00:00.000Z","feelings":["happy"],"description":"This day has been a great day! I've talked with my friends.","base":{"kind":"date","referencedDate":"2024-04-27T00:00:00.000Z"},"assets":[]}]`) + entries: JSON.parse( + `[{"id":"0","creationDate":"2024-04-13T00:00:00.000Z","feelings":["active","happy"],"base":{"kind":"song","id":[{"provider":"spotify","id":"53mChDyESfwn9Dz8poHRf6"}],"link":["https://open.spotify.com/track/53mChDyESfwn9Dz8poHRf6"],"title":"Taking What's Not Yours","artist":"TV Girl"},"assets":[]},{"id":"1","creationDate":"2024-04-13T00:00:00.000Z","feelings":[],"base":{"kind":"album","id":[{"provider":"spotify","id":"1d2PspdXmwrBEcOtquCvzT"}],"link":["https://open.spotify.com/album/1d2PspdXmwrBEcOtquCvzT"],"title":"CHASER","artist":"femtanyl"},"assets":[]},{"id":"2","creationDate":"2024-04-26T00:00:00.000Z","feelings":["excited"],"title":"SalmorejoTech 2024","description":"SalmorejoTech is a great tech-event. I met some people and everything went great! :)","base":{"kind":"event"},"assets":[]},{"id":"3","creationDate":"2024-06-26T00:00:00.000Z","feelings":["happy","relaxed"],"title":"Playing Minecraft with Mr. Pablo","description":"Mr. Pablo is my friend, she is a great friend. We spent a good time playing Minecraft. I am lucky to have a friend like him.","base":{"kind":"memory"},"assets":[]},{"id":"4","creationDate":"2024-01-01T00:00:00.000Z","feelings":["excited","nervous"],"description":"New Year, New me! I'm really excited about what's going to happen this year, lots of changes. Changes may be scary, but they usually are for good!","base":{"kind":"feeling"},"assets":["f9d040d6-598c-4483-952f-08e7d35d5420.jpg"]},{"id":"5","creationDate":"2024-04-28T00:00:00.000Z","feelings":["happy","relaxed"],"title":"The park","description":"The park is a really chill place where I can go and relax for a bit before going to work.","base":{"kind":"environment"},"assets":[]},{"id":"6","creationDate":"2024-04-28T00:00:00.000Z","feelings":["happy"],"description":"This day has been a great day! I've talked with my friends.","base":{"kind":"date","referencedDate":"2024-04-27T00:00:00.000Z"},"assets":[]},{"id":"0a","creationDate":"2024-04-13T00:00:00.000Z","feelings":["active","happy"],"base":{"kind":"song","id":[{"provider":"spotify","id":"53mChDyESfwn9Dz8poHRf6"}],"link":["https://open.spotify.com/track/53mChDyESfwn9Dz8poHRf6"],"title":"Taking What's Not Yours","artist":"TV Girl"},"assets":[]},{"id":"1a","creationDate":"2024-04-13T00:00:00.000Z","feelings":[],"base":{"kind":"album","id":[{"provider":"spotify","id":"1d2PspdXmwrBEcOtquCvzT"}],"link":["https://open.spotify.com/album/1d2PspdXmwrBEcOtquCvzT"],"title":"CHASER","artist":"femtanyl"},"assets":[]},{"id":"2a","creationDate":"2024-04-26T00:00:00.000Z","feelings":["excited"],"title":"SalmorejoTech 2024","description":"SalmorejoTech is a great tech-event. I met some people and everything went great! :)","base":{"kind":"event"},"assets":[]},{"id":"3a","creationDate":"2024-06-26T00:00:00.000Z","feelings":["happy","relaxed"],"title":"Playing Minecraft with Mr. Pablo","description":"Mr. Pablo is my friend, she is a great friend. We spent a good time playing Minecraft. I am lucky to have a friend like him.","base":{"kind":"memory"},"assets":[]},{"id":"4a","creationDate":"2024-01-01T00:00:00.000Z","feelings":["excited","nervous"],"description":"New Year, New me! I'm really excited about what's going to happen this year, lots of changes. Changes may be scary, but they usually are for good!","base":{"kind":"feeling"},"assets":["f9d040d6-598c-4483-952f-08e7d35d5420.jpg"]},{"id":"5a","creationDate":"2024-04-28T00:00:00.000Z","feelings":["happy","relaxed"],"title":"The park","description":"The park is a really chill place where I can go and relax for a bit before going to work.","base":{"kind":"environment"},"assets":[]},{"id":"6a","creationDate":"2024-04-28T00:00:00.000Z","feelings":["happy"],"description":"This day has been a great day! I've talked with my friends.","base":{"kind":"date","referencedDate":"2024-04-27T00:00:00.000Z"},"assets":[]},{"id":"0b","creationDate":"2024-04-13T00:00:00.000Z","feelings":["active","happy"],"base":{"kind":"song","id":[{"provider":"spotify","id":"53mChDyESfwn9Dz8poHRf6"}],"link":["https://open.spotify.com/track/53mChDyESfwn9Dz8poHRf6"],"title":"Taking What's Not Yours","artist":"TV Girl"},"assets":[]},{"id":"1b","creationDate":"2024-04-13T00:00:00.000Z","feelings":[],"base":{"kind":"album","id":[{"provider":"spotify","id":"1d2PspdXmwrBEcOtquCvzT"}],"link":["https://open.spotify.com/album/1d2PspdXmwrBEcOtquCvzT"],"title":"CHASER","artist":"femtanyl"},"assets":[]},{"id":"2b","creationDate":"2024-04-26T00:00:00.000Z","feelings":["excited"],"title":"SalmorejoTech 2024","description":"SalmorejoTech is a great tech-event. I met some people and everything went great! :)","base":{"kind":"event"},"assets":[]},{"id":"3b","creationDate":"2024-06-26T00:00:00.000Z","feelings":["happy","relaxed"],"title":"Playing Minecraft with Mr. Pablo","description":"Mr. Pablo is my friend, she is a great friend. We spent a good time playing Minecraft. I am lucky to have a friend like him.","base":{"kind":"memory"},"assets":[]},{"id":"4b","creationDate":"2024-01-01T00:00:00.000Z","feelings":["excited","nervous"],"description":"New Year, New me! I'm really excited about what's going to happen this year, lots of changes. Changes may be scary, but they usually are for good!","base":{"kind":"feeling"},"assets":["f9d040d6-598c-4483-952f-08e7d35d5420.jpg"]},{"id":"5b","creationDate":"2024-04-28T00:00:00.000Z","feelings":["happy","relaxed"],"title":"The park","description":"The park is a really chill place where I can go and relax for a bit before going to work.","base":{"kind":"environment"},"assets":[]},{"id":"6b","creationDate":"2024-04-28T00:00:00.000Z","feelings":["happy"],"description":"This day has been a great day! I've talked with my friends.","base":{"kind":"date","referencedDate":"2024-04-27T00:00:00.000Z"},"assets":[]},{"id":"0c","creationDate":"2024-04-13T00:00:00.000Z","feelings":["active","happy"],"base":{"kind":"song","id":[{"provider":"spotify","id":"53mChDyESfwn9Dz8poHRf6"}],"link":["https://open.spotify.com/track/53mChDyESfwn9Dz8poHRf6"],"title":"Taking What's Not Yours","artist":"TV Girl"},"assets":[]},{"id":"1c","creationDate":"2024-04-13T00:00:00.000Z","feelings":[],"base":{"kind":"album","id":[{"provider":"spotify","id":"1d2PspdXmwrBEcOtquCvzT"}],"link":["https://open.spotify.com/album/1d2PspdXmwrBEcOtquCvzT"],"title":"CHASER","artist":"femtanyl"},"assets":[]},{"id":"2c","creationDate":"2024-04-26T00:00:00.000Z","feelings":["excited"],"title":"SalmorejoTech 2024","description":"SalmorejoTech is a great tech-event. I met some people and everything went great! :)","base":{"kind":"event"},"assets":[]},{"id":"3c","creationDate":"2024-06-26T00:00:00.000Z","feelings":["happy","relaxed"],"title":"Playing Minecraft with Mr. Pablo","description":"Mr. Pablo is my friend, she is a great friend. We spent a good time playing Minecraft. I am lucky to have a friend like him.","base":{"kind":"memory"},"assets":[]},{"id":"4c","creationDate":"2024-01-01T00:00:00.000Z","feelings":["excited","nervous"],"description":"New Year, New me! I'm really excited about what's going to happen this year, lots of changes. Changes may be scary, but they usually are for good!","base":{"kind":"feeling"},"assets":["f9d040d6-598c-4483-952f-08e7d35d5420.jpg"]},{"id":"5c","creationDate":"2024-04-28T00:00:00.000Z","feelings":["happy","relaxed"],"title":"The park","description":"The park is a really chill place where I can go and relax for a bit before going to work.","base":{"kind":"environment"},"assets":[]},{"id":"6c","creationDate":"2024-04-28T00:00:00.000Z","feelings":["happy"],"description":"This day has been a great day! I've talked with my friends.","base":{"kind":"date","referencedDate":"2024-04-27T00:00:00.000Z"},"assets":[]},{"id":"0d","creationDate":"2024-04-13T00:00:00.000Z","feelings":["active","happy"],"base":{"kind":"song","id":[{"provider":"spotify","id":"53mChDyESfwn9Dz8poHRf6"}],"link":["https://open.spotify.com/track/53mChDyESfwn9Dz8poHRf6"],"title":"Taking What's Not Yours","artist":"TV Girl"},"assets":[]},{"id":"1d","creationDate":"2024-04-13T00:00:00.000Z","feelings":[],"base":{"kind":"album","id":[{"provider":"spotify","id":"1d2PspdXmwrBEcOtquCvzT"}],"link":["https://open.spotify.com/album/1d2PspdXmwrBEcOtquCvzT"],"title":"CHASER","artist":"femtanyl"},"assets":[]},{"id":"2d","creationDate":"2024-04-26T00:00:00.000Z","feelings":["excited"],"title":"SalmorejoTech 2024","description":"SalmorejoTech is a great tech-event. I met some people and everything went great! :)","base":{"kind":"event"},"assets":[]},{"id":"3d","creationDate":"2024-06-26T00:00:00.000Z","feelings":["happy","relaxed"],"title":"Playing Minecraft with Mr. Pablo","description":"Mr. Pablo is my friend, she is a great friend. We spent a good time playing Minecraft. I am lucky to have a friend like him.","base":{"kind":"memory"},"assets":[]},{"id":"4d","creationDate":"2024-01-01T00:00:00.000Z","feelings":["excited","nervous"],"description":"New Year, New me! I'm really excited about what's going to happen this year, lots of changes. Changes may be scary, but they usually are for good!","base":{"kind":"feeling"},"assets":["f9d040d6-598c-4483-952f-08e7d35d5420.jpg"]},{"id":"5d","creationDate":"2024-04-28T00:00:00.000Z","feelings":["happy","relaxed"],"title":"The park","description":"The park is a really chill place where I can go and relax for a bit before going to work.","base":{"kind":"environment"},"assets":[]},{"id":"6d","creationDate":"2024-04-28T00:00:00.000Z","feelings":["happy"],"description":"This day has been a great day! I've talked with my friends.","base":{"kind":"date","referencedDate":"2024-04-27T00:00:00.000Z"},"assets":[]},{"id":"0e","creationDate":"2024-04-13T00:00:00.000Z","feelings":["active","happy"],"base":{"kind":"song","id":[{"provider":"spotify","id":"53mChDyESfwn9Dz8poHRf6"}],"link":["https://open.spotify.com/track/53mChDyESfwn9Dz8poHRf6"],"title":"Taking What's Not Yours","artist":"TV Girl"},"assets":[]},{"id":"1e","creationDate":"2024-04-13T00:00:00.000Z","feelings":[],"base":{"kind":"album","id":[{"provider":"spotify","id":"1d2PspdXmwrBEcOtquCvzT"}],"link":["https://open.spotify.com/album/1d2PspdXmwrBEcOtquCvzT"],"title":"CHASER","artist":"femtanyl"},"assets":[]},{"id":"2e","creationDate":"2024-04-26T00:00:00.000Z","feelings":["excited"],"title":"SalmorejoTech 2024","description":"SalmorejoTech is a great tech-event. I met some people and everything went great! :)","base":{"kind":"event"},"assets":[]},{"id":"3e","creationDate":"2024-06-26T00:00:00.000Z","feelings":["happy","relaxed"],"title":"Playing Minecraft with Mr. Pablo","description":"Mr. Pablo is my friend, she is a great friend. We spent a good time playing Minecraft. I am lucky to have a friend like him.","base":{"kind":"memory"},"assets":[]},{"id":"4e","creationDate":"2024-01-01T00:00:00.000Z","feelings":["excited","nervous"],"description":"New Year, New me! I'm really excited about what's going to happen this year, lots of changes. Changes may be scary, but they usually are for good!","base":{"kind":"feeling"},"assets":["f9d040d6-598c-4483-952f-08e7d35d5420.jpg"]},{"id":"5e","creationDate":"2024-04-28T00:00:00.000Z","feelings":["happy","relaxed"],"title":"The park","description":"The park is a really chill place where I can go and relax for a bit before going to work.","base":{"kind":"environment"},"assets":[]},{"id":"6e","creationDate":"2024-04-28T00:00:00.000Z","feelings":["happy"],"description":"This day has been a great day! I've talked with my friends.","base":{"kind":"date","referencedDate":"2024-04-27T00:00:00.000Z"},"assets":[]},{"id":"0f","creationDate":"2024-04-13T00:00:00.000Z","feelings":["active","happy"],"base":{"kind":"song","id":[{"provider":"spotify","id":"53mChDyESfwn9Dz8poHRf6"}],"link":["https://open.spotify.com/track/53mChDyESfwn9Dz8poHRf6"],"title":"Taking What's Not Yours","artist":"TV Girl"},"assets":[]},{"id":"1f","creationDate":"2024-04-13T00:00:00.000Z","feelings":[],"base":{"kind":"album","id":[{"provider":"spotify","id":"1d2PspdXmwrBEcOtquCvzT"}],"link":["https://open.spotify.com/album/1d2PspdXmwrBEcOtquCvzT"],"title":"CHASER","artist":"femtanyl"},"assets":[]},{"id":"2f","creationDate":"2024-04-26T00:00:00.000Z","feelings":["excited"],"title":"SalmorejoTech 2024","description":"SalmorejoTech is a great tech-event. I met some people and everything went great! :)","base":{"kind":"event"},"assets":[]},{"id":"3f","creationDate":"2024-06-26T00:00:00.000Z","feelings":["happy","relaxed"],"title":"Playing Minecraft with Mr. Pablo","description":"Mr. Pablo is my friend, she is a great friend. We spent a good time playing Minecraft. I am lucky to have a friend like him.","base":{"kind":"memory"},"assets":[]},{"id":"4f","creationDate":"2024-01-01T00:00:00.000Z","feelings":["excited","nervous"],"description":"New Year, New me! I'm really excited about what's going to happen this year, lots of changes. Changes may be scary, but they usually are for good!","base":{"kind":"feeling"},"assets":["f9d040d6-598c-4483-952f-08e7d35d5420.jpg"]},{"id":"5f","creationDate":"2024-04-28T00:00:00.000Z","feelings":["happy","relaxed"],"title":"The park","description":"The park is a really chill place where I can go and relax for a bit before going to work.","base":{"kind":"environment"},"assets":[]},{"id":"6f","creationDate":"2024-04-28T00:00:00.000Z","feelings":["happy"],"description":"This day has been a great day! I've talked with my friends.","base":{"kind":"date","referencedDate":"2024-04-27T00:00:00.000Z"},"assets":[]},{"id":"0g","creationDate":"2024-04-13T00:00:00.000Z","feelings":["active","happy"],"base":{"kind":"song","id":[{"provider":"spotify","id":"53mChDyESfwn9Dz8poHRf6"}],"link":["https://open.spotify.com/track/53mChDyESfwn9Dz8poHRf6"],"title":"Taking What's Not Yours","artist":"TV Girl"},"assets":[]},{"id":"1g","creationDate":"2024-04-13T00:00:00.000Z","feelings":[],"base":{"kind":"album","id":[{"provider":"spotify","id":"1d2PspdXmwrBEcOtquCvzT"}],"link":["https://open.spotify.com/album/1d2PspdXmwrBEcOtquCvzT"],"title":"CHASER","artist":"femtanyl"},"assets":[]},{"id":"2g","creationDate":"2024-04-26T00:00:00.000Z","feelings":["excited"],"title":"SalmorejoTech 2024","description":"SalmorejoTech is a great tech-event. I met some people and everything went great! :)","base":{"kind":"event"},"assets":[]},{"id":"3g","creationDate":"2024-06-26T00:00:00.000Z","feelings":["happy","relaxed"],"title":"Playing Minecraft with Mr. Pablo","description":"Mr. Pablo is my friend, she is a great friend. We spent a good time playing Minecraft. I am lucky to have a friend like him.","base":{"kind":"memory"},"assets":[]},{"id":"4g","creationDate":"2024-01-01T00:00:00.000Z","feelings":["excited","nervous"],"description":"New Year, New me! I'm really excited about what's going to happen this year, lots of changes. Changes may be scary, but they usually are for good!","base":{"kind":"feeling"},"assets":["f9d040d6-598c-4483-952f-08e7d35d5420.jpg"]},{"id":"5g","creationDate":"2024-04-28T00:00:00.000Z","feelings":["happy","relaxed"],"title":"The park","description":"The park is a really chill place where I can go and relax for a bit before going to work.","base":{"kind":"environment"},"assets":[]},{"id":"6g","creationDate":"2024-04-28T00:00:00.000Z","feelings":["happy"],"description":"This day has been a great day! I've talked with my friends.","base":{"kind":"date","referencedDate":"2024-04-27T00:00:00.000Z"},"assets":[]}]`, + ), }, }; @@ -75,10 +77,10 @@ export async function startAuth() { session_keys[`uid:${uid}`] = key; session_keys[`key:${key}`] = uid; - return key + return key; }, createJwt: async (uid) => { - let user = await funcs.user(uid) + let user = await funcs.user(uid); return await new Jose.SignJWT({ uid: user.uid, @@ -93,7 +95,7 @@ export async function startAuth() { verifyJwt: async (jwt) => { return await Jose.jwtVerify(jwt, JWT_SECRET); }, - } + }; return funcs; -} \ No newline at end of file +} diff --git a/identity-api/src/consts.js b/identity-api/src/consts.js index 4c2024e..291da48 100644 --- a/identity-api/src/consts.js +++ b/identity-api/src/consts.js @@ -1,28 +1,31 @@ // 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 . -import "dotenv/config" +import "dotenv/config"; import app from "./app.js"; const REQUIRED_VARS = ["IDENTITY_API_JWT_SECRET", "IDENTITY_API_ASSET_API_ENDPOINT", "IDENTITY_API_JWT_ALG"]; -REQUIRED_VARS.forEach(element => { - if (process.env[element] == null || (typeof process.env[element] === "string" && process.env[element].length === 0)) { +REQUIRED_VARS.forEach((element) => { + if ( + process.env[element] == null || + (typeof process.env[element] === "string" && process.env[element].length === 0) + ) { app.log.error(`Required environment variable was not set: ${element}`); - app.close().then(() => process.exit(1)) + app.close().then(() => process.exit(1)); } }); @@ -31,4 +34,5 @@ export const JWT_SECRET = new TextEncoder().encode(process.env["IDENTITY_API_JWT export const JWT_ALG = process.env["IDENTITY_API_JWT_ALG"]; export const LISTEN_PORT = process.env["IDENTITY_API_LISTEN_PORT"] || 3000; export const ASSET_API_ENDPOINT = process.env["IDENTITY_API_ASSET_API_ENDPOINT"]; -export const ASSET_API_M2M_REFRESH_INTERVAL = process.env["IDENTITY_API_ASSET_API_M2M_REFRESH_INTERVAL_MS"] || 60 * 1000 \ No newline at end of file +export const ASSET_API_M2M_REFRESH_INTERVAL = + process.env["IDENTITY_API_ASSET_API_M2M_REFRESH_INTERVAL_MS"] || 60 * 1000; diff --git a/identity-api/src/index.js b/identity-api/src/index.js index 766ed30..f5d4476 100644 --- a/identity-api/src/index.js +++ b/identity-api/src/index.js @@ -1,304 +1,45 @@ // 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 . -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 app from "./app.js"; +import { IDENTITY_API_LANDING_MESSAGE, LISTEN_PORT } from "./consts.js"; import { startAuth } from "./auth.js"; -import { randomUUID } from "node:crypto"; + import cors from "@fastify/cors"; +import { registerRoutes } from "./routes/index.js"; let auth = await startAuth(); +app.addSchema({ + $id: "schema://identity/authorization", + type: "object", + properties: { + authorization: { type: "string" }, + }, + required: ["authorization"], +}); + app.register(cors, { origin: true, -}) +}); + +registerRoutes(app, auth); 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 }); diff --git a/identity-api/src/m2m.js b/identity-api/src/m2m.js index ddc02aa..aed9328 100644 --- a/identity-api/src/m2m.js +++ b/identity-api/src/m2m.js @@ -1,26 +1,26 @@ // 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 . import { createVerify } from "node:crypto"; -import assert from "node:assert" +import assert from "node:assert"; import app from "./app.js"; import { ASSET_API_ENDPOINT, ASSET_API_M2M_REFRESH_INTERVAL } from "./consts.js"; -let assetPubKey = await fetchAssetPubkey() -let assetAlgorithm = await fetchAssetAlgorithm() +let assetPubKey = await fetchAssetPubkey(); +let assetAlgorithm = await fetchAssetAlgorithm(); setInterval(async () => { try { @@ -29,7 +29,7 @@ setInterval(async () => { if (pubkey != null && algo != null) { if (assetPubKey !== pubkey) { - app.log.warn("The M2M public key has changed!") + app.log.warn("The M2M public key has changed!"); } if (assetAlgorithm !== algo) { @@ -46,7 +46,7 @@ setInterval(async () => { app.log.warn("Failed to update the M2M credentials"); app.log.warn(e); } -}, ASSET_API_M2M_REFRESH_INTERVAL) +}, ASSET_API_M2M_REFRESH_INTERVAL); async function fetchAssetPubkey() { let url = new URL(ASSET_API_ENDPOINT); @@ -72,11 +72,11 @@ function partsFromSigned(content) { assert(parts.length === 2); - return parts + return parts; } export function verifySignature(content) { - let parts = partsFromSigned(content) + let parts = partsFromSigned(content); let verify = createVerify(assetAlgorithm); verify.update(parts[0]); @@ -89,4 +89,4 @@ export function verifySignature(content) { export function contentFromSigned(content) { return partsFromSigned(content)[0]; -} \ No newline at end of file +} diff --git a/identity-api/src/routes/asset/endpoint.js b/identity-api/src/routes/asset/endpoint.js new file mode 100644 index 0000000..3635593 --- /dev/null +++ b/identity-api/src/routes/asset/endpoint.js @@ -0,0 +1,9 @@ +import { ASSET_API_ENDPOINT } from "../../consts.js"; + +export default function register(app) { + app.get("/asset/endpoint", { + async handler() { + return ASSET_API_ENDPOINT; + }, + }); +} diff --git a/identity-api/src/routes/asset/index.js b/identity-api/src/routes/asset/index.js new file mode 100644 index 0000000..5f34368 --- /dev/null +++ b/identity-api/src/routes/asset/index.js @@ -0,0 +1,5 @@ +import endpoint from "./endpoint.js"; + +export default function registerRoutes(app, auth) { + endpoint(app, auth); +} diff --git a/identity-api/src/routes/auth/account.js b/identity-api/src/routes/auth/account.js new file mode 100644 index 0000000..3fc38af --- /dev/null +++ b/identity-api/src/routes/auth/account.js @@ -0,0 +1,21 @@ +export default function register(app, auth) { + 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: { $ref: "schema://identity/authorization" }, + }, + }); +} diff --git a/identity-api/src/routes/auth/genkey.js b/identity-api/src/routes/auth/genkey.js new file mode 100644 index 0000000..b0330a4 --- /dev/null +++ b/identity-api/src/routes/auth/genkey.js @@ -0,0 +1,17 @@ +export default function register(app, auth) { + 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: { $ref: "schema://identity/authorization" }, + }, + }); +} diff --git a/identity-api/src/routes/auth/heirs.js b/identity-api/src/routes/auth/heirs.js new file mode 100644 index 0000000..424ab85 --- /dev/null +++ b/identity-api/src/routes/auth/heirs.js @@ -0,0 +1,24 @@ +export default function register(app, auth) { + 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: { $ref: "schema://identity/authorization" }, + body: { + type: "array", + }, + }, + }); +} diff --git a/identity-api/src/routes/auth/index.js b/identity-api/src/routes/auth/index.js new file mode 100644 index 0000000..ab04fcf --- /dev/null +++ b/identity-api/src/routes/auth/index.js @@ -0,0 +1,13 @@ +import account from "./account.js"; +import genkey from "./genkey.js"; +import heirs from "./heirs.js"; +import login from "./login.js"; +import register from "./register.js"; + +export default function registerRoutes(app, auth) { + account(app, auth); + genkey(app, auth); + heirs(app, auth); + login(app, auth); + register(app, auth); +} diff --git a/identity-api/src/routes/auth/login.js b/identity-api/src/routes/auth/login.js new file mode 100644 index 0000000..faa4247 --- /dev/null +++ b/identity-api/src/routes/auth/login.js @@ -0,0 +1,30 @@ +export default function register(app, auth) { + 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"], + }, + }); +} diff --git a/identity-api/src/routes/auth/register.js b/identity-api/src/routes/auth/register.js new file mode 100644 index 0000000..e56ae46 --- /dev/null +++ b/identity-api/src/routes/auth/register.js @@ -0,0 +1,36 @@ +export default function register(app, auth) { + 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"], + }, + }, + }); +} diff --git a/identity-api/src/routes/entry/index.js b/identity-api/src/routes/entry/index.js new file mode 100644 index 0000000..38febe1 --- /dev/null +++ b/identity-api/src/routes/entry/index.js @@ -0,0 +1,51 @@ +import { randomUUID } from "node:crypto"; +import list from "./list.js"; + +export default function registerRoutes(app, auth) { + list(app, auth); + + app.delete("/entry", { + async handler(request) { + 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: { $ref: "schema://identity/authorization" }, + query: { + type: "object", + properties: { + entry_id: { type: "string" }, + }, + required: ["entry_id"], + }, + }, + }); + + app.put("/entry", { + async handler(request) { + 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: { $ref: "schema://identity/authorization" }, + body: { + type: "object", + properties: { + entry: { type: "object" }, + }, + required: ["entry"], + }, + }, + }); +} diff --git a/identity-api/src/routes/entry/list.js b/identity-api/src/routes/entry/list.js new file mode 100644 index 0000000..8b8d33a --- /dev/null +++ b/identity-api/src/routes/entry/list.js @@ -0,0 +1,27 @@ +export default function register(app, auth) { + 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: { $ref: "schema://identity/authorization" }, + query: { + type: "object", + properties: { + limit: { type: "number" }, + offset: { type: "number" }, + }, + required: ["limit", "offset"], + }, + }, + }); +} diff --git a/identity-api/src/routes/index.js b/identity-api/src/routes/index.js new file mode 100644 index 0000000..5ef4b5d --- /dev/null +++ b/identity-api/src/routes/index.js @@ -0,0 +1,11 @@ +import m2m from "./m2m/index.js"; +import asset from "./asset/index.js"; +import entry from "./entry/index.js"; +import authRoutes from "./auth/index.js"; + +export function registerRoutes(app, auth) { + m2m(app, auth); + asset(app, auth); + entry(app, auth); + authRoutes(app, auth); +} diff --git a/identity-api/src/routes/m2m/account.js b/identity-api/src/routes/m2m/account.js new file mode 100644 index 0000000..1ca2665 --- /dev/null +++ b/identity-api/src/routes/m2m/account.js @@ -0,0 +1,20 @@ +import { contentFromSigned, verifySignature } from "../../m2m.js"; + +export default function register(app, auth) { + 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; + }, + }); +} diff --git a/identity-api/src/routes/m2m/asset.js b/identity-api/src/routes/m2m/asset.js new file mode 100644 index 0000000..0697392 --- /dev/null +++ b/identity-api/src/routes/m2m/asset.js @@ -0,0 +1,20 @@ +import { contentFromSigned, verifySignature } from "../../m2m.js"; + +export default function register(app, auth) { + 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); + }, + }); +} diff --git a/identity-api/src/routes/m2m/index.js b/identity-api/src/routes/m2m/index.js new file mode 100644 index 0000000..e667a03 --- /dev/null +++ b/identity-api/src/routes/m2m/index.js @@ -0,0 +1,7 @@ +import asset from "./asset.js"; +import account from "./account.js"; + +export default function registerRoutes(app, auth) { + asset(app, auth); + account(app, auth); +}