Compare commits

..

18 Commits

Author SHA1 Message Date
Simon ed30c8de24 Fix chart precision
continuous-integration/drone/push Build is passing Details
2021-10-06 02:13:14 +01:00
Simon 76e35c7a63 fix graph gridlines
continuous-integration/drone/push Build is passing Details
2021-10-06 02:01:41 +01:00
Simon 868291c135 Remove Privacy page, clean up some css, add jacknet login link
continuous-integration/drone/push Build is passing Details
2021-10-06 00:45:38 +01:00
Simon d7c38191ce Add device page filter
continuous-integration/drone/push Build is passing Details
2021-10-05 23:43:23 +01:00
Simon 26017568f0 Cache api device keys
continuous-integration/drone/push Build is passing Details
2021-10-04 00:56:24 +01:00
Simon 04028b41e7 Remove maintain aspect ratio
continuous-integration/drone/push Build is passing Details
2021-10-03 16:18:05 +01:00
Simon 51b0324e13 Update graph formating
continuous-integration/drone/push Build is passing Details
2021-10-03 15:09:13 +01:00
Simon 6c8fdf875f Update nginx
continuous-integration/drone/push Build is passing Details
2021-10-03 03:52:45 +01:00
Simon 55486aaedd Im in? 2021-10-03 03:48:30 +01:00
Simon bacb791ba9 :`(
continuous-integration/drone/push Build is passing Details
2021-10-03 03:11:40 +01:00
Simon 2d52da61a3 Another attempt
continuous-integration/drone/push Build is passing Details
2021-10-03 03:05:31 +01:00
Simon b7f07c36b9 More attempting to read forward headers
continuous-integration/drone/push Build is passing Details
2021-10-03 02:55:25 +01:00
Simon afbcf4ae11 Attempt to use ForwardedHeadersOptions
continuous-integration/drone/push Build is passing Details
2021-10-03 02:42:03 +01:00
Simon a9e1baf7c3 Update injection of values to frontend
continuous-integration/drone/push Build is passing Details
2021-10-03 02:08:31 +01:00
Simon 90346cefda Update read database path
continuous-integration/drone/push Build is passing Details
2021-10-03 00:13:51 +01:00
Simon 3e5bf1d23d Read mongodb path from env
continuous-integration/drone/push Build is failing Details
2021-10-03 00:08:41 +01:00
Simon 9bb6c12ef9 update naming issue
continuous-integration/drone/push Build is passing Details
2021-10-02 03:45:15 +01:00
Simon 42ad8129b5 Collect all firmware
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2021-10-02 03:41:39 +01:00
25 changed files with 498 additions and 107 deletions

View File

@ -28,7 +28,7 @@ steps:
settings: settings:
context: ManagementPage context: ManagementPage
dockerfile: ManagementPage/ManagementPage/Dockerfile dockerfile: ManagementPage/ManagementPage/Dockerfile
repo: registry.jacknet.io/51m0n/environment-api repo: registry.jacknet.io/51m0n/environment-frontend
username: simon username: simon
password: password:
from_secret: docker_password from_secret: docker_password
@ -64,7 +64,6 @@ steps:
base_url: https://git.jacknet.io base_url: https://git.jacknet.io
api_key: api_key:
from_secret: gitea_token from_secret: gitea_token
files: files: ESP-Temp-Humidity\.pio\build\esp07\firmware.*
- ESP-Temp-Humidity\.pio\build\esp07\firmware.bin
checksum: checksum:
- sha1 - sha1

View File

@ -3,6 +3,7 @@ module 51m0n.com/EnvironmentManagerAPI/v2
go 1.15 go 1.15
require ( require (
github.com/coocood/freecache v1.1.1
github.com/gin-gonic/gin v1.7.4 github.com/gin-gonic/gin v1.7.4
go.mongodb.org/mongo-driver v1.7.2 go.mongodb.org/mongo-driver v1.7.2
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9

View File

@ -1,4 +1,9 @@
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/coocood/freecache v1.1.1 h1:uukNF7QKCZEdZ9gAV7WQzvh0SbjwdMF6m3x3rxEkaPc=
github.com/coocood/freecache v1.1.1/go.mod h1:OKrEjkGVoxZhyWAJoeFi5BMLUJm2Tit0kpGkIr7NGYY=
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/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
@ -80,6 +85,7 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR
github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
@ -109,8 +115,11 @@ golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaE
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 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-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -125,8 +134,13 @@ golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42 h1:vEOn+mP2zCOVzKckCZy6YsCtDblrpj/w7B9nxGNELpg= golang.org/x/sys v0.0.0-20200116001909-b77594299b42 h1:vEOn+mP2zCOVzKckCZy6YsCtDblrpj/w7B9nxGNELpg=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ= golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
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=

View File

@ -3,9 +3,12 @@ package src
import ( import (
"context" "context"
"fmt" "fmt"
"os"
"encoding/base64" "encoding/base64"
"encoding/binary"
"github.com/coocood/freecache"
"go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options" "go.mongodb.org/mongo-driver/mongo/options"
@ -13,15 +16,21 @@ import (
"golang.org/x/crypto/blake2s" "golang.org/x/crypto/blake2s"
) )
const uri = "mongodb://192.168.0.159:27017"
const salt = "ENVIRONMENT" const salt = "ENVIRONMENT"
// 30m
const timeout = 1800
// 10m
const cacheSize = 10 * 1024 * 1024
var dbCollection *mongo.Collection var dbCollection *mongo.Collection
var dbDevices *mongo.Collection var dbDevices *mongo.Collection
var mongoClient *mongo.Client var mongoClient *mongo.Client
var cache *freecache.Cache
func DbConnect() { func DbConnect() {
mongoClient, err := mongo.Connect(context.TODO(), options.Client().ApplyURI(uri)) mongoClient, err := mongo.Connect(context.TODO(), options.Client().ApplyURI(getMongoURI()))
if err != nil { if err != nil {
panic(err) panic(err)
@ -33,9 +42,16 @@ func DbConnect() {
db := mongoClient.Database("Environment") db := mongoClient.Database("Environment")
dbCollection = db.Collection("Main") dbCollection = db.Collection("Main")
dbDevices = db.Collection("Devices") dbDevices = db.Collection("Devices")
cache = freecache.NewCache(cacheSize)
} }
func GetDeviceKey(api uint64) ([]byte, error) { func GetDeviceKey(api uint64) ([]byte, error) {
cacheKey := Uint64ToBytes(api)
// Check the cache for the user
val, err := cache.Get(cacheKey)
if err == nil {
return val, err
} else {
apiSigned := int64(api) apiSigned := int64(api)
filter := bson.D{{"ApiID", apiSigned}} filter := bson.D{{"ApiID", apiSigned}}
var result bson.M var result bson.M
@ -47,8 +63,16 @@ func GetDeviceKey(api uint64) ([]byte, error) {
key, err := DeriveKey(result["Passcode"].(string)) key, err := DeriveKey(result["Passcode"].(string))
fmt.Printf(base64.StdEncoding.EncodeToString(key)) fmt.Printf(base64.StdEncoding.EncodeToString(key))
// We should cache this! // We should cache this!
_ = cache.Set(cacheKey, key, timeout)
return key, err return key, err
} }
}
func Uint64ToBytes(num uint64) []byte {
buf := make([]byte, 8)
binary.BigEndian.PutUint64(buf, num)
return buf
}
func DeriveKey(passcode string) ([]byte, error) { func DeriveKey(passcode string) ([]byte, error) {
@ -70,3 +94,13 @@ func DbDisconnect() {
panic(err) panic(err)
} }
} }
func getMongoURI() string {
dbPath := os.Getenv("GIN_DB_PATH")
if dbPath == "" {
dbPath = "mongodb://192.168.0.159:27017"
}
return dbPath
}

5
EnvTest/go.mod Normal file
View File

@ -0,0 +1,5 @@
module 51m0n.com/EnvironmentManagerTest/v2
go 1.15
require golang.org/x/crypto v0.0.0-20210921155107-089bfa567519

9
EnvTest/go.sum Normal file
View File

@ -0,0 +1,9 @@
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=

73
EnvTest/main.go Normal file
View File

@ -0,0 +1,73 @@
package main
import (
"bytes"
"crypto/rand"
"encoding/json"
"fmt"
"io"
"net/http"
"golang.org/x/crypto/blake2s"
"golang.org/x/crypto/chacha20poly1305"
)
type EnvironmentData struct {
Temp float64 `json:"t" binding:"required"`
Humidity float64 `json:"h" binding:"required"`
}
const passcode = "pass2"
const salt = "ENVIRONMENT"
func main() {
data := EnvironmentData{Temp: 25, Humidity: 40}
b, err := json.Marshal(data)
if err != nil {
panic(err)
}
pass, err := DeriveKey(passcode)
if err != nil {
panic(err)
}
aead, err := chacha20poly1305.New([]byte(pass))
if err != nil {
panic(err)
}
iv := make([]byte, chacha20poly1305.NonceSize)
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
panic(err)
}
cypher := aead.Seal(nil, iv, b, nil)
cypher = append(iv, cypher...)
request, err := http.NewRequest(http.MethodPut, "http://localhost:8080/data/authed/7701238505945920037", bytes.NewReader(cypher))
if err == nil {
resp, err := http.DefaultClient.Do(request)
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Printf("Sent, code: %s", resp.Status)
} else {
panic(err)
}
}
func DeriveKey(passcode string) ([]byte, error) {
hash, err := blake2s.New256(nil)
if err != nil {
return nil, err
}
hash.Write([]byte(salt))
hash.Write([]byte(passcode))
fmt.Printf("SALT %s PASS %s\n", salt, passcode)
return hash.Sum(nil), nil
}

View File

@ -11,7 +11,7 @@ namespace ManagementPage.Database
private const string _accountsCollectionName = "Accounts"; private const string _accountsCollectionName = "Accounts";
private const string _deviceCollectionName = "Devices"; private const string _deviceCollectionName = "Devices";
private const string _databaseName = "Environment"; private const string _databaseName = "Environment";
private const string _uri = "mongodb://192.168.0.159:27017"; private readonly string _uri;
private readonly IMongoDatabase _database; private readonly IMongoDatabase _database;
private readonly MongoClient _client; private readonly MongoClient _client;
@ -20,8 +20,9 @@ namespace ManagementPage.Database
public IMongoCollection<DeviceData> DeviceCollection { get; private set; } public IMongoCollection<DeviceData> DeviceCollection { get; private set; }
public MongoDbClient() public MongoDbClient(IConfiguration configRoot)
{ {
_uri = configRoot["mongodb:uri"];
_client = new MongoClient(_uri); _client = new MongoClient(_uri);
_database = _client.GetDatabase(_databaseName); _database = _client.GetDatabase(_databaseName);
BsonClassMap.RegisterClassMap<EnvironmentData>(cm => BsonClassMap.RegisterClassMap<EnvironmentData>(cm =>

View File

@ -6,6 +6,9 @@
<RazorPage_SelectedScaffolderID>RazorPageScaffolder</RazorPage_SelectedScaffolderID> <RazorPage_SelectedScaffolderID>RazorPageScaffolder</RazorPage_SelectedScaffolderID>
<RazorPage_SelectedScaffolderCategoryPath>root/Common/RazorPage</RazorPage_SelectedScaffolderCategoryPath> <RazorPage_SelectedScaffolderCategoryPath>root/Common/RazorPage</RazorPage_SelectedScaffolderCategoryPath>
<NameOfLastUsedPublishProfile>P:\EnvironmentManagement\ManagementPage\ManagementPage\Properties\PublishProfiles\registry.jacknet.io.pubxml</NameOfLastUsedPublishProfile> <NameOfLastUsedPublishProfile>P:\EnvironmentManagement\ManagementPage\ManagementPage\Properties\PublishProfiles\registry.jacknet.io.pubxml</NameOfLastUsedPublishProfile>
<ActiveDebugProfile>Docker</ActiveDebugProfile> <ActiveDebugProfile>ManagementPage</ActiveDebugProfile>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DebuggerFlavor>ProjectDebugger</DebuggerFlavor>
</PropertyGroup> </PropertyGroup>
</Project> </Project>

View File

@ -8,10 +8,10 @@
<h2>@Model.device.Name</h2> <h2>@Model.device.Name</h2>
<h4>Current Conditions</h4> <h4>Current Conditions</h4>
<div> <div>
Temp: @Model.data.LastOrDefault()?.Temperature.ToString("N1") Temp: @Model.data.FirstOrDefault()?.Temperature.ToString("N1")°C
</div> </div>
<div> <div>
Humidity: @Model.data.LastOrDefault()?.Humidity.ToString("N1") Humidity: @Model.data.FirstOrDefault()?.Humidity.ToString("N1")%
</div> </div>
</div> </div>
<div > <div >
@ -19,6 +19,8 @@
</div> </div>
<script src="~/lib/chart.js/dist/chart.js"></script> <script src="~/lib/chart.js/dist/chart.js"></script>
<script src="https://cdn.jsdelivr.net/npm/moment@2.29.1/moment.js" integrity="sha256-8AdWdyRXkrETyAGla9NmgkYVlqw4MOHR6sJJmtFGAYQ=" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-moment@1.0.0/dist/chartjs-adapter-moment.min.js" integrity="sha256-sFB24K2xU2EOgWAtb3ySAGjhMqcUvUJGmwjDcTQa04k=" crossorigin="anonymous"></script>
<script src="~/js/temperature_chart.js" asp-append-version="true"></script> <script src="~/js/temperature_chart.js" asp-append-version="true"></script>
<script> <script>
var ctx = document.getElementById('tempChart'); var ctx = document.getElementById('tempChart');

View File

@ -25,11 +25,12 @@ namespace ManagementPage.Pages
humidity = new List<DataSet>(); humidity = new List<DataSet>();
temperature = new List<DataSet>(); temperature = new List<DataSet>();
_dbClient = dbClient; _dbClient = dbClient;
device = new DeviceData("","",0);
} }
public async Task<IActionResult> OnGetAsync() public async Task<IActionResult> OnGetAsync()
{ {
var deviceId = 0l ; var deviceId = 0L;
try try
{ {
var idString = (string?)RouteData.Values.Where(k => k.Key == "id")?.First().Value; var idString = (string?)RouteData.Values.Where(k => k.Key == "id")?.First().Value;

View File

@ -3,7 +3,7 @@
@{ @{
ViewData["Title"] = "Error"; ViewData["Title"] = "Error";
} }
<div style="font-family:'Trebuchet MS', 'Lucida Sans Unicode', 'Lucida Grande', 'Lucida Sans', Arial, sans-serif">
<h1 class="text-danger">Error.</h1> <h1 class="text-danger">Error.</h1>
<h2 class="text-danger">An error occurred while processing your request.</h2> <h2 class="text-danger">An error occurred while processing your request.</h2>
@ -13,14 +13,3 @@
<strong>Request ID:</strong> <code>@Model.RequestId</code> <strong>Request ID:</strong> <code>@Model.RequestId</code>
</p> </p>
} }
<h3>Development Mode</h3>
<p>
Swapping to the <strong>Development</strong> environment displays detailed information about the error that occurred.
</p>
<p>
<strong>The Development environment shouldn't be enabled for deployed applications.</strong>
It can result in displaying sensitive information from exceptions to end users.
For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>
and restarting the app.
</p>

View File

@ -6,5 +6,21 @@
<div class="text-center"> <div class="text-center">
<h1 class="display-4">Welcome</h1> <h1 class="display-4">Welcome</h1>
<p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p> <div class="container-fluid">
@if (User.Identity == null || !User.Identity.IsAuthenticated)
{
<h2>Please log in</h2>
<a asp-page="/UserHome" style="display: inline-block;">
<span style="white-space: nowrap;display: flex;">
Login with
<img style="no-repeat;width: 6em;background-size: contain;background-position: center;margin-left: 10px;" src="~/static/JackNet-auth-logo-orange.svg"></img>
</span>
</a>
}
else
{
<p>You're already logged in, please use the <a asp-area="" asp-page="/UserHome">User</a> tab to see your devices.</p>
}
</div> </div>

View File

@ -1,8 +0,0 @@
@page
@model PrivacyModel
@{
ViewData["Title"] = "Privacy Policy";
}
<h1>@ViewData["Title"]</h1>
<p>Use this page to detail your site's privacy policy.</p>

View File

@ -1,19 +0,0 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace ManagementPage.Pages
{
public class PrivacyModel : PageModel
{
private readonly ILogger<PrivacyModel> _logger;
public PrivacyModel(ILogger<PrivacyModel> logger)
{
_logger = logger;
}
public void OnGet()
{
}
}
}

View File

@ -23,16 +23,16 @@
<li class="nav-item"> <li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a> <a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
</li> </li>
<li class="nav-item"> @if (User.Identity != null && User.Identity.IsAuthenticated)
<a class="nav-link text-dark" asp-area="" asp-page="/Privacy">Privacy</a> {
</li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-page="/UserHome">User</a> <a class="nav-link text-dark" asp-area="" asp-page="/UserHome">User</a>
</li> </li>
}
</ul> </ul>
@if (User.Identity != null && User.Identity.IsAuthenticated) @if (User.Identity != null && User.Identity.IsAuthenticated)
{ {
<ul class="navbar-nav flex-grow-1"> <ul class="navbar-nav flex-grow-1" style="justify-content: right">
<li class="nav-item"> <li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-page="/logout">Logout</a> <a class="nav-link text-dark" asp-area="" asp-page="/logout">Logout</a>
</li> </li>
@ -50,7 +50,7 @@
<footer class="border-top footer text-muted"> <footer class="border-top footer text-muted">
<div class="container"> <div class="container">
&copy; 2021 - ManagementPage - <a asp-area="" asp-page="/Privacy">Privacy</a> &copy; 2021 - 51m0n</a>
</div> </div>
</footer> </footer>

View File

@ -6,6 +6,7 @@
<h3>Hi @Model.name</h3> <h3>Hi @Model.name</h3>
<hr></hr> <hr></hr>
<div class="container-fluid">
<div class="card-deck row row-cols-1 row-cols-md-3 g-4"> <div class="card-deck row row-cols-1 row-cols-md-3 g-4">
@foreach (var item in @Model.data) @foreach (var item in @Model.data)
{ {
@ -23,14 +24,16 @@
} }
<div class="card text-center" style="width: 18rem;"> <div class="card text-center" style="width: 18rem;">
<div class="card-body "> <div class="card-body d-flex flex-column">
<h5 class="card-title">New Item</h5> <h5 class="card-title">New Item</h5>
<p class="card-text">Register a new device</p> <p class="card-text">Register a new device</p>
<div class="mt-auto">
<button type="button" class="btn btn-primary oi oi-plus" data-bs-toggle="modal" data-bs-target="#devicemodal"></button> <button type="button" class="btn btn-primary oi oi-plus" data-bs-toggle="modal" data-bs-target="#devicemodal"></button>
</div> </div>
</div> </div>
</div> </div>
</div>
</div>
<div class="modal fade" id="devicemodal" tabindex="-1" aria-labelledby="deviceModalLabel" aria-hidden="true"> <div class="modal fade" id="devicemodal" tabindex="-1" aria-labelledby="deviceModalLabel" aria-hidden="true">
<div class="modal-dialog"> <div class="modal-dialog">
<div class="modal-content"> <div class="modal-content">

View File

@ -44,9 +44,9 @@ namespace ManagementPage.Pages
var id = await binder.GetLocalAccount(User.FindFirstValue(ClaimTypes.NameIdentifier)); var id = await binder.GetLocalAccount(User.FindFirstValue(ClaimTypes.NameIdentifier));
name = User.FindFirstValue(ClaimTypes.GivenName); name = User.FindFirstValue(ClaimTypes.GivenName);
using var cursor = await _dbClient.DeviceCollection.FindAsync(new BsonDocument()); data.Clear();
data = cursor.ToList();
data.AddRange(_dbClient.DeviceCollection.AsQueryable().Where(s => id.Devices.Contains(s._id)).ToArray());
foreach (var item in data) foreach (var item in data)
{ {

View File

@ -4,10 +4,19 @@ using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.OpenIdConnect; using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.HttpOverrides; using Microsoft.AspNetCore.HttpOverrides;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using System.Collections;
var builder = WebApplication.CreateBuilder(args); var builder = WebApplication.CreateBuilder(args);
var Configuration = builder.Configuration; var Configuration = builder.Configuration;
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
options.KnownNetworks.Clear();
options.KnownProxies.Clear();
});
// Add services to the container. // Add services to the container.
builder.Services.AddRazorPages(); builder.Services.AddRazorPages();
builder.Services.AddControllers(); builder.Services.AddControllers();
@ -24,7 +33,6 @@ builder.Services.AddAuthentication(options => {
options.ClientSecret = Configuration["oidc:clientsecret"]; options.ClientSecret = Configuration["oidc:clientsecret"];
options.Authority = @"https://auth.jacknet.io/auth/realms/JackNet"; options.Authority = @"https://auth.jacknet.io/auth/realms/JackNet";
//options.Authority = String.Format("https://{0}.onelogin.com/oidc/2", Configuration["oidc:region"]); //options.Authority = String.Format("https://{0}.onelogin.com/oidc/2", Configuration["oidc:region"]);
options.ResponseType = "code"; options.ResponseType = "code";
options.GetClaimsFromUserInfoEndpoint = true; options.GetClaimsFromUserInfoEndpoint = true;
} }
@ -32,6 +40,8 @@ builder.Services.AddAuthentication(options => {
var app = builder.Build(); var app = builder.Build();
app.UseForwardedHeaders();
// Configure the HTTP request pipeline. // Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment()) if (!app.Environment.IsDevelopment())
{ {
@ -40,7 +50,6 @@ if (!app.Environment.IsDevelopment())
app.UseHsts(); app.UseHsts();
} }
//app.UseHttpsRedirection();
app.UseStaticFiles(); app.UseStaticFiles();
app.UseAuthentication(); app.UseAuthentication();
@ -49,12 +58,6 @@ app.UseRouting();
app.UseAuthorization(); app.UseAuthorization();
app.UseForwardedHeaders(new ForwardedHeadersOptions
{
RequireHeaderSymmetry = false,
ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
});
app.MapRazorPages(); app.MapRazorPages();
app.Run(); app.Run();

View File

@ -14,7 +14,7 @@
"environmentVariables": { "environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development" "ASPNETCORE_ENVIRONMENT": "Development"
}, },
"applicationUrl": "https://environment.51m0n.com;http://+:80", "applicationUrl": "https://localhost:443;http://+:80",
"dotnetRunMessages": true "dotnetRunMessages": true
}, },
"IIS Express": { "IIS Express": {

View File

@ -6,6 +6,9 @@
"Microsoft.AspNetCore": "Warning" "Microsoft.AspNetCore": "Warning"
} }
}, },
"mongodb": {
"uri": "mongodb://192.168.0.159:27017"
},
"oidc": { "oidc": {
"region": "openid-connect", "region": "openid-connect",
"clientid": "51m0n-temperature", "clientid": "51m0n-temperature",

View File

@ -24,7 +24,65 @@ function CreateChart(ctx, temp, humidity) {
const config = { const config = {
type: 'line', type: 'line',
data: data, data: data,
options: { maintainAspectRatio: true } options: {
maintainAspectRatio: true,
scales: {
y: {
title: {
display: true,
text: "Temperature",
},
ticks: {
callback: function (value, index, values) {
return value + '°C';
},
precision: 1,
}
},
humid: {
title: {
display: true,
text: "Humidity",
},
position: "right",
ticks: {
callback: function (value, index, values) {
return value + '%';
},
precision: 0,
},
grid: {
drawOnChartArea: false,
},
},
x: {
title: {
display: true,
text: "Time",
},
type: 'time',
time: {
unit: 'minute',
displayFormats: {
minute: "D MMM HH:mm"
},
},
ticks: {
autoSkip: true,
maxTicksLimit: 25
}
}
},
plugins: {
legend: {
labels: {
font: {
family: "'Quicksand', serif"
}
}
}
}
}
}; };
return tempChart = new Chart(ctx, config); return tempChart = new Chart(ctx, config);

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 23 KiB

View File

@ -2,13 +2,34 @@ version: "3.4"
services: services:
frontend: frontend:
image: registry.jacknet.io/51m0n/environment-frontend:latest image: registry.jacknet.io/51m0n/environment-frontend:latest
depends_on:
- database
environment:
- ASPNETCORE_oidc_region=openid-connect
- ASPNETCORE_oidc_clientid=51m0n-temperature
- ASPNETCORE_oidc_clientsecret=
- ASPNETCORE_mongodb_uri=mongodb://database:27017/
database: database:
image: mongodb:latest image: mongo:latest
volumes:
- "db-data:/data/db"
apiserver: apiserver:
image: registry.jacknet.io/51m0n/environment-api:latest image: registry.jacknet.io/51m0n/environment-api:latest
environment:
- GIN_DB_PATH=mongodb://database:27017/
depends_on:
- database
proxy: proxy:
image: nginx:latest image: nginx:latest
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
ports:
- "9030:9000"
depends_on:
- apiserver
- frontend
volumes:
db-data:

79
env_page_nginx.conf Normal file
View File

@ -0,0 +1,79 @@
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
# include /etc/nginx/conf.d/*.conf;
server {
listen 9000;
listen [::]:9000;
server_name localhost;
# To allow special characters in headers
ignore_invalid_headers off;
# Allow any size file to be uploaded.
# Set to a value such as 1000m; to restrict file size to a specific value
client_max_body_size 1m;
# To disable buffering
proxy_buffering off;
location /api/ {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_connect_timeout 300;
# Default is HTTP/1, keepalive is only enabled in HTTP/1.1
proxy_http_version 1.1;
proxy_set_header Connection "";
chunked_transfer_encoding off;
proxy_pass http://apiserver:8080/;
}
location / {
# Do preserve this
proxy_set_header Host $http_host;
# again dont overwrite this
#proxy_set_header X-Real-IP $remote_addr;
# this just seems to append another ip ie <host>, <proxy>
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# Preserve the scheme as https if behind another proxy
#proxy_set_header X-Forwarded-Proto $scheme;
proxy_connect_timeout 300;
# Default is HTTP/1, keepalive is only enabled in HTTP/1.1
proxy_http_version 1.1;
proxy_set_header Connection "";
chunked_transfer_encoding off;
proxy_pass http://frontend;
}
}
}