mirror of
				https://github.com/TeaOSLab/EdgeAdmin.git
				synced 2025-11-04 13:10:26 +08:00 
			
		
		
		
	证书上传时可以选择输入文本内容
This commit is contained in:
		@@ -7,6 +7,7 @@ import (
 | 
				
			|||||||
	"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
 | 
						"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
 | 
				
			||||||
	"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/sslconfigs"
 | 
						"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/sslconfigs"
 | 
				
			||||||
	"github.com/iwind/TeaGo/actions"
 | 
						"github.com/iwind/TeaGo/actions"
 | 
				
			||||||
 | 
						timeutil "github.com/iwind/TeaGo/utils/time"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type UpdatePopupAction struct {
 | 
					type UpdatePopupAction struct {
 | 
				
			||||||
@@ -45,6 +46,8 @@ func (this *UpdatePopupAction) RunGet(params struct {
 | 
				
			|||||||
func (this *UpdatePopupAction) RunPost(params struct {
 | 
					func (this *UpdatePopupAction) RunPost(params struct {
 | 
				
			||||||
	CertId int64
 | 
						CertId int64
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						TextMode bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Name        string
 | 
						Name        string
 | 
				
			||||||
	IsCA        bool
 | 
						IsCA        bool
 | 
				
			||||||
	Description string
 | 
						Description string
 | 
				
			||||||
@@ -53,6 +56,9 @@ func (this *UpdatePopupAction) RunPost(params struct {
 | 
				
			|||||||
	CertFile *actions.File
 | 
						CertFile *actions.File
 | 
				
			||||||
	KeyFile  *actions.File
 | 
						KeyFile  *actions.File
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						CertText string
 | 
				
			||||||
 | 
						KeyText  string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Must *actions.Must
 | 
						Must *actions.Must
 | 
				
			||||||
}) {
 | 
					}) {
 | 
				
			||||||
	// 创建日志
 | 
						// 创建日志
 | 
				
			||||||
@@ -82,18 +88,31 @@ func (this *UpdatePopupAction) RunPost(params struct {
 | 
				
			|||||||
		Field("name", params.Name).
 | 
							Field("name", params.Name).
 | 
				
			||||||
		Require("请输入证书说明")
 | 
							Require("请输入证书说明")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if params.CertFile != nil {
 | 
						if params.TextMode {
 | 
				
			||||||
		certConfig.CertData, err = params.CertFile.Read()
 | 
							if len(params.CertText) > 0 {
 | 
				
			||||||
		if err != nil {
 | 
								certConfig.CertData = []byte(params.CertText)
 | 
				
			||||||
			this.Fail("读取证书文件内容错误,请重新上传")
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if !params.IsCA {
 | 
							if !params.IsCA {
 | 
				
			||||||
		if params.KeyFile != nil {
 | 
								if len(params.KeyText) > 0 {
 | 
				
			||||||
			certConfig.KeyData, err = params.KeyFile.Read()
 | 
									certConfig.KeyData = []byte(params.KeyText)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if params.CertFile != nil {
 | 
				
			||||||
 | 
								certConfig.CertData, err = params.CertFile.Read()
 | 
				
			||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
				this.Fail("读取密钥文件内容错误,请重新上传")
 | 
									this.FailField("certFile", "读取证书文件内容错误,请重新上传")
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if !params.IsCA {
 | 
				
			||||||
 | 
								if params.KeyFile != nil {
 | 
				
			||||||
 | 
									certConfig.KeyData, err = params.KeyFile.Read()
 | 
				
			||||||
 | 
									if err != nil {
 | 
				
			||||||
 | 
										this.FailField("keyFile", "读取私钥文件内容错误,请重新上传")
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -109,6 +128,10 @@ func (this *UpdatePopupAction) RunPost(params struct {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(timeutil.Format("Y", certConfig.TimeEnd())) != 4 {
 | 
				
			||||||
 | 
							this.Fail("证书格式错误:无法读取到证书有效期")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// 保存
 | 
						// 保存
 | 
				
			||||||
	_, err = this.RPC().SSLCertRPC().UpdateSSLCert(this.AdminContext(), &pb.UpdateSSLCertRequest{
 | 
						_, err = this.RPC().SSLCertRPC().UpdateSSLCert(this.AdminContext(), &pb.UpdateSSLCertRequest{
 | 
				
			||||||
		SslCertId:   params.CertId,
 | 
							SslCertId:   params.CertId,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,6 +7,7 @@ import (
 | 
				
			|||||||
	"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
 | 
						"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
 | 
				
			||||||
	"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/sslconfigs"
 | 
						"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/sslconfigs"
 | 
				
			||||||
	"github.com/iwind/TeaGo/actions"
 | 
						"github.com/iwind/TeaGo/actions"
 | 
				
			||||||
 | 
						timeutil "github.com/iwind/TeaGo/utils/time"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type UploadPopupAction struct {
 | 
					type UploadPopupAction struct {
 | 
				
			||||||
@@ -22,6 +23,7 @@ func (this *UploadPopupAction) RunGet(params struct{}) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (this *UploadPopupAction) RunPost(params struct {
 | 
					func (this *UploadPopupAction) RunPost(params struct {
 | 
				
			||||||
 | 
						TextMode    bool
 | 
				
			||||||
	Name        string
 | 
						Name        string
 | 
				
			||||||
	IsCA        bool
 | 
						IsCA        bool
 | 
				
			||||||
	Description string
 | 
						Description string
 | 
				
			||||||
@@ -30,6 +32,9 @@ func (this *UploadPopupAction) RunPost(params struct {
 | 
				
			|||||||
	CertFile *actions.File
 | 
						CertFile *actions.File
 | 
				
			||||||
	KeyFile  *actions.File
 | 
						KeyFile  *actions.File
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						CertText string
 | 
				
			||||||
 | 
						KeyText  string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Must *actions.Must
 | 
						Must *actions.Must
 | 
				
			||||||
}) {
 | 
					}) {
 | 
				
			||||||
	params.Must.
 | 
						params.Must.
 | 
				
			||||||
@@ -39,22 +44,37 @@ func (this *UploadPopupAction) RunPost(params struct {
 | 
				
			|||||||
	certData := []byte{}
 | 
						certData := []byte{}
 | 
				
			||||||
	keyData := []byte{}
 | 
						keyData := []byte{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if params.CertFile == nil {
 | 
						if params.TextMode {
 | 
				
			||||||
		this.Fail("请选择要上传的证书文件")
 | 
							if len(params.CertText) == 0 {
 | 
				
			||||||
	}
 | 
								this.FailField("certText", "请输入证书内容")
 | 
				
			||||||
	var err error
 | 
							}
 | 
				
			||||||
	certData, err = params.CertFile.Read()
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		this.Fail("读取证书文件内容错误,请重新上传")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if !params.IsCA {
 | 
							if !params.IsCA {
 | 
				
			||||||
		if params.KeyFile == nil {
 | 
								if len(params.KeyText) == 0 {
 | 
				
			||||||
			this.Fail("请选择要上传的私钥文件")
 | 
									this.FailField("keyText", "请输入私钥内容")
 | 
				
			||||||
		} else {
 | 
								}
 | 
				
			||||||
			keyData, err = params.KeyFile.Read()
 | 
							}
 | 
				
			||||||
			if err != nil {
 | 
					
 | 
				
			||||||
				this.Fail("读取密钥文件内容错误,请重新上传")
 | 
							certData = []byte(params.CertText)
 | 
				
			||||||
 | 
							keyData = []byte(params.KeyText)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							if params.CertFile == nil {
 | 
				
			||||||
 | 
								this.FailField("certFile", "请选择要上传的证书文件")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							var err error
 | 
				
			||||||
 | 
							certData, err = params.CertFile.Read()
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								this.FailField("certFile", "读取证书文件内容错误,请重新上传")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if !params.IsCA {
 | 
				
			||||||
 | 
								if params.KeyFile == nil {
 | 
				
			||||||
 | 
									this.FailField("keyFile", "请选择要上传的私钥文件")
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									keyData, err = params.KeyFile.Read()
 | 
				
			||||||
 | 
									if err != nil {
 | 
				
			||||||
 | 
										this.FailField("keyFile", "读取密钥文件内容错误,请重新上传")
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -65,7 +85,7 @@ func (this *UploadPopupAction) RunPost(params struct {
 | 
				
			|||||||
		CertData: certData,
 | 
							CertData: certData,
 | 
				
			||||||
		KeyData:  keyData,
 | 
							KeyData:  keyData,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	err = sslConfig.Init()
 | 
						err := sslConfig.Init()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		if params.IsCA {
 | 
							if params.IsCA {
 | 
				
			||||||
			this.Fail("证书校验错误:" + err.Error())
 | 
								this.Fail("证书校验错误:" + err.Error())
 | 
				
			||||||
@@ -73,6 +93,9 @@ func (this *UploadPopupAction) RunPost(params struct {
 | 
				
			|||||||
			this.Fail("证书或密钥校验错误:" + err.Error())
 | 
								this.Fail("证书或密钥校验错误:" + err.Error())
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						if len(timeutil.Format("Y", sslConfig.TimeEnd())) != 4 {
 | 
				
			||||||
 | 
							this.Fail("证书格式错误:无法读取到证书有效期")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// 保存
 | 
						// 保存
 | 
				
			||||||
	createResp, err := this.RPC().SSLCertRPC().CreateSSLCert(this.AdminContext(), &pb.CreateSSLCertRequest{
 | 
						createResp, err := this.RPC().SSLCertRPC().CreateSSLCert(this.AdminContext(), &pb.CreateSSLCertRequest{
 | 
				
			||||||
 
 | 
				
			|||||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							@@ -44,7 +44,7 @@
 | 
				
			|||||||
		<tr v-for="(cert, index) in certs">
 | 
							<tr v-for="(cert, index) in certs">
 | 
				
			||||||
            <td><keyword :v-word="keyword">{{cert.name}}</keyword>
 | 
					            <td><keyword :v-word="keyword">{{cert.name}}</keyword>
 | 
				
			||||||
				<div v-if="cert.isCA" style="margin-top:0.5em">
 | 
									<div v-if="cert.isCA" style="margin-top:0.5em">
 | 
				
			||||||
					<micro-basic-label :class="olive">CA</micro-basic-label>
 | 
										<micro-basic-label class="olive">CA</micro-basic-label>
 | 
				
			||||||
				</div>
 | 
									</div>
 | 
				
			||||||
				<div v-if="cert.isACME" style="margin-top: 0.5em">
 | 
									<div v-if="cert.isACME" style="margin-top: 0.5em">
 | 
				
			||||||
					<micro-basic-label class="olive" title="通过ACME协议免费申请">ACME</micro-basic-label>
 | 
										<micro-basic-label class="olive" title="通过ACME协议免费申请">ACME</micro-basic-label>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,7 +2,7 @@ Tea.context(function () {
 | 
				
			|||||||
	// 上传证书
 | 
						// 上传证书
 | 
				
			||||||
	this.uploadCert = function () {
 | 
						this.uploadCert = function () {
 | 
				
			||||||
		teaweb.popup("/servers/certs/uploadPopup", {
 | 
							teaweb.popup("/servers/certs/uploadPopup", {
 | 
				
			||||||
			height: "28em",
 | 
								height: "30em",
 | 
				
			||||||
			callback: function () {
 | 
								callback: function () {
 | 
				
			||||||
				teaweb.success("上传成功", function () {
 | 
									teaweb.success("上传成功", function () {
 | 
				
			||||||
					window.location.reload()
 | 
										window.location.reload()
 | 
				
			||||||
@@ -34,7 +34,7 @@ Tea.context(function () {
 | 
				
			|||||||
	// 修改证书
 | 
						// 修改证书
 | 
				
			||||||
	this.updateCert = function (certId) {
 | 
						this.updateCert = function (certId) {
 | 
				
			||||||
		teaweb.popup("/servers/certs/updatePopup?certId=" + certId, {
 | 
							teaweb.popup("/servers/certs/updatePopup?certId=" + certId, {
 | 
				
			||||||
			height: "28em",
 | 
								height: "30em",
 | 
				
			||||||
			callback: function () {
 | 
								callback: function () {
 | 
				
			||||||
				teaweb.success("上传成功", function () {
 | 
									teaweb.success("上传成功", function () {
 | 
				
			||||||
					window.location.reload()
 | 
										window.location.reload()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,6 +4,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
<form method="post" class="ui form" data-tea-action="$" data-tea-success="success">
 | 
					<form method="post" class="ui form" data-tea-action="$" data-tea-success="success">
 | 
				
			||||||
	<input type="hidden" name="certId" :value="certConfig.id"/>
 | 
						<input type="hidden" name="certId" :value="certConfig.id"/>
 | 
				
			||||||
 | 
					    <input type="hidden" name="textMode" :value="textMode ? 1 : 0"/>
 | 
				
			||||||
	<table class="ui table definition selectable">
 | 
						<table class="ui table definition selectable">
 | 
				
			||||||
		<tr>
 | 
							<tr>
 | 
				
			||||||
			<td class="title">证书说明 *</td>
 | 
								<td class="title">证书说明 *</td>
 | 
				
			||||||
@@ -24,15 +25,17 @@
 | 
				
			|||||||
		<tr>
 | 
							<tr>
 | 
				
			||||||
			<td>选择证书文件</td>
 | 
								<td>选择证书文件</td>
 | 
				
			||||||
			<td>
 | 
								<td>
 | 
				
			||||||
				<input type="file" name="certFile" accept="application/x-pem-file, application/pkcs10, application/x-pkcs12, application/x-x509-user-cert, application/x-x509-ca-cert, application/pkix-cert"/>
 | 
					                <input type="file" name="certFile" accept="application/x-pem-file, application/pkcs10, application/x-pkcs12, application/x-x509-user-cert, application/x-x509-ca-cert, application/pkix-cert" v-if="!textMode"/>
 | 
				
			||||||
				<p class="comment">内容中通常含有"-----BEGIN CERTIFICATE-----"类似的信息。</p>
 | 
					                <textarea name="certText" placeholder="-----BEGIN CERTIFICATE-----" v-if="textMode"></textarea>
 | 
				
			||||||
 | 
					                <p class="comment"><a href="" @click.prevent="switchTextMode">[<span v-if="!textMode">输入内容</span><span v-else>上传文件</span>]</a>。文件内容中通常含有"-----BEGIN CERTIFICATE-----"类似的信息。</p>
 | 
				
			||||||
			</td>
 | 
								</td>
 | 
				
			||||||
		</tr>
 | 
							</tr>
 | 
				
			||||||
		<tr v-show="isCA == 0">
 | 
							<tr v-show="isCA == 0">
 | 
				
			||||||
			<td>选择私钥文件</td>
 | 
								<td>选择私钥文件</td>
 | 
				
			||||||
			<td>
 | 
								<td>
 | 
				
			||||||
				<input type="file" name="keyFile" accept="application/pkcs8"/>
 | 
					                <input type="file" name="keyFile" accept="application/pkcs8" v-if="!textMode"/>
 | 
				
			||||||
				<p class="comment">内容中通常含有"-----BEGIN RSA PRIVATE KEY-----"类似的信息。</p>
 | 
					                <textarea name="keyText" placeholder="-----BEGIN RSA PRIVATE KEY-----" v-if="textMode"></textarea>
 | 
				
			||||||
 | 
					                <p class="comment"><a href="" @click.prevent="switchTextMode">[<span v-if="!textMode">输入内容</span><span v-else>上传文件</span>]</a>。文件内容中通常含有"-----BEGIN RSA PRIVATE KEY-----"类似的信息。</p>
 | 
				
			||||||
			</td>
 | 
								</td>
 | 
				
			||||||
		</tr>
 | 
							</tr>
 | 
				
			||||||
		<tr>
 | 
							<tr>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,9 @@
 | 
				
			|||||||
Tea.context(function () {
 | 
					Tea.context(function () {
 | 
				
			||||||
	this.success = NotifyPopup
 | 
						this.success = NotifyPopup
 | 
				
			||||||
	this.isCA = this.certConfig.isCA ? 1 : 0
 | 
						this.isCA = this.certConfig.isCA ? 1 : 0
 | 
				
			||||||
 | 
						this.textMode = false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						this.switchTextMode = function () {
 | 
				
			||||||
 | 
							this.textMode = !this.textMode
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
@@ -3,6 +3,7 @@
 | 
				
			|||||||
<h3>上传证书</h3>
 | 
					<h3>上传证书</h3>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<form method="post" class="ui form" data-tea-action="$" data-tea-success="success">
 | 
					<form method="post" class="ui form" data-tea-action="$" data-tea-success="success">
 | 
				
			||||||
 | 
					    <input type="hidden" name="textMode" :value="textMode ? 1 : 0"/>
 | 
				
			||||||
	<table class="ui table definition selectable">
 | 
						<table class="ui table definition selectable">
 | 
				
			||||||
		<tr>
 | 
							<tr>
 | 
				
			||||||
			<td class="title">证书说明 *</td>
 | 
								<td class="title">证书说明 *</td>
 | 
				
			||||||
@@ -23,15 +24,17 @@
 | 
				
			|||||||
		<tr>
 | 
							<tr>
 | 
				
			||||||
			<td>选择证书文件 *</td>
 | 
								<td>选择证书文件 *</td>
 | 
				
			||||||
			<td>
 | 
								<td>
 | 
				
			||||||
				<input type="file" name="certFile" accept="application/x-pem-file, application/pkcs10, application/x-pkcs12, application/x-x509-user-cert, application/x-x509-ca-cert, application/pkix-cert"/>
 | 
									<input type="file" name="certFile" accept="application/x-pem-file, application/pkcs10, application/x-pkcs12, application/x-x509-user-cert, application/x-x509-ca-cert, application/pkix-cert" v-if="!textMode"/>
 | 
				
			||||||
				<p class="comment">内容中通常含有"-----BEGIN CERTIFICATE-----"类似的信息。</p>
 | 
					                <textarea name="certText" placeholder="-----BEGIN CERTIFICATE-----" v-if="textMode"></textarea>
 | 
				
			||||||
 | 
					                <p class="comment"><a href="" @click.prevent="switchTextMode">[<span v-if="!textMode">输入内容</span><span v-else>上传文件</span>]</a>。文件内容中通常含有"-----BEGIN CERTIFICATE-----"类似的信息。</p>
 | 
				
			||||||
			</td>
 | 
								</td>
 | 
				
			||||||
		</tr>
 | 
							</tr>
 | 
				
			||||||
		<tr v-show="isCA == 0">
 | 
							<tr v-show="isCA == 0">
 | 
				
			||||||
			<td>选择私钥文件 *</td>
 | 
								<td>选择私钥文件 *</td>
 | 
				
			||||||
			<td>
 | 
								<td>
 | 
				
			||||||
				<input type="file" name="keyFile" accept="application/pkcs8"/>
 | 
									<input type="file" name="keyFile" accept="application/pkcs8" v-if="!textMode"/>
 | 
				
			||||||
				<p class="comment">内容中通常含有"-----BEGIN RSA PRIVATE KEY-----"类似的信息。</p>
 | 
					                <textarea name="keyText" placeholder="-----BEGIN RSA PRIVATE KEY-----" v-if="textMode"></textarea>
 | 
				
			||||||
 | 
									<p class="comment"><a href="" @click.prevent="switchTextMode">[<span v-if="!textMode">输入内容</span><span v-else>上传文件</span>]</a>。文件内容中通常含有"-----BEGIN RSA PRIVATE KEY-----"类似的信息。</p>
 | 
				
			||||||
			</td>
 | 
								</td>
 | 
				
			||||||
		</tr>
 | 
							</tr>
 | 
				
			||||||
		<tr>
 | 
							<tr>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,9 @@
 | 
				
			|||||||
Tea.context(function () {
 | 
					Tea.context(function () {
 | 
				
			||||||
	this.success = NotifyPopup
 | 
						this.success = NotifyPopup
 | 
				
			||||||
	this.isCA = 0
 | 
						this.isCA = 0
 | 
				
			||||||
 | 
						this.textMode = false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						this.switchTextMode = function () {
 | 
				
			||||||
 | 
							this.textMode = !this.textMode
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
		Reference in New Issue
	
	Block a user