Merge branch 'master' into http-basicauth
This commit is contained in:
		
						commit
						34d8984e3a
					
				
					 10 changed files with 111 additions and 8 deletions
				
			
		
							
								
								
									
										2
									
								
								.github/ISSUE_TEMPLATE/ask-for-help.yaml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/ISSUE_TEMPLATE/ask-for-help.yaml
									
									
									
									
										vendored
									
									
								
							|  | @ -1,6 +1,6 @@ | ||||||
| name: "❓ Ask for help" | name: "❓ Ask for help" | ||||||
| description: "Submit any question related to Uptime Kuma" | description: "Submit any question related to Uptime Kuma" | ||||||
| title: "[Help] " | #title: "[Help] " | ||||||
| labels: [help] | labels: [help] | ||||||
| body: | body: | ||||||
|   - type: checkboxes |   - type: checkboxes | ||||||
|  |  | ||||||
							
								
								
									
										2
									
								
								.github/ISSUE_TEMPLATE/bug_report.yaml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/ISSUE_TEMPLATE/bug_report.yaml
									
									
									
									
										vendored
									
									
								
							|  | @ -1,6 +1,6 @@ | ||||||
| name: "🐛 Bug Report" | name: "🐛 Bug Report" | ||||||
| description: "Submit a bug report to help us improve" | description: "Submit a bug report to help us improve" | ||||||
| title: "[Bug] " | #title: "[Bug] " | ||||||
| labels: [bug] | labels: [bug] | ||||||
| body: | body: | ||||||
|   - type: checkboxes |   - type: checkboxes | ||||||
|  |  | ||||||
							
								
								
									
										2
									
								
								.github/ISSUE_TEMPLATE/feature_request.yaml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/ISSUE_TEMPLATE/feature_request.yaml
									
									
									
									
										vendored
									
									
								
							|  | @ -1,6 +1,6 @@ | ||||||
| name: 🚀 Feature Request | name: 🚀 Feature Request | ||||||
| description: "Submit a proposal for a new feature" | description: "Submit a proposal for a new feature" | ||||||
| title: "[Feature] " | #title: "[Feature] " | ||||||
| labels: [enhancement] | labels: [enhancement] | ||||||
| body: | body: | ||||||
|   - type: checkboxes |   - type: checkboxes | ||||||
|  |  | ||||||
|  | @ -160,6 +160,8 @@ class Monitor extends BeanModel { | ||||||
|                         }; |                         }; | ||||||
|                     } |                     } | ||||||
| 
 | 
 | ||||||
|  |                     debug(`[${this.name}] Prepare Options for axios`); | ||||||
|  | 
 | ||||||
|                     const options = { |                     const options = { | ||||||
|                         url: this.url, |                         url: this.url, | ||||||
|                         method: (this.method || "get").toLowerCase(), |                         method: (this.method || "get").toLowerCase(), | ||||||
|  | @ -180,6 +182,8 @@ class Monitor extends BeanModel { | ||||||
|                             return checkStatusCode(status, this.getAcceptedStatuscodes()); |                             return checkStatusCode(status, this.getAcceptedStatuscodes()); | ||||||
|                         }, |                         }, | ||||||
|                     }; |                     }; | ||||||
|  | 
 | ||||||
