From b018adf240679ec59a7344e30be39400f1ecd8af Mon Sep 17 00:00:00 2001 From: vantezzen Date: Thu, 22 Aug 2019 11:12:36 +0200 Subject: Initial commit --- app/Controllers/Http/ServiceController.js | 94 +++++++++++++ app/Controllers/Http/StaticController.js | 224 ++++++++++++++++++++++++++++++ app/Controllers/Http/UserController.js | 94 +++++++++++++ 3 files changed, 412 insertions(+) create mode 100644 app/Controllers/Http/ServiceController.js create mode 100644 app/Controllers/Http/StaticController.js create mode 100644 app/Controllers/Http/UserController.js (limited to 'app/Controllers') diff --git a/app/Controllers/Http/ServiceController.js b/app/Controllers/Http/ServiceController.js new file mode 100644 index 0000000..47a8a6f --- /dev/null +++ b/app/Controllers/Http/ServiceController.js @@ -0,0 +1,94 @@ +'use strict' + +const User = use('App/Models/User'); +const Service = use('App/Models/Service'); + +class ServiceController { + // Create a new service for user + async create({ + request, + response, + auth + }) { + try { + await auth.getUser() + } catch (error) { + return response.send('Missing or invalid api token') + } + + const data = request.all(); + + const service = await Service.create({ + userId: auth.user.id, + name: data.name, + recipeId: data.recipeId, + settings: JSON.stringify(data) + }); + + return response.send({ + "data": { + userId: auth.user.id, + id: service.id, + "isEnabled": true, + "isNotificationEnabled": true, + "isBadgeEnabled": true, + "isMuted": false, + "isDarkModeEnabled": "", + "spellcheckerLanguage": "", + "order": 1, + "customRecipe": false, + "hasCustomIcon": false, + "workspaces": [], + "iconUrl": null, + ...data, + }, + "status": ["created"] + }) + } + + // List all services a user has created + async list({ + request, + response, + auth + }) { + try { + await auth.getUser() + } catch (error) { + return response.send('Missing or invalid api token') + } + + + const services = (await auth.user.services().fetch()).rows; + // Convert to array with all data Franz wants + const servicesArray = services.map(service => ({ + "customRecipe": false, + "hasCustomIcon": false, + "isBadgeEnabled": true, + "isDarkModeEnabled": "", + "isEnabled": true, + "isMuted": false, + "isNotificationEnabled": true, + "order": 1, + "spellcheckerLanguage": "", + "workspaces": [], + "iconUrl": null, + ...JSON.parse(service.settings), + "id": service.id, + "name": service.name, + "recipeId": service.recipeId, + "userId": auth.user.id, + })) + + return response.send(servicesArray) + } + + // Download a recipe (currently simply redirects to Franz's API) + download({ request, response, params }) { + const service = params.recipe; + + response.redirect('https://api.franzinfra.com/v1/recipes/download/' + service) + } +} + +module.exports = ServiceController diff --git a/app/Controllers/Http/StaticController.js b/app/Controllers/Http/StaticController.js new file mode 100644 index 0000000..70f2d7f --- /dev/null +++ b/app/Controllers/Http/StaticController.js @@ -0,0 +1,224 @@ +'use strict' +/** + * Controller for routes with static responses + */ + +class StaticController { + // Enable all features + features({ + response + }) { + return response.send({ + "needToWaitToProceed": false, + "isSpellcheckerPremiumFeature": true, + "isServiceProxyEnabled": true, + "isServiceProxyPremiumFeature": true, + "isWorkspacePremiumFeature": true, + "isWorkspaceEnabled": true, + "isAnnouncementsEnabled": true, + "isSettingsWSEnabled": false, + "isServiceLimitEnabled": false, + "serviceLimitCount": 0, + "isCommunityRecipesPremiumFeature": false + }) + } + + // Return an empty array + emptyArray({ + response + }) { + return response.send([]) + } + + // Payment plans availible + plans({ + response + }) { + return response.send({ + "month": { + "id": "franz-supporter-license", + "price": 99 + }, + "year": { + "id": "franz-supporter-license-year-2019", + "price": 99 + } + }) + } + + // Return list of popular recipes (copy of the response Franz's API is returning) + popularRecipes({ + response + }) { + return response.send([{ + "author": "Stefan Malzner ", + "featured": false, + "id": "slack", + "name": "Slack", + "version": "1.0.4", + "icons": { + "png": "https://cdn.franzinfra.com/recipes/dist/slack/src/icon.png", + "svg": "https://cdn.franzinfra.com/recipes/dist/slack/src/icon.svg" + } + }, { + "author": "Stefan Malzner ", + "featured": false, + "id": "whatsapp", + "name": "WhatsApp", + "version": "1.0.1", + "icons": { + "png": "https://cdn.franzinfra.com/recipes/dist/whatsapp/src/icon.png", + "svg": "https://cdn.franzinfra.com/recipes/dist/whatsapp/src/icon.svg" + } + }, { + "author": "Stefan Malzner ", + "featured": false, + "id": "messenger", + "name": "Messenger", + "version": "1.0.6", + "icons": { + "png": "https://cdn.franzinfra.com/recipes/dist/messenger/src/icon.png", + "svg": "https://cdn.franzinfra.com/recipes/dist/messenger/src/icon.svg" + } + }, { + "author": "Stefan Malzner ", + "featured": false, + "id": "telegram", + "name": "Telegram", + "version": "1.0.0", + "icons": { + "png": "https://cdn.franzinfra.com/recipes/dist/telegram/src/icon.png", + "svg": "https://cdn.franzinfra.com/recipes/dist/telegram/src/icon.svg" + } + }, { + "author": "Stefan Malzner ", + "featured": false, + "id": "gmail", + "name": "Gmail", + "version": "1.0.0", + "icons": { + "png": "https://cdn.franzinfra.com/recipes/dist/gmail/src/icon.png", + "svg": "https://cdn.franzinfra.com/recipes/dist/gmail/src/icon.svg" + } + }, { + "author": "Stefan Malzner ", + "featured": false, + "id": "skype", + "name": "Skype", + "version": "1.0.0", + "icons": { + "png": "https://cdn.franzinfra.com/recipes/dist/skype/src/icon.png", + "svg": "https://cdn.franzinfra.com/recipes/dist/skype/src/icon.svg" + } + }, { + "author": "Stefan Malzner ", + "featured": false, + "id": "hangouts", + "name": "Hangouts", + "version": "1.0.0", + "icons": { + "png": "https://cdn.franzinfra.com/recipes/dist/hangouts/src/icon.png", + "svg": "https://cdn.franzinfra.com/recipes/dist/hangouts/src/icon.svg" + } + }, { + "author": "Stefan Malzner ", + "featured": false, + "id": "discord", + "name": "Discord", + "version": "1.0.0", + "icons": { + "png": "https://cdn.franzinfra.com/recipes/dist/discord/src/icon.png", + "svg": "https://cdn.franzinfra.com/recipes/dist/discord/src/icon.svg" + } + }, { + "author": "Stefan Malzner ", + "featured": false, + "id": "tweetdeck", + "name": "Tweetdeck", + "version": "1.0.1", + "icons": { + "png": "https://cdn.franzinfra.com/recipes/dist/tweetdeck/src/icon.png", + "svg": "https://cdn.franzinfra.com/recipes/dist/tweetdeck/src/icon.svg" + } + }, { + "author": "Stefan Malzner ", + "featured": false, + "id": "hipchat", + "name": "HipChat", + "version": "1.0.1", + "icons": { + "png": "https://cdn.franzinfra.com/recipes/dist/hipchat/src/icon.png", + "svg": "https://cdn.franzinfra.com/recipes/dist/hipchat/src/icon.svg" + } + }, { + "author": "Stefan Malzner ", + "featured": false, + "id": "gmailinbox", + "name": "Inbox by Gmail", + "version": "1.0.0", + "icons": { + "png": "https://cdn.franzinfra.com/recipes/dist/gmailinbox/src/icon.png", + "svg": "https://cdn.franzinfra.com/recipes/dist/gmailinbox/src/icon.svg" + } + }, { + "author": "Stefan Malzner ", + "featured": false, + "id": "rocketchat", + "name": "Rocket.Chat", + "version": "1.0.1", + "icons": { + "png": "https://cdn.franzinfra.com/recipes/dist/rocketchat/src/icon.png", + "svg": "https://cdn.franzinfra.com/recipes/dist/rocketchat/src/icon.svg" + } + }, { + "author": "Brian Gilbert ", + "featured": false, + "id": "gitter", + "name": "Gitter", + "version": "1.0.0", + "icons": { + "png": "https://cdn.franzinfra.com/recipes/dist/gitter/src/icon.png", + "svg": "https://cdn.franzinfra.com/recipes/dist/gitter/src/icon.svg" + } + }, { + "author": "Stefan Malzner ", + "featured": false, + "id": "mattermost", + "name": "Mattermost", + "version": "1.0.0", + "icons": { + "png": "https://cdn.franzinfra.com/recipes/dist/mattermost/src/icon.png", + "svg": "https://cdn.franzinfra.com/recipes/dist/mattermost/src/icon.svg" + } + }, { + "author": "Franz ", + "featured": false, + "id": "toggl", + "name": "toggl", + "version": "1.0.0", + "icons": { + "png": "https://cdn.franzinfra.com/recipes/dist/toggl/src/icon.png", + "svg": "https://cdn.franzinfra.com/recipes/dist/toggl/src/icon.svg" + } + }, { + "author": "Stuart Clark ", + "featured": false, + "id": "twist", + "name": "twist", + "version": "1.0.0", + "icons": { + "png": "https://cdn.franzinfra.com/recipes/dist/twist/src/icon.png", + "svg": "https://cdn.franzinfra.com/recipes/dist/twist/src/icon.svg" + } + }]) + } + + // Show announcements + announcement({ response, params }) { + return response.send({ + 'en-US': 'You are using an unofficial Franz Server.' + }); + } +} + +module.exports = StaticController diff --git a/app/Controllers/Http/UserController.js b/app/Controllers/Http/UserController.js new file mode 100644 index 0000000..88f7ecd --- /dev/null +++ b/app/Controllers/Http/UserController.js @@ -0,0 +1,94 @@ +'use strict' + +const User = use('App/Models/User'); +const atob = require('atob'); + +class UserController { + + // Register a new user + async signup({ + request, + response, + auth, + session + }) { + const data = request.only(['firstname', 'email', 'password']); + const user = await User.create({ + email: data.email, + password: data.password, + username: data.firstname + }); + const token = await auth.generate(user) + + return response.send({ + "message": "Successfully created account", + "token": token.token + }); + } + + // Login using an existing user + async login({ + request, + response, + auth + }) { + const authHeader = atob(request.header('Authorization')).split(':'); + + let user = (await User.query().where('email', authHeader[0]).limit(1).fetch()).toJSON(); + if (!user[0] || !user[0].email) { + return response.status(401).send({ + "message": "User credentials not valid", + "code": "invalid-credentials", + "status": 401 + }); + } + + let token; + try { + // TODO: Login is currently not working as the password is incorrect + token = await auth.attempt(user[0].id, authHeader[1]) + } catch (e) { + return response.status(401).send({ + "message": "User credentials not valid", + "code": "invalid-credentials", + "status": 401 + }); + } + + return response.send({ + "message": "Successfully logged in", + "token": token.token + }); + } + + // Return information about the current user + async me({ + request, + response, + auth, + session + }) { + try { + await auth.getUser() + } catch (error) { + response.send('Missing or invalid api token') + } + + return response.send({ + accountType: "individual", + beta: false, + donor: {}, + email: auth.user.email, + emailValidated: true, + features: {}, + firstname: "Franz", + id: "2acd2aa0-0869-4a91-adab-f700ac256dbe", + isPremium: true, + isSubscriptionOwner: true, + lastname: "Franz", + locale: "en-US" + }); + } +} + +module.exports = UserController -- cgit v1.2.3-70-g09d2