mirror of
https://github.com/lumapu/ahoy.git
synced 2025-06-02 18:51:38 +02:00
0.8.77
* merge PR: BugFix: ACK #1414 * fix suspicious if condition #1416 * prepared API token for access, not functional #1415
This commit is contained in:
parent
d4a4f9cfb6
commit
15349520d2
9 changed files with 98 additions and 23 deletions
|
@ -1,5 +1,10 @@
|
||||||
# Development Changes
|
# Development Changes
|
||||||
|
|
||||||
|
## 0.8.77 - 2024-02-08
|
||||||
|
* merge PR: BugFix: ACK #1414
|
||||||
|
* fix suspicious if condition #1416
|
||||||
|
* prepared API token for access, not functional #1415
|
||||||
|
|
||||||
## 0.8.76 - 2024-02-07
|
## 0.8.76 - 2024-02-07
|
||||||
* revert changes from yesterday regarding snprintf and its size #1410, #1411
|
* revert changes from yesterday regarding snprintf and its size #1410, #1411
|
||||||
* reduced cppcheck linter warnings significantly
|
* reduced cppcheck linter warnings significantly
|
||||||
|
|
|
@ -239,7 +239,7 @@ void app::updateNtp(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((mSunrise == 0) && (mConfig->sun.lat) && (mConfig->sun.lon)) {
|
if ((0 == mSunrise) && (0.0 != mConfig->sun.lat) && (0.0 != mConfig->sun.lon)) {
|
||||||
mCalculatedTimezoneOffset = (int8_t)((mConfig->sun.lon >= 0 ? mConfig->sun.lon + 7.5 : mConfig->sun.lon - 7.5) / 15) * 3600;
|
mCalculatedTimezoneOffset = (int8_t)((mConfig->sun.lon >= 0 ? mConfig->sun.lon + 7.5 : mConfig->sun.lon - 7.5) / 15) * 3600;
|
||||||
tickCalcSunrise();
|
tickCalcSunrise();
|
||||||
}
|
}
|
||||||
|
|
|
@ -251,8 +251,8 @@ class app : public IApp, public ah::Scheduler {
|
||||||
mProtection->lock();
|
mProtection->lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
void unlock(const char *clientIp) override {
|
char *unlock(const char *clientIp) override {
|
||||||
mProtection->unlock(clientIp);
|
return mProtection->unlock(clientIp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void resetLockTimeout(void) override {
|
void resetLockTimeout(void) override {
|
||||||
|
@ -267,6 +267,10 @@ class app : public IApp, public ah::Scheduler {
|
||||||
return mProtection->isProtected(clientIp);
|
return mProtection->isProtected(clientIp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isProtected(const char *clientIp, const char *token) const override {
|
||||||
|
return mProtection->isProtected(clientIp, token);
|
||||||
|
}
|
||||||
|
|
||||||
bool getNrfEnabled(void) override {
|
bool getNrfEnabled(void) override {
|
||||||
return mConfig->nrf.enabled;
|
return mConfig->nrf.enabled;
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,10 +62,11 @@ class IApp {
|
||||||
virtual uint32_t getMqttTxCnt() = 0;
|
virtual uint32_t getMqttTxCnt() = 0;
|
||||||
|
|
||||||
virtual void lock(void) = 0;
|
virtual void lock(void) = 0;
|
||||||
virtual void unlock(const char *clientIp) = 0;
|
virtual char *unlock(const char *clientIp) = 0;
|
||||||
virtual void resetLockTimeout(void) = 0;
|
virtual void resetLockTimeout(void) = 0;
|
||||||
virtual bool isProtected(void) const = 0;
|
virtual bool isProtected(void) const = 0;
|
||||||
virtual bool isProtected(const char *clientIp) const = 0;
|
virtual bool isProtected(const char *clientIp) const = 0;
|
||||||
|
virtual bool isProtected(const char *clientIp, const char *token) const = 0;
|
||||||
|
|
||||||
virtual uint16_t getHistoryValue(uint8_t type, uint16_t i) = 0;
|
virtual uint16_t getHistoryValue(uint8_t type, uint16_t i) = 0;
|
||||||
virtual uint16_t getHistoryMaxDay() = 0;
|
virtual uint16_t getHistoryMaxDay() = 0;
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
//-------------------------------------
|
//-------------------------------------
|
||||||
#define VERSION_MAJOR 0
|
#define VERSION_MAJOR 0
|
||||||
#define VERSION_MINOR 8
|
#define VERSION_MINOR 8
|
||||||
#define VERSION_PATCH 76
|
#define VERSION_PATCH 77
|
||||||
|
|
||||||
//-------------------------------------
|
//-------------------------------------
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
|
@ -19,6 +19,7 @@ class Protection {
|
||||||
mPwd = pwd;
|
mPwd = pwd;
|
||||||
mLogoutTimeout = 0;
|
mLogoutTimeout = 0;
|
||||||
mLoginIp.fill(0);
|
mLoginIp.fill(0);
|
||||||
|
mToken.fill(0);
|
||||||
|
|
||||||
// no password set - unlock
|
// no password set - unlock
|
||||||
if(pwd[0] == '\0')
|
if(pwd[0] == '\0')
|
||||||
|
@ -50,20 +51,34 @@ class Protection {
|
||||||
mLoginIp.fill(0);
|
mLoginIp.fill(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void unlock(const char *clientIp) {
|
char *unlock(const char *clientIp) {
|
||||||
mLogoutTimeout = LOGOUT_TIMEOUT;
|
mLogoutTimeout = LOGOUT_TIMEOUT;
|
||||||
mProtected = false;
|
mProtected = false;
|
||||||
ah::ip2Arr(static_cast<uint8_t*>(mLoginIp.data()), clientIp);
|
ah::ip2Arr(static_cast<uint8_t*>(mLoginIp.data()), clientIp);
|
||||||
|
genToken();
|
||||||
|
|
||||||
|
return reinterpret_cast<char*>(mToken.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
void resetLockTimeout(void) {
|
void resetLockTimeout(void) {
|
||||||
mLogoutTimeout = LOGOUT_TIMEOUT;
|
if(0 != mLogoutTimeout)
|
||||||
|
mLogoutTimeout = LOGOUT_TIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isProtected(void) const {
|
bool isProtected(void) const {
|
||||||
return mProtected;
|
return mProtected;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isProtected(const char *clientIp, const char *token) const {
|
||||||
|
if(isProtected(clientIp))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if(0 == mToken[0]) // token is zero
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return (0 != strncmp(token, mToken.data(), 16));
|
||||||
|
}
|
||||||
|
|
||||||
bool isProtected(const char *clientIp) const {
|
bool isProtected(const char *clientIp) const {
|
||||||
if(mProtected)
|
if(mProtected)
|
||||||
return true;
|
return true;
|
||||||
|
@ -81,14 +96,27 @@ class Protection {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void genToken() {
|
||||||
|
mToken.fill(0);
|
||||||
|
for(uint8_t i = 0; i < 16; i++) {
|
||||||
|
mToken[i] = random(1, 35);
|
||||||
|
if(mToken[i] < 10)
|
||||||
|
mToken[i] += 0x30; // convert to ascii number 1-9 (zero isn't allowed)
|
||||||
|
else
|
||||||
|
mToken[i] += 0x37; // convert to ascii upper case character
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static Protection *mInstance;
|
static Protection *mInstance;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const char *mPwd;
|
const char *mPwd;
|
||||||
bool mProtected = true;
|
bool mProtected = true;
|
||||||
uint16_t mLogoutTimeout = LOGOUT_TIMEOUT;
|
uint16_t mLogoutTimeout = 0;
|
||||||
std::array<uint8_t, 4> mLoginIp;
|
std::array<uint8_t, 4> mLoginIp;
|
||||||
|
std::array<char, 17> mToken;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /*__PROTECTION_H__*/
|
#endif /*__PROTECTION_H__*/
|
||||||
|
|
|
@ -70,7 +70,7 @@ class RestApi {
|
||||||
if(obj[F("path")] == "ctrl")
|
if(obj[F("path")] == "ctrl")
|
||||||
setCtrl(obj, dummy, "*");
|
setCtrl(obj, dummy, "*");
|
||||||
else if(obj[F("path")] == "setup")
|
else if(obj[F("path")] == "setup")
|
||||||
setSetup(obj, dummy);
|
setSetup(obj, dummy, "*");
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -169,7 +169,7 @@ class RestApi {
|
||||||
if(path == "ctrl")
|
if(path == "ctrl")
|
||||||
root[F("success")] = setCtrl(obj, root, request->client()->remoteIP().toString().c_str());
|
root[F("success")] = setCtrl(obj, root, request->client()->remoteIP().toString().c_str());
|
||||||
else if(path == "setup")
|
else if(path == "setup")
|
||||||
root[F("success")] = setSetup(obj, root);
|
root[F("success")] = setSetup(obj, root, request->client()->remoteIP().toString().c_str());
|
||||||
else {
|
else {
|
||||||
root[F("success")] = false;
|
root[F("success")] = false;
|
||||||
root[F("error")] = F(PATH_NOT_FOUND) + path;
|
root[F("error")] = F(PATH_NOT_FOUND) + path;
|
||||||
|
@ -831,6 +831,36 @@ class RestApi {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool setCtrl(JsonObject jsonIn, JsonObject jsonOut, const char *clientIP) {
|
bool setCtrl(JsonObject jsonIn, JsonObject jsonOut, const char *clientIP) {
|
||||||
|
if(F("auth") == jsonIn[F("cmd")]) {
|
||||||
|
if(String(jsonIn["val"]) == String(mConfig->sys.adminPwd))
|
||||||
|
jsonOut["token"] = mApp->unlock(clientIP);
|
||||||
|
else {
|
||||||
|
jsonOut[F("error")] = F(AUTH_ERROR);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*if(mConfig->sys.adminPwd[0] != '\0') { // check if admin password is set
|
||||||
|
if(strncmp("*", clientIP, 1) != 0) { // no call from MqTT
|
||||||
|
const char* token = jsonIn["token"];
|
||||||
|
if(mApp->isProtected(clientIP, token)) {
|
||||||
|
jsonOut[F("error")] = F(IS_PROTECTED);
|
||||||
|
jsonOut[F("bla")] = String(token);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
if(mConfig->sys.adminPwd[0] != '\0') { // check if admin password is set
|
||||||
|
if(strncmp("*", clientIP, 1) != 0) { // no call from MqTT
|
||||||
|
if(mApp->isProtected(clientIP)) {
|
||||||
|
jsonOut[F("error")] = F(IS_PROTECTED);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Inverter<> *iv = mSys->getInverterByPos(jsonIn[F("id")]);
|
Inverter<> *iv = mSys->getInverterByPos(jsonIn[F("id")]);
|
||||||
bool accepted = true;
|
bool accepted = true;
|
||||||
if(NULL == iv) {
|
if(NULL == iv) {
|
||||||
|
@ -839,15 +869,6 @@ class RestApi {
|
||||||
}
|
}
|
||||||
jsonOut[F("id")] = jsonIn[F("id")];
|
jsonOut[F("id")] = jsonIn[F("id")];
|
||||||
|
|
||||||
if(mConfig->sys.adminPwd[0] != '\0') {
|
|
||||||
if(strncmp("*", clientIP, 1) != 0) { // no call from API (MqTT)
|
|
||||||
if(mApp->isProtected(clientIP)) {
|
|
||||||
jsonOut[F("error")] = F(INV_IS_PROTECTED);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(F("power") == jsonIn[F("cmd")])
|
if(F("power") == jsonIn[F("cmd")])
|
||||||
accepted = iv->setDevControlRequest((jsonIn[F("val")] == 1) ? TurnOn : TurnOff);
|
accepted = iv->setDevControlRequest((jsonIn[F("val")] == 1) ? TurnOn : TurnOff);
|
||||||
else if(F("restart") == jsonIn[F("cmd")])
|
else if(F("restart") == jsonIn[F("cmd")])
|
||||||
|
@ -882,7 +903,17 @@ class RestApi {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool setSetup(JsonObject jsonIn, JsonObject jsonOut) {
|
bool setSetup(JsonObject jsonIn, JsonObject jsonOut, const char *clientIP) {
|
||||||
|
/*if(mConfig->sys.adminPwd[0] != '\0') { // check if admin password is set
|
||||||
|
if(strncmp("*", clientIP, 1) != 0) { // no call from MqTT
|
||||||
|
const char* token = jsonIn["token"];
|
||||||
|
if(mApp->isProtected(clientIP, token)) {
|
||||||
|
jsonOut[F("error")] = F(IS_PROTECTED);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
#if !defined(ETHERNET)
|
#if !defined(ETHERNET)
|
||||||
if(F("scan_wifi") == jsonIn[F("cmd")])
|
if(F("scan_wifi") == jsonIn[F("cmd")])
|
||||||
mApp->scanAvailNetworks();
|
mApp->scanAvailNetworks();
|
||||||
|
|
|
@ -30,6 +30,12 @@
|
||||||
#define INV_INDEX_INVALID "inverter index invalid: "
|
#define INV_INDEX_INVALID "inverter index invalid: "
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef LANG_DE
|
||||||
|
#define AUTH_ERROR "Authentifizierungsfehler"
|
||||||
|
#else /*LANG_EN*/
|
||||||
|
#define AUTH_ERROR "authentication error"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef LANG_DE
|
#ifdef LANG_DE
|
||||||
#define UNKNOWN_CMD "unbekanntes Kommando: '"
|
#define UNKNOWN_CMD "unbekanntes Kommando: '"
|
||||||
#else /*LANG_EN*/
|
#else /*LANG_EN*/
|
||||||
|
@ -37,9 +43,9 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef LANG_DE
|
#ifdef LANG_DE
|
||||||
#define INV_IS_PROTECTED "nicht angemeldet, Kommando nicht möglich!"
|
#define IS_PROTECTED "nicht angemeldet, Kommando nicht möglich!"
|
||||||
#else /*LANG_EN*/
|
#else /*LANG_EN*/
|
||||||
#define INV_IS_PROTECTED "not logged in, command not possible!"
|
#define IS_PROTECTED "not logged in, command not possible!"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef LANG_DE
|
#ifdef LANG_DE
|
||||||
|
|
|
@ -782,7 +782,7 @@ class Web {
|
||||||
// report value
|
// report value
|
||||||
if (0 == channel) {
|
if (0 == channel) {
|
||||||
// Report a _total value if also channel values were reported. Otherwise report without _total
|
// Report a _total value if also channel values were reported. Otherwise report without _total
|
||||||
char total[7];
|
char total[7] = {0};
|
||||||
if (metricDeclared) {
|
if (metricDeclared) {
|
||||||
// A declaration and value for channels have been delivered. So declare and deliver a _total metric
|
// A declaration and value for channels have been delivered. So declare and deliver a _total metric
|
||||||
snprintf(total, sizeof(total), "_total");
|
snprintf(total, sizeof(total), "_total");
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue