Improve the workflow of cloudflared

This commit is contained in:
Louis Lam 2022-03-30 11:59:49 +08:00
parent f1f4b3b377
commit 82ea896bbc
5 changed files with 70 additions and 19 deletions

View file

@ -83,7 +83,7 @@
"jsonwebtoken": "~8.5.1", "jsonwebtoken": "~8.5.1",
"jwt-decode": "^3.1.2", "jwt-decode": "^3.1.2",
"limiter": "^2.1.0", "limiter": "^2.1.0",
"node-cloudflared-tunnel": "~1.0.6", "node-cloudflared-tunnel": "~1.0.7",
"nodemailer": "~6.6.5", "nodemailer": "~6.6.5",
"notp": "~2.0.3", "notp": "~2.0.3",
"password-hash": "~1.2.2", "password-hash": "~1.2.2",

View file

@ -133,7 +133,7 @@ const { statusPageSocketHandler } = require("./socket-handlers/status-page-socke
const databaseSocketHandler = require("./socket-handlers/database-socket-handler"); const databaseSocketHandler = require("./socket-handlers/database-socket-handler");
const TwoFA = require("./2fa"); const TwoFA = require("./2fa");
const StatusPage = require("./model/status_page"); const StatusPage = require("./model/status_page");
const { cloudflaredSocketHandler } = require("./socket-handlers/cloudflared-socket-handler"); const { cloudflaredSocketHandler, autoStart: cloudflaredAutoStart } = require("./socket-handlers/cloudflared-socket-handler");
app.use(express.json()); app.use(express.json());
@ -1406,6 +1406,9 @@ exports.entryPage = "dashboard";
initBackgroundJobs(args); initBackgroundJobs(args);
// Start cloudflared at the end if configured
await cloudflaredAutoStart();
})(); })();
async function updateMonitorNotification(monitorID, notificationIDList) { async function updateMonitorNotification(monitorID, notificationIDList) {

View file

@ -1,17 +1,13 @@
const { checkLogin, setSetting, setting } = require("../util-server"); const { checkLogin, setSetting, setting, doubleCheckPassword } = require("../util-server");
const { CloudflaredTunnel } = require("node-cloudflared-tunnel"); const { CloudflaredTunnel } = require("node-cloudflared-tunnel");
const { io } = require("../server"); const { io } = require("../server");
const prefix = "cloudflared_"; const prefix = "cloudflared_";
const cloudflared = new CloudflaredTunnel(); const cloudflared = new CloudflaredTunnel();
let isRunning;
cloudflared.change = (running, message) => { cloudflared.change = (running, message) => {
io.to("cloudflared").emit(prefix + "running", running); io.to("cloudflared").emit(prefix + "running", running);
io.to("cloudflared").emit(prefix + "message", message); io.to("cloudflared").emit(prefix + "message", message);
isRunning = running;
}; };
cloudflared.error = (errorMessage) => { cloudflared.error = (errorMessage) => {
@ -25,7 +21,7 @@ module.exports.cloudflaredSocketHandler = (socket) => {
checkLogin(socket); checkLogin(socket);
socket.join("cloudflared"); socket.join("cloudflared");
io.to(socket.userID).emit(prefix + "installed", cloudflared.checkInstalled()); io.to(socket.userID).emit(prefix + "installed", cloudflared.checkInstalled());
io.to(socket.userID).emit(prefix + "running", isRunning); io.to(socket.userID).emit(prefix + "running", cloudflared.running);
io.to(socket.userID).emit(prefix + "token", await setting("cloudflaredTunnelToken")); io.to(socket.userID).emit(prefix + "token", await setting("cloudflaredTunnelToken"));
} catch (error) { } } catch (error) { }
}); });
@ -62,11 +58,34 @@ module.exports.cloudflaredSocketHandler = (socket) => {
} catch (error) { } } catch (error) { }
}); });
socket.on(prefix + "stop", async () => { socket.on(prefix + "stop", async (currentPassword, callback) => {
try { try {
checkLogin(socket); checkLogin(socket);
await doubleCheckPassword(socket, currentPassword);
cloudflared.stop(); cloudflared.stop();
} catch (error) {
callback({
ok: false,
msg: error.message,
});
}
});
socket.on(prefix + "removeToken", async () => {
try {
checkLogin(socket);
await setSetting("cloudflaredTunnelToken", "");
} catch (error) { } } catch (error) { }
}); });
}; };
module.exports.autoStart = async () => {
let token = await setting("cloudflaredTunnelToken");
if (token) {
console.log("Start cloudflared");
cloudflared.token = token;
cloudflared.start();
}
};