|  |                     debug(`[${this.name}] Axios Request`); | ||||||
|                     let res = await axios.request(options); |                     let res = await axios.request(options); | ||||||
|                     bean.msg = `${res.status} - ${res.statusText}`; |                     bean.msg = `${res.status} - ${res.statusText}`; | ||||||
|                     bean.ping = dayjs().valueOf() - startTime; |                     bean.ping = dayjs().valueOf() - startTime; | ||||||
|  | @ -187,12 +191,13 @@ class Monitor extends BeanModel { | ||||||
|                     // Check certificate if https is used
 |                     // Check certificate if https is used
 | ||||||
|                     let certInfoStartTime = dayjs().valueOf(); |                     let certInfoStartTime = dayjs().valueOf(); | ||||||
|                     if (this.getUrl()?.protocol === "https:") { |                     if (this.getUrl()?.protocol === "https:") { | ||||||
|  |                         debug(`[${this.name}] Check cert`); | ||||||
|                         try { |                         try { | ||||||
|                             let tlsInfoObject = checkCertificate(res); |                             let tlsInfoObject = checkCertificate(res); | ||||||
|                             tlsInfo = await this.updateTlsInfo(tlsInfoObject); |                             tlsInfo = await this.updateTlsInfo(tlsInfoObject); | ||||||
| 
 | 
 | ||||||
|                             if (!this.getIgnoreTls()) { |                             if (!this.getIgnoreTls()) { | ||||||
|                                 debug("call sendCertNotification"); |                                 debug(`[${this.name}] call sendCertNotification`); | ||||||
|                                 await this.sendCertNotification(tlsInfoObject); |                                 await this.sendCertNotification(tlsInfoObject); | ||||||
|                             } |                             } | ||||||
| 
 | 
 | ||||||
|  | @ -371,15 +376,19 @@ class Monitor extends BeanModel { | ||||||
| 
 | 
 | ||||||
|             let beatInterval = this.interval; |             let beatInterval = this.interval; | ||||||
| 
 | 
 | ||||||
|  |             debug(`[${this.name}] Check isImportant`); | ||||||
|             let isImportant = Monitor.isImportantBeat(isFirstBeat, previousBeat?.status, bean.status); |             let isImportant = Monitor.isImportantBeat(isFirstBeat, previousBeat?.status, bean.status); | ||||||
| 
 | 
 | ||||||
|             // Mark as important if status changed, ignore pending pings,
 |             // Mark as important if status changed, ignore pending pings,
 | ||||||
|             // Don't notify if disrupted changes to up
 |             // Don't notify if disrupted changes to up
 | ||||||
|             if (isImportant) { |             if (isImportant) { | ||||||
|                 bean.important = true; |                 bean.important = true; | ||||||
|  | 
 | ||||||
|  |                 debug(`[${this.name}] sendNotification`); | ||||||
|                 await Monitor.sendNotification(isFirstBeat, this, bean); |                 await Monitor.sendNotification(isFirstBeat, this, bean); | ||||||
| 
 | 
 | ||||||
|                 // Clear Status Page Cache
 |                 // Clear Status Page Cache
 | ||||||
|  |                 debug(`[${this.name}] Check isImportant`); | ||||||
|                 apicache.clear(); |                 apicache.clear(); | ||||||
| 
 | 
 | ||||||
|             } else { |             } else { | ||||||
|  | @ -397,10 +406,14 @@ class Monitor extends BeanModel { | ||||||
|                 console.warn(`Monitor #${this.id} '${this.name}': Failing: ${bean.msg} | Interval: ${beatInterval} seconds | Type: ${this.type}`); |                 console.warn(`Monitor #${this.id} '${this.name}': Failing: ${bean.msg} | Interval: ${beatInterval} seconds | Type: ${this.type}`); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|  |             debug(`[${this.name}] Send to socket`); | ||||||
|             io.to(this.user_id).emit("heartbeat", bean.toJSON()); |             io.to(this.user_id).emit("heartbeat", bean.toJSON()); | ||||||
|             Monitor.sendStats(io, this.id, this.user_id); |             Monitor.sendStats(io, this.id, this.user_id); | ||||||
| 
 | 
 | ||||||
|  |             debug(`[${this.name}] Store`); | ||||||
|             await R.store(bean); |             await R.store(bean); | ||||||
|  | 
 | ||||||
|  |             debug(`[${this.name}] prometheus.update`); | ||||||
|             prometheus.update(bean, tlsInfo); |             prometheus.update(bean, tlsInfo); | ||||||
| 
 | 
 | ||||||
|             previousBeat = bean; |             previousBeat = bean; | ||||||
|  | @ -414,7 +427,10 @@ class Monitor extends BeanModel { | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|  |                 debug(`[${this.name}] SetTimeout for next check.`); | ||||||
|                 this.heartbeatInterval = setTimeout(safeBeat, beatInterval * 1000); |                 this.heartbeatInterval = setTimeout(safeBeat, beatInterval * 1000); | ||||||
|  |             } else { | ||||||
|  |                 console.log(`[${this.name}] isStop = true, no next check.`); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|         }; |         }; | ||||||
|  |  | ||||||
|  | @ -101,6 +101,10 @@ router.get("/api/status-page/config", async (_request, response) => { | ||||||
|         config.statusPagePublished = true; |         config.statusPagePublished = true; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     if (! config.statusPageTags) { | ||||||
|  |         config.statusPageTags = false; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     if (! config.title) { |     if (! config.title) { | ||||||
|         config.title = "Uptime Kuma"; |         config.title = "Uptime Kuma"; | ||||||
|     } |     } | ||||||
|  | @ -140,10 +144,25 @@ router.get("/api/status-page/monitor-list", cache("5 minutes"), async (_request, | ||||||
|     try { |     try { | ||||||
|         await checkPublished(); |         await checkPublished(); | ||||||
|         const publicGroupList = []; |         const publicGroupList = []; | ||||||
|         let list = await R.find("group", " public = 1 ORDER BY weight "); |         const tagsVisible = (await getSettings("statusPage")).statusPageTags; | ||||||
| 
 |         const list = await R.find("group", " public = 1 ORDER BY weight "); | ||||||
|         for (let groupBean of list) { |         for (let groupBean of list) { | ||||||
|             publicGroupList.push(await groupBean.toPublicJSON()); |             let monitorGroup = await groupBean.toPublicJSON(); | ||||||
|  |             if (tagsVisible) { | ||||||
|  |                 monitorGroup.monitorList = await Promise.all(monitorGroup.monitorList.map(async (monitor) => { | ||||||
|  |                     // Includes tags as an array in response, allows for tags to be displayed on public status page
 | ||||||
|  |                     const tags = await R.getAll( | ||||||
|  |                             `SELECT monitor_tag.monitor_id, monitor_tag.value, tag.name, tag.color
 | ||||||
|  |                             FROM monitor_tag | ||||||
|  |                             JOIN tag | ||||||
|  |                             ON monitor_tag.tag_id = tag.id | ||||||
|  |                             WHERE monitor_tag.monitor_id = ?`, [monitor.id]
 | ||||||
|  |                         ); | ||||||
|  |                     return {...monitor, tags: tags} | ||||||
|  |                 })); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             publicGroupList.push(monitorGroup); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         response.json(publicGroupList); |         response.json(publicGroupList); | ||||||
|  |  | ||||||
|  | @ -346,6 +346,10 @@ textarea.form-control { | ||||||
|         &.active { |         &.active { | ||||||
|             background-color: #cdf8f4; |             background-color: #cdf8f4; | ||||||
|         } |         } | ||||||
|  |         .tags { | ||||||
|  |             // Removes margin to line up tags list with uptime percentage | ||||||
|  |             margin-left: -0.25rem; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -41,6 +41,9 @@ | ||||||
|                                             <Uptime :monitor="monitor.element" type="24" :pill="true" /> |                                             <Uptime :monitor="monitor.element" type="24" :pill="true" /> | ||||||
|                                             {{ monitor.element.name }} |                                             {{ monitor.element.name }} | ||||||
|                                         </div> |                                         </div> | ||||||
|  |                                         <div class="tags"> | ||||||
|  |                                             <Tag v-for="tag in monitor.element.tags" :key="tag" :item="tag" :size="'sm'" /> | ||||||
|  |                                         </div> | ||||||
|                                     </div> |                                     </div> | ||||||
|                                     <div :key="$root.userHeartbeatBar" class="col-3 col-md-4"> |                                     <div :key="$root.userHeartbeatBar" class="col-3 col-md-4"> | ||||||
|                                         <HeartbeatBar size="small" :monitor-id="monitor.element.id" /> |                                         <HeartbeatBar size="small" :monitor-id="monitor.element.id" /> | ||||||
|  | @ -59,12 +62,14 @@ | ||||||
| import Draggable from "vuedraggable"; | import Draggable from "vuedraggable"; | ||||||
| import HeartbeatBar from "./HeartbeatBar.vue"; | import HeartbeatBar from "./HeartbeatBar.vue"; | ||||||
| import Uptime from "./Uptime.vue"; | import Uptime from "./Uptime.vue"; | ||||||
|  | import Tag from "./Tag.vue"; | ||||||
| 
 | 
 | ||||||
| export default { | export default { | ||||||
|     components: { |     components: { | ||||||
|         Draggable, |         Draggable, | ||||||
|         HeartbeatBar, |         HeartbeatBar, | ||||||
|         Uptime, |         Uptime, | ||||||
|  |         Tag, | ||||||
|     }, |     }, | ||||||
|     props: { |     props: { | ||||||
|         editMode: { |         editMode: { | ||||||
|  |  | ||||||
|  | @ -1,5 +1,5 @@ | ||||||
| <template> | <template> | ||||||
|     <span :class="className">{{ uptime }}</span> |     <span :class="className" :title="24 + $t('-hour')">{{ uptime }}</span> | ||||||
| </template> | </template> | ||||||
| 
 | 
 | ||||||
| <script> | <script> | ||||||
|  |  | ||||||
|  | @ -279,4 +279,29 @@ export default { | ||||||
|     promosmsTypeSpeed: "SMS SPEED - La plus haute des priorités dans le système. Très rapide et fiable mais cher (environ le double du prix d'un SMS FULL).", |     promosmsTypeSpeed: "SMS SPEED - La plus haute des priorités dans le système. Très rapide et fiable mais cher (environ le double du prix d'un SMS FULL).", | ||||||
|     promosmsPhoneNumber: "Numéro de téléphone (Poiur les déstinataires Polonais, vous pouvez enlever les codes interna.)", |     promosmsPhoneNumber: "Numéro de téléphone (Poiur les déstinataires Polonais, vous pouvez enlever les codes interna.)", | ||||||
|     promosmsSMSSender: "SMS Expéditeur : Nom pré-enregistré ou l'un de base: InfoSMS, SMS Info, MaxSMS, INFO, SMS", |     promosmsSMSSender: "SMS Expéditeur : Nom pré-enregistré ou l'un de base: InfoSMS, SMS Info, MaxSMS, INFO, SMS", | ||||||
|  |     "Primary Base URL": "Primary Base URL", | ||||||
|  |     emailCustomSubject: "Sujet personalisé", | ||||||
|  |     clicksendsms: "ClickSend SMS", | ||||||
|  |     checkPrice: "Vérification {0} tarifs:", | ||||||
|  |     apiCredentials: "Crédentials de l'API", | ||||||
|  |     octopushLegacyHint: "Vous utilisez l'ancienne version d'Octopush (2011-2020) ou la nouvelle version ?", | ||||||
|  |     "Feishu WebHookUrl": "Feishu WebHookURL", | ||||||
|  |     matrixHomeserverURL: "L'URL du serveur (avec http(s):// et le port de manière facultatif)", | ||||||
|  |     "Internal Room Id": "ID de la salle interne", | ||||||
|  |     matrixDesc1: "Vous pouvez trouvez l'ID de salle interne en regardant dans la section avancée des paramètres dans le client Matrix. C'est sensé ressembler à: !QMdRCpUIfLwsfjxye6:home.server.", | ||||||
|  |     matrixDesc2: "Il est fortement recommandé de créer un nouvel utilisateur et de ne pas utiliser le jeton d'accès de votre propre utilisateur Matrix, car il vous donnera un accès complet à votre compte et à toutes les salles que vous avez rejointes. Au lieu de cela, créez un nouvel utilisateur et invitez-le uniquement dans la salle dans laquelle vous souhaitez recevoir la notification. Vous pouvez obtenir le jeton d'accès en exécutant {0}", | ||||||
|  |     Method: "Méthode", | ||||||
|  |     Body: "Le corps", | ||||||
|  |     Headers: "En-têtes", | ||||||
|  |     PushUrl: "Push URL", | ||||||
|  |     HeadersInvalidFormat: "L'en-têtes de la requête n'est pas dans un format JSON valide: ", | ||||||
|  |     BodyInvalidFormat: "Le corps de la requête n'est pas dans un format JSON valide: ", | ||||||
|  |     "Monitor History": "Historique de la sonde", | ||||||
|  |     clearDataOlderThan: "Garder l'historique des données de la sonde durant {0} jours.", | ||||||
|  |     PasswordsDoNotMatch: "Les mots de passe ne correspondent pas.", | ||||||
|  |     records: "Enregistrements", | ||||||
|  |     "One record": "Un enregistrement", | ||||||
|  |     steamApiKeyDescription: "Pour surveiller un serveur Steam, vous avez besoin  d'une clé Steam Web-API. Vous pouvez enregistrer votre clé ici: ", | ||||||
|  |     "Current User": "Utilisateur actuel", | ||||||
|  |     recent: "Récent", | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | @ -77,6 +77,17 @@ | ||||||
|                     <font-awesome-icon icon="save" /> |                     <font-awesome-icon icon="save" /> | ||||||
|                     {{ $t("Switch to Dark Theme") }} |                     {{ $t("Switch to Dark Theme") }} | ||||||
|                 </button> |                 </button> | ||||||
|  | 
 | ||||||
|  |                 <button class="btn btn-secondary me-2" @click="changeTagsVisibilty(!tagsVisible)"> | ||||||
|  |                     <template v-if="tagsVisible"> | ||||||
|  |                         <font-awesome-icon icon="eye-slash" /> | ||||||
|  |                         {{ $t("Hide Tags") }} | ||||||
|  |                     </template> | ||||||
|  |                     <template v-else> | ||||||
|  |                         <font-awesome-icon icon="eye" /> | ||||||
|  |                         {{ $t("Show Tags") }} | ||||||
|  |                     </template> | ||||||
|  |                 </button> | ||||||
|             </div> |             </div> | ||||||
|         </div> |         </div> | ||||||
| 
 | 
 | ||||||
|  | @ -292,6 +303,10 @@ export default { | ||||||
|             return this.config.statusPageTheme; |             return this.config.statusPageTheme; | ||||||
|         }, |         }, | ||||||
| 
 | 
 | ||||||
|  |         tagsVisible() { | ||||||
|  |             return this.config.statusPageTags | ||||||
|  |         }, | ||||||
|  | 
 | ||||||
|         logoClass() { |         logoClass() { | ||||||
|             if (this.editMode) { |             if (this.editMode) { | ||||||
|                 return { |                 return { | ||||||
|  | @ -472,6 +487,25 @@ export default { | ||||||
|         changeTheme(name) { |         changeTheme(name) { | ||||||
|             this.config.statusPageTheme = name; |             this.config.statusPageTheme = name; | ||||||
|         }, |         }, | ||||||
|  |         changeTagsVisibilty(newState) { | ||||||
|  |             this.config.statusPageTags = newState; | ||||||
|  | 
 | ||||||
|  |             // On load, the status page will not include tags if it's not enabled for security reasons | ||||||
|  |             // Which means if we enable tags, it won't show in the UI until saved | ||||||
|  |             // So we have this to enhance UX and load in the tags from the authenticated source instantly | ||||||
|  |             this.$root.publicGroupList = this.$root.publicGroupList.map((group) => { | ||||||
|  |                 return { | ||||||
|  |                     ...group, | ||||||
|  |                     monitorList: group.monitorList.map((monitor) => { | ||||||
|  |                         // We only include the tags if visible so we can reuse the logic to hide the tags on disable | ||||||
|  |                         return { | ||||||
|  |                             ...monitor, | ||||||
|  |                             tags: newState ? this.$root.monitorList[monitor.id].tags : [] | ||||||
|  |                         } | ||||||
|  |                     }) | ||||||
|  |                 } | ||||||
|  |             }); | ||||||
|  |         }, | ||||||
| 
 | 
 | ||||||
|         /** |         /** | ||||||
|          * Crop Success |          * Crop Success | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue