Render <StatusPage> if domain matched
This commit is contained in:
		
							parent
							
								
									fee88b32e3
								
							
						
					
					
						commit
						c4e74c9943
					
				
					 6 changed files with 91 additions and 16 deletions
				
			
		|  | @ -3,6 +3,20 @@ const { R } = require("redbean-node"); | |||
| 
 | ||||
| class StatusPage extends BeanModel { | ||||
| 
 | ||||
|     static domainMappingList = { }; | ||||
| 
 | ||||
|     /** | ||||
|      * Return object like this: { "test-uptime.kuma.pet": "default" } | ||||
|      * @returns {Promise<void>} | ||||
|      */ | ||||
|     static async loadDomainMappingList() { | ||||
|         this.domainMappingList = await R.getAssoc(` | ||||
|             SELECT domain, slug | ||||
|             FROM status_page, status_page_cname | ||||
|             WHERE status_page.id = status_page_cname.status_page_id | ||||
|         `);
 | ||||
|     } | ||||
| 
 | ||||
|     static async sendStatusPageList(io, socket) { | ||||
|         let result = {}; | ||||
| 
 | ||||
|  | @ -16,6 +30,18 @@ class StatusPage extends BeanModel { | |||
|         return list; | ||||
|     } | ||||
| 
 | ||||
|     getDomainList() { | ||||
|         let domainList = []; | ||||
|         for (let domain in StatusPage.domainMappingList) { | ||||
|             let s = StatusPage.domainMappingList[domain]; | ||||
| 
 | ||||
|             if (this.slug === s) { | ||||
|                 domainList.push(domain); | ||||
|             } | ||||
|         } | ||||
|         return domainList; | ||||
|     } | ||||
| 
 | ||||
|     async toJSON() { | ||||
|         return { | ||||
|             id: this.id, | ||||
|  | @ -26,6 +52,7 @@ class StatusPage extends BeanModel { | |||
|             theme: this.theme, | ||||
|             published: !!this.published, | ||||
|             showTags: !!this.show_tags, | ||||
|             domainList: this.getDomainList(), | ||||
|         }; | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
|  | @ -12,9 +12,19 @@ let router = express.Router(); | |||
| let cache = apicache.middleware; | ||||
| let io = server.io; | ||||
| 
 | ||||
| router.get("/api/entry-page", async (_, response) => { | ||||
| router.get("/api/entry-page", async (request, response) => { | ||||
|     allowDevAllOrigin(response); | ||||
|     response.json(server.entryPage); | ||||
| 
 | ||||
|     let result = { }; | ||||
| 
 | ||||
|     if (request.hostname in StatusPage.domainMappingList) { | ||||
|         result.type = "statusPageMatchedDomain"; | ||||
|         result.statusPageSlug = StatusPage.domainMappingList[request.hostname]; | ||||
|     } else { | ||||
|         result.type = "entryPage"; | ||||
|         result.entryPage = server.entryPage; | ||||
|     } | ||||
|     response.json(result); | ||||
| }); | ||||
| 
 | ||||
| router.get("/api/push/:pushToken", async (request, response) => { | ||||
|  |  | |||
|  | @ -197,6 +197,7 @@ exports.entryPage = "dashboard"; | |||
|     await initDatabase(testMode); | ||||
| 
 | ||||
|     exports.entryPage = await setting("entryPage"); | ||||
|     await StatusPage.loadDomainMappingList(); | ||||
| 
 | ||||
|     console.log("Adding route"); | ||||
| 
 | ||||
|  | @ -205,8 +206,13 @@ exports.entryPage = "dashboard"; | |||
|     // ***************************
 | ||||
| 
 | ||||
|     // Entry Page
 | ||||
|     app.get("/", async (_request, response) => { | ||||
|         if (exports.entryPage && exports.entryPage.startsWith("statusPage-")) { | ||||
|     app.get("/", async (request, response) => { | ||||
|         debug(`Request Domain: ${request.hostname}`); | ||||
| 
 | ||||
|         if (request.hostname in StatusPage.domainMappingList) { | ||||
|             debug("This is a status page domain"); | ||||
|             response.send(indexHTML); | ||||
|         } else if (exports.entryPage && exports.entryPage.startsWith("statusPage-")) { | ||||
|             response.redirect("/status/" + exports.entryPage.replace("statusPage-", "")); | ||||
|         } else { | ||||
|             response.redirect("/dashboard"); | ||||
|  |  | |||
|  | @ -37,6 +37,7 @@ import { | |||
|     faPen, | ||||
|     faExternalLinkSquareAlt, | ||||
|     faSpinner, | ||||
|     faUndo, | ||||
| } from "@fortawesome/free-solid-svg-icons"; | ||||
| 
 | ||||
| library.add( | ||||
|  | @ -73,6 +74,7 @@ library.add( | |||
|     faPen, | ||||
|     faExternalLinkSquareAlt, | ||||
|     faSpinner, | ||||
|     faUndo, | ||||
| ); | ||||
| 
 | ||||
| export { FontAwesomeIcon }; | ||||
|  |  | |||
|  | @ -1,23 +1,44 @@ | |||
| <template> | ||||
|     <div> | ||||
|         <!-- | ||||
|             TODO: If the domain name matched, directly render the <StatusPage> component. | ||||
|         --> | ||||
|         <StatusPage v-if="statusPageSlug" override-slug="statusPageSlug" /> | ||||
|     </div> | ||||
| </template> | ||||
| 
 | ||||
| <script> | ||||
| import axios from "axios"; | ||||
| import StatusPage from "./StatusPage.vue"; | ||||
| 
 | ||||
| export default { | ||||
|     components: { | ||||
|         StatusPage, | ||||
|     }, | ||||
|     data() { | ||||
|         return { | ||||
|             statusPageSlug: null, | ||||
|         }; | ||||
|     }, | ||||
|     async mounted() { | ||||
|         let entryPage = (await axios.get("/api/entry-page")).data; | ||||
| 
 | ||||
|         if (entryPage === "statusPage") { | ||||
|             this.$router.push("/status"); | ||||
|         // There are only 2 cases that could come in here. | ||||
|         // 1. Matched status Page domain name | ||||
|         // 2. Vue Frontend Dev | ||||
|         let res = (await axios.get("/api/entry-page")).data; | ||||
| 
 | ||||
|         if (res.type === "statusPageMatchedDomain") { | ||||
|             this.statusPageSlug = res.statusPageSlug; | ||||
| 
 | ||||
|         } else if (res.type === "entryPage") {          // Dev only | ||||
|             const entryPage = res.entryPage; | ||||
| 
 | ||||
|             if (entryPage === "statusPage") { | ||||
|                 this.$router.push("/status"); | ||||
|             } else { | ||||
|                 this.$router.push("/dashboard"); | ||||
|             } | ||||
|         } else { | ||||
|             this.$router.push("/dashboard"); | ||||
|         } | ||||
| 
 | ||||
|     }, | ||||
| 
 | ||||
| }; | ||||
|  |  | |||
|  | @ -35,9 +35,9 @@ | |||
|                 <input id="password" v-model="config.password" disabled type="password" autocomplete="new-password" class="form-control"> | ||||
|             </div> | ||||
| 
 | ||||
|             <div v-if="false" class="my-3"> | ||||
|                 <label for="cname" class="form-label">Domain Names <sup>Coming Soon</sup></label> | ||||
|                 <textarea id="cname" v-model="config.domanNames" rows="3" disabled class="form-control" :placeholder="domainNamesPlaceholder"></textarea> | ||||
|             <div class="my-3"> | ||||
|                 <label for="cname" class="form-label">Domain Names</label> | ||||
|                 <textarea id="cname" v-model="config.domanNames" rows="3" class="form-control" :placeholder="domainNamesPlaceholder"></textarea> | ||||
|             </div> | ||||
| 
 | ||||
|             <div class="danger-zone"> | ||||
|  | @ -55,7 +55,7 @@ | |||
|                 </button> | ||||
| 
 | ||||
|                 <button class="btn btn-danger me-2" @click="discard"> | ||||
|                     <font-awesome-icon icon="save" /> | ||||
|                     <font-awesome-icon icon="undo" /> | ||||
|                     {{ $t("Discard") }} | ||||
|                 </button> | ||||
|             </div> | ||||
|  | @ -259,6 +259,7 @@ const favicon = new Favico({ | |||
| }); | ||||
| 
 | ||||
| export default { | ||||
| 
 | ||||
|     components: { | ||||
|         PublicGroupList, | ||||
|         ImageCropUpload, | ||||
|  | @ -278,6 +279,14 @@ export default { | |||
|         next(); | ||||
|     }, | ||||
| 
 | ||||
|     props: { | ||||
|         overrideSlug: { | ||||
|             type: String, | ||||
|             required: false, | ||||
|             default: null, | ||||
|         }, | ||||
|     }, | ||||
| 
 | ||||
|     data() { | ||||
|         return { | ||||
|             slug: null, | ||||
|  | @ -294,7 +303,7 @@ export default { | |||
|             loadedData: false, | ||||
|             baseURL: "", | ||||
|             clickedEditButton: false, | ||||
|             domainNamesPlaceholder: "domain1.com\ndomain2.com\n..." | ||||
|             domainNamesPlaceholder: "example1.com\nexample2.com\n..." | ||||
|         }; | ||||
|     }, | ||||
|     computed: { | ||||
|  | @ -449,7 +458,7 @@ export default { | |||
|         this.baseURL = getResBaseURL(); | ||||
|     }, | ||||
|     async mounted() { | ||||
|         this.slug = this.$route.params.slug; | ||||
|         this.slug = this.overrideSlug || this.$route.params.slug; | ||||
| 
 | ||||
|         if (!this.slug) { | ||||
|             this.slug = "default"; | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue