diff --git a/go.mod b/go.mod index 7af5e66e..59d08730 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,9 @@ require ( github.com/go-sql-driver/mysql v1.5.0 github.com/go-yaml/yaml v2.1.0+incompatible github.com/iwind/TeaGo v0.0.0-20201206115018-cdd967bfb13d + github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e github.com/tealeg/xlsx/v3 v3.2.3 + github.com/xlzd/gotp v0.0.0-20181030022105-c8557ba2c119 golang.org/x/sys v0.0.0-20200724161237-0e2f3a69832c // indirect google.golang.org/grpc v1.32.0 gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/go.sum b/go.sum index 6106e1ee..f68e9779 100644 --- a/go.sum +++ b/go.sum @@ -3,6 +3,7 @@ dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/DataDog/sketches-go v0.0.0-20190923095040-43f19ad77ff7/go.mod h1:Q5DbzQ+3AkgGwymQO7aZFNP7ns2lZKGtvRBzRXfdi60= +github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= @@ -47,18 +48,12 @@ github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/iwind/TeaGo v0.0.0-20200923021120-f5d76441fe9e h1:/xn7wUvlwaoA5IkdBUctv2OQbJSZ0/Dw8qRJmn55sJk= github.com/iwind/TeaGo v0.0.0-20200923021120-f5d76441fe9e/go.mod h1:KU4mS7QNiZ7QWEuDBk1zw0/Q2LrAPZv3tycEFBsuUwc= -github.com/iwind/TeaGo v0.0.0-20201120063500-ee2d7090f4bc h1:AOKJWsgCX5e7xnW2f7evcrgj6vzvvHIoDmA+xxL3BMI= -github.com/iwind/TeaGo v0.0.0-20201120063500-ee2d7090f4bc/go.mod h1:KU4mS7QNiZ7QWEuDBk1zw0/Q2LrAPZv3tycEFBsuUwc= -github.com/iwind/TeaGo v0.0.0-20201206100217-6b8965ebe91b h1:ZoR880XHIMdWgGqqLok3OUbpViBIgDmyvVXiw3lmLlA= -github.com/iwind/TeaGo v0.0.0-20201206100217-6b8965ebe91b/go.mod h1:KU4mS7QNiZ7QWEuDBk1zw0/Q2LrAPZv3tycEFBsuUwc= github.com/iwind/TeaGo v0.0.0-20201206115018-cdd967bfb13d h1:J4ohNUwOqCQkY62LFwaygfGtHJj+87pnzr+RJxEYSBo= github.com/iwind/TeaGo v0.0.0-20201206115018-cdd967bfb13d/go.mod h1:KU4mS7QNiZ7QWEuDBk1zw0/Q2LrAPZv3tycEFBsuUwc= github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68= @@ -68,11 +63,9 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= @@ -98,6 +91,9 @@ github.com/rogpeppe/fastuuid v1.2.0 h1:Ppwyp6VYCF1nvBTXL3trRso7mXMlRrw9ooo375wvi github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/shabbyrobe/xmlwriter v0.0.0-20200208144257-9fca06d00ffa h1:2cO3RojjYl3hVTbEvJVqrMaFmORhL6O06qdW42toftk= github.com/shabbyrobe/xmlwriter v0.0.0-20200208144257-9fca06d00ffa/go.mod h1:Yjr3bdWaVWyME1kha7X0jsz3k2DgXNa1Pj3XGyUAbx8= +github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0= +github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72 h1:qLC7fQah7D6K1B0ujays3HV9gkFtllcxhzImRR7ArPQ= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= @@ -105,6 +101,8 @@ github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/tealeg/xlsx/v3 v3.2.3 h1:MXnVh+9Y8cUglowItTy2HL3Kv6z+q/0aNjeKuTsVqZQ= github.com/tealeg/xlsx/v3 v3.2.3/go.mod h1:0hGmAEoZ48SS1ZAE6eqZJkJVXgOMY+8a33vjXa8S8HA= +github.com/xlzd/gotp v0.0.0-20181030022105-c8557ba2c119 h1:YyPWX3jLOtYKulBR6AScGIs74lLrJcgeKRwcbAuQOG4= +github.com/xlzd/gotp v0.0.0-20181030022105-c8557ba2c119/go.mod h1:/nuTSlK+okRfR/vnIPqR89fFKonnWPiZymN5ydRJkX8= go.opentelemetry.io/otel v0.7.0/go.mod h1:aZMyHG5TqDOXEgH2tyLiXSUKly1jT3yqE9PmrzIeCdo= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -123,7 +121,6 @@ golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -136,7 +133,6 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -146,11 +142,9 @@ golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200519105757-fe76b779f299 h1:DYfZAGf2WMFjMxbgTjaC+2HC7NkNAQs+6Q8b9WEB/F4= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200724161237-0e2f3a69832c h1:UIcGWL6/wpCfyGuJnRFJRurA+yj8RrW7Q6x2YMCXt6c= golang.org/x/sys v0.0.0-20200724161237-0e2f3a69832c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= @@ -159,7 +153,6 @@ golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa h1:5E4dL8+NgFOgjwbTKz+OOEGGhP+ectTmF842l6KjupQ= golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= @@ -167,9 +160,7 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20191009194640-548a555dbc03 h1:4HYDjxeNXAOTv3o1N2tjo8UUSlhQgAD52FVkwxnWgM8= google.golang.org/genproto v0.0.0-20191009194640-548a555dbc03/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= @@ -177,7 +168,6 @@ google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZi google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.30.0 h1:M5a8xTlYTxwMn5ZFkwhRabsygDY5G8TYLyQDBxJNAxE= google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.32.0 h1:zWTV+LMdc3kaiJMSTOFz2UgSBgx8RNQoTGiZu3fR9S0= google.golang.org/grpc v1.32.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= @@ -187,7 +177,6 @@ google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQ google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= @@ -201,11 +190,9 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWD gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ= gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/internal/const/const.go b/internal/const/const.go index 186a82dd..0ff9ecf5 100644 --- a/internal/const/const.go +++ b/internal/const/const.go @@ -1,7 +1,7 @@ package teaconst const ( - Version = "0.0.6" + Version = "0.0.6.1" ProductName = "Edge Admin" ProcessName = "edge-admin" diff --git a/internal/rpc/rpc_client.go b/internal/rpc/rpc_client.go index f3db8293..2a996a6f 100644 --- a/internal/rpc/rpc_client.go +++ b/internal/rpc/rpc_client.go @@ -248,6 +248,10 @@ func (this *RPCClient) UserBillRPC() pb.UserBillServiceClient { return pb.NewUserBillServiceClient(this.pickConn()) } +func (this *RPCClient) LoginRPC() pb.LoginServiceClient { + return pb.NewLoginServiceClient(this.pickConn()) +} + // 构造Admin上下文 func (this *RPCClient) Context(adminId int64) context.Context { ctx := context.Background() diff --git a/internal/web/actions/default/admins/admin.go b/internal/web/actions/default/admins/admin.go new file mode 100644 index 00000000..ddb5334a --- /dev/null +++ b/internal/web/actions/default/admins/admin.go @@ -0,0 +1,74 @@ +package admins + +import ( + "encoding/json" + "github.com/TeaOSLab/EdgeAdmin/internal/configloaders" + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" + "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" + "github.com/iwind/TeaGo/maps" +) + +type AdminAction struct { + actionutils.ParentAction +} + +func (this *AdminAction) Init() { + this.Nav("", "", "index") +} + +func (this *AdminAction) RunGet(params struct { + AdminId int64 +}) { + adminResp, err := this.RPC().AdminRPC().FindEnabledAdmin(this.AdminContext(), &pb.FindEnabledAdminRequest{AdminId: params.AdminId}) + if err != nil { + this.ErrorPage(err) + return + } + admin := adminResp.Admin + if admin == nil { + this.NotFound("admin", params.AdminId) + return + } + + this.Data["admin"] = maps.Map{ + "id": admin.Id, + "fullname": admin.Fullname, + "username": admin.Username, + "isOn": admin.IsOn, + "isSuper": admin.IsSuper, + } + + // 权限 + moduleMaps := []maps.Map{} + for _, m := range configloaders.AllModuleMaps() { + code := m.GetString("code") + isChecked := false + for _, module := range admin.Modules { + if module.Code == code { + isChecked = true + break + } + } + if isChecked { + moduleMaps = append(moduleMaps, m) + } + } + this.Data["modules"] = moduleMaps + + // OTP + this.Data["otp"] = nil + if admin.OtpLogin != nil && admin.OtpLogin.IsOn { + loginParams := maps.Map{} + err = json.Unmarshal(admin.OtpLogin.ParamsJSON, &loginParams) + if err != nil { + this.ErrorPage(err) + return + } + this.Data["otp"] = maps.Map{ + "isOn": true, + "params": loginParams, + } + } + + this.Show() +} diff --git a/internal/web/actions/default/admins/createPopup.go b/internal/web/actions/default/admins/createPopup.go index 075c6ed7..fc1f0185 100644 --- a/internal/web/actions/default/admins/createPopup.go +++ b/internal/web/actions/default/admins/createPopup.go @@ -7,6 +7,8 @@ import ( "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" "github.com/TeaOSLab/EdgeCommon/pkg/systemconfigs" "github.com/iwind/TeaGo/actions" + "github.com/iwind/TeaGo/maps" + "github.com/xlzd/gotp" ) type CreatePopupAction struct { @@ -30,6 +32,9 @@ func (this *CreatePopupAction) RunPost(params struct { ModuleCodes []string IsSuper bool + // OTP + OtpOn bool + Must *actions.Must CSRF *actionutils.CSRF }) { @@ -89,6 +94,24 @@ func (this *CreatePopupAction) RunPost(params struct { return } + // OTP + if params.OtpOn { + _, err = this.RPC().LoginRPC().UpdateLogin(this.AdminContext(), &pb.UpdateLoginRequest{Login: &pb.Login{ + Id: 0, + Type: "otp", + ParamsJSON: maps.Map{ + "secret": gotp.RandomSecret(16), // TODO 改成可以设置secret长度 + }.AsJSON(), + IsOn: true, + AdminId: createResp.AdminId, + UserId: 0, + }}) + if err != nil { + this.ErrorPage(err) + return + } + } + defer this.CreateLogInfo("创建系统用户 %d", createResp.AdminId) // 通知更改 diff --git a/internal/web/actions/default/admins/index.go b/internal/web/actions/default/admins/index.go index 947c4e64..2f20c5fd 100644 --- a/internal/web/actions/default/admins/index.go +++ b/internal/web/actions/default/admins/index.go @@ -35,12 +35,13 @@ func (this *IndexAction) RunGet(params struct{}) { adminMaps := []maps.Map{} for _, admin := range adminsResp.Admins { adminMaps = append(adminMaps, maps.Map{ - "id": admin.Id, - "isOn": admin.IsOn, - "isSuper": admin.IsSuper, - "username": admin.Username, - "fullname": admin.Fullname, - "createdTime": timeutil.FormatTime("Y-m-d H:i:s", admin.CreatedAt), + "id": admin.Id, + "isOn": admin.IsOn, + "isSuper": admin.IsSuper, + "username": admin.Username, + "fullname": admin.Fullname, + "createdTime": timeutil.FormatTime("Y-m-d H:i:s", admin.CreatedAt), + "otpLoginIsOn": admin.OtpLogin != nil && admin.OtpLogin.IsOn, }) } this.Data["admins"] = adminMaps diff --git a/internal/web/actions/default/admins/init.go b/internal/web/actions/default/admins/init.go index a602d385..c2922369 100644 --- a/internal/web/actions/default/admins/init.go +++ b/internal/web/actions/default/admins/init.go @@ -14,8 +14,10 @@ func init() { Prefix("/admins"). Get("", new(IndexAction)). GetPost("/createPopup", new(CreatePopupAction)). - GetPost("/updatePopup", new(UpdatePopupAction)). + GetPost("/update", new(UpdateAction)). Post("/delete", new(DeleteAction)). + Get("/admin", new(AdminAction)). + Get("/otpQrcode", new(OtpQrcodeAction)). EndAll() }) } diff --git a/internal/web/actions/default/admins/otpQrcode.go b/internal/web/actions/default/admins/otpQrcode.go new file mode 100644 index 00000000..545882aa --- /dev/null +++ b/internal/web/actions/default/admins/otpQrcode.go @@ -0,0 +1,71 @@ +package admins + +import ( + "encoding/json" + "github.com/TeaOSLab/EdgeAdmin/internal/configloaders" + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" + "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" + "github.com/iwind/TeaGo/maps" + "github.com/skip2/go-qrcode" + "github.com/xlzd/gotp" +) + +type OtpQrcodeAction struct { + actionutils.ParentAction +} + +func (this *OtpQrcodeAction) Init() { + this.Nav("", "", "") +} + +func (this *OtpQrcodeAction) RunGet(params struct { + AdminId int64 +}) { + loginResp, err := this.RPC().LoginRPC().FindEnabledLogin(this.AdminContext(), &pb.FindEnabledLoginRequest{ + AdminId: params.AdminId, + Type: "otp", + }) + if err != nil { + this.ErrorPage(err) + return + } + login := loginResp.Login + if login == nil || !login.IsOn { + this.NotFound("adminLogin", params.AdminId) + return + } + + loginParams := maps.Map{} + err = json.Unmarshal(login.ParamsJSON, &loginParams) + if err != nil { + this.ErrorPage(err) + return + } + secret := loginParams.GetString("secret") + + // 当前用户信息 + adminResp, err := this.RPC().AdminRPC().FindEnabledAdmin(this.AdminContext(), &pb.FindEnabledAdminRequest{AdminId: params.AdminId}) + if err != nil { + this.ErrorPage(err) + return + } + admin := adminResp.Admin + if admin == nil { + this.NotFound("admin", params.AdminId) + return + } + + uiConfig, err := configloaders.LoadAdminUIConfig() + if err != nil { + this.ErrorPage(err) + return + } + url := gotp.NewDefaultTOTP(secret).ProvisioningUri(admin.Username, uiConfig.AdminSystemName) + data, err := qrcode.Encode(url, qrcode.Medium, 256) + if err != nil { + this.ErrorPage(err) + return + } + this.AddHeader("Content-Type", "image/png") + this.Write(data) +} diff --git a/internal/web/actions/default/admins/updatePopup.go b/internal/web/actions/default/admins/update.go similarity index 61% rename from internal/web/actions/default/admins/updatePopup.go rename to internal/web/actions/default/admins/update.go index 384f0c28..e5ec7580 100644 --- a/internal/web/actions/default/admins/updatePopup.go +++ b/internal/web/actions/default/admins/update.go @@ -8,35 +8,47 @@ import ( "github.com/TeaOSLab/EdgeCommon/pkg/systemconfigs" "github.com/iwind/TeaGo/actions" "github.com/iwind/TeaGo/maps" + "github.com/xlzd/gotp" ) -type UpdatePopupAction struct { +type UpdateAction struct { actionutils.ParentAction } -func (this *UpdatePopupAction) Init() { - this.Nav("", "", "") +func (this *UpdateAction) Init() { + this.Nav("", "", "update") } -func (this *UpdatePopupAction) RunGet(params struct { +func (this *UpdateAction) RunGet(params struct { AdminId int64 }) { - adminResp, err := this.RPC().AdminRPC().FindEnabledAdmin(this.AdminContext(), &pb.FindEnabledAdminRequest{AdminId: params.AdminId}) if err != nil { this.ErrorPage(err) return } admin := adminResp.Admin - - this.Data["admin"] = maps.Map{ - "id": admin.Id, - "fullname": admin.Fullname, - "username": admin.Username, - "isOn": admin.IsOn, - "isSuper": admin.IsSuper, + if admin == nil { + this.NotFound("admin", params.AdminId) + return } + // OTP认证 + otpLoginIsOn := false + if admin.OtpLogin != nil { + otpLoginIsOn = admin.OtpLogin.IsOn + } + + this.Data["admin"] = maps.Map{ + "id": admin.Id, + "fullname": admin.Fullname, + "username": admin.Username, + "isOn": admin.IsOn, + "isSuper": admin.IsSuper, + "otpLoginIsOn": otpLoginIsOn, + } + + // 权限 moduleMaps := configloaders.AllModuleMaps() for _, m := range moduleMaps { code := m.GetString("code") @@ -54,7 +66,7 @@ func (this *UpdatePopupAction) RunGet(params struct { this.Show() } -func (this *UpdatePopupAction) RunPost(params struct { +func (this *UpdateAction) RunPost(params struct { AdminId int64 Fullname string @@ -65,6 +77,9 @@ func (this *UpdatePopupAction) RunPost(params struct { IsOn bool IsSuper bool + // OTP + OtpOn bool + Must *actions.Must CSRF *actionutils.CSRF }) { @@ -130,12 +145,58 @@ func (this *UpdatePopupAction) RunPost(params struct { return } - // 通知更改 - err = configloaders.NotifyAdminModuleMappingChange() + // 修改OTP + otpLoginResp, err := this.RPC().LoginRPC().FindEnabledLogin(this.AdminContext(), &pb.FindEnabledLoginRequest{ + AdminId: params.AdminId, + Type: "otp", + }) if err != nil { this.ErrorPage(err) return } + { + otpLogin := otpLoginResp.Login + if params.OtpOn { + if otpLogin == nil { + otpLogin = &pb.Login{ + Id: 0, + Type: "otp", + ParamsJSON: maps.Map{ + "secret": gotp.RandomSecret(16), // TODO 改成可以设置secret长度 + }.AsJSON(), + IsOn: true, + AdminId: params.AdminId, + UserId: 0, + } + } else { + // 如果已经有了,就覆盖,这样可以保留既有的参数 + otpLogin.IsOn = true + } - this.Success() + _, err = this.RPC().LoginRPC().UpdateLogin(this.AdminContext(), &pb.UpdateLoginRequest{Login: otpLogin}) + if err != nil { + this.ErrorPage(err) + return + } + } else { + _, err = this.RPC().LoginRPC().UpdateLogin(this.AdminContext(), &pb.UpdateLoginRequest{Login: &pb.Login{ + Type: "otp", + IsOn: false, + AdminId: params.AdminId, + }}) + if err != nil { + this.ErrorPage(err) + return + } + } + + // 通知更改 + err = configloaders.NotifyAdminModuleMappingChange() + if err != nil { + this.ErrorPage(err) + return + } + + this.Success() + } } diff --git a/internal/web/actions/default/index/checkOTP.go b/internal/web/actions/default/index/checkOTP.go new file mode 100644 index 00000000..75afe643 --- /dev/null +++ b/internal/web/actions/default/index/checkOTP.go @@ -0,0 +1,30 @@ +package index + +import ( + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" + "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" + "github.com/iwind/TeaGo/actions" +) + +// 检查是否需要OTP +type CheckOTPAction struct { + actionutils.ParentAction +} + +func (this *CheckOTPAction) Init() { + this.Nav("", "", "") +} + +func (this *CheckOTPAction) RunPost(params struct { + Username string + + Must *actions.Must +}) { + checkResp, err := this.RPC().AdminRPC().CheckAdminOTPWithUsername(this.AdminContext(), &pb.CheckAdminOTPWithUsernameRequest{Username: params.Username}) + if err != nil { + this.ErrorPage(err) + return + } + this.Data["requireOTP"] = checkResp.RequireOTP + this.Success() +} diff --git a/internal/web/actions/default/index/index.go b/internal/web/actions/default/index/index.go index abbf23d6..eab96dd6 100644 --- a/internal/web/actions/default/index/index.go +++ b/internal/web/actions/default/index/index.go @@ -1,6 +1,7 @@ package index import ( + "encoding/json" "fmt" "github.com/TeaOSLab/EdgeAdmin/internal/configloaders" teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const" @@ -13,8 +14,10 @@ import ( "github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao" "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" "github.com/iwind/TeaGo/actions" + "github.com/iwind/TeaGo/maps" "github.com/iwind/TeaGo/types" stringutil "github.com/iwind/TeaGo/utils/string" + "github.com/xlzd/gotp" "time" ) @@ -71,6 +74,7 @@ func (this *IndexAction) RunPost(params struct { Token string Username string Password string + OtpCode string Remember bool Must *actions.Must Auth *helpers.UserShouldAuth @@ -126,6 +130,28 @@ func (this *IndexAction) RunPost(params struct { this.Fail("请输入正确的用户名密码") } + // 检查OTP + otpLoginResp, err := this.RPC().LoginRPC().FindEnabledLogin(this.AdminContext(), &pb.FindEnabledLoginRequest{ + AdminId: resp.AdminId, + Type: "otp", + }) + if err != nil { + this.ErrorPage(err) + return + } + if otpLoginResp.Login != nil && otpLoginResp.Login.IsOn { + loginParams := maps.Map{} + err = json.Unmarshal(otpLoginResp.Login.ParamsJSON, &loginParams) + if err != nil { + this.ErrorPage(err) + return + } + secret := loginParams.GetString("secret") + if gotp.NewDefaultTOTP(secret).Now() != params.OtpCode { + this.Fail("请输入正确的OTP动态密码") + } + } + adminId := resp.AdminId params.Auth.StoreAdmin(adminId, params.Remember) diff --git a/internal/web/actions/default/index/init.go b/internal/web/actions/default/index/init.go index d5352f6e..0348a503 100644 --- a/internal/web/actions/default/index/init.go +++ b/internal/web/actions/default/index/init.go @@ -6,7 +6,9 @@ import ( func init() { TeaGo.BeforeStart(func(server *TeaGo.Server) { - server.Prefix("/"). + server. + Post("/checkOTP", new(CheckOTPAction)). + Prefix("/"). GetPost("", new(IndexAction)). EndAll() }) diff --git a/web/views/@default/@layout_popup.css b/web/views/@default/@layout_popup.css index ba25b550..da631593 100644 --- a/web/views/@default/@layout_popup.css +++ b/web/views/@default/@layout_popup.css @@ -52,7 +52,7 @@ tbody { } p.comment, div.comment { - color: rgba(0, 0, 0, 0.3); + color: rgba(0, 0, 0, 0.4); padding-top: 0.4em; } p.comment em, diff --git a/web/views/@default/@layout_popup.less b/web/views/@default/@layout_popup.less index f21643b7..568dd7ab 100644 --- a/web/views/@default/@layout_popup.less +++ b/web/views/@default/@layout_popup.less @@ -56,7 +56,7 @@ tbody { } p.comment, div.comment { - color: rgba(0, 0, 0, 0.3); + color: rgba(0, 0, 0, 0.4); padding-top: 0.4em; } diff --git a/web/views/@default/admins/@admin_menu.html b/web/views/@default/admins/@admin_menu.html new file mode 100644 index 00000000..00f01bf4 --- /dev/null +++ b/web/views/@default/admins/@admin_menu.html @@ -0,0 +1,6 @@ + + 系统用户 + | + "{{admin.fullname}}" 详情 + 修改 + \ No newline at end of file diff --git a/web/views/@default/admins/admin.css b/web/views/@default/admins/admin.css new file mode 100644 index 00000000..b47829f9 --- /dev/null +++ b/web/views/@default/admins/admin.css @@ -0,0 +1,7 @@ +.modules-box .module-box { + float: left; + width: 9em; + margin-top: 0.3em; + margin-bottom: 0.3em; +} +/*# sourceMappingURL=admin.css.map */ \ No newline at end of file diff --git a/web/views/@default/admins/admin.css.map b/web/views/@default/admins/admin.css.map new file mode 100644 index 00000000..4f129494 --- /dev/null +++ b/web/views/@default/admins/admin.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["admin.less"],"names":[],"mappings":"AAAA,YACC;EACC,WAAA;EACA,UAAA;EACA,iBAAA;EACA,oBAAA","file":"admin.css"} \ No newline at end of file diff --git a/web/views/@default/admins/admin.html b/web/views/@default/admins/admin.html new file mode 100644 index 00000000..02df825e --- /dev/null +++ b/web/views/@default/admins/admin.html @@ -0,0 +1,66 @@ +{$layout} +{$template "admin_menu"} + + + + + + + + + + + + + + + + + + + + + + +
全名 + {{admin.fullname}} +
状态 + +
登录用户名 + {{admin.username}} +
是否为超级管理员 + Y + N +
权限 +
+
+ {{module.name}} +
+
+ 暂时还没有可以管理的模块。 +
+ +

OTP认证

+ + + + + + + + + + + + + + + + +
状态 + 已启用 + 未启用 +
更多信息
认证二维码 + +

可以通过二维码快速添加OTP认证信息到App中。

+
密钥{{otp.params.secret}}
\ No newline at end of file diff --git a/web/views/@default/admins/admin.less b/web/views/@default/admins/admin.less new file mode 100644 index 00000000..8c4afe7d --- /dev/null +++ b/web/views/@default/admins/admin.less @@ -0,0 +1,8 @@ +.modules-box { + .module-box { + float: left; + width: 9em; + margin-top: 0.3em; + margin-bottom: 0.3em; + } +} \ No newline at end of file diff --git a/web/views/@default/admins/createPopup.html b/web/views/@default/admins/createPopup.html index f16c2d8c..67f725ff 100644 --- a/web/views/@default/admins/createPopup.html +++ b/web/views/@default/admins/createPopup.html @@ -49,6 +49,13 @@ + + OTP认证 + + 启用OTP +

启用OTP认证后,在用户登录的时候需要同时填写OTP动态密码。

+ + diff --git a/web/views/@default/admins/index.html b/web/views/@default/admins/index.html index c8f96d8a..3d924f36 100644 --- a/web/views/@default/admins/index.html +++ b/web/views/@default/admins/index.html @@ -6,7 +6,7 @@ 用户名 全名 - 创建时间 + OTP认证 状态 操作 @@ -18,12 +18,15 @@ {{admin.fullname}} - {{admin.createdTime}} + + Y + N + - 修改   删除 + 详情   删除 diff --git a/web/views/@default/admins/index.js b/web/views/@default/admins/index.js index 888e0215..b0820c9e 100644 --- a/web/views/@default/admins/index.js +++ b/web/views/@default/admins/index.js @@ -21,15 +21,4 @@ Tea.context(function () { .refresh() }) } - - this.updateAdmin = function (adminId) { - teaweb.popup("/admins/updatePopup?adminId=" + adminId, { - height: "22em", - callback: function () { - teaweb.success("保存成功", function () { - teaweb.reload() - }) - } - }) - } }) \ No newline at end of file diff --git a/web/views/@default/admins/updatePopup.css b/web/views/@default/admins/update.css similarity index 70% rename from web/views/@default/admins/updatePopup.css rename to web/views/@default/admins/update.css index 99c17be4..994fab3b 100644 --- a/web/views/@default/admins/updatePopup.css +++ b/web/views/@default/admins/update.css @@ -4,4 +4,4 @@ margin-top: 0.3em; margin-bottom: 0.3em; } -/*# sourceMappingURL=updatePopup.css.map */ \ No newline at end of file +/*# sourceMappingURL=update.css.map */ \ No newline at end of file diff --git a/web/views/@default/admins/update.css.map b/web/views/@default/admins/update.css.map new file mode 100644 index 00000000..d7c9b4d2 --- /dev/null +++ b/web/views/@default/admins/update.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["update.less"],"names":[],"mappings":"AAAA,YACC;EACC,WAAA;EACA,WAAA;EACA,iBAAA;EACA,oBAAA","file":"update.css"} \ No newline at end of file diff --git a/web/views/@default/admins/update.html b/web/views/@default/admins/update.html new file mode 100644 index 00000000..96706661 --- /dev/null +++ b/web/views/@default/admins/update.html @@ -0,0 +1,68 @@ +{$layout} +{$template "admin_menu"} + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
全名 * + +

可以输入姓名、公司名等容易识别的名称。

+
登录用户名 * + +

用户名只能英文、数字、下划线的组合。

+
登录密码 + +

留空表示不修改。

+
确认登录密码 + +
是否为超级管理员 + +

超级管理员自动拥有所有的管理权限。

+
权限 +
+
+ {{module.name}} +
+
+
OTP认证 + 启用OTP +

启用OTP认证后,在用户登录的时候需要同时填写OTP动态密码。

+
是否启用 + +
+ + +
\ No newline at end of file diff --git a/web/views/@default/admins/update.js b/web/views/@default/admins/update.js new file mode 100644 index 00000000..d6c71028 --- /dev/null +++ b/web/views/@default/admins/update.js @@ -0,0 +1,3 @@ +Tea.context(function () { + this.success = NotifySuccess("保存成功", "/admins/admin?adminId=" + this.admin.id) +}) \ No newline at end of file diff --git a/web/views/@default/admins/updatePopup.less b/web/views/@default/admins/update.less similarity index 100% rename from web/views/@default/admins/updatePopup.less rename to web/views/@default/admins/update.less diff --git a/web/views/@default/admins/updatePopup.css.map b/web/views/@default/admins/updatePopup.css.map deleted file mode 100644 index e7d9ad0e..00000000 --- a/web/views/@default/admins/updatePopup.css.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["updatePopup.less"],"names":[],"mappings":"AAAA,YACC;EACC,WAAA;EACA,WAAA;EACA,iBAAA;EACA,oBAAA","file":"updatePopup.css"} \ No newline at end of file diff --git a/web/views/@default/admins/updatePopup.html b/web/views/@default/admins/updatePopup.html deleted file mode 100644 index a7af12c0..00000000 --- a/web/views/@default/admins/updatePopup.html +++ /dev/null @@ -1,64 +0,0 @@ -{$layout "layout_popup"} - -

修改系统用户

- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
全名 * - -

可以输入姓名、公司名等容易识别的名称。

-
登录用户名 * - -

用户名只能英文、数字、下划线的组合。

-
登录密码 - -

留空表示不修改。

-
确认登录密码 - -
是否为超级管理员 - -

超级管理员自动拥有所有的管理权限。

-
权限 -
-
- {{module.name}} -
-
-
是否启用 - -
- - -
\ No newline at end of file diff --git a/web/views/@default/index/index.css b/web/views/@default/index/index.css index 2c58da00..91c89616 100644 --- a/web/views/@default/index/index.css +++ b/web/views/@default/index/index.css @@ -1,6 +1,6 @@ .form-box { position: fixed; - top: 2.5em; + top: 2em; bottom: 0; left: 0; right: 0; diff --git a/web/views/@default/index/index.css.map b/web/views/@default/index/index.css.map index 91fb9caf..176648e4 100644 --- a/web/views/@default/index/index.css.map +++ b/web/views/@default/index/index.css.map @@ -1 +1 @@ -{"version":3,"sources":["index.less"],"names":[],"mappings":"AAAA;EACI,eAAA;EACA,UAAA;EACA,SAAA;EACA,OAAA;EACA,QAAA;;AAGJ;EACI,eAAA;EACA,WAAA;EACA,QAAA;EACA,SAAA;EACA,kBAAA;EACA,iBAAA;;AANJ,IAQC;EACC,kBAAA;EACA,yBAAA;;AAVF,IAaC;EACC,gBAAA;EACA,iBAAA;EACA,gBAAA;EACA,mBAAA;EACA,UAAA;;AAlBF,IAqBC;EACC,iBAAA;EACA,cAAA;EACA,WAAA;;AASD,mBALoC;EACjC;IACI,UAAA;IACA,iBAAA","file":"index.css"} \ No newline at end of file +{"version":3,"sources":["index.less"],"names":[],"mappings":"AAAA;EACI,eAAA;EACA,QAAA;EACA,SAAA;EACA,OAAA;EACA,QAAA;;AAGJ;EACI,eAAA;EACA,WAAA;EACA,QAAA;EACA,SAAA;EACA,kBAAA;EACA,iBAAA;;AANJ,IAQC;EACC,kBAAA;EACA,yBAAA;;AAVF,IAaC;EACC,gBAAA;EACA,iBAAA;EACA,gBAAA;EACA,mBAAA;EACA,UAAA;;AAlBF,IAqBC;EACC,iBAAA;EACA,cAAA;EACA,WAAA;;AASD,mBALoC;EACjC;IACI,UAAA;IACA,iBAAA","file":"index.css"} \ No newline at end of file diff --git a/web/views/@default/index/index.html b/web/views/@default/index/index.html index fca68f3a..fbdeba56 100644 --- a/web/views/@default/index/index.html +++ b/web/views/@default/index/index.html @@ -28,7 +28,7 @@
- +
@@ -37,6 +37,12 @@
+
+
+ + +
+
更多选项
diff --git a/web/views/@default/index/index.js b/web/views/@default/index/index.js index e6f27c16..b6abff90 100644 --- a/web/views/@default/index/index.js +++ b/web/views/@default/index/index.js @@ -1,16 +1,28 @@ Tea.context(function () { - this.username = ""; - this.password = ""; - this.passwordMd5 = ""; - this.encodedFrom = window.encodeURIComponent(this.from); + this.username = "" + this.password = "" + this.passwordMd5 = "" + this.encodedFrom = window.encodeURIComponent(this.from) - this.isSubmitting = false; + this.showOTP = false + + this.isSubmitting = false this.$delay(function () { - this.$find("form input[name='username']").focus(); - this.changePassword(); + this.$find("form input[name='username']").focus() + this.changePassword() }); + this.changeUsername = function () { + this.$post("/checkOTP") + .params({ + username: this.username + }) + .success(function (resp) { + this.showOTP = resp.data.requireOTP + }) + } + this.changePassword = function () { this.passwordMd5 = md5(this.password.trim()); }; diff --git a/web/views/@default/index/index.less b/web/views/@default/index/index.less index 6b77c422..4de95032 100644 --- a/web/views/@default/index/index.less +++ b/web/views/@default/index/index.less @@ -1,6 +1,6 @@ .form-box { position: fixed; - top: 2.5em; + top: 2em; bottom: 0; left: 0; right: 0;