View file

@ -19,7 +19,7 @@
{{ message }} {{ message }}
</div> </div>
<div class="mt-3"> <div v-if="errorMessage" class="mt-3">
Message: Message:
<textarea v-model="errorMessage" class="form-control" readonly></textarea> <textarea v-model="errorMessage" class="form-control" readonly></textarea>
</div> </div>
@ -37,8 +37,13 @@
id="cloudflareTunnelToken" id="cloudflareTunnelToken"
v-model="cloudflareTunnelToken" v-model="cloudflareTunnelToken"
autocomplete="one-time-code" autocomplete="one-time-code"
:readonly="running"
/> />
<div class="form-text"> <div class="form-text">
<div v-if="cloudflareTunnelToken" class="mb-3">
<span v-if="!running" class="remove-token" @click="removeToken">{{ $t("Remove Token") }}</span>
</div>
Don't know how to get the token? Please read the guide:<br /> Don't know how to get the token? Please read the guide:<br />
<a href="https://github.com/louislam/uptime-kuma/wiki/Reverse-Proxy-with-Cloudflare-Tunnel" target="_blank"> <a href="https://github.com/louislam/uptime-kuma/wiki/Reverse-Proxy-with-Cloudflare-Tunnel" target="_blank">
https://github.com/louislam/uptime-kuma/wiki/Reverse-Proxy-with-Cloudflare-Tunnel https://github.com/louislam/uptime-kuma/wiki/Reverse-Proxy-with-Cloudflare-Tunnel
@ -46,15 +51,31 @@
</div> </div>
</div> </div>
<!-- Save Button -->
<div> <div>
<button v-if="!running" class="btn btn-primary" type="submit" @click="start"> <button v-if="!running" class="btn btn-primary" type="submit" @click="start">
{{ $t("Start") }} cloudflared {{ $t("Start") }} cloudflared
</button> </button>
<button v-if="running" class="btn btn-danger" type="submit" @click="stop"> <button v-if="running" class="btn btn-danger" type="submit" @click="$refs.confirmStop.show();">
{{ $t("Stop") }} cloudflared {{ $t("Stop") }} cloudflared
</button> </button>
<Confirm ref="confirmStop" btn-style="btn-danger" :yes-text="$t('Stop') + ' cloudflared'" :no-text="$t('Cancel')" @yes="stop">
The current connection may be lost if you are connecting Cloudflare Tunnel. Are you sure want to stop it? Type your password to confirm it.
<div class="mt-3">
<label for="current-password2" class="form-label">
{{ $t("Current Password") }}
</label>
<input
id="current-password2"
v-model="currentPassword"
type="password"
class="form-control"
required
/>
</div>
</Confirm>
</div> </div>
</div> </div>
@ -68,14 +89,17 @@
<script> <script>
import HiddenInput from "../../components/HiddenInput.vue"; import HiddenInput from "../../components/HiddenInput.vue";
import Confirm from "../Confirm.vue";
const prefix = "cloudflared_"; const prefix = "cloudflared_";
export default { export default {
components: { components: {
HiddenInput, HiddenInput,
Confirm
}, },
data() { data() {
// See /src/mixins/socket.js
return this.$root.cloudflared; return this.$root.cloudflared;
}, },
computed: { computed: {
@ -84,7 +108,7 @@ export default {
watch: { watch: {
}, },
mounted() { created() {
this.$root.getSocket().emit(prefix + "join"); this.$root.getSocket().emit(prefix + "join");
}, },
unmounted() { unmounted() {
@ -95,17 +119,21 @@ export default {
this.$root.getSocket().emit(prefix + "start", this.cloudflareTunnelToken); this.$root.getSocket().emit(prefix + "start", this.cloudflareTunnelToken);
}, },
stop() { stop() {
this.$root.getSocket().emit(prefix + "stop"); this.$root.getSocket().emit(prefix + "stop", this.currentPassword, (res) => {
this.$root.toastRes(res);
});
}, },
removeToken() {
this.$root.getSocket().emit(prefix + "removeToken");
this.cloudflareTunnelToken = "";
}
} }
}; };
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.logo { .remove-token {
margin: 4em 1em; text-decoration: underline;
} cursor: pointer;
.update-link {
font-size: 0.9em;
} }
</style> </style>

View file

@ -48,6 +48,7 @@ export default {
running: false, running: false,
message: "", message: "",
errorMessage: "", errorMessage: "",
currentPassword: "",
} }
}; };
}, },