From 3c1f07f3b0489d663dc8b3760e26e1561e8587ec Mon Sep 17 00:00:00 2001 From: Dominik Korsa Date: Fri, 22 Jan 2021 17:47:26 +0100 Subject: [PATCH] Add error screen --- backend/src/routes/oauth2/authorize.ts | 27 ++- website/.eslintrc.js | 6 + website/src/compontents/dialog-app.vue | 35 ++++ website/src/pages/authenticate-prompt/app.vue | 190 ++++++++---------- website/src/pages/prompt-error/app.vue | 48 +++++ website/src/pages/prompt-error/main.ts | 10 + website/vue.config.js | 8 +- 7 files changed, 217 insertions(+), 107 deletions(-) create mode 100644 website/src/compontents/dialog-app.vue create mode 100644 website/src/pages/prompt-error/app.vue create mode 100644 website/src/pages/prompt-error/main.ts diff --git a/backend/src/routes/oauth2/authorize.ts b/backend/src/routes/oauth2/authorize.ts index 3316b8b..a37b0d5 100644 --- a/backend/src/routes/oauth2/authorize.ts +++ b/backend/src/routes/oauth2/authorize.ts @@ -18,17 +18,28 @@ export default function registerAuthorize(server: MyFastifyInstance): void { ) => { if (!isObject(request.query)) { server.log.warn('Request query is not an object'); - throw server.httpErrors.badRequest(); + await reply.redirect(urlJoin( + websitePrefix, + `/prompt-error?code=invalid_request&description=${ + encodeURIComponent('Request query is not an object') + }`, + )); + return; } try { validateParam('client_id', request.query.client_id); validateParam('redirect_uri', request.query.redirect_uri); } catch (error) { if (error instanceof ParamError) { - throw server.httpErrors.badRequest(error.message); + await reply.redirect(urlJoin( + websitePrefix, + `/prompt-error?code=invalid_request&description=${encodeURIComponent(error.message)}`, + )); + return; } server.log.error(error); - throw server.httpErrors.internalServerError(); + await reply.redirect(urlJoin(websitePrefix, '/prompt-error?code=internal')); + return; } const application = await database.applicationRepo.findOne({ @@ -36,8 +47,14 @@ export default function registerAuthorize(server: MyFastifyInstance): void { clientId: request.query.client_id, }, }); - if (application === undefined) throw server.httpErrors.badRequest('Unknown application'); - if (!application.redirectUris.includes(request.query.redirect_uri)) throw server.httpErrors.badRequest('Redirect URI not registered'); + if (application === undefined) { + await reply.redirect(urlJoin(websitePrefix, '/prompt-error?code=unknown_application')); + return; + } + if (!application.redirectUris.includes(request.query.redirect_uri)) { + await reply.redirect(urlJoin(websitePrefix, '/prompt-error?code=unknown_redirect_uri')); + return; + } try { validateParam('response_type', request.query.response_type); diff --git a/website/.eslintrc.js b/website/.eslintrc.js index 1537043..a42a333 100644 --- a/website/.eslintrc.js +++ b/website/.eslintrc.js @@ -23,5 +23,11 @@ module.exports = { 'max-len': ['off'] }, }, + { + files: '**/*.vue', + rules: { + 'class-methods-use-this': ['off'] + } + } ], }; diff --git a/website/src/compontents/dialog-app.vue b/website/src/compontents/dialog-app.vue new file mode 100644 index 0000000..db65523 --- /dev/null +++ b/website/src/compontents/dialog-app.vue @@ -0,0 +1,35 @@ + + + + + diff --git a/website/src/pages/authenticate-prompt/app.vue b/website/src/pages/authenticate-prompt/app.vue index 0054819..13ad8c4 100644 --- a/website/src/pages/authenticate-prompt/app.vue +++ b/website/src/pages/authenticate-prompt/app.vue @@ -1,107 +1,96 @@ + @@ -136,10 +121,13 @@ import { PromptInfo, Student } from '@/types'; import LoginWindow from '@/compontents/authenticate-prompt-windows/login-window.vue'; import StudentsWindow from '@/compontents/authenticate-prompt-windows/students-window.vue'; import { sdk } from '@/pages/authenticate-prompt/sdk'; +import DialogApp from '@/compontents/dialog-app.vue'; @Component({ name: 'AuthenticatePromptApp', - components: { LoginWindow, OverviewWindow, StudentsWindow }, + components: { + LoginWindow, OverviewWindow, StudentsWindow, DialogApp, + }, }) export default class AuthenticatePromptApp extends Vue { @Ref() readonly loginWindow!: LoginWindow diff --git a/website/src/pages/prompt-error/app.vue b/website/src/pages/prompt-error/app.vue new file mode 100644 index 0000000..b32e6c9 --- /dev/null +++ b/website/src/pages/prompt-error/app.vue @@ -0,0 +1,48 @@ + + + diff --git a/website/src/pages/prompt-error/main.ts b/website/src/pages/prompt-error/main.ts new file mode 100644 index 0000000..15117df --- /dev/null +++ b/website/src/pages/prompt-error/main.ts @@ -0,0 +1,10 @@ +import Vue from 'vue'; +import vuetify from '@/plugins/vuetify'; +import AuthenticatePromptApp from './app.vue'; + +Vue.config.productionTip = false; + +new Vue({ + vuetify, + render: (h) => h(AuthenticatePromptApp), +}).$mount('#app'); diff --git a/website/vue.config.js b/website/vue.config.js index 3611cb9..8895adb 100644 --- a/website/vue.config.js +++ b/website/vue.config.js @@ -7,7 +7,13 @@ module.exports = { entry: 'src/pages/authenticate-prompt/main.ts', template: 'public/index.html', filename: 'authenticate-prompt.html', - title: 'Authorize application | Wulkanowy Bridge', + title: 'Autoryzuj aplikację | Wulkanowy Bridge', + }, + 'prompt-error': { + entry: 'src/pages/prompt-error/main.ts', + template: 'public/index.html', + filename: 'prompt-error.html', + title: 'Błąd autoryzacji | Wulkanowy Bridge', }, }, };