@silexlabs/silex 3.0.1-0 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.default +3 -2
- package/.silex.js +39 -1
- package/README.md +37 -35
- package/dist/client/client/api.d.ts +8 -1
- package/dist/client/client/assetUrl.d.ts +54 -0
- package/dist/client/client/config.d.ts +60 -1
- package/dist/client/client/events.d.ts +19 -10
- package/dist/client/client/grapesjs/PublicationManager.d.ts +6 -8
- package/dist/client/client/grapesjs/PublicationUi.d.ts +8 -10
- package/dist/client/client/grapesjs/breadcrumbs.d.ts +1 -0
- package/dist/client/client/grapesjs/css-props.d.ts +6 -0
- package/dist/client/client/grapesjs/footer.d.ts +2 -0
- package/dist/client/client/grapesjs/img.d.ts +6 -0
- package/dist/client/client/grapesjs/index.d.ts +6 -2
- package/dist/client/client/grapesjs/internal-links.d.ts +1 -1
- package/dist/client/client/grapesjs/keymaps.d.ts +123 -0
- package/dist/client/client/grapesjs/new-page-dialog.d.ts +1 -1
- package/dist/client/client/grapesjs/page-panel.d.ts +7 -1
- package/dist/client/client/grapesjs/project-bar.d.ts +20 -0
- package/dist/client/client/grapesjs/resize-panel.d.ts +1 -0
- package/dist/client/client/grapesjs/rich-text.d.ts +4 -1
- package/dist/client/client/grapesjs/semantic.d.ts +1 -1
- package/dist/client/client/grapesjs/settings-sections.d.ts +16 -0
- package/dist/client/client/grapesjs/settings.d.ts +3 -1
- package/dist/client/client/grapesjs/storage.d.ts +1 -0
- package/dist/client/client/grapesjs/symbolDialogs.d.ts +1 -1
- package/dist/client/client/grapesjs/view-buttons.d.ts +1 -0
- package/dist/client/client/index.d.ts +5 -0
- package/dist/client/client/publication-transformers.d.ts +42 -0
- package/dist/client/client/publish-custom-code-block.d.ts +4 -0
- package/dist/client/client/publish-fonts.d.ts +4 -0
- package/dist/client/client/utils.d.ts +22 -1
- package/dist/client/constants.d.ts +3 -0
- package/dist/client/css/admin.css +1107 -411
- package/dist/client/css/admin.css.map +1 -0
- package/dist/client/grapesjs-filter-styles/dist/index.d.ts +4 -0
- package/dist/client/grapesjs-fonts/dist/index.d.ts +4 -0
- package/dist/client/grapesjs-fonts/src/commands.d.ts +3 -0
- package/dist/client/grapesjs-fonts/src/fonts.d.ts +4 -0
- package/dist/client/grapesjs-storage-rate-limit/dist/index.d.ts +4 -0
- package/dist/client/grapesjs-ui-suggest-classes/dist/index.d.ts +4 -0
- package/dist/client/index.html +3 -2
- package/dist/client/js/main.js +305 -170
- package/dist/client/js/main.js.LICENSE.txt +21 -1
- package/dist/client/page.d.ts +1 -1
- package/dist/client/silex-lib/src/ts/client/api.d.ts +90 -0
- package/dist/client/silex-lib/src/ts/client/assetUrl.d.ts +54 -0
- package/dist/client/silex-lib/src/ts/client/config.d.ts +102 -0
- package/dist/client/silex-lib/src/ts/client/events.d.ts +23 -0
- package/dist/client/silex-lib/src/ts/client/expose.d.ts +8 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/LoginDialog.d.ts +15 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/PublicationManager.d.ts +73 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/PublicationUi.d.ts +59 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/blocks.d.ts +1 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/breadcrumbs.d.ts +1 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/css-props.d.ts +6 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/footer.d.ts +2 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/img.d.ts +6 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/index.d.ts +9 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/internal-links.d.ts +1 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/keymaps.d.ts +123 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/new-page-dialog.d.ts +2 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/openImport.d.ts +9 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/page-panel.d.ts +9 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/project-bar.d.ts +21 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/resize-panel.d.ts +1 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/rich-text.d.ts +4 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/semantic.d.ts +1 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/settings-sections.d.ts +16 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/settings.d.ts +4 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/storage.d.ts +2 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/symbolDialogs.d.ts +3 -0
- package/dist/client/silex-lib/src/ts/client/grapesjs/view-buttons.d.ts +1 -0
- package/dist/client/silex-lib/src/ts/client/index.d.ts +10 -0
- package/dist/client/silex-lib/src/ts/client/publication-transformers.d.ts +42 -0
- package/dist/client/silex-lib/src/ts/client/publish-custom-code-block.d.ts +4 -0
- package/dist/client/silex-lib/src/ts/client/publish-fonts.d.ts +4 -0
- package/dist/client/silex-lib/src/ts/client/utils.d.ts +22 -0
- package/dist/client/silex-lib/src/ts/constants.d.ts +32 -0
- package/dist/client/silex-lib/src/ts/page.d.ts +2 -0
- package/dist/client/silex-lib/src/ts/types.d.ts +339 -0
- package/dist/client/types.d.ts +59 -35
- package/dist/plugins/client/client/events.d.ts +19 -10
- package/dist/plugins/client/client/events.js +11 -0
- package/dist/plugins/client/client/events.js.map +1 -1
- package/dist/plugins/client/plugins/client/template.js +119 -71
- package/dist/plugins/client/plugins/client/template.js.map +1 -1
- package/dist/plugins/client/plugins/client/website-info.d.ts +1 -0
- package/dist/plugins/client/plugins/client/website-info.js +72 -0
- package/dist/plugins/client/plugins/client/website-info.js.map +1 -0
- package/dist/plugins/client/types.d.ts +59 -35
- package/dist/plugins/client/types.js +23 -0
- package/dist/plugins/client/types.js.map +1 -1
- package/dist/plugins/server/constants.d.ts +3 -0
- package/dist/plugins/server/constants.js +28 -1
- package/dist/plugins/server/constants.js.map +1 -1
- package/dist/plugins/server/plugins/server/Cache.js +9 -5
- package/dist/plugins/server/plugins/server/Cache.js.map +1 -1
- package/dist/plugins/server/plugins/server/DownloadConnector.d.ts +29 -0
- package/dist/plugins/server/plugins/server/DownloadConnector.js +127 -0
- package/dist/plugins/server/plugins/server/DownloadConnector.js.map +1 -0
- package/dist/plugins/server/plugins/server/FtpConnector.d.ts +5 -2
- package/dist/plugins/server/plugins/server/FtpConnector.js +38 -23
- package/dist/plugins/server/plugins/server/FtpConnector.js.map +1 -1
- package/dist/plugins/server/plugins/server/GitlabConnector.d.ts +63 -9
- package/dist/plugins/server/plugins/server/GitlabConnector.js +367 -91
- package/dist/plugins/server/plugins/server/GitlabConnector.js.map +1 -1
- package/dist/plugins/server/plugins/server/GitlabHostingConnector.d.ts +16 -0
- package/dist/plugins/server/plugins/server/GitlabHostingConnector.js +209 -0
- package/dist/plugins/server/plugins/server/GitlabHostingConnector.js.map +1 -0
- package/dist/plugins/server/plugins/server/SslPlugin.js +6 -6
- package/dist/plugins/server/plugins/server/SslPlugin.js.map +1 -1
- package/dist/plugins/server/plugins/server/StaticPlugin.d.ts +8 -1
- package/dist/plugins/server/plugins/server/StaticPlugin.js +5 -31
- package/dist/plugins/server/plugins/server/StaticPlugin.js.map +1 -1
- package/dist/plugins/server/server/config.js +8 -9
- package/dist/plugins/server/server/config.js.map +1 -1
- package/dist/plugins/server/server/connectors/FsHosting.d.ts +3 -2
- package/dist/plugins/server/server/connectors/FsHosting.js +18 -7
- package/dist/plugins/server/server/connectors/FsHosting.js.map +1 -1
- package/dist/plugins/server/server/connectors/FsStorage.d.ts +3 -1
- package/dist/plugins/server/server/connectors/FsStorage.js +35 -28
- package/dist/plugins/server/server/connectors/FsStorage.js.map +1 -1
- package/dist/plugins/server/server/connectors/connectors.d.ts +7 -7
- package/dist/plugins/server/server/connectors/connectors.js +6 -7
- package/dist/plugins/server/server/connectors/connectors.js.map +1 -1
- package/dist/plugins/server/server/events.js +16 -0
- package/dist/plugins/server/server/events.js.map +1 -1
- package/dist/plugins/server/server/jobs.d.ts +6 -0
- package/dist/plugins/server/server/jobs.js +12 -8
- package/dist/plugins/server/server/jobs.js.map +1 -1
- package/dist/plugins/server/server/utils/validation.js +1 -2
- package/dist/plugins/server/server/utils/validation.js.map +1 -1
- package/dist/plugins/server/types.d.ts +59 -35
- package/dist/plugins/server/types.js +24 -1
- package/dist/plugins/server/types.js.map +1 -1
- package/dist/server/constants.js +27 -1
- package/dist/server/plugins/server/Cache.js +9 -5
- package/dist/server/server/api/api.js +1 -1
- package/dist/server/server/api/connectorApi.js +154 -25
- package/dist/server/server/api/publicationApi.js +17 -25
- package/dist/server/server/api/websiteApi.js +30 -8
- package/dist/server/server/cli.js +9 -6
- package/dist/server/server/config.js +8 -9
- package/dist/server/server/connectors/FsHosting.js +17 -7
- package/dist/server/server/connectors/FsStorage.js +34 -28
- package/dist/server/server/connectors/connectors.js +6 -7
- package/dist/server/server/express.js +4 -5
- package/dist/server/server/index.js +5 -1
- package/dist/server/server/jobs.js +11 -8
- package/dist/server/server/utils/validation.js +1 -2
- package/dist/server/types.js +13 -1
- package/package.json +56 -42
- package/public/assets/download.png +0 -0
- package/public/assets/favicon.ico +0 -0
- package/public/assets/favicon.png +0 -0
- package/public/assets/ftp.png +0 -0
- package/public/assets/gitlab.png +0 -0
- package/public/assets/gitlab2.png +0 -0
- package/public/assets/laptop.png +0 -0
- package/public/assets/logo-silex-small.png +0 -0
- package/public/silex.js +5 -23
- package/src/css/_variables.scss +23 -20
- package/src/css/dialog.scss +27 -1
- package/src/css/fonts.scss +31 -0
- package/src/css/footer.scss +12 -0
- package/src/css/grapesjs-light.scss +180 -0
- package/src/css/grapesjs-plugins.scss +227 -0
- package/src/css/grapesjs.scss +84 -10
- package/src/css/index.scss +12 -1
- package/src/css/light.scss +7 -0
- package/src/css/project-bar.scss +32 -16
- package/src/css/silex.scss +79 -5
- package/src/css/website-info.scss +14 -0
- package/src/html/index.pug +3 -3
- package/src/ts/client/api.ts +38 -14
- package/src/ts/client/assetUrl.test.ts +164 -0
- package/src/ts/client/assetUrl.ts +254 -0
- package/src/ts/client/config.ts +133 -5
- package/src/ts/client/events.ts +21 -9
- package/src/ts/client/grapesjs/LoginDialog.ts +4 -2
- package/src/ts/client/grapesjs/PublicationManager.ts +180 -54
- package/src/ts/client/grapesjs/PublicationUi.ts +122 -86
- package/src/ts/client/grapesjs/breadcrumbs.ts +79 -0
- package/src/ts/client/grapesjs/css-props.ts +910 -0
- package/src/ts/client/grapesjs/eleventy.ts +11 -8
- package/{dist/plugins/client/page.js → src/ts/client/grapesjs/footer.ts} +24 -13
- package/src/ts/client/grapesjs/img.ts +147 -0
- package/src/ts/client/grapesjs/index.ts +234 -52
- package/src/ts/client/grapesjs/internal-links.test.ts +2 -1
- package/src/ts/client/grapesjs/internal-links.ts +14 -7
- package/src/ts/client/grapesjs/keymaps.ts +207 -0
- package/src/ts/client/grapesjs/new-page-dialog.ts +2 -3
- package/src/ts/client/grapesjs/page-panel.ts +92 -7
- package/src/ts/client/grapesjs/project-bar.ts +116 -72
- package/src/ts/client/grapesjs/resize-panel.ts +20 -0
- package/src/ts/client/grapesjs/rich-text.ts +21 -13
- package/src/ts/client/grapesjs/semantic.ts +3 -3
- package/src/ts/client/grapesjs/settings-sections.ts +117 -0
- package/src/ts/client/grapesjs/settings.ts +174 -96
- package/src/ts/client/grapesjs/storage.ts +98 -33
- package/src/ts/client/grapesjs/symbolDialogs.ts +3 -4
- package/src/ts/{plugins/server/AuthPlugin.ts → client/grapesjs/view-buttons.ts} +23 -19
- package/src/ts/client/index.ts +35 -16
- package/src/ts/client/publication-transformers.test.ts +207 -0
- package/src/ts/client/publication-transformers.ts +280 -0
- package/{dist/plugins/client/client/utils.js → src/ts/client/publish-custom-code-block.ts} +14 -8
- package/src/ts/client/publish-fonts.ts +36 -0
- package/src/ts/client/utils.ts +53 -1
- package/src/ts/constants.ts +31 -0
- package/src/ts/page.ts +2 -2
- package/src/ts/plugins/client/template.ts +125 -75
- package/src/ts/plugins/client/website-info.ts +84 -0
- package/src/ts/plugins/server/Cache.ts +6 -2
- package/src/ts/plugins/server/DownloadConnector.ts +146 -0
- package/src/ts/plugins/server/FtpConnector.ts +47 -21
- package/src/ts/plugins/server/GitlabConnector.ts +423 -108
- package/src/ts/plugins/server/GitlabHostingConnector.ts +215 -0
- package/src/ts/plugins/server/SslPlugin.ts +5 -5
- package/src/ts/plugins/server/StaticPlugin.ts +3 -30
- package/src/ts/server/api/connectorApi.ts +165 -28
- package/src/ts/server/api/publicationApi.ts +17 -24
- package/src/ts/server/api/websiteApi.ts +57 -14
- package/src/ts/server/cli.ts +7 -5
- package/src/ts/server/config.ts +9 -10
- package/src/ts/server/connectors/FsHosting.ts +14 -8
- package/src/ts/server/connectors/FsStorage.ts +40 -7
- package/src/ts/server/connectors/connectors.ts +8 -6
- package/src/ts/server/events.ts +17 -0
- package/src/ts/server/express.ts +2 -2
- package/src/ts/server/index.ts +6 -0
- package/src/ts/server/jobs.ts +14 -2
- package/src/ts/server/utils/BackwardCompat.ts +530 -529
- package/src/ts/types.ts +78 -34
- package/dist/plugins/client/client/utils.d.ts +0 -1
- package/dist/plugins/client/client/utils.js.map +0 -1
- package/dist/plugins/client/page.d.ts +0 -2
- package/dist/plugins/client/page.js.map +0 -1
- package/dist/plugins/client/plugins/client/publicationRenderer.d.ts +0 -2
- package/dist/plugins/client/plugins/client/publicationRenderer.js +0 -128
- package/dist/plugins/client/plugins/client/publicationRenderer.js.map +0 -1
- package/dist/plugins/server/plugins/server/AuthPlugin.d.ts +0 -1
- package/dist/plugins/server/plugins/server/AuthPlugin.js +0 -38
- package/dist/plugins/server/plugins/server/AuthPlugin.js.map +0 -1
- package/dist/plugins/server/plugins/server/HooksPlugin.d.ts +0 -7
- package/dist/plugins/server/plugins/server/HooksPlugin.js +0 -74
- package/dist/plugins/server/plugins/server/HooksPlugin.js.map +0 -1
- package/src/example-client-config.js +0 -64
- package/src/ts/plugins/client/publicationRenderer.ts +0 -128
- package/src/ts/plugins/server/HooksPlugin.ts +0 -76
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Silex website builder, free/libre no-code tool for makers.
|
|
3
|
+
* Copyright (c) 2023 lexoyo and Silex Labs foundation
|
|
4
|
+
*
|
|
5
|
+
* This program is free software: you can redistribute it and/or modify
|
|
6
|
+
* it under the terms of the GNU Affero General Public License as published by
|
|
7
|
+
* the Free Software Foundation, either version 3 of the License, or any later version.
|
|
8
|
+
*
|
|
9
|
+
* This program is distributed in the hope that it will be useful,
|
|
10
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
* GNU Affero General Public License for more details.
|
|
13
|
+
*
|
|
14
|
+
* You should have received a copy of the GNU Affero General Public License
|
|
15
|
+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Gitlab hosting connector
|
|
20
|
+
* @fileoverview Gitlab hosting connector for Silex, connect to the user's Gitlab account to host websites with .gitlab-ci.yml file template for plain html by default
|
|
21
|
+
* @see https://docs.gitlab.com/ee/api/oauth2.html
|
|
22
|
+
* @see https://docs.gitlab.com/ee/user/project/pages/getting_started/pages_ci_cd_template.html
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
import dedent from 'dedent'
|
|
26
|
+
import GitlabConnector, { GitlabOptions, GitlabSession} from './GitlabConnector'
|
|
27
|
+
import { HostingConnector, ConnectorFile } from '../../server/connectors/connectors'
|
|
28
|
+
import { ConnectorType, WebsiteId, JobData, JobStatus, PublicationJobData } from '../../types'
|
|
29
|
+
import { JobManager } from '../../server/jobs'
|
|
30
|
+
import { ServerConfig } from '../../server/config'
|
|
31
|
+
import { setTimeout } from 'timers/promises'
|
|
32
|
+
|
|
33
|
+
const waitTimeOut = 5000 /* for wait loop in job pages getting */
|
|
34
|
+
const SILEX_OVERWRITE_NOTICE = '# silexOverwrite: true'
|
|
35
|
+
|
|
36
|
+
export default class GitlabHostingConnector extends GitlabConnector implements HostingConnector {
|
|
37
|
+
|
|
38
|
+
displayName = 'Gitlab hosting'
|
|
39
|
+
connectorType = ConnectorType.HOSTING
|
|
40
|
+
|
|
41
|
+
constructor( config: ServerConfig, opts: Partial<GitlabOptions>) {
|
|
42
|
+
super (config, opts)
|
|
43
|
+
// public directory for standard gitlab pages
|
|
44
|
+
this.options.assetsFolder= 'public'
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async publish(session: GitlabSession, websiteId: WebsiteId, files: ConnectorFile[], {startJob, jobSuccess, jobError}: JobManager): Promise<JobData> {
|
|
48
|
+
const job = startJob(`Publishing to ${this.displayName}`) as PublicationJobData
|
|
49
|
+
job.logs = [[`Publishing to ${this.displayName}`]]
|
|
50
|
+
job.errors = [[]]
|
|
51
|
+
/* Configuration file .gitlab-ci.yml contains template for plain html Gitlab pages*/
|
|
52
|
+
const pathYml = '.gitlab-ci.yml'
|
|
53
|
+
const contentYml = dedent`
|
|
54
|
+
${SILEX_OVERWRITE_NOTICE}
|
|
55
|
+
# You will want to remove these lines if you customize your build process
|
|
56
|
+
# Silex will overwrite this file unless you remove these lines
|
|
57
|
+
# This is the default build process for plain eleventy sites
|
|
58
|
+
image: node:20
|
|
59
|
+
pages:
|
|
60
|
+
stage: deploy
|
|
61
|
+
environment: production
|
|
62
|
+
script:${files.find(file => file.path.includes('.11tydata.')) ? `
|
|
63
|
+
- npx @11ty/eleventy@v3.0.0-alpha.20 --input=public --output=_site
|
|
64
|
+
- mkdir -p public/css public/assets && cp -R public/css public/assets _site/
|
|
65
|
+
- rm -rf public && mv _site public`
|
|
66
|
+
: ''}
|
|
67
|
+
- echo "The site will be deployed to $CI_PAGES_URL"
|
|
68
|
+
artifacts:
|
|
69
|
+
paths:
|
|
70
|
+
- public
|
|
71
|
+
rules:
|
|
72
|
+
- if: '$CI_COMMIT_TAG'
|
|
73
|
+
- if: '$CI_PIPELINE_SOURCE == "trigger"'
|
|
74
|
+
`
|
|
75
|
+
try {
|
|
76
|
+
const originalCi = await this.readFile(session, websiteId, pathYml)
|
|
77
|
+
if(originalCi.toString().startsWith(SILEX_OVERWRITE_NOTICE)) {
|
|
78
|
+
await this.updateFile(session, websiteId, pathYml, contentYml)
|
|
79
|
+
}
|
|
80
|
+
} catch (e) {
|
|
81
|
+
// If the file .gitlab-ci.yml does not exist, create it, otherwise do nothing (do not overwriting existing one)
|
|
82
|
+
if (e.statusCode === 404 || e.httpStatusCode === 404 || e.message.endsWith('A file with this name doesn\'t exist')) {
|
|
83
|
+
await this.createFile(session, websiteId, pathYml, contentYml)
|
|
84
|
+
} else {
|
|
85
|
+
jobError(job.jobId, e.message)
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// publishing all files for website
|
|
90
|
+
// Do not await for the result, return the job and continue the publication in the background
|
|
91
|
+
this.writeAssets(session, websiteId, files, async ({status, message}) => {
|
|
92
|
+
// Update the job status
|
|
93
|
+
if(status === JobStatus.SUCCESS) {
|
|
94
|
+
/* Squash and tag the commits */
|
|
95
|
+
const successTag = await this.createTag(session, websiteId, job, { startJob, jobSuccess, jobError })
|
|
96
|
+
if(!successTag) {
|
|
97
|
+
// jobError will have been called in createTag
|
|
98
|
+
return
|
|
99
|
+
}
|
|
100
|
+
try {
|
|
101
|
+
job.message = 'Getting the website URL...'
|
|
102
|
+
job.logs[0].push(job.message)
|
|
103
|
+
const gitlabUrl = await this.getUrl(session, websiteId)
|
|
104
|
+
job.logs[0].push(`Website URL: ${gitlabUrl}`)
|
|
105
|
+
job.message = 'Getting the admin URL...'
|
|
106
|
+
job.logs[0].push(job.message)
|
|
107
|
+
const adminUrl = await this.getAdminUrl(session, websiteId)
|
|
108
|
+
job.logs[0].push(`Admin URL: ${adminUrl}`)
|
|
109
|
+
job.message = 'Getting the page URL...'
|
|
110
|
+
job.logs[0].push(job.message)
|
|
111
|
+
const pageUrl = await this.getPageUrl(session, websiteId, adminUrl)
|
|
112
|
+
job.logs[0].push(`Page URL: ${pageUrl}`)
|
|
113
|
+
job.message = 'Getting the deployment logs URL...'
|
|
114
|
+
job.logs[0].push(job.message)
|
|
115
|
+
const gitlabJobLogsUrl = await this.getGitlabJobLogsUrl(session, websiteId, job, { startJob, jobSuccess, jobError }, adminUrl, successTag)
|
|
116
|
+
// Because of the GitLab policy, this can be null (and we suggest the user to verify their account)
|
|
117
|
+
if (!gitlabJobLogsUrl) {
|
|
118
|
+
let errorMessage = 'Could not retrieve the deployment logs URL.'
|
|
119
|
+
|
|
120
|
+
if (this.isUsingOfficialInstance()) {
|
|
121
|
+
const verifyURL = 'https://gitlab.com/-/identity_verification'
|
|
122
|
+
errorMessage +=
|
|
123
|
+
`<div class="notice">
|
|
124
|
+
If your GitLab account is recent, you may need to verify it <a href="${verifyURL}" target="_blank">here</a>
|
|
125
|
+
in order to be able to use pipelines (this is GitLab's policy, not Silex's).
|
|
126
|
+
</div>`
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
throw new Error(errorMessage)
|
|
130
|
+
}
|
|
131
|
+
job.logs[0].push(`Deployment logs URL: ${gitlabJobLogsUrl}`)
|
|
132
|
+
const message = `
|
|
133
|
+
<p><a href="${gitlabUrl}" target="_blank">Your website will soon be live here</a>.</p>
|
|
134
|
+
<p>Changes may take a few minutes to appear, <a href="${gitlabJobLogsUrl}" target="_blank">follow deployment here</a>.</p>
|
|
135
|
+
<p>Manage <a href="${pageUrl}" target="_blank">GitLab Pages settings</a>.</p>
|
|
136
|
+
`
|
|
137
|
+
job.logs[0].push(message)
|
|
138
|
+
jobSuccess(job.jobId, message)
|
|
139
|
+
} catch (error) {
|
|
140
|
+
console.error('Error during getting the website URLs:', error.message)
|
|
141
|
+
jobError(job.jobId, `Failed to get the website URLs: ${error.message}`)
|
|
142
|
+
}
|
|
143
|
+
} else if (status === JobStatus.ERROR) {
|
|
144
|
+
job.errors[0].push(message)
|
|
145
|
+
jobError(job.jobId, message)
|
|
146
|
+
} else {
|
|
147
|
+
// Update the job status while uploading files
|
|
148
|
+
job.status = status
|
|
149
|
+
job.message = message
|
|
150
|
+
job.logs[0].push(message)
|
|
151
|
+
}
|
|
152
|
+
})
|
|
153
|
+
.catch(e => {
|
|
154
|
+
console.error('Error uploading files to gitlab:', e.message)
|
|
155
|
+
jobError(job.jobId, `Failed to upload files: ${e.message}`)
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
return job
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/* Get and return Url Gitlab Pages */
|
|
162
|
+
async getUrl(session: GitlabSession, websiteId: WebsiteId): Promise<string> {
|
|
163
|
+
const response = await this.callApi(session, `api/v4/projects/${websiteId}/pages`, 'GET')
|
|
164
|
+
return response.url
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
async getAdminUrl(session: GitlabSession, websiteId: WebsiteId): Promise<string> {
|
|
168
|
+
const projectInfo = await this.callApi(session, `api/v4/projects/${websiteId}`, 'GET')
|
|
169
|
+
return projectInfo.web_url
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
async getPageUrl(session: GitlabSession, websiteId: WebsiteId, projectUrl: string): Promise<string> {
|
|
173
|
+
return `${projectUrl}/pages`
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// waiting for the job corresponding to the current tag
|
|
177
|
+
async getGitlabJobLogsUrl(session: GitlabSession, websiteId: WebsiteId, job: PublicationJobData, { startJob, jobSuccess, jobError }: JobManager, projectUrl: string, tag): Promise<string | null> {
|
|
178
|
+
const t0 = Date.now()
|
|
179
|
+
do {
|
|
180
|
+
const jobs = await this.callApi(session, `api/v4/projects/${websiteId}/jobs`, 'GET')
|
|
181
|
+
if (!jobs.length) return null
|
|
182
|
+
if (jobs[0].ref === tag) {return `${projectUrl}/-/jobs/${jobs[0].id}`}
|
|
183
|
+
await setTimeout(waitTimeOut)
|
|
184
|
+
} while ((Date.now() - t0) < this.options.timeOut)
|
|
185
|
+
|
|
186
|
+
// failed in timelaps allowed (avoiding infinite loop)
|
|
187
|
+
jobError(job.jobId, 'Failed to get job id')
|
|
188
|
+
job.message = 'Unable to get job id'
|
|
189
|
+
job.logs[0].push(job.message)
|
|
190
|
+
return `${projectUrl}/-/jobs/`
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
async createTag(session: GitlabSession, websiteId: WebsiteId, job: PublicationJobData, { startJob, jobSuccess, jobError }: JobManager): Promise<string | null> {
|
|
194
|
+
const projectId = websiteId // Assuming websiteId corresponds to GitLab project ID
|
|
195
|
+
const newTag = '_silex_' + Date.now()
|
|
196
|
+
// Create a new tag
|
|
197
|
+
try {
|
|
198
|
+
job.message = `Creating new tag ${newTag}...`
|
|
199
|
+
job.logs[0].push(job.message)
|
|
200
|
+
await this.callApi(session, `api/v4/projects/${projectId}/repository/tags`, 'POST', {
|
|
201
|
+
tag_name: newTag,
|
|
202
|
+
ref: 'main',
|
|
203
|
+
message: 'Publication from Silex',
|
|
204
|
+
})
|
|
205
|
+
} catch (error) {
|
|
206
|
+
console.error('Error during creating new tag:', error.message)
|
|
207
|
+
jobError(job.jobId, `Failed to create new tag: ${error.message}`)
|
|
208
|
+
return null
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Return new tag
|
|
212
|
+
return newTag
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
}
|
|
@@ -47,18 +47,18 @@ export default async function(config, opts = {}) {
|
|
|
47
47
|
// SSL
|
|
48
48
|
// force ssl if the env var SILEX_FORCE_HTTPS is set
|
|
49
49
|
if (options.forceHttps) {
|
|
50
|
-
console.
|
|
50
|
+
console.info('> [SslPlugin] Force SSL option is enabled')
|
|
51
51
|
app.set('forceSSLOptions', {
|
|
52
52
|
trustXFPHeader: !!options.trustXFPHeader,
|
|
53
53
|
})
|
|
54
54
|
router.use(forceSSL)
|
|
55
55
|
} else {
|
|
56
|
-
console.
|
|
56
|
+
console.info('> [SslPlugin] Force SSL option is disabled, env var SILEX_FORCE_HTTPS not set')
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
// SSL certificate
|
|
60
60
|
if (options.privateKey && options.certificate) {
|
|
61
|
-
console.
|
|
61
|
+
console.info('> [SslPlugin] SSL certificate is enabled, found certificate:', options.certificate)
|
|
62
62
|
try {
|
|
63
63
|
const privateKey = readFileSync(options.privateKey).toString()
|
|
64
64
|
const certificate = readFileSync(options.certificate).toString()
|
|
@@ -71,13 +71,13 @@ export default async function(config, opts = {}) {
|
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
createServer(sslServerOptions, this).listen(options.sslPort, () => {
|
|
74
|
-
console.
|
|
74
|
+
console.info('> [SslPlugin] Listening on port ', options.sslPort)
|
|
75
75
|
})
|
|
76
76
|
} catch (e) {
|
|
77
77
|
console.error('> [SslPlugin] Load certificate failed.', e)
|
|
78
78
|
}
|
|
79
79
|
} else {
|
|
80
|
-
console.
|
|
80
|
+
console.info('> [SslPlugin] Certificate disabled, env vars SILEX_SSL_CERTIFICATE and SILEX_SSL_PRIVATE_KEY not set')
|
|
81
81
|
}
|
|
82
82
|
app.use(router)
|
|
83
83
|
})
|
|
@@ -16,10 +16,8 @@
|
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
18
|
import express from 'express'
|
|
19
|
-
import nodeModules from 'node_modules-path'
|
|
20
19
|
import serveStatic from 'serve-static'
|
|
21
20
|
import { withCache } from './Cache'
|
|
22
|
-
import { join } from 'path'
|
|
23
21
|
import { ServerEvent } from '../../server/events'
|
|
24
22
|
|
|
25
23
|
type StaticOptions = {
|
|
@@ -29,34 +27,9 @@ type StaticOptions = {
|
|
|
29
27
|
}[]
|
|
30
28
|
}
|
|
31
29
|
|
|
32
|
-
export default async function(config,
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
routes: [
|
|
36
|
-
{
|
|
37
|
-
route: '/',
|
|
38
|
-
path: join(__dirname, '../../../../..', 'public'),
|
|
39
|
-
}, {
|
|
40
|
-
route: '/css/',
|
|
41
|
-
path: nodeModules('@fortawesome/fontawesome-free') + '/@fortawesome/fontawesome-free/css/',
|
|
42
|
-
}, {
|
|
43
|
-
route: '/webfonts/',
|
|
44
|
-
path: nodeModules('@fortawesome/fontawesome-free') + '/@fortawesome/fontawesome-free/webfonts/',
|
|
45
|
-
}, {
|
|
46
|
-
route: '/node_modules/',
|
|
47
|
-
path: nodeModules(),
|
|
48
|
-
}, {
|
|
49
|
-
route: '/',
|
|
50
|
-
path: join(__dirname, '../../../../..', 'dist', 'client'),
|
|
51
|
-
},
|
|
52
|
-
]
|
|
53
|
-
// add project route for source maps
|
|
54
|
-
.concat(config.debug ? [{
|
|
55
|
-
route: '/',
|
|
56
|
-
path: './',
|
|
57
|
-
}] : []),
|
|
58
|
-
...opts,
|
|
59
|
-
}
|
|
30
|
+
export default async function(config, options: StaticOptions = { routes: [] }) {
|
|
31
|
+
if(!options.routes) throw new Error('The config for static module has no `routes` attribute')
|
|
32
|
+
console.info(`> [StaticPlugin] Serving ${options.routes.length} static files`)
|
|
60
33
|
|
|
61
34
|
config.on(ServerEvent.STARTUP_START, ({app}) => {
|
|
62
35
|
const router = express.Router()
|
|
@@ -3,7 +3,7 @@ import { API_CONNECTOR_LIST, API_CONNECTOR_LOGIN_CALLBACK, API_CONNECTOR_USER, A
|
|
|
3
3
|
import { ServerConfig } from '../config'
|
|
4
4
|
import { requiredParam } from '../utils/validation'
|
|
5
5
|
import { Connector, getConnector, toConnectorData, toConnectorEnum } from '../connectors/connectors'
|
|
6
|
-
import { ApiConnectorListQuery, ApiConnectorListResponse, ApiConnectorLoggedInPostMessage, ApiConnectorLoginQuery, ApiConnectorUserQuery, ApiConnectorUserResponse, ApiConnectorLogoutQuery, ConnectorId, ApiConnectorLoginCbkQuery, ApiConnectorLoginCbkBody, ConnectorOptions, ApiResponseError } from '../../types'
|
|
6
|
+
import { ApiConnectorListQuery, ApiConnectorListResponse, ApiConnectorLoggedInPostMessage, ApiConnectorLoginQuery, ApiConnectorUserQuery, ApiConnectorUserResponse, ApiConnectorLogoutQuery, ConnectorId, ApiConnectorLoginCbkQuery, ApiConnectorLoginCbkBody, ConnectorOptions, ApiResponseError, ConnectorType } from '../../types'
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* @fileoverview The connector API adds routes to handle the connectors and the methods they implement, this includes authentication and user data.
|
|
@@ -45,6 +45,24 @@ export default function(config: ServerConfig) {
|
|
|
45
45
|
return router
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
+
/**
|
|
49
|
+
* Method to validate HTTP status codes
|
|
50
|
+
* Returns a suitable error code if it is not valid
|
|
51
|
+
*/
|
|
52
|
+
function validateStatus(status: number, _default = 500): number {
|
|
53
|
+
if(!status) {
|
|
54
|
+
console.warn(`Status code is undefined, returning default ${_default}`)
|
|
55
|
+
return _default
|
|
56
|
+
}
|
|
57
|
+
// Make sure it is a string
|
|
58
|
+
status = parseInt(status.toString())
|
|
59
|
+
// Check the status code
|
|
60
|
+
if (status >= 100 && status < 600) return status
|
|
61
|
+
// Invalid status code
|
|
62
|
+
console.warn(`Invalid status code ${status}, returning default ${_default}}`)
|
|
63
|
+
return _default
|
|
64
|
+
}
|
|
65
|
+
|
|
48
66
|
/**
|
|
49
67
|
* Express route to check if the user is logged in
|
|
50
68
|
* Returns user data and connector data
|
|
@@ -78,8 +96,8 @@ async function routeUser(req: Request, res: Response) {
|
|
|
78
96
|
const user = await connector.getUser(session)
|
|
79
97
|
res.json(user as ApiConnectorUserResponse)
|
|
80
98
|
} catch (error) {
|
|
81
|
-
console.error('Error in the
|
|
82
|
-
res.status(error
|
|
99
|
+
console.error('Error in the user request', error, error.code)
|
|
100
|
+
res.status(validateStatus(error.code ?? error.httpStatusCode, 500)).json({
|
|
83
101
|
error: true,
|
|
84
102
|
message: error.message,
|
|
85
103
|
} as ApiResponseError)
|
|
@@ -101,14 +119,14 @@ async function routeListConnectors(req: Request, res: Response) {
|
|
|
101
119
|
res.json(list as ApiConnectorListResponse)
|
|
102
120
|
} catch (error) {
|
|
103
121
|
console.error('Error while listing connectors', error)
|
|
104
|
-
res.status(error?.code ?? error?.httpStatusCode
|
|
122
|
+
res.status(validateStatus(error?.code ?? error?.httpStatusCode, 500)).json({
|
|
105
123
|
error: true,
|
|
106
124
|
message: 'Error while listing connectors: ' + error.message,
|
|
107
125
|
} as ApiResponseError)
|
|
108
126
|
}
|
|
109
127
|
} catch (error) {
|
|
110
128
|
console.error('Error in the list connectors request', error)
|
|
111
|
-
res.status(error?.code ?? error?.httpStatusCode
|
|
129
|
+
res.status(validateStatus(error?.code ?? error?.httpStatusCode, 400)).json({
|
|
112
130
|
error: true,
|
|
113
131
|
message: 'Error in the list connectors request: ' + error.message,
|
|
114
132
|
} as ApiResponseError)
|
|
@@ -132,7 +150,7 @@ async function routeLogin(req: Request, res: Response) {
|
|
|
132
150
|
if (!connector) throw new Error(`Connector not found ${connectorId} ${type}`)
|
|
133
151
|
// Check if the user is already logged in
|
|
134
152
|
if (await connector.isLoggedIn(session)) {
|
|
135
|
-
res.redirect(`${API_PATH}${API_CONNECTOR_PATH}${API_CONNECTOR_LOGIN_CALLBACK}?connectorId=${connectorId}&type=${type}`)
|
|
153
|
+
res.redirect(`${config.url}${API_PATH}${API_CONNECTOR_PATH}${API_CONNECTOR_LOGIN_CALLBACK}?connectorId=${connectorId}&type=${type}`)
|
|
136
154
|
return
|
|
137
155
|
}
|
|
138
156
|
const oauthUrl = await connector.getOAuthUrl(session)
|
|
@@ -142,13 +160,13 @@ async function routeLogin(req: Request, res: Response) {
|
|
|
142
160
|
} else {
|
|
143
161
|
// Display the login form
|
|
144
162
|
const redirectTo = await connector.getSettingsForm(session, '') ?
|
|
145
|
-
`${API_PATH}${API_CONNECTOR_PATH}${API_CONNECTOR_SETTINGS}?connectorId=${connectorId}&type=${type}` :
|
|
146
|
-
`${API_PATH}${API_CONNECTOR_PATH}${API_CONNECTOR_LOGIN_CALLBACK}?connectorId=${connectorId}&type=${type}`
|
|
163
|
+
`${config.url}${API_PATH}${API_CONNECTOR_PATH}${API_CONNECTOR_SETTINGS}?connectorId=${connectorId}&type=${type}` :
|
|
164
|
+
`${config.url}${API_PATH}${API_CONNECTOR_PATH}${API_CONNECTOR_LOGIN_CALLBACK}?connectorId=${connectorId}&type=${type}`
|
|
147
165
|
res.send(await connector.getLoginForm(session, redirectTo))
|
|
148
166
|
}
|
|
149
167
|
} catch (error) {
|
|
150
168
|
console.error('Error in the login request', error)
|
|
151
|
-
res.status(error?.code ?? error?.httpStatusCode
|
|
169
|
+
res.status(validateStatus(error?.code ?? error?.httpStatusCode, 400)).json({
|
|
152
170
|
error: true,
|
|
153
171
|
message: 'Error in the login request: ' + error.message,
|
|
154
172
|
} as ApiResponseError)
|
|
@@ -171,7 +189,7 @@ async function routeLogin(req: Request, res: Response) {
|
|
|
171
189
|
// if (!connector) throw new Error(`Connector not found ${connectorId} ${type}`)
|
|
172
190
|
// // Check if the user is already logged in
|
|
173
191
|
// if (!await connector.isLoggedIn(session)) {
|
|
174
|
-
// res.redirect(`${API_PATH}${API_CONNECTOR_PATH}${API_CONNECTOR_LOGIN_CALLBACK}?connectorId=${connectorId}&type=${type}&error=Not logged in`)
|
|
192
|
+
// res.redirect(`${config.url}${API_PATH}${API_CONNECTOR_PATH}${API_CONNECTOR_LOGIN_CALLBACK}?connectorId=${connectorId}&type=${type}&error=Not logged in`)
|
|
175
193
|
// return
|
|
176
194
|
// }
|
|
177
195
|
// // Display the login form
|
|
@@ -202,7 +220,7 @@ async function routeLogin(req: Request, res: Response) {
|
|
|
202
220
|
// if (!connector) throw new Error(`Connector not found ${connectorId} ${type}`)
|
|
203
221
|
// // Check if the user is already logged in
|
|
204
222
|
// if (!await connector.isLoggedIn(session)) {
|
|
205
|
-
// res.redirect(`${API_PATH}${API_CONNECTOR_PATH}${API_CONNECTOR_LOGIN_CALLBACK}?connectorId=${connectorId}&type=${type}&error=Not logged in`)
|
|
223
|
+
// res.redirect(`${config.url}${API_PATH}${API_CONNECTOR_PATH}${API_CONNECTOR_LOGIN_CALLBACK}?connectorId=${connectorId}&type=${type}&error=Not logged in`)
|
|
206
224
|
// return
|
|
207
225
|
// }
|
|
208
226
|
// // Save the settings
|
|
@@ -245,11 +263,11 @@ async function routeLoginSuccess(req: Request, res: Response) {
|
|
|
245
263
|
})
|
|
246
264
|
}
|
|
247
265
|
// End the auth flow
|
|
248
|
-
res.send(getEndAuthHtml('Logged in', false, connectorId, connector.getOptions(body)))
|
|
266
|
+
res.send(getEndAuthHtml('Logged in', false, connectorId, type, connector.getOptions(body)))
|
|
249
267
|
} catch (error) {
|
|
250
268
|
res
|
|
251
|
-
.status(error?.code ?? error?.httpStatusCode
|
|
252
|
-
.send(getEndAuthHtml(error.message, true))
|
|
269
|
+
.status(validateStatus(error?.code ?? error?.httpStatusCode, 500))
|
|
270
|
+
.send(getEndAuthHtml(error.message, true, req.query.connectorId as ConnectorId, req.query.type as ConnectorType))
|
|
253
271
|
}
|
|
254
272
|
}
|
|
255
273
|
|
|
@@ -276,7 +294,7 @@ async function routeLogout(req: Request, res: Response) {
|
|
|
276
294
|
} as ApiResponseError)
|
|
277
295
|
} catch (error) {
|
|
278
296
|
console.error('Error while logging out', error)
|
|
279
|
-
res.status(error?.code ?? error?.httpStatusCode
|
|
297
|
+
res.status(validateStatus(error?.code ?? error?.httpStatusCode, 500)).json({
|
|
280
298
|
error: true,
|
|
281
299
|
message: 'Error while logging out: ' + error.message,
|
|
282
300
|
} as ApiResponseError)
|
|
@@ -284,7 +302,7 @@ async function routeLogout(req: Request, res: Response) {
|
|
|
284
302
|
}
|
|
285
303
|
} catch (error) {
|
|
286
304
|
console.error('Error in the logout request', error)
|
|
287
|
-
res.status(error?.code ?? error?.httpStatusCode
|
|
305
|
+
res.status(validateStatus(error?.code ?? error?.httpStatusCode, 400)).json({
|
|
288
306
|
error: true,
|
|
289
307
|
message: 'Error in the logout request: ' + error.message,
|
|
290
308
|
} as ApiResponseError)
|
|
@@ -296,31 +314,150 @@ async function routeLogout(req: Request, res: Response) {
|
|
|
296
314
|
* Utility function to send an HTML page to the browser
|
|
297
315
|
* is page will send a postMessage to the parent window and close itself
|
|
298
316
|
*/
|
|
299
|
-
function getEndAuthHtml(message: string, error: boolean, connectorId
|
|
317
|
+
function getEndAuthHtml(message: string, error: boolean, connectorId: ConnectorId, connectorType: ConnectorType, options?: ConnectorOptions): string {
|
|
300
318
|
// Data for postMessage
|
|
301
319
|
const data = {
|
|
302
320
|
type: 'login', // For postMessage
|
|
303
321
|
error,
|
|
304
322
|
message,
|
|
305
323
|
connectorId,
|
|
324
|
+
connectorType,
|
|
306
325
|
options,
|
|
307
326
|
} as ApiConnectorLoggedInPostMessage
|
|
308
|
-
//
|
|
327
|
+
// Determine status title and heading based on the error
|
|
328
|
+
const status = error ? 'Error' : 'Success'
|
|
329
|
+
// Return the HTML template
|
|
309
330
|
return `
|
|
310
|
-
|
|
331
|
+
<!DOCTYPE html><html lang="en">
|
|
311
332
|
<head>
|
|
312
|
-
<
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
333
|
+
<title>Authentication ${status}</title>
|
|
334
|
+
<style>
|
|
335
|
+
:root {
|
|
336
|
+
--primaryColor: #333333;
|
|
337
|
+
--secondaryColor: #ddd;
|
|
338
|
+
--tertiaryColor: #8873FE;
|
|
339
|
+
--quaternaryColor: #A291FF;
|
|
340
|
+
--darkerPrimaryColor: #292929;
|
|
341
|
+
--lighterPrimaryColor: #575757;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
body {
|
|
345
|
+
font-family: Arial, sans-serif;
|
|
346
|
+
text-align: center;
|
|
347
|
+
margin: 50px;
|
|
348
|
+
color: var(--primaryColor);
|
|
349
|
+
background-color: var(--secondaryColor);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
h1 {
|
|
353
|
+
color: var(--tertiaryColor);
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
p {
|
|
357
|
+
font-size: 18px;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
a {
|
|
361
|
+
color: var(--tertiaryColor);
|
|
362
|
+
text-decoration: none;
|
|
318
363
|
}
|
|
319
|
-
|
|
364
|
+
|
|
365
|
+
a:hover {
|
|
366
|
+
text-decoration: underline;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
.container {
|
|
370
|
+
max-width: 600px;
|
|
371
|
+
margin: auto;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
.button {
|
|
375
|
+
display: inline-block;
|
|
376
|
+
margin-top: 20px;
|
|
377
|
+
padding: 10px 20px;
|
|
378
|
+
font-size: 16px;
|
|
379
|
+
color: var(--secondaryColor);
|
|
380
|
+
background-color: var(--tertiaryColor);
|
|
381
|
+
border: none;
|
|
382
|
+
border-radius: 5px;
|
|
383
|
+
text-decoration: none;
|
|
384
|
+
cursor: pointer;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
.button:hover {
|
|
388
|
+
background-color: var(--quaternaryColor); /* Slightly lighter shade of tertiary color */
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
.error {
|
|
392
|
+
display: none;
|
|
393
|
+
margin-top: 20px;
|
|
394
|
+
padding: 15px;
|
|
395
|
+
border: 1px solid var(--tertiaryColor);
|
|
396
|
+
border-radius: 5px;
|
|
397
|
+
text-wrap: wrap;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
</style>
|
|
320
401
|
</head>
|
|
321
402
|
<body>
|
|
322
|
-
<
|
|
323
|
-
|
|
403
|
+
<div class="container">
|
|
404
|
+
<div id="message">
|
|
405
|
+
<h1>Authentication ${status}</h1>
|
|
406
|
+
<p>${error ? '' : message}</p>
|
|
407
|
+
</div>
|
|
408
|
+
${ error ? `
|
|
409
|
+
<p><a data-link-to href="/">click here to continue</a>.</p>
|
|
410
|
+
<a data-link-to href="/" class="button">Retry</a>
|
|
411
|
+
<pre id="error-container" class="error">${message}</pre>
|
|
412
|
+
<script>
|
|
413
|
+
document.getElementById('error-container').style.display = "block";
|
|
414
|
+
fetch("${ API_PATH }${ API_CONNECTOR_PATH }${ API_CONNECTOR_LOGOUT }?connectorId=${ connectorId }&type=${ connectorType }", {
|
|
415
|
+
method: 'POST',
|
|
416
|
+
headers: {
|
|
417
|
+
'Content-Type': 'application/json',
|
|
418
|
+
credentials: 'include', // sends the cookies with the request
|
|
419
|
+
},
|
|
420
|
+
})
|
|
421
|
+
if(window.opener && window.opener !== window) {
|
|
422
|
+
const linksTo = document.querySelectorAll('[data-link-to]');
|
|
423
|
+
linksTo.forEach(link => {
|
|
424
|
+
link.addEventListener('click', (e) => {
|
|
425
|
+
e.preventDefault();
|
|
426
|
+
const data = ${JSON.stringify(data)};
|
|
427
|
+
window.opener.postMessage(data, '*');
|
|
428
|
+
window.close();
|
|
429
|
+
});
|
|
430
|
+
});
|
|
431
|
+
}
|
|
432
|
+
</script>
|
|
433
|
+
` : `
|
|
434
|
+
<p>If this window doesn’t close automatically, <a href="/">click here to return to the homepage</a>.</p>
|
|
435
|
+
<a href="/" class="button">Go to Homepage</a>
|
|
436
|
+
<pre id="error-container" class="error"></pre>
|
|
437
|
+
<script>
|
|
438
|
+
const data = ${JSON.stringify(data)};
|
|
439
|
+
const errorContainer = document.getElementById('error-container');
|
|
440
|
+
const messageContainer = document.getElementById('message');
|
|
441
|
+
|
|
442
|
+
// Check if the window was opened programmatically and is valid
|
|
443
|
+
if (window.opener && window.opener !== window) {
|
|
444
|
+
try {
|
|
445
|
+
// Send a postMessage to the opener
|
|
446
|
+
window.opener.postMessage(data, '*');
|
|
447
|
+
// Attempt to close the window
|
|
448
|
+
window.close();
|
|
449
|
+
} catch (e) {
|
|
450
|
+
// Display error message if closing fails
|
|
451
|
+
errorContainer.innerText = "Unable to close the window. Please close it manually.";
|
|
452
|
+
errorContainer.style.display = "block";
|
|
453
|
+
}
|
|
454
|
+
} else {
|
|
455
|
+
messageContainer.innerHTML = '<h1>Redirecting, please wait...</h1>';
|
|
456
|
+
window.location.href = '/'
|
|
457
|
+
}
|
|
458
|
+
</script>
|
|
459
|
+
`}
|
|
460
|
+
</div>
|
|
324
461
|
</body>
|
|
325
462
|
</html>
|
|
326
463
|
`
|