123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457 |
- <template>
- <v-layout
- column
- fill-height
- >
- <v-toolbar color="grey">
- <v-toolbar-title flex>
- {{ title }}
- </v-toolbar-title>
- <v-spacer />
- <v-text-field
- v-if="this.hideUrl == undefined"
- :disabled="disableUrl"
- label="Telws URL"
- single-line
- prepend-icon="mdi-link-variant"
- hide-details
- v-model="telwsurl"
- />
- <v-tooltip bottom>
- <template v-slot:activator="{ on }">
- <v-btn
- icon
- @click="connect"
- v-on="on"
- >
- <v-icon>mdi-lan-connect</v-icon>
- </v-btn>
- </template>
- <span>Connect</span>
- </v-tooltip>
- <v-tooltip bottom>
- <template v-slot:activator="{ on }">
- <v-btn
- icon
- @click="disconnect"
- v-on="on"
- >
- <v-icon>mdi-lan-disconnect</v-icon>
- </v-btn>
- </template>
- <span>Disconnect</span>
- </v-tooltip>
- <v-tooltip bottom>
- <template v-slot:activator="{ on }">
- <v-btn
- icon
- v-on="on"
- @click="popChangeBackgroundDialog"
- >
- <v-icon>mdi-palette</v-icon>
- </v-btn>
- </template>
- <span>Change Console Background Color</span>
- </v-tooltip>
- </v-toolbar>
- <v-layout fill-height>
- <xterm-vue
- ref="term"
- v-on:title-change="titleChange"
- />
- </v-layout>
- <v-toolbar color="grey">
- <v-text-field
- placeholder="Write here and press Enter to send..."
- single-line
- prepend-icon="mdi-typewriter"
- hide-details
- v-model="writeBarText"
- @keydown.enter="pasteWriteBar"
- />
- </v-toolbar>
- <v-dialog
- v-model="userAuthDialog"
- max-width="290"
- >
- <v-card>
- <v-card-title class="headline">Simple AAA Auth</v-card-title>
- <v-card-text>
- <v-form>
- <v-text-field
- ref="authUsername"
- v-model="authDialogUsername"
- label="Username"
- @keydown.enter="focusPasswordTextfield"
- />
- <v-text-field
- ref="authPassword"
- v-model="authDialogPassword"
- label="Password"
- type="password"
- @keydown.enter="doUserLogin"
- />
- </v-form>
- </v-card-text>
- <v-card-actions>
- <v-spacer></v-spacer>
- <v-btn
- color="danger"
- text
- @click="cancelUserLogin"
- >
- Cancel
- </v-btn>
- <v-btn
- color="success"
- text
- @click="doUserLogin"
- >
- Login
- </v-btn>
- </v-card-actions>
- </v-card>
- </v-dialog>
- <v-dialog
- v-model="changeBackgroundDialog"
- max-width="290"
- >
- <v-card>
- <v-card-title class="headline">Change Background</v-card-title>
- <v-card-text>
- <v-color-picker
- flat
- hide-mode-switch
- mode="hexa"
- v-model="background"
- />
- </v-card-text>
- <v-card-actions>
- <v-spacer></v-spacer>
- <v-btn
- color="danger"
- text
- @click="closeChangeBackgroundDialog"
- >
- Close
- </v-btn>
- </v-card-actions>
- </v-card>
- </v-dialog>
- </v-layout>
- </template>
- <script>
- //import XtermVuePlugin from "@swzry/xterm-vue";
- import axios from "axios";
- import smcrypto from "sm-crypto";
- const ConnState = {
- IDLE: 0,
- GET_INFO: 1,
- USER_AUTH: 2,
- SERVER_AUTH: 3,
- AUTH_OK: 4,
- CONNECTED: 5
- };
- export default {
- name: "telws_view",
- props: [
- "hideUrl",
- "defaultUrl",
- "autoConnect",
- "defaultBackground",
- "disableUrl"
- ],
- watch: {
- background(newVal, oldVal) {
- if (this.$refs.term.$term) {
- console.log("Change Background", this.$refs.term.$term, newVal);
- this.$refs.term.$term.setOption("theme", { background: newVal });
- }
- }
- },
- data: () => ({
- background: "",
- writeBarText: "",
- title: "Untitled",
- telwsurl: "",
- changeBackgroundDialog: false,
- userAuthDialog: false,
- authDialogUsername: "",
- authDialogPassword: "",
- connSM: {
- state: ConnState.IDLE,
- axiosCancel: undefined,
- continueDo: false,
- url_prefix: "",
- auth_jwt: "",
- wsurl: "",
- wsconn: undefined
- },
- encryptConfig: undefined
- }),
- mounted() {
- this.$refs.term.fit();
- if (this.defaultBackground) {
- this.background = this.defaultBackground;
- } else {
- this.background = "#002b36";
- }
- if (this.defaultUrl) {
- this.telwsurl = this.defaultUrl;
- }
- if (this.autoConnect != undefined) {
- this.connect();
- }
- },
- destroyed() {
- this.disconnect();
- },
- methods: {
- popChangeBackgroundDialog() {
- this.changeBackgroundDialog = true;
- },
- closeChangeBackgroundDialog() {
- this.changeBackgroundDialog = false;
- },
- focusUsernameTextfield() {
- this.$refs.authUsername.focus();
- },
- focusPasswordTextfield() {
- this.$refs.authPassword.focus();
- },
- pasteWriteBar(event) {
- this.$refs.term.paste(this.writeBarText);
- this.writeBarText = "";
- },
- titleChange(title) {
- this.title = title;
- },
- popUserLoginDialog() {
- this.authDialogUsername = "";
- this.authDialogPassword = "";
- this.userAuthDialog = true;
- var self = this;
- this.$nextTick(() => {
- self.focusUsernameTextfield();
- });
- },
- doUserLogin() {
- this.userAuthDialog = false;
- var authData = {
- method: "simple-aaa",
- username: this.authDialogUsername,
- password: this.authDialogPassword
- };
- var jsondata = JSON.stringify(authData);
- var cm = 1;
- if (this.encryptConfig.cipherMode === "C1C3C2") {
- cm = 1;
- } else {
- cm = 0;
- }
- if (this.encryptConfig) {
- var ct = smcrypto.sm2.doEncrypt(
- jsondata,
- this.encryptConfig.pubkey,
- cm
- );
- var tureCipher = this.encryptConfig.header + ct;
- this.doLoginAuth(tureCipher);
- } else {
- this.connSM.state = ConnState.IDLE;
- this.$refs.term.$term.writeln("Password encypt failed.");
- this.$refs.term.$term.onData(function(data) {});
- }
- },
- doWebsocketConnect() {
- if (this.connSM.wsconn) {
- this.connSM.wsconn.close();
- }
- this.$refs.term.$term.writeln(
- "Connecting Websocket '" + this.connSM.wsurl + "'..."
- );
- var trueUrl = this.connSM.wsurl + "?token=" + this.connSM.auth_jwt;
- this.connSM.wsconn = new WebSocket(trueUrl);
- var tty = this.$refs.term.$term;
- var wsconn = this.connSM.wsconn;
- var self = this;
- wsconn.onopen = function() {
- //wsconn.binaryType = "arrayBuffer"
- wsconn.binaryType = "blob";
- tty.writeln("Connected.\r\n");
- self.connSM.state = ConnState.CONNECTED;
- };
- wsconn.onmessage = function(event) {
- var er = new FileReader();
- er.onload = function(e) {
- var buf = new Uint8Array(er.result);
- tty.write(buf);
- };
- er.readAsArrayBuffer(event.data);
- };
- wsconn.onclose = function() {
- tty.writeln("\r\n\r\nConnection Closed.");
- };
- wsconn.onerror = function() {
- tty.writeln("\r\n\r\nConnection Error.");
- };
- this.$refs.term.$term.onData(function(data) {
- if (wsconn) {
- var bd = Buffer.from(data, "utf8");
- wsconn.send(bd);
- }
- });
- },
- doLoginAuth(authData) {
- var adjson = { authData: authData };
- var self = this;
- this.connSM.state = ConnState.SERVER_AUTH;
- axios
- .post(this.connSM.url_prefix + "login.satori", adjson, {
- cancelToken: new axios.CancelToken(function executor(c) {
- self.connSM.cancelToken = c;
- })
- })
- .then(resp => {
- if (resp.data.suc) {
- this.connSM.auth_jwt = resp.data.jwt;
- this.connSM.state = ConnState.AUTH_OK;
- this.doWebsocketConnect();
- } else {
- if (resp.data.etype == "auth_failed") {
- this.$refs.term.$term.writeln("Simple AAA Auth Failed.");
- this.$refs.term.$term.writeln(
- "Reason: " + resp.data.auth_error_msg
- );
- } else {
- this.$refs.term.$term.writeln("Failed to do remote auth.");
- this.$refs.term.$term.writeln("Error: " + resp.data.etype);
- }
- this.connSM.state = ConnState.IDLE;
- }
- })
- .catch(errmsg => {
- this.$refs.term.$term.writeln("Failed to do remote auth.");
- console.warn(errmsg);
- if (errmsg.response) {
- console.warn(errmsg.response);
- this.$refs.term.$term.writeln("Error: " + errmsg.response.data);
- } else if (errmsg.request) {
- console.warn(errmsg.request);
- this.$refs.term.$term.writeln(
- "Error: request failed. See javascript console for detail."
- );
- } else {
- this.$refs.term.$term.writeln(
- "Error: unknown. See javascript console for more detail."
- );
- }
- this.connSM.state = ConnState.IDLE;
- });
- },
- cancelUserLogin() {
- this.userAuthDialog = false;
- this.connSM.state = ConnState.IDLE;
- this.$refs.term.$term.writeln("Auth cancel by user.");
- this.$refs.term.$term.onData(function(data) {});
- },
- disconnect() {
- if (this.connSM.state == ConnState.IDLE) {
- return;
- }
- this.connSM.continueDo = false;
- if (this.connSM.cancelToken) {
- this.connSM.cancelToken();
- }
- this.connSM.state = ConnState.IDLE;
- this.$refs.term.$term.writeln("");
- this.$refs.term.$term.writeln("Disconnected.");
- this.$refs.term.$term.onData(function(data) {});
- if (this.connSM.wsconn) {
- this.connSM.wsconn.close();
- }
- },
- connect() {
- if (this.connSM.state != ConnState.IDLE) {
- this.disconnect();
- }
- this.$refs.term.$term.clear();
- if (this.telwsurl.charAt(this.telwsurl.length - 1) == "/") {
- this.connSM.url_prefix = this.telwsurl;
- } else {
- this.connSM.url_prefix = this.telwsurl + "/";
- }
- var turl = new URL(this.connSM.url_prefix);
- var schpre = "ws:";
- if (turl.protocol === "https:") {
- schpre = "wss:";
- }
- this.connSM.wsurl =
- schpre + "//" + turl.host + turl.pathname + "ws.satori";
- this.$refs.term.$term.writeln("Connecting " + this.telwsurl + "...");
- var self = this;
- this.connSM.continueDo = true;
- this.connSM.state = ConnState.GET_INFO;
- axios
- .get(this.telwsurl, {
- cancelToken: new axios.CancelToken(function executor(c) {
- self.connSM.cancelToken = c;
- })
- })
- .then(resp => {
- if (self.connSM.continueDo) {
- this.$refs.term.$term.writeln("Telws server info fetched.");
- console.log(resp.data);
- if (resp.data.auth_methods) {
- if (resp.data.auth_methods.indexOf("simple-aaa") > -1) {
- this.encryptConfig = resp.data.encrypt;
- this.connSM.state = ConnState.USER_AUTH;
- this.popUserLoginDialog();
- } else {
- this.$refs.term.$term.writeln(
- "Failed to connect to telws server."
- );
- this.$refs.term.$term.writeln(
- "Error: no auth method supported by this client."
- );
- this.connSM.state = ConnState.IDLE;
- }
- } else {
- this.$refs.term.$term.writeln(
- "Failed to connect to telws server."
- );
- this.$refs.term.$term.writeln("Error: not a valid telws server.");
- this.connSM.state = ConnState.IDLE;
- }
- }
- })
- .catch(errmsg => {
- this.$refs.term.$term.writeln("Failed to connect to telws server.");
- console.warn(errmsg);
- if (errmsg.response) {
- console.warn(errmsg.response);
- this.$refs.term.$term.writeln("Error: " + errmsg.response.data);
- } else if (errmsg.request) {
- console.warn(errmsg.request);
- this.$refs.term.$term.writeln(
- "Error: request failed. See javascript console for detail."
- );
- } else {
- this.$refs.term.$term.writeln(
- "Error: unknown. See javascript console for more detail."
- );
- }
- this.connSM.state = ConnState.IDLE;
- });
- }
- }
- };
- </script>
|