diff options
author | vantezzen <hello@vantezzen.io> | 2019-10-14 17:42:24 +0200 |
---|---|---|
committer | vantezzen <hello@vantezzen.io> | 2019-10-14 17:42:24 +0200 |
commit | 37c2448778e6595dc09291e46c4ba7dca89eb20d (patch) | |
tree | 5a389311df5cb1dc813c93cde62d633c1bd99bb0 /src | |
parent | Add local server (diff) | |
download | ferdium-app-37c2448778e6595dc09291e46c4ba7dca89eb20d.tar.gz ferdium-app-37c2448778e6595dc09291e46c4ba7dca89eb20d.tar.zst ferdium-app-37c2448778e6595dc09291e46c4ba7dca89eb20d.zip |
Develop internal server
Diffstat (limited to 'src')
-rw-r--r-- | src/server/README.md | 35 | ||||
-rw-r--r-- | src/server/app/Controllers/Http/DashboardController.js | 38 | ||||
-rw-r--r-- | src/server/app/Controllers/Http/RecipeController.js | 91 | ||||
-rw-r--r-- | src/server/app/Exceptions/Handler.js | 2 | ||||
-rw-r--r-- | src/server/app/Models/User.js | 2 | ||||
-rw-r--r-- | src/server/database/ferdi.sqlite | bin | 36864 -> 0 bytes | |||
-rw-r--r-- | src/server/logo.png | bin | 340668 -> 298671 bytes | |||
-rw-r--r-- | src/server/public/js/new.js | 24 | ||||
-rw-r--r-- | src/server/resources/views/import.edge (renamed from src/server/resources/views/others/import.edge) | 6 | ||||
-rw-r--r-- | src/server/resources/views/index.edge (renamed from src/server/resources/views/others/index.edge) | 12 | ||||
-rw-r--r-- | src/server/resources/views/others/new.edge | 40 | ||||
-rw-r--r-- | src/server/start/routes.js | 13 |
12 files changed, 11 insertions, 252 deletions
diff --git a/src/server/README.md b/src/server/README.md index 833d9643e..0074f2314 100644 --- a/src/server/README.md +++ b/src/server/README.md | |||
@@ -5,23 +5,8 @@ | |||
5 | # ferdi-internal-server | 5 | # ferdi-internal-server |
6 | Internal Ferdi Server used for storing settings without logging into an external server. | 6 | Internal Ferdi Server used for storing settings without logging into an external server. |
7 | 7 | ||
8 | npm i @adonisjs/ace @adonisjs/auth @adonisjs/bodyparser @adonisjs/cors @adonisjs/drive @adonisjs/fold @adonisjs/framework @adonisjs/ignitor @adonisjs/lucid @adonisjs/session @adonisjs/shield @adonisjs/validator atob btoa fs-extra node-fetch sqlite3 uuid targz | ||
9 | |||
10 | ### Manual setup | ||
11 | 1. Clone this repository | ||
12 | 2. Install the [AdonisJS CLI](https://adonisjs.com/) | ||
13 | 3. Run the database migrations with | ||
14 | ```js | ||
15 | adonis migration:run | ||
16 | ``` | ||
17 | 4. Start the server with | ||
18 | ```js | ||
19 | adonis serve --dev | ||
20 | ``` | ||
21 | |||
22 | ## Configuration | 8 | ## Configuration |
23 | franz-server's configuration is saved inside the `.env` file. Besides AdonisJS's settings, ferdi-server has the following custom settings: | 9 | franz-server's configuration is saved inside the `env.ini` file. Besides AdonisJS's settings, ferdi-internal-server has the following custom settings: |
24 | - `IS_CREATION_ENABLED` (`true` or `false`, default: `true`): Whether to enable the [creation of custom recipes](#creating-and-using-custom-recipes) | ||
25 | - `CONNECT_WITH_FRANZ` (`true` or `false`, default: `true`): Whether to enable connections to the Franz server. By enabling this option, ferdi-server can: | 10 | - `CONNECT_WITH_FRANZ` (`true` or `false`, default: `true`): Whether to enable connections to the Franz server. By enabling this option, ferdi-server can: |
26 | - Show the full Franz recipe library instead of only custom recipes | 11 | - Show the full Franz recipe library instead of only custom recipes |
27 | - Import Franz accounts | 12 | - Import Franz accounts |
@@ -30,21 +15,3 @@ franz-server's configuration is saved inside the `.env` file. Besides AdonisJS's | |||
30 | ferdi-server allows you to import your full Franz account, including all its settings. | 15 | ferdi-server allows you to import your full Franz account, including all its settings. |
31 | 16 | ||
32 | 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. | 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. |
33 | |||
34 | ## Creating and using custom recipes | ||
35 | ferdi-server allows to extends the Franz recipe catalogue with custom Ferdi recipes. | ||
36 | |||
37 | For documentation on how to create a recipe, please visit [the official guide by Franz](https://github.com/meetfranz/plugins/blob/master/docs/integration.md). | ||
38 | |||
39 | To add your recipe to ferdi-server, open `http://localhost:45569/new` in your browser. You can now define the following settings: | ||
40 | - `Author`: Author who created the recipe | ||
41 | - `Name`: Name for your new service. Can contain spaces and unicode characters | ||
42 | - `Service ID`: Unique ID for this recipe. Does not contain spaces or special characters (e.g. `google-drive`) | ||
43 | - `Link to PNG/SVG image`: Direct link to a 1024x1024 PNG image and SVG that is used as a logo inside the store. Please use jsDelivr when using a file uploaded to GitHub as raw.githubusercontent files won't load | ||
44 | - `Recipe files`: Recipe files that you created using the [Franz recipe creation guide](https://github.com/meetfranz/plugins/blob/master/docs/integration.md). Please do *not* package your files beforehand - upload the raw files (you can drag and drop multiple files). ferdi-server will automatically package and store the recipe in the right format. Please also do not drag and drop or select the whole folder, select the individual files. | ||
45 | |||
46 | ### Listing custom recipes | ||
47 | Inside Ferdi, searching for `ferdi:custom` will list all your custom recipes. | ||
48 | |||
49 | ## License | ||
50 | ferdi-server is licensed under the MIT License | ||
diff --git a/src/server/app/Controllers/Http/DashboardController.js b/src/server/app/Controllers/Http/DashboardController.js deleted file mode 100644 index 69af16227..000000000 --- a/src/server/app/Controllers/Http/DashboardController.js +++ /dev/null | |||
@@ -1,38 +0,0 @@ | |||
1 | class DashboardController { | ||
2 | async data({ | ||
3 | auth, | ||
4 | view, | ||
5 | }) { | ||
6 | const general = auth.user; | ||
7 | const services = (await auth.user.services().fetch()).toJSON(); | ||
8 | const workspaces = (await auth.user.workspaces().fetch()).toJSON(); | ||
9 | |||
10 | return view.render('dashboard.data', { | ||
11 | username: general.username, | ||
12 | mail: general.email, | ||
13 | created: general.created_at, | ||
14 | updated: general.updated_at, | ||
15 | services, | ||
16 | workspaces, | ||
17 | }); | ||
18 | } | ||
19 | |||
20 | logout({ | ||
21 | auth, | ||
22 | response, | ||
23 | }) { | ||
24 | auth.authenticator('session').logout(); | ||
25 | return response.redirect('/user/login'); | ||
26 | } | ||
27 | |||
28 | delete({ | ||
29 | auth, | ||
30 | response, | ||
31 | }) { | ||
32 | auth.user.delete(); | ||
33 | auth.authenticator('session').logout(); | ||
34 | return response.redirect('/user/login'); | ||
35 | } | ||
36 | } | ||
37 | |||
38 | module.exports = DashboardController; | ||
diff --git a/src/server/app/Controllers/Http/RecipeController.js b/src/server/app/Controllers/Http/RecipeController.js index 5ed21122a..c887ea00e 100644 --- a/src/server/app/Controllers/Http/RecipeController.js +++ b/src/server/app/Controllers/Http/RecipeController.js | |||
@@ -8,29 +8,15 @@ const { | |||
8 | const Env = use('Env'); | 8 | const Env = use('Env'); |
9 | 9 | ||
10 | const fetch = require('node-fetch'); | 10 | const fetch = require('node-fetch'); |
11 | const targz = require('targz'); | ||
12 | const path = require('path'); | 11 | const path = require('path'); |
13 | const fs = require('fs-extra'); | 12 | const fs = require('fs-extra'); |
14 | 13 | ||
15 | const compress = (src, dest) => new Promise((resolve, reject) => { | ||
16 | targz.compress({ | ||
17 | src, | ||
18 | dest, | ||
19 | }, (err) => { | ||
20 | if (err) { | ||
21 | reject(err); | ||
22 | } else { | ||
23 | resolve(dest); | ||
24 | } | ||
25 | }); | ||
26 | }); | ||
27 | |||
28 | class RecipeController { | 14 | class RecipeController { |
29 | // List official and custom recipes | 15 | // List official and custom recipes |
30 | async list({ | 16 | async list({ |
31 | response, | 17 | response, |
32 | }) { | 18 | }) { |
33 | const officialRecipes = JSON.parse(await (await fetch('https://api.franzinfra.com/v1/recipes')).text()); | 19 | const officialRecipes = JSON.parse(await (await fetch('https://api.getferdi.com/v1/recipes')).text()); |
34 | const customRecipesArray = (await Recipe.all()).rows; | 20 | const customRecipesArray = (await Recipe.all()).rows; |
35 | const customRecipes = customRecipesArray.map(recipe => ({ | 21 | const customRecipes = customRecipesArray.map(recipe => ({ |
36 | id: recipe.recipeId, | 22 | id: recipe.recipeId, |
@@ -46,77 +32,6 @@ class RecipeController { | |||
46 | return response.send(recipes); | 32 | return response.send(recipes); |
47 | } | 33 | } |
48 | 34 | ||
49 | // Create a new recipe using the new.html page | ||
50 | async create({ | ||
51 | request, | ||
52 | response, | ||
53 | }) { | ||
54 | // Check if recipe creation is enabled | ||
55 | if (Env.get('IS_CREATION_ENABLED') == 'false') { // eslint-disable-line eqeqeq | ||
56 | return response.send('This server doesn\'t allow the creation of new recipes.'); | ||
57 | } | ||
58 | |||
59 | // Validate user input | ||
60 | const validation = await validateAll(request.all(), { | ||
61 | name: 'required|string', | ||
62 | id: 'required|unique:recipes,recipeId', | ||
63 | author: 'required|accepted', | ||
64 | png: 'required|url', | ||
65 | svg: 'required|url', | ||
66 | }); | ||
67 | if (validation.fails()) { | ||
68 | return response.status(401).send({ | ||
69 | message: 'Invalid POST arguments', | ||
70 | messages: validation.messages(), | ||
71 | status: 401, | ||
72 | }); | ||
73 | } | ||
74 | |||
75 | const data = request.all(); | ||
76 | |||
77 | if (!data.id) { | ||
78 | return response.send('Please provide an ID'); | ||
79 | } | ||
80 | |||
81 | // Check for invalid characters | ||
82 | if (/\.{1,}/.test(data.id) || /\/{1,}/.test(data.id)) { | ||
83 | return response.send('Invalid recipe name. Your recipe name may not contain "." or "/"'); | ||
84 | } | ||
85 | |||
86 | // Clear temporary recipe folder | ||
87 | await fs.emptyDir(Helpers.tmpPath('recipe')); | ||
88 | |||
89 | // Move uploaded files to temporary path | ||
90 | const files = request.file('files'); | ||
91 | await files.moveAll(Helpers.tmpPath('recipe')); | ||
92 | |||
93 | // Compress files to .tar.gz file | ||
94 | const source = Helpers.tmpPath('recipe'); | ||
95 | const destination = path.join(Helpers.appRoot(), `/recipes/${data.id}.tar.gz`); | ||
96 | |||
97 | compress( | ||
98 | source, | ||
99 | destination, | ||
100 | ); | ||
101 | |||
102 | // Create recipe in db | ||
103 | await Recipe.create({ | ||
104 | name: data.name, | ||
105 | recipeId: data.id, | ||
106 | data: JSON.stringify({ | ||
107 | author: data.author, | ||
108 | featured: false, | ||
109 | version: '1.0.0', | ||
110 | icons: { | ||
111 | png: data.png, | ||
112 | svg: data.svg, | ||
113 | }, | ||
114 | }), | ||
115 | }); | ||
116 | |||
117 | return response.send('Created new recipe'); | ||
118 | } | ||
119 | |||
120 | // Search official and custom recipes | 35 | // Search official and custom recipes |
121 | async search({ | 36 | async search({ |
122 | request, | 37 | request, |
@@ -149,7 +64,7 @@ class RecipeController { | |||
149 | } else { | 64 | } else { |
150 | let remoteResults = []; | 65 | let remoteResults = []; |
151 | if (Env.get('CONNECT_WITH_FRANZ') == 'true') { // eslint-disable-line eqeqeq | 66 | if (Env.get('CONNECT_WITH_FRANZ') == 'true') { // eslint-disable-line eqeqeq |
152 | remoteResults = JSON.parse(await (await fetch(`https://api.franzinfra.com/v1/recipes/search?needle=${encodeURIComponent(needle)}`)).text()); | 67 | remoteResults = JSON.parse(await (await fetch(`https://api.getferdi.com/v1/recipes/search?needle=${encodeURIComponent(needle)}`)).text()); |
153 | } | 68 | } |
154 | const localResultsArray = (await Recipe.query().where('name', 'LIKE', `%${needle}%`).fetch()).toJSON(); | 69 | const localResultsArray = (await Recipe.query().where('name', 'LIKE', `%${needle}%`).fetch()).toJSON(); |
155 | const localResults = localResultsArray.map(recipe => ({ | 70 | const localResults = localResultsArray.map(recipe => ({ |
@@ -195,7 +110,7 @@ class RecipeController { | |||
195 | if (await Drive.exists(`${service}.tar.gz`)) { | 110 | if (await Drive.exists(`${service}.tar.gz`)) { |
196 | return response.send(await Drive.get(`${service}.tar.gz`)); | 111 | return response.send(await Drive.get(`${service}.tar.gz`)); |
197 | } if (Env.get('CONNECT_WITH_FRANZ') == 'true') { // eslint-disable-line eqeqeq | 112 | } if (Env.get('CONNECT_WITH_FRANZ') == 'true') { // eslint-disable-line eqeqeq |
198 | return response.redirect(`https://api.franzinfra.com/v1/recipes/download/${service}`); | 113 | return response.redirect(`https://api.getferdi.com/v1/recipes/download/${service}`); |
199 | } | 114 | } |
200 | return response.status(400).send({ | 115 | return response.status(400).send({ |
201 | message: 'Recipe not found', | 116 | message: 'Recipe not found', |
diff --git a/src/server/app/Exceptions/Handler.js b/src/server/app/Exceptions/Handler.js index cb9e10bbe..e8d2d2ee2 100644 --- a/src/server/app/Exceptions/Handler.js +++ b/src/server/app/Exceptions/Handler.js | |||
@@ -22,8 +22,6 @@ class ExceptionHandler extends BaseExceptionHandler { | |||
22 | async handle(error, { response }) { | 22 | async handle(error, { response }) { |
23 | if (error.name === 'ValidationException') { | 23 | if (error.name === 'ValidationException') { |
24 | return response.status(400).send('Invalid arguments'); | 24 | return response.status(400).send('Invalid arguments'); |
25 | } if (error.name === 'InvalidSessionException') { | ||
26 | return response.status(401).redirect('/user/login'); | ||
27 | } | 25 | } |
28 | 26 | ||
29 | return response.status(error.status).send(error.message); | 27 | return response.status(error.status).send(error.message); |
diff --git a/src/server/app/Models/User.js b/src/server/app/Models/User.js index 9783cbe45..907710d8d 100644 --- a/src/server/app/Models/User.js +++ b/src/server/app/Models/User.js | |||
@@ -1,4 +1,4 @@ | |||
1 | 1 | // File is required by AdonisJS but not used by the server | |
2 | /** @type {typeof import('@adonisjs/lucid/src/Lucid/Model')} */ | 2 | /** @type {typeof import('@adonisjs/lucid/src/Lucid/Model')} */ |
3 | const Model = use('Model'); | 3 | const Model = use('Model'); |
4 | 4 | ||
diff --git a/src/server/database/ferdi.sqlite b/src/server/database/ferdi.sqlite deleted file mode 100644 index db5425ee6..000000000 --- a/src/server/database/ferdi.sqlite +++ /dev/null | |||
Binary files differ | |||
diff --git a/src/server/logo.png b/src/server/logo.png index 587e0b86e..4145a077a 100644 --- a/src/server/logo.png +++ b/src/server/logo.png | |||
Binary files differ | |||
diff --git a/src/server/public/js/new.js b/src/server/public/js/new.js deleted file mode 100644 index beaa36da6..000000000 --- a/src/server/public/js/new.js +++ /dev/null | |||
@@ -1,24 +0,0 @@ | |||
1 | /* eslint-env browser */ | ||
2 | const elDrop = document.getElementById('dropzone'); | ||
3 | const submitBtn = document.getElementById('submitbutton'); | ||
4 | const fileInput = document.getElementById('files'); | ||
5 | |||
6 | elDrop.addEventListener('dragover', (event) => { | ||
7 | event.preventDefault(); | ||
8 | }); | ||
9 | |||
10 | elDrop.addEventListener('drop', async (event) => { | ||
11 | event.preventDefault(); | ||
12 | |||
13 | submitBtn.disabled = true; | ||
14 | |||
15 | fileInput.files = event.dataTransfer.files; | ||
16 | |||
17 | elDrop.innerText = `✓ ${fileInput.files.length} files selected`; | ||
18 | elDrop.style.height = 'inherit'; | ||
19 | |||
20 | submitBtn.disabled = false; | ||
21 | }); | ||
22 | elDrop.addEventListener('click', () => { | ||
23 | fileInput.click(); | ||
24 | }); | ||
diff --git a/src/server/resources/views/others/import.edge b/src/server/resources/views/import.edge index b890bbb2a..f7b52b179 100644 --- a/src/server/resources/views/others/import.edge +++ b/src/server/resources/views/import.edge | |||
@@ -2,7 +2,7 @@ | |||
2 | 2 | ||
3 | @section('content') | 3 | @section('content') |
4 | <h1>Import a Franz account</h1> | 4 | <h1>Import a Franz account</h1> |
5 | <p>Please login using your Franz account. We will create a new Ferdi account with the same credentials.</p> | 5 | <p>Please login using your Franz account. We will import your services and workspaces.</p> |
6 | <form action="import" method="post"> | 6 | <form action="import" method="post"> |
7 | <label for="email">E-Mail address</label><br /> | 7 | <label for="email">E-Mail address</label><br /> |
8 | <input type="email" name="email" placeholder="joe@example.com" required><br /> | 8 | <input type="email" name="email" placeholder="joe@example.com" required><br /> |
@@ -11,9 +11,5 @@ | |||
11 | <input type="password" name="password" placeholder="********" required><br /> | 11 | <input type="password" name="password" placeholder="********" required><br /> |
12 | 12 | ||
13 | <button type="submit" id="submitbutton">Import Franz account</button> | 13 | <button type="submit" id="submitbutton">Import Franz account</button> |
14 | <small> | ||
15 | By importing your Franz account, you accept the <a href="/terms">Terms of service</a> and <a href="/privacy">Privacy | ||
16 | policy</a> | ||
17 | </small> | ||
18 | </form> | 14 | </form> |
19 | @endsection | 15 | @endsection |
diff --git a/src/server/resources/views/others/index.edge b/src/server/resources/views/index.edge index c594d3142..3e0198a09 100644 --- a/src/server/resources/views/others/index.edge +++ b/src/server/resources/views/index.edge | |||
@@ -8,22 +8,16 @@ | |||
8 | } | 8 | } |
9 | 9 | ||
10 | </style> | 10 | </style> |
11 | <h1>ferdi-server</h1> | 11 | <h1>Internal Ferdi Server</h1> |
12 | <p>You are accessing a custom <a href="https://github.com/kytwb/ferdi">Ferdi</a> server.</p> | 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> | 13 | <p> |
14 | To use this server in your Ferdi client, <a href="ferdi://settings/app">open Ferdi's settings</a> and as the | 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> | 15 | <code>server</code>, enter <code id="server"></code> |
16 | </p> | 16 | </p> |
17 | <p> | 17 | <p> |
18 | Alternatively, you can manage your account in the <a href="/user/account">account dashboard</a>. | 18 | Alternatively, you can <a href="/import">import your Franz account</a>. |
19 | </p> | 19 | </p> |
20 | 20 | ||
21 | <br /> | ||
22 | <small> | ||
23 | <a href="https://github.com/vantezzen/ferdi-server">ferdi-server</a> is a project by <a | ||
24 | href="https://vantezzen.io">vantezzen</a>. | ||
25 | </small> | ||
26 | |||
27 | <script> | 21 | <script> |
28 | // Get server URL for current location | 22 | // Get server URL for current location |
29 | let server = location.href.replace('/index.html', ''); | 23 | let server = location.href.replace('/index.html', ''); |
diff --git a/src/server/resources/views/others/new.edge b/src/server/resources/views/others/new.edge deleted file mode 100644 index 1b54558fc..000000000 --- a/src/server/resources/views/others/new.edge +++ /dev/null | |||
@@ -1,40 +0,0 @@ | |||
1 | @layout('layouts.main') | ||
2 | |||
3 | @section('content') | ||
4 | <h1>Create a new recipe</h1> | ||
5 | <p>Please create a recipe using <a href="https://github.com/meetfranz/plugins/blob/master/docs/integration.md">the | ||
6 | official Franz guide</a>, then publish it here.</p> | ||
7 | <form action="new" method="post" enctype="multipart/form-data"> | ||
8 | <label for="author">Author</label><br /> | ||
9 | <input type="text" name="author" placeholder="Jon Doe" required><br /> | ||
10 | |||
11 | <label for="name">Name</label><br /> | ||
12 | <input type="text" name="name" placeholder="Sample Service" required><br /> | ||
13 | |||
14 | <label for="id">Service ID</label><br /> | ||
15 | <input type="text" name="id" placeholder="sample-service" required><br /> | ||
16 | |||
17 | <label for="png">Link to PNG image*</label><br /> | ||
18 | <input type="text" name="png" placeholder="https://.../logo.png" required><br /> | ||
19 | |||
20 | <label for="svg">Link to SVG image*</label><br /> | ||
21 | <input type="text" name="svg" placeholder="https://.../logo.svg" required><br /> | ||
22 | *These images must be publicly availible and have CORS enabled in order to work.<br /><br /> | ||
23 | |||
24 | <label for="package">Recipe files</label><br /> | ||
25 | <div id="dropzone" effectAllowed="move"> | ||
26 | <div> | ||
27 | Drop recipe files here<br />or click here to select files | ||
28 | <p> | ||
29 | Drag and drop your recipe files into this area.<br /> | ||
30 | Please do not select the folder that contains the files but rather the files itself. | ||
31 | </p> | ||
32 | </div> | ||
33 | </div> | ||
34 | <input type="file" name="files[]" id="files" value="" multiple required><br /><br /> | ||
35 | |||
36 | <button type="submit" id="submitbutton">Create recipe</button> | ||
37 | </form> | ||
38 | |||
39 | <script src="js/new.js"></script> | ||
40 | @endsection | ||
diff --git a/src/server/start/routes.js b/src/server/start/routes.js index f3896bfa3..ec2e79a7c 100644 --- a/src/server/start/routes.js +++ b/src/server/start/routes.js | |||
@@ -57,18 +57,9 @@ Route.group(() => { | |||
57 | Route.get('announcements/:version', 'StaticController.announcement'); | 57 | Route.get('announcements/:version', 'StaticController.announcement'); |
58 | }).prefix('v1'); | 58 | }).prefix('v1'); |
59 | 59 | ||
60 | // Recipe creation | ||
61 | Route.post('new', 'RecipeController.create'); | ||
62 | Route.get('new', ({ response, view }) => { | ||
63 | if (Env.get('IS_CREATION_ENABLED') == 'false') { // eslint-disable-line eqeqeq | ||
64 | return response.send('This server doesn\'t allow the creation of new recipes.\n\nIf you are the server owner, please set IS_CREATION_ENABLED to true to enable recipe creation.'); | ||
65 | } | ||
66 | return view.render('others.new'); | ||
67 | }); | ||
68 | |||
69 | // Franz account import | 60 | // Franz account import |
70 | Route.post('import', 'UserController.import'); | 61 | Route.post('import', 'UserController.import'); |
71 | Route.get('import', ({ view }) => view.render('others.import')); | 62 | Route.get('import', ({ view }) => view.render('import')); |
72 | 63 | ||
73 | // Index | 64 | // Index |
74 | Route.get('/', ({ view }) => view.render('others.index')); | 65 | Route.get('/', ({ view }) => view.render('index')); |