From 419933f6505caf4c5e685f8436b1ff735185e55a Mon Sep 17 00:00:00 2001 From: Vijay Raghavan Aravamudhan Date: Sun, 1 Aug 2021 11:07:57 +0000 Subject: Moved 'internal-server' into a sub-folder as opposed to a git submodule. (#1715) * Ignored tests in 'internal-server' folder since there are none. * Linter fixes --- src/internal-server/start/app.js | 61 +++++++++++++++++++++++++ src/internal-server/start/kernel.js | 55 +++++++++++++++++++++++ src/internal-server/start/migrate.js | 44 ++++++++++++++++++ src/internal-server/start/routes.js | 87 ++++++++++++++++++++++++++++++++++++ 4 files changed, 247 insertions(+) create mode 100644 src/internal-server/start/app.js create mode 100644 src/internal-server/start/kernel.js create mode 100644 src/internal-server/start/migrate.js create mode 100644 src/internal-server/start/routes.js (limited to 'src/internal-server/start') diff --git a/src/internal-server/start/app.js b/src/internal-server/start/app.js new file mode 100644 index 000000000..8b1a49f57 --- /dev/null +++ b/src/internal-server/start/app.js @@ -0,0 +1,61 @@ +/* +|-------------------------------------------------------------------------- +| Providers +|-------------------------------------------------------------------------- +| +| Providers are building blocks for your Adonis app. Anytime you install +| a new Adonis specific package, chances are you will register the +| provider here. +| +*/ +const providers = [ + '@adonisjs/framework/providers/AppProvider', + '@adonisjs/bodyparser/providers/BodyParserProvider', + '@adonisjs/cors/providers/CorsProvider', + '@adonisjs/lucid/providers/LucidProvider', + '@adonisjs/drive/providers/DriveProvider', + '@adonisjs/validator/providers/ValidatorProvider', + '@adonisjs/framework/providers/ViewProvider', + '@adonisjs/shield/providers/ShieldProvider', +]; + +/* +|-------------------------------------------------------------------------- +| Ace Providers +|-------------------------------------------------------------------------- +| +| Ace providers are required only when running ace commands. For example +| Providers for migrations, tests etc. +| +*/ +const aceProviders = [ + '@adonisjs/lucid/providers/MigrationsProvider', +]; + +/* +|-------------------------------------------------------------------------- +| Aliases +|-------------------------------------------------------------------------- +| +| Aliases are short unique names for IoC container bindings. You are free +| to create your own aliases. +| +| For example: +| { Route: 'Adonis/Src/Route' } +| +*/ +const aliases = {}; + +/* +|-------------------------------------------------------------------------- +| Commands +|-------------------------------------------------------------------------- +| +| Here you store ace commands for your package +| +*/ +const commands = []; + +module.exports = { + providers, aceProviders, aliases, commands, +}; diff --git a/src/internal-server/start/kernel.js b/src/internal-server/start/kernel.js new file mode 100644 index 000000000..7b540f829 --- /dev/null +++ b/src/internal-server/start/kernel.js @@ -0,0 +1,55 @@ +/** @type {import('@adonisjs/framework/src/Server')} */ +const Server = use('Server'); + +/* +|-------------------------------------------------------------------------- +| Global Middleware +|-------------------------------------------------------------------------- +| +| Global middleware are executed on each http request only when the routes +| match. +| +*/ +const globalMiddleware = [ + 'Adonis/Middleware/BodyParser', + 'App/Middleware/ConvertEmptyStringsToNull', +]; + +/* +|-------------------------------------------------------------------------- +| Named Middleware +|-------------------------------------------------------------------------- +| +| Named middleware is key/value object to conditionally add middleware on +| specific routes or group of routes. +| +| // define +| { +| auth: 'Adonis/Middleware/Auth' +| } +| +| // use +| Route.get().middleware('auth') +| +*/ +const namedMiddleware = { +}; + +/* +|-------------------------------------------------------------------------- +| Server Middleware +|-------------------------------------------------------------------------- +| +| Server level middleware are executed even when route for a given URL is +| not registered. Features like `static assets` and `cors` needs better +| control over request lifecycle. +| +*/ +const serverMiddleware = [ + 'Adonis/Middleware/Static', +]; + +Server + .registerGlobal(globalMiddleware) + .registerNamed(namedMiddleware) + .use(serverMiddleware); diff --git a/src/internal-server/start/migrate.js b/src/internal-server/start/migrate.js new file mode 100644 index 000000000..6846beef6 --- /dev/null +++ b/src/internal-server/start/migrate.js @@ -0,0 +1,44 @@ +/** + * Migrate server database to work with current Ferdi version + */ +const Database = use('Database'); +const User = use('App/Models/User'); + +const migrateLog = (text) => { + console.log('\x1b[36m%s\x1b[0m', 'Ferdi Migration:', '\x1b[0m', text); +}; + +module.exports = async () => { + migrateLog('🧙‍ Running database migration wizard'); + + // Make sure user table exists + await Database.raw('CREATE TABLE IF NOT EXISTS `users` (`id` integer not null primary key autoincrement, `settings` text, `created_at` datetime, `updated_at` datetime);'); + + const user = await User.find(1); + let settings; + if (!user) { + migrateLog('🎩 Migrating from old Ferdi version as user doesn\'t exist'); + + // Create new user + await Database.raw('INSERT INTO "users" ("id") VALUES (\'1\');'); + } else { + settings = typeof user.settings === 'string' ? JSON.parse(user.settings) : user.settings; + } + + if (!settings || !settings.db_version || settings.db_version !== process.env.FERDI_VERSION) { + const srcVersion = settings && settings.db_version ? settings.db_version : '5.4.0-beta.2'; + migrateLog(`🔮 Migrating table from ${srcVersion} to ${process.env.FERDI_VERSION}`); + + // Migrate database to current Ferdi version + // Currently no migrations + + // Update version number in database + if (!settings) settings = {}; + settings.db_version = process.env.FERDI_VERSION; + const newUser = await User.find(1); // Fetch user again as we might have only just created it + newUser.settings = JSON.stringify(settings); + await newUser.save(); + } else { + migrateLog('🔧 Nothing to migrate, already on the newest version'); + } +}; diff --git a/src/internal-server/start/routes.js b/src/internal-server/start/routes.js new file mode 100644 index 000000000..63ac42c47 --- /dev/null +++ b/src/internal-server/start/routes.js @@ -0,0 +1,87 @@ +/* +|-------------------------------------------------------------------------- +| Routes +|-------------------------------------------------------------------------- +| +*/ + +/** @type {typeof import('@adonisjs/framework/src/Route/Manager')} */ +const Route = use('Route'); + +// Run latest database migration +const migrate = require('./migrate'); + +migrate(); + +const OnlyAllowFerdi = async ({ request, response }, next) => { + const version = request.header('X-Franz-Version'); + if (!version) { + return response.status(403).redirect('/'); + } + + await next(); + return true; +}; + +// Health: Returning if all systems function correctly +Route.get('health', ({ + response, +}) => response.send({ + api: 'success', + db: 'success', +})).middleware(OnlyAllowFerdi); + +// API is grouped under '/v1/' route +Route.group(() => { + // User authentification + Route.post('auth/signup', 'UserController.signup'); + Route.post('auth/login', 'UserController.login'); + + // User info + Route.get('me', 'UserController.me'); + Route.put('me', 'UserController.updateMe'); + + // Service info + Route.post('service', 'ServiceController.create'); + Route.put('service/reorder', 'ServiceController.reorder'); + Route.put('service/:id', 'ServiceController.edit'); + Route.delete('service/:id', 'ServiceController.delete'); + Route.get('me/services', 'ServiceController.list'); + + // Recipe store + Route.get('recipe', 'ServiceController.list'); + Route.post('recipes/update', 'ServiceController.update'); + Route.get('recipes', 'RecipeController.list'); + Route.get('recipes/download/:recipe', 'RecipeController.download'); + Route.get('recipes/search', 'RecipeController.search'); + Route.get('recipes/popular', 'StaticController.popularRecipes'); + Route.get('recipes/update', 'StaticController.emptyArray'); + + // Workspaces + Route.put('workspace/:id', 'WorkspaceController.edit'); + Route.delete('workspace/:id', 'WorkspaceController.delete'); + Route.post('workspace', 'WorkspaceController.create'); + Route.get('workspace', 'WorkspaceController.list'); + + // Static responses + Route.get('features/:mode?', 'StaticController.features'); + Route.get('services', 'StaticController.emptyArray'); + Route.get('news', 'StaticController.emptyArray'); + Route.get('announcements/:version', 'StaticController.announcement'); +}).prefix('v1').middleware(OnlyAllowFerdi); + +Route.group(() => { + Route.get('icon/:id', 'ServiceController.icon'); +}).prefix('v1'); + +// Franz account import +Route.post('import', 'UserController.import'); +Route.get('import', ({ view }) => view.render('import')); + +// Account transfer +Route.get('export', 'UserController.export'); +Route.post('transfer', 'UserController.importFerdi'); +Route.get('transfer', ({ view }) => view.render('transfer')); + +// Index +Route.get('/', ({ view }) => view.render('index')); -- cgit v1.2.3-70-g09d2