diff --git a/Insomnia.json b/Insomnia.json index 81a6e33..8d33ff3 100644 --- a/Insomnia.json +++ b/Insomnia.json @@ -1,140 +1 @@ -{ - "_type": "export", - "__export_format": 4, - "__export_source": "apimatic.transformer", - "resources": [ - { - "name": "tracovid", - "_type": "workspace", - "_id": "wrk_0c7e46baea1348808af5376ae04cfc48" - }, - { - "name": "Misc", - "_type": "request_group", - "_id": "fld_d17a33fe0ef742dab8aa78c5a570ef5f", - "parentId": "wrk_0c7e46baea1348808af5376ae04cfc48", - "description": "" - }, - { - "name": "login", - "method": "GET", - "url": "http://localhost/login/facebook", - "authentication": { - "type": "bearer" - }, - "_type": "request", - "_id": "req_81137cfbc661458b8d3b80b3b6175cb9", - "parentId": "fld_d17a33fe0ef742dab8aa78c5a570ef5f" - }, - { - "name": "all-cases", - "method": "GET", - "url": "http://localhost/api/v1/case/all", - "authentication": { - "type": "bearer" - }, - "_type": "request", - "_id": "req_d0f490d97cf349cf9e263d5e76cfeaca", - "parentId": "fld_d17a33fe0ef742dab8aa78c5a570ef5f" - }, - { - "name": "add-case", - "method": "POST", - "url": "http://localhost/api/v1/case", - "body": { - "mimeType": "application/json", - "text": "{\r\n \"status\": 1,\r\n \"postalCode\": \"4200-192\",\r\n \"confinementState\": 1,\r\n \"condition\": 1,\r\n \"info\": null,\r\n \"geo\": {\r\n \"lat\": 0,\r\n \"lon\": 0\r\n },\r\n \"symptoms\": [\r\n 3,\r\n 4,\r\n 5\r\n ]\r\n}" - }, - "headers": [ - { - "name": "Content-Type", - "value": "application/json", - "disabled": false - } - ], - "authentication": { - "type": "bearer" - }, - "_type": "request", - "_id": "req_be25ff70d1b140c4bdc8439a25fd6281", - "parentId": "fld_d17a33fe0ef742dab8aa78c5a570ef5f" - }, - { - "name": "all-symptoms", - "method": "GET", - "url": "http://localhost/api/v1/symptom/all", - "authentication": { - "type": "bearer" - }, - "_type": "request", - "_id": "req_b553b2433f1d4dbd9ad9f8789a4f8c3b", - "parentId": "fld_d17a33fe0ef742dab8aa78c5a570ef5f" - }, - { - "name": "all-conditions", - "method": "GET", - "url": "http://localhost/api/v1/condition/all", - "authentication": { - "type": "bearer" - }, - "_type": "request", - "_id": "req_7dcfda178cb04cdbab5d191f4b9c362f", - "parentId": "fld_d17a33fe0ef742dab8aa78c5a570ef5f" - }, - { - "name": "all-confinement-states", - "method": "GET", - "url": "http://localhost/api/v1/confinementState/all", - "authentication": { - "type": "bearer" - }, - "_type": "request", - "_id": "req_3ec8c33bf0bc476e8c100ca8759b478f", - "parentId": "fld_d17a33fe0ef742dab8aa78c5a570ef5f" - }, - { - "name": "case-condiitons-by-postalcode", - "method": "GET", - "url": "http://localhost/api/v1/case/condition/4200-192", - "authentication": { - "type": "bearer" - }, - "_type": "request", - "_id": "req_8361810611b14630884eb3fce5bc1bbe", - "parentId": "fld_d17a33fe0ef742dab8aa78c5a570ef5f" - }, - { - "name": "case-confinements-by-postalcode", - "method": "GET", - "url": "http://localhost/api/v1/case/confinement/4200-192", - "authentication": { - "type": "bearer" - }, - "_type": "request", - "_id": "req_c4a905f0302a47df829fe1c7a1224e2c", - "parentId": "fld_d17a33fe0ef742dab8aa78c5a570ef5f" - }, - { - "name": "update-user", - "method": "PUT", - "url": "http://localhost/api/v1/user", - "body": { - "mimeType": "application/json", - "text": "{\r\n \"postalCode\": \"4200-192\",\r\n \"geo\": {\r\n \"lat\": 10.34,\r\n \"lon\": 2.8\r\n },\r\n \"phone\": \"+351960123122\",\r\n \"email\": \"jane@doe.com\",\r\n \"name\": \"John Doe\",\r\n \"patientToken\": \"QWERTY\",\r\n \"showOnboarding\": false\r\n}" - }, - "headers": [ - { - "name": "Content-Type", - "value": "application/json", - "disabled": false - } - ], - "authentication": { - "type": "bearer" - }, - "_type": "request", - "_id": "req_fd80cb07074d49169a95751d52d77857", - "parentId": "fld_d17a33fe0ef742dab8aa78c5a570ef5f" - } - ] -} \ No newline at end of file +{"_type":"export","__export_format":4,"__export_date":"2020-03-21T22:19:51.351Z","__export_source":"insomnia.desktop.app:v7.1.1","resources":[{"_id":"req_fd80cb07074d49169a95751d52d77857","authentication":{"token":"{{ bearer_token }}","type":"bearer"},"body":{"mimeType":"application/json","text":"{\r\n \"postalCode\": \"4200-192\",\r\n \"geo\": {\r\n \"lat\": 10.34,\r\n \"lon\": 2.8\r\n },\r\n \"phone\": \"+351960123122\",\r\n \"email\": \"jane@doe.com\",\r\n \"name\": \"John Doe\",\r\n \"patientToken\": \"QWERTY\",\r\n \"showOnboarding\": false\r\n}"},"created":1584813902546,"description":"","headers":[{"disabled":false,"id":"pair_5dbe70387ce046fe9825d1b8e0512865","name":"Content-Type","value":"application/json"}],"isPrivate":false,"metaSortKey":-1584813902546,"method":"PUT","modified":1584829120955,"name":"update-user","parameters":[],"parentId":"fld_d17a33fe0ef742dab8aa78c5a570ef5f","settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingFollowRedirects":"global","settingRebuildPath":true,"settingSendCookies":true,"settingStoreCookies":true,"url":"{{ base_url }}/user","_type":"request"},{"_id":"fld_d17a33fe0ef742dab8aa78c5a570ef5f","created":1584813902589,"description":"","environment":{},"environmentPropertyOrder":null,"metaSortKey":-1584813902590,"modified":1584813902589,"name":"Misc","parentId":"wrk_0c7e46baea1348808af5376ae04cfc48","_type":"request_group"},{"_id":"wrk_0c7e46baea1348808af5376ae04cfc48","created":1584813902593,"description":"","modified":1584813902593,"name":"tracovid","parentId":null,"_type":"workspace"},{"_id":"req_c4a905f0302a47df829fe1c7a1224e2c","authentication":{"token":"{{ bearer_token }}","type":"bearer"},"body":{},"created":1584813902554,"description":"","headers":[],"isPrivate":false,"metaSortKey":-1584813902554,"method":"GET","modified":1584829114535,"name":"case-confinements-by-postalcode","parameters":[],"parentId":"fld_d17a33fe0ef742dab8aa78c5a570ef5f","settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingFollowRedirects":"global","settingRebuildPath":true,"settingSendCookies":true,"settingStoreCookies":true,"url":"{{ base_url }}/case/confinement/4200-192","_type":"request"},{"_id":"req_8361810611b14630884eb3fce5bc1bbe","authentication":{"token":"{{ bearer_token }}","type":"bearer"},"body":{},"created":1584813902561,"description":"","headers":[],"isPrivate":false,"metaSortKey":-1584813902561,"method":"GET","modified":1584829107727,"name":"case-conditions-by-postalcode","parameters":[],"parentId":"fld_d17a33fe0ef742dab8aa78c5a570ef5f","settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingFollowRedirects":"global","settingRebuildPath":true,"settingSendCookies":true,"settingStoreCookies":true,"url":"{{ base_url }}/case/condition/4200-192","_type":"request"},{"_id":"req_3ec8c33bf0bc476e8c100ca8759b478f","authentication":{"token":"{{ bearer_token }}","type":"bearer"},"body":{},"created":1584813902567,"description":"","headers":[],"isPrivate":false,"metaSortKey":-1584813902567,"method":"GET","modified":1584829089335,"name":"all-confinement-states","parameters":[],"parentId":"fld_d17a33fe0ef742dab8aa78c5a570ef5f","settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingFollowRedirects":"global","settingRebuildPath":true,"settingSendCookies":true,"settingStoreCookies":true,"url":"{{ base_url }}/confinementState/all","_type":"request"},{"_id":"req_7dcfda178cb04cdbab5d191f4b9c362f","authentication":{"token":"{{ bearer_token }}","type":"bearer"},"body":{},"created":1584813902571,"description":"","headers":[],"isPrivate":false,"metaSortKey":-1584813902571,"method":"GET","modified":1584829075889,"name":"all-conditions","parameters":[],"parentId":"fld_d17a33fe0ef742dab8aa78c5a570ef5f","settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingFollowRedirects":"global","settingRebuildPath":true,"settingSendCookies":true,"settingStoreCookies":true,"url":"{{ base_url }}/condition/all","_type":"request"},{"_id":"req_b553b2433f1d4dbd9ad9f8789a4f8c3b","authentication":{"token":"{{ bearer_token }}","type":"bearer"},"body":{},"created":1584813902576,"description":"","headers":[],"isPrivate":false,"metaSortKey":-1584813902576,"method":"GET","modified":1584829062751,"name":"all-symptoms","parameters":[],"parentId":"fld_d17a33fe0ef742dab8aa78c5a570ef5f","settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingFollowRedirects":"global","settingRebuildPath":true,"settingSendCookies":true,"settingStoreCookies":true,"url":"{{ base_url }}/symptom/all","_type":"request"},{"_id":"req_be25ff70d1b140c4bdc8439a25fd6281","authentication":{"token":"{{ bearer_token }}","type":"bearer"},"body":{"mimeType":"application/json","text":"{\r\n \"status\": 1,\r\n \"postalCode\": \"4200-192\",\r\n \"confinementState\": 1,\r\n \"condition\": 1,\r\n \"info\": null,\r\n \"geo\": {\r\n \"lat\": 0,\r\n \"lon\": 0\r\n },\r\n \"symptoms\": [\r\n 3,\r\n 4,\r\n 5\r\n ]\r\n}"},"created":1584813902580,"description":"","headers":[{"disabled":false,"id":"pair_1979a08cf91f4e66b8182d458c591a81","name":"Content-Type","value":"application/json"}],"isPrivate":false,"metaSortKey":-1584813902580,"method":"POST","modified":1584829053421,"name":"add-case","parameters":[],"parentId":"fld_d17a33fe0ef742dab8aa78c5a570ef5f","settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingFollowRedirects":"global","settingRebuildPath":true,"settingSendCookies":true,"settingStoreCookies":true,"url":"{{ base_url }}/case","_type":"request"},{"_id":"req_d0f490d97cf349cf9e263d5e76cfeaca","authentication":{"token":"{{ bearer_token }}","type":"bearer"},"body":{},"created":1584813902584,"description":"","headers":[],"isPrivate":false,"metaSortKey":-1584813902584,"method":"GET","modified":1584829039499,"name":"all-cases","parameters":[],"parentId":"fld_d17a33fe0ef742dab8aa78c5a570ef5f","settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingFollowRedirects":"global","settingRebuildPath":true,"settingSendCookies":true,"settingStoreCookies":true,"url":"{{ base_url }}/case/all","_type":"request"},{"_id":"req_81137cfbc661458b8d3b80b3b6175cb9","authentication":{"token":"","type":"bearer"},"body":{},"created":1584813902587,"description":"","headers":[],"isPrivate":false,"metaSortKey":-1584813902587,"method":"GET","modified":1584829014579,"name":"login","parameters":[],"parentId":"fld_d17a33fe0ef742dab8aa78c5a570ef5f","settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingFollowRedirects":"global","settingRebuildPath":true,"settingSendCookies":true,"settingStoreCookies":true,"url":"http://localhost:3000/login/facebook","_type":"request"},{"_id":"req_db047fde6b1b4c749387b94c3c7e02be","authentication":{"token":"{{ bearer_token }}","type":"bearer"},"body":{},"created":1584824578256,"description":"","headers":[],"isPrivate":false,"metaSortKey":-1584813902573.5,"method":"GET","modified":1584828987535,"name":"all-videos","parameters":[],"parentId":"fld_d17a33fe0ef742dab8aa78c5a570ef5f","settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingFollowRedirects":"global","settingRebuildPath":true,"settingSendCookies":true,"settingStoreCookies":true,"url":"{{ base_url }}/video/all","_type":"request"},{"_id":"env_2fb0733ff3f6695909ad7f5614108dc516ce22da","color":null,"created":1584813902629,"data":{},"dataPropertyOrder":null,"isPrivate":false,"metaSortKey":1584813902629,"modified":1584813902629,"name":"Base Environment","parentId":"wrk_0c7e46baea1348808af5376ae04cfc48","_type":"environment"},{"_id":"jar_2fb0733ff3f6695909ad7f5614108dc516ce22da","cookies":[{"creation":"2020-03-21T18:08:51.728Z","domain":"facebook.com","expires":"2020-06-19T18:08:50.000Z","hostOnly":false,"httpOnly":true,"id":"9371270736889055","key":"fr","lastAccessed":"2020-03-21T18:08:51.728Z","maxAge":7775999,"path":"/","secure":true,"value":"1FqJRHE2YIzKEeBEy..Bedlgz.-N.AAA.0.0.Bedlgz.AWU58_hh"},{"creation":"2020-03-21T18:08:51.729Z","domain":"facebook.com","expires":"2022-03-21T18:08:51.000Z","hostOnly":false,"httpOnly":true,"id":"24595114806620177","key":"sb","lastAccessed":"2020-03-21T18:08:51.729Z","maxAge":63072000,"path":"/","secure":true,"value":"M1h2XpifPwkCCDXjao3eYoFs"}],"created":1584813902633,"modified":1584814131729,"name":"Default Jar","parentId":"wrk_0c7e46baea1348808af5376ae04cfc48","_type":"cookie_jar"},{"_id":"env_045951f59bc34282bfcbfbe50b7cee9f","color":null,"created":1584813958858,"data":{"base_url":"http://localhost:3000/api/v1","bearer_token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJwYXlsb2FkIjp7ImlkIjoiMzg1NDc2NjA1MTIwODA2NiIsIm5hbWUiOiJDYXJsb3MgUG9tYmVpcm8ifSwicm9sZXMiOlsidXNlciJdLCJpYXQiOjE1ODQ4MTM3NjQsImV4cCI6MTU4NDkwMDE2NH0.gGtpbj0PFjfADblsW0lOuhYrsANJwvgYVPchS3-nnnw"},"dataPropertyOrder":{"&":["base_url","bearer_token"]},"isPrivate":false,"metaSortKey":1584813958858,"modified":1584829001360,"name":"Development","parentId":"env_2fb0733ff3f6695909ad7f5614108dc516ce22da","_type":"environment"}]} \ No newline at end of file diff --git a/README.md b/README.md index c77575d..db228cb 100644 --- a/README.md +++ b/README.md @@ -88,7 +88,7 @@ This is to handle external dependencies for 3rd party modules, otherwise we will 2. You will receive a JWT token, use it as a Bearer Token in all the authenticated requests; 3. Please load the `insomnia.json` file into your Insomnia Rest Client and call the routes or consult https://trackcovid19.docs.apiary.io; -> Do not forget to set the Bearer token on insomnia! +> Do not forget to set the Bearer token on insomnia environment and check other variables! ## Serverless Usage diff --git a/controllers/v1/video/index.js b/controllers/v1/video/index.js new file mode 100644 index 0000000..1a10310 --- /dev/null +++ b/controllers/v1/video/index.js @@ -0,0 +1,55 @@ +'use strict' + +module.exports = async (fastify, opts) => { + + fastify.get('/video/all', { + schema: { + tags: ['video'] + } + }, async (request, reply) => { + try { + const videosDB = await fastify.models().Videos.findAll({ + where: { available: true }, + order: [ + ['video_order', 'ASC'] + ], + include: [ + { + model: fastify.models().VideoShares, + where: { available: true }, + order: [ + ['share_order', 'ASC'] + ], + required: false + } + ] + }); + + let videos = []; + if (videosDB) { + videos = videosDB.map(v => { + let o = { + id: v.id, + title: v.title, + description: v.description, + video: v.video, + share: null + }; + if (v.video_shares) { + o.share = o.share || {}; + v.video_shares.forEach(s => { + o.share[s.target] = s.share_link + }); + } + return o; + }) + } + return videos; + } catch (error) { + request.log.error(error) + reply.status(500).send({ + error + }); + } + }) +} \ No newline at end of file diff --git a/db/models/video_shares.js b/db/models/video_shares.js new file mode 100644 index 0000000..607918b --- /dev/null +++ b/db/models/video_shares.js @@ -0,0 +1,39 @@ +/* jshint indent: 1 */ + +module.exports = function(sequelize, DataTypes) { + return sequelize.define('video_shares', { + id: { + type: DataTypes.BIGINT, + allowNull: false, + primaryKey: true, + autoIncrement: true + }, + video_id: { + type: DataTypes.INTEGER, + allowNull: true, + references: { + model: 'videos', + key: 'id' + } + }, + target: { + type: DataTypes.STRING, + allowNull: false + }, + share_link: { + type: DataTypes.STRING, + allowNull: false + }, + share_order: { + type: DataTypes.INTEGER, + allowNull: false + }, + available: { + type: DataTypes.BOOLEAN, + allowNull: false + } + }, { + tableName: 'video_shares', + timestamps: false + }); +}; diff --git a/db/models/videos.js b/db/models/videos.js new file mode 100644 index 0000000..b14fcf2 --- /dev/null +++ b/db/models/videos.js @@ -0,0 +1,35 @@ +/* jshint indent: 1 */ + +module.exports = function(sequelize, DataTypes) { + return sequelize.define('videos', { + id: { + type: DataTypes.INTEGER, + allowNull: false, + primaryKey: true, + autoIncrement: true + }, + title: { + type: DataTypes.STRING, + allowNull: false + }, + description: { + type: DataTypes.STRING, + allowNull: false + }, + video: { + type: DataTypes.STRING, + allowNull: false + }, + video_order: { + type: DataTypes.INTEGER, + allowNull: false + }, + available: { + type: DataTypes.BOOLEAN, + allowNull: false + } + }, { + tableName: 'videos', + timestamps: false + }); +}; diff --git a/db/schema-videos.sql b/db/schema-videos.sql new file mode 100644 index 0000000..3d54d63 --- /dev/null +++ b/db/schema-videos.sql @@ -0,0 +1,102 @@ +-- videos ------------------------------------ + +CREATE SEQUENCE public.videos_id_seq + INCREMENT 1 + START 1 + MINVALUE 1 + MAXVALUE 2147483647 + CACHE 1; + +ALTER SEQUENCE public.videos_id_seq + OWNER TO postgres; + + +CREATE TABLE public.videos +( + id integer NOT NULL DEFAULT nextval('videos_id_seq'::regclass), + title character varying(100) NOT NULL, + description character varying(500) NOT NULL, + video character varying(500) NOT NULL, + video_order integer NOT NULL, + available boolean NOT NULL, + CONSTRAINT videos_pkey PRIMARY KEY (id) +); + +ALTER TABLE public.videos + OWNER to postgres; + +CREATE UNIQUE INDEX videos_id0 + ON public.videos USING btree + (id ASC NULLS LAST); + + +-- video shares ------------------------------------ + +CREATE SEQUENCE public.video_shares_id_seq + INCREMENT 1 + START 1 + MINVALUE 1 + MAXVALUE 2147483647 + CACHE 1; + +ALTER SEQUENCE public.video_shares_id_seq + OWNER TO postgres; + + +CREATE TABLE public.video_shares +( + id integer NOT NULL DEFAULT nextval('video_shares_id_seq'::regclass), + video_id integer NOT NULL, + target character varying(50) NOT NULL, + share_link character varying(500) NOT NULL, + share_order integer NOT NULL, + available boolean NOT NULL, + CONSTRAINT video_shares_pkey PRIMARY KEY (id) +); + +ALTER TABLE public.video_shares + OWNER to postgres; + +CREATE UNIQUE INDEX video_shares_id0 ON public.video_shares USING btree (id); + +CREATE INDEX video_shares_video ON public.video_shares USING btree (video_id); + +ALTER TABLE ONLY public.video_shares + ADD CONSTRAINT video_shares_video_fkey FOREIGN KEY (video_id) REFERENCES public.videos(id); + + +-- dummy data + +INSERT INTO public.videos( + title, description, video, video_order, available) + VALUES ('video 1', 'video 1 desc', 'youtube/ajhsdg', 1, true); + +INSERT INTO public.video_shares( + video_id, target, share_link, share_order, available) + VALUES (1, 'facebook', 'facebook-link', 1, true); + +INSERT INTO public.video_shares( + video_id, target, share_link, share_order, available) + VALUES (1, 'twitter', 'twitter-link', 2, true); + + +INSERT INTO public.videos( + title, description, video, video_order, available) + VALUES ('video 2', 'video 2 desc', 'youtube/wdf3f34f34g34g34g34tg', 2, true); + +INSERT INTO public.video_shares( + video_id, target, share_link, share_order, available) + VALUES (2, 'facebook', 'facebook-link2', 1, true); + +INSERT INTO public.video_shares( + video_id, target, share_link, share_order, available) + VALUES (2, 'twitter', 'twitter-link2-not-available', 2, false); + + +INSERT INTO public.videos( + title, description, video, video_order, available) + VALUES ('video 3', 'video 3 desc', 'youtube/3', 3, true); + +INSERT INTO public.video_shares( + video_id, target, share_link, share_order, available) + VALUES (3, 'facebook', 'facebook-link3', 1, true); \ No newline at end of file diff --git a/plugins/models.js b/plugins/models.js index 657c73a..5fdd88a 100644 --- a/plugins/models.js +++ b/plugins/models.js @@ -11,6 +11,8 @@ module.exports = fp(async (fastify, opts) => { const Condition = fastify.sequelize.import('../db/models/user_status.js'); const StatusByPostalCode = fastify.sequelize.import('../db/models/status_by_postalcode.js'); const ConfinementStateByPostalCode = fastify.sequelize.import('../db/models/confinement_state_by_postalcode.js'); + const VideoShares = fastify.sequelize.import('../db/models/video_shares.js'); + const Videos = fastify.sequelize.import('../db/models/videos.js'); //relationships Case.belongsTo(Users, { foreignKey: 'user_id' }); @@ -23,6 +25,9 @@ module.exports = fp(async (fastify, opts) => { Case.hasMany(UserSymptom, { foreignKey: 'case_id' }); UserSymptom.belongsTo(Case, { foreignKey: 'case_id' }); - return { Case, Network, Users, Symptom, ConfinementState, Condition, StatusByPostalCode, ConfinementStateByPostalCode, UserSymptom } + VideoShares.belongsTo(Videos, { foreignKey: 'video_id' }); + Videos.hasMany(VideoShares, { foreignKey: 'video_id' }); + + return { Case, Network, Users, Symptom, ConfinementState, Condition, StatusByPostalCode, ConfinementStateByPostalCode, UserSymptom, Videos, VideoShares } }) })