commit
15953af96d
2
LICENSE
2
LICENSE
|
|
@ -186,7 +186,7 @@
|
||||||
same "printed page" as the copyright notice for easier
|
same "printed page" as the copyright notice for easier
|
||||||
identification within third-party archives.
|
identification within third-party archives.
|
||||||
|
|
||||||
Copyright [2023] [Leandro Antônio Farias Machado]
|
Copyright 2024 Leandro Antônio Farias Machado
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
|
|
||||||
11
README.md
11
README.md
|
|
@ -1,7 +1,13 @@
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<img src="https://github.com/OktopUSP/oktopus/assets/83298718/fc05c512-951d-448c-8c31-1e0881783460"/>
|
<img src="https://github.com/OktopUSP/oktopus/assets/83298718/fc05c512-951d-448c-8c31-1e0881783460"/></p>
|
||||||
</p>
|
|
||||||
<br/>
|
<br/>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<h4>Overview:</h4>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<img src="https://github.com/OktopUSP/oktopus/assets/83298718/11401f40-2e73-4610-97bb-29fea7e1e5e0"/>
|
||||||
|
image source = <a href="https://oktopus.app.br/controller">https://oktopus.app.br/controller</a>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<h4>Introduction:</h4>
|
<h4>Introduction:</h4>
|
||||||
|
|
@ -239,7 +245,6 @@ OBS: Do not use those instructions in production. To implement the project in pr
|
||||||
<img src="https://github.com/OktopUSP/oktopus/assets/83298718/4599d566-eada-4313-8ae1-31dae82391de"/>
|
<img src="https://github.com/OktopUSP/oktopus/assets/83298718/4599d566-eada-4313-8ae1-31dae82391de"/>
|
||||||
<img src="https://github.com/OktopUSP/oktopus/assets/83298718/501b4ccd-6147-4957-9096-695134e34b5e"/>
|
<img src="https://github.com/OktopUSP/oktopus/assets/83298718/501b4ccd-6147-4957-9096-695134e34b5e"/>
|
||||||
</li>
|
</li>
|
||||||
<h4>Agent Simulation:</h4>
|
|
||||||
<p>
|
<p>
|
||||||
In case you want a more complete and real-world simulation of devices you might use <a href="https://github.com/OktopUSP/agent-sim">Oktopus TR-369 Agent Simulator</a>.
|
In case you want a more complete and real-world simulation of devices you might use <a href="https://github.com/OktopUSP/agent-sim">Oktopus TR-369 Agent Simulator</a>.
|
||||||
</p>
|
</p>
|
||||||
|
|
|
||||||
1
agent/run.sh
Normal file
1
agent/run.sh
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
obuspa -p -v 4 -r ./oktopus-mqtt-obuspa.txt -i lo
|
||||||
10
backend/services/controller/go.mod
Executable file → Normal file
10
backend/services/controller/go.mod
Executable file → Normal file
|
|
@ -3,21 +3,22 @@ module github.com/leandrofars/oktopus
|
||||||
go 1.18
|
go 1.18
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
|
||||||
github.com/eclipse/paho.golang v0.10.0
|
github.com/eclipse/paho.golang v0.10.0
|
||||||
|
github.com/go-stomp/stomp v2.1.4+incompatible
|
||||||
|
github.com/golang-jwt/jwt/v5 v5.2.0
|
||||||
github.com/google/uuid v1.3.0
|
github.com/google/uuid v1.3.0
|
||||||
github.com/googollee/go-socket.io v1.7.0
|
github.com/googollee/go-socket.io v1.7.0
|
||||||
github.com/gorilla/mux v1.8.0
|
github.com/gorilla/mux v1.8.0
|
||||||
github.com/joho/godotenv v1.5.1
|
github.com/joho/godotenv v1.5.1
|
||||||
github.com/rs/cors v1.9.0
|
github.com/rs/cors v1.9.0
|
||||||
go.mongodb.org/mongo-driver v1.11.3
|
go.mongodb.org/mongo-driver v1.11.3
|
||||||
golang.org/x/crypto v0.14.0
|
golang.org/x/crypto v0.17.0
|
||||||
golang.org/x/net v0.17.0
|
golang.org/x/net v0.17.0
|
||||||
|
golang.org/x/sys v0.15.0
|
||||||
google.golang.org/protobuf v1.28.1
|
google.golang.org/protobuf v1.28.1
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/go-stomp/stomp v2.1.4+incompatible // indirect
|
|
||||||
github.com/gofrs/uuid v4.0.0+incompatible // indirect
|
github.com/gofrs/uuid v4.0.0+incompatible // indirect
|
||||||
github.com/golang/snappy v0.0.1 // indirect
|
github.com/golang/snappy v0.0.1 // indirect
|
||||||
github.com/gomodule/redigo v1.8.4 // indirect
|
github.com/gomodule/redigo v1.8.4 // indirect
|
||||||
|
|
@ -30,6 +31,5 @@ require (
|
||||||
github.com/xdg-go/stringprep v1.0.3 // indirect
|
github.com/xdg-go/stringprep v1.0.3 // indirect
|
||||||
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
|
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
|
||||||
golang.org/x/sys v0.13.0 // indirect
|
golang.org/x/text v0.14.0 // indirect
|
||||||
golang.org/x/text v0.13.0 // indirect
|
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
|
|
||||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
|
||||||
github.com/eclipse/paho.golang v0.10.0 h1:oUGPjRwWcZQRgDD9wVDV7y7i7yBSxts3vcvcNJo8B4Q=
|
github.com/eclipse/paho.golang v0.10.0 h1:oUGPjRwWcZQRgDD9wVDV7y7i7yBSxts3vcvcNJo8B4Q=
|
||||||
github.com/eclipse/paho.golang v0.10.0/go.mod h1:rhrV37IEwauUyx8FHrvmXOKo+QRKng5ncoN1vJiJMcs=
|
github.com/eclipse/paho.golang v0.10.0/go.mod h1:rhrV37IEwauUyx8FHrvmXOKo+QRKng5ncoN1vJiJMcs=
|
||||||
github.com/go-stomp/stomp v2.1.4+incompatible h1:D3SheUVDOz9RsjVWkoh/1iCOwD0qWjyeTZMUZ0EXg2Y=
|
github.com/go-stomp/stomp v2.1.4+incompatible h1:D3SheUVDOz9RsjVWkoh/1iCOwD0qWjyeTZMUZ0EXg2Y=
|
||||||
github.com/go-stomp/stomp v2.1.4+incompatible/go.mod h1:VqCtqNZv1226A1/79yh+rMiFUcfY3R109np+7ke4n0c=
|
github.com/go-stomp/stomp v2.1.4+incompatible/go.mod h1:VqCtqNZv1226A1/79yh+rMiFUcfY3R109np+7ke4n0c=
|
||||||
github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw=
|
github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw=
|
||||||
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||||
|
github.com/golang-jwt/jwt/v5 v5.2.0 h1:d/ix8ftRUorsN+5eMIlF4T6J8CAt9rch3My2winC1Jw=
|
||||||
|
github.com/golang-jwt/jwt/v5 v5.2.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
||||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||||
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
|
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
|
||||||
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
|
|
@ -60,8 +60,8 @@ github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7Jul
|
||||||
go.mongodb.org/mongo-driver v1.11.3 h1:Ql6K6qYHEzB6xvu4+AU0BoRoqf9vFPcc4o7MUIdPW8Y=
|
go.mongodb.org/mongo-driver v1.11.3 h1:Ql6K6qYHEzB6xvu4+AU0BoRoqf9vFPcc4o7MUIdPW8Y=
|
||||||
go.mongodb.org/mongo-driver v1.11.3/go.mod h1:PTSz5yu21bkT/wXpkS7WR5f0ddqw5quethTUn9WM+2g=
|
go.mongodb.org/mongo-driver v1.11.3/go.mod h1:PTSz5yu21bkT/wXpkS7WR5f0ddqw5quethTUn9WM+2g=
|
||||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
|
golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
|
||||||
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
|
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
||||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
|
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
|
||||||
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
||||||
|
|
@ -71,13 +71,13 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJ
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
|
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
|
||||||
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
|
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
|
@ -85,6 +85,7 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0
|
||||||
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
|
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
|
||||||
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/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.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,12 @@ package auth
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"github.com/dgrijalva/jwt-go"
|
"fmt"
|
||||||
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/golang-jwt/jwt/v5"
|
||||||
)
|
)
|
||||||
|
|
||||||
func getJwtKey() []byte {
|
func getJwtKey() []byte {
|
||||||
|
|
@ -18,16 +21,17 @@ func getJwtKey() []byte {
|
||||||
type JWTClaim struct {
|
type JWTClaim struct {
|
||||||
Username string `json:"username"`
|
Username string `json:"username"`
|
||||||
Email string `json:"email"`
|
Email string `json:"email"`
|
||||||
jwt.StandardClaims
|
jwt.RegisteredClaims
|
||||||
}
|
}
|
||||||
|
|
||||||
func GenerateJWT(email string, username string) (tokenString string, err error) {
|
func GenerateJWT(email string, username string) (tokenString string, err error) {
|
||||||
expirationTime := time.Now().Add(4 * time.Hour)
|
expirationTime := time.Now().Add(4 * time.Hour)
|
||||||
claims := &JWTClaim{
|
claims := &JWTClaim{
|
||||||
Email: email,
|
username,
|
||||||
Username: username,
|
email,
|
||||||
StandardClaims: jwt.StandardClaims{
|
jwt.RegisteredClaims{
|
||||||
ExpiresAt: expirationTime.Unix(),
|
ExpiresAt: jwt.NewNumericDate(expirationTime),
|
||||||
|
Issuer: "Oktopus",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||||
|
|
@ -40,21 +44,25 @@ func ValidateToken(signedToken string) (email string, err error) {
|
||||||
signedToken,
|
signedToken,
|
||||||
&JWTClaim{},
|
&JWTClaim{},
|
||||||
func(token *jwt.Token) (interface{}, error) {
|
func(token *jwt.Token) (interface{}, error) {
|
||||||
|
// Don't forget to validate the alg is what you expect:
|
||||||
|
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
|
||||||
|
return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
|
||||||
|
}
|
||||||
|
|
||||||
|
// hmacSampleSecret is a []byte containing your secret, e.g. []byte("my_secret_key")
|
||||||
return getJwtKey(), nil
|
return getJwtKey(), nil
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
claims, ok := token.Claims.(*JWTClaim)
|
claims, ok := token.Claims.(*JWTClaim)
|
||||||
if !ok {
|
if !ok {
|
||||||
err = errors.New("couldn't parse claims")
|
err = errors.New("couldn't parse claims")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if claims.ExpiresAt < time.Now().Local().Unix() {
|
|
||||||
err = errors.New("token expired")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
email = claims.Email
|
email = claims.Email
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,12 @@ package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"go.mongodb.org/mongo-driver/bson"
|
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"go.mongodb.org/mongo-driver/bson"
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"github.com/leandrofars/oktopus/internal/db"
|
"github.com/leandrofars/oktopus/internal/db"
|
||||||
usp_msg "github.com/leandrofars/oktopus/internal/usp_message"
|
usp_msg "github.com/leandrofars/oktopus/internal/usp_message"
|
||||||
|
|
@ -37,11 +38,15 @@ func (a *Api) retrieveDevices(w http.ResponseWriter, r *http.Request) {
|
||||||
const PAGE_SIZE_DEFAULT = 20
|
const PAGE_SIZE_DEFAULT = 20
|
||||||
|
|
||||||
// Get specific device
|
// Get specific device
|
||||||
id := mux.Vars(r)["id"]
|
id := r.URL.Query().Get("id")
|
||||||
if id != "" {
|
if id != "" {
|
||||||
device, err := a.Db.RetrieveDevice(id)
|
device, err := a.Db.RetrieveDevice(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err)
|
if err == mongo.ErrNoDocuments {
|
||||||
|
json.NewEncoder(w).Encode("Device id: " + id + " not found")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
json.NewEncoder(w).Encode(err)
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -59,7 +64,7 @@ func (a *Api) retrieveDevices(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
var page_number int64
|
var page_number int64
|
||||||
if page_n == "" {
|
if page_n == "" {
|
||||||
page_number = 1
|
page_number = 0
|
||||||
} else {
|
} else {
|
||||||
page_number, err = strconv.ParseInt(page_n, 10, 64)
|
page_number, err = strconv.ParseInt(page_n, 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -93,6 +98,7 @@ func (a *Api) retrieveDevices(w http.ResponseWriter, r *http.Request) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
json.NewEncoder(w).Encode("Unable to get devices count from database")
|
json.NewEncoder(w).Encode("Unable to get devices count from database")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
skip := page_number * (page_size - 1)
|
skip := page_number * (page_size - 1)
|
||||||
|
|
@ -103,9 +109,12 @@ func (a *Api) retrieveDevices(w http.ResponseWriter, r *http.Request) {
|
||||||
//TODO: Create filters
|
//TODO: Create filters
|
||||||
//TODO: Create sorting
|
//TODO: Create sorting
|
||||||
|
|
||||||
|
sort := bson.M{}
|
||||||
|
sort["status"] = 1
|
||||||
|
|
||||||
filter := bson.A{
|
filter := bson.A{
|
||||||
//bson.M{"$match": filter},
|
//bson.M{"$match": filter},
|
||||||
//bson.M{"$sort": sort},
|
bson.M{"$sort": sort}, // shows online devices first
|
||||||
bson.M{"$skip": skip},
|
bson.M{"$skip": skip},
|
||||||
bson.M{"$limit": page_size},
|
bson.M{"$limit": page_size},
|
||||||
}
|
}
|
||||||
|
|
@ -117,12 +126,15 @@ func (a *Api) retrieveDevices(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = json.NewEncoder(w).Encode(devices)
|
err = json.NewEncoder(w).Encode(map[string]interface{}{
|
||||||
|
"pages": total / page_size,
|
||||||
|
"page": page_number,
|
||||||
|
"size": page_size,
|
||||||
|
"devices": devices,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Api) deviceCreateMsg(w http.ResponseWriter, r *http.Request) {
|
func (a *Api) deviceCreateMsg(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
|
||||||
14
backend/services/socketio/package-lock.json
generated
14
backend/services/socketio/package-lock.json
generated
|
|
@ -9,7 +9,7 @@
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@koa/cors": "^4.0.0",
|
"@koa/cors": "^5.0.0",
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"dotenv": "^16.3.1",
|
"dotenv": "^16.3.1",
|
||||||
"express": "^4.18.2",
|
"express": "^4.18.2",
|
||||||
|
|
@ -18,9 +18,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@koa/cors": {
|
"node_modules/@koa/cors": {
|
||||||
"version": "4.0.0",
|
"version": "5.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/@koa/cors/-/cors-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/@koa/cors/-/cors-5.0.0.tgz",
|
||||||
"integrity": "sha512-Y4RrbvGTlAaa04DBoPBWJqDR5gPj32OOz827ULXfgB1F7piD1MB/zwn8JR2LAnvdILhxUbXbkXGWuNVsFuVFCQ==",
|
"integrity": "sha512-x/iUDjcS90W69PryLDIMgFyV21YLTnG9zOpPXS7Bkt2b8AsY3zZsIpOLBkYr9fBcF3HbkKaER5hOBZLfpLgYNw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"vary": "^1.1.2"
|
"vary": "^1.1.2"
|
||||||
},
|
},
|
||||||
|
|
@ -1084,9 +1084,9 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@koa/cors": {
|
"@koa/cors": {
|
||||||
"version": "4.0.0",
|
"version": "5.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/@koa/cors/-/cors-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/@koa/cors/-/cors-5.0.0.tgz",
|
||||||
"integrity": "sha512-Y4RrbvGTlAaa04DBoPBWJqDR5gPj32OOz827ULXfgB1F7piD1MB/zwn8JR2LAnvdILhxUbXbkXGWuNVsFuVFCQ==",
|
"integrity": "sha512-x/iUDjcS90W69PryLDIMgFyV21YLTnG9zOpPXS7Bkt2b8AsY3zZsIpOLBkYr9fBcF3HbkKaER5hOBZLfpLgYNw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"vary": "^1.1.2"
|
"vary": "^1.1.2"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
"author": "",
|
"author": "",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@koa/cors": "^4.0.0",
|
"@koa/cors": "^5.0.0",
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"dotenv": "^16.3.1",
|
"dotenv": "^16.3.1",
|
||||||
"express": "^4.18.2",
|
"express": "^4.18.2",
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,44 @@ http {
|
||||||
# for more information.
|
# for more information.
|
||||||
include /etc/nginx/conf.d/*.conf;
|
include /etc/nginx/conf.d/*.conf;
|
||||||
|
|
||||||
|
server {
|
||||||
|
if ($host = oktopus.app.br) {
|
||||||
|
return 301 https://$host$request_uri;
|
||||||
|
}
|
||||||
|
listen 80;
|
||||||
|
listen [::]:80;
|
||||||
|
server_name oktopus.app.br;
|
||||||
|
return 404;
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 443 ssl http2;
|
||||||
|
listen [::]:443 ssl http2;
|
||||||
|
server_name oktopus.app.br;
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
|
||||||
|
# Load configuration files for the default server block.
|
||||||
|
include /etc/nginx/default.d/*.conf;
|
||||||
|
|
||||||
|
ssl_certificate "/etc/letsencrypt/live/oktopus.app.br/fullchain.pem";
|
||||||
|
ssl_certificate_key "/etc/letsencrypt/live/oktopus.app.br/privkey.pem";
|
||||||
|
ssl_session_cache shared:SSL:1m;
|
||||||
|
ssl_session_timeout 10m;
|
||||||
|
ssl_ciphers HIGH:!aNULL:!MD5;
|
||||||
|
ssl_prefer_server_ciphers on;
|
||||||
|
|
||||||
|
error_page 404 /404.html;
|
||||||
|
location = /404.html {
|
||||||
|
}
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://127.0.0.1:3001;
|
||||||
|
proxy_read_timeout 60;
|
||||||
|
proxy_connect_timeout 60;
|
||||||
|
proxy_redirect off;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
server {
|
server {
|
||||||
if ($host = oktopustr369.com) {
|
if ($host = oktopustr369.com) {
|
||||||
return 301 https://$host$request_uri;
|
return 301 https://$host$request_uri;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,18 @@
|
||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import Head from 'next/head';
|
import Head from 'next/head';
|
||||||
import { Box, Container, Unstable_Grid2 as Grid } from '@mui/material';
|
import {
|
||||||
|
Box,
|
||||||
|
Container,
|
||||||
|
Unstable_Grid2 as Grid,
|
||||||
|
Card,
|
||||||
|
OutlinedInput,
|
||||||
|
InputAdornment,
|
||||||
|
SvgIcon,
|
||||||
|
Stack,
|
||||||
|
Pagination,
|
||||||
|
CircularProgress
|
||||||
|
} from '@mui/material';
|
||||||
|
import MagnifyingGlassIcon from '@heroicons/react/24/solid/MagnifyingGlassIcon';
|
||||||
import { Layout as DashboardLayout } from 'src/layouts/dashboard/layout';
|
import { Layout as DashboardLayout } from 'src/layouts/dashboard/layout';
|
||||||
import { OverviewLatestOrders } from 'src/sections/overview/overview-latest-orders';
|
import { OverviewLatestOrders } from 'src/sections/overview/overview-latest-orders';
|
||||||
import { useAuth } from 'src/hooks/use-auth';
|
import { useAuth } from 'src/hooks/use-auth';
|
||||||
|
|
@ -10,9 +22,14 @@ const Page = () => {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const auth = useAuth();
|
const auth = useAuth();
|
||||||
const [devices, setDevices] = useState([]);
|
const [devices, setDevices] = useState([]);
|
||||||
|
const [deviceFound, setDeviceFound] = useState(false)
|
||||||
|
const [pages, setPages] = useState(0);
|
||||||
|
const [page, setPage] = useState(null);
|
||||||
|
const [Loading, setLoading] = useState(true);
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
setLoading(true)
|
||||||
if (auth.user.token) {
|
if (auth.user.token) {
|
||||||
console.log("auth.user.token =", auth.user.token)
|
console.log("auth.user.token =", auth.user.token)
|
||||||
}else{
|
}else{
|
||||||
|
|
@ -36,13 +53,106 @@ const Page = () => {
|
||||||
return response.json()
|
return response.json()
|
||||||
})
|
})
|
||||||
.then(json => {
|
.then(json => {
|
||||||
return setDevices(json)
|
setPages(json.pages + 1)
|
||||||
|
setPage(json.page)
|
||||||
|
setDevices(json.devices)
|
||||||
|
setLoading(false)
|
||||||
|
return setDeviceFound(true)
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
return console.error('Error:', error)
|
return console.error('Error:', error)
|
||||||
});
|
});
|
||||||
}, [auth.user]);
|
}, [auth.user]);
|
||||||
|
|
||||||
|
const handleChangePage = (event, value) => {
|
||||||
|
console.log("new page: ", value)
|
||||||
|
setPage(value)
|
||||||
|
fetchDevicePerPage(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
const fetchDevicePerPage = async (p) => {
|
||||||
|
setLoading(true)
|
||||||
|
|
||||||
|
var myHeaders = new Headers();
|
||||||
|
myHeaders.append("Content-Type", "application/json");
|
||||||
|
myHeaders.append("Authorization", auth.user.token);
|
||||||
|
|
||||||
|
var requestOptions = {
|
||||||
|
method: 'GET',
|
||||||
|
headers: myHeaders,
|
||||||
|
redirect: 'follow'
|
||||||
|
}
|
||||||
|
|
||||||
|
p = p - 1
|
||||||
|
p = p.toString()
|
||||||
|
|
||||||
|
fetch(process.env.NEXT_PUBLIC_REST_ENPOINT+'/device?page_number='+p, requestOptions)
|
||||||
|
.then(response => {
|
||||||
|
if (response.status === 401)
|
||||||
|
router.push("/auth/login")
|
||||||
|
return response.json()
|
||||||
|
})
|
||||||
|
.then(json => {
|
||||||
|
setDevices(json.devices)
|
||||||
|
setLoading(false)
|
||||||
|
return
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
return console.error('Error:', error)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const fetchDevicePerId = async (id) => {
|
||||||
|
setLoading(true)
|
||||||
|
var myHeaders = new Headers();
|
||||||
|
myHeaders.append("Content-Type", "application/json");
|
||||||
|
myHeaders.append("Authorization", auth.user.token);
|
||||||
|
|
||||||
|
var requestOptions = {
|
||||||
|
method: 'GET',
|
||||||
|
headers: myHeaders,
|
||||||
|
redirect: 'follow'
|
||||||
|
}
|
||||||
|
|
||||||
|
if (id == ""){
|
||||||
|
return fetch(process.env.NEXT_PUBLIC_REST_ENPOINT+'/device', requestOptions)
|
||||||
|
.then(response => {
|
||||||
|
if (response.status === 401)
|
||||||
|
router.push("/auth/login")
|
||||||
|
return response.json()
|
||||||
|
})
|
||||||
|
.then(json => {
|
||||||
|
setPages(json.pages + 1)
|
||||||
|
setPage(json.page)
|
||||||
|
setDevices(json.devices)
|
||||||
|
setLoading(false)
|
||||||
|
return setDeviceFound(true)
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
return console.error('Error:', error)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let response = await fetch(process.env.NEXT_PUBLIC_REST_ENPOINT+'/device?id='+id, requestOptions)
|
||||||
|
if (response.status === 401)
|
||||||
|
router.push("/auth/login")
|
||||||
|
let json = await response.json()
|
||||||
|
if (json.MTP != undefined){
|
||||||
|
setDevices([json])
|
||||||
|
setDeviceFound(true)
|
||||||
|
setLoading(false)
|
||||||
|
setPages(1)
|
||||||
|
setPage(1)
|
||||||
|
}else{
|
||||||
|
setDeviceFound(false)
|
||||||
|
setDevices([])
|
||||||
|
setPages(1)
|
||||||
|
setPage(1)
|
||||||
|
setLoading(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Head>
|
<Head>
|
||||||
|
|
@ -50,6 +160,7 @@ const Page = () => {
|
||||||
Oktopus | TR-369
|
Oktopus | TR-369
|
||||||
</title>
|
</title>
|
||||||
</Head>
|
</Head>
|
||||||
|
|
||||||
<Box
|
<Box
|
||||||
component="main"
|
component="main"
|
||||||
sx={{
|
sx={{
|
||||||
|
|
@ -58,15 +169,68 @@ const Page = () => {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Container maxWidth="xl" >
|
<Container maxWidth="xl" >
|
||||||
|
<Stack spacing={3}>
|
||||||
<Grid
|
<Grid
|
||||||
container
|
container
|
||||||
spacing={3}
|
|
||||||
>
|
>
|
||||||
|
<Grid xs={8}>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
<OutlinedInput
|
||||||
|
xs={4}
|
||||||
|
defaultValue=""
|
||||||
|
fullWidth
|
||||||
|
placeholder="Search Device"
|
||||||
|
onKeyDownCapture={(e) => {
|
||||||
|
if (e.key === 'Enter') {
|
||||||
|
console.log("Fetch devices per id: ", e.target.value)
|
||||||
|
fetchDevicePerId(e.target.value)
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
startAdornment={(
|
||||||
|
<InputAdornment position="start">
|
||||||
|
<SvgIcon
|
||||||
|
color="action"
|
||||||
|
fontSize="small"
|
||||||
|
>
|
||||||
|
<MagnifyingGlassIcon />
|
||||||
|
</SvgIcon>
|
||||||
|
</InputAdornment>
|
||||||
|
)}
|
||||||
|
sx={{ maxWidth: 500 }}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
{deviceFound ?
|
||||||
|
( !Loading ?
|
||||||
<OverviewLatestOrders
|
<OverviewLatestOrders
|
||||||
orders={devices}
|
orders={devices}
|
||||||
sx={{ height: '100%' }}
|
sx={{ height: '100%' }}
|
||||||
/>
|
/> : <CircularProgress></CircularProgress>
|
||||||
|
)
|
||||||
|
:
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'center'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<p>Device Not Found</p>
|
||||||
|
</Box>
|
||||||
|
}
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'center'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{pages ? <Pagination
|
||||||
|
count={pages}
|
||||||
|
size="small"
|
||||||
|
page={page}
|
||||||
|
onChange={handleChangePage}
|
||||||
|
/>: null}
|
||||||
|
{/* //TODO: show loading */}
|
||||||
|
</Box>
|
||||||
|
</Stack>
|
||||||
</Container>
|
</Container>
|
||||||
</Box>
|
</Box>
|
||||||
</>
|
</>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user