diff options
author | vantezzen <hello@vantezzen.io> | 2019-10-18 21:43:42 +0200 |
---|---|---|
committer | vantezzen <hello@vantezzen.io> | 2019-10-18 21:43:42 +0200 |
commit | 1cfff4a4324e130aa7579ea8694438ade686dd55 (patch) | |
tree | 7f50f0142283aa1f1e41084dd8efa243ba91b8c0 /src/server | |
parent | Fix lint (diff) | |
download | ferdium-app-1cfff4a4324e130aa7579ea8694438ade686dd55.tar.gz ferdium-app-1cfff4a4324e130aa7579ea8694438ade686dd55.tar.zst ferdium-app-1cfff4a4324e130aa7579ea8694438ade686dd55.zip |
Move internal server to submodule
Diffstat (limited to 'src/server')
45 files changed, 0 insertions, 2794 deletions
diff --git a/src/server/.editorconfig b/src/server/.editorconfig deleted file mode 100644 index 914223976..000000000 --- a/src/server/.editorconfig +++ /dev/null | |||
@@ -1,13 +0,0 @@ | |||
1 | # editorconfig.org | ||
2 | root = true | ||
3 | |||
4 | [*] | ||
5 | indent_size = 2 | ||
6 | indent_style = space | ||
7 | end_of_line = lf | ||
8 | charset = utf-8 | ||
9 | trim_trailing_whitespace = true | ||
10 | insert_final_newline = true | ||
11 | |||
12 | [*.md] | ||
13 | trim_trailing_whitespace = false | ||
diff --git a/src/server/.eslintrc.js b/src/server/.eslintrc.js deleted file mode 100644 index d02f4890d..000000000 --- a/src/server/.eslintrc.js +++ /dev/null | |||
@@ -1,22 +0,0 @@ | |||
1 | module.exports = { | ||
2 | env: { | ||
3 | commonjs: true, | ||
4 | es6: true, | ||
5 | node: true, | ||
6 | }, | ||
7 | extends: [ | ||
8 | 'airbnb-base', | ||
9 | ], | ||
10 | globals: { | ||
11 | Atomics: 'readonly', | ||
12 | SharedArrayBuffer: 'readonly', | ||
13 | use: 'readonly' | ||
14 | }, | ||
15 | parserOptions: { | ||
16 | ecmaVersion: 2018, | ||
17 | }, | ||
18 | rules: { | ||
19 | "class-methods-use-this": 'off', | ||
20 | "no-restricted-syntax": 'off', | ||
21 | }, | ||
22 | }; | ||
diff --git a/src/server/.gitattributes b/src/server/.gitattributes deleted file mode 100644 index dfe077042..000000000 --- a/src/server/.gitattributes +++ /dev/null | |||
@@ -1,2 +0,0 @@ | |||
1 | # Auto detect text files and perform LF normalization | ||
2 | * text=auto | ||
diff --git a/src/server/.gitignore b/src/server/.gitignore deleted file mode 100644 index d84ffadd4..000000000 --- a/src/server/.gitignore +++ /dev/null | |||
@@ -1,19 +0,0 @@ | |||
1 | # Node modules | ||
2 | node_modules | ||
3 | |||
4 | # Adonis directory for storing tmp files | ||
5 | tmp | ||
6 | |||
7 | # Environment variables, never commit this file | ||
8 | .env | ||
9 | |||
10 | # The development sqlite file | ||
11 | database/development.sqlite | ||
12 | database/adonis.sqlite | ||
13 | |||
14 | # Uploaded recipes | ||
15 | recipes/ | ||
16 | |||
17 | .DS_Store | ||
18 | public/terms.html | ||
19 | public/privacy.html | ||
diff --git a/src/server/README.md b/src/server/README.md deleted file mode 100644 index 0074f2314..000000000 --- a/src/server/README.md +++ /dev/null | |||
@@ -1,17 +0,0 @@ | |||
1 | <p align="center"> | ||
2 | <img src="./logo.png" alt="" width="300"/> | ||
3 | </p> | ||
4 | |||
5 | # ferdi-internal-server | ||
6 | Internal Ferdi Server used for storing settings without logging into an external server. | ||
7 | |||
8 | ## Configuration | ||
9 | franz-server's configuration is saved inside the `env.ini` file. Besides AdonisJS's settings, ferdi-internal-server has the following custom settings: | ||
10 | - `CONNECT_WITH_FRANZ` (`true` or `false`, default: `true`): Whether to enable connections to the Franz server. By enabling this option, ferdi-server can: | ||
11 | - Show the full Franz recipe library instead of only custom recipes | ||
12 | - Import Franz accounts | ||
13 | |||
14 | ## Importing your Franz account | ||
15 | ferdi-server allows you to import your full Franz account, including all its settings. | ||
16 | |||
17 | To import your Franz account, open `http://localhost:45569/import` in your browser and login using your Franz account details. ferdi-server will create a new user with the same credentials and copy your Franz settings, services and workspaces. | ||
diff --git a/src/server/ace b/src/server/ace deleted file mode 100644 index 42f8f10d1..000000000 --- a/src/server/ace +++ /dev/null | |||
@@ -1,21 +0,0 @@ | |||
1 | 'use strict' | ||
2 | |||
3 | /* | ||
4 | |-------------------------------------------------------------------------- | ||
5 | | Ace Commands | ||
6 | |-------------------------------------------------------------------------- | ||
7 | | | ||
8 | | The ace file is just a regular Javascript file but with no extension. You | ||
9 | | can call `node ace` followed by the command name and it just works. | ||
10 | | | ||
11 | | Also you can use `adonis` followed by the command name, since the adonis | ||
12 | | global proxies all the ace commands. | ||
13 | | | ||
14 | */ | ||
15 | |||
16 | const { Ignitor } = require('@adonisjs/ignitor') | ||
17 | |||
18 | new Ignitor(require('@adonisjs/fold')) | ||
19 | .appRoot(__dirname) | ||
20 | .fireAce() | ||
21 | .catch(console.error) | ||
diff --git a/src/server/app/Controllers/Http/RecipeController.js b/src/server/app/Controllers/Http/RecipeController.js deleted file mode 100644 index 71ac12c0f..000000000 --- a/src/server/app/Controllers/Http/RecipeController.js +++ /dev/null | |||
@@ -1,119 +0,0 @@ | |||
1 | |||
2 | const Recipe = use('App/Models/Recipe'); | ||
3 | const Drive = use('Drive'); | ||
4 | const { | ||
5 | validateAll, | ||
6 | } = use('Validator'); | ||
7 | const Env = use('Env'); | ||
8 | |||
9 | const fetch = require('node-fetch'); | ||
10 | |||
11 | class RecipeController { | ||
12 | // List official and custom recipes | ||
13 | async list({ | ||
14 | response, | ||
15 | }) { | ||
16 | const officialRecipes = JSON.parse(await (await fetch('https://api.getferdi.com/v1/recipes')).text()); | ||
17 | const customRecipesArray = (await Recipe.all()).rows; | ||
18 | const customRecipes = customRecipesArray.map(recipe => ({ | ||
19 | id: recipe.recipeId, | ||
20 | name: recipe.name, | ||
21 | ...JSON.parse(recipe.data), | ||
22 | })); | ||
23 | |||
24 | const recipes = [ | ||
25 | ...officialRecipes, | ||
26 | ...customRecipes, | ||
27 | ]; | ||
28 | |||
29 | return response.send(recipes); | ||
30 | } | ||
31 | |||
32 | // Search official and custom recipes | ||
33 | async search({ | ||
34 | request, | ||
35 | response, | ||
36 | }) { | ||
37 | // Validate user input | ||
38 | const validation = await validateAll(request.all(), { | ||
39 | needle: 'required', | ||
40 | }); | ||
41 | if (validation.fails()) { | ||
42 | return response.status(401).send({ | ||
43 | message: 'Please provide a needle', | ||
44 | messages: validation.messages(), | ||
45 | status: 401, | ||
46 | }); | ||
47 | } | ||
48 | |||
49 | const needle = request.input('needle'); | ||
50 | |||
51 | // Get results | ||
52 | let results; | ||
53 | |||
54 | if (needle === 'ferdi:custom') { | ||
55 | const dbResults = (await Recipe.all()).toJSON(); | ||
56 | results = dbResults.map(recipe => ({ | ||
57 | id: recipe.recipeId, | ||
58 | name: recipe.name, | ||
59 | ...JSON.parse(recipe.data), | ||
60 | })); | ||
61 | } else { | ||
62 | let remoteResults = []; | ||
63 | if (Env.get('CONNECT_WITH_FRANZ') == 'true') { // eslint-disable-line eqeqeq | ||
64 | remoteResults = JSON.parse(await (await fetch(`https://api.getferdi.com/v1/recipes/search?needle=${encodeURIComponent(needle)}`)).text()); | ||
65 | } | ||
66 | const localResultsArray = (await Recipe.query().where('name', 'LIKE', `%${needle}%`).fetch()).toJSON(); | ||
67 | const localResults = localResultsArray.map(recipe => ({ | ||
68 | id: recipe.recipeId, | ||
69 | name: recipe.name, | ||
70 | ...JSON.parse(recipe.data), | ||
71 | })); | ||
72 | |||
73 | results = [ | ||
74 | ...localResults, | ||
75 | ...remoteResults || [], | ||
76 | ]; | ||
77 | } | ||
78 | |||
79 | return response.send(results); | ||
80 | } | ||
81 | |||
82 | // Download a recipe | ||
83 | async download({ | ||
84 | response, | ||
85 | params, | ||
86 | }) { | ||
87 | // Validate user input | ||
88 | const validation = await validateAll(params, { | ||
89 | recipe: 'required|accepted', | ||
90 | }); | ||
91 | if (validation.fails()) { | ||
92 | return response.status(401).send({ | ||
93 | message: 'Please provide a recipe ID', | ||
94 | messages: validation.messages(), | ||
95 | status: 401, | ||
96 | }); | ||
97 | } | ||
98 | |||
99 | const service = params.recipe; | ||
100 | |||
101 | // Check for invalid characters | ||
102 | if (/\.{1,}/.test(service) || /\/{1,}/.test(service)) { | ||
103 | return response.send('Invalid recipe name'); | ||
104 | } | ||
105 | |||
106 | // Check if recipe exists in recipes folder | ||
107 | if (await Drive.exists(`${service}.tar.gz`)) { | ||
108 | return response.send(await Drive.get(`${service}.tar.gz`)); | ||
109 | } if (Env.get('CONNECT_WITH_FRANZ') == 'true') { // eslint-disable-line eqeqeq | ||
110 | return response.redirect(`https://api.getferdi.com/v1/recipes/download/${service}`); | ||
111 | } | ||
112 | return response.status(400).send({ | ||
113 | message: 'Recipe not found', | ||
114 | code: 'recipe-not-found', | ||
115 | }); | ||
116 | } | ||
117 | } | ||
118 | |||
119 | module.exports = RecipeController; | ||
diff --git a/src/server/app/Controllers/Http/ServiceController.js b/src/server/app/Controllers/Http/ServiceController.js deleted file mode 100644 index ea7035ca1..000000000 --- a/src/server/app/Controllers/Http/ServiceController.js +++ /dev/null | |||
@@ -1,211 +0,0 @@ | |||
1 | const Service = use('App/Models/Service'); | ||
2 | const { | ||
3 | validateAll, | ||
4 | } = use('Validator'); | ||
5 | |||
6 | const uuid = require('uuid/v4'); | ||
7 | |||
8 | class ServiceController { | ||
9 | // Create a new service for user | ||
10 | async create({ | ||
11 | request, | ||
12 | response, | ||
13 | }) { | ||
14 | // Validate user input | ||
15 | const validation = await validateAll(request.all(), { | ||
16 | name: 'required|string', | ||
17 | recipeId: 'required', | ||
18 | }); | ||
19 | if (validation.fails()) { | ||
20 | return response.status(401).send({ | ||
21 | message: 'Invalid POST arguments', | ||
22 | messages: validation.messages(), | ||
23 | status: 401, | ||
24 | }); | ||
25 | } | ||
26 | |||
27 | const data = request.all(); | ||
28 | |||
29 | // Get new, unused uuid | ||
30 | let serviceId; | ||
31 | do { | ||
32 | serviceId = uuid(); | ||
33 | } while ((await Service.query().where('serviceId', serviceId).fetch()).rows.length > 0); // eslint-disable-line no-await-in-loop | ||
34 | |||
35 | await Service.create({ | ||
36 | serviceId, | ||
37 | name: data.name, | ||
38 | recipeId: data.recipeId, | ||
39 | settings: JSON.stringify(data), | ||
40 | }); | ||
41 | |||
42 | return response.send({ | ||
43 | data: { | ||
44 | userId: 1, | ||
45 | id: serviceId, | ||
46 | isEnabled: true, | ||
47 | isNotificationEnabled: true, | ||
48 | isBadgeEnabled: true, | ||
49 | isMuted: false, | ||
50 | isDarkModeEnabled: '', | ||
51 | spellcheckerLanguage: '', | ||
52 | order: 1, | ||
53 | customRecipe: false, | ||
54 | hasCustomIcon: false, | ||
55 | workspaces: [], | ||
56 | iconUrl: null, | ||
57 | ...data, | ||
58 | }, | ||
59 | status: ['created'], | ||
60 | }); | ||
61 | } | ||
62 | |||
63 | // List all services a user has created | ||
64 | async list({ | ||
65 | response, | ||
66 | }) { | ||
67 | const services = (await Service.all()).rows; | ||
68 | // Convert to array with all data Franz wants | ||
69 | const servicesArray = services.map(service => ({ | ||
70 | customRecipe: false, | ||
71 | hasCustomIcon: false, | ||
72 | isBadgeEnabled: true, | ||
73 | isDarkModeEnabled: '', | ||
74 | isEnabled: true, | ||
75 | isMuted: false, | ||
76 | isNotificationEnabled: true, | ||
77 | order: 1, | ||
78 | spellcheckerLanguage: '', | ||
79 | workspaces: [], | ||
80 | iconUrl: null, | ||
81 | ...JSON.parse(service.settings), | ||
82 | id: service.serviceId, | ||
83 | name: service.name, | ||
84 | recipeId: service.recipeId, | ||
85 | userId: 1, | ||
86 | })); | ||
87 | |||
88 | return response.send(servicesArray); | ||
89 | } | ||
90 | |||
91 | async edit({ | ||
92 | request, | ||
93 | response, | ||
94 | params, | ||
95 | }) { | ||
96 | // Validate user input | ||
97 | const validation = await validateAll(request.all(), { | ||
98 | name: 'required', | ||
99 | }); | ||
100 | if (validation.fails()) { | ||
101 | return response.status(401).send({ | ||
102 | message: 'Invalid POST arguments', | ||
103 | messages: validation.messages(), | ||
104 | status: 401, | ||
105 | }); | ||
106 | } | ||
107 | |||
108 | const data = request.all(); | ||
109 | const { | ||
110 | id, | ||
111 | } = params; | ||
112 | |||
113 | // Get current settings from db | ||
114 | const serviceData = (await Service.query() | ||
115 | .where('serviceId', id).fetch()).rows[0]; | ||
116 | |||
117 | const settings = { | ||
118 | ...JSON.parse(serviceData.settings), | ||
119 | ...data, | ||
120 | }; | ||
121 | |||
122 | // Update data in database | ||
123 | await (Service.query() | ||
124 | .where('serviceId', id)).update({ | ||
125 | name: data.name, | ||
126 | settings: JSON.stringify(settings), | ||
127 | }); | ||
128 | |||
129 | // Get updated row | ||
130 | const service = (await Service.query() | ||
131 | .where('serviceId', id).fetch()).rows[0]; | ||
132 | |||
133 | return response.send({ | ||
134 | id: service.serviceId, | ||
135 | name: data.name, | ||
136 | ...settings, | ||
137 | userId: 1, | ||
138 | }); | ||
139 | } | ||
140 | |||
141 | async reorder({ | ||
142 | request, | ||
143 | response, | ||
144 | }) { | ||
145 | const data = request.all(); | ||
146 | |||
147 | for (const service of Object.keys(data)) { | ||
148 | // Get current settings from db | ||
149 | const serviceData = (await Service.query() // eslint-disable-line no-await-in-loop | ||
150 | .where('serviceId', service).fetch()).rows[0]; | ||
151 | |||
152 | const settings = { | ||
153 | ...JSON.parse(serviceData.settings), | ||
154 | order: data[service], | ||
155 | }; | ||
156 | |||
157 | // Update data in database | ||
158 | await (Service.query() // eslint-disable-line no-await-in-loop | ||
159 | .where('serviceId', service)) | ||
160 | .update({ | ||
161 | settings: JSON.stringify(settings), | ||
162 | }); | ||
163 | } | ||
164 | |||
165 | // Get new services | ||
166 | const services = (await Service.all()).rows; | ||
167 | // Convert to array with all data Franz wants | ||
168 | const servicesArray = services.map(service => ({ | ||
169 | customRecipe: false, | ||
170 | hasCustomIcon: false, | ||
171 | isBadgeEnabled: true, | ||
172 | isDarkModeEnabled: '', | ||
173 | isEnabled: true, | ||
174 | isMuted: false, | ||
175 | isNotificationEnabled: true, | ||
176 | order: 1, | ||
177 | spellcheckerLanguage: '', | ||
178 | workspaces: [], | ||
179 | iconUrl: null, | ||
180 | ...JSON.parse(service.settings), | ||
181 | id: service.serviceId, | ||
182 | name: service.name, | ||
183 | recipeId: service.recipeId, | ||
184 | userId: 1, | ||
185 | })); | ||
186 | |||
187 | return response.send(servicesArray); | ||
188 | } | ||
189 | |||
190 | update({ | ||
191 | response, | ||
192 | }) { | ||
193 | return response.send([]); | ||
194 | } | ||
195 | |||
196 | async delete({ | ||
197 | params, | ||
198 | response, | ||
199 | }) { | ||
200 | // Update data in database | ||
201 | await (Service.query() | ||
202 | .where('serviceId', params.id)).delete(); | ||
203 | |||
204 | return response.send({ | ||
205 | message: 'Sucessfully deleted service', | ||
206 | status: 200, | ||
207 | }); | ||
208 | } | ||
209 | } | ||
210 | |||
211 | module.exports = ServiceController; | ||
diff --git a/src/server/app/Controllers/Http/StaticController.js b/src/server/app/Controllers/Http/StaticController.js deleted file mode 100644 index b16e6cb6d..000000000 --- a/src/server/app/Controllers/Http/StaticController.js +++ /dev/null | |||
@@ -1,224 +0,0 @@ | |||
1 | |||
2 | /** | ||
3 | * Controller for routes with static responses | ||
4 | */ | ||
5 | |||
6 | class StaticController { | ||
7 | // Enable all features | ||
8 | features({ | ||
9 | response, | ||
10 | }) { | ||
11 | return response.send({ | ||
12 | needToWaitToProceed: false, | ||
13 | isSpellcheckerPremiumFeature: true, | ||
14 | isServiceProxyEnabled: true, | ||
15 | isServiceProxyPremiumFeature: true, | ||
16 | isWorkspacePremiumFeature: true, | ||
17 | isWorkspaceEnabled: true, | ||
18 | isAnnouncementsEnabled: true, | ||
19 | isSettingsWSEnabled: false, | ||
20 | isServiceLimitEnabled: false, | ||
21 | serviceLimitCount: 0, | ||
22 | isCommunityRecipesPremiumFeature: false, | ||
23 | }); | ||
24 | } | ||
25 | |||
26 | // Return an empty array | ||
27 | emptyArray({ | ||
28 | response, | ||
29 | }) { | ||
30 | return response.send([]); | ||
31 | } | ||
32 | |||
33 | // Payment plans availible | ||
34 | plans({ | ||
35 | response, | ||
36 | }) { | ||
37 | return response.send({ | ||
38 | month: { | ||
39 | id: 'franz-supporter-license', | ||
40 | price: 99, | ||
41 | }, | ||
42 | year: { | ||
43 | id: 'franz-supporter-license-year-2019', | ||
44 | price: 99, | ||
45 | }, | ||
46 | }); | ||
47 | } | ||
48 | |||
49 | // Return list of popular recipes (copy of the response Franz's API is returning) | ||
50 | popularRecipes({ | ||
51 | response, | ||
52 | }) { | ||
53 | return response.send([{ | ||
54 | author: 'Stefan Malzner <stefan@adlk.io>', | ||
55 | featured: false, | ||
56 | id: 'slack', | ||
57 | name: 'Slack', | ||
58 | version: '1.0.4', | ||
59 | icons: { | ||
60 | png: 'https://cdn.franzinfra.com/recipes/dist/slack/src/icon.png', | ||
61 | svg: 'https://cdn.franzinfra.com/recipes/dist/slack/src/icon.svg', | ||
62 | }, | ||
63 | }, { | ||
64 | author: 'Stefan Malzner <stefan@adlk.io>', | ||
65 | featured: false, | ||
66 | id: 'whatsapp', | ||
67 | name: 'WhatsApp', | ||
68 | version: '1.0.1', | ||
69 | icons: { | ||
70 | png: 'https://cdn.franzinfra.com/recipes/dist/whatsapp/src/icon.png', | ||
71 | svg: 'https://cdn.franzinfra.com/recipes/dist/whatsapp/src/icon.svg', | ||
72 | }, | ||
73 | }, { | ||
74 | author: 'Stefan Malzner <stefan@adlk.io>', | ||
75 | featured: false, | ||
76 | id: 'messenger', | ||
77 | name: 'Messenger', | ||
78 | version: '1.0.6', | ||
79 | icons: { | ||
80 | png: 'https://cdn.franzinfra.com/recipes/dist/messenger/src/icon.png', | ||
81 | svg: 'https://cdn.franzinfra.com/recipes/dist/messenger/src/icon.svg', | ||
82 | }, | ||
83 | }, { | ||
84 | author: 'Stefan Malzner <stefan@adlk.io>', | ||
85 | featured: false, | ||
86 | id: 'telegram', | ||
87 | name: 'Telegram', | ||
88 | version: '1.0.0', | ||
89 | icons: { | ||
90 | png: 'https://cdn.franzinfra.com/recipes/dist/telegram/src/icon.png', | ||
91 | svg: 'https://cdn.franzinfra.com/recipes/dist/telegram/src/icon.svg', | ||
92 | }, | ||
93 | }, { | ||
94 | author: 'Stefan Malzner <stefan@adlk.io>', | ||
95 | featured: false, | ||
96 | id: 'gmail', | ||
97 | name: 'Gmail', | ||
98 | version: '1.0.0', | ||
99 | icons: { | ||
100 | png: 'https://cdn.franzinfra.com/recipes/dist/gmail/src/icon.png', | ||
101 | svg: 'https://cdn.franzinfra.com/recipes/dist/gmail/src/icon.svg', | ||
102 | }, | ||
103 | }, { | ||
104 | author: 'Stefan Malzner <stefan@adlk.io>', | ||
105 | featured: false, | ||
106 | id: 'skype', | ||
107 | name: 'Skype', | ||
108 | version: '1.0.0', | ||
109 | icons: { | ||
110 | png: 'https://cdn.franzinfra.com/recipes/dist/skype/src/icon.png', | ||
111 | svg: 'https://cdn.franzinfra.com/recipes/dist/skype/src/icon.svg', | ||
112 | }, | ||
113 | }, { | ||
114 | author: 'Stefan Malzner <stefan@adlk.io>', | ||
115 | featured: false, | ||
116 | id: 'hangouts', | ||
117 | name: 'Hangouts', | ||
118 | version: '1.0.0', | ||
119 | icons: { | ||
120 | png: 'https://cdn.franzinfra.com/recipes/dist/hangouts/src/icon.png', | ||
121 | svg: 'https://cdn.franzinfra.com/recipes/dist/hangouts/src/icon.svg', | ||
122 | }, | ||
123 | }, { | ||
124 | author: 'Stefan Malzner <stefan@adlk.io>', | ||
125 | featured: false, | ||
126 | id: 'discord', | ||
127 | name: 'Discord', | ||
128 | version: '1.0.0', | ||
129 | icons: { | ||
130 | png: 'https://cdn.franzinfra.com/recipes/dist/discord/src/icon.png', | ||
131 | svg: 'https://cdn.franzinfra.com/recipes/dist/discord/src/icon.svg', | ||
132 | }, | ||
133 | }, { | ||
134 | author: 'Stefan Malzner <stefan@adlk.io>', | ||
135 | featured: false, | ||
136 | id: 'tweetdeck', | ||
137 | name: 'Tweetdeck', | ||
138 | version: '1.0.1', | ||
139 | icons: { | ||
140 | png: 'https://cdn.franzinfra.com/recipes/dist/tweetdeck/src/icon.png', | ||
141 | svg: 'https://cdn.franzinfra.com/recipes/dist/tweetdeck/src/icon.svg', | ||
142 | }, | ||
143 | }, { | ||
144 | author: 'Stefan Malzner <stefan@adlk.io>', | ||
145 | featured: false, | ||
146 | id: 'hipchat', | ||
147 | name: 'HipChat', | ||
148 | version: '1.0.1', | ||
149 | icons: { | ||
150 | png: 'https://cdn.franzinfra.com/recipes/dist/hipchat/src/icon.png', | ||
151 | svg: 'https://cdn.franzinfra.com/recipes/dist/hipchat/src/icon.svg', | ||
152 | }, | ||
153 | }, { | ||
154 | author: 'Stefan Malzner <stefan@adlk.io>', | ||
155 | featured: false, | ||
156 | id: 'gmailinbox', | ||
157 | name: 'Inbox by Gmail', | ||
158 | version: '1.0.0', | ||
159 | icons: { | ||
160 | png: 'https://cdn.franzinfra.com/recipes/dist/gmailinbox/src/icon.png', | ||
161 | svg: 'https://cdn.franzinfra.com/recipes/dist/gmailinbox/src/icon.svg', | ||
162 | }, | ||
163 | }, { | ||
164 | author: 'Stefan Malzner <stefan@adlk.io>', | ||
165 | featured: false, | ||
166 | id: 'rocketchat', | ||
167 | name: 'Rocket.Chat', | ||
168 | version: '1.0.1', | ||
169 | icons: { | ||
170 | png: 'https://cdn.franzinfra.com/recipes/dist/rocketchat/src/icon.png', | ||
171 | svg: 'https://cdn.franzinfra.com/recipes/dist/rocketchat/src/icon.svg', | ||
172 | }, | ||
173 | }, { | ||
174 | author: 'Brian Gilbert <brian@briangilbert.net>', | ||
175 | featured: false, | ||
176 | id: 'gitter', | ||
177 | name: 'Gitter', | ||
178 | version: '1.0.0', | ||
179 | icons: { | ||
180 | png: 'https://cdn.franzinfra.com/recipes/dist/gitter/src/icon.png', | ||
181 | svg: 'https://cdn.franzinfra.com/recipes/dist/gitter/src/icon.svg', | ||
182 | }, | ||
183 | }, { | ||
184 | author: 'Stefan Malzner <stefan@adlk.io>', | ||
185 | featured: false, | ||
186 | id: 'mattermost', | ||
187 | name: 'Mattermost', | ||
188 | version: '1.0.0', | ||
189 | icons: { | ||
190 | png: 'https://cdn.franzinfra.com/recipes/dist/mattermost/src/icon.png', | ||
191 | svg: 'https://cdn.franzinfra.com/recipes/dist/mattermost/src/icon.svg', | ||
192 | }, | ||
193 | }, { | ||
194 | author: 'Franz <recipe@meetfranz.com>', | ||
195 | featured: false, | ||
196 | id: 'toggl', | ||
197 | name: 'toggl', | ||
198 | version: '1.0.0', | ||
199 | icons: { | ||
200 | png: 'https://cdn.franzinfra.com/recipes/dist/toggl/src/icon.png', | ||
201 | svg: 'https://cdn.franzinfra.com/recipes/dist/toggl/src/icon.svg', | ||
202 | }, | ||
203 | }, { | ||
204 | author: 'Stuart Clark <stuart@realityloop.com>', | ||
205 | featured: false, | ||
206 | id: 'twist', | ||
207 | name: 'twist', | ||
208 | version: '1.0.0', | ||
209 | icons: { | ||
210 | png: 'https://cdn.franzinfra.com/recipes/dist/twist/src/icon.png', | ||
211 | svg: 'https://cdn.franzinfra.com/recipes/dist/twist/src/icon.svg', | ||
212 | }, | ||
213 | }]); | ||
214 | } | ||
215 | |||
216 | // Show announcements | ||
217 | announcement({ | ||
218 | response, | ||
219 | }) { | ||
220 | return response.send('No announcement found.'); | ||
221 | } | ||
222 | } | ||
223 | |||
224 | module.exports = StaticController; | ||
diff --git a/src/server/app/Controllers/Http/UserController.js b/src/server/app/Controllers/Http/UserController.js deleted file mode 100644 index 07e118afd..000000000 --- a/src/server/app/Controllers/Http/UserController.js +++ /dev/null | |||
@@ -1,228 +0,0 @@ | |||
1 | const Service = use('App/Models/Service'); | ||
2 | const Workspace = use('App/Models/Workspace'); | ||
3 | const { | ||
4 | validateAll, | ||
5 | } = use('Validator'); | ||
6 | |||
7 | const btoa = require('btoa'); | ||
8 | const fetch = require('node-fetch'); | ||
9 | const uuid = require('uuid/v4'); | ||
10 | const crypto = require('crypto'); | ||
11 | |||
12 | const apiRequest = (url, route, method, auth) => new Promise((resolve, reject) => { | ||
13 | const base = `${url}/v1/`; | ||
14 | const user = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Ferdi/5.3.0-beta.1 Chrome/69.0.3497.128 Electron/4.2.4 Safari/537.36'; | ||
15 | |||
16 | try { | ||
17 | fetch(base + route, { | ||
18 | method, | ||
19 | headers: { | ||
20 | Authorization: `Bearer ${auth}`, | ||
21 | 'User-Agent': user, | ||
22 | }, | ||
23 | }) | ||
24 | .then(data => data.json()) | ||
25 | .then(json => resolve(json)); | ||
26 | } catch (e) { | ||
27 | reject(); | ||
28 | } | ||
29 | }); | ||
30 | |||
31 | class UserController { | ||
32 | // Register a new user | ||
33 | async signup({ | ||
34 | request, | ||
35 | response, | ||
36 | }) { | ||
37 | // Validate user input | ||
38 | const validation = await validateAll(request.all(), { | ||
39 | firstname: 'required', | ||
40 | email: 'required|email', | ||
41 | password: 'required', | ||
42 | }); | ||
43 | if (validation.fails()) { | ||
44 | return response.status(401).send({ | ||
45 | message: 'Invalid POST arguments', | ||
46 | messages: validation.messages(), | ||
47 | status: 401, | ||
48 | }); | ||
49 | } | ||
50 | |||
51 | return response.send({ | ||
52 | message: 'Successfully created account', | ||
53 | token: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJGZXJkaSBJbnRlcm5hbCBTZXJ2ZXIiLCJpYXQiOjE1NzEwNDAyMTUsImV4cCI6MjUzMzk1NDE3ODQ0LCJhdWQiOiJnZXRmZXJkaS5jb20iLCJzdWIiOiJmZXJkaUBsb2NhbGhvc3QiLCJ1c2VySWQiOiIxIn0.9_TWFGp6HROv8Yg82Rt6i1-95jqWym40a-HmgrdMC6M', | ||
54 | }); | ||
55 | } | ||
56 | |||
57 | // Login using an existing user | ||
58 | async login({ | ||
59 | request, | ||
60 | response, | ||
61 | }) { | ||
62 | if (!request.header('Authorization')) { | ||
63 | return response.status(401).send({ | ||
64 | message: 'Please provide authorization', | ||
65 | status: 401, | ||
66 | }); | ||
67 | } | ||
68 | |||
69 | return response.send({ | ||
70 | message: 'Successfully logged in', | ||
71 | token: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJGZXJkaSBJbnRlcm5hbCBTZXJ2ZXIiLCJpYXQiOjE1NzEwNDAyMTUsImV4cCI6MjUzMzk1NDE3ODQ0LCJhdWQiOiJnZXRmZXJkaS5jb20iLCJzdWIiOiJmZXJkaUBsb2NhbGhvc3QiLCJ1c2VySWQiOiIxIn0.9_TWFGp6HROv8Yg82Rt6i1-95jqWym40a-HmgrdMC6M', | ||
72 | }); | ||
73 | } | ||
74 | |||
75 | // Return information about the current user | ||
76 | async me({ | ||
77 | response, | ||
78 | }) { | ||
79 | return response.send({ | ||
80 | accountType: 'individual', | ||
81 | beta: false, | ||
82 | donor: {}, | ||
83 | email: '', | ||
84 | emailValidated: true, | ||
85 | features: {}, | ||
86 | firstname: 'Ferdi', | ||
87 | id: '82c1cf9d-ab58-4da2-b55e-aaa41d2142d8', | ||
88 | isPremium: true, | ||
89 | isSubscriptionOwner: true, | ||
90 | lastname: 'Application', | ||
91 | locale: 'en-US', | ||
92 | }); | ||
93 | } | ||
94 | |||
95 | |||
96 | async import({ | ||
97 | request, | ||
98 | response, | ||
99 | }) { | ||
100 | // Validate user input | ||
101 | const validation = await validateAll(request.all(), { | ||
102 | email: 'required|email', | ||
103 | password: 'required', | ||
104 | server: 'required', | ||
105 | }); | ||
106 | if (validation.fails()) { | ||
107 | let errorMessage = 'There was an error while trying to import your account:\n'; | ||
108 | for (const message of validation.messages()) { | ||
109 | if (message.validation === 'required') { | ||
110 | errorMessage += `- Please make sure to supply your ${message.field}\n`; | ||
111 | } else if (message.validation === 'unique') { | ||
112 | errorMessage += '- There is already a user with this email.\n'; | ||
113 | } else { | ||
114 | errorMessage += `${message.message}\n`; | ||
115 | } | ||
116 | } | ||
117 | return response.status(401).send(errorMessage); | ||
118 | } | ||
119 | |||
120 | const { | ||
121 | email, | ||
122 | password, | ||
123 | server, | ||
124 | } = request.all(); | ||
125 | |||
126 | const hashedPassword = crypto.createHash('sha256').update(password).digest('base64'); | ||
127 | |||
128 | const base = `${server}/v1/`; | ||
129 | const userAgent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Ferdi/5.3.0-beta.1 Chrome/69.0.3497.128 Electron/4.2.4 Safari/537.36'; | ||
130 | |||
131 | // Try to get an authentication token | ||
132 | let token; | ||
133 | try { | ||
134 | const basicToken = btoa(`${email}:${hashedPassword}`); | ||
135 | |||
136 | const rawResponse = await fetch(`${base}auth/login`, { | ||
137 | method: 'POST', | ||
138 | headers: { | ||
139 | Authorization: `Basic ${basicToken}`, | ||
140 | 'User-Agent': userAgent, | ||
141 | }, | ||
142 | }); | ||
143 | const content = await rawResponse.json(); | ||
144 | |||
145 | if (!content.message || content.message !== 'Successfully logged in') { | ||
146 | const errorMessage = 'Could not login into Franz with your supplied credentials. Please check and try again'; | ||
147 | return response.status(401).send(errorMessage); | ||
148 | } | ||
149 | |||
150 | // eslint-disable-next-line prefer-destructuring | ||
151 | token = content.token; | ||
152 | } catch (e) { | ||
153 | return response.status(401).send({ | ||
154 | message: 'Cannot login to Franz', | ||
155 | error: e, | ||
156 | }); | ||
157 | } | ||
158 | |||
159 | // Get user information | ||
160 | let userInf = false; | ||
161 | try { | ||
162 | userInf = await apiRequest(server, 'me', 'GET', token); | ||
163 | } catch (e) { | ||
164 | const errorMessage = `Could not get your user info from Franz. Please check your credentials or try again later.\nError: ${e}`; | ||
165 | return response.status(401).send(errorMessage); | ||
166 | } | ||
167 | if (!userInf) { | ||
168 | const errorMessage = 'Could not get your user info from Franz. Please check your credentials or try again later'; | ||
169 | return response.status(401).send(errorMessage); | ||
170 | } | ||
171 | |||
172 | const serviceIdTranslation = {}; | ||
173 | |||
174 | // Import services | ||
175 | try { | ||
176 | const services = await apiRequest(server, 'me/services', 'GET', token); | ||
177 | |||
178 | for (const service of services) { | ||
179 | // Get new, unused uuid | ||
180 | let serviceId; | ||
181 | do { | ||
182 | serviceId = uuid(); | ||
183 | } while ((await Service.query().where('serviceId', serviceId).fetch()).rows.length > 0); // eslint-disable-line no-await-in-loop | ||
184 | |||
185 | await Service.create({ // eslint-disable-line no-await-in-loop | ||
186 | serviceId, | ||
187 | name: service.name, | ||
188 | recipeId: service.recipeId, | ||
189 | settings: JSON.stringify(service), | ||
190 | }); | ||
191 | |||
192 | serviceIdTranslation[service.id] = serviceId; | ||
193 | } | ||
194 | } catch (e) { | ||
195 | const errorMessage = `Could not import your services into our system.\nError: ${e}`; | ||
196 | return response.status(401).send(errorMessage); | ||
197 | } | ||
198 | |||
199 | // Import workspaces | ||
200 | try { | ||
201 | const workspaces = await apiRequest(server, 'workspace', 'GET', token); | ||
202 | |||
203 | for (const workspace of workspaces) { | ||
204 | let workspaceId; | ||
205 | do { | ||
206 | workspaceId = uuid(); | ||
207 | } while ((await Workspace.query().where('workspaceId', workspaceId).fetch()).rows.length > 0); // eslint-disable-line no-await-in-loop | ||
208 | |||
209 | const services = workspace.services.map(service => serviceIdTranslation[service]); | ||
210 | |||
211 | await Workspace.create({ // eslint-disable-line no-await-in-loop | ||
212 | workspaceId, | ||
213 | name: workspace.name, | ||
214 | order: workspace.order, | ||
215 | services: JSON.stringify(services), | ||
216 | data: JSON.stringify({}), | ||
217 | }); | ||
218 | } | ||
219 | } catch (e) { | ||
220 | const errorMessage = `Could not import your workspaces into our system.\nError: ${e}`; | ||
221 | return response.status(401).send(errorMessage); | ||
222 | } | ||
223 | |||
224 | return response.send('Your account has been imported. You can now use your Franz account in Ferdi.'); | ||
225 | } | ||
226 | } | ||
227 | |||
228 | module.exports = UserController; | ||
diff --git a/src/server/app/Controllers/Http/WorkspaceController.js b/src/server/app/Controllers/Http/WorkspaceController.js deleted file mode 100644 index 7990b8434..000000000 --- a/src/server/app/Controllers/Http/WorkspaceController.js +++ /dev/null | |||
@@ -1,148 +0,0 @@ | |||
1 | const Workspace = use('App/Models/Workspace'); | ||
2 | const { | ||
3 | validateAll, | ||
4 | } = use('Validator'); | ||
5 | |||
6 | const uuid = require('uuid/v4'); | ||
7 | |||
8 | class WorkspaceController { | ||
9 | // Create a new workspace for user | ||
10 | async create({ | ||
11 | request, | ||
12 | response, | ||
13 | }) { | ||
14 | // Validate user input | ||
15 | const validation = await validateAll(request.all(), { | ||
16 | name: 'required|alpha', | ||
17 | }); | ||
18 | if (validation.fails()) { | ||
19 | return response.status(401).send({ | ||
20 | message: 'Invalid POST arguments', | ||
21 | messages: validation.messages(), | ||
22 | status: 401, | ||
23 | }); | ||
24 | } | ||
25 | |||
26 | const data = request.all(); | ||
27 | |||
28 | // Get new, unused uuid | ||
29 | let workspaceId; | ||
30 | do { | ||
31 | workspaceId = uuid(); | ||
32 | } while ((await Workspace.query().where('workspaceId', workspaceId).fetch()).rows.length > 0); // eslint-disable-line no-await-in-loop | ||
33 | |||
34 | const order = (await Workspace.all()).rows.length; | ||
35 | |||
36 | await Workspace.create({ | ||
37 | workspaceId, | ||
38 | name: data.name, | ||
39 | order, | ||
40 | services: JSON.stringify([]), | ||
41 | data: JSON.stringify(data), | ||
42 | }); | ||
43 | |||
44 | return response.send({ | ||
45 | userId: 1, | ||
46 | name: data.name, | ||
47 | id: workspaceId, | ||
48 | order, | ||
49 | workspaces: [], | ||
50 | }); | ||
51 | } | ||
52 | |||
53 | async edit({ | ||
54 | request, | ||
55 | response, | ||
56 | params, | ||
57 | }) { | ||
58 | // Validate user input | ||
59 | const validation = await validateAll(request.all(), { | ||
60 | name: 'required|alpha', | ||
61 | services: 'required|array', | ||
62 | }); | ||
63 | if (validation.fails()) { | ||
64 | return response.status(401).send({ | ||
65 | message: 'Invalid POST arguments', | ||
66 | messages: validation.messages(), | ||
67 | status: 401, | ||
68 | }); | ||
69 | } | ||
70 | |||
71 | const data = request.all(); | ||
72 | const { | ||
73 | id, | ||
74 | } = params; | ||
75 | |||
76 | // Update data in database | ||
77 | await (Workspace.query() | ||
78 | .where('workspaceId', id)).update({ | ||
79 | name: data.name, | ||
80 | services: JSON.stringify(data.services), | ||
81 | }); | ||
82 | |||
83 | // Get updated row | ||
84 | const workspace = (await Workspace.query() | ||
85 | .where('workspaceId', id).fetch()).rows[0]; | ||
86 | |||
87 | return response.send({ | ||
88 | id: workspace.workspaceId, | ||
89 | name: data.name, | ||
90 | order: workspace.order, | ||
91 | services: data.services, | ||
92 | userId: 1, | ||
93 | }); | ||
94 | } | ||
95 | |||
96 | async delete({ | ||
97 | request, | ||
98 | response, | ||
99 | params, | ||
100 | }) { | ||
101 | // Validate user input | ||
102 | const validation = await validateAll(request.all(), { | ||
103 | id: 'required', | ||
104 | }); | ||
105 | if (validation.fails()) { | ||
106 | return response.status(401).send({ | ||
107 | message: 'Invalid POST arguments', | ||
108 | messages: validation.messages(), | ||
109 | status: 401, | ||
110 | }); | ||
111 | } | ||
112 | |||
113 | const { | ||
114 | id, | ||
115 | } = params; | ||
116 | |||
117 | // Update data in database | ||
118 | await (Workspace.query() | ||
119 | .where('workspaceId', id)).delete(); | ||
120 | |||
121 | return response.send({ | ||
122 | message: 'Successfully deleted workspace', | ||
123 | }); | ||
124 | } | ||
125 | |||
126 | // List all workspaces a user has created | ||
127 | async list({ | ||
128 | response, | ||
129 | }) { | ||
130 | const workspaces = (await Workspace.all()).rows; | ||
131 | // Convert to array with all data Franz wants | ||
132 | let workspacesArray = []; | ||
133 | if (workspaces) { | ||
134 | workspacesArray = workspaces.map(workspace => ({ | ||
135 | id: workspace.workspaceId, | ||
136 | name: workspace.name, | ||
137 | order: workspace.order, | ||
138 | services: JSON.parse(workspace.services), | ||
139 | userId: 1, | ||
140 | })); | ||
141 | } | ||
142 | |||
143 | |||
144 | return response.send(workspacesArray); | ||
145 | } | ||
146 | } | ||
147 | |||
148 | module.exports = WorkspaceController; | ||
diff --git a/src/server/app/Exceptions/Handler.js b/src/server/app/Exceptions/Handler.js deleted file mode 100644 index e8d2d2ee2..000000000 --- a/src/server/app/Exceptions/Handler.js +++ /dev/null | |||
@@ -1,45 +0,0 @@ | |||
1 | |||
2 | const BaseExceptionHandler = use('BaseExceptionHandler'); | ||
3 | |||
4 | /** | ||
5 | * This class handles all exceptions thrown during | ||
6 | * the HTTP request lifecycle. | ||
7 | * | ||
8 | * @class ExceptionHandler | ||
9 | */ | ||
10 | class ExceptionHandler extends BaseExceptionHandler { | ||
11 | /** | ||
12 | * Handle exception thrown during the HTTP lifecycle | ||
13 | * | ||
14 | * @method handle | ||
15 | * | ||
16 | * @param {Object} error | ||
17 | * @param {Object} options.request | ||
18 | * @param {Object} options.response | ||
19 | * | ||
20 | * @return {void} | ||
21 | */ | ||
22 | async handle(error, { response }) { | ||
23 | if (error.name === 'ValidationException') { | ||
24 | return response.status(400).send('Invalid arguments'); | ||
25 | } | ||
26 | |||
27 | return response.status(error.status).send(error.message); | ||
28 | } | ||
29 | |||
30 | /** | ||
31 | * Report exception for logging or debugging. | ||
32 | * | ||
33 | * @method report | ||
34 | * | ||
35 | * @param {Object} error | ||
36 | * @param {Object} options.request | ||
37 | * | ||
38 | * @return {void} | ||
39 | */ | ||
40 | async report() { | ||
41 | return true; | ||
42 | } | ||
43 | } | ||
44 | |||
45 | module.exports = ExceptionHandler; | ||
diff --git a/src/server/app/Middleware/ConvertEmptyStringsToNull.js b/src/server/app/Middleware/ConvertEmptyStringsToNull.js deleted file mode 100644 index bc3079a7f..000000000 --- a/src/server/app/Middleware/ConvertEmptyStringsToNull.js +++ /dev/null | |||
@@ -1,16 +0,0 @@ | |||
1 | |||
2 | class ConvertEmptyStringsToNull { | ||
3 | async handle({ request }, next) { | ||
4 | if (Object.keys(request.body).length) { | ||
5 | request.body = Object.assign( | ||
6 | ...Object.keys(request.body).map(key => ({ | ||
7 | [key]: request.body[key] !== '' ? request.body[key] : null, | ||
8 | })), | ||
9 | ); | ||
10 | } | ||
11 | |||
12 | await next(); | ||
13 | } | ||
14 | } | ||
15 | |||
16 | module.exports = ConvertEmptyStringsToNull; | ||
diff --git a/src/server/app/Models/Recipe.js b/src/server/app/Models/Recipe.js deleted file mode 100644 index da3618bf7..000000000 --- a/src/server/app/Models/Recipe.js +++ /dev/null | |||
@@ -1,8 +0,0 @@ | |||
1 | |||
2 | /** @type {typeof import('@adonisjs/lucid/src/Lucid/Model')} */ | ||
3 | const Model = use('Model'); | ||
4 | |||
5 | class Recipe extends Model { | ||
6 | } | ||
7 | |||
8 | module.exports = Recipe; | ||
diff --git a/src/server/app/Models/Service.js b/src/server/app/Models/Service.js deleted file mode 100644 index 20679feb1..000000000 --- a/src/server/app/Models/Service.js +++ /dev/null | |||
@@ -1,8 +0,0 @@ | |||
1 | |||
2 | /** @type {typeof import('@adonisjs/lucid/src/Lucid/Model')} */ | ||
3 | const Model = use('Model'); | ||
4 | |||
5 | class Service extends Model { | ||
6 | } | ||
7 | |||
8 | module.exports = Service; | ||
diff --git a/src/server/app/Models/Token.js b/src/server/app/Models/Token.js deleted file mode 100644 index f6bec0852..000000000 --- a/src/server/app/Models/Token.js +++ /dev/null | |||
@@ -1,8 +0,0 @@ | |||
1 | |||
2 | /** @type {typeof import('@adonisjs/lucid/src/Lucid/Model')} */ | ||
3 | const Model = use('Model'); | ||
4 | |||
5 | class Token extends Model { | ||
6 | } | ||
7 | |||
8 | module.exports = Token; | ||
diff --git a/src/server/app/Models/Traits/NoTimestamp.js b/src/server/app/Models/Traits/NoTimestamp.js deleted file mode 100644 index c647428b3..000000000 --- a/src/server/app/Models/Traits/NoTimestamp.js +++ /dev/null | |||
@@ -1,15 +0,0 @@ | |||
1 | |||
2 | class NoTimestamp { | ||
3 | register(Model) { | ||
4 | Object.defineProperties(Model, { | ||
5 | createdAtColumn: { | ||
6 | get: () => null, | ||
7 | }, | ||
8 | updatedAtColumn: { | ||
9 | get: () => null, | ||
10 | }, | ||
11 | }); | ||
12 | } | ||
13 | } | ||
14 | |||
15 | module.exports = NoTimestamp; | ||
diff --git a/src/server/app/Models/User.js b/src/server/app/Models/User.js deleted file mode 100644 index 907710d8d..000000000 --- a/src/server/app/Models/User.js +++ /dev/null | |||
@@ -1,8 +0,0 @@ | |||
1 | // File is required by AdonisJS but not used by the server | ||
2 | /** @type {typeof import('@adonisjs/lucid/src/Lucid/Model')} */ | ||
3 | const Model = use('Model'); | ||
4 | |||
5 | class User extends Model { | ||
6 | } | ||
7 | |||
8 | module.exports = User; | ||
diff --git a/src/server/app/Models/Workspace.js b/src/server/app/Models/Workspace.js deleted file mode 100644 index 3b73cbf33..000000000 --- a/src/server/app/Models/Workspace.js +++ /dev/null | |||
@@ -1,8 +0,0 @@ | |||
1 | |||
2 | /** @type {typeof import('@adonisjs/lucid/src/Lucid/Model')} */ | ||
3 | const Model = use('Model'); | ||
4 | |||
5 | class Workspace extends Model { | ||
6 | } | ||
7 | |||
8 | module.exports = Workspace; | ||
diff --git a/src/server/config/app.js b/src/server/config/app.js deleted file mode 100644 index 7938b81df..000000000 --- a/src/server/config/app.js +++ /dev/null | |||
@@ -1,242 +0,0 @@ | |||
1 | |||
2 | /** @type {import('@adonisjs/framework/src/Env')} */ | ||
3 | const Env = use('Env'); | ||
4 | |||
5 | module.exports = { | ||
6 | |||
7 | /* | ||
8 | |-------------------------------------------------------------------------- | ||
9 | | Application Name | ||
10 | |-------------------------------------------------------------------------- | ||
11 | | | ||
12 | | This value is the name of your application and can used when you | ||
13 | | need to place the application's name in a email, view or | ||
14 | | other location. | ||
15 | | | ||
16 | */ | ||
17 | |||
18 | name: Env.get('APP_NAME', 'Ferdi Internal Server'), | ||
19 | |||
20 | /* | ||
21 | |-------------------------------------------------------------------------- | ||
22 | | App Key | ||
23 | |-------------------------------------------------------------------------- | ||
24 | | | ||
25 | | App key is a randomly generated 16 or 32 characters long string required | ||
26 | | to encrypt cookies, sessions and other sensitive data. | ||
27 | | | ||
28 | */ | ||
29 | appKey: Env.getOrFail('APP_KEY'), | ||
30 | |||
31 | http: { | ||
32 | /* | ||
33 | |-------------------------------------------------------------------------- | ||
34 | | Allow Method Spoofing | ||
35 | |-------------------------------------------------------------------------- | ||
36 | | | ||
37 | | Method spoofing allows to make requests by spoofing the http verb. | ||
38 | | Which means you can make a GET request but instruct the server to | ||
39 | | treat as a POST or PUT request. If you want this feature, set the | ||
40 | | below value to true. | ||
41 | | | ||
42 | */ | ||
43 | allowMethodSpoofing: true, | ||
44 | |||
45 | /* | ||
46 | |-------------------------------------------------------------------------- | ||
47 | | Trust Proxy | ||
48 | |-------------------------------------------------------------------------- | ||
49 | | | ||
50 | | Trust proxy defines whether X-Forwarded-* headers should be trusted or not. | ||
51 | | When your application is behind a proxy server like nginx, these values | ||
52 | | are set automatically and should be trusted. Apart from setting it | ||
53 | | to true or false Adonis supports handful or ways to allow proxy | ||
54 | | values. Read documentation for that. | ||
55 | | | ||
56 | */ | ||
57 | trustProxy: false, | ||
58 | |||
59 | /* | ||
60 | |-------------------------------------------------------------------------- | ||
61 | | Subdomains | ||
62 | |-------------------------------------------------------------------------- | ||
63 | | | ||
64 | | Offset to be used for returning subdomains for a given request.For | ||
65 | | majority of applications it will be 2, until you have nested | ||
66 | | sudomains. | ||
67 | | cheatsheet.adonisjs.com - offset - 2 | ||
68 | | virk.cheatsheet.adonisjs.com - offset - 3 | ||
69 | | | ||
70 | */ | ||
71 | subdomainOffset: 2, | ||
72 | |||
73 | /* | ||
74 | |-------------------------------------------------------------------------- | ||
75 | | JSONP Callback | ||
76 | |-------------------------------------------------------------------------- | ||
77 | | | ||
78 | | Default jsonp callback to be used when callback query string is missing | ||
79 | | in request url. | ||
80 | | | ||
81 | */ | ||
82 | jsonpCallback: 'callback', | ||
83 | |||
84 | |||
85 | /* | ||
86 | |-------------------------------------------------------------------------- | ||
87 | | Etag | ||
88 | |-------------------------------------------------------------------------- | ||
89 | | | ||
90 | | Set etag on all HTTP response. In order to disable for selected routes, | ||
91 | | you can call the `response.send` with an options object as follows. | ||
92 | | | ||
93 | | response.send('Hello', { ignoreEtag: true }) | ||
94 | | | ||
95 | */ | ||
96 | etag: false, | ||
97 | }, | ||
98 | |||
99 | views: { | ||
100 | /* | ||
101 | |-------------------------------------------------------------------------- | ||
102 | | Cache Views | ||
103 | |-------------------------------------------------------------------------- | ||
104 | | | ||
105 | | Define whether or not to cache the compiled view. Set it to true in | ||
106 | | production to optimize view loading time. | ||
107 | | | ||
108 | */ | ||
109 | cache: Env.get('CACHE_VIEWS', true), | ||
110 | }, | ||
111 | |||
112 | static: { | ||
113 | /* | ||
114 | |-------------------------------------------------------------------------- | ||
115 | | Dot Files | ||
116 | |-------------------------------------------------------------------------- | ||
117 | | | ||
118 | | Define how to treat dot files when trying to server static resources. | ||
119 | | By default it is set to ignore, which will pretend that dotfiles | ||
120 | | does not exists. | ||
121 | | | ||
122 | | Can be one of the following | ||
123 | | ignore, deny, allow | ||
124 | | | ||
125 | */ | ||
126 | dotfiles: 'ignore', | ||
127 | |||
128 | /* | ||
129 | |-------------------------------------------------------------------------- | ||
130 | | ETag | ||
131 | |-------------------------------------------------------------------------- | ||
132 | | | ||
133 | | Enable or disable etag generation | ||
134 | | | ||
135 | */ | ||
136 | etag: true, | ||
137 | |||
138 | /* | ||
139 | |-------------------------------------------------------------------------- | ||
140 | | Extensions | ||
141 | |-------------------------------------------------------------------------- | ||
142 | | | ||
143 | | Set file extension fallbacks. When set, if a file is not found, the given | ||
144 | | extensions will be added to the file name and search for. The first | ||
145 | | that exists will be served. Example: ['html', 'htm']. | ||
146 | | | ||
147 | */ | ||
148 | extensions: false, | ||
149 | }, | ||
150 | |||
151 | locales: { | ||
152 | /* | ||
153 | |-------------------------------------------------------------------------- | ||
154 | | Loader | ||
155 | |-------------------------------------------------------------------------- | ||
156 | | | ||
157 | | The loader to be used for fetching and updating locales. Below is the | ||
158 | | list of available options. | ||
159 | | | ||
160 | | file, database | ||
161 | | | ||
162 | */ | ||
163 | loader: 'file', | ||
164 | |||
165 | /* | ||
166 | |-------------------------------------------------------------------------- | ||
167 | | Default Locale | ||
168 | |-------------------------------------------------------------------------- | ||
169 | | | ||
170 | | Default locale to be used by Antl provider. You can always switch drivers | ||
171 | | in runtime or use the official Antl middleware to detect the driver | ||
172 | | based on HTTP headers/query string. | ||
173 | | | ||
174 | */ | ||
175 | locale: 'en', | ||
176 | }, | ||
177 | |||
178 | logger: { | ||
179 | /* | ||
180 | |-------------------------------------------------------------------------- | ||
181 | | Transport | ||
182 | |-------------------------------------------------------------------------- | ||
183 | | | ||
184 | | Transport to be used for logging messages. You can have multiple | ||
185 | | transports using same driver. | ||
186 | | | ||
187 | | Available drivers are: `file` and `console`. | ||
188 | | | ||
189 | */ | ||
190 | transport: 'console', | ||
191 | |||
192 | /* | ||
193 | |-------------------------------------------------------------------------- | ||
194 | | Console Transport | ||
195 | |-------------------------------------------------------------------------- | ||
196 | | | ||
197 | | Using `console` driver for logging. This driver writes to `stdout` | ||
198 | | and `stderr` | ||
199 | | | ||
200 | */ | ||
201 | console: { | ||
202 | driver: 'console', | ||
203 | name: 'adonis-app', | ||
204 | level: 'info', | ||
205 | }, | ||
206 | |||
207 | /* | ||
208 | |-------------------------------------------------------------------------- | ||
209 | | File Transport | ||
210 | |-------------------------------------------------------------------------- | ||
211 | | | ||
212 | | File transport uses file driver and writes log messages for a given | ||
213 | | file inside `tmp` directory for your app. | ||
214 | | | ||
215 | | For a different directory, set an absolute path for the filename. | ||
216 | | | ||
217 | */ | ||
218 | file: { | ||
219 | driver: 'file', | ||
220 | name: 'adonis-app', | ||
221 | filename: 'adonis.log', | ||
222 | level: 'info', | ||
223 | }, | ||
224 | }, | ||
225 | |||
226 | /* | ||
227 | |-------------------------------------------------------------------------- | ||
228 | | Generic Cookie Options | ||
229 | |-------------------------------------------------------------------------- | ||
230 | | | ||
231 | | The following cookie options are generic settings used by AdonisJs to create | ||
232 | | cookies. However, some parts of the application like `sessions` can have | ||
233 | | separate settings for cookies inside `config/session.js`. | ||
234 | | | ||
235 | */ | ||
236 | cookie: { | ||
237 | httpOnly: true, | ||
238 | sameSite: false, | ||
239 | path: '/', | ||
240 | maxAge: 7200, | ||
241 | }, | ||
242 | }; | ||
diff --git a/src/server/config/auth.js b/src/server/config/auth.js deleted file mode 100644 index b831b06c6..000000000 --- a/src/server/config/auth.js +++ /dev/null | |||
@@ -1,93 +0,0 @@ | |||
1 | |||
2 | /** @type {import('@adonisjs/framework/src/Env')} */ | ||
3 | const Env = use('Env'); | ||
4 | |||
5 | module.exports = { | ||
6 | /* | ||
7 | |-------------------------------------------------------------------------- | ||
8 | | Authenticator | ||
9 | |-------------------------------------------------------------------------- | ||
10 | | | ||
11 | | Authentication is a combination of serializer and scheme with extra | ||
12 | | config to define on how to authenticate a user. | ||
13 | | | ||
14 | | Available Schemes - basic, session, jwt, api | ||
15 | | Available Serializers - lucid, database | ||
16 | | | ||
17 | */ | ||
18 | authenticator: 'jwt', | ||
19 | |||
20 | /* | ||
21 | |-------------------------------------------------------------------------- | ||
22 | | Session | ||
23 | |-------------------------------------------------------------------------- | ||
24 | | | ||
25 | | Session authenticator makes use of sessions to authenticate a user. | ||
26 | | Session authentication is always persistent. | ||
27 | | | ||
28 | */ | ||
29 | session: { | ||
30 | serializer: 'lucid', | ||
31 | model: 'App/Models/User', | ||
32 | scheme: 'session', | ||
33 | uid: 'email', | ||
34 | password: 'password', | ||
35 | }, | ||
36 | |||
37 | /* | ||
38 | |-------------------------------------------------------------------------- | ||
39 | | Basic Auth | ||
40 | |-------------------------------------------------------------------------- | ||
41 | | | ||
42 | | The basic auth authenticator uses basic auth header to authenticate a | ||
43 | | user. | ||
44 | | | ||
45 | | NOTE: | ||
46 | | This scheme is not persistent and users are supposed to pass | ||
47 | | login credentials on each request. | ||
48 | | | ||
49 | */ | ||
50 | basic: { | ||
51 | serializer: 'lucid', | ||
52 | model: 'App/Models/User', | ||
53 | scheme: 'basic', | ||
54 | uid: 'email', | ||
55 | password: 'password', | ||
56 | }, | ||
57 | |||
58 | /* | ||
59 | |-------------------------------------------------------------------------- | ||
60 | | Jwt | ||
61 | |-------------------------------------------------------------------------- | ||
62 | | | ||
63 | | The jwt authenticator works by passing a jwt token on each HTTP request | ||
64 | | via HTTP `Authorization` header. | ||
65 | | | ||
66 | */ | ||
67 | jwt: { | ||
68 | serializer: 'lucid', | ||
69 | model: 'App/Models/User', | ||
70 | scheme: 'jwt', | ||
71 | uid: 'email', | ||
72 | password: 'password', | ||
73 | options: { | ||
74 | secret: Env.get('APP_KEY'), | ||
75 | }, | ||
76 | }, | ||
77 | |||
78 | /* | ||
79 | |-------------------------------------------------------------------------- | ||
80 | | Api | ||
81 | |-------------------------------------------------------------------------- | ||
82 | | | ||
83 | | The Api scheme makes use of API personal tokens to authenticate a user. | ||
84 | | | ||
85 | */ | ||
86 | api: { | ||
87 | serializer: 'lucid', | ||
88 | model: 'App/Models/User', | ||
89 | scheme: 'api', | ||
90 | uid: 'email', | ||
91 | password: 'password', | ||
92 | }, | ||
93 | }; | ||
diff --git a/src/server/config/bodyParser.js b/src/server/config/bodyParser.js deleted file mode 100644 index c336e67d2..000000000 --- a/src/server/config/bodyParser.js +++ /dev/null | |||
@@ -1,156 +0,0 @@ | |||
1 | |||
2 | module.exports = { | ||
3 | /* | ||
4 | |-------------------------------------------------------------------------- | ||
5 | | JSON Parser | ||
6 | |-------------------------------------------------------------------------- | ||
7 | | | ||
8 | | Below settings are applied when the request body contains a JSON payload. | ||
9 | | If you want body parser to ignore JSON payloads, then simply set `types` | ||
10 | | to an empty array. | ||
11 | */ | ||
12 | json: { | ||
13 | /* | ||
14 | |-------------------------------------------------------------------------- | ||
15 | | limit | ||
16 | |-------------------------------------------------------------------------- | ||
17 | | | ||
18 | | Defines the limit of JSON that can be sent by the client. If payload | ||
19 | | is over 1mb it will not be processed. | ||
20 | | | ||
21 | */ | ||
22 | limit: '50mb', | ||
23 | |||
24 | /* | ||
25 | |-------------------------------------------------------------------------- | ||
26 | | strict | ||
27 | |-------------------------------------------------------------------------- | ||
28 | | | ||
29 | | When `strict` is set to true, body parser will only parse Arrays and | ||
30 | | Object. Otherwise everything parseable by `JSON.parse` is parsed. | ||
31 | | | ||
32 | */ | ||
33 | strict: true, | ||
34 | |||
35 | /* | ||
36 | |-------------------------------------------------------------------------- | ||
37 | | types | ||
38 | |-------------------------------------------------------------------------- | ||
39 | | | ||
40 | | Which content types are processed as JSON payloads. You are free to | ||
41 | | add your own types here, but the request body should be parseable | ||
42 | | by `JSON.parse` method. | ||
43 | | | ||
44 | */ | ||
45 | types: [ | ||
46 | 'application/json', | ||
47 | 'application/json-patch+json', | ||
48 | 'application/vnd.api+json', | ||
49 | 'application/csp-report', | ||
50 | ], | ||
51 | }, | ||
52 | |||
53 | /* | ||
54 | |-------------------------------------------------------------------------- | ||
55 | | Raw Parser | ||
56 | |-------------------------------------------------------------------------- | ||
57 | | | ||
58 | | | ||
59 | | | ||
60 | */ | ||
61 | raw: { | ||
62 | types: [ | ||
63 | 'text/*', | ||
64 | ], | ||
65 | }, | ||
66 | |||
67 | /* | ||
68 | |-------------------------------------------------------------------------- | ||
69 | | Form Parser | ||
70 | |-------------------------------------------------------------------------- | ||
71 | | | ||
72 | | | ||
73 | | | ||
74 | */ | ||
75 | form: { | ||
76 | types: [ | ||
77 | 'application/x-www-form-urlencoded', | ||
78 | ], | ||
79 | }, | ||
80 | |||
81 | /* | ||
82 | |-------------------------------------------------------------------------- | ||
83 | | Files Parser | ||
84 | |-------------------------------------------------------------------------- | ||
85 | | | ||
86 | | | ||
87 | | | ||
88 | */ | ||
89 | files: { | ||
90 | types: [ | ||
91 | 'multipart/form-data', | ||
92 | ], | ||
93 | |||
94 | /* | ||
95 | |-------------------------------------------------------------------------- | ||
96 | | Max Size | ||
97 | |-------------------------------------------------------------------------- | ||
98 | | | ||
99 | | Below value is the max size of all the files uploaded to the server. It | ||
100 | | is validated even before files have been processed and hard exception | ||
101 | | is thrown. | ||
102 | | | ||
103 | | Consider setting a reasonable value here, otherwise people may upload GB's | ||
104 | | of files which will keep your server busy. | ||
105 | | | ||
106 | | Also this value is considered when `autoProcess` is set to true. | ||
107 | | | ||
108 | */ | ||
109 | maxSize: '20mb', | ||
110 | |||
111 | /* | ||
112 | |-------------------------------------------------------------------------- | ||
113 | | Auto Process | ||
114 | |-------------------------------------------------------------------------- | ||
115 | | | ||
116 | | Whether or not to auto-process files. Since HTTP servers handle files via | ||
117 | | couple of specific endpoints. It is better to set this value off and | ||
118 | | manually process the files when required. | ||
119 | | | ||
120 | | This value can contain a boolean or an array of route patterns | ||
121 | | to be autoprocessed. | ||
122 | */ | ||
123 | autoProcess: true, | ||
124 | |||
125 | /* | ||
126 | |-------------------------------------------------------------------------- | ||
127 | | Process Manually | ||
128 | |-------------------------------------------------------------------------- | ||
129 | | | ||
130 | | The list of routes that should not process files and instead rely on | ||
131 | | manual process. This list should only contain routes when autoProcess | ||
132 | | is to true. Otherwise everything is processed manually. | ||
133 | | | ||
134 | */ | ||
135 | processManually: [], | ||
136 | |||
137 | /* | ||
138 | |-------------------------------------------------------------------------- | ||
139 | | Temporary file name | ||
140 | |-------------------------------------------------------------------------- | ||
141 | | | ||
142 | | Define a function, which should return a string to be used as the | ||
143 | | tmp file name. | ||
144 | | | ||
145 | | If not defined, Bodyparser will use `uuid` as the tmp file name. | ||
146 | | | ||
147 | | To be defined as. If you are defining the function, then do make sure | ||
148 | | to return a value from it. | ||
149 | | | ||
150 | | tmpFileName () { | ||
151 | | return 'some-unique-value' | ||
152 | | } | ||
153 | | | ||
154 | */ | ||
155 | }, | ||
156 | }; | ||
diff --git a/src/server/config/cors.js b/src/server/config/cors.js deleted file mode 100644 index 7ebbe3ffa..000000000 --- a/src/server/config/cors.js +++ /dev/null | |||
@@ -1,86 +0,0 @@ | |||
1 | |||
2 | module.exports = { | ||
3 | /* | ||
4 | |-------------------------------------------------------------------------- | ||
5 | | Origin | ||
6 | |-------------------------------------------------------------------------- | ||
7 | | | ||
8 | | Set a list of origins to be allowed. The value can be one of the following | ||
9 | | | ||
10 | | Boolean: true - Allow current request origin | ||
11 | | Boolean: false - Disallow all | ||
12 | | String - Comma separated list of allowed origins | ||
13 | | Array - An array of allowed origins | ||
14 | | String: * - A wildcard to allow current request origin | ||
15 | | Function - Receives the current origin and should return one of the above values. | ||
16 | | | ||
17 | */ | ||
18 | origin: false, | ||
19 | |||
20 | /* | ||
21 | |-------------------------------------------------------------------------- | ||
22 | | Methods | ||
23 | |-------------------------------------------------------------------------- | ||
24 | | | ||
25 | | HTTP methods to be allowed. The value can be one of the following | ||
26 | | | ||
27 | | String - Comma separated list of allowed methods | ||
28 | | Array - An array of allowed methods | ||
29 | | | ||
30 | */ | ||
31 | methods: ['GET', 'PUT', 'PATCH', 'POST', 'DELETE'], | ||
32 | |||
33 | /* | ||
34 | |-------------------------------------------------------------------------- | ||
35 | | Headers | ||
36 | |-------------------------------------------------------------------------- | ||
37 | | | ||
38 | | List of headers to be allowed via Access-Control-Request-Headers header. | ||
39 | | The value can be one of the following. | ||
40 | | | ||
41 | | Boolean: true - Allow current request headers | ||
42 | | Boolean: false - Disallow all | ||
43 | | String - Comma separated list of allowed headers | ||
44 | | Array - An array of allowed headers | ||
45 | | String: * - A wildcard to allow current request headers | ||
46 | | Function - Receives the current header and should return one of the above values. | ||
47 | | | ||
48 | */ | ||
49 | headers: true, | ||
50 | |||
51 | /* | ||
52 | |-------------------------------------------------------------------------- | ||
53 | | Expose Headers | ||
54 | |-------------------------------------------------------------------------- | ||
55 | | | ||
56 | | A list of headers to be exposed via `Access-Control-Expose-Headers` | ||
57 | | header. The value can be one of the following. | ||
58 | | | ||
59 | | Boolean: false - Disallow all | ||
60 | | String: Comma separated list of allowed headers | ||
61 | | Array - An array of allowed headers | ||
62 | | | ||
63 | */ | ||
64 | exposeHeaders: false, | ||
65 | |||
66 | /* | ||
67 | |-------------------------------------------------------------------------- | ||
68 | | Credentials | ||
69 | |-------------------------------------------------------------------------- | ||
70 | | | ||
71 | | Define Access-Control-Allow-Credentials header. It should always be a | ||
72 | | boolean. | ||
73 | | | ||
74 | */ | ||
75 | credentials: false, | ||
76 | |||
77 | /* | ||
78 | |-------------------------------------------------------------------------- | ||
79 | | MaxAge | ||
80 | |-------------------------------------------------------------------------- | ||
81 | | | ||
82 | | Define Access-Control-Allow-Max-Age | ||
83 | | | ||
84 | */ | ||
85 | maxAge: 90, | ||
86 | }; | ||
diff --git a/src/server/config/database.js b/src/server/config/database.js deleted file mode 100644 index a413f7050..000000000 --- a/src/server/config/database.js +++ /dev/null | |||
@@ -1,83 +0,0 @@ | |||
1 | |||
2 | /** @type {import('@adonisjs/framework/src/Env')} */ | ||
3 | const Env = use('Env'); | ||
4 | |||
5 | const dbPath = process.env.DB_PATH; | ||
6 | |||
7 | module.exports = { | ||
8 | /* | ||
9 | |-------------------------------------------------------------------------- | ||
10 | | Default Connection | ||
11 | |-------------------------------------------------------------------------- | ||
12 | | | ||
13 | | Connection defines the default connection settings to be used while | ||
14 | | interacting with SQL databases. | ||
15 | | | ||
16 | */ | ||
17 | connection: Env.get('DB_CONNECTION', 'sqlite'), | ||
18 | |||
19 | /* | ||
20 | |-------------------------------------------------------------------------- | ||
21 | | Sqlite | ||
22 | |-------------------------------------------------------------------------- | ||
23 | | | ||
24 | | Sqlite is a flat file database and can be a good choice for a development | ||
25 | | environment. | ||
26 | | | ||
27 | | npm i --save sqlite3 | ||
28 | | | ||
29 | */ | ||
30 | sqlite: { | ||
31 | client: 'sqlite3', | ||
32 | connection: { | ||
33 | // filename: Helpers.databasePath(`${Env.get('DB_DATABASE', 'development')}.sqlite`), | ||
34 | filename: dbPath, | ||
35 | }, | ||
36 | useNullAsDefault: true, | ||
37 | debug: Env.get('DB_DEBUG', false), | ||
38 | }, | ||
39 | |||
40 | /* | ||
41 | |-------------------------------------------------------------------------- | ||
42 | | MySQL | ||
43 | |-------------------------------------------------------------------------- | ||
44 | | | ||
45 | | Here we define connection settings for MySQL database. | ||
46 | | | ||
47 | | npm i --save mysql | ||
48 | | | ||
49 | */ | ||
50 | mysql: { | ||
51 | client: 'mysql', | ||
52 | connection: { | ||
53 | host: Env.get('DB_HOST', 'localhost'), | ||
54 | port: Env.get('DB_PORT', ''), | ||
55 | user: Env.get('DB_USER', 'root'), | ||
56 | password: Env.get('DB_PASSWORD', ''), | ||
57 | database: Env.get('DB_DATABASE', 'adonis'), | ||
58 | }, | ||
59 | debug: Env.get('DB_DEBUG', false), | ||
60 | }, | ||
61 | |||
62 | /* | ||
63 | |-------------------------------------------------------------------------- | ||
64 | | PostgreSQL | ||
65 | |-------------------------------------------------------------------------- | ||
66 | | | ||
67 | | Here we define connection settings for PostgreSQL database. | ||
68 | | | ||
69 | | npm i --save pg | ||
70 | | | ||
71 | */ | ||
72 | pg: { | ||
73 | client: 'pg', | ||
74 | connection: { | ||
75 | host: Env.get('DB_HOST', 'localhost'), | ||
76 | port: Env.get('DB_PORT', ''), | ||
77 | user: Env.get('DB_USER', 'root'), | ||
78 | password: Env.get('DB_PASSWORD', ''), | ||
79 | database: Env.get('DB_DATABASE', 'adonis'), | ||
80 | }, | ||
81 | debug: Env.get('DB_DEBUG', false), | ||
82 | }, | ||
83 | }; | ||
diff --git a/src/server/config/drive.js b/src/server/config/drive.js deleted file mode 100644 index 617ce470a..000000000 --- a/src/server/config/drive.js +++ /dev/null | |||
@@ -1,45 +0,0 @@ | |||
1 | const Env = use('Env'); | ||
2 | |||
3 | module.exports = { | ||
4 | /* | ||
5 | |-------------------------------------------------------------------------- | ||
6 | | Default disk | ||
7 | |-------------------------------------------------------------------------- | ||
8 | | | ||
9 | | The default disk is used when you interact with the file system without | ||
10 | | defining a disk name | ||
11 | | | ||
12 | */ | ||
13 | default: 'local', | ||
14 | |||
15 | disks: { | ||
16 | /* | ||
17 | |-------------------------------------------------------------------------- | ||
18 | | Local | ||
19 | |-------------------------------------------------------------------------- | ||
20 | | | ||
21 | | Local disk interacts with the a local folder inside your application | ||
22 | | | ||
23 | */ | ||
24 | local: { | ||
25 | root: `${__dirname}/../recipes`, | ||
26 | driver: 'local', | ||
27 | }, | ||
28 | |||
29 | /* | ||
30 | |-------------------------------------------------------------------------- | ||
31 | | S3 | ||
32 | |-------------------------------------------------------------------------- | ||
33 | | | ||
34 | | S3 disk interacts with a bucket on aws s3 | ||
35 | | | ||
36 | */ | ||
37 | s3: { | ||
38 | driver: 's3', | ||
39 | key: Env.get('S3_KEY'), | ||
40 | secret: Env.get('S3_SECRET'), | ||
41 | bucket: Env.get('S3_BUCKET'), | ||
42 | region: Env.get('S3_REGION'), | ||
43 | }, | ||
44 | }, | ||
45 | }; | ||
diff --git a/src/server/config/hash.js b/src/server/config/hash.js deleted file mode 100644 index 297c977fc..000000000 --- a/src/server/config/hash.js +++ /dev/null | |||
@@ -1,48 +0,0 @@ | |||
1 | |||
2 | /** @type {import('@adonisjs/framework/src/Env')} */ | ||
3 | const Env = use('Env'); | ||
4 | |||
5 | module.exports = { | ||
6 | /* | ||
7 | |-------------------------------------------------------------------------- | ||
8 | | Driver | ||
9 | |-------------------------------------------------------------------------- | ||
10 | | | ||
11 | | Driver to be used for hashing values. The same driver is used by the | ||
12 | | auth module too. | ||
13 | | | ||
14 | */ | ||
15 | driver: Env.get('HASH_DRIVER', 'bcrypt'), | ||
16 | |||
17 | /* | ||
18 | |-------------------------------------------------------------------------- | ||
19 | | Bcrypt | ||
20 | |-------------------------------------------------------------------------- | ||
21 | | | ||
22 | | Config related to bcrypt hashing. https://www.npmjs.com/package/bcrypt | ||
23 | | package is used internally. | ||
24 | | | ||
25 | */ | ||
26 | bcrypt: { | ||
27 | rounds: 10, | ||
28 | }, | ||
29 | |||
30 | /* | ||
31 | |-------------------------------------------------------------------------- | ||
32 | | Argon | ||
33 | |-------------------------------------------------------------------------- | ||
34 | | | ||
35 | | Config related to argon. https://www.npmjs.com/package/argon2 package is | ||
36 | | used internally. | ||
37 | | | ||
38 | | Since argon is optional, you will have to install the dependency yourself | ||
39 | | | ||
40 | |============================================================================ | ||
41 | | npm i argon2 | ||
42 | |============================================================================ | ||
43 | | | ||
44 | */ | ||
45 | argon: { | ||
46 | type: 1, | ||
47 | }, | ||
48 | }; | ||
diff --git a/src/server/config/session.js b/src/server/config/session.js deleted file mode 100644 index bce28bdd9..000000000 --- a/src/server/config/session.js +++ /dev/null | |||
@@ -1,98 +0,0 @@ | |||
1 | |||
2 | const Env = use('Env'); | ||
3 | |||
4 | module.exports = { | ||
5 | /* | ||
6 | |-------------------------------------------------------------------------- | ||
7 | | Session Driver | ||
8 | |-------------------------------------------------------------------------- | ||
9 | | | ||
10 | | The session driver to be used for storing session values. It can be | ||
11 | | cookie, file or redis. | ||
12 | | | ||
13 | | For `redis` driver, make sure to install and register `@adonisjs/redis` | ||
14 | | | ||
15 | */ | ||
16 | driver: Env.get('SESSION_DRIVER', 'cookie'), | ||
17 | |||
18 | /* | ||
19 | |-------------------------------------------------------------------------- | ||
20 | | Cookie Name | ||
21 | |-------------------------------------------------------------------------- | ||
22 | | | ||
23 | | The name of the cookie to be used for saving session id. Session ids | ||
24 | | are signed and encrypted. | ||
25 | | | ||
26 | */ | ||
27 | cookieName: 'adonis-session', | ||
28 | |||
29 | /* | ||
30 | |-------------------------------------------------------------------------- | ||
31 | | Clear session when browser closes | ||
32 | |-------------------------------------------------------------------------- | ||
33 | | | ||
34 | | If this value is true, the session cookie will be temporary and will be | ||
35 | | removed when browser closes. | ||
36 | | | ||
37 | */ | ||
38 | clearWithBrowser: true, | ||
39 | |||
40 | /* | ||
41 | |-------------------------------------------------------------------------- | ||
42 | | Session age | ||
43 | |-------------------------------------------------------------------------- | ||
44 | | | ||
45 | | This value is only used when `clearWithBrowser` is set to false. The | ||
46 | | age must be a valid https://npmjs.org/package/ms string or should | ||
47 | | be in milliseconds. | ||
48 | | | ||
49 | | Valid values are: | ||
50 | | '2h', '10d', '5y', '2.5 hrs' | ||
51 | | | ||
52 | */ | ||
53 | age: '2h', | ||
54 | |||
55 | /* | ||
56 | |-------------------------------------------------------------------------- | ||
57 | | Cookie options | ||
58 | |-------------------------------------------------------------------------- | ||
59 | | | ||
60 | | Cookie options defines the options to be used for setting up session | ||
61 | | cookie | ||
62 | | | ||
63 | */ | ||
64 | cookie: { | ||
65 | httpOnly: true, | ||
66 | path: '/', | ||
67 | sameSite: false, | ||
68 | }, | ||
69 | |||
70 | /* | ||
71 | |-------------------------------------------------------------------------- | ||
72 | | Sessions location | ||
73 | |-------------------------------------------------------------------------- | ||
74 | | | ||
75 | | If driver is set to file, we need to define the relative location from | ||
76 | | the temporary path or absolute url to any location. | ||
77 | | | ||
78 | */ | ||
79 | file: { | ||
80 | location: 'sessions', | ||
81 | }, | ||
82 | |||
83 | /* | ||
84 | |-------------------------------------------------------------------------- | ||
85 | | Redis config | ||
86 | |-------------------------------------------------------------------------- | ||
87 | | | ||
88 | | The configuration for the redis driver. | ||
89 | | | ||
90 | */ | ||
91 | redis: { | ||
92 | host: '127.0.0.1', | ||
93 | port: 6379, | ||
94 | password: null, | ||
95 | db: 0, | ||
96 | keyPrefix: '', | ||
97 | }, | ||
98 | }; | ||
diff --git a/src/server/config/shield.js b/src/server/config/shield.js deleted file mode 100644 index 5c1c5cd73..000000000 --- a/src/server/config/shield.js +++ /dev/null | |||
@@ -1,144 +0,0 @@ | |||
1 | |||
2 | module.exports = { | ||
3 | /* | ||
4 | |-------------------------------------------------------------------------- | ||
5 | | Content Security Policy | ||
6 | |-------------------------------------------------------------------------- | ||
7 | | | ||
8 | | Content security policy filters out the origins not allowed to execute | ||
9 | | and load resources like scripts, styles and fonts. There are wide | ||
10 | | variety of options to choose from. | ||
11 | */ | ||
12 | csp: { | ||
13 | /* | ||
14 | |-------------------------------------------------------------------------- | ||
15 | | Directives | ||
16 | |-------------------------------------------------------------------------- | ||
17 | | | ||
18 | | All directives are defined in camelCase and here is the list of | ||
19 | | available directives and their possible values. | ||
20 | | | ||
21 | | https://content-security-policy.com | ||
22 | | | ||
23 | | @example | ||
24 | | directives: { | ||
25 | | defaultSrc: ['self', '@nonce', 'cdnjs.cloudflare.com'] | ||
26 | | } | ||
27 | | | ||
28 | */ | ||
29 | directives: { | ||
30 | }, | ||
31 | /* | ||
32 | |-------------------------------------------------------------------------- | ||
33 | | Report only | ||
34 | |-------------------------------------------------------------------------- | ||
35 | | | ||
36 | | Setting `reportOnly=true` will not block the scripts from running and | ||
37 | | instead report them to a URL. | ||
38 | | | ||
39 | */ | ||
40 | reportOnly: false, | ||
41 | /* | ||
42 | |-------------------------------------------------------------------------- | ||
43 | | Set all headers | ||
44 | |-------------------------------------------------------------------------- | ||
45 | | | ||
46 | | Headers staring with `X` have been depreciated, since all major browsers | ||
47 | | supports the standard CSP header. So its better to disable deperciated | ||
48 | | headers, unless you want them to be set. | ||
49 | | | ||
50 | */ | ||
51 | setAllHeaders: false, | ||
52 | |||
53 | /* | ||
54 | |-------------------------------------------------------------------------- | ||
55 | | Disable on android | ||
56 | |-------------------------------------------------------------------------- | ||
57 | | | ||
58 | | Certain versions of android are buggy with CSP policy. So you can set | ||
59 | | this value to true, to disable it for Android versions with buggy | ||
60 | | behavior. | ||
61 | | | ||
62 | | Here is an issue reported on a different package, but helpful to read | ||
63 | | if you want to know the behavior. https://github.com/helmetjs/helmet/pull/82 | ||
64 | | | ||
65 | */ | ||
66 | disableAndroid: true, | ||
67 | }, | ||
68 | |||
69 | /* | ||
70 | |-------------------------------------------------------------------------- | ||
71 | | X-XSS-Protection | ||
72 | |-------------------------------------------------------------------------- | ||
73 | | | ||
74 | | X-XSS Protection saves from applications from XSS attacks. It is adopted | ||
75 | | by IE and later followed by some other browsers. | ||
76 | | | ||
77 | | Learn more at https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection | ||
78 | | | ||
79 | */ | ||
80 | xss: { | ||
81 | enabled: true, | ||
82 | enableOnOldIE: false, | ||
83 | }, | ||
84 | |||
85 | /* | ||
86 | |-------------------------------------------------------------------------- | ||
87 | | Iframe Options | ||
88 | |-------------------------------------------------------------------------- | ||
89 | | | ||
90 | | xframe defines whether or not your website can be embedded inside an | ||
91 | | iframe. Choose from one of the following options. | ||
92 | | @available options | ||
93 | | DENY, SAMEORIGIN, ALLOW-FROM http://example.com | ||
94 | | | ||
95 | | Learn more at https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options | ||
96 | */ | ||
97 | xframe: 'DENY', | ||
98 | |||
99 | /* | ||
100 | |-------------------------------------------------------------------------- | ||
101 | | No Sniff | ||
102 | |-------------------------------------------------------------------------- | ||
103 | | | ||
104 | | Browsers have a habit of sniffing content-type of a response. Which means | ||
105 | | files with .txt extension containing Javascript code will be executed as | ||
106 | | Javascript. You can disable this behavior by setting nosniff to false. | ||
107 | | | ||
108 | | Learn more at https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options | ||
109 | | | ||
110 | */ | ||
111 | nosniff: true, | ||
112 | |||
113 | /* | ||
114 | |-------------------------------------------------------------------------- | ||
115 | | No Open | ||
116 | |-------------------------------------------------------------------------- | ||
117 | | | ||
118 | | IE users can execute webpages in the context of your website, which is | ||
119 | | a serious security risk. Below option will manage this for you. | ||
120 | | | ||
121 | */ | ||
122 | noopen: true, | ||
123 | |||
124 | /* | ||
125 | |-------------------------------------------------------------------------- | ||
126 | | CSRF Protection | ||
127 | |-------------------------------------------------------------------------- | ||
128 | | | ||
129 | | CSRF Protection adds another layer of security by making sure, actionable | ||
130 | | routes does have a valid token to execute an action. | ||
131 | | | ||
132 | */ | ||
133 | csrf: { | ||
134 | enable: true, | ||
135 | methods: ['POST', 'PUT', 'DELETE'], | ||
136 | filterUris: [], | ||
137 | cookieOptions: { | ||
138 | httpOnly: false, | ||
139 | sameSite: true, | ||
140 | path: '/', | ||
141 | maxAge: 7200, | ||
142 | }, | ||
143 | }, | ||
144 | }; | ||
diff --git a/src/server/database/factory.js b/src/server/database/factory.js deleted file mode 100644 index 550c5e6ab..000000000 --- a/src/server/database/factory.js +++ /dev/null | |||
@@ -1,20 +0,0 @@ | |||
1 | |||
2 | /* | ||
3 | |-------------------------------------------------------------------------- | ||
4 | | Factory | ||
5 | |-------------------------------------------------------------------------- | ||
6 | | | ||
7 | | Factories are used to define blueprints for database tables or Lucid | ||
8 | | models. Later you can use these blueprints to seed your database | ||
9 | | with dummy data. | ||
10 | | | ||
11 | */ | ||
12 | |||
13 | /** @type {import('@adonisjs/lucid/src/Factory')} */ | ||
14 | // const Factory = use('Factory') | ||
15 | |||
16 | // Factory.blueprint('App/Models/User', (faker) => { | ||
17 | // return { | ||
18 | // username: faker.username() | ||
19 | // } | ||
20 | // }) | ||
diff --git a/src/server/database/migrations/1566385379883_service_schema.js b/src/server/database/migrations/1566385379883_service_schema.js deleted file mode 100644 index 1db95c19d..000000000 --- a/src/server/database/migrations/1566385379883_service_schema.js +++ /dev/null | |||
@@ -1,22 +0,0 @@ | |||
1 | |||
2 | /** @type {import('@adonisjs/lucid/src/Schema')} */ | ||
3 | const Schema = use('Schema'); | ||
4 | |||
5 | class ServiceSchema extends Schema { | ||
6 | up() { | ||
7 | this.create('services', (table) => { | ||
8 | table.increments(); | ||
9 | table.string('serviceId', 80).notNullable(); | ||
10 | table.string('name', 80).notNullable(); | ||
11 | table.string('recipeId', 254).notNullable(); | ||
12 | table.json('settings'); | ||
13 | table.timestamps(); | ||
14 | }); | ||
15 | } | ||
16 | |||
17 | down() { | ||
18 | this.drop('services'); | ||
19 | } | ||
20 | } | ||
21 | |||
22 | module.exports = ServiceSchema; | ||
diff --git a/src/server/database/migrations/1566554231482_recipe_schema.js b/src/server/database/migrations/1566554231482_recipe_schema.js deleted file mode 100644 index 14fcb82e5..000000000 --- a/src/server/database/migrations/1566554231482_recipe_schema.js +++ /dev/null | |||
@@ -1,21 +0,0 @@ | |||
1 | |||
2 | /** @type {import('@adonisjs/lucid/src/Schema')} */ | ||
3 | const Schema = use('Schema'); | ||
4 | |||
5 | class RecipeSchema extends Schema { | ||
6 | up() { | ||
7 | this.create('recipes', (table) => { | ||
8 | table.increments(); | ||
9 | table.string('name', 80).notNullable(); | ||
10 | table.string('recipeId', 254).notNullable().unique(); | ||
11 | table.json('data'); | ||
12 | table.timestamps(); | ||
13 | }); | ||
14 | } | ||
15 | |||
16 | down() { | ||
17 | this.drop('recipes'); | ||
18 | } | ||
19 | } | ||
20 | |||
21 | module.exports = RecipeSchema; | ||
diff --git a/src/server/database/migrations/1566554359294_workspace_schema.js b/src/server/database/migrations/1566554359294_workspace_schema.js deleted file mode 100644 index b53bbe656..000000000 --- a/src/server/database/migrations/1566554359294_workspace_schema.js +++ /dev/null | |||
@@ -1,23 +0,0 @@ | |||
1 | |||
2 | /** @type {import('@adonisjs/lucid/src/Schema')} */ | ||
3 | const Schema = use('Schema'); | ||
4 | |||
5 | class WorkspaceSchema extends Schema { | ||
6 | up() { | ||
7 | this.create('workspaces', (table) => { | ||
8 | table.increments(); | ||
9 | table.string('workspaceId', 80).notNullable().unique(); | ||
10 | table.string('name', 80).notNullable(); | ||
11 | table.integer('order'); | ||
12 | table.json('services'); | ||
13 | table.json('data'); | ||
14 | table.timestamps(); | ||
15 | }); | ||
16 | } | ||
17 | |||
18 | down() { | ||
19 | this.drop('workspaces'); | ||
20 | } | ||
21 | } | ||
22 | |||
23 | module.exports = WorkspaceSchema; | ||
diff --git a/src/server/database/template.sqlite b/src/server/database/template.sqlite deleted file mode 100644 index db5425ee6..000000000 --- a/src/server/database/template.sqlite +++ /dev/null | |||
Binary files differ | |||
diff --git a/src/server/env.ini b/src/server/env.ini deleted file mode 100644 index 902e8e4c8..000000000 --- a/src/server/env.ini +++ /dev/null | |||
@@ -1,16 +0,0 @@ | |||
1 | HOST=127.0.0.1 | ||
2 | PORT=45569 | ||
3 | NODE_ENV=development | ||
4 | APP_NAME=Ferdi Internal Server | ||
5 | APP_URL=http://${HOST}:${PORT} | ||
6 | CACHE_VIEWS=false | ||
7 | APP_KEY=FERDIINTERNALSERVER | ||
8 | DB_CONNECTION=sqlite | ||
9 | DB_HOST=127.0.0.1 | ||
10 | DB_PORT=3306 | ||
11 | DB_USER=root | ||
12 | DB_PASSWORD= | ||
13 | DB_DATABASE=ferdi | ||
14 | HASH_DRIVER=bcrypt | ||
15 | IS_CREATION_ENABLED=true | ||
16 | CONNECT_WITH_FRANZ=true \ No newline at end of file | ||
diff --git a/src/server/logo.png b/src/server/logo.png deleted file mode 100644 index 4145a077a..000000000 --- a/src/server/logo.png +++ /dev/null | |||
Binary files differ | |||
diff --git a/src/server/package.json b/src/server/package.json deleted file mode 100644 index 60dd58e93..000000000 --- a/src/server/package.json +++ /dev/null | |||
@@ -1,49 +0,0 @@ | |||
1 | { | ||
2 | "name": "ferdi-internal-server", | ||
3 | "version": "1.0.0", | ||
4 | "adonis-version": "4.1.0", | ||
5 | "description": "Internal server used by the Ferdi application.", | ||
6 | "main": "index.js", | ||
7 | "scripts": { | ||
8 | "start": "node server.js", | ||
9 | "test": "node ace test", | ||
10 | "lint": "eslint --fix ./" | ||
11 | }, | ||
12 | "keywords": [ | ||
13 | ], | ||
14 | "author": "", | ||
15 | "license": "MIT License", | ||
16 | "private": true, | ||
17 | "dependencies": { | ||
18 | "@adonisjs/ace": "^5.0.8", | ||
19 | "@adonisjs/auth": "^3.0.7", | ||
20 | "@adonisjs/bodyparser": "^2.0.5", | ||
21 | "@adonisjs/cors": "^1.0.7", | ||
22 | "@adonisjs/drive": "^1.0.4", | ||
23 | "@adonisjs/fold": "^4.0.9", | ||
24 | "@adonisjs/framework": "^5.0.9", | ||
25 | "@adonisjs/ignitor": "^2.0.8", | ||
26 | "@adonisjs/lucid": "^6.1.3", | ||
27 | "@adonisjs/session": "^1.0.29", | ||
28 | "@adonisjs/shield": "^1.0.8", | ||
29 | "@adonisjs/validator": "^5.0.6", | ||
30 | "atob": "^2.1.2", | ||
31 | "btoa": "^1.2.1", | ||
32 | "fs-extra": "^8.1.0", | ||
33 | "node-fetch": "^2.6.0", | ||
34 | "sqlite3": "^4.1.0", | ||
35 | "uuid": "^3.3.3" | ||
36 | }, | ||
37 | "devDependencies": { | ||
38 | "eslint": "^6.3.0", | ||
39 | "eslint-config-airbnb": "^18.0.1", | ||
40 | "eslint-config-airbnb-base": "^14.0.0", | ||
41 | "eslint-plugin-import": "^2.18.2", | ||
42 | "eslint-plugin-jsx-a11y": "^6.2.3", | ||
43 | "eslint-plugin-react": "^7.14.3", | ||
44 | "eslint-plugin-react-hooks": "^1.7.0" | ||
45 | }, | ||
46 | "autoload": { | ||
47 | "App": "./app" | ||
48 | } | ||
49 | } | ||
diff --git a/src/server/public/css/main.css b/src/server/public/css/main.css deleted file mode 100644 index a1c5653d7..000000000 --- a/src/server/public/css/main.css +++ /dev/null | |||
@@ -1,69 +0,0 @@ | |||
1 | input { | ||
2 | margin-bottom: 1rem; | ||
3 | width: 100%; | ||
4 | padding: 0.5rem; | ||
5 | } | ||
6 | |||
7 | button, .button { | ||
8 | display: flex; | ||
9 | overflow: hidden; | ||
10 | padding: 12px 12px; | ||
11 | cursor: pointer; | ||
12 | width: 100%; | ||
13 | -webkit-user-select: none; | ||
14 | -moz-user-select: none; | ||
15 | -ms-user-select: none; | ||
16 | user-select: none; | ||
17 | transition: all 150ms linear; | ||
18 | text-align: center; | ||
19 | white-space: nowrap; | ||
20 | text-decoration: none !important; | ||
21 | text-transform: none; | ||
22 | text-transform: capitalize; | ||
23 | color: #fff !important; | ||
24 | border: 0 none; | ||
25 | border-radius: 4px; | ||
26 | font-size: 13px; | ||
27 | font-weight: 500; | ||
28 | line-height: 1.3; | ||
29 | -webkit-appearance: none; | ||
30 | -moz-appearance: none; | ||
31 | appearance: none; | ||
32 | justify-content: center; | ||
33 | align-items: center; | ||
34 | flex: 0 0 160px; | ||
35 | box-shadow: 2px 5px 10px #e4e4e4; | ||
36 | color: #FFFFFF; | ||
37 | background: #161616; | ||
38 | } | ||
39 | |||
40 | #dropzone { | ||
41 | width: 100%; | ||
42 | height: 30vh; | ||
43 | background-color: #ebebeb; | ||
44 | |||
45 | display: flex; | ||
46 | align-items: center; | ||
47 | justify-content: center; | ||
48 | text-align: center; | ||
49 | |||
50 | cursor: pointer; | ||
51 | } | ||
52 | |||
53 | #dropzone p { | ||
54 | font-size: 0.85rem; | ||
55 | } | ||
56 | |||
57 | #files { | ||
58 | display: none; | ||
59 | } | ||
60 | |||
61 | .alert { | ||
62 | background-color: #e7a8a6; | ||
63 | padding: 0.8rem; | ||
64 | margin-bottom: 1rem; | ||
65 | } | ||
66 | |||
67 | td { | ||
68 | word-break: break-all; | ||
69 | } \ No newline at end of file | ||
diff --git a/src/server/public/css/vanilla.css b/src/server/public/css/vanilla.css deleted file mode 100644 index 37bc051a2..000000000 --- a/src/server/public/css/vanilla.css +++ /dev/null | |||
@@ -1,138 +0,0 @@ | |||
1 | /* Reset */ | ||
2 | html, body, div, span, applet, object, iframe, | ||
3 | h1, h2, h3, h4, h5, h6, p, blockquote, pre, | ||
4 | a, abbr, acronym, address, big, cite, code, | ||
5 | del, dfn, em, img, ins, kbd, q, s, samp, | ||
6 | small, strike, strong, sub, sup, tt, var, | ||
7 | b, u, i, center, | ||
8 | dl, dt, dd, ol, ul, li, | ||
9 | fieldset, form, label, legend, | ||
10 | table, caption, tbody, tfoot, thead, tr, th, td, | ||
11 | article, aside, canvas, details, embed, | ||
12 | figure, figcaption, footer, header, hgroup, | ||
13 | menu, nav, output, ruby, section, summary, | ||
14 | time, mark, audio, video { | ||
15 | margin: 0; | ||
16 | padding: 0; | ||
17 | border: 0; | ||
18 | font-size: 100%; | ||
19 | font: inherit; | ||
20 | vertical-align: baseline; | ||
21 | } | ||
22 | * { | ||
23 | box-sizing: border-box; | ||
24 | } | ||
25 | |||
26 | |||
27 | |||
28 | /* Variables */ | ||
29 | :root { | ||
30 | --desktop-font-size: 1.3rem/1.5; | ||
31 | --mobile-font-size: 1.1rem/1.4; | ||
32 | --text-color: #2d2d2d; | ||
33 | --link-color: blue; | ||
34 | --primary-color: lightsteelblue; | ||
35 | --secondary-color: aliceblue; | ||
36 | --tertiary-color: whitesmoke; | ||
37 | } | ||
38 | |||
39 | |||
40 | |||
41 | |||
42 | /* Typography */ | ||
43 | body { | ||
44 | color: var(--text-color); | ||
45 | padding: 3rem; | ||
46 | font: var(--desktop-font-size) -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto, Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji", "Segoe UI Symbol"; | ||
47 | } | ||
48 | |||
49 | h1,h2,h3,h4,h5,h6,p,blockquote,dl,img,figure { | ||
50 | margin: 2rem 0; | ||
51 | } | ||
52 | |||
53 | h1,h2,h3,h4,h5,h6 { font-weight: bold; } | ||
54 | h1 { font-size: 200%; } | ||
55 | h2 { font-size: 150%; } | ||
56 | h3 { font-size: 120%; } | ||
57 | h4,h5,h6 { font-size: 100%; } | ||
58 | h5, h6 { text-transform: uppercase; } | ||
59 | |||
60 | header h1 { border-bottom: 1px solid; } | ||
61 | |||
62 | p { margin: 2rem 0; } | ||
63 | |||
64 | a,a:visited { color: var(--link-color); } | ||
65 | |||
66 | strong, time, b { font-weight: bold; } | ||
67 | em, dfn, i { font-style: italic; } | ||
68 | sub { font-size: 60%; vertical-align: bottom; } | ||
69 | small { font-size: 80%; } | ||
70 | |||
71 | blockquote, q { | ||
72 | background: var(--secondary-color); | ||
73 | border-left: 10px solid var(--primary-color); | ||
74 | font-family: "Georgia", serif; | ||
75 | padding: 1rem; | ||
76 | } | ||
77 | blockquote p:first-child { margin-top: 0; } | ||
78 | cite { | ||
79 | font-family: "Georgia", serif; | ||
80 | font-style: italic; | ||
81 | font-weight: bold; | ||
82 | } | ||
83 | |||
84 | kbd,code,samp,pre,var { font-family: monospace; font-weight: bold; } | ||
85 | code, pre { | ||
86 | background: var(--tertiary-color); | ||
87 | padding: 0.5rem 1rem; | ||
88 | } | ||
89 | code pre , pre code { padding: 0; } | ||
90 | |||
91 | |||
92 | |||
93 | /* Elements */ | ||
94 | hr { | ||
95 | background: var(--text-color); | ||
96 | border: 0; | ||
97 | height: 1px; | ||
98 | margin: 4rem 0; | ||
99 | } | ||
100 | |||
101 | img { max-width: 100%; } | ||
102 | |||
103 | figure { | ||
104 | border: 1px solid var(--primary-color); | ||
105 | display: inline-block; | ||
106 | padding: 1rem; | ||
107 | width: auto; | ||
108 | } | ||
109 | figure img { margin: 0; } | ||
110 | figure figcaption { font-size: 80%; } | ||
111 | |||
112 | ul, ol { margin: 2rem 0; padding: 0 0 0 4rem; } | ||
113 | |||
114 | dl dd { padding-left: 2rem; } | ||
115 | |||
116 | table { | ||
117 | border: 1px solid var(--primary-color); | ||
118 | border-collapse: collapse; | ||
119 | table-layout: fixed; | ||
120 | width: 100%; | ||
121 | } | ||
122 | table caption { margin: 2rem 0; } | ||
123 | table thead { text-align: center; } | ||
124 | table tbody { text-align: right; } | ||
125 | table tr { border-bottom: 1px solid var(--primary-color); } | ||
126 | table tbody tr:nth-child(even) { background: var(--tertiary-color); } | ||
127 | table th { background: var(--secondary-color); font-weight: bold; } | ||
128 | table th, table td { padding: 1rem; } | ||
129 | table th:not(last-of-type), table td:not(last-of-type) { border-right: 1px solid var(--primary-color); } | ||
130 | |||
131 | |||
132 | |||
133 | /* Mobile Styling */ | ||
134 | @media screen and (max-width: 50rem) { | ||
135 | body { | ||
136 | font: var(--mobile-font-size) -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto, Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji", "Segoe UI Symbol" | ||
137 | } | ||
138 | } \ No newline at end of file | ||
diff --git a/src/server/resources/views/import.edge b/src/server/resources/views/import.edge deleted file mode 100644 index 561021a0c..000000000 --- a/src/server/resources/views/import.edge +++ /dev/null | |||
@@ -1,18 +0,0 @@ | |||
1 | @layout('layouts.main') | ||
2 | |||
3 | @section('content') | ||
4 | <h1>Import a Franz account</h1> | ||
5 | <p>Please login using your Franz account. We will import your services and workspaces.</p> | ||
6 | <form action="import" method="post"> | ||
7 | <label for="email">E-Mail address</label><br /> | ||
8 | <input type="email" name="email" placeholder="joe@example.com" required><br /> | ||
9 | |||
10 | <label for="password">Password</label><br /> | ||
11 | <input type="password" name="password" placeholder="********" required><br /> | ||
12 | |||
13 | <label for="server">API Server to import from</label><br /> | ||
14 | <input type="text" name="server" value="https://api.franzinfra.com" required><br /> | ||
15 | |||
16 | <button type="submit" id="submitbutton">Import Franz account</button> | ||
17 | </form> | ||
18 | @endsection | ||
diff --git a/src/server/resources/views/index.edge b/src/server/resources/views/index.edge deleted file mode 100644 index 3e0198a09..000000000 --- a/src/server/resources/views/index.edge +++ /dev/null | |||
@@ -1,32 +0,0 @@ | |||
1 | @layout('layouts.main') | ||
2 | |||
3 | @section('content') | ||
4 | <style> | ||
5 | ol, | ||
6 | p { | ||
7 | margin: 0.5rem 0; | ||
8 | } | ||
9 | |||
10 | </style> | ||
11 | <h1>Internal Ferdi Server</h1> | ||
12 | <p>You are accessing the local server instance of your Ferdi application. This server is used to enable Ferdi's "Use without an Account" feature.</p> | ||
13 | <p> | ||
14 | To use this server in your Ferdi client, <a href="ferdi://settings/app">open Ferdi's settings</a> and as the | ||
15 | <code>server</code>, enter <code id="server"></code> | ||
16 | </p> | ||
17 | <p> | ||
18 | Alternatively, you can <a href="/import">import your Franz account</a>. | ||
19 | </p> | ||
20 | |||
21 | <script> | ||
22 | // Get server URL for current location | ||
23 | let server = location.href.replace('/index.html', ''); | ||
24 | if (server[server.length - 1] == '/') { | ||
25 | server = server.substr(0, server.length - 1) | ||
26 | } | ||
27 | |||
28 | // Show on page | ||
29 | document.getElementById('server').innerText = server; | ||
30 | |||
31 | </script> | ||
32 | @endsection | ||
diff --git a/src/server/resources/views/layouts/main.edge b/src/server/resources/views/layouts/main.edge deleted file mode 100644 index 77af30327..000000000 --- a/src/server/resources/views/layouts/main.edge +++ /dev/null | |||
@@ -1,18 +0,0 @@ | |||
1 | <!DOCTYPE html> | ||
2 | <html lang="en"> | ||
3 | |||
4 | <head> | ||
5 | <meta charset="UTF-8"> | ||
6 | <meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
7 | <meta http-equiv="X-UA-Compatible" content="ie=edge"> | ||
8 | <title>ferdi-internal-server</title> | ||
9 | |||
10 | {{ style('css/vanilla') }} | ||
11 | {{ style('css/main') }} | ||
12 | </head> | ||
13 | |||
14 | <body> | ||
15 | @!section('content') | ||
16 | </body> | ||
17 | |||
18 | </html> | ||
diff --git a/src/server/start.js b/src/server/start.js deleted file mode 100644 index 34b2cb5fa..000000000 --- a/src/server/start.js +++ /dev/null | |||
@@ -1,41 +0,0 @@ | |||
1 | |||
2 | /* | ||
3 | |-------------------------------------------------------------------------- | ||
4 | | Http server | ||
5 | |-------------------------------------------------------------------------- | ||
6 | | | ||
7 | | This file bootstraps Adonisjs to start the HTTP server. You are free to | ||
8 | | customize the process of booting the http server. | ||
9 | | | ||
10 | | """ Loading ace commands """ | ||
11 | | At times you may want to load ace commands when starting the HTTP server. | ||
12 | | Same can be done by chaining `loadCommands()` method after | ||
13 | | | ||
14 | | """ Preloading files """ | ||
15 | | Also you can preload files by calling `preLoad('path/to/file')` method. | ||
16 | | Make sure to pass a relative path from the project root. | ||
17 | */ | ||
18 | const path = require('path'); | ||
19 | const fs = require('fs-extra'); | ||
20 | |||
21 | process.env.ENV_PATH = path.join(__dirname, 'env.ini'); | ||
22 | |||
23 | const { Ignitor } = require('@adonisjs/ignitor'); | ||
24 | const fold = require('@adonisjs/fold'); | ||
25 | |||
26 | module.exports = (dbPath, port) => { | ||
27 | if (!fs.existsSync(dbPath)) { | ||
28 | fs.copySync( | ||
29 | path.join(__dirname, 'database', 'template.sqlite'), | ||
30 | dbPath, | ||
31 | ); | ||
32 | } | ||
33 | |||
34 | process.env.DB_PATH = dbPath; | ||
35 | process.env.PORT = port; | ||
36 | |||
37 | new Ignitor(fold) | ||
38 | .appRoot(__dirname) | ||
39 | .fireHttpServer() | ||
40 | .catch(console.error); // eslint-disable-line no-console | ||
41 | }; | ||
diff --git a/src/server/start/app.js b/src/server/start/app.js deleted file mode 100644 index a29ca6594..000000000 --- a/src/server/start/app.js +++ /dev/null | |||
@@ -1,62 +0,0 @@ | |||
1 | |||
2 | /* | ||
3 | |-------------------------------------------------------------------------- | ||
4 | | Providers | ||
5 | |-------------------------------------------------------------------------- | ||
6 | | | ||
7 | | Providers are building blocks for your Adonis app. Anytime you install | ||
8 | | a new Adonis specific package, chances are you will register the | ||
9 | | provider here. | ||
10 | | | ||
11 | */ | ||
12 | const providers = [ | ||
13 | '@adonisjs/framework/providers/AppProvider', | ||
14 | '@adonisjs/bodyparser/providers/BodyParserProvider', | ||
15 | '@adonisjs/cors/providers/CorsProvider', | ||
16 | '@adonisjs/lucid/providers/LucidProvider', | ||
17 | '@adonisjs/drive/providers/DriveProvider', | ||
18 | '@adonisjs/validator/providers/ValidatorProvider', | ||
19 | '@adonisjs/framework/providers/ViewProvider', | ||
20 | '@adonisjs/shield/providers/ShieldProvider', | ||
21 | ]; | ||
22 | |||
23 | /* | ||
24 | |-------------------------------------------------------------------------- | ||
25 | | Ace Providers | ||
26 | |-------------------------------------------------------------------------- | ||
27 | | | ||
28 | | Ace providers are required only when running ace commands. For example | ||
29 | | Providers for migrations, tests etc. | ||
30 | | | ||
31 | */ | ||
32 | const aceProviders = [ | ||
33 | '@adonisjs/lucid/providers/MigrationsProvider', | ||
34 | ]; | ||
35 | |||
36 | /* | ||
37 | |-------------------------------------------------------------------------- | ||
38 | | Aliases | ||
39 | |-------------------------------------------------------------------------- | ||
40 | | | ||
41 | | Aliases are short unique names for IoC container bindings. You are free | ||
42 | | to create your own aliases. | ||
43 | | | ||
44 | | For example: | ||
45 | | { Route: 'Adonis/Src/Route' } | ||
46 | | | ||
47 | */ | ||
48 | const aliases = {}; | ||
49 | |||
50 | /* | ||
51 | |-------------------------------------------------------------------------- | ||
52 | | Commands | ||
53 | |-------------------------------------------------------------------------- | ||
54 | | | ||
55 | | Here you store ace commands for your package | ||
56 | | | ||
57 | */ | ||
58 | const commands = []; | ||
59 | |||
60 | module.exports = { | ||
61 | providers, aceProviders, aliases, commands, | ||
62 | }; | ||
diff --git a/src/server/start/kernel.js b/src/server/start/kernel.js deleted file mode 100644 index 54fe1f35d..000000000 --- a/src/server/start/kernel.js +++ /dev/null | |||
@@ -1,56 +0,0 @@ | |||
1 | |||
2 | /** @type {import('@adonisjs/framework/src/Server')} */ | ||
3 | const Server = use('Server'); | ||
4 | |||
5 | /* | ||
6 | |-------------------------------------------------------------------------- | ||
7 | | Global Middleware | ||
8 | |-------------------------------------------------------------------------- | ||
9 | | | ||
10 | | Global middleware are executed on each http request only when the routes | ||
11 | | match. | ||
12 | | | ||
13 | */ | ||
14 | const globalMiddleware = [ | ||
15 | 'Adonis/Middleware/BodyParser', | ||
16 | 'App/Middleware/ConvertEmptyStringsToNull', | ||
17 | ]; | ||
18 | |||
19 | /* | ||
20 | |-------------------------------------------------------------------------- | ||
21 | | Named Middleware | ||
22 | |-------------------------------------------------------------------------- | ||
23 | | | ||
24 | | Named middleware is key/value object to conditionally add middleware on | ||
25 | | specific routes or group of routes. | ||
26 | | | ||
27 | | // define | ||
28 | | { | ||
29 | | auth: 'Adonis/Middleware/Auth' | ||
30 | | } | ||
31 | | | ||
32 | | // use | ||
33 | | Route.get().middleware('auth') | ||
34 | | | ||
35 | */ | ||
36 | const namedMiddleware = { | ||
37 | }; | ||
38 | |||
39 | /* | ||
40 | |-------------------------------------------------------------------------- | ||
41 | | Server Middleware | ||
42 | |-------------------------------------------------------------------------- | ||
43 | | | ||
44 | | Server level middleware are executed even when route for a given URL is | ||
45 | | not registered. Features like `static assets` and `cors` needs better | ||
46 | | control over request lifecycle. | ||
47 | | | ||
48 | */ | ||
49 | const serverMiddleware = [ | ||
50 | 'Adonis/Middleware/Static', | ||
51 | ]; | ||
52 | |||
53 | Server | ||
54 | .registerGlobal(globalMiddleware) | ||
55 | .registerNamed(namedMiddleware) | ||
56 | .use(serverMiddleware); | ||
diff --git a/src/server/start/routes.js b/src/server/start/routes.js deleted file mode 100644 index 333a5ba06..000000000 --- a/src/server/start/routes.js +++ /dev/null | |||
@@ -1,74 +0,0 @@ | |||
1 | |||
2 | /* | ||
3 | |-------------------------------------------------------------------------- | ||
4 | | Routes | ||
5 | |-------------------------------------------------------------------------- | ||
6 | | | ||
7 | */ | ||
8 | |||
9 | /** @type {typeof import('@adonisjs/framework/src/Route/Manager')} */ | ||
10 | const Route = use('Route'); | ||
11 | |||
12 | const OnlyAllowFerdi = async ({ request, response }, next) => { | ||
13 | const user = request.header('User-Agent'); | ||
14 | if (!/Ferdi\/\d(\.\d){2}/g.test(user)) { | ||
15 | return response.status(403).redirect('/'); | ||
16 | } | ||
17 | |||
18 | await next(); | ||
19 | return true; | ||
20 | }; | ||
21 | |||
22 | // Health: Returning if all systems function correctly | ||
23 | Route.get('health', ({ | ||
24 | response, | ||
25 | }) => response.send({ | ||
26 | api: 'success', | ||
27 | db: 'success', | ||
28 | })).middleware(OnlyAllowFerdi); | ||
29 | |||
30 | // API is grouped under '/v1/' route | ||
31 | Route.group(() => { | ||
32 | // User authentification | ||
33 | Route.post('auth/signup', 'UserController.signup'); | ||
34 | Route.post('auth/login', 'UserController.login'); | ||
35 | |||
36 | // User info | ||
37 | Route.get('me', 'UserController.me'); | ||
38 | |||
39 | // Service info | ||
40 | Route.post('service', 'ServiceController.create'); | ||
41 | Route.put('service/:id', 'ServiceController.edit'); | ||
42 | Route.delete('service/:id', 'ServiceController.delete'); | ||
43 | Route.get('me/services', 'ServiceController.list'); | ||
44 | Route.put('service/reorder', 'ServiceController.reorder'); | ||
45 | Route.get('recipe', 'ServiceController.list'); | ||
46 | Route.post('recipes/update', 'ServiceController.update'); | ||
47 | |||
48 | // Recipe store | ||
49 | Route.get('recipes', 'RecipeController.list'); | ||
50 | Route.get('recipes/download/:recipe', 'RecipeController.download'); | ||
51 | Route.get('recipes/search', 'RecipeController.search'); | ||
52 | Route.get('recipes/popular', 'StaticController.popularRecipes'); | ||
53 | Route.get('recipes/update', 'StaticController.emptyArray'); | ||
54 | |||
55 | // Workspaces | ||
56 | Route.put('workspace/:id', 'WorkspaceController.edit'); | ||
57 | Route.delete('workspace/:id', 'WorkspaceController.delete'); | ||
58 | Route.post('workspace', 'WorkspaceController.create'); | ||
59 | Route.get('workspace', 'WorkspaceController.list'); | ||
60 | |||
61 | // Static responses | ||
62 | Route.get('features', 'StaticController.features'); | ||
63 | Route.get('services', 'StaticController.emptyArray'); | ||
64 | Route.get('news', 'StaticController.emptyArray'); | ||
65 | Route.get('payment/plans', 'StaticController.plans'); | ||
66 | Route.get('announcements/:version', 'StaticController.announcement'); | ||
67 | }).prefix('v1').middleware(OnlyAllowFerdi); | ||
68 | |||
69 | // Franz account import | ||
70 | Route.post('import', 'UserController.import'); | ||
71 | Route.get('import', ({ view }) => view.render('import')); | ||
72 | |||
73 | // Index | ||
74 | Route.get('/', ({ view }) => view.render('index')); | ||