Add AEAD
This commit is contained in:
parent
1b4c4add09
commit
a6f0f8c72a
|
@ -5,4 +5,5 @@ go 1.15
|
|||
require (
|
||||
github.com/gin-gonic/gin v1.7.4
|
||||
go.mongodb.org/mongo-driver v1.7.2
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9
|
||||
)
|
||||
|
|
|
@ -19,6 +19,10 @@ func main() {
|
|||
func initializeRoutes(r *gin.Engine) {
|
||||
r.POST("/data", src.CreateData)
|
||||
r.PUT("/data/:id", src.CreateEnvironmentData)
|
||||
r.Use(src.AEADHandler)
|
||||
{
|
||||
r.PUT("/data/authed/:id", src.CreateEnvironmentData)
|
||||
}
|
||||
}
|
||||
|
||||
func getPort() string {
|
||||
|
|
|
@ -2,15 +2,22 @@ package src
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"encoding/base64"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
"go.mongodb.org/mongo-driver/mongo/readpref"
|
||||
"golang.org/x/crypto/blake2s"
|
||||
)
|
||||
|
||||
const uri = "mongodb://192.168.0.159:27017"
|
||||
const salt = "ENVIRONMENT"
|
||||
|
||||
var dbCollection *mongo.Collection
|
||||
var dbDevices *mongo.Collection
|
||||
var mongoClient *mongo.Client
|
||||
|
||||
func DbConnect() {
|
||||
|
@ -23,8 +30,38 @@ func DbConnect() {
|
|||
if err := mongoClient.Ping(context.TODO(), readpref.Primary()); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
db := mongoClient.Database("Environment")
|
||||
dbCollection = db.Collection("Main")
|
||||
dbDevices = db.Collection("Devices")
|
||||
}
|
||||
|
||||
dbCollection = mongoClient.Database("Environment").Collection("Main")
|
||||
func GetDeviceKey(api uint64) ([]byte, error) {
|
||||
apiSigned := int64(api)
|
||||
filter := bson.D{{"ApiID", apiSigned}}
|
||||
var result bson.M
|
||||
err := dbDevices.FindOne(context.TODO(), filter).Decode(&result)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
key, err := DeriveKey(result["Passcode"].(string))
|
||||
fmt.Printf(base64.StdEncoding.EncodeToString(key))
|
||||
// We should cache this!
|
||||
return key, 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
|
||||
}
|
||||
|
||||
func DbDisconnect() {
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
package src
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"golang.org/x/crypto/chacha20poly1305"
|
||||
)
|
||||
|
||||
const ivSize = 12
|
||||
const DecryptedData = "DecryptedData"
|
||||
|
||||
func AEADHandler(c *gin.Context) {
|
||||
// get id
|
||||
uintID, err := strconv.ParseUint(c.Param("id"), 10, 64)
|
||||
if err != nil {
|
||||
fmt.Printf("ERR %s", err.Error())
|
||||
c.AbortWithStatus(http.StatusUnauthorized)
|
||||
} else {
|
||||
// get key
|
||||
passcode, err := GetDeviceKey(uintID)
|
||||
if err != nil {
|
||||
fmt.Printf("ERR %s", err.Error())
|
||||
c.AbortWithStatus(http.StatusNotFound)
|
||||
} else {
|
||||
// get content
|
||||
data, err := c.GetRawData()
|
||||
if err != nil {
|
||||
fmt.Printf("ERR %s", err.Error())
|
||||
c.AbortWithStatus(http.StatusBadRequest)
|
||||
} else {
|
||||
// decrypt
|
||||
iv, ciphertext := data[:ivSize], data[ivSize:]
|
||||
aead, err := chacha20poly1305.New(passcode)
|
||||
if err != nil {
|
||||
fmt.Printf("ERR %s", err.Error())
|
||||
c.AbortWithStatus(http.StatusInternalServerError)
|
||||
} else {
|
||||
fmt.Printf("iv: %s cypher: %s", base64.StdEncoding.EncodeToString(iv), base64.StdEncoding.EncodeToString(ciphertext))
|
||||
plaintext, err := aead.Open(nil, iv, ciphertext, nil)
|
||||
|
||||
if err != nil {
|
||||
fmt.Printf("ERR %s", err.Error())
|
||||
c.AbortWithStatus(http.StatusBadRequest)
|
||||
} else {
|
||||
c.Request.Body = ioutil.NopCloser(bytes.NewBuffer(plaintext))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -3,6 +3,7 @@
|
|||
#include <Ticker.h>
|
||||
#include <U8g2lib.h>
|
||||
#include <ESP8266HTTPClient.h>
|
||||
#include "byte_buffer.h"
|
||||
|
||||
//scl D1
|
||||
//sda D2
|
||||
|
@ -26,9 +27,16 @@ float humidity = 0;
|
|||
|
||||
#define TEMP "Temperature: "
|
||||
#define HUMID "Humidity: "
|
||||
|
||||
#define DERIVATION_HASH_SIZE 32
|
||||
static constexpr const char *DERIVATION_SALT = "ENVIRONMENT";
|
||||
|
||||
void UpdateEnvironment();
|
||||
|
||||
void PostEnvironment();
|
||||
|
||||
void InitializeWifi();
|
||||
|
||||
utils::byte_buffer Encrypt(std::string data);
|
||||
|
||||
void DeriveKey();
|
|
@ -0,0 +1,19 @@
|
|||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
namespace Environment
|
||||
{
|
||||
class Settings
|
||||
{
|
||||
private:
|
||||
/* data */
|
||||
public:
|
||||
uint64_t apiID;
|
||||
|
||||
std::string endpoint;
|
||||
|
||||
std::string passcode;
|
||||
};
|
||||
|
||||
}
|
|
@ -26,7 +26,7 @@ class setup_server
|
|||
|
||||
bool serverConnection;
|
||||
|
||||
uint8_t connect_to_ap(const std::string ssid, const std::string password);
|
||||
uint8_t connect_to_ap(const std::string &ssid, const std::string &password);
|
||||
|
||||
void root_callback();
|
||||
|
||||
|
|
|
@ -0,0 +1,200 @@
|
|||
#include <byte_buffer.h>
|
||||
|
||||
#include <cstdlib>
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <osapi.h>
|
||||
#include <libb64/cdecode.h>
|
||||
#include <libb64/cencode.h>
|
||||
|
||||
namespace utils
|
||||
{
|
||||
byte_buffer::byte_buffer(uint_fast16_t length)
|
||||
: _length(length)
|
||||
{
|
||||
// +1 to allow this to be safely printed as a char
|
||||
_buffer = reinterpret_cast<unsigned char *>(std::calloc(length + 1, sizeof(unsigned char)));
|
||||
}
|
||||
|
||||
byte_buffer::~byte_buffer()
|
||||
{
|
||||
clear_buffer();
|
||||
std::free(_buffer);
|
||||
}
|
||||
|
||||
const bool byte_buffer::is_valid()
|
||||
{
|
||||
return _buffer != nullptr;
|
||||
}
|
||||
|
||||
unsigned char *byte_buffer::get_ptr()
|
||||
{
|
||||
if (is_valid())
|
||||
{
|
||||
return _buffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Get the length of the buffer.
|
||||
//
|
||||
// Returns: The length of the buffer, or 0 if the buffer is invalid.
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
const uint_fast16_t byte_buffer::get_length()
|
||||
{
|
||||
if (is_valid())
|
||||
{
|
||||
return _length;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Get a pointer to a location in the buffer, length is updated to show the length
|
||||
// available in that buffer
|
||||
//
|
||||
// index: The location to get a pointer to.
|
||||
// length: The length of the data you expect to access from this pointer.
|
||||
//
|
||||
// Returns: A ptr to the buffer, or nullptr if reading that much data would cause
|
||||
// an overflow
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
unsigned char *byte_buffer::get_ptr(const uint_fast16_t index, uint_fast16_t &length)
|
||||
{
|
||||
unsigned char *ret = nullptr;
|
||||
|
||||
if (is_valid() && _length > index)
|
||||
{
|
||||
length = _length - index;
|
||||
ret = &_buffer[index];
|
||||
}
|
||||
else
|
||||
{
|
||||
length = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Copy data into this buffer. The index value is updated to the index of the next point in the buffer
|
||||
const bool byte_buffer::copy_from(const void *const sourceBuffer, uint_fast16_t &index, const uint_fast16_t &length)
|
||||
{
|
||||
auto ret = false;
|
||||
if (is_valid() &&
|
||||
sourceBuffer != nullptr &&
|
||||
(index + length) <= _length)
|
||||
{
|
||||
std::memcpy(_buffer + index, sourceBuffer, length);
|
||||
index += length;
|
||||
ret = true;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Copy data out of this buffer. The index value is updated to the index of the next point in the buffer
|
||||
const bool byte_buffer::copy_to(void *destinationBuffer, uint_fast16_t &index, const uint_fast16_t &length)
|
||||
{
|
||||
auto ret = false;
|
||||
if (is_valid() &&
|
||||
destinationBuffer != nullptr &&
|
||||
(index + length) < _length)
|
||||
{
|
||||
std::memcpy(destinationBuffer, _buffer + index, length);
|
||||
index += length;
|
||||
ret = true;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
const bool byte_buffer::clone(byte_buffer &bufferToClone)
|
||||
{
|
||||
auto ret = false;
|
||||
if (is_valid() &&
|
||||
bufferToClone.is_valid() &&
|
||||
bufferToClone.get_length() <= _length)
|
||||
{
|
||||
std::memcpy(bufferToClone.get_ptr(), 0, bufferToClone.get_length());
|
||||
ret = true;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
const void byte_buffer::clear_buffer()
|
||||
{
|
||||
if (is_valid())
|
||||
{
|
||||
std::fill(_buffer, _buffer + _length, 0);
|
||||
}
|
||||
}
|
||||
|
||||
const void byte_buffer::fill_random()
|
||||
{
|
||||
if (is_valid())
|
||||
{
|
||||
os_get_random(_buffer, _length);
|
||||
}
|
||||
}
|
||||
|
||||
// Return the size of the data stored
|
||||
const uint_fast16_t byte_buffer::load_base64(std::string base64Data)
|
||||
{
|
||||
auto read = 0u;
|
||||
|
||||
if (is_valid() && _length >= base64_decode_expected_len(base64Data.length()))
|
||||
{
|
||||
base64_decodestate state;
|
||||
base64_init_decodestate(&state);
|
||||
read = base64_decode_block(base64Data.c_str(), base64Data.length(), reinterpret_cast<char *>(_buffer), &state);
|
||||
}
|
||||
|
||||
return read;
|
||||
}
|
||||
|
||||
//// Get a base64 encoded string of this buffer.
|
||||
const std::string byte_buffer::get_base64()
|
||||
{
|
||||
if (!is_valid())
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
auto b64String = std::string("");
|
||||
auto size = base64_encode_expected_len_nonewlines(_length) + 1;
|
||||
auto buffer = reinterpret_cast<char *>(std::calloc(size, 1));
|
||||
if (buffer != nullptr)
|
||||
{
|
||||
|
||||
base64_encodestate state;
|
||||
base64_init_encodestate_nonewlines(&state);
|
||||
|
||||
auto encoded = base64_encode_block(reinterpret_cast<const char *>(_buffer), _length, buffer, &state);
|
||||
encoded = base64_encode_blockend(buffer + encoded, &state);
|
||||
|
||||
b64String = std::string(buffer);
|
||||
std::free(buffer);
|
||||
}
|
||||
|
||||
return b64String;
|
||||
}
|
||||
|
||||
const std::string byte_buffer::to_string()
|
||||
{
|
||||
if (!is_valid())
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
// Make sure that extra byte really is null!
|
||||
_buffer[_length] = '\0';
|
||||
return std::string(reinterpret_cast<char *>(_buffer));
|
||||
}
|
||||
} // namespace Control_System
|
|
@ -0,0 +1,38 @@
|
|||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
|
||||
namespace utils
|
||||
{
|
||||
class byte_buffer
|
||||
{
|
||||
|
||||
public:
|
||||
byte_buffer(uint_fast16_t length);
|
||||
~byte_buffer();
|
||||
|
||||
const bool is_valid();
|
||||
|
||||
unsigned char *get_ptr();
|
||||
const uint_fast16_t get_length();
|
||||
|
||||
unsigned char *get_ptr(const uint_fast16_t index, uint_fast16_t &length);
|
||||
|
||||
const bool copy_to(void *destinationBuffer, uint_fast16_t &index, const uint_fast16_t &length);
|
||||
const bool copy_from(const void *const sourceBuffer, uint_fast16_t &index, const uint_fast16_t &length);
|
||||
|
||||
const bool clone(byte_buffer &bufferToClone);
|
||||
|
||||
const void clear_buffer();
|
||||
const void fill_random();
|
||||
|
||||
const uint_fast16_t load_base64(std::string base64Data);
|
||||
const std::string get_base64();
|
||||
const std::string to_string();
|
||||
|
||||
private:
|
||||
unsigned char *_buffer;
|
||||
const uint_fast16_t _length;
|
||||
};
|
||||
|
||||
} // namespace Control_System
|
|
@ -15,3 +15,4 @@ framework = arduino
|
|||
lib_deps =
|
||||
olikraus/U8g2@^2.28.8
|
||||
finitespace/BME280@^3.0.0
|
||||
rweather/Crypto@^0.2.0
|
||||
|
|
|
@ -4,37 +4,58 @@
|
|||
#include "setup_server.h"
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <string>
|
||||
#include "settings.h"
|
||||
|
||||
void setup()
|
||||
#include <ChaChaPoly.h>
|
||||
#include <BLAKE2s.h>
|
||||
|
||||
Environment::Settings settings;
|
||||
utils::byte_buffer passcode(DERIVATION_HASH_SIZE);
|
||||
|
||||
void setup()
|
||||
{
|
||||
settings.apiID = 11085093266951290551U;
|
||||
settings.endpoint = std::string("http://192.168.64.244:8080/data/authed/");
|
||||
settings.passcode = std::string("password");
|
||||
|
||||
Serial.begin(9600);
|
||||
Serial.println("\nSTART");
|
||||
Serial.print("Last Shutdown: ");
|
||||
Serial.println(ESP.getResetReason());
|
||||
|
||||
Serial.print("Derive Key: ");
|
||||
DeriveKey();
|
||||
// put your setup code here, to run once:
|
||||
screen.begin();
|
||||
Wire.begin();
|
||||
bme.begin();
|
||||
environmentUpdate.attach_scheduled(1, UpdateEnvironment);
|
||||
environmentPost.attach_scheduled(60, PostEnvironment);
|
||||
screen.firstPage();
|
||||
do
|
||||
{
|
||||
screen.setFont(FONT);
|
||||
screen.drawStr(2, LINE_1, "Connecting...");
|
||||
} while (screen.nextPage());
|
||||
InitializeWifi();
|
||||
}
|
||||
|
||||
void loop()
|
||||
void loop()
|
||||
{
|
||||
// put your main code here, to run repeatedly:
|
||||
screen.firstPage();
|
||||
do{
|
||||
do
|
||||
{
|
||||
screen.setFont(FONT);
|
||||
screen.drawStr(2, LINE_1, "Hello World!");
|
||||
screen.drawStr(2, LINE_2, "Hi Butlersaurus!");
|
||||
}while(screen.nextPage());
|
||||
} while (screen.nextPage());
|
||||
|
||||
delay(1000);
|
||||
|
||||
screen.firstPage();
|
||||
do{
|
||||
do
|
||||
{
|
||||
screen.setFont(FONT);
|
||||
screen.drawStr(2, LINE_1, TEMP);
|
||||
screen.setCursor(screen.getStrWidth(TEMP), LINE_1);
|
||||
|
@ -42,35 +63,68 @@ void loop()
|
|||
screen.drawStr(2, LINE_2, HUMID);
|
||||
screen.setCursor(screen.getStrWidth(HUMID), LINE_2);
|
||||
screen.print(humidity);
|
||||
}while(screen.nextPage());
|
||||
} while (screen.nextPage());
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
void UpdateEnvironment()
|
||||
{
|
||||
bme.read(pressure, temp, humidity,tempUnit, presUnit);
|
||||
bme.read(pressure, temp, humidity, tempUnit, presUnit);
|
||||
}
|
||||
|
||||
void PostEnvironment()
|
||||
{
|
||||
utils::debug_print("Post");
|
||||
requests.begin(client, "http://192.168.64.239/api/environment");
|
||||
//requests.begin(client, "http://192.168.64.239/api/environment");
|
||||
auto endpoint = std::string(settings.endpoint);
|
||||
endpoint.append(std::to_string(settings.apiID));
|
||||
requests.begin(client, endpoint.c_str());
|
||||
requests.addHeader("Content-Type", "application/json");
|
||||
char dataBuffer[128];
|
||||
char formatString[] = "{\"h\":\"%f\",\"t\":\"%f\"}";
|
||||
char dataBuffer[128] = {0};
|
||||
char formatString[] = "{\"h\":%f,\"t\":%f}";
|
||||
snprintf(&dataBuffer[0], 128, &formatString[0], humidity, temp);
|
||||
auto code = requests.POST(dataBuffer);
|
||||
if (code > 0){
|
||||
utils::debug_print(code);
|
||||
}else{
|
||||
utils::debug_print(requests.errorToString(code));
|
||||
auto data = Encrypt(std::string(dataBuffer));
|
||||
auto code = requests.PUT(data.get_ptr(), data.get_length());
|
||||
if (code > 0)
|
||||
{
|
||||
utils::debug_print(code);
|
||||
}
|
||||
else
|
||||
{
|
||||
utils::debug_print(requests.errorToString(code));
|
||||
}
|
||||
requests.end();
|
||||
utils::debug_print("Posted");
|
||||
}
|
||||
|
||||
utils::byte_buffer Encrypt(std::string data)
|
||||
{
|
||||
// struct used by go, with basically no docs :|
|
||||
// iv (12) | cipher (x) | tag(16)
|
||||
const uint_fast16_t ivSize = 12;
|
||||
auto size = ivSize + data.length() + 16;
|
||||
auto dataOut = utils::byte_buffer(size);
|
||||
// for the iv
|
||||
dataOut.fill_random();
|
||||
// first 12 bytes
|
||||
auto cipher = ChaChaPoly();
|
||||
|
||||
cipher.setKey(passcode.get_ptr(), passcode.get_length());
|
||||
cipher.setIV(dataOut.get_ptr(), ivSize);
|
||||
|
||||
uint_fast16_t buffLen = 0;
|
||||
auto encryptBuffer = dataOut.get_ptr(ivSize, buffLen);
|
||||
cipher.encrypt(encryptBuffer, (const uint8_t *)data.c_str(), data.length());
|
||||
|
||||
auto tagBuffer = dataOut.get_ptr(ivSize + data.length(), buffLen);
|
||||
cipher.computeTag(tagBuffer, buffLen);
|
||||
|
||||
return dataOut;
|
||||
}
|
||||
|
||||
void InitializeWifi()
|
||||
{
|
||||
delay(1);
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFi.begin();
|
||||
auto ret = WiFi.waitForConnectResult();
|
||||
|
@ -83,6 +137,16 @@ void InitializeWifi()
|
|||
std::string password = std::string();
|
||||
setup.get_connection(ssid, password);
|
||||
}
|
||||
WiFi.setAutoConnect(true);
|
||||
|
||||
utils::debug_print("Wifi Connected: " + WiFi.SSID());
|
||||
}
|
||||
|
||||
void DeriveKey()
|
||||
{
|
||||
BLAKE2s hash = BLAKE2s();
|
||||
hash.reset();
|
||||
hash.update(DERIVATION_SALT, strlen(DERIVATION_SALT));
|
||||
hash.update(settings.passcode.c_str(), settings.passcode.length());
|
||||
hash.finalize(passcode.get_ptr(), passcode.get_length());
|
||||
utils::debug_print(passcode.get_base64());
|
||||
}
|
|
@ -1,15 +1,15 @@
|
|||
#include <setup_server.h>
|
||||
#include <string>
|
||||
|
||||
#include <html/first_connection_page.h>
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define _DEBUG_PRINT(x) utils::debug_print(x)
|
||||
#define _DEBUG_PRINT(x) utils::debug_print(x)
|
||||
#else
|
||||
#define _DEBUG_PRINT(x)
|
||||
#define _DEBUG_PRINT(x)
|
||||
#endif
|
||||
|
||||
setup_server::setup_server()
|
||||
: server(new ESP8266WebServer(80))
|
||||
setup_server::setup_server()
|
||||
: server(new ESP8266WebServer(80))
|
||||
{
|
||||
server->on("/", [this] { this->root_callback(); });
|
||||
server->on("/submit", HTTP_POST, [this] { this->ap_submission_callback(); });
|
||||
|
@ -53,7 +53,7 @@ setup_server::SetupErrorCodes setup_server::get_connection(const std::string &ss
|
|||
return ret;
|
||||
}
|
||||
|
||||
uint8_t setup_server::connect_to_ap(const std::string ssid, const std::string password)
|
||||
uint8_t setup_server::connect_to_ap(const std::string &ssid, const std::string &password)
|
||||
{
|
||||
_DEBUG_PRINT("Connecting " + ssid + ":" + password);
|
||||
WiFi.begin(ssid.c_str(), password.c_str());
|
||||
|
@ -65,10 +65,11 @@ void setup_server::root_callback()
|
|||
{
|
||||
_DEBUG_PRINT("Request \"/\" from " + server->client().remoteIP().toString());
|
||||
auto pageSize = strlen_P(first_connection_page);
|
||||
auto outBuffer = new char(pageSize);
|
||||
auto outBuffer = new char[pageSize + 1];
|
||||
strncpy_P(outBuffer, first_connection_page, pageSize);
|
||||
outBuffer[pageSize] = '\0';
|
||||
server->send(200, "text/html", outBuffer);
|
||||
delete outBuffer;
|
||||
delete[] outBuffer;
|
||||
}
|
||||
|
||||
void setup_server::ap_submission_callback()
|
||||
|
|
|
@ -5,6 +5,7 @@ using Microsoft.AspNetCore.Mvc;
|
|||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Driver;
|
||||
using System.Security.Claims;
|
||||
|
||||
namespace ManagementPage.Pages
|
||||
{
|
||||
|
@ -44,16 +45,34 @@ namespace ManagementPage.Pages
|
|||
return NotFound();
|
||||
}
|
||||
|
||||
var filter = new BsonDocument("ApiID", deviceId);
|
||||
// get the logged in user
|
||||
var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
|
||||
var filter = new BsonDocument("OpenId", userId);
|
||||
var claims = await _dbClient.AccountsCollection.Find(filter).SingleOrDefaultAsync();
|
||||
|
||||
// No user?
|
||||
if (claims == null)
|
||||
{
|
||||
return Forbid();
|
||||
}
|
||||
|
||||
// Get the device
|
||||
filter = new BsonDocument("ApiID", deviceId);
|
||||
device = await _dbClient.DeviceCollection.Find(filter).FirstOrDefaultAsync();
|
||||
|
||||
FindOptions<EnvironmentData> options = new FindOptions<EnvironmentData>
|
||||
// No device?
|
||||
if (device == null)
|
||||
{
|
||||
Limit = 100,
|
||||
NoCursorTimeout = false
|
||||
};
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
using var cursor = await _dbClient.Collection.FindAsync(filter, options);
|
||||
// Device owned by someone else?
|
||||
if (!claims.Devices.Contains(device._id))
|
||||
{
|
||||
return Forbid();
|
||||
}
|
||||
|
||||
using var cursor = await _dbClient.Collection.Find(filter).SortByDescending(x => x.Time).Limit(100).ToCursorAsync();
|
||||
data.AddRange(await cursor.ToListAsync());
|
||||
foreach (var item in data)
|
||||
{
|
||||
|
@ -61,6 +80,9 @@ namespace ManagementPage.Pages
|
|||
temperature.Add(new DataSet() { x = item.Time, y = item.Temperature });
|
||||
}
|
||||
|
||||
humidity.Reverse();
|
||||
temperature.Reverse();
|
||||
|
||||
return Page();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ namespace ManagementPage.Pages
|
|||
foreach (var item in data)
|
||||
{
|
||||
var filter = new BsonDocument("ApiID", item.ApiID);
|
||||
var envData = await _dbClient.Collection.Find(filter).FirstOrDefaultAsync();
|
||||
var envData = await _dbClient.Collection.Find(filter).SortByDescending(x => x.Time).FirstOrDefaultAsync();
|
||||
envData ??= new EnvironmentData(item.ApiID, 0, 0, DateTime.UtcNow);
|
||||
currentEnvironment.Add(item.ApiID, envData);
|
||||
}
|
||||
|
@ -65,9 +65,15 @@ namespace ManagementPage.Pages
|
|||
}
|
||||
var id = BitConverter.ToInt64(Guid.NewGuid().ToByteArray(),4);
|
||||
var device = new DeviceData(NewDevice.Name, NewDevice.Passcode, id);
|
||||
device._id = ObjectId.GenerateNewId();
|
||||
await _dbClient.DeviceCollection.InsertOneAsync(device);
|
||||
|
||||
return Page();
|
||||
var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
|
||||
var filter = new BsonDocument("OpenId", userId);
|
||||
var update = Builders<UserData>.Update.AddToSet("Devices", device._id);
|
||||
|
||||
await _dbClient.AccountsCollection.UpdateOneAsync(filter, update);
|
||||
return new RedirectToPageResult("/UserHome");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"applicationUrl": "https://localhost:8800;http://+:80",
|
||||
"applicationUrl": "https://environment.51m0n.com;http://+:80",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
|
|
|
@ -8,5 +8,7 @@
|
|||
},
|
||||
"oidc": {
|
||||
"region": "openid-connect",
|
||||
"clientid": "51m0n-temperature",
|
||||
"clientsecret": "577b32ae-d36e-42ec-b6a2-92025dc16619"
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue