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);
+}