mirror of
https://github.com/Telecominfraproject/wlan-cloud-ucentralsec.git
synced 2025-10-30 10:22:22 +00:00
Compare commits
98 Commits
v2.3.0-RC1
...
v2.4.0-RC1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
350df38c3f | ||
|
|
9e79b73e20 | ||
|
|
eb4dfc25f2 | ||
|
|
bedec254c5 | ||
|
|
96a566a2b5 | ||
|
|
ad2eb1711e | ||
|
|
7244bcb455 | ||
|
|
1db5201418 | ||
|
|
1bc635f553 | ||
|
|
257ac42d7c | ||
|
|
acb38e5313 | ||
|
|
7940f0bd85 | ||
|
|
62c06d0bad | ||
|
|
494a199610 | ||
|
|
5307b0b35a | ||
|
|
c58728f38e | ||
|
|
1f09c3b619 | ||
|
|
d9c6388502 | ||
|
|
5e35906aec | ||
|
|
773618ae07 | ||
|
|
cca4441ac7 | ||
|
|
730ca7b292 | ||
|
|
5b4dbb088f | ||
|
|
bc11a19ee4 | ||
|
|
c835e4d0b9 | ||
|
|
f1a2ba90f6 | ||
|
|
5b96ef396f | ||
|
|
c204d34bf4 | ||
|
|
4b982bf64b | ||
|
|
37298cc600 | ||
|
|
03619cc900 | ||
|
|
f4fc6975e1 | ||
|
|
1f1d596c5a | ||
|
|
a5802bf631 | ||
|
|
6471eabc82 | ||
|
|
ab6fbaca11 | ||
|
|
1e8e5c18b2 | ||
|
|
3cf23af068 | ||
|
|
1a0b549731 | ||
|
|
a835d2e571 | ||
|
|
ff7455af24 | ||
|
|
48610bac5d | ||
|
|
7bd5b4d4e6 | ||
|
|
e1a51c2a91 | ||
|
|
cd0222f765 | ||
|
|
12fddd8bc4 | ||
|
|
9095d831db | ||
|
|
4e8f97df9b | ||
|
|
28808eae93 | ||
|
|
6c24a23863 | ||
|
|
5931c91054 | ||
|
|
9d956c13f7 | ||
|
|
ea1adde361 | ||
|
|
eaac1f1625 | ||
|
|
c5f4c067bb | ||
|
|
31a9e4564b | ||
|
|
a9affc29bb | ||
|
|
65fc0a1d10 | ||
|
|
82c01ce438 | ||
|
|
5f900883e8 | ||
|
|
e97b8e64be | ||
|
|
6c90c75708 | ||
|
|
a3d86c7cf9 | ||
|
|
50b6ac9522 | ||
|
|
15b947a34d | ||
|
|
160bd00a99 | ||
|
|
3c7daa537a | ||
|
|
c5bab1d749 | ||
|
|
96c3244be0 | ||
|
|
7e4b515f60 | ||
|
|
a63f80e497 | ||
|
|
2eae6cc73c | ||
|
|
96f215b3c2 | ||
|
|
9551384358 | ||
|
|
b21c5c5e00 | ||
|
|
031d35256c | ||
|
|
5738fa47bb | ||
|
|
fe17650333 | ||
|
|
7636568fb4 | ||
|
|
c0ef77eb53 | ||
|
|
00742a5d0a | ||
|
|
a96f673380 | ||
|
|
53ecdb471e | ||
|
|
f80a0c5007 | ||
|
|
9e7d7ba67d | ||
|
|
b508c0d054 | ||
|
|
79788dab44 | ||
|
|
8dec946c45 | ||
|
|
43ea5ac424 | ||
|
|
328ff158cb | ||
|
|
2b89d843c3 | ||
|
|
45a50483be | ||
|
|
c8ae94a062 | ||
|
|
7b19143d6f | ||
|
|
bc0c889098 | ||
|
|
6f8f81866f | ||
|
|
f213c99816 | ||
|
|
423aca9892 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -18,3 +18,4 @@ _deps
|
|||||||
*.csr
|
*.csr
|
||||||
/cmake-build/
|
/cmake-build/
|
||||||
/smake-build-debug/
|
/smake-build-debug/
|
||||||
|
test_scripts/curl/result.json
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
cmake_minimum_required(VERSION 3.13)
|
cmake_minimum_required(VERSION 3.13)
|
||||||
project(owsec VERSION 2.3.0)
|
project(owsec VERSION 2.4.0)
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
|
||||||
@@ -42,7 +42,7 @@ find_package(Boost REQUIRED system)
|
|||||||
find_package(OpenSSL REQUIRED)
|
find_package(OpenSSL REQUIRED)
|
||||||
find_package(ZLIB REQUIRED)
|
find_package(ZLIB REQUIRED)
|
||||||
find_package(AWSSDK REQUIRED COMPONENTS sns)
|
find_package(AWSSDK REQUIRED COMPONENTS sns)
|
||||||
|
find_package(nlohmann_json REQUIRED)
|
||||||
find_package(CppKafka REQUIRED)
|
find_package(CppKafka REQUIRED)
|
||||||
find_package(PostgreSQL REQUIRED)
|
find_package(PostgreSQL REQUIRED)
|
||||||
find_package(MySQL REQUIRED)
|
find_package(MySQL REQUIRED)
|
||||||
@@ -86,7 +86,11 @@ add_executable( owsec
|
|||||||
src/MFAServer.cpp src/MFAServer.h
|
src/MFAServer.cpp src/MFAServer.h
|
||||||
src/SMS_provider_aws.cpp src/SMS_provider_aws.h
|
src/SMS_provider_aws.cpp src/SMS_provider_aws.h
|
||||||
src/SMS_provider.cpp src/SMS_provider.h
|
src/SMS_provider.cpp src/SMS_provider.h
|
||||||
src/SMS_provider_twilio.cpp src/SMS_provider_twilio.h)
|
src/SMS_provider_twilio.cpp src/SMS_provider_twilio.h
|
||||||
|
src/storage/storage_actionLinks.cpp src/storage/storage_actionLinks.h
|
||||||
|
src/storage/storage_tokens.h
|
||||||
|
src/ActionLinkManager.cpp src/ActionLinkManager.h
|
||||||
|
src/ACLProcessor.h)
|
||||||
|
|
||||||
if(NOT SMALL_BUILD)
|
if(NOT SMALL_BUILD)
|
||||||
target_link_libraries(owsec PUBLIC
|
target_link_libraries(owsec PUBLIC
|
||||||
|
|||||||
17
Dockerfile
17
Dockerfile
@@ -11,6 +11,8 @@ RUN apk add --update --no-cache \
|
|||||||
|
|
||||||
RUN git clone https://github.com/stephb9959/poco /poco
|
RUN git clone https://github.com/stephb9959/poco /poco
|
||||||
RUN git clone https://github.com/stephb9959/cppkafka /cppkafka
|
RUN git clone https://github.com/stephb9959/cppkafka /cppkafka
|
||||||
|
RUN git clone https://github.com/nlohmann/json /json
|
||||||
|
RUN git clone https://github.com/pboettch/json-schema-validator /json-schema-validator
|
||||||
RUN git clone --recurse-submodules https://github.com/aws/aws-sdk-cpp /aws-sdk-cpp
|
RUN git clone --recurse-submodules https://github.com/aws/aws-sdk-cpp /aws-sdk-cpp
|
||||||
|
|
||||||
WORKDIR /aws-sdk-cpp
|
WORKDIR /aws-sdk-cpp
|
||||||
@@ -37,6 +39,20 @@ RUN cmake ..
|
|||||||
RUN cmake --build . --config Release -j8
|
RUN cmake --build . --config Release -j8
|
||||||
RUN cmake --build . --target install
|
RUN cmake --build . --target install
|
||||||
|
|
||||||
|
WORKDIR /json
|
||||||
|
RUN mkdir cmake-build
|
||||||
|
WORKDIR cmake-build
|
||||||
|
RUN cmake ..
|
||||||
|
RUN make
|
||||||
|
RUN make install
|
||||||
|
|
||||||
|
WORKDIR /json-schema-validator
|
||||||
|
RUN mkdir cmake-build
|
||||||
|
WORKDIR cmake-build
|
||||||
|
RUN cmake ..
|
||||||
|
RUN make
|
||||||
|
RUN make install
|
||||||
|
|
||||||
ADD CMakeLists.txt build /owsec/
|
ADD CMakeLists.txt build /owsec/
|
||||||
ADD cmake /owsec/cmake
|
ADD cmake /owsec/cmake
|
||||||
ADD src /owsec/src
|
ADD src /owsec/src
|
||||||
@@ -75,6 +91,7 @@ RUN wget https://raw.githubusercontent.com/Telecominfraproject/wlan-cloud-ucentr
|
|||||||
-O /usr/local/share/ca-certificates/restapi-ca-selfsigned.pem
|
-O /usr/local/share/ca-certificates/restapi-ca-selfsigned.pem
|
||||||
|
|
||||||
COPY readiness_check /readiness_check
|
COPY readiness_check /readiness_check
|
||||||
|
COPY test_scripts/curl/cli /cli
|
||||||
|
|
||||||
EXPOSE 16001 17001 16101
|
EXPOSE 16001 17001 16101
|
||||||
|
|
||||||
|
|||||||
34
README.md
34
README.md
@@ -98,6 +98,40 @@ to get a sample. The default is
|
|||||||
### `authentication.oldpasswords`
|
### `authentication.oldpasswords`
|
||||||
The number of older passwords to keep. Default is 5.
|
The number of older passwords to keep. Default is 5.
|
||||||
|
|
||||||
|
### Changing default password
|
||||||
|
|
||||||
|
On the first startup of the service new user will be created with the default credentials from properties `authentication.default.username` and `authentication.default.password`, but **you will have to change the password** before making any real requests.
|
||||||
|
|
||||||
|
You can this using [owgw-ui](https://github.com/Telecominfraproject/wlan-cloud-ucentralgw-ui/) on first login or using the following script:
|
||||||
|
|
||||||
|
```
|
||||||
|
export OWSEC=openwifi.wlan.local:16001 # endpoint to your owsec RESTAPI endpoint
|
||||||
|
#export FLAGS="-k" # uncomment and add curl flags that you would like to pass for the request (for example '-k' may be used to pass errors with self-signed certificates)
|
||||||
|
export OWSEC_DEFAULT_USERNAME=root@system.com # default username that you've set in property 'authentication.default.username'
|
||||||
|
export OWSEC_DEFAULT_PASSWORD=weLoveWifi # default password __in cleartext__ from property 'authentication.default.password'
|
||||||
|
export OWSEC_NEW_PASSWORD=NewPass123% # new password that must be set for the user (must comply with 'authentication.validation.expression')
|
||||||
|
test_scripts/curl/cli testlogin $OWSEC_DEFAULT_USERNAME $OWSEC_DEFAULT_PASSWORD $OWSEC_NEW_PASSWORD
|
||||||
|
```
|
||||||
|
|
||||||
|
CLI is also included in Docker image if you want to run it this way:
|
||||||
|
|
||||||
|
```
|
||||||
|
export OWSEC=openwifi.wlan.local:16001
|
||||||
|
#export FLAGS="-k"
|
||||||
|
export OWSEC_DEFAULT_USERNAME=root@system.com
|
||||||
|
export OWSEC_DEFAULT_PASSWORD=weLoveWifi
|
||||||
|
export OWSEC_NEW_PASSWORD=NewPass123%
|
||||||
|
docker run --rm -ti \
|
||||||
|
--network=host \
|
||||||
|
--env OWSEC \
|
||||||
|
--env FLAGS \
|
||||||
|
--env OWSEC_DEFAULT_USERNAME \
|
||||||
|
--env OWSEC_DEFAULT_PASSWORD \
|
||||||
|
--env OWSEC_NEW_PASSWORD \
|
||||||
|
tip-tip-wlan-cloud-ucentral.jfrog.io/owsec:main \
|
||||||
|
/cli testlogin $OWSEC_DEFAULT_USERNAME $OWSEC_DEFAULT_PASSWORD $OWSEC_NEW_PASSWORD
|
||||||
|
```
|
||||||
|
|
||||||
### Kafka integration
|
### Kafka integration
|
||||||
This security service uses Kafka to coordinate security with other services that are part of the system. You must have a Kafka service running
|
This security service uses Kafka to coordinate security with other services that are part of the system. You must have a Kafka service running
|
||||||
in order to use this. You can find several examples of Kafka services available with Docker. Here are the values you need to configure.
|
in order to use this. You can find several examples of Kafka services available with Docker. Here are the values you need to configure.
|
||||||
|
|||||||
@@ -24,6 +24,9 @@ spec:
|
|||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
checksum/config: {{ include "owsec.config" . | sha256sum }}
|
checksum/config: {{ include "owsec.config" . | sha256sum }}
|
||||||
|
{{- with .Values.podAnnotations }}
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
labels:
|
labels:
|
||||||
app.kubernetes.io/name: {{ include "owsec.name" . }}
|
app.kubernetes.io/name: {{ include "owsec.name" . }}
|
||||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ fullnameOverride: ""
|
|||||||
images:
|
images:
|
||||||
owsec:
|
owsec:
|
||||||
repository: tip-tip-wlan-cloud-ucentral.jfrog.io/owsec
|
repository: tip-tip-wlan-cloud-ucentral.jfrog.io/owsec
|
||||||
tag: main
|
tag: v2.4.0-RC1
|
||||||
pullPolicy: Always
|
pullPolicy: Always
|
||||||
# regcred:
|
# regcred:
|
||||||
# registry: tip-tip-wlan-cloud-ucentral.jfrog.io
|
# registry: tip-tip-wlan-cloud-ucentral.jfrog.io
|
||||||
@@ -95,6 +95,8 @@ tolerations: []
|
|||||||
|
|
||||||
affinity: {}
|
affinity: {}
|
||||||
|
|
||||||
|
podAnnotations: {}
|
||||||
|
|
||||||
persistence:
|
persistence:
|
||||||
enabled: true
|
enabled: true
|
||||||
# storageClassName: "-"
|
# storageClassName: "-"
|
||||||
|
|||||||
@@ -51,6 +51,18 @@ components:
|
|||||||
properties:
|
properties:
|
||||||
ErrorCode:
|
ErrorCode:
|
||||||
type: integer
|
type: integer
|
||||||
|
enum:
|
||||||
|
- 0 # Success
|
||||||
|
- 1 # PASSWORD_CHANGE_REQUIRED,
|
||||||
|
- 2 # INVALID_CREDENTIALS,
|
||||||
|
- 3 # PASSWORD_ALREADY_USED,
|
||||||
|
- 4 # USERNAME_PENDING_VERIFICATION,
|
||||||
|
- 5 # PASSWORD_INVALID,
|
||||||
|
- 6 # INTERNAL_ERROR,
|
||||||
|
- 7 # ACCESS_DENIED,
|
||||||
|
- 8 # INVALID_TOKEN
|
||||||
|
- 9 # expired token
|
||||||
|
- 10 # rate limit exceeded
|
||||||
ErrorDetails:
|
ErrorDetails:
|
||||||
type: string
|
type: string
|
||||||
ErrorDescription:
|
ErrorDescription:
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ openwifi.system.commandchannel = /tmp/app.ucentralsec
|
|||||||
openwifi.service.key = $OWSEC_ROOT/certs/restapi-key.pem
|
openwifi.service.key = $OWSEC_ROOT/certs/restapi-key.pem
|
||||||
openwifi.service.key.password = mypassword
|
openwifi.service.key.password = mypassword
|
||||||
|
|
||||||
|
smssender.enabled = false
|
||||||
smssender.provider = aws
|
smssender.provider = aws
|
||||||
smssender.aws.secretkey = ***************************************
|
smssender.aws.secretkey = ***************************************
|
||||||
smssender.aws.accesskey = ***************************************
|
smssender.aws.accesskey = ***************************************
|
||||||
@@ -53,6 +54,7 @@ smssender.aws.region = **************
|
|||||||
#
|
#
|
||||||
# Security Microservice Specific Section
|
# Security Microservice Specific Section
|
||||||
#
|
#
|
||||||
|
mailer.enabled = false
|
||||||
mailer.hostname = smtp.gmail.com
|
mailer.hostname = smtp.gmail.com
|
||||||
mailer.username = ************************
|
mailer.username = ************************
|
||||||
mailer.password = ************************
|
mailer.password = ************************
|
||||||
|
|||||||
45
src/ACLProcessor.h
Normal file
45
src/ACLProcessor.h
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
//
|
||||||
|
// Created by stephane bourque on 2021-11-12.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef OWSEC_ACLPROCESSOR_H
|
||||||
|
#define OWSEC_ACLPROCESSOR_H
|
||||||
|
|
||||||
|
#include "RESTObjects/RESTAPI_SecurityObjects.h"
|
||||||
|
|
||||||
|
namespace OpenWifi {
|
||||||
|
|
||||||
|
class ACLProcessor {
|
||||||
|
public:
|
||||||
|
enum ACL_OPS {
|
||||||
|
READ,
|
||||||
|
MODIFY,
|
||||||
|
DELETE,
|
||||||
|
CREATE
|
||||||
|
};
|
||||||
|
static inline bool Can( const SecurityObjects::UserInfo & User, const SecurityObjects::UserInfo & Target, ACL_OPS Op) {
|
||||||
|
if(User.Id == Target.Id && Op==DELETE)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if(User.userRole==SecurityObjects::ROOT)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if(User.Id == Target.Id)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if(User.userRole!=SecurityObjects::ADMIN && User.userRole!=SecurityObjects::ROOT && Op!=READ)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if(Target.userRole==SecurityObjects::ROOT && Op!=READ)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif //OWSEC_ACLPROCESSOR_H
|
||||||
68
src/ActionLinkManager.cpp
Normal file
68
src/ActionLinkManager.cpp
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
//
|
||||||
|
// Created by stephane bourque on 2021-11-08.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "ActionLinkManager.h"
|
||||||
|
#include "StorageService.h"
|
||||||
|
#include "RESTObjects/RESTAPI_SecurityObjects.h"
|
||||||
|
|
||||||
|
namespace OpenWifi {
|
||||||
|
|
||||||
|
int ActionLinkManager::Start() {
|
||||||
|
if(!Running_)
|
||||||
|
Thr_.start(*this);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ActionLinkManager::Stop() {
|
||||||
|
if(Running_) {
|
||||||
|
Running_ = false;
|
||||||
|
Thr_.wakeUp();
|
||||||
|
Thr_.join();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ActionLinkManager::run() {
|
||||||
|
Running_ = true ;
|
||||||
|
|
||||||
|
while(Running_) {
|
||||||
|
Poco::Thread::trySleep(2000);
|
||||||
|
if(!Running_)
|
||||||
|
break;
|
||||||
|
std::vector<SecurityObjects::ActionLink> Links;
|
||||||
|
{
|
||||||
|
std::lock_guard G(Mutex_);
|
||||||
|
StorageService()->GetActions(Links);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(Links.empty())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for(auto &i:Links) {
|
||||||
|
if(!Running_)
|
||||||
|
break;
|
||||||
|
|
||||||
|
SecurityObjects::UserInfo UInfo;
|
||||||
|
if(!StorageService()->GetUserById(i.userId,UInfo)) {
|
||||||
|
StorageService()->CancelAction(i.id);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(i.action==OpenWifi::SecurityObjects::LinkActions::FORGOT_PASSWORD) {
|
||||||
|
if(AuthService::SendEmailToUser(i.id, UInfo.email, AuthService::FORGOT_PASSWORD)) {
|
||||||
|
Logger_.information(Poco::format("Send password reset link to %s",UInfo.email));
|
||||||
|
}
|
||||||
|
StorageService()->SentAction(i.id);
|
||||||
|
} else if (i.action==OpenWifi::SecurityObjects::LinkActions::VERIFY_EMAIL) {
|
||||||
|
if(AuthService::SendEmailToUser(i.id, UInfo.email, AuthService::EMAIL_VERIFICATION)) {
|
||||||
|
Logger_.information(Poco::format("Send email verification link to %s",UInfo.email));
|
||||||
|
}
|
||||||
|
StorageService()->SentAction(i.id);
|
||||||
|
} else {
|
||||||
|
StorageService()->SentAction(i.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
41
src/ActionLinkManager.h
Normal file
41
src/ActionLinkManager.h
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
//
|
||||||
|
// Created by stephane bourque on 2021-11-08.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef OWSEC_ACTIONLINKMANAGER_H
|
||||||
|
#define OWSEC_ACTIONLINKMANAGER_H
|
||||||
|
|
||||||
|
#include "framework/MicroService.h"
|
||||||
|
|
||||||
|
namespace OpenWifi {
|
||||||
|
|
||||||
|
class ActionLinkManager : public SubSystemServer, Poco::Runnable {
|
||||||
|
public:
|
||||||
|
|
||||||
|
enum Actions {
|
||||||
|
FORGOT_PASSWORD,
|
||||||
|
VERIFY_EMAIL
|
||||||
|
};
|
||||||
|
|
||||||
|
static ActionLinkManager * instance() {
|
||||||
|
static auto * instance_ = new ActionLinkManager;
|
||||||
|
return instance_;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Start() final;
|
||||||
|
void Stop() final;
|
||||||
|
void run();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Poco::Thread Thr_;
|
||||||
|
std::atomic_bool Running_ = false;
|
||||||
|
|
||||||
|
ActionLinkManager() noexcept:
|
||||||
|
SubSystemServer("ActionLinkManager", "ACTION-SVR", "action.server")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
inline ActionLinkManager * ActionLinkManager() { return ActionLinkManager::instance(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //OWSEC_ACTIONLINKMANAGER_H
|
||||||
@@ -11,6 +11,7 @@
|
|||||||
#include "Poco/Net/OAuth20Credentials.h"
|
#include "Poco/Net/OAuth20Credentials.h"
|
||||||
#include "Poco/JWT/Token.h"
|
#include "Poco/JWT/Token.h"
|
||||||
#include "Poco/JWT/Signer.h"
|
#include "Poco/JWT/Signer.h"
|
||||||
|
#include "Poco/StringTokenizer.h"
|
||||||
|
|
||||||
#include "framework/MicroService.h"
|
#include "framework/MicroService.h"
|
||||||
#include "StorageService.h"
|
#include "StorageService.h"
|
||||||
@@ -21,7 +22,6 @@
|
|||||||
#include "MFAServer.h"
|
#include "MFAServer.h"
|
||||||
|
|
||||||
namespace OpenWifi {
|
namespace OpenWifi {
|
||||||
class AuthService *AuthService::instance_ = nullptr;
|
|
||||||
|
|
||||||
AuthService::ACCESS_TYPE AuthService::IntToAccessType(int C) {
|
AuthService::ACCESS_TYPE AuthService::IntToAccessType(int C) {
|
||||||
switch (C) {
|
switch (C) {
|
||||||
@@ -46,10 +46,6 @@ namespace OpenWifi {
|
|||||||
Signer_.setRSAKey(MicroService::instance().Key());
|
Signer_.setRSAKey(MicroService::instance().Key());
|
||||||
Signer_.addAllAlgorithms();
|
Signer_.addAllAlgorithms();
|
||||||
Logger_.notice("Starting...");
|
Logger_.notice("Starting...");
|
||||||
Secure_ = MicroService::instance().ConfigGetBool("authentication.enabled",true);
|
|
||||||
DefaultPassword_ = MicroService::instance().ConfigGetString("authentication.default.password","");
|
|
||||||
DefaultUserName_ = MicroService::instance().ConfigGetString("authentication.default.username","");
|
|
||||||
Mechanism_ = MicroService::instance().ConfigGetString("authentication.service.type","internal");
|
|
||||||
PasswordValidation_ = PasswordValidationStr_ = MicroService::instance().ConfigGetString("authentication.validation.expression","^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{8,}$");
|
PasswordValidation_ = PasswordValidationStr_ = MicroService::instance().ConfigGetString("authentication.validation.expression","^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{8,}$");
|
||||||
TokenAging_ = (uint64_t) MicroService::instance().ConfigGetInt("authentication.token.ageing", 30 * 24 * 60 * 60);
|
TokenAging_ = (uint64_t) MicroService::instance().ConfigGetInt("authentication.token.ageing", 30 * 24 * 60 * 60);
|
||||||
HowManyOldPassword_ = MicroService::instance().ConfigGetInt("authentication.oldpasswords", 5);
|
HowManyOldPassword_ = MicroService::instance().ConfigGetInt("authentication.oldpasswords", 5);
|
||||||
@@ -60,54 +56,67 @@ namespace OpenWifi {
|
|||||||
Logger_.notice("Stopping...");
|
Logger_.notice("Stopping...");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AuthService::IsAuthorized(Poco::Net::HTTPServerRequest & Request, std::string & SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo )
|
bool AuthService::IsAuthorized(Poco::Net::HTTPServerRequest & Request, std::string & SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo, bool & Expired )
|
||||||
{
|
{
|
||||||
if(!Secure_)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
std::lock_guard Guard(Mutex_);
|
std::lock_guard Guard(Mutex_);
|
||||||
|
Expired = false;
|
||||||
std::string CallToken;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
std::string CallToken;
|
||||||
Poco::Net::OAuth20Credentials Auth(Request);
|
Poco::Net::OAuth20Credentials Auth(Request);
|
||||||
|
|
||||||
if (Auth.getScheme() == "Bearer") {
|
if (Auth.getScheme() == "Bearer") {
|
||||||
CallToken = Auth.getBearerToken();
|
CallToken = Auth.getBearerToken();
|
||||||
}
|
}
|
||||||
} catch(const Poco::Exception &E) {
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!CallToken.empty()) {
|
if(!CallToken.empty()) {
|
||||||
if(StorageService()->IsTokenRevoked(CallToken))
|
auto Client = UserCache_.get(CallToken);
|
||||||
|
if( Client.isNull() ) {
|
||||||
|
SecurityObjects::UserInfoAndPolicy UInfo2;
|
||||||
|
uint64_t RevocationDate=0;
|
||||||
|
if(StorageService()->GetToken(CallToken,UInfo2,RevocationDate)) {
|
||||||
|
if(RevocationDate!=0)
|
||||||
return false;
|
return false;
|
||||||
auto Client = UserCache_.find(CallToken);
|
Expired = (UInfo2.webtoken.created_ + UInfo2.webtoken.expires_in_) < time(nullptr);
|
||||||
if( Client == UserCache_.end() )
|
if(StorageService()->GetUserById(UInfo2.userinfo.Id,UInfo.userinfo)) {
|
||||||
return ValidateToken(CallToken, CallToken, UInfo);
|
UInfo.webtoken = UInfo2.webtoken;
|
||||||
|
UserCache_.update(CallToken, UInfo);
|
||||||
if((Client->second.webtoken.created_ + Client->second.webtoken.expires_in_) > time(nullptr)) {
|
|
||||||
SessionToken = CallToken;
|
SessionToken = CallToken;
|
||||||
UInfo = Client->second ;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
UserCache_.erase(CallToken);
|
}
|
||||||
StorageService()->RevokeToken(CallToken);
|
return false;
|
||||||
|
}
|
||||||
|
if(!Expired) {
|
||||||
|
SessionToken = CallToken;
|
||||||
|
UInfo = *Client ;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
RevokeToken(CallToken);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} catch(const Poco::Exception &E) {
|
||||||
|
Logger_.log(E);
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
void AuthService::RevokeToken(std::string & Token) {
|
||||||
|
UserCache_.remove(Token);
|
||||||
|
StorageService()->RevokeToken(Token);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AuthService::DeleteUserFromCache(const std::string &UserName) {
|
bool AuthService::DeleteUserFromCache(const std::string &UserName) {
|
||||||
std::lock_guard Guard(Mutex_);
|
std::lock_guard Guard(Mutex_);
|
||||||
|
|
||||||
for(auto i=UserCache_.begin();i!=UserCache_.end();) {
|
std::vector<std::string> OldTokens;
|
||||||
if (i->second.userinfo.email==UserName) {
|
|
||||||
Logout(i->first, false);
|
UserCache_.forEach([&OldTokens,UserName](const std::string &token, const SecurityObjects::UserInfoAndPolicy& O) -> void
|
||||||
i = UserCache_.erase(i);
|
{ if(O.userinfo.email==UserName)
|
||||||
} else {
|
OldTokens.push_back(token);
|
||||||
++i;
|
});
|
||||||
}
|
|
||||||
|
for(const auto &i:OldTokens) {
|
||||||
|
Logout(i,false);
|
||||||
|
UserCache_.remove(i);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -123,9 +132,6 @@ namespace OpenWifi {
|
|||||||
void AuthService::Logout(const std::string &token, bool EraseFromCache) {
|
void AuthService::Logout(const std::string &token, bool EraseFromCache) {
|
||||||
std::lock_guard Guard(Mutex_);
|
std::lock_guard Guard(Mutex_);
|
||||||
|
|
||||||
if(EraseFromCache)
|
|
||||||
UserCache_.erase(token);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Poco::JSON::Object Obj;
|
Poco::JSON::Object Obj;
|
||||||
Obj.set("event", "remove-token");
|
Obj.set("event", "remove-token");
|
||||||
@@ -134,7 +140,7 @@ namespace OpenWifi {
|
|||||||
std::stringstream ResultText;
|
std::stringstream ResultText;
|
||||||
Poco::JSON::Stringifier::stringify(Obj, ResultText);
|
Poco::JSON::Stringifier::stringify(Obj, ResultText);
|
||||||
std::string Tmp{token};
|
std::string Tmp{token};
|
||||||
StorageService()->RevokeToken(Tmp);
|
RevokeToken(Tmp);
|
||||||
KafkaManager()->PostMessage(KafkaTopics::SERVICE_EVENTS, MicroService::instance().PrivateEndPoint(), ResultText.str(),
|
KafkaManager()->PostMessage(KafkaTopics::SERVICE_EVENTS, MicroService::instance().PrivateEndPoint(), ResultText.str(),
|
||||||
false);
|
false);
|
||||||
} catch (const Poco::Exception &E) {
|
} catch (const Poco::Exception &E) {
|
||||||
@@ -143,7 +149,7 @@ namespace OpenWifi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] std::string AuthService::GenerateTokenHMAC(const std::string & UserName, ACCESS_TYPE Type) {
|
[[nodiscard]] std::string AuthService::GenerateTokenHMAC(const std::string & UserName, ACCESS_TYPE Type) {
|
||||||
std::string Identity(UserName + ":" + Poco::format("%d",(int)std::time(nullptr)));
|
std::string Identity(UserName + ":" + Poco::format("%d",(int)std::time(nullptr)) + ":" + std::to_string(rand()));
|
||||||
HMAC_.update(Identity);
|
HMAC_.update(Identity);
|
||||||
return Poco::DigestEngine::digestToHex(HMAC_.digest());
|
return Poco::DigestEngine::digestToHex(HMAC_.digest());
|
||||||
}
|
}
|
||||||
@@ -168,28 +174,6 @@ namespace OpenWifi {
|
|||||||
return JWT;
|
return JWT;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AuthService::ValidateToken(const std::string & Token, std::string & SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo ) {
|
|
||||||
std::lock_guard Guard(Mutex_);
|
|
||||||
|
|
||||||
try {
|
|
||||||
auto E = UserCache_.find(SessionToken);
|
|
||||||
if(E == UserCache_.end()) {
|
|
||||||
if(StorageService()->GetToken(SessionToken,UInfo)) {
|
|
||||||
if(StorageService()->GetUserById(UInfo.userinfo.email,UInfo.userinfo)) {
|
|
||||||
UserCache_[UInfo.webtoken.access_token_] = UInfo;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
UInfo = E->second;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} catch (const Poco::Exception &E ) {
|
|
||||||
Logger_.log(E);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AuthService::CreateToken(const std::string & UserName, SecurityObjects::UserInfoAndPolicy &UInfo)
|
void AuthService::CreateToken(const std::string & UserName, SecurityObjects::UserInfoAndPolicy &UInfo)
|
||||||
{
|
{
|
||||||
std::lock_guard Guard(Mutex_);
|
std::lock_guard Guard(Mutex_);
|
||||||
@@ -207,43 +191,88 @@ namespace OpenWifi {
|
|||||||
UInfo.webtoken.username_ = UserName;
|
UInfo.webtoken.username_ = UserName;
|
||||||
UInfo.webtoken.errorCode = 0;
|
UInfo.webtoken.errorCode = 0;
|
||||||
UInfo.webtoken.userMustChangePassword = false;
|
UInfo.webtoken.userMustChangePassword = false;
|
||||||
UserCache_[UInfo.webtoken.access_token_] = UInfo;
|
UserCache_.update(UInfo.webtoken.access_token_,UInfo);
|
||||||
StorageService()->SetLastLogin(UInfo.userinfo.Id);
|
StorageService()->SetLastLogin(UInfo.userinfo.Id);
|
||||||
StorageService()->AddToken(UInfo.webtoken.username_, UInfo.webtoken.access_token_,
|
StorageService()->AddToken(UInfo.userinfo.Id, UInfo.webtoken.access_token_,
|
||||||
UInfo.webtoken.refresh_token_, UInfo.webtoken.token_type_,
|
UInfo.webtoken.refresh_token_, UInfo.webtoken.token_type_,
|
||||||
UInfo.webtoken.expires_in_, UInfo.webtoken.idle_timeout_);
|
UInfo.webtoken.expires_in_, UInfo.webtoken.idle_timeout_);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AuthService::SetPassword(const std::string &NewPassword, SecurityObjects::UserInfo & UInfo) {
|
bool AuthService::SetPassword(const std::string &NewPassword, SecurityObjects::UserInfo & UInfo) {
|
||||||
auto NewPasswordHash = ComputePasswordHash(UInfo.email, NewPassword);
|
std::lock_guard G(Mutex_);
|
||||||
for (auto const &i:UInfo.lastPasswords) {
|
|
||||||
if (i == NewPasswordHash) {
|
Poco::toLowerInPlace(UInfo.email);
|
||||||
|
for (const auto &i:UInfo.lastPasswords) {
|
||||||
|
auto Tokens = Poco::StringTokenizer(i,"|");
|
||||||
|
if(Tokens.count()==2) {
|
||||||
|
const auto & Salt = Tokens[0];
|
||||||
|
for(const auto &j:UInfo.lastPasswords) {
|
||||||
|
auto OldTokens = Poco::StringTokenizer(j,"|");
|
||||||
|
if(OldTokens.count()==2) {
|
||||||
|
SHA2_.update(Salt+NewPassword+UInfo.email);
|
||||||
|
if(OldTokens[1]==Utils::ToHex(SHA2_.digest()))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
SHA2_.update(NewPassword+UInfo.email);
|
||||||
|
if(Tokens[0]==Utils::ToHex(SHA2_.digest()))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(UInfo.lastPasswords.size()==HowManyOldPassword_) {
|
if(UInfo.lastPasswords.size()==HowManyOldPassword_) {
|
||||||
UInfo.lastPasswords.erase(UInfo.lastPasswords.begin());
|
UInfo.lastPasswords.erase(UInfo.lastPasswords.begin());
|
||||||
}
|
}
|
||||||
UInfo.lastPasswords.push_back(NewPasswordHash);
|
|
||||||
UInfo.currentPassword = NewPasswordHash;
|
auto NewHash = ComputeNewPasswordHash(UInfo.email,NewPassword);
|
||||||
|
UInfo.lastPasswords.push_back(NewHash);
|
||||||
|
UInfo.currentPassword = NewHash;
|
||||||
UInfo.changePassword = false;
|
UInfo.changePassword = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
AuthService::AUTH_ERROR AuthService::Authorize( std::string & UserName, const std::string & Password, const std::string & NewPassword, SecurityObjects::UserInfoAndPolicy & UInfo )
|
static std::string GetMeSomeSalt() {
|
||||||
|
auto start = std::chrono::high_resolution_clock::now();
|
||||||
|
return std::to_string(start.time_since_epoch().count());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string AuthService::ComputeNewPasswordHash(const std::string &UserName, const std::string &Password) {
|
||||||
|
std::string UName = Poco::trim(Poco::toLower(UserName));
|
||||||
|
auto Salt = GetMeSomeSalt();
|
||||||
|
SHA2_.update(Salt + Password + UName );
|
||||||
|
return Salt + "|" + Utils::ToHex(SHA2_.digest());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AuthService::ValidatePasswordHash(const std::string & UserName, const std::string & Password, const std::string &StoredPassword) {
|
||||||
|
std::lock_guard G(Mutex_);
|
||||||
|
|
||||||
|
std::string UName = Poco::trim(Poco::toLower(UserName));
|
||||||
|
auto Tokens = Poco::StringTokenizer(StoredPassword,"|");
|
||||||
|
if(Tokens.count()==1) {
|
||||||
|
SHA2_.update(Password+UName);
|
||||||
|
if(Tokens[0]==Utils::ToHex(SHA2_.digest()))
|
||||||
|
return true;
|
||||||
|
} else if (Tokens.count()==2) {
|
||||||
|
SHA2_.update(Tokens[0]+Password+UName);
|
||||||
|
if(Tokens[1]==Utils::ToHex(SHA2_.digest()))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
UNAUTHORIZED_REASON AuthService::Authorize( std::string & UserName, const std::string & Password, const std::string & NewPassword, SecurityObjects::UserInfoAndPolicy & UInfo , bool & Expired )
|
||||||
{
|
{
|
||||||
std::lock_guard Guard(Mutex_);
|
std::lock_guard Guard(Mutex_);
|
||||||
SecurityObjects::AclTemplate ACL;
|
|
||||||
|
|
||||||
Poco::toLowerInPlace(UserName);
|
Poco::toLowerInPlace(UserName);
|
||||||
auto PasswordHash = ComputePasswordHash(UserName, Password);
|
|
||||||
|
|
||||||
if(StorageService()->GetUserByEmail(UserName,UInfo.userinfo)) {
|
if(StorageService()->GetUserByEmail(UserName,UInfo.userinfo)) {
|
||||||
if(UInfo.userinfo.waitingForEmailCheck) {
|
if(UInfo.userinfo.waitingForEmailCheck) {
|
||||||
return USERNAME_PENDING_VERIFICATION;
|
return USERNAME_PENDING_VERIFICATION;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(PasswordHash != UInfo.userinfo.currentPassword) {
|
if(!ValidatePasswordHash(UserName,Password,UInfo.userinfo.currentPassword)) {
|
||||||
return INVALID_CREDENTIALS;
|
return INVALID_CREDENTIALS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -270,54 +299,35 @@ namespace OpenWifi {
|
|||||||
UInfo.userinfo.lastLogin=std::time(nullptr);
|
UInfo.userinfo.lastLogin=std::time(nullptr);
|
||||||
StorageService()->SetLastLogin(UInfo.userinfo.Id);
|
StorageService()->SetLastLogin(UInfo.userinfo.Id);
|
||||||
CreateToken(UserName, UInfo );
|
CreateToken(UserName, UInfo );
|
||||||
|
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(((UserName == DefaultUserName_) && (DefaultPassword_== ComputePasswordHash(UserName,Password))) || !Secure_)
|
|
||||||
{
|
|
||||||
ACL.PortalLogin_ = ACL.Read_ = ACL.ReadWrite_ = ACL.ReadWriteCreate_ = ACL.Delete_ = true;
|
|
||||||
UInfo.webtoken.acl_template_ = ACL;
|
|
||||||
UInfo.userinfo.email = DefaultUserName_;
|
|
||||||
UInfo.userinfo.currentPassword = DefaultPassword_;
|
|
||||||
UInfo.userinfo.name = DefaultUserName_;
|
|
||||||
UInfo.userinfo.userRole = SecurityObjects::ROOT;
|
|
||||||
CreateToken(UserName, UInfo );
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
|
||||||
return INVALID_CREDENTIALS;
|
return INVALID_CREDENTIALS;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string AuthService::ComputePasswordHash(const std::string &UserName, const std::string &Password) {
|
bool AuthService::SendEmailToUser(const std::string &LinkId, std::string &Email, EMAIL_REASON Reason) {
|
||||||
std::string UName = Poco::trim(Poco::toLower(UserName));
|
|
||||||
SHA2_.update(Password + UName);
|
|
||||||
return Utils::ToHex(SHA2_.digest());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AuthService::SendEmailToUser(std::string &Email, EMAIL_REASON Reason) {
|
|
||||||
SecurityObjects::UserInfo UInfo;
|
SecurityObjects::UserInfo UInfo;
|
||||||
|
|
||||||
if(StorageService()->GetUserByEmail(Email,UInfo)) {
|
if(StorageService()->GetUserByEmail(Email,UInfo)) {
|
||||||
switch (Reason) {
|
switch (Reason) {
|
||||||
|
|
||||||
case FORGOT_PASSWORD: {
|
case FORGOT_PASSWORD: {
|
||||||
MessageAttributes Attrs;
|
MessageAttributes Attrs;
|
||||||
|
|
||||||
Attrs[RECIPIENT_EMAIL] = UInfo.email;
|
Attrs[RECIPIENT_EMAIL] = UInfo.email;
|
||||||
Attrs[LOGO] = "logo.jpg";
|
Attrs[LOGO] = GetLogoAssetURI();
|
||||||
Attrs[SUBJECT] = "Password reset link";
|
Attrs[SUBJECT] = "Password reset link";
|
||||||
Attrs[ACTION_LINK] =
|
Attrs[ACTION_LINK] = MicroService::instance().GetPublicAPIEndPoint() + "/actionLink?action=password_reset&id=" + LinkId ;
|
||||||
MicroService::instance().GetPublicAPIEndPoint() + "/actionLink?action=password_reset&id=" + UInfo.Id ;
|
|
||||||
SMTPMailerService()->SendMessage(UInfo.email, "password_reset.txt", Attrs);
|
SMTPMailerService()->SendMessage(UInfo.email, "password_reset.txt", Attrs);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EMAIL_VERIFICATION: {
|
case EMAIL_VERIFICATION: {
|
||||||
MessageAttributes Attrs;
|
MessageAttributes Attrs;
|
||||||
|
|
||||||
Attrs[RECIPIENT_EMAIL] = UInfo.email;
|
Attrs[RECIPIENT_EMAIL] = UInfo.email;
|
||||||
Attrs[LOGO] = "logo.jpg";
|
Attrs[LOGO] = GetLogoAssetURI();
|
||||||
Attrs[SUBJECT] = "EMail Address Verification";
|
Attrs[SUBJECT] = "EMail Address Verification";
|
||||||
Attrs[ACTION_LINK] =
|
Attrs[ACTION_LINK] = MicroService::instance().GetPublicAPIEndPoint() + "/actionLink?action=email_verification&id=" + LinkId ;
|
||||||
MicroService::instance().GetPublicAPIEndPoint() + "/actionLink?action=email_verification&id=" + UInfo.Id ;
|
|
||||||
SMTPMailerService()->SendMessage(UInfo.email, "email_verification.txt", Attrs);
|
SMTPMailerService()->SendMessage(UInfo.email, "email_verification.txt", Attrs);
|
||||||
UInfo.waitingForEmailCheck = true;
|
UInfo.waitingForEmailCheck = true;
|
||||||
}
|
}
|
||||||
@@ -326,33 +336,57 @@ namespace OpenWifi {
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AuthService::VerifyEmail(SecurityObjects::UserInfo &UInfo) {
|
bool AuthService::VerifyEmail(SecurityObjects::UserInfo &UInfo) {
|
||||||
MessageAttributes Attrs;
|
SecurityObjects::ActionLink A;
|
||||||
|
|
||||||
Attrs[RECIPIENT_EMAIL] = UInfo.email;
|
A.action = OpenWifi::SecurityObjects::LinkActions::VERIFY_EMAIL;
|
||||||
Attrs[LOGO] = "logo.jpg";
|
A.userId = UInfo.email;
|
||||||
Attrs[SUBJECT] = "EMail Address Verification";
|
A.id = MicroService::CreateUUID();
|
||||||
Attrs[ACTION_LINK] =
|
A.created = std::time(nullptr);
|
||||||
MicroService::instance().GetPublicAPIEndPoint() + "/actionLink?action=email_verification&id=" + UInfo.Id ;
|
A.expires = A.created + 24*60*60;
|
||||||
SMTPMailerService()->SendMessage(UInfo.email, "email_verification.txt", Attrs);
|
StorageService()->CreateAction(A);
|
||||||
UInfo.waitingForEmailCheck = true;
|
UInfo.waitingForEmailCheck = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AuthService::IsValidToken(const std::string &Token, SecurityObjects::WebToken &WebToken, SecurityObjects::UserInfo &UserInfo) {
|
bool AuthService::IsValidToken(const std::string &Token, SecurityObjects::WebToken &WebToken, SecurityObjects::UserInfo &UserInfo, bool & Expired) {
|
||||||
std::lock_guard G(Mutex_);
|
std::lock_guard G(Mutex_);
|
||||||
auto It = UserCache_.find(Token);
|
|
||||||
|
|
||||||
if(It==UserCache_.end())
|
Expired = false;
|
||||||
return false;
|
|
||||||
WebToken = It->second.webtoken;
|
auto Client = UserCache_.get(Token);
|
||||||
UserInfo = It->second.userinfo;
|
if(!Client.isNull()) {
|
||||||
|
Expired = (Client->webtoken.created_ + Client->webtoken.expires_in_) < std::time(nullptr);
|
||||||
|
WebToken = Client->webtoken;
|
||||||
|
UserInfo = Client->userinfo;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string TToken{Token};
|
||||||
|
if(StorageService()->IsTokenRevoked(TToken)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the token from disk...
|
||||||
|
SecurityObjects::UserInfoAndPolicy UInfo;
|
||||||
|
uint64_t RevocationDate=0;
|
||||||
|
if(StorageService()->GetToken(TToken, UInfo, RevocationDate)) {
|
||||||
|
if(RevocationDate!=0)
|
||||||
|
return false;
|
||||||
|
Expired = (UInfo.webtoken.created_ + UInfo.webtoken.expires_in_) < std::time(nullptr);
|
||||||
|
if(StorageService()->GetUserById(UInfo.userinfo.Id,UInfo.userinfo)) {
|
||||||
|
WebToken = UInfo.webtoken;
|
||||||
|
UserCache_.update(UInfo.webtoken.access_token_, UInfo);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} // end of namespace
|
} // end of namespace
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
#include "Poco/SHA2Engine.h"
|
#include "Poco/SHA2Engine.h"
|
||||||
#include "Poco/Crypto/DigestEngine.h"
|
#include "Poco/Crypto/DigestEngine.h"
|
||||||
#include "Poco/HMACEngine.h"
|
#include "Poco/HMACEngine.h"
|
||||||
|
#include "Poco/ExpireLRUCache.h"
|
||||||
|
|
||||||
#include "framework/MicroService.h"
|
#include "framework/MicroService.h"
|
||||||
#include "RESTObjects/RESTAPI_SecurityObjects.h"
|
#include "RESTObjects/RESTAPI_SecurityObjects.h"
|
||||||
@@ -35,16 +36,6 @@ namespace OpenWifi{
|
|||||||
CUSTOM
|
CUSTOM
|
||||||
};
|
};
|
||||||
|
|
||||||
enum AUTH_ERROR {
|
|
||||||
SUCCESS,
|
|
||||||
PASSWORD_CHANGE_REQUIRED,
|
|
||||||
INVALID_CREDENTIALS,
|
|
||||||
PASSWORD_ALREADY_USED,
|
|
||||||
USERNAME_PENDING_VERIFICATION,
|
|
||||||
PASSWORD_INVALID,
|
|
||||||
INTERNAL_ERROR
|
|
||||||
};
|
|
||||||
|
|
||||||
enum EMAIL_REASON {
|
enum EMAIL_REASON {
|
||||||
FORGOT_PASSWORD,
|
FORGOT_PASSWORD,
|
||||||
EMAIL_VERIFICATION
|
EMAIL_VERIFICATION
|
||||||
@@ -54,48 +45,51 @@ namespace OpenWifi{
|
|||||||
static int AccessTypeToInt(ACCESS_TYPE T);
|
static int AccessTypeToInt(ACCESS_TYPE T);
|
||||||
|
|
||||||
static AuthService *instance() {
|
static AuthService *instance() {
|
||||||
if (instance_ == nullptr) {
|
static auto * instance_ = new AuthService;
|
||||||
instance_ = new AuthService;
|
|
||||||
}
|
|
||||||
return instance_;
|
return instance_;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Start() override;
|
int Start() override;
|
||||||
void Stop() override;
|
void Stop() override;
|
||||||
|
|
||||||
[[nodiscard]] bool IsAuthorized(Poco::Net::HTTPServerRequest & Request,std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo );
|
[[nodiscard]] bool IsAuthorized(Poco::Net::HTTPServerRequest & Request,std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo, bool & Expired);
|
||||||
[[nodiscard]] AUTH_ERROR Authorize( std::string & UserName, const std::string & Password, const std::string & NewPassword, SecurityObjects::UserInfoAndPolicy & UInfo );
|
[[nodiscard]] UNAUTHORIZED_REASON Authorize( std::string & UserName, const std::string & Password, const std::string & NewPassword, SecurityObjects::UserInfoAndPolicy & UInfo, bool & Expired );
|
||||||
void CreateToken(const std::string & UserName, SecurityObjects::UserInfoAndPolicy &UInfo);
|
void CreateToken(const std::string & UserName, SecurityObjects::UserInfoAndPolicy &UInfo);
|
||||||
[[nodiscard]] bool ValidateToken(const std::string & Token, std::string & SessionToken, SecurityObjects::UserInfoAndPolicy & UserInfo );
|
|
||||||
[[nodiscard]] bool SetPassword(const std::string &Password, SecurityObjects::UserInfo & UInfo);
|
[[nodiscard]] bool SetPassword(const std::string &Password, SecurityObjects::UserInfo & UInfo);
|
||||||
[[nodiscard]] const std:: string & PasswordValidationExpression() const { return PasswordValidationStr_;};
|
[[nodiscard]] const std:: string & PasswordValidationExpression() const { return PasswordValidationStr_;};
|
||||||
void Logout(const std::string &token, bool EraseFromCache=true);
|
void Logout(const std::string &token, bool EraseFromCache=true);
|
||||||
|
|
||||||
bool ValidatePassword(const std::string &pwd);
|
bool ValidatePassword(const std::string &pwd);
|
||||||
|
|
||||||
[[nodiscard]] bool IsValidToken(const std::string &Token, SecurityObjects::WebToken &WebToken, SecurityObjects::UserInfo &UserInfo);
|
[[nodiscard]] bool IsValidToken(const std::string &Token, SecurityObjects::WebToken &WebToken, SecurityObjects::UserInfo &UserInfo, bool & Expired);
|
||||||
[[nodiscard]] bool IsValidAPIKEY(const Poco::Net::HTTPServerRequest &Request);
|
|
||||||
[[nodiscard]] std::string GenerateTokenJWT(const std::string & UserName, ACCESS_TYPE Type);
|
[[nodiscard]] std::string GenerateTokenJWT(const std::string & UserName, ACCESS_TYPE Type);
|
||||||
[[nodiscard]] std::string GenerateTokenHMAC(const std::string & UserName, ACCESS_TYPE Type);
|
[[nodiscard]] std::string GenerateTokenHMAC(const std::string & UserName, ACCESS_TYPE Type);
|
||||||
[[nodiscard]] bool ValidateToken(const std::string & Token, std::string & SessionToken, SecurityObjects::WebToken & UserInfo );
|
|
||||||
[[nodiscard]] std::string ComputePasswordHash(const std::string &UserName, const std::string &Password);
|
[[nodiscard]] std::string ComputeNewPasswordHash(const std::string &UserName, const std::string &Password);
|
||||||
|
[[nodiscard]] bool ValidatePasswordHash(const std::string & UserName, const std::string & Password, const std::string &StoredPassword);
|
||||||
|
|
||||||
[[nodiscard]] bool UpdatePassword(const std::string &Admin, const std::string &UserName, const std::string & OldPassword, const std::string &NewPassword);
|
[[nodiscard]] bool UpdatePassword(const std::string &Admin, const std::string &UserName, const std::string & OldPassword, const std::string &NewPassword);
|
||||||
[[nodiscard]] std::string ResetPassword(const std::string &Admin, const std::string &UserName);
|
[[nodiscard]] std::string ResetPassword(const std::string &Admin, const std::string &UserName);
|
||||||
|
|
||||||
[[nodiscard]] static bool VerifyEmail(SecurityObjects::UserInfo &UInfo);
|
[[nodiscard]] static bool VerifyEmail(SecurityObjects::UserInfo &UInfo);
|
||||||
[[nodiscard]] static bool SendEmailToUser(std::string &Email, EMAIL_REASON Reason);
|
[[nodiscard]] static bool SendEmailToUser(const std::string &LinkId, std::string &Email, EMAIL_REASON Reason);
|
||||||
[[nodiscard]] bool DeleteUserFromCache(const std::string &UserName);
|
[[nodiscard]] bool DeleteUserFromCache(const std::string &UserName);
|
||||||
[[nodiscard]] bool RequiresMFA(const SecurityObjects::UserInfoAndPolicy &UInfo);
|
[[nodiscard]] bool RequiresMFA(const SecurityObjects::UserInfoAndPolicy &UInfo);
|
||||||
|
void RevokeToken(std::string & Token);
|
||||||
|
|
||||||
|
[[nodiscard]] static inline const std::string GetLogoAssetURI() {
|
||||||
|
return MicroService::instance().PublicEndPoint() + "/wwwassets/the_logo.png";
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] static inline const std::string GetLogoAssetFileName() {
|
||||||
|
return MicroService::instance().WWWAssetsDir() + "/the_logo.png";
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static AuthService *instance_;
|
|
||||||
bool Secure_ = false ;
|
|
||||||
std::string DefaultUserName_;
|
|
||||||
std::string DefaultPassword_;
|
|
||||||
std::string Mechanism_;
|
|
||||||
Poco::JWT::Signer Signer_;
|
Poco::JWT::Signer Signer_;
|
||||||
Poco::SHA2Engine SHA2_;
|
Poco::SHA2Engine SHA2_;
|
||||||
SecurityObjects::UserInfoCache UserCache_;
|
Poco::ExpireLRUCache<std::string,SecurityObjects::UserInfoAndPolicy> UserCache_{2048,1200000};
|
||||||
|
// SecurityObjects::UserInfoCache UserCache_;
|
||||||
std::string PasswordValidationStr_;
|
std::string PasswordValidationStr_;
|
||||||
std::regex PasswordValidation_;
|
std::regex PasswordValidation_;
|
||||||
uint64_t TokenAging_ = 30 * 24 * 60 * 60;
|
uint64_t TokenAging_ = 30 * 24 * 60 * 60;
|
||||||
@@ -127,8 +121,8 @@ namespace OpenWifi{
|
|||||||
|
|
||||||
inline AuthService * AuthService() { return AuthService::instance(); }
|
inline AuthService * AuthService() { return AuthService::instance(); }
|
||||||
|
|
||||||
[[nodiscard]] inline bool AuthServiceIsAuthorized(Poco::Net::HTTPServerRequest & Request,std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo ) {
|
[[nodiscard]] inline bool AuthServiceIsAuthorized(Poco::Net::HTTPServerRequest & Request,std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo , bool & Expired) {
|
||||||
return AuthService()->IsAuthorized(Request, SessionToken, UInfo );
|
return AuthService()->IsAuthorized(Request, SessionToken, UInfo, Expired );
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end of namespace
|
} // end of namespace
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
#include "SMTPMailerService.h"
|
#include "SMTPMailerService.h"
|
||||||
#include "AuthService.h"
|
#include "AuthService.h"
|
||||||
#include "SMSSender.h"
|
#include "SMSSender.h"
|
||||||
|
#include "ActionLinkManager.h"
|
||||||
|
|
||||||
namespace OpenWifi {
|
namespace OpenWifi {
|
||||||
class Daemon *Daemon::instance_ = nullptr;
|
class Daemon *Daemon::instance_ = nullptr;
|
||||||
@@ -44,7 +45,9 @@ namespace OpenWifi {
|
|||||||
SubSystemVec{
|
SubSystemVec{
|
||||||
StorageService(),
|
StorageService(),
|
||||||
SMSSender(),
|
SMSSender(),
|
||||||
|
ActionLinkManager(),
|
||||||
SMTPMailerService(),
|
SMTPMailerService(),
|
||||||
|
RESTAPI_RateLimiter(),
|
||||||
AuthService()
|
AuthService()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -53,8 +56,8 @@ namespace OpenWifi {
|
|||||||
|
|
||||||
void Daemon::initialize() {
|
void Daemon::initialize() {
|
||||||
AssetDir_ = MicroService::instance().ConfigPath("openwifi.restapi.wwwassets");
|
AssetDir_ = MicroService::instance().ConfigPath("openwifi.restapi.wwwassets");
|
||||||
AccessPolicy_ = MicroService::instance().ConfigGetString("openwifi.document.policy.access", "/wwwassets/access_policy.html");
|
AccessPolicy_ = MicroService::instance().ConfigPath("openwifi.document.policy.access", "/wwwassets/access_policy.html");
|
||||||
PasswordPolicy_ = MicroService::instance().ConfigGetString("openwifi.document.policy.password", "/wwwassets/password_policy.html");
|
PasswordPolicy_ = MicroService::instance().ConfigPath("openwifi.document.policy.password", "/wwwassets/password_policy.html");
|
||||||
}
|
}
|
||||||
|
|
||||||
void MicroServicePostInitialization() {
|
void MicroServicePostInitialization() {
|
||||||
|
|||||||
@@ -6,11 +6,10 @@
|
|||||||
#include "SMSSender.h"
|
#include "SMSSender.h"
|
||||||
#include "SMTPMailerService.h"
|
#include "SMTPMailerService.h"
|
||||||
#include "framework/MicroService.h"
|
#include "framework/MicroService.h"
|
||||||
|
#include "AuthService.h"
|
||||||
|
|
||||||
namespace OpenWifi {
|
namespace OpenWifi {
|
||||||
|
|
||||||
class MFAServer * MFAServer::instance_ = nullptr;
|
|
||||||
|
|
||||||
int MFAServer::Start() {
|
int MFAServer::Start() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -27,7 +26,7 @@ namespace OpenWifi {
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
std::string Challenge = MakeChallenge();
|
std::string Challenge = MakeChallenge();
|
||||||
std::string uuid = MicroService::instance().CreateUUID();
|
std::string uuid = MicroService::CreateUUID();
|
||||||
uint64_t Created = std::time(nullptr);
|
uint64_t Created = std::time(nullptr);
|
||||||
|
|
||||||
ChallengeStart.set("uuid",uuid);
|
ChallengeStart.set("uuid",uuid);
|
||||||
@@ -47,7 +46,7 @@ namespace OpenWifi {
|
|||||||
if(Method=="email" && SMTPMailerService()->Enabled() && !UInfo.userinfo.email.empty()) {
|
if(Method=="email" && SMTPMailerService()->Enabled() && !UInfo.userinfo.email.empty()) {
|
||||||
MessageAttributes Attrs;
|
MessageAttributes Attrs;
|
||||||
Attrs[RECIPIENT_EMAIL] = UInfo.userinfo.email;
|
Attrs[RECIPIENT_EMAIL] = UInfo.userinfo.email;
|
||||||
Attrs[LOGO] = "logo.jpg";
|
Attrs[LOGO] = AuthService::GetLogoAssetURI();
|
||||||
Attrs[SUBJECT] = "Login validation code";
|
Attrs[SUBJECT] = "Login validation code";
|
||||||
Attrs[CHALLENGE_CODE] = Challenge;
|
Attrs[CHALLENGE_CODE] = Challenge;
|
||||||
return SMTPMailerService()->SendMessage(UInfo.userinfo.email, "verification_code.txt", Attrs);
|
return SMTPMailerService()->SendMessage(UInfo.userinfo.email, "verification_code.txt", Attrs);
|
||||||
@@ -72,8 +71,9 @@ namespace OpenWifi {
|
|||||||
|
|
||||||
auto uuid = ChallengeResponse->get("uuid").toString();
|
auto uuid = ChallengeResponse->get("uuid").toString();
|
||||||
auto Hint = Cache_.find(uuid);
|
auto Hint = Cache_.find(uuid);
|
||||||
if(Hint == end(Cache_))
|
if(Hint == end(Cache_)) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
auto answer = ChallengeResponse->get("answer").toString();
|
auto answer = ChallengeResponse->get("answer").toString();
|
||||||
if(Hint->second.Answer!=answer) {
|
if(Hint->second.Answer!=answer) {
|
||||||
|
|||||||
@@ -24,24 +24,21 @@ namespace OpenWifi {
|
|||||||
int Start() override;
|
int Start() override;
|
||||||
void Stop() override;
|
void Stop() override;
|
||||||
static MFAServer *instance() {
|
static MFAServer *instance() {
|
||||||
if (instance_ == nullptr) {
|
static auto * instance_ = new MFAServer;
|
||||||
instance_ = new MFAServer;
|
|
||||||
}
|
|
||||||
return instance_;
|
return instance_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StartMFAChallenge(const SecurityObjects::UserInfoAndPolicy &UInfo, Poco::JSON::Object &Challenge);
|
bool StartMFAChallenge(const SecurityObjects::UserInfoAndPolicy &UInfo, Poco::JSON::Object &Challenge);
|
||||||
bool CompleteMFAChallenge(Poco::JSON::Object::Ptr &ChallengeResponse, SecurityObjects::UserInfoAndPolicy &UInfo);
|
bool CompleteMFAChallenge(Poco::JSON::Object::Ptr &ChallengeResponse, SecurityObjects::UserInfoAndPolicy &UInfo);
|
||||||
bool MethodEnabled(const std::string &Method);
|
static bool MethodEnabled(const std::string &Method);
|
||||||
bool ResendCode(const std::string &uuid);
|
bool ResendCode(const std::string &uuid);
|
||||||
bool SendChallenge(const SecurityObjects::UserInfoAndPolicy &UInfo, const std::string &Method, const std::string &Challenge);
|
static bool SendChallenge(const SecurityObjects::UserInfoAndPolicy &UInfo, const std::string &Method, const std::string &Challenge);
|
||||||
|
|
||||||
static inline std::string MakeChallenge() {
|
static inline std::string MakeChallenge() {
|
||||||
return std::to_string(rand() % 999999);
|
return std::to_string(MicroService::instance().Random(1,999999));
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static MFAServer * instance_;
|
|
||||||
MFAChallengeCache Cache_;
|
MFAChallengeCache Cache_;
|
||||||
MFAServer() noexcept:
|
MFAServer() noexcept:
|
||||||
SubSystemServer("MFServer", "MFA-SVR", "mfa")
|
SubSystemServer("MFServer", "MFA-SVR", "mfa")
|
||||||
|
|||||||
@@ -11,46 +11,61 @@
|
|||||||
#include "Daemon.h"
|
#include "Daemon.h"
|
||||||
|
|
||||||
namespace OpenWifi {
|
namespace OpenWifi {
|
||||||
|
|
||||||
void RESTAPI_action_links::DoGet() {
|
void RESTAPI_action_links::DoGet() {
|
||||||
|
|
||||||
auto Action = GetParameter("action","");
|
auto Action = GetParameter("action","");
|
||||||
auto Id = GetParameter("id","");
|
auto Id = GetParameter("id","");
|
||||||
|
|
||||||
|
SecurityObjects::ActionLink Link;
|
||||||
|
if(!StorageService()->GetActionLink(Id,Link))
|
||||||
|
return DoReturnA404();
|
||||||
|
|
||||||
if(Action=="password_reset")
|
if(Action=="password_reset")
|
||||||
return RequestResetPassword(Id);
|
return RequestResetPassword(Link);
|
||||||
else if(Action=="email_verification")
|
else if(Action=="email_verification")
|
||||||
return DoEmailVerification(Id);
|
return DoEmailVerification(Link);
|
||||||
else
|
else
|
||||||
return DoReturnA404();
|
return DoReturnA404();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RESTAPI_action_links::DoPost() {
|
void RESTAPI_action_links::DoPost() {
|
||||||
auto Action = GetParameter("action","");
|
auto Action = GetParameter("action","");
|
||||||
auto Id = GetParameter("id","");
|
|
||||||
|
|
||||||
Logger_.information(Poco::format("COMPLETE-PASSWORD-RESET(%s): For ID=%s", Request->clientAddress().toString(), Id));
|
|
||||||
if(Action=="password_reset")
|
if(Action=="password_reset")
|
||||||
CompleteResetPassword(Id);
|
return CompleteResetPassword();
|
||||||
else
|
else
|
||||||
DoReturnA404();
|
return DoReturnA404();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RESTAPI_action_links::RequestResetPassword(std::string &Id) {
|
void RESTAPI_action_links::RequestResetPassword(SecurityObjects::ActionLink &Link) {
|
||||||
Logger_.information(Poco::format("REQUEST-PASSWORD-RESET(%s): For ID=%s", Request->clientAddress().toString(), Id));
|
Logger_.information(Poco::format("REQUEST-PASSWORD-RESET(%s): For ID=%s", Request->clientAddress().toString(), Link.userId));
|
||||||
Poco::File FormFile{ Daemon()->AssetDir() + "/password_reset.html"};
|
Poco::File FormFile{ Daemon()->AssetDir() + "/password_reset.html"};
|
||||||
Types::StringPairVec FormVars{ {"UUID", Id},
|
Types::StringPairVec FormVars{ {"UUID", Link.id},
|
||||||
{"PASSWORD_VALIDATION", AuthService()->PasswordValidationExpression()}};
|
{"PASSWORD_VALIDATION", AuthService()->PasswordValidationExpression()}};
|
||||||
SendHTMLFileBack(FormFile,FormVars);
|
SendHTMLFileBack(FormFile,FormVars);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RESTAPI_action_links::CompleteResetPassword(std::string &Id) {
|
void RESTAPI_action_links::CompleteResetPassword() {
|
||||||
// form has been posted...
|
// form has been posted...
|
||||||
RESTAPI_PartHandler PartHandler;
|
RESTAPI_PartHandler PartHandler;
|
||||||
Poco::Net::HTMLForm Form(*Request, Request->stream(), PartHandler);
|
Poco::Net::HTMLForm Form(*Request, Request->stream(), PartHandler);
|
||||||
if (!Form.empty()) {
|
if (!Form.empty()) {
|
||||||
|
|
||||||
auto Password1 = Form.get("password1","bla");
|
auto Password1 = Form.get("password1","bla");
|
||||||
auto Password2 = Form.get("password1","blu");
|
auto Password2 = Form.get("password1","blu");
|
||||||
Id = Form.get("id","");
|
auto Id = Form.get("id","");
|
||||||
|
auto Now = std::time(nullptr);
|
||||||
|
|
||||||
|
SecurityObjects::ActionLink Link;
|
||||||
|
if(!StorageService()->GetActionLink(Id,Link))
|
||||||
|
return DoReturnA404();
|
||||||
|
|
||||||
|
if(Now > Link.expires) {
|
||||||
|
StorageService()->CancelAction(Id);
|
||||||
|
return DoReturnA404();
|
||||||
|
}
|
||||||
|
|
||||||
if(Password1!=Password2 || !AuthService()->ValidatePassword(Password2) || !AuthService()->ValidatePassword(Password1)) {
|
if(Password1!=Password2 || !AuthService()->ValidatePassword(Password2) || !AuthService()->ValidatePassword(Password1)) {
|
||||||
Poco::File FormFile{ Daemon()->AssetDir() + "/password_reset_error.html"};
|
Poco::File FormFile{ Daemon()->AssetDir() + "/password_reset_error.html"};
|
||||||
Types::StringPairVec FormVars{ {"UUID", Id},
|
Types::StringPairVec FormVars{ {"UUID", Id},
|
||||||
@@ -62,7 +77,7 @@ namespace OpenWifi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SecurityObjects::UserInfo UInfo;
|
SecurityObjects::UserInfo UInfo;
|
||||||
if(!StorageService()->GetUserById(Id,UInfo)) {
|
if(!StorageService()->GetUserById(Link.userId,UInfo)) {
|
||||||
Poco::File FormFile{ Daemon()->AssetDir() + "/password_reset_error.html"};
|
Poco::File FormFile{ Daemon()->AssetDir() + "/password_reset_error.html"};
|
||||||
Types::StringPairVec FormVars{ {"UUID", Id},
|
Types::StringPairVec FormVars{ {"UUID", Id},
|
||||||
{"ERROR_TEXT", "This request does not contain a valid user ID. Please contact your system administrator."}};
|
{"ERROR_TEXT", "This request does not contain a valid user ID. Please contact your system administrator."}};
|
||||||
@@ -82,37 +97,45 @@ namespace OpenWifi {
|
|||||||
{"ERROR_TEXT", "You cannot reuse one of your recent passwords."}};
|
{"ERROR_TEXT", "You cannot reuse one of your recent passwords."}};
|
||||||
return SendHTMLFileBack(FormFile,FormVars);
|
return SendHTMLFileBack(FormFile,FormVars);
|
||||||
}
|
}
|
||||||
StorageService()->UpdateUserInfo(UInfo.email,Id,UInfo);
|
StorageService()->UpdateUserInfo(UInfo.email,Link.userId,UInfo);
|
||||||
Poco::File FormFile{ Daemon()->AssetDir() + "/password_reset_success.html"};
|
Poco::File FormFile{ Daemon()->AssetDir() + "/password_reset_success.html"};
|
||||||
Types::StringPairVec FormVars{ {"UUID", Id},
|
Types::StringPairVec FormVars{ {"UUID", Id},
|
||||||
{"USERNAME", UInfo.email},
|
{"USERNAME", UInfo.email},
|
||||||
{"ACTION_LINK",MicroService::instance().GetUIURI()}};
|
{"ACTION_LINK",MicroService::instance().GetUIURI()}};
|
||||||
|
StorageService()->CompleteAction(Id);
|
||||||
SendHTMLFileBack(FormFile,FormVars);
|
SendHTMLFileBack(FormFile,FormVars);
|
||||||
} else {
|
} else {
|
||||||
DoReturnA404();
|
DoReturnA404();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RESTAPI_action_links::DoEmailVerification(std::string &Id) {
|
void RESTAPI_action_links::DoEmailVerification(SecurityObjects::ActionLink &Link) {
|
||||||
SecurityObjects::UserInfo UInfo;
|
auto Now = std::time(nullptr);
|
||||||
|
|
||||||
Logger_.information(Poco::format("EMAIL-VERIFICATION(%s): For ID=%s", Request->clientAddress().toString(), Id));
|
if(Now > Link.expires) {
|
||||||
if (!StorageService()->GetUserById(Id, UInfo)) {
|
StorageService()->CancelAction(Link.id);
|
||||||
Types::StringPairVec FormVars{{"UUID", Id},
|
return DoReturnA404();
|
||||||
|
}
|
||||||
|
|
||||||
|
SecurityObjects::UserInfo UInfo;
|
||||||
|
if (!StorageService()->GetUserById(Link.userId, UInfo)) {
|
||||||
|
Types::StringPairVec FormVars{{"UUID", Link.id},
|
||||||
{"ERROR_TEXT", "This does not appear to be a valid email verification link.."}};
|
{"ERROR_TEXT", "This does not appear to be a valid email verification link.."}};
|
||||||
Poco::File FormFile{Daemon()->AssetDir() + "/email_verification_error.html"};
|
Poco::File FormFile{Daemon()->AssetDir() + "/email_verification_error.html"};
|
||||||
return SendHTMLFileBack(FormFile, FormVars);
|
return SendHTMLFileBack(FormFile, FormVars);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Logger_.information(Poco::format("EMAIL-VERIFICATION(%s): For ID=%s", Request->clientAddress().toString(), UInfo.email));
|
||||||
UInfo.waitingForEmailCheck = false;
|
UInfo.waitingForEmailCheck = false;
|
||||||
UInfo.validated = true;
|
UInfo.validated = true;
|
||||||
UInfo.lastEmailCheck = std::time(nullptr);
|
UInfo.lastEmailCheck = std::time(nullptr);
|
||||||
UInfo.validationDate = std::time(nullptr);
|
UInfo.validationDate = std::time(nullptr);
|
||||||
StorageService()->UpdateUserInfo(UInfo.email, Id, UInfo);
|
StorageService()->UpdateUserInfo(UInfo.email, Link.userId, UInfo);
|
||||||
Types::StringPairVec FormVars{{"UUID", Id},
|
Types::StringPairVec FormVars{{"UUID", Link.id},
|
||||||
{"USERNAME", UInfo.email},
|
{"USERNAME", UInfo.email},
|
||||||
{"ACTION_LINK",MicroService::instance().GetUIURI()}};
|
{"ACTION_LINK",MicroService::instance().GetUIURI()}};
|
||||||
Poco::File FormFile{Daemon()->AssetDir() + "/email_verification_success.html"};
|
Poco::File FormFile{Daemon()->AssetDir() + "/email_verification_success.html"};
|
||||||
|
StorageService()->CompleteAction(Link.id);
|
||||||
SendHTMLFileBack(FormFile, FormVars);
|
SendHTMLFileBack(FormFile, FormVars);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,11 +19,12 @@ namespace OpenWifi {
|
|||||||
Poco::Net::HTTPRequest::HTTP_OPTIONS},
|
Poco::Net::HTTPRequest::HTTP_OPTIONS},
|
||||||
Server,
|
Server,
|
||||||
Internal,
|
Internal,
|
||||||
false) {}
|
false,
|
||||||
|
true, RateLimit{.Interval=1000,.MaxCalls=10}) {}
|
||||||
static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/actionLink"}; };
|
static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/actionLink"}; };
|
||||||
void RequestResetPassword(std::string &Id);
|
void RequestResetPassword(SecurityObjects::ActionLink &Link);
|
||||||
void CompleteResetPassword(std::string &Id);
|
void CompleteResetPassword();
|
||||||
void DoEmailVerification(std::string &Id);
|
void DoEmailVerification(SecurityObjects::ActionLink &Link);
|
||||||
void DoReturnA404();
|
void DoReturnA404();
|
||||||
|
|
||||||
void DoGet() final;
|
void DoGet() final;
|
||||||
|
|||||||
@@ -14,25 +14,41 @@
|
|||||||
#include "MFAServer.h"
|
#include "MFAServer.h"
|
||||||
#include "framework/RESTAPI_protocol.h"
|
#include "framework/RESTAPI_protocol.h"
|
||||||
#include "framework/MicroService.h"
|
#include "framework/MicroService.h"
|
||||||
|
#include "StorageService.h"
|
||||||
|
|
||||||
namespace OpenWifi {
|
namespace OpenWifi {
|
||||||
|
|
||||||
|
static void FilterCredentials(SecurityObjects::UserInfo & U) {
|
||||||
|
U.currentPassword.clear();
|
||||||
|
U.lastPasswords.clear();
|
||||||
|
U.oauthType.clear();
|
||||||
|
}
|
||||||
|
|
||||||
void RESTAPI_oauth2Handler::DoGet() {
|
void RESTAPI_oauth2Handler::DoGet() {
|
||||||
if (!IsAuthorized()) {
|
bool Expired = false;
|
||||||
return UnAuthorized("Not authorized.");
|
if (!IsAuthorized(Expired)) {
|
||||||
|
if(Expired)
|
||||||
|
return UnAuthorized(RESTAPI::Errors::ExpiredToken,EXPIRED_TOKEN);
|
||||||
|
return UnAuthorized(RESTAPI::Errors::MissingAuthenticationInformation);
|
||||||
}
|
}
|
||||||
bool GetMe = GetBoolParameter(RESTAPI::Protocol::ME, false);
|
bool GetMe = GetBoolParameter(RESTAPI::Protocol::ME, false);
|
||||||
if(GetMe) {
|
if(GetMe) {
|
||||||
Logger_.information(Poco::format("REQUEST-ME(%s): Request for %s", Request->clientAddress().toString(), UserInfo_.userinfo.email));
|
Logger_.information(Poco::format("REQUEST-ME(%s): Request for %s", Request->clientAddress().toString(), UserInfo_.userinfo.email));
|
||||||
Poco::JSON::Object Me;
|
Poco::JSON::Object Me;
|
||||||
UserInfo_.userinfo.to_json(Me);
|
SecurityObjects::UserInfo ReturnedUser = UserInfo_.userinfo;
|
||||||
|
FilterCredentials(ReturnedUser);
|
||||||
|
ReturnedUser.to_json(Me);
|
||||||
return ReturnObject(Me);
|
return ReturnObject(Me);
|
||||||
}
|
}
|
||||||
BadRequest("Ill-formed request. Please consult documentation.");
|
BadRequest(RESTAPI::Errors::UnrecognizedRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RESTAPI_oauth2Handler::DoDelete() {
|
void RESTAPI_oauth2Handler::DoDelete() {
|
||||||
if (!IsAuthorized()) {
|
bool Expired = false;
|
||||||
return UnAuthorized("Not authorized.");
|
if (!IsAuthorized(Expired)) {
|
||||||
|
if(Expired)
|
||||||
|
return UnAuthorized(RESTAPI::Errors::ExpiredToken,EXPIRED_TOKEN);
|
||||||
|
return UnAuthorized(RESTAPI::Errors::MissingAuthenticationInformation);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Token = GetBinding(RESTAPI::Protocol::TOKEN, "...");
|
auto Token = GetBinding(RESTAPI::Protocol::TOKEN, "...");
|
||||||
@@ -63,15 +79,31 @@ namespace OpenWifi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(GetBoolParameter(RESTAPI::Protocol::FORGOTPASSWORD,false)) {
|
if(GetBoolParameter(RESTAPI::Protocol::FORGOTPASSWORD,false)) {
|
||||||
// Send an email to the userId
|
SecurityObjects::UserInfo UInfo1;
|
||||||
|
auto UserExists = StorageService()->GetUserByEmail(userId,UInfo1);
|
||||||
|
if(UserExists) {
|
||||||
Logger_.information(Poco::format("FORGOTTEN-PASSWORD(%s): Request for %s", Request->clientAddress().toString(), userId));
|
Logger_.information(Poco::format("FORGOTTEN-PASSWORD(%s): Request for %s", Request->clientAddress().toString(), userId));
|
||||||
SecurityObjects::UserInfoAndPolicy UInfo;
|
SecurityObjects::ActionLink NewLink;
|
||||||
if(AuthService::SendEmailToUser(userId,AuthService::FORGOT_PASSWORD))
|
|
||||||
Logger_.information(Poco::format("Send password reset link to %s",userId));
|
NewLink.action = OpenWifi::SecurityObjects::LinkActions::FORGOT_PASSWORD;
|
||||||
UInfo.webtoken.userMustChangePassword=true;
|
NewLink.id = MicroService::CreateUUID();
|
||||||
|
NewLink.userId = UInfo1.Id;
|
||||||
|
NewLink.created = std::time(nullptr);
|
||||||
|
NewLink.expires = NewLink.created + (24*60*60);
|
||||||
|
StorageService()->CreateAction(NewLink);
|
||||||
|
|
||||||
Poco::JSON::Object ReturnObj;
|
Poco::JSON::Object ReturnObj;
|
||||||
|
SecurityObjects::UserInfoAndPolicy UInfo;
|
||||||
|
UInfo.webtoken.userMustChangePassword = true;
|
||||||
UInfo.webtoken.to_json(ReturnObj);
|
UInfo.webtoken.to_json(ReturnObj);
|
||||||
return ReturnObject(ReturnObj);
|
return ReturnObject(ReturnObj);
|
||||||
|
} else {
|
||||||
|
Poco::JSON::Object ReturnObj;
|
||||||
|
SecurityObjects::UserInfoAndPolicy UInfo;
|
||||||
|
UInfo.webtoken.userMustChangePassword = true;
|
||||||
|
UInfo.webtoken.to_json(ReturnObj);
|
||||||
|
return ReturnObject(ReturnObj);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(GetBoolParameter(RESTAPI::Protocol::RESENDMFACODE,false)) {
|
if(GetBoolParameter(RESTAPI::Protocol::RESENDMFACODE,false)) {
|
||||||
@@ -80,9 +112,8 @@ namespace OpenWifi {
|
|||||||
auto uuid = Obj->get("uuid").toString();
|
auto uuid = Obj->get("uuid").toString();
|
||||||
if(MFAServer().ResendCode(uuid))
|
if(MFAServer().ResendCode(uuid))
|
||||||
return OK();
|
return OK();
|
||||||
return UnAuthorized("Unrecognized credentials (username/password).");
|
|
||||||
}
|
}
|
||||||
return UnAuthorized("Unrecognized credentials (username/password).");
|
return UnAuthorized(RESTAPI::Errors::InvalidCredentials);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(GetBoolParameter(RESTAPI::Protocol::COMPLETEMFACHALLENGE,false)) {
|
if(GetBoolParameter(RESTAPI::Protocol::COMPLETEMFACHALLENGE,false)) {
|
||||||
@@ -95,29 +126,37 @@ namespace OpenWifi {
|
|||||||
return ReturnObject(ReturnObj);
|
return ReturnObject(ReturnObj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return UnAuthorized("Unrecognized credentials (username/password).");
|
return UnAuthorized(RESTAPI::Errors::InvalidCredentials);
|
||||||
}
|
}
|
||||||
|
|
||||||
SecurityObjects::UserInfoAndPolicy UInfo;
|
SecurityObjects::UserInfoAndPolicy UInfo;
|
||||||
auto Code=AuthService()->Authorize(userId, password, newPassword, UInfo);
|
bool Expired=false;
|
||||||
if (Code==AuthService::SUCCESS) {
|
auto Code=AuthService()->Authorize(userId, password, newPassword, UInfo, Expired);
|
||||||
|
if (Code==SUCCESS) {
|
||||||
Poco::JSON::Object ReturnObj;
|
Poco::JSON::Object ReturnObj;
|
||||||
if(AuthService()->RequiresMFA(UInfo)) {
|
if(AuthService()->RequiresMFA(UInfo)) {
|
||||||
if(MFAServer().StartMFAChallenge(UInfo, ReturnObj)) {
|
if(MFAServer().StartMFAChallenge(UInfo, ReturnObj)) {
|
||||||
return ReturnObject(ReturnObj);
|
return ReturnObject(ReturnObj);
|
||||||
}
|
}
|
||||||
Logger_.warning("MFA Seems ot be broken. Please fix. Disabling MFA checking for now.");
|
Logger_.warning("MFA Seems to be broken. Please fix. Disabling MFA checking for now.");
|
||||||
}
|
}
|
||||||
UInfo.webtoken.to_json(ReturnObj);
|
UInfo.webtoken.to_json(ReturnObj);
|
||||||
return ReturnObject(ReturnObj);
|
return ReturnObject(ReturnObj);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
switch(Code) {
|
switch(Code) {
|
||||||
case AuthService::INVALID_CREDENTIALS: return UnAuthorized("Unrecognized credentials (username/password)."); break;
|
case INVALID_CREDENTIALS:
|
||||||
case AuthService::PASSWORD_INVALID: return UnAuthorized("Invalid password."); break;
|
return UnAuthorized(RESTAPI::Errors::InvalidCredentials, Code);
|
||||||
case AuthService::PASSWORD_ALREADY_USED: return UnAuthorized("Password already used previously."); break;
|
case PASSWORD_INVALID:
|
||||||
case AuthService::USERNAME_PENDING_VERIFICATION: return UnAuthorized("User access pending email verification."); break;
|
return UnAuthorized(RESTAPI::Errors::InvalidPassword, Code);
|
||||||
case AuthService::PASSWORD_CHANGE_REQUIRED: return UnAuthorized("Password change expected."); break;
|
case PASSWORD_ALREADY_USED:
|
||||||
default: return UnAuthorized("Unrecognized credentials (username/password)."); break;
|
return UnAuthorized(RESTAPI::Errors::PasswordRejected, Code);
|
||||||
|
case USERNAME_PENDING_VERIFICATION:
|
||||||
|
return UnAuthorized(RESTAPI::Errors::UserPendingVerification, Code);
|
||||||
|
case PASSWORD_CHANGE_REQUIRED:
|
||||||
|
return UnAuthorized(RESTAPI::Errors::PasswordMustBeChanged, Code);
|
||||||
|
default:
|
||||||
|
return UnAuthorized(RESTAPI::Errors::InvalidCredentials); break;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ namespace OpenWifi {
|
|||||||
Poco::Net::HTTPRequest::HTTP_GET,
|
Poco::Net::HTTPRequest::HTTP_GET,
|
||||||
Poco::Net::HTTPRequest::HTTP_OPTIONS},
|
Poco::Net::HTTPRequest::HTTP_OPTIONS},
|
||||||
Server,
|
Server,
|
||||||
Internal, false) {}
|
Internal, false, true , RateLimit{.Interval=1000,.MaxCalls=10}) {}
|
||||||
static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/oauth2/{token}","/api/v1/oauth2"}; };
|
static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/oauth2/{token}","/api/v1/oauth2"}; };
|
||||||
void DoGet() final;
|
void DoGet() final;
|
||||||
void DoPost() final;
|
void DoPost() final;
|
||||||
|
|||||||
@@ -7,8 +7,16 @@
|
|||||||
#include "Poco/JSON/Parser.h"
|
#include "Poco/JSON/Parser.h"
|
||||||
#include "framework/RESTAPI_errors.h"
|
#include "framework/RESTAPI_errors.h"
|
||||||
#include "SMSSender.h"
|
#include "SMSSender.h"
|
||||||
|
#include "ACLProcessor.h"
|
||||||
|
|
||||||
namespace OpenWifi {
|
namespace OpenWifi {
|
||||||
|
|
||||||
|
static void FilterCredentials(SecurityObjects::UserInfo & U) {
|
||||||
|
U.currentPassword.clear();
|
||||||
|
U.lastPasswords.clear();
|
||||||
|
U.oauthType.clear();
|
||||||
|
}
|
||||||
|
|
||||||
void RESTAPI_user_handler::DoGet() {
|
void RESTAPI_user_handler::DoGet() {
|
||||||
std::string Id = GetBinding("id", "");
|
std::string Id = GetBinding("id", "");
|
||||||
if(Id.empty()) {
|
if(Id.empty()) {
|
||||||
@@ -25,7 +33,9 @@ namespace OpenWifi {
|
|||||||
} else if(!StorageService()->GetUserById(Id,UInfo)) {
|
} else if(!StorageService()->GetUserById(Id,UInfo)) {
|
||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
Poco::JSON::Object UserInfoObject;
|
Poco::JSON::Object UserInfoObject;
|
||||||
|
FilterCredentials(UInfo);
|
||||||
UInfo.to_json(UserInfoObject);
|
UInfo.to_json(UserInfoObject);
|
||||||
ReturnObject(UserInfoObject);
|
ReturnObject(UserInfoObject);
|
||||||
}
|
}
|
||||||
@@ -41,12 +51,20 @@ namespace OpenWifi {
|
|||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!ACLProcessor::Can(UserInfo_.userinfo, UInfo,ACLProcessor::DELETE)) {
|
||||||
|
return UnAuthorized(RESTAPI::Errors::InsufficientAccessRights, ACCESS_DENIED);
|
||||||
|
}
|
||||||
|
|
||||||
if(!StorageService()->DeleteUser(UserInfo_.userinfo.email,Id)) {
|
if(!StorageService()->DeleteUser(UserInfo_.userinfo.email,Id)) {
|
||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(AuthService()->DeleteUserFromCache(UInfo.email))
|
if(AuthService()->DeleteUserFromCache(UInfo.email)) {
|
||||||
;
|
// nothing to do
|
||||||
|
}
|
||||||
|
|
||||||
|
StorageService()->DeleteAvatar(UserInfo_.userinfo.email,Id);
|
||||||
|
|
||||||
Logger_.information(Poco::format("Remove all tokens for '%s'", UserInfo_.userinfo.email));
|
Logger_.information(Poco::format("Remove all tokens for '%s'", UserInfo_.userinfo.email));
|
||||||
StorageService()->RevokeAllTokens(UInfo.email);
|
StorageService()->RevokeAllTokens(UInfo.email);
|
||||||
Logger_.information(Poco::format("User '%s' deleted by '%s'.",Id,UserInfo_.userinfo.email));
|
Logger_.information(Poco::format("User '%s' deleted by '%s'.",Id,UserInfo_.userinfo.email));
|
||||||
@@ -59,49 +77,52 @@ namespace OpenWifi {
|
|||||||
return BadRequest(RESTAPI::Errors::IdMustBe0);
|
return BadRequest(RESTAPI::Errors::IdMustBe0);
|
||||||
}
|
}
|
||||||
|
|
||||||
SecurityObjects::UserInfo UInfo;
|
SecurityObjects::UserInfo NewUser;
|
||||||
RESTAPI_utils::from_request(UInfo,*Request);
|
RESTAPI_utils::from_request(NewUser,*Request);
|
||||||
|
|
||||||
if(UInfo.userRole == SecurityObjects::UNKNOWN) {
|
if(NewUser.userRole == SecurityObjects::UNKNOWN) {
|
||||||
return BadRequest(RESTAPI::Errors::InvalidUserRole);
|
return BadRequest(RESTAPI::Errors::InvalidUserRole);
|
||||||
}
|
}
|
||||||
|
|
||||||
Poco::toLowerInPlace(UInfo.email);
|
if(!ACLProcessor::Can(UserInfo_.userinfo,NewUser,ACLProcessor::CREATE)) {
|
||||||
if(!Utils::ValidEMailAddress(UInfo.email)) {
|
return UnAuthorized("Insufficient access rights.", ACCESS_DENIED);
|
||||||
|
}
|
||||||
|
|
||||||
|
Poco::toLowerInPlace(NewUser.email);
|
||||||
|
if(!Utils::ValidEMailAddress(NewUser.email)) {
|
||||||
return BadRequest(RESTAPI::Errors::InvalidEmailAddress);
|
return BadRequest(RESTAPI::Errors::InvalidEmailAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!UInfo.currentPassword.empty()) {
|
if(!NewUser.currentPassword.empty()) {
|
||||||
if(!AuthService()->ValidatePassword(UInfo.currentPassword)) {
|
if(!AuthService()->ValidatePassword(NewUser.currentPassword)) {
|
||||||
return BadRequest(RESTAPI::Errors::InvalidPassword);
|
return BadRequest(RESTAPI::Errors::InvalidPassword);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(UInfo.name.empty())
|
if(NewUser.name.empty())
|
||||||
UInfo.name = UInfo.email;
|
NewUser.name = NewUser.email;
|
||||||
|
|
||||||
if(!StorageService()->CreateUser(UInfo.email,UInfo)) {
|
if(!StorageService()->CreateUser(NewUser.email,NewUser)) {
|
||||||
Logger_.information(Poco::format("Could not add user '%s'.",UInfo.email));
|
Logger_.information(Poco::format("Could not add user '%s'.",NewUser.email));
|
||||||
return BadRequest(RESTAPI::Errors::RecordNotCreated);
|
return BadRequest(RESTAPI::Errors::RecordNotCreated);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(GetParameter("email_verification","false")=="true") {
|
if(GetParameter("email_verification","false")=="true") {
|
||||||
if(AuthService::VerifyEmail(UInfo))
|
if(AuthService::VerifyEmail(NewUser))
|
||||||
Logger_.information(Poco::format("Verification e-mail requested for %s",UInfo.email));
|
Logger_.information(Poco::format("Verification e-mail requested for %s",NewUser.email));
|
||||||
StorageService()->UpdateUserInfo(UserInfo_.userinfo.email,UInfo.Id,UInfo);
|
StorageService()->UpdateUserInfo(UserInfo_.userinfo.email,NewUser.Id,NewUser);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!StorageService()->GetUserByEmail(UInfo.email, UInfo)) {
|
if(!StorageService()->GetUserByEmail(NewUser.email, NewUser)) {
|
||||||
Logger_.information(Poco::format("User '%s' but not retrieved.",UInfo.email));
|
Logger_.information(Poco::format("User '%s' but not retrieved.",NewUser.email));
|
||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
Poco::JSON::Object UserInfoObject;
|
Poco::JSON::Object UserInfoObject;
|
||||||
UInfo.to_json(UserInfoObject);
|
FilterCredentials(NewUser);
|
||||||
|
NewUser.to_json(UserInfoObject);
|
||||||
ReturnObject(UserInfoObject);
|
ReturnObject(UserInfoObject);
|
||||||
|
Logger_.information(Poco::format("User '%s' has been added by '%s')",NewUser.email, UserInfo_.userinfo.email));
|
||||||
Logger_.information(Poco::format("User '%s' has been added by '%s')",UInfo.email, UserInfo_.userinfo.email));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RESTAPI_user_handler::DoPut() {
|
void RESTAPI_user_handler::DoPut() {
|
||||||
@@ -115,6 +136,10 @@ namespace OpenWifi {
|
|||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!ACLProcessor::Can(UserInfo_.userinfo,Existing,ACLProcessor::MODIFY)) {
|
||||||
|
return UnAuthorized("Insufficient access rights.", ACCESS_DENIED);
|
||||||
|
}
|
||||||
|
|
||||||
SecurityObjects::UserInfo NewUser;
|
SecurityObjects::UserInfo NewUser;
|
||||||
auto RawObject = ParseStream();
|
auto RawObject = ParseStream();
|
||||||
if(!NewUser.from_json(RawObject)) {
|
if(!NewUser.from_json(RawObject)) {
|
||||||
@@ -136,8 +161,19 @@ namespace OpenWifi {
|
|||||||
AssignIfPresent(RawObject,"suspended", Existing.suspended);
|
AssignIfPresent(RawObject,"suspended", Existing.suspended);
|
||||||
AssignIfPresent(RawObject,"blackListed", Existing.blackListed);
|
AssignIfPresent(RawObject,"blackListed", Existing.blackListed);
|
||||||
|
|
||||||
if(RawObject->has("userRole"))
|
if(RawObject->has("userRole")) {
|
||||||
Existing.userRole = SecurityObjects::UserTypeFromString(RawObject->get("userRole").toString());
|
auto NewRole = SecurityObjects::UserTypeFromString(RawObject->get("userRole").toString());
|
||||||
|
if(NewRole!=Existing.userRole) {
|
||||||
|
if(UserInfo_.userinfo.userRole!=SecurityObjects::ROOT && NewRole==SecurityObjects::ROOT) {
|
||||||
|
return UnAuthorized(RESTAPI::Errors::InsufficientAccessRights, ACCESS_DENIED);
|
||||||
|
}
|
||||||
|
if(Id==UserInfo_.userinfo.Id) {
|
||||||
|
return UnAuthorized(RESTAPI::Errors::InsufficientAccessRights, ACCESS_DENIED);
|
||||||
|
}
|
||||||
|
Existing.userRole = NewRole;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(RawObject->has("notes")) {
|
if(RawObject->has("notes")) {
|
||||||
SecurityObjects::NoteInfoVec NIV;
|
SecurityObjects::NoteInfoVec NIV;
|
||||||
NIV = RESTAPI_utils::to_object_array<SecurityObjects::NoteInfo>(RawObject->get("notes").toString());
|
NIV = RESTAPI_utils::to_object_array<SecurityObjects::NoteInfo>(RawObject->get("notes").toString());
|
||||||
@@ -161,26 +197,34 @@ namespace OpenWifi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(RawObject->has("userTypeProprietaryInfo")) {
|
if(RawObject->has("userTypeProprietaryInfo")) {
|
||||||
|
bool ChangingMFA = NewUser.userTypeProprietaryInfo.mfa.enabled && !Existing.userTypeProprietaryInfo.mfa.enabled;
|
||||||
|
|
||||||
Existing.userTypeProprietaryInfo.mfa.enabled = NewUser.userTypeProprietaryInfo.mfa.enabled;
|
Existing.userTypeProprietaryInfo.mfa.enabled = NewUser.userTypeProprietaryInfo.mfa.enabled;
|
||||||
if(NewUser.userTypeProprietaryInfo.mfa.method=="sms") {
|
|
||||||
Existing.userTypeProprietaryInfo.mfa.method=NewUser.userTypeProprietaryInfo.mfa.method;
|
auto PropInfo = RawObject->get("userTypeProprietaryInfo");
|
||||||
auto MobileStruct = RawObject->get("userTypeProprietaryInfo");
|
auto PInfo = PropInfo.extract<Poco::JSON::Object::Ptr>();
|
||||||
auto Info = MobileStruct.extract<Poco::JSON::Object::Ptr>();
|
|
||||||
if(Info->isArray("mobiles")) {
|
if(PInfo->isArray("mobiles")) {
|
||||||
Existing.userTypeProprietaryInfo.mobiles = NewUser.userTypeProprietaryInfo.mobiles;
|
Existing.userTypeProprietaryInfo.mobiles = NewUser.userTypeProprietaryInfo.mobiles;
|
||||||
}
|
}
|
||||||
if(!NewUser.userTypeProprietaryInfo.mobiles.empty() && !SMSSender()->IsNumberValid(NewUser.userTypeProprietaryInfo.mobiles[0].number,UserInfo_.userinfo.email)){
|
|
||||||
|
if(ChangingMFA && !NewUser.userTypeProprietaryInfo.mobiles.empty() && !SMSSender()->IsNumberValid(NewUser.userTypeProprietaryInfo.mobiles[0].number,UserInfo_.userinfo.email)){
|
||||||
return BadRequest(RESTAPI::Errors::NeedMobileNumber);
|
return BadRequest(RESTAPI::Errors::NeedMobileNumber);
|
||||||
}
|
}
|
||||||
if(NewUser.userTypeProprietaryInfo.mfa.enabled && Existing.userTypeProprietaryInfo.mobiles.empty()) {
|
|
||||||
|
if(NewUser.userTypeProprietaryInfo.mfa.method=="sms" && Existing.userTypeProprietaryInfo.mobiles.empty()) {
|
||||||
return BadRequest(RESTAPI::Errors::NeedMobileNumber);
|
return BadRequest(RESTAPI::Errors::NeedMobileNumber);
|
||||||
}
|
}
|
||||||
} else if(NewUser.userTypeProprietaryInfo.mfa.method=="email") {
|
|
||||||
|
if(!NewUser.userTypeProprietaryInfo.mfa.method.empty()) {
|
||||||
|
if(NewUser.userTypeProprietaryInfo.mfa.method!="email" && NewUser.userTypeProprietaryInfo.mfa.method!="sms" ) {
|
||||||
|
return BadRequest("Unknown MFA method");
|
||||||
|
}
|
||||||
Existing.userTypeProprietaryInfo.mfa.method=NewUser.userTypeProprietaryInfo.mfa.method;
|
Existing.userTypeProprietaryInfo.mfa.method=NewUser.userTypeProprietaryInfo.mfa.method;
|
||||||
} else {
|
|
||||||
if(NewUser.userTypeProprietaryInfo.mfa.enabled && Existing.userTypeProprietaryInfo.mfa.method.empty()) {
|
|
||||||
return BadRequest(RESTAPI::Errors::BadMFAMethod);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(Existing.userTypeProprietaryInfo.mfa.enabled && Existing.userTypeProprietaryInfo.mfa.method.empty()) {
|
||||||
|
return BadRequest("Illegal MFA method");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,6 +232,7 @@ namespace OpenWifi {
|
|||||||
SecurityObjects::UserInfo NewUserInfo;
|
SecurityObjects::UserInfo NewUserInfo;
|
||||||
StorageService()->GetUserByEmail(UserInfo_.userinfo.email,NewUserInfo);
|
StorageService()->GetUserByEmail(UserInfo_.userinfo.email,NewUserInfo);
|
||||||
Poco::JSON::Object ModifiedObject;
|
Poco::JSON::Object ModifiedObject;
|
||||||
|
FilterCredentials(NewUserInfo);
|
||||||
NewUserInfo.to_json(ModifiedObject);
|
NewUserInfo.to_json(ModifiedObject);
|
||||||
return ReturnObject(ModifiedObject);
|
return ReturnObject(ModifiedObject);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,11 +16,14 @@ namespace OpenWifi {
|
|||||||
Poco::JSON::Array ArrayObj;
|
Poco::JSON::Array ArrayObj;
|
||||||
Poco::JSON::Object Answer;
|
Poco::JSON::Object Answer;
|
||||||
if (StorageService()->GetUsers(QB_.Offset, QB_.Limit, Users)) {
|
if (StorageService()->GetUsers(QB_.Offset, QB_.Limit, Users)) {
|
||||||
for (const auto &i : Users) {
|
for (auto &i : Users) {
|
||||||
Poco::JSON::Object Obj;
|
Poco::JSON::Object Obj;
|
||||||
if (IdOnly) {
|
if (IdOnly) {
|
||||||
ArrayObj.add(i.Id);
|
ArrayObj.add(i.Id);
|
||||||
} else {
|
} else {
|
||||||
|
i.currentPassword.clear();
|
||||||
|
i.lastPasswords.clear();
|
||||||
|
i.oauthType.clear();
|
||||||
i.to_json(Obj);
|
i.to_json(Obj);
|
||||||
ArrayObj.add(Obj);
|
ArrayObj.add(Obj);
|
||||||
}
|
}
|
||||||
@@ -38,6 +41,9 @@ namespace OpenWifi {
|
|||||||
if (IdOnly) {
|
if (IdOnly) {
|
||||||
ArrayObj.add(UInfo.Id);
|
ArrayObj.add(UInfo.Id);
|
||||||
} else {
|
} else {
|
||||||
|
UInfo.currentPassword.clear();
|
||||||
|
UInfo.lastPasswords.clear();
|
||||||
|
UInfo.oauthType.clear();
|
||||||
UInfo.to_json(Obj);
|
UInfo.to_json(Obj);
|
||||||
ArrayObj.add(Obj);
|
ArrayObj.add(Obj);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,8 @@ namespace OpenWifi {
|
|||||||
if (i.first == "token") {
|
if (i.first == "token") {
|
||||||
// can we find this token?
|
// can we find this token?
|
||||||
SecurityObjects::UserInfoAndPolicy SecObj;
|
SecurityObjects::UserInfoAndPolicy SecObj;
|
||||||
if (AuthService()->IsValidToken(i.second, SecObj.webtoken, SecObj.userinfo)) {
|
bool Expired = false;
|
||||||
|
if (AuthService()->IsValidToken(i.second, SecObj.webtoken, SecObj.userinfo, Expired)) {
|
||||||
Poco::JSON::Object Obj;
|
Poco::JSON::Object Obj;
|
||||||
SecObj.to_json(Obj);
|
SecObj.to_json(Obj);
|
||||||
return ReturnObject(Obj);
|
return ReturnObject(Obj);
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ namespace OpenWifi::GWObjects {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Device::from_json(Poco::JSON::Object::Ptr Obj) {
|
bool Device::from_json(Poco::JSON::Object::Ptr &Obj) {
|
||||||
try {
|
try {
|
||||||
field_from_json(Obj,"serialNumber",SerialNumber);
|
field_from_json(Obj,"serialNumber",SerialNumber);
|
||||||
field_from_json(Obj,"deviceType",DeviceType);
|
field_from_json(Obj,"deviceType",DeviceType);
|
||||||
@@ -147,7 +147,7 @@ namespace OpenWifi::GWObjects {
|
|||||||
field_to_json(Obj,"attachFile", AttachDate);
|
field_to_json(Obj,"attachFile", AttachDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DefaultConfiguration::from_json(Poco::JSON::Object::Ptr Obj) {
|
bool DefaultConfiguration::from_json(Poco::JSON::Object::Ptr &Obj) {
|
||||||
try {
|
try {
|
||||||
field_from_json(Obj,"name",Name);
|
field_from_json(Obj,"name",Name);
|
||||||
field_from_json(Obj,"configuration",Configuration);
|
field_from_json(Obj,"configuration",Configuration);
|
||||||
@@ -166,7 +166,7 @@ namespace OpenWifi::GWObjects {
|
|||||||
field_to_json(Obj,"created", created);
|
field_to_json(Obj,"created", created);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BlackListedDevice::from_json(Poco::JSON::Object::Ptr Obj) {
|
bool BlackListedDevice::from_json(Poco::JSON::Object::Ptr &Obj) {
|
||||||
try {
|
try {
|
||||||
field_from_json(Obj,"serialNumber",serialNumber);
|
field_from_json(Obj,"serialNumber",serialNumber);
|
||||||
field_from_json(Obj,"author",author);
|
field_from_json(Obj,"author",author);
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ namespace OpenWifi::GWObjects {
|
|||||||
std::string DevicePassword;
|
std::string DevicePassword;
|
||||||
void to_json(Poco::JSON::Object &Obj) const;
|
void to_json(Poco::JSON::Object &Obj) const;
|
||||||
void to_json_with_status(Poco::JSON::Object &Obj) const;
|
void to_json_with_status(Poco::JSON::Object &Obj) const;
|
||||||
bool from_json(Poco::JSON::Object::Ptr Obj);
|
bool from_json(Poco::JSON::Object::Ptr &Obj);
|
||||||
void Print() const;
|
void Print() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -116,7 +116,7 @@ namespace OpenWifi::GWObjects {
|
|||||||
uint64_t Created;
|
uint64_t Created;
|
||||||
uint64_t LastModified;
|
uint64_t LastModified;
|
||||||
void to_json(Poco::JSON::Object &Obj) const;
|
void to_json(Poco::JSON::Object &Obj) const;
|
||||||
bool from_json(Poco::JSON::Object::Ptr Obj);
|
bool from_json(Poco::JSON::Object::Ptr &Obj);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CommandDetails {
|
struct CommandDetails {
|
||||||
@@ -147,7 +147,7 @@ namespace OpenWifi::GWObjects {
|
|||||||
std::string author;
|
std::string author;
|
||||||
uint64_t created;
|
uint64_t created;
|
||||||
void to_json(Poco::JSON::Object &Obj) const;
|
void to_json(Poco::JSON::Object &Obj) const;
|
||||||
bool from_json(Poco::JSON::Object::Ptr Obj);
|
bool from_json(Poco::JSON::Object::Ptr &Obj);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RttySessionDetails {
|
struct RttySessionDetails {
|
||||||
|
|||||||
@@ -10,27 +10,30 @@
|
|||||||
#include "RESTAPI_ProvObjects.h"
|
#include "RESTAPI_ProvObjects.h"
|
||||||
#include "framework/MicroService.h"
|
#include "framework/MicroService.h"
|
||||||
|
|
||||||
|
using OpenWifi::RESTAPI_utils::field_to_json;
|
||||||
|
using OpenWifi::RESTAPI_utils::field_from_json;
|
||||||
|
|
||||||
namespace OpenWifi::ProvObjects {
|
namespace OpenWifi::ProvObjects {
|
||||||
|
|
||||||
void ObjectInfo::to_json(Poco::JSON::Object &Obj) const {
|
void ObjectInfo::to_json(Poco::JSON::Object &Obj) const {
|
||||||
RESTAPI_utils::field_to_json(Obj,"id",id);
|
field_to_json(Obj,"id",id);
|
||||||
RESTAPI_utils::field_to_json(Obj,"name",name);
|
field_to_json(Obj,"name",name);
|
||||||
RESTAPI_utils::field_to_json(Obj,"description",description);
|
field_to_json(Obj,"description",description);
|
||||||
RESTAPI_utils::field_to_json(Obj,"created",created);
|
field_to_json(Obj,"created",created);
|
||||||
RESTAPI_utils::field_to_json(Obj,"modified",modified);
|
field_to_json(Obj,"modified",modified);
|
||||||
RESTAPI_utils::field_to_json(Obj,"notes",notes);
|
field_to_json(Obj,"notes",notes);
|
||||||
RESTAPI_utils::field_to_json(Obj,"tags",tags);
|
field_to_json(Obj,"tags",tags);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ObjectInfo::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
bool ObjectInfo::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||||
try {
|
try {
|
||||||
RESTAPI_utils::field_from_json(Obj,"id",id);
|
field_from_json(Obj,"id",id);
|
||||||
RESTAPI_utils::field_from_json(Obj,"name",name);
|
field_from_json(Obj,"name",name);
|
||||||
RESTAPI_utils::field_from_json(Obj,"description",description);
|
field_from_json(Obj,"description",description);
|
||||||
RESTAPI_utils::field_from_json(Obj,"created",created);
|
field_from_json(Obj,"created",created);
|
||||||
RESTAPI_utils::field_from_json(Obj,"modified",modified);
|
field_from_json(Obj,"modified",modified);
|
||||||
RESTAPI_utils::field_from_json(Obj,"notes",notes);
|
field_from_json(Obj,"notes",notes);
|
||||||
RESTAPI_utils::field_from_json(Obj,"tags",tags);
|
field_from_json(Obj,"tags",tags);
|
||||||
return true;
|
return true;
|
||||||
} catch(...) {
|
} catch(...) {
|
||||||
|
|
||||||
@@ -39,18 +42,18 @@ namespace OpenWifi::ProvObjects {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ManagementPolicyEntry::to_json(Poco::JSON::Object &Obj) const {
|
void ManagementPolicyEntry::to_json(Poco::JSON::Object &Obj) const {
|
||||||
RESTAPI_utils::field_to_json( Obj,"users",users);
|
field_to_json( Obj,"users",users);
|
||||||
RESTAPI_utils::field_to_json( Obj,"resources",resources);
|
field_to_json( Obj,"resources",resources);
|
||||||
RESTAPI_utils::field_to_json( Obj,"access",access);
|
field_to_json( Obj,"access",access);
|
||||||
RESTAPI_utils::field_to_json( Obj,"policy",policy);
|
field_to_json( Obj,"policy",policy);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ManagementPolicyEntry::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
bool ManagementPolicyEntry::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||||
try {
|
try {
|
||||||
RESTAPI_utils::field_from_json( Obj,"users",users);
|
field_from_json( Obj,"users",users);
|
||||||
RESTAPI_utils::field_from_json( Obj,"resources",resources);
|
field_from_json( Obj,"resources",resources);
|
||||||
RESTAPI_utils::field_from_json( Obj,"access",access);
|
field_from_json( Obj,"access",access);
|
||||||
RESTAPI_utils::field_from_json( Obj,"policy",policy);
|
field_from_json( Obj,"policy",policy);
|
||||||
return true;
|
return true;
|
||||||
} catch(...) {
|
} catch(...) {
|
||||||
|
|
||||||
@@ -60,17 +63,17 @@ namespace OpenWifi::ProvObjects {
|
|||||||
|
|
||||||
void ManagementPolicy::to_json(Poco::JSON::Object &Obj) const {
|
void ManagementPolicy::to_json(Poco::JSON::Object &Obj) const {
|
||||||
info.to_json(Obj);
|
info.to_json(Obj);
|
||||||
RESTAPI_utils::field_to_json(Obj, "entries", entries);
|
field_to_json(Obj, "entries", entries);
|
||||||
RESTAPI_utils::field_to_json(Obj, "inUse", inUse);
|
field_to_json(Obj, "inUse", inUse);
|
||||||
RESTAPI_utils::field_to_json(Obj, "entity", entity);
|
field_to_json(Obj, "entity", entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ManagementPolicy::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
bool ManagementPolicy::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||||
try {
|
try {
|
||||||
info.from_json(Obj);
|
info.from_json(Obj);
|
||||||
RESTAPI_utils::field_from_json(Obj, "entries", entries);
|
field_from_json(Obj, "entries", entries);
|
||||||
RESTAPI_utils::field_from_json(Obj, "inUse", inUse);
|
field_from_json(Obj, "inUse", inUse);
|
||||||
RESTAPI_utils::field_from_json(Obj, "entity", entity);
|
field_from_json(Obj, "entity", entity);
|
||||||
return true;
|
return true;
|
||||||
} catch(...) {
|
} catch(...) {
|
||||||
|
|
||||||
@@ -80,31 +83,31 @@ namespace OpenWifi::ProvObjects {
|
|||||||
|
|
||||||
void Entity::to_json(Poco::JSON::Object &Obj) const {
|
void Entity::to_json(Poco::JSON::Object &Obj) const {
|
||||||
info.to_json(Obj);
|
info.to_json(Obj);
|
||||||
RESTAPI_utils::field_to_json( Obj,"parent",parent);
|
field_to_json( Obj,"parent",parent);
|
||||||
RESTAPI_utils::field_to_json( Obj,"venues",venues);
|
field_to_json( Obj,"venues",venues);
|
||||||
RESTAPI_utils::field_to_json( Obj,"children",children);
|
field_to_json( Obj,"children",children);
|
||||||
RESTAPI_utils::field_to_json( Obj,"contacts",contacts);
|
field_to_json( Obj,"contacts",contacts);
|
||||||
RESTAPI_utils::field_to_json( Obj,"locations",locations);
|
field_to_json( Obj,"locations",locations);
|
||||||
RESTAPI_utils::field_to_json( Obj,"managementPolicy",managementPolicy);
|
field_to_json( Obj,"managementPolicy",managementPolicy);
|
||||||
RESTAPI_utils::field_to_json( Obj,"deviceConfiguration",deviceConfiguration);
|
field_to_json( Obj,"deviceConfiguration",deviceConfiguration);
|
||||||
RESTAPI_utils::field_to_json( Obj,"devices",devices);
|
field_to_json( Obj,"devices",devices);
|
||||||
RESTAPI_utils::field_to_json( Obj,"rrm",rrm);
|
field_to_json( Obj,"rrm",rrm);
|
||||||
RESTAPI_utils::field_to_json( Obj,"sourceIP",sourceIP);
|
field_to_json( Obj,"sourceIP",sourceIP);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Entity::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
bool Entity::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||||
try {
|
try {
|
||||||
info.from_json(Obj);
|
info.from_json(Obj);
|
||||||
RESTAPI_utils::field_from_json( Obj,"parent",parent);
|
field_from_json( Obj,"parent",parent);
|
||||||
RESTAPI_utils::field_from_json( Obj,"venues",venues);
|
field_from_json( Obj,"venues",venues);
|
||||||
RESTAPI_utils::field_from_json( Obj,"children",children);
|
field_from_json( Obj,"children",children);
|
||||||
RESTAPI_utils::field_from_json( Obj,"contacts",contacts);
|
field_from_json( Obj,"contacts",contacts);
|
||||||
RESTAPI_utils::field_from_json( Obj,"locations",locations);
|
field_from_json( Obj,"locations",locations);
|
||||||
RESTAPI_utils::field_from_json( Obj,"managementPolicy",managementPolicy);
|
field_from_json( Obj,"managementPolicy",managementPolicy);
|
||||||
RESTAPI_utils::field_from_json( Obj,"deviceConfiguration",deviceConfiguration);
|
field_from_json( Obj,"deviceConfiguration",deviceConfiguration);
|
||||||
RESTAPI_utils::field_from_json( Obj,"devices",devices);
|
field_from_json( Obj,"devices",devices);
|
||||||
RESTAPI_utils::field_from_json( Obj,"rrm",rrm);
|
field_from_json( Obj,"rrm",rrm);
|
||||||
RESTAPI_utils::field_from_json( Obj,"sourceIP",sourceIP);
|
field_from_json( Obj,"sourceIP",sourceIP);
|
||||||
return true;
|
return true;
|
||||||
} catch(...) {
|
} catch(...) {
|
||||||
|
|
||||||
@@ -113,14 +116,14 @@ namespace OpenWifi::ProvObjects {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DiGraphEntry::to_json(Poco::JSON::Object &Obj) const {
|
void DiGraphEntry::to_json(Poco::JSON::Object &Obj) const {
|
||||||
RESTAPI_utils::field_to_json( Obj,"parent",parent);
|
field_to_json( Obj,"parent",parent);
|
||||||
RESTAPI_utils::field_to_json( Obj,"child",child);
|
field_to_json( Obj,"child",child);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DiGraphEntry::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
bool DiGraphEntry::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||||
try {
|
try {
|
||||||
RESTAPI_utils::field_from_json( Obj,"parent",parent);
|
field_from_json( Obj,"parent",parent);
|
||||||
RESTAPI_utils::field_from_json( Obj,"child",child);
|
field_from_json( Obj,"child",child);
|
||||||
return true;
|
return true;
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
|
|
||||||
@@ -130,37 +133,37 @@ namespace OpenWifi::ProvObjects {
|
|||||||
|
|
||||||
void Venue::to_json(Poco::JSON::Object &Obj) const {
|
void Venue::to_json(Poco::JSON::Object &Obj) const {
|
||||||
info.to_json(Obj);
|
info.to_json(Obj);
|
||||||
RESTAPI_utils::field_to_json( Obj,"parent",parent);
|
field_to_json( Obj,"parent",parent);
|
||||||
RESTAPI_utils::field_to_json( Obj,"entity",entity);
|
field_to_json( Obj,"entity",entity);
|
||||||
RESTAPI_utils::field_to_json( Obj,"children",children);
|
field_to_json( Obj,"children",children);
|
||||||
RESTAPI_utils::field_to_json( Obj,"devices",devices);
|
field_to_json( Obj,"devices",devices);
|
||||||
RESTAPI_utils::field_to_json( Obj,"topology",topology);
|
field_to_json( Obj,"topology",topology);
|
||||||
RESTAPI_utils::field_to_json( Obj,"parent",parent);
|
field_to_json( Obj,"parent",parent);
|
||||||
RESTAPI_utils::field_to_json( Obj,"design",design);
|
field_to_json( Obj,"design",design);
|
||||||
RESTAPI_utils::field_to_json( Obj,"managementPolicy",managementPolicy);
|
field_to_json( Obj,"managementPolicy",managementPolicy);
|
||||||
RESTAPI_utils::field_to_json( Obj,"deviceConfiguration",deviceConfiguration);
|
field_to_json( Obj,"deviceConfiguration",deviceConfiguration);
|
||||||
RESTAPI_utils::field_to_json( Obj,"contact",contact);
|
field_to_json( Obj,"contact",contact);
|
||||||
RESTAPI_utils::field_to_json( Obj,"location",location);
|
field_to_json( Obj,"location",location);
|
||||||
RESTAPI_utils::field_to_json( Obj,"rrm",rrm);
|
field_to_json( Obj,"rrm",rrm);
|
||||||
RESTAPI_utils::field_to_json( Obj,"sourceIP",sourceIP);
|
field_to_json( Obj,"sourceIP",sourceIP);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Venue::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
bool Venue::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||||
try {
|
try {
|
||||||
info.from_json(Obj);
|
info.from_json(Obj);
|
||||||
RESTAPI_utils::field_from_json( Obj,"parent",parent);
|
field_from_json( Obj,"parent",parent);
|
||||||
RESTAPI_utils::field_from_json( Obj,"entity",entity);
|
field_from_json( Obj,"entity",entity);
|
||||||
RESTAPI_utils::field_from_json( Obj,"children",children);
|
field_from_json( Obj,"children",children);
|
||||||
RESTAPI_utils::field_from_json( Obj,"devices",devices);
|
field_from_json( Obj,"devices",devices);
|
||||||
RESTAPI_utils::field_from_json( Obj,"topology",topology);
|
field_from_json( Obj,"topology",topology);
|
||||||
RESTAPI_utils::field_from_json( Obj,"parent",parent);
|
field_from_json( Obj,"parent",parent);
|
||||||
RESTAPI_utils::field_from_json( Obj,"design",design);
|
field_from_json( Obj,"design",design);
|
||||||
RESTAPI_utils::field_from_json( Obj,"managementPolicy",managementPolicy);
|
field_from_json( Obj,"managementPolicy",managementPolicy);
|
||||||
RESTAPI_utils::field_from_json( Obj,"deviceConfiguration",deviceConfiguration);
|
field_from_json( Obj,"deviceConfiguration",deviceConfiguration);
|
||||||
RESTAPI_utils::field_from_json( Obj,"contact",contact);
|
field_from_json( Obj,"contact",contact);
|
||||||
RESTAPI_utils::field_from_json( Obj,"location",location);
|
field_from_json( Obj,"location",location);
|
||||||
RESTAPI_utils::field_from_json( Obj,"rrm",rrm);
|
field_from_json( Obj,"rrm",rrm);
|
||||||
RESTAPI_utils::field_from_json( Obj,"sourceIP",sourceIP);
|
field_from_json( Obj,"sourceIP",sourceIP);
|
||||||
return true;
|
return true;
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
|
|
||||||
@@ -169,16 +172,16 @@ namespace OpenWifi::ProvObjects {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void UserInfoDigest::to_json(Poco::JSON::Object &Obj) const {
|
void UserInfoDigest::to_json(Poco::JSON::Object &Obj) const {
|
||||||
RESTAPI_utils::field_to_json( Obj,"id",id);
|
field_to_json( Obj,"id",id);
|
||||||
RESTAPI_utils::field_to_json( Obj,"entity",loginId);
|
field_to_json( Obj,"entity",loginId);
|
||||||
RESTAPI_utils::field_to_json( Obj,"children",userType);
|
field_to_json( Obj,"children",userType);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UserInfoDigest::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
bool UserInfoDigest::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||||
try {
|
try {
|
||||||
RESTAPI_utils::field_from_json( Obj,"id",id);
|
field_from_json( Obj,"id",id);
|
||||||
RESTAPI_utils::field_from_json( Obj,"entity",loginId);
|
field_from_json( Obj,"entity",loginId);
|
||||||
RESTAPI_utils::field_from_json( Obj,"children",userType);
|
field_from_json( Obj,"children",userType);
|
||||||
return true;
|
return true;
|
||||||
} catch(...) {
|
} catch(...) {
|
||||||
}
|
}
|
||||||
@@ -187,17 +190,17 @@ namespace OpenWifi::ProvObjects {
|
|||||||
|
|
||||||
void ManagementRole::to_json(Poco::JSON::Object &Obj) const {
|
void ManagementRole::to_json(Poco::JSON::Object &Obj) const {
|
||||||
info.to_json(Obj);
|
info.to_json(Obj);
|
||||||
RESTAPI_utils::field_to_json( Obj,"managementPolicy",managementPolicy);
|
field_to_json( Obj,"managementPolicy",managementPolicy);
|
||||||
RESTAPI_utils::field_to_json( Obj,"users",users);
|
field_to_json( Obj,"users",users);
|
||||||
RESTAPI_utils::field_to_json( Obj,"entity",entity);
|
field_to_json( Obj,"entity",entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ManagementRole::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
bool ManagementRole::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||||
try {
|
try {
|
||||||
info.from_json(Obj);
|
info.from_json(Obj);
|
||||||
RESTAPI_utils::field_from_json( Obj,"managementPolicy",managementPolicy);
|
field_from_json( Obj,"managementPolicy",managementPolicy);
|
||||||
RESTAPI_utils::field_from_json( Obj,"users",users);
|
field_from_json( Obj,"users",users);
|
||||||
RESTAPI_utils::field_from_json( Obj,"entity",entity);
|
field_from_json( Obj,"entity",entity);
|
||||||
return true;
|
return true;
|
||||||
} catch(...) {
|
} catch(...) {
|
||||||
}
|
}
|
||||||
@@ -206,39 +209,39 @@ namespace OpenWifi::ProvObjects {
|
|||||||
|
|
||||||
void Location::to_json(Poco::JSON::Object &Obj) const {
|
void Location::to_json(Poco::JSON::Object &Obj) const {
|
||||||
info.to_json(Obj);
|
info.to_json(Obj);
|
||||||
RESTAPI_utils::field_to_json( Obj,"type",OpenWifi::ProvObjects::to_string(type));
|
field_to_json( Obj,"type",OpenWifi::ProvObjects::to_string(type));
|
||||||
RESTAPI_utils::field_to_json( Obj,"buildingName",buildingName);
|
field_to_json( Obj,"buildingName",buildingName);
|
||||||
RESTAPI_utils::field_to_json( Obj,"addressLines",addressLines);
|
field_to_json( Obj,"addressLines",addressLines);
|
||||||
RESTAPI_utils::field_to_json( Obj,"city",city);
|
field_to_json( Obj,"city",city);
|
||||||
RESTAPI_utils::field_to_json( Obj,"state",state);
|
field_to_json( Obj,"state",state);
|
||||||
RESTAPI_utils::field_to_json( Obj,"postal",postal);
|
field_to_json( Obj,"postal",postal);
|
||||||
RESTAPI_utils::field_to_json( Obj,"country",country);
|
field_to_json( Obj,"country",country);
|
||||||
RESTAPI_utils::field_to_json( Obj,"phones",phones);
|
field_to_json( Obj,"phones",phones);
|
||||||
RESTAPI_utils::field_to_json( Obj,"mobiles",mobiles);
|
field_to_json( Obj,"mobiles",mobiles);
|
||||||
RESTAPI_utils::field_to_json( Obj,"geoCode",geoCode);
|
field_to_json( Obj,"geoCode",geoCode);
|
||||||
RESTAPI_utils::field_to_json( Obj,"inUse",inUse);
|
field_to_json( Obj,"inUse",inUse);
|
||||||
RESTAPI_utils::field_to_json( Obj,"entity",entity);
|
field_to_json( Obj,"entity",entity);
|
||||||
RESTAPI_utils::field_to_json( Obj,"managementPolicy",managementPolicy);
|
field_to_json( Obj,"managementPolicy",managementPolicy);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Location::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
bool Location::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||||
try {
|
try {
|
||||||
info.from_json(Obj);
|
info.from_json(Obj);
|
||||||
std::string tmp_type;
|
std::string tmp_type;
|
||||||
RESTAPI_utils::field_from_json( Obj,"type", tmp_type);
|
field_from_json( Obj,"type", tmp_type);
|
||||||
type = location_from_string(tmp_type);
|
type = location_from_string(tmp_type);
|
||||||
RESTAPI_utils::field_from_json( Obj,"buildingName",buildingName);
|
field_from_json( Obj,"buildingName",buildingName);
|
||||||
RESTAPI_utils::field_from_json( Obj,"addressLines",addressLines);
|
field_from_json( Obj,"addressLines",addressLines);
|
||||||
RESTAPI_utils::field_from_json( Obj,"city",city);
|
field_from_json( Obj,"city",city);
|
||||||
RESTAPI_utils::field_from_json( Obj,"state",state);
|
field_from_json( Obj,"state",state);
|
||||||
RESTAPI_utils::field_from_json( Obj,"postal",postal);
|
field_from_json( Obj,"postal",postal);
|
||||||
RESTAPI_utils::field_from_json( Obj,"country",country);
|
field_from_json( Obj,"country",country);
|
||||||
RESTAPI_utils::field_from_json( Obj,"phones",phones);
|
field_from_json( Obj,"phones",phones);
|
||||||
RESTAPI_utils::field_from_json( Obj,"mobiles",mobiles);
|
field_from_json( Obj,"mobiles",mobiles);
|
||||||
RESTAPI_utils::field_from_json( Obj,"geoCode",geoCode);
|
field_from_json( Obj,"geoCode",geoCode);
|
||||||
RESTAPI_utils::field_from_json( Obj,"inUse",inUse);
|
field_from_json( Obj,"inUse",inUse);
|
||||||
RESTAPI_utils::field_from_json( Obj,"entity",entity);
|
field_from_json( Obj,"entity",entity);
|
||||||
RESTAPI_utils::field_from_json( Obj,"managementPolicy",managementPolicy);
|
field_from_json( Obj,"managementPolicy",managementPolicy);
|
||||||
return true;
|
return true;
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
|
|
||||||
@@ -248,43 +251,43 @@ namespace OpenWifi::ProvObjects {
|
|||||||
|
|
||||||
void Contact::to_json(Poco::JSON::Object &Obj) const {
|
void Contact::to_json(Poco::JSON::Object &Obj) const {
|
||||||
info.to_json(Obj);
|
info.to_json(Obj);
|
||||||
RESTAPI_utils::field_to_json( Obj,"type", to_string(type));
|
field_to_json( Obj,"type", to_string(type));
|
||||||
RESTAPI_utils::field_to_json( Obj,"title",title);
|
field_to_json( Obj,"title",title);
|
||||||
RESTAPI_utils::field_to_json( Obj,"salutation",salutation);
|
field_to_json( Obj,"salutation",salutation);
|
||||||
RESTAPI_utils::field_to_json( Obj,"firstname",firstname);
|
field_to_json( Obj,"firstname",firstname);
|
||||||
RESTAPI_utils::field_to_json( Obj,"lastname",lastname);
|
field_to_json( Obj,"lastname",lastname);
|
||||||
RESTAPI_utils::field_to_json( Obj,"initials",initials);
|
field_to_json( Obj,"initials",initials);
|
||||||
RESTAPI_utils::field_to_json( Obj,"visual",visual);
|
field_to_json( Obj,"visual",visual);
|
||||||
RESTAPI_utils::field_to_json( Obj,"mobiles",mobiles);
|
field_to_json( Obj,"mobiles",mobiles);
|
||||||
RESTAPI_utils::field_to_json( Obj,"phones",phones);
|
field_to_json( Obj,"phones",phones);
|
||||||
RESTAPI_utils::field_to_json( Obj,"primaryEmail",primaryEmail);
|
field_to_json( Obj,"primaryEmail",primaryEmail);
|
||||||
RESTAPI_utils::field_to_json( Obj,"secondaryEmail",secondaryEmail);
|
field_to_json( Obj,"secondaryEmail",secondaryEmail);
|
||||||
RESTAPI_utils::field_to_json( Obj,"accessPIN",accessPIN);
|
field_to_json( Obj,"accessPIN",accessPIN);
|
||||||
RESTAPI_utils::field_to_json( Obj,"inUse",inUse);
|
field_to_json( Obj,"inUse",inUse);
|
||||||
RESTAPI_utils::field_to_json( Obj,"entity",entity);
|
field_to_json( Obj,"entity",entity);
|
||||||
RESTAPI_utils::field_to_json( Obj,"managementPolicy",managementPolicy);
|
field_to_json( Obj,"managementPolicy",managementPolicy);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Contact::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
bool Contact::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||||
try {
|
try {
|
||||||
info.from_json(Obj);
|
info.from_json(Obj);
|
||||||
std::string tmp_type;
|
std::string tmp_type;
|
||||||
RESTAPI_utils::field_from_json( Obj,"type", tmp_type);
|
field_from_json( Obj,"type", tmp_type);
|
||||||
type = contact_from_string(tmp_type);
|
type = contact_from_string(tmp_type);
|
||||||
RESTAPI_utils::field_from_json( Obj,"title",title);
|
field_from_json( Obj,"title",title);
|
||||||
RESTAPI_utils::field_from_json( Obj,"salutation",salutation);
|
field_from_json( Obj,"salutation",salutation);
|
||||||
RESTAPI_utils::field_from_json( Obj,"firstname",firstname);
|
field_from_json( Obj,"firstname",firstname);
|
||||||
RESTAPI_utils::field_from_json( Obj,"lastname",lastname);
|
field_from_json( Obj,"lastname",lastname);
|
||||||
RESTAPI_utils::field_from_json( Obj,"initials",initials);
|
field_from_json( Obj,"initials",initials);
|
||||||
RESTAPI_utils::field_from_json( Obj,"visual",visual);
|
field_from_json( Obj,"visual",visual);
|
||||||
RESTAPI_utils::field_from_json( Obj,"mobiles",mobiles);
|
field_from_json( Obj,"mobiles",mobiles);
|
||||||
RESTAPI_utils::field_from_json( Obj,"phones",phones);
|
field_from_json( Obj,"phones",phones);
|
||||||
RESTAPI_utils::field_from_json( Obj,"primaryEmail",primaryEmail);
|
field_from_json( Obj,"primaryEmail",primaryEmail);
|
||||||
RESTAPI_utils::field_from_json( Obj,"secondaryEmail",secondaryEmail);
|
field_from_json( Obj,"secondaryEmail",secondaryEmail);
|
||||||
RESTAPI_utils::field_from_json( Obj,"accessPIN",accessPIN);
|
field_from_json( Obj,"accessPIN",accessPIN);
|
||||||
RESTAPI_utils::field_from_json( Obj,"inUse",inUse);
|
field_from_json( Obj,"inUse",inUse);
|
||||||
RESTAPI_utils::field_from_json( Obj,"entity",entity);
|
field_from_json( Obj,"entity",entity);
|
||||||
RESTAPI_utils::field_from_json( Obj,"managementPolicy",managementPolicy);
|
field_from_json( Obj,"managementPolicy",managementPolicy);
|
||||||
return true;
|
return true;
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
|
|
||||||
@@ -294,35 +297,35 @@ namespace OpenWifi::ProvObjects {
|
|||||||
|
|
||||||
void InventoryTag::to_json(Poco::JSON::Object &Obj) const {
|
void InventoryTag::to_json(Poco::JSON::Object &Obj) const {
|
||||||
info.to_json(Obj);
|
info.to_json(Obj);
|
||||||
RESTAPI_utils::field_to_json(Obj, "serialNumber", serialNumber);
|
field_to_json(Obj, "serialNumber", serialNumber);
|
||||||
RESTAPI_utils::field_to_json(Obj, "venue", venue);
|
field_to_json(Obj, "venue", venue);
|
||||||
RESTAPI_utils::field_to_json(Obj, "entity", entity);
|
field_to_json(Obj, "entity", entity);
|
||||||
RESTAPI_utils::field_to_json(Obj, "subscriber", subscriber);
|
field_to_json(Obj, "subscriber", subscriber);
|
||||||
RESTAPI_utils::field_to_json(Obj, "deviceType", deviceType);
|
field_to_json(Obj, "deviceType", deviceType);
|
||||||
RESTAPI_utils::field_to_json(Obj, "qrCode", qrCode);
|
field_to_json(Obj, "qrCode", qrCode);
|
||||||
RESTAPI_utils::field_to_json(Obj, "geoCode", geoCode);
|
field_to_json(Obj, "geoCode", geoCode);
|
||||||
RESTAPI_utils::field_to_json(Obj, "location", location);
|
field_to_json(Obj, "location", location);
|
||||||
RESTAPI_utils::field_to_json(Obj, "contact", contact);
|
field_to_json(Obj, "contact", contact);
|
||||||
RESTAPI_utils::field_to_json( Obj,"deviceConfiguration",deviceConfiguration);
|
field_to_json( Obj,"deviceConfiguration",deviceConfiguration);
|
||||||
RESTAPI_utils::field_to_json( Obj,"rrm",rrm);
|
field_to_json( Obj,"rrm",rrm);
|
||||||
RESTAPI_utils::field_to_json( Obj,"managementPolicy",managementPolicy);
|
field_to_json( Obj,"managementPolicy",managementPolicy);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InventoryTag::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
bool InventoryTag::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||||
try {
|
try {
|
||||||
info.from_json(Obj);
|
info.from_json(Obj);
|
||||||
RESTAPI_utils::field_from_json( Obj,"serialNumber",serialNumber);
|
field_from_json( Obj,"serialNumber",serialNumber);
|
||||||
RESTAPI_utils::field_from_json( Obj,"venue",venue);
|
field_from_json( Obj,"venue",venue);
|
||||||
RESTAPI_utils::field_from_json( Obj,"entity",entity);
|
field_from_json( Obj,"entity",entity);
|
||||||
RESTAPI_utils::field_from_json( Obj,"subscriber",subscriber);
|
field_from_json( Obj,"subscriber",subscriber);
|
||||||
RESTAPI_utils::field_from_json( Obj,"deviceType",deviceType);
|
field_from_json( Obj,"deviceType",deviceType);
|
||||||
RESTAPI_utils::field_from_json(Obj, "qrCode", qrCode);
|
field_from_json(Obj, "qrCode", qrCode);
|
||||||
RESTAPI_utils::field_from_json( Obj,"geoCode",geoCode);
|
field_from_json( Obj,"geoCode",geoCode);
|
||||||
RESTAPI_utils::field_from_json( Obj,"location",location);
|
field_from_json( Obj,"location",location);
|
||||||
RESTAPI_utils::field_from_json( Obj,"contact",contact);
|
field_from_json( Obj,"contact",contact);
|
||||||
RESTAPI_utils::field_from_json( Obj,"deviceConfiguration",deviceConfiguration);
|
field_from_json( Obj,"deviceConfiguration",deviceConfiguration);
|
||||||
RESTAPI_utils::field_from_json( Obj,"rrm",rrm);
|
field_from_json( Obj,"rrm",rrm);
|
||||||
RESTAPI_utils::field_from_json( Obj,"managementPolicy",managementPolicy);
|
field_from_json( Obj,"managementPolicy",managementPolicy);
|
||||||
return true;
|
return true;
|
||||||
} catch(...) {
|
} catch(...) {
|
||||||
|
|
||||||
@@ -331,18 +334,18 @@ namespace OpenWifi::ProvObjects {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DeviceConfigurationElement::to_json(Poco::JSON::Object &Obj) const {
|
void DeviceConfigurationElement::to_json(Poco::JSON::Object &Obj) const {
|
||||||
RESTAPI_utils::field_to_json( Obj,"name", name);
|
field_to_json( Obj,"name", name);
|
||||||
RESTAPI_utils::field_to_json( Obj,"description", description);
|
field_to_json( Obj,"description", description);
|
||||||
RESTAPI_utils::field_to_json( Obj,"weight", weight);
|
field_to_json( Obj,"weight", weight);
|
||||||
RESTAPI_utils::field_to_json( Obj,"configuration", configuration);
|
field_to_json( Obj,"configuration", configuration);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DeviceConfigurationElement::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
bool DeviceConfigurationElement::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||||
try {
|
try {
|
||||||
RESTAPI_utils::field_from_json( Obj,"name",name);
|
field_from_json( Obj,"name",name);
|
||||||
RESTAPI_utils::field_from_json( Obj,"description",description);
|
field_from_json( Obj,"description",description);
|
||||||
RESTAPI_utils::field_from_json( Obj,"weight",weight);
|
field_from_json( Obj,"weight",weight);
|
||||||
RESTAPI_utils::field_from_json( Obj,"configuration",configuration);
|
field_from_json( Obj,"configuration",configuration);
|
||||||
return true;
|
return true;
|
||||||
} catch(...) {
|
} catch(...) {
|
||||||
|
|
||||||
@@ -352,27 +355,27 @@ namespace OpenWifi::ProvObjects {
|
|||||||
|
|
||||||
void DeviceConfiguration::to_json(Poco::JSON::Object &Obj) const {
|
void DeviceConfiguration::to_json(Poco::JSON::Object &Obj) const {
|
||||||
info.to_json(Obj);
|
info.to_json(Obj);
|
||||||
RESTAPI_utils::field_to_json( Obj,"managementPolicy",managementPolicy);
|
field_to_json( Obj,"managementPolicy",managementPolicy);
|
||||||
RESTAPI_utils::field_to_json( Obj,"deviceTypes",deviceTypes);
|
field_to_json( Obj,"deviceTypes",deviceTypes);
|
||||||
RESTAPI_utils::field_to_json( Obj,"configuration",configuration);
|
field_to_json( Obj,"configuration",configuration);
|
||||||
RESTAPI_utils::field_to_json( Obj,"inUse",inUse);
|
field_to_json( Obj,"inUse",inUse);
|
||||||
RESTAPI_utils::field_to_json( Obj,"variables",variables);
|
field_to_json( Obj,"variables",variables);
|
||||||
RESTAPI_utils::field_to_json( Obj,"rrm",rrm);
|
field_to_json( Obj,"rrm",rrm);
|
||||||
RESTAPI_utils::field_to_json( Obj,"firmwareUpgrade",firmwareUpgrade);
|
field_to_json( Obj,"firmwareUpgrade",firmwareUpgrade);
|
||||||
RESTAPI_utils::field_to_json( Obj,"firmwareRCOnly",firmwareRCOnly);
|
field_to_json( Obj,"firmwareRCOnly",firmwareRCOnly);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DeviceConfiguration::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
bool DeviceConfiguration::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||||
try {
|
try {
|
||||||
info.from_json(Obj);
|
info.from_json(Obj);
|
||||||
RESTAPI_utils::field_from_json( Obj,"managementPolicy",managementPolicy);
|
field_from_json( Obj,"managementPolicy",managementPolicy);
|
||||||
RESTAPI_utils::field_from_json( Obj,"deviceTypes",deviceTypes);
|
field_from_json( Obj,"deviceTypes",deviceTypes);
|
||||||
RESTAPI_utils::field_from_json( Obj,"configuration",configuration);
|
field_from_json( Obj,"configuration",configuration);
|
||||||
RESTAPI_utils::field_from_json( Obj,"inUse",inUse);
|
field_from_json( Obj,"inUse",inUse);
|
||||||
RESTAPI_utils::field_from_json( Obj,"variables",variables);
|
field_from_json( Obj,"variables",variables);
|
||||||
RESTAPI_utils::field_from_json( Obj,"rrm",rrm);
|
field_from_json( Obj,"rrm",rrm);
|
||||||
RESTAPI_utils::field_from_json( Obj,"firmwareUpgrade",firmwareUpgrade);
|
field_from_json( Obj,"firmwareUpgrade",firmwareUpgrade);
|
||||||
RESTAPI_utils::field_from_json( Obj,"firmwareRCOnly",firmwareRCOnly);
|
field_from_json( Obj,"firmwareRCOnly",firmwareRCOnly);
|
||||||
return true;
|
return true;
|
||||||
} catch(...) {
|
} catch(...) {
|
||||||
|
|
||||||
@@ -381,8 +384,8 @@ namespace OpenWifi::ProvObjects {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Report::to_json(Poco::JSON::Object &Obj) const {
|
void Report::to_json(Poco::JSON::Object &Obj) const {
|
||||||
RESTAPI_utils::field_to_json(Obj, "snapshot", snapShot);
|
field_to_json(Obj, "snapshot", snapShot);
|
||||||
RESTAPI_utils::field_to_json(Obj, "devices", tenants);
|
field_to_json(Obj, "devices", tenants);
|
||||||
};
|
};
|
||||||
|
|
||||||
void Report::reset() {
|
void Report::reset() {
|
||||||
@@ -390,16 +393,16 @@ namespace OpenWifi::ProvObjects {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ExpandedUseEntry::to_json(Poco::JSON::Object &Obj) const {
|
void ExpandedUseEntry::to_json(Poco::JSON::Object &Obj) const {
|
||||||
RESTAPI_utils::field_to_json(Obj, "uuid", uuid);
|
field_to_json(Obj, "uuid", uuid);
|
||||||
RESTAPI_utils::field_to_json(Obj, "name", name);
|
field_to_json(Obj, "name", name);
|
||||||
RESTAPI_utils::field_to_json(Obj, "description", description);
|
field_to_json(Obj, "description", description);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ExpandedUseEntry::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
bool ExpandedUseEntry::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||||
try {
|
try {
|
||||||
RESTAPI_utils::field_from_json( Obj,"uuid",uuid);
|
field_from_json( Obj,"uuid",uuid);
|
||||||
RESTAPI_utils::field_from_json( Obj,"name",name);
|
field_from_json( Obj,"name",name);
|
||||||
RESTAPI_utils::field_from_json( Obj,"description",description);
|
field_from_json( Obj,"description",description);
|
||||||
return true;
|
return true;
|
||||||
} catch(...) {
|
} catch(...) {
|
||||||
|
|
||||||
@@ -408,14 +411,14 @@ namespace OpenWifi::ProvObjects {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ExpandedUseEntryList::to_json(Poco::JSON::Object &Obj) const {
|
void ExpandedUseEntryList::to_json(Poco::JSON::Object &Obj) const {
|
||||||
RESTAPI_utils::field_to_json(Obj, "type", type);
|
field_to_json(Obj, "type", type);
|
||||||
RESTAPI_utils::field_to_json(Obj, "entries", entries);
|
field_to_json(Obj, "entries", entries);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ExpandedUseEntryList::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
bool ExpandedUseEntryList::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||||
try {
|
try {
|
||||||
RESTAPI_utils::field_from_json( Obj,"type",type);
|
field_from_json( Obj,"type",type);
|
||||||
RESTAPI_utils::field_from_json( Obj,"entries",entries);
|
field_from_json( Obj,"entries",entries);
|
||||||
return true;
|
return true;
|
||||||
} catch(...) {
|
} catch(...) {
|
||||||
|
|
||||||
@@ -424,12 +427,94 @@ namespace OpenWifi::ProvObjects {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ExpandedUseEntryMapList::to_json(Poco::JSON::Object &Obj) const {
|
void ExpandedUseEntryMapList::to_json(Poco::JSON::Object &Obj) const {
|
||||||
RESTAPI_utils::field_to_json(Obj, "entries", entries);
|
field_to_json(Obj, "entries", entries);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ExpandedUseEntryMapList::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
bool ExpandedUseEntryMapList::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||||
try {
|
try {
|
||||||
RESTAPI_utils::field_from_json( Obj,"entries",entries);
|
field_from_json( Obj,"entries",entries);
|
||||||
|
return true;
|
||||||
|
} catch(...) {
|
||||||
|
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UserList::to_json(Poco::JSON::Object &Obj) const {
|
||||||
|
field_to_json(Obj, "list", list);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UserList::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||||
|
try {
|
||||||
|
field_from_json(Obj, "list", list);
|
||||||
|
return true;
|
||||||
|
} catch(...) {
|
||||||
|
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObjectACL::to_json(Poco::JSON::Object &Obj) const {
|
||||||
|
field_to_json(Obj, "users", users);
|
||||||
|
field_to_json(Obj, "access", access);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ObjectACL::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||||
|
try {
|
||||||
|
field_from_json(Obj, "users", users);
|
||||||
|
field_from_json(Obj, "access", access);
|
||||||
|
return true;
|
||||||
|
} catch(...) {
|
||||||
|
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObjectACLList::to_json(Poco::JSON::Object &Obj) const {
|
||||||
|
field_to_json(Obj, "list", list);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ObjectACLList::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||||
|
try {
|
||||||
|
field_from_json(Obj, "list", list);
|
||||||
|
return true;
|
||||||
|
} catch(...) {
|
||||||
|
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Map::to_json(Poco::JSON::Object &Obj) const {
|
||||||
|
info.to_json(Obj);
|
||||||
|
field_to_json( Obj,"data",data);
|
||||||
|
field_to_json( Obj,"entity",entity);
|
||||||
|
field_to_json( Obj,"creator",creator);
|
||||||
|
field_to_json( Obj,"visibility",visibility);
|
||||||
|
field_to_json( Obj,"access",access);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Map::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||||
|
try {
|
||||||
|
info.from_json(Obj);
|
||||||
|
field_from_json( Obj,"data",data);
|
||||||
|
field_from_json( Obj,"entity",entity);
|
||||||
|
field_from_json( Obj,"creator",creator);
|
||||||
|
field_from_json( Obj,"visibility",visibility);
|
||||||
|
field_from_json( Obj,"access",access);
|
||||||
|
return true;
|
||||||
|
} catch(...) {
|
||||||
|
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MapList::to_json(Poco::JSON::Object &Obj) const {
|
||||||
|
field_to_json( Obj,"list",list);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MapList::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||||
|
try {
|
||||||
|
field_from_json( Obj,"list",list);
|
||||||
return true;
|
return true;
|
||||||
} catch(...) {
|
} catch(...) {
|
||||||
|
|
||||||
@@ -438,13 +523,47 @@ namespace OpenWifi::ProvObjects {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool UpdateObjectInfo(const Poco::JSON::Object::Ptr &O, const SecurityObjects::UserInfo &U, ObjectInfo &I) {
|
bool UpdateObjectInfo(const Poco::JSON::Object::Ptr &O, const SecurityObjects::UserInfo &U, ObjectInfo &I) {
|
||||||
|
uint64_t Now = std::time(nullptr);
|
||||||
if(O->has("name"))
|
if(O->has("name"))
|
||||||
I.name = O->get("name").toString();
|
I.name = O->get("name").toString();
|
||||||
|
|
||||||
|
if(I.name.empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
if(O->has("description"))
|
if(O->has("description"))
|
||||||
I.description = O->get("description").toString();
|
I.description = O->get("description").toString();
|
||||||
SecurityObjects::MergeNotes(O,U,I.notes);
|
SecurityObjects::MergeNotes(O,U,I.notes);
|
||||||
I.modified = std::time(nullptr);
|
SecurityObjects::NoteInfoVec N;
|
||||||
|
for(auto &i:I.notes) {
|
||||||
|
if(i.note.empty())
|
||||||
|
continue;
|
||||||
|
N.push_back(SecurityObjects::NoteInfo{.created=Now,.createdBy=U.email,.note=i.note});
|
||||||
|
}
|
||||||
|
I.modified = Now;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CreateObjectInfo(const Poco::JSON::Object::Ptr &O, const SecurityObjects::UserInfo &U, ObjectInfo &I) {
|
||||||
|
uint64_t Now = std::time(nullptr);
|
||||||
|
if(O->has("name"))
|
||||||
|
I.name = O->get("name").toString();
|
||||||
|
|
||||||
|
if(I.name.empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if(O->has("description"))
|
||||||
|
I.description = O->get("description").toString();
|
||||||
|
|
||||||
|
SecurityObjects::NoteInfoVec N;
|
||||||
|
for(auto &i:I.notes) {
|
||||||
|
if(i.note.empty())
|
||||||
|
continue;
|
||||||
|
N.push_back(SecurityObjects::NoteInfo{.created=Now,.createdBy=U.email,.note=i.note});
|
||||||
|
}
|
||||||
|
I.notes = N;
|
||||||
|
I.modified = I.created = Now;
|
||||||
|
I.id = MicroService::CreateUUID();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -15,6 +15,13 @@
|
|||||||
|
|
||||||
namespace OpenWifi::ProvObjects {
|
namespace OpenWifi::ProvObjects {
|
||||||
|
|
||||||
|
enum FIRMWARE_UPGRADE_RULES {
|
||||||
|
dont_upgrade,
|
||||||
|
upgrade_inherit,
|
||||||
|
upgrade_release_only,
|
||||||
|
upgrade_latest
|
||||||
|
};
|
||||||
|
|
||||||
struct ObjectInfo {
|
struct ObjectInfo {
|
||||||
Types::UUID_t id;
|
Types::UUID_t id;
|
||||||
std::string name;
|
std::string name;
|
||||||
@@ -317,7 +324,50 @@ namespace OpenWifi::ProvObjects {
|
|||||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct UserList {
|
||||||
|
std::vector<std::string> list;
|
||||||
|
|
||||||
|
void to_json(Poco::JSON::Object &Obj) const;
|
||||||
|
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ObjectACL {
|
||||||
|
UserList users;
|
||||||
|
std::string access;
|
||||||
|
|
||||||
|
void to_json(Poco::JSON::Object &Obj) const;
|
||||||
|
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ObjectACLList {
|
||||||
|
std::vector<ObjectACL> list;
|
||||||
|
|
||||||
|
void to_json(Poco::JSON::Object &Obj) const;
|
||||||
|
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Map {
|
||||||
|
ObjectInfo info;
|
||||||
|
std::string data;
|
||||||
|
std::string entity;
|
||||||
|
std::string creator;
|
||||||
|
std::string visibility;
|
||||||
|
ObjectACLList access;
|
||||||
|
|
||||||
|
void to_json(Poco::JSON::Object &Obj) const;
|
||||||
|
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MapList {
|
||||||
|
std::vector<Map> list;
|
||||||
|
|
||||||
|
void to_json(Poco::JSON::Object &Obj) const;
|
||||||
|
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||||
|
};
|
||||||
|
|
||||||
bool UpdateObjectInfo(const Poco::JSON::Object::Ptr &O, const SecurityObjects::UserInfo &U, ObjectInfo &I);
|
bool UpdateObjectInfo(const Poco::JSON::Object::Ptr &O, const SecurityObjects::UserInfo &U, ObjectInfo &I);
|
||||||
|
bool CreateObjectInfo(const Poco::JSON::Object::Ptr &O, const SecurityObjects::UserInfo &U, ObjectInfo &I);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -138,7 +138,7 @@ namespace OpenWifi::SecurityObjects {
|
|||||||
field_to_json(Obj,"primary", primary);
|
field_to_json(Obj,"primary", primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MobilePhoneNumber::from_json(Poco::JSON::Object::Ptr Obj) {
|
bool MobilePhoneNumber::from_json(Poco::JSON::Object::Ptr &Obj) {
|
||||||
try {
|
try {
|
||||||
field_from_json(Obj,"number",number);
|
field_from_json(Obj,"number",number);
|
||||||
field_from_json(Obj,"verified",verified);
|
field_from_json(Obj,"verified",verified);
|
||||||
@@ -155,7 +155,7 @@ namespace OpenWifi::SecurityObjects {
|
|||||||
field_to_json(Obj,"method", method);
|
field_to_json(Obj,"method", method);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MfaAuthInfo::from_json(Poco::JSON::Object::Ptr Obj) {
|
bool MfaAuthInfo::from_json(Poco::JSON::Object::Ptr &Obj) {
|
||||||
try {
|
try {
|
||||||
field_from_json(Obj,"enabled",enabled);
|
field_from_json(Obj,"enabled",enabled);
|
||||||
field_from_json(Obj,"method",method);
|
field_from_json(Obj,"method",method);
|
||||||
@@ -171,7 +171,7 @@ namespace OpenWifi::SecurityObjects {
|
|||||||
field_to_json(Obj, "mfa", mfa);
|
field_to_json(Obj, "mfa", mfa);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UserLoginLoginExtensions::from_json(Poco::JSON::Object::Ptr Obj) {
|
bool UserLoginLoginExtensions::from_json(Poco::JSON::Object::Ptr &Obj) {
|
||||||
try {
|
try {
|
||||||
field_from_json(Obj,"mobiles",mobiles);
|
field_from_json(Obj,"mobiles",mobiles);
|
||||||
field_from_json(Obj,"mfa",mfa);
|
field_from_json(Obj,"mfa",mfa);
|
||||||
@@ -189,7 +189,7 @@ namespace OpenWifi::SecurityObjects {
|
|||||||
field_to_json(Obj, "method", method);
|
field_to_json(Obj, "method", method);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MFAChallengeRequest::from_json(Poco::JSON::Object::Ptr Obj) {
|
bool MFAChallengeRequest::from_json(Poco::JSON::Object::Ptr &Obj) {
|
||||||
try {
|
try {
|
||||||
field_from_json(Obj,"uuid",uuid);
|
field_from_json(Obj,"uuid",uuid);
|
||||||
field_from_json(Obj,"question",question);
|
field_from_json(Obj,"question",question);
|
||||||
@@ -208,7 +208,7 @@ namespace OpenWifi::SecurityObjects {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MFAChallengeResponse::from_json(Poco::JSON::Object::Ptr Obj) {
|
bool MFAChallengeResponse::from_json(Poco::JSON::Object::Ptr &Obj) {
|
||||||
try {
|
try {
|
||||||
field_from_json(Obj,"uuid",uuid);
|
field_from_json(Obj,"uuid",uuid);
|
||||||
field_from_json(Obj,"answer",answer);
|
field_from_json(Obj,"answer",answer);
|
||||||
@@ -387,11 +387,12 @@ namespace OpenWifi::SecurityObjects {
|
|||||||
field_to_json(Obj,"note", note);
|
field_to_json(Obj,"note", note);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NoteInfo::from_json(Poco::JSON::Object::Ptr Obj) {
|
bool NoteInfo::from_json(Poco::JSON::Object::Ptr &Obj) {
|
||||||
try {
|
try {
|
||||||
field_from_json(Obj,"created",created);
|
field_from_json(Obj,"created",created);
|
||||||
field_from_json(Obj,"createdBy",createdBy);
|
field_from_json(Obj,"createdBy",createdBy);
|
||||||
field_from_json(Obj,"note",note);
|
field_from_json(Obj,"note",note);
|
||||||
|
return true;
|
||||||
} catch(...) {
|
} catch(...) {
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -428,10 +429,11 @@ namespace OpenWifi::SecurityObjects {
|
|||||||
field_to_json<ResourceAccessType>(Obj,"access", access, ResourceAccessTypeToString);
|
field_to_json<ResourceAccessType>(Obj,"access", access, ResourceAccessTypeToString);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ProfileAction::from_json(Poco::JSON::Object::Ptr Obj) {
|
bool ProfileAction::from_json(Poco::JSON::Object::Ptr &Obj) {
|
||||||
try {
|
try {
|
||||||
field_from_json(Obj,"resource",resource);
|
field_from_json(Obj,"resource",resource);
|
||||||
field_from_json<ResourceAccessType>(Obj,"access",access,ResourceAccessTypeFromString );
|
field_from_json<ResourceAccessType>(Obj,"access",access,ResourceAccessTypeFromString );
|
||||||
|
return true;
|
||||||
} catch(...) {
|
} catch(...) {
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -447,7 +449,7 @@ namespace OpenWifi::SecurityObjects {
|
|||||||
field_to_json(Obj,"notes", notes);
|
field_to_json(Obj,"notes", notes);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SecurityProfile::from_json(Poco::JSON::Object::Ptr Obj) {
|
bool SecurityProfile::from_json(Poco::JSON::Object::Ptr &Obj) {
|
||||||
try {
|
try {
|
||||||
field_from_json(Obj,"id",id);
|
field_from_json(Obj,"id",id);
|
||||||
field_from_json(Obj,"name",name);
|
field_from_json(Obj,"name",name);
|
||||||
@@ -455,6 +457,7 @@ namespace OpenWifi::SecurityObjects {
|
|||||||
field_from_json(Obj,"policy",policy);
|
field_from_json(Obj,"policy",policy);
|
||||||
field_from_json(Obj,"role",role);
|
field_from_json(Obj,"role",role);
|
||||||
field_from_json(Obj,"notes",notes);
|
field_from_json(Obj,"notes",notes);
|
||||||
|
return true;
|
||||||
} catch(...) {
|
} catch(...) {
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -465,9 +468,47 @@ namespace OpenWifi::SecurityObjects {
|
|||||||
field_to_json(Obj, "profiles", profiles);
|
field_to_json(Obj, "profiles", profiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SecurityProfileList::from_json(Poco::JSON::Object::Ptr Obj) {
|
bool SecurityProfileList::from_json(Poco::JSON::Object::Ptr &Obj) {
|
||||||
try {
|
try {
|
||||||
field_from_json(Obj,"profiles",profiles);
|
field_from_json(Obj,"profiles",profiles);
|
||||||
|
return true;
|
||||||
|
} catch(...) {
|
||||||
|
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ActionLink::to_json(Poco::JSON::Object &Obj) const {
|
||||||
|
field_to_json(Obj,"id",id);
|
||||||
|
field_to_json(Obj,"action",action);
|
||||||
|
field_to_json(Obj,"userId",userId);
|
||||||
|
field_to_json(Obj,"actionTemplate",actionTemplate);
|
||||||
|
field_to_json(Obj,"variables",variables);
|
||||||
|
field_to_json(Obj,"locale",locale);
|
||||||
|
field_to_json(Obj,"message",message);
|
||||||
|
field_to_json(Obj,"sent",sent);
|
||||||
|
field_to_json(Obj,"created",created);
|
||||||
|
field_to_json(Obj,"expires",expires);
|
||||||
|
field_to_json(Obj,"completed",completed);
|
||||||
|
field_to_json(Obj,"canceled",canceled);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ActionLink::from_json(Poco::JSON::Object::Ptr &Obj) {
|
||||||
|
try {
|
||||||
|
field_from_json(Obj,"id",id);
|
||||||
|
field_from_json(Obj,"action",action);
|
||||||
|
field_from_json(Obj,"userId",userId);
|
||||||
|
field_from_json(Obj,"actionTemplate",actionTemplate);
|
||||||
|
field_from_json(Obj,"variables",variables);
|
||||||
|
field_from_json(Obj,"locale",locale);
|
||||||
|
field_from_json(Obj,"message",message);
|
||||||
|
field_from_json(Obj,"sent",sent);
|
||||||
|
field_from_json(Obj,"created",created);
|
||||||
|
field_from_json(Obj,"expires",expires);
|
||||||
|
field_from_json(Obj,"completed",completed);
|
||||||
|
field_from_json(Obj,"canceled",canceled);
|
||||||
|
return true;
|
||||||
} catch(...) {
|
} catch(...) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
#define UCENTRAL_RESTAPI_SECURITYOBJECTS_H
|
#define UCENTRAL_RESTAPI_SECURITYOBJECTS_H
|
||||||
|
|
||||||
#include "Poco/JSON/Object.h"
|
#include "Poco/JSON/Object.h"
|
||||||
#include "../framework/OpenWifiTypes.h"
|
#include "framework/OpenWifiTypes.h"
|
||||||
|
|
||||||
namespace OpenWifi::SecurityObjects {
|
namespace OpenWifi::SecurityObjects {
|
||||||
|
|
||||||
@@ -53,25 +53,25 @@ namespace OpenWifi::SecurityObjects {
|
|||||||
std::string createdBy;
|
std::string createdBy;
|
||||||
std::string note;
|
std::string note;
|
||||||
void to_json(Poco::JSON::Object &Obj) const;
|
void to_json(Poco::JSON::Object &Obj) const;
|
||||||
bool from_json(Poco::JSON::Object::Ptr Obj);
|
bool from_json(Poco::JSON::Object::Ptr &Obj);
|
||||||
};
|
};
|
||||||
typedef std::vector<NoteInfo> NoteInfoVec;
|
typedef std::vector<NoteInfo> NoteInfoVec;
|
||||||
|
|
||||||
struct MobilePhoneNumber {
|
struct MobilePhoneNumber {
|
||||||
std::string number;
|
std::string number;
|
||||||
bool verified;
|
bool verified = false;
|
||||||
bool primary;
|
bool primary = false;
|
||||||
|
|
||||||
void to_json(Poco::JSON::Object &Obj) const;
|
void to_json(Poco::JSON::Object &Obj) const;
|
||||||
bool from_json(Poco::JSON::Object::Ptr Obj);
|
bool from_json(Poco::JSON::Object::Ptr &Obj);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MfaAuthInfo {
|
struct MfaAuthInfo {
|
||||||
bool enabled;
|
bool enabled = false;
|
||||||
std::string method;
|
std::string method;
|
||||||
|
|
||||||
void to_json(Poco::JSON::Object &Obj) const;
|
void to_json(Poco::JSON::Object &Obj) const;
|
||||||
bool from_json(Poco::JSON::Object::Ptr Obj);
|
bool from_json(Poco::JSON::Object::Ptr &Obj);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct UserLoginLoginExtensions {
|
struct UserLoginLoginExtensions {
|
||||||
@@ -79,17 +79,17 @@ namespace OpenWifi::SecurityObjects {
|
|||||||
struct MfaAuthInfo mfa;
|
struct MfaAuthInfo mfa;
|
||||||
|
|
||||||
void to_json(Poco::JSON::Object &Obj) const;
|
void to_json(Poco::JSON::Object &Obj) const;
|
||||||
bool from_json(Poco::JSON::Object::Ptr Obj);
|
bool from_json(Poco::JSON::Object::Ptr &Obj);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MFAChallengeRequest {
|
struct MFAChallengeRequest {
|
||||||
std::string uuid;
|
std::string uuid;
|
||||||
std::string question;
|
std::string question;
|
||||||
std::string method;
|
std::string method;
|
||||||
uint64_t created;
|
uint64_t created = std::time(nullptr);
|
||||||
|
|
||||||
void to_json(Poco::JSON::Object &Obj) const;
|
void to_json(Poco::JSON::Object &Obj) const;
|
||||||
bool from_json(Poco::JSON::Object::Ptr Obj);
|
bool from_json(Poco::JSON::Object::Ptr &Obj);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MFAChallengeResponse {
|
struct MFAChallengeResponse {
|
||||||
@@ -97,7 +97,7 @@ namespace OpenWifi::SecurityObjects {
|
|||||||
std::string answer;
|
std::string answer;
|
||||||
|
|
||||||
void to_json(Poco::JSON::Object &Obj) const;
|
void to_json(Poco::JSON::Object &Obj) const;
|
||||||
bool from_json(Poco::JSON::Object::Ptr Obj);
|
bool from_json(Poco::JSON::Object::Ptr &Obj);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct UserInfo {
|
struct UserInfo {
|
||||||
@@ -200,7 +200,7 @@ namespace OpenWifi::SecurityObjects {
|
|||||||
std::string resource;
|
std::string resource;
|
||||||
ResourceAccessType access;
|
ResourceAccessType access;
|
||||||
void to_json(Poco::JSON::Object &Obj) const;
|
void to_json(Poco::JSON::Object &Obj) const;
|
||||||
bool from_json(Poco::JSON::Object::Ptr Obj);
|
bool from_json(Poco::JSON::Object::Ptr &Obj);
|
||||||
};
|
};
|
||||||
typedef std::vector<ProfileAction> ProfileActionVec;
|
typedef std::vector<ProfileAction> ProfileActionVec;
|
||||||
|
|
||||||
@@ -212,14 +212,37 @@ namespace OpenWifi::SecurityObjects {
|
|||||||
std::string role;
|
std::string role;
|
||||||
NoteInfoVec notes;
|
NoteInfoVec notes;
|
||||||
void to_json(Poco::JSON::Object &Obj) const;
|
void to_json(Poco::JSON::Object &Obj) const;
|
||||||
bool from_json(Poco::JSON::Object::Ptr Obj);
|
bool from_json(Poco::JSON::Object::Ptr &Obj);
|
||||||
};
|
};
|
||||||
typedef std::vector<SecurityProfile> SecurityProfileVec;
|
typedef std::vector<SecurityProfile> SecurityProfileVec;
|
||||||
|
|
||||||
struct SecurityProfileList {
|
struct SecurityProfileList {
|
||||||
SecurityProfileVec profiles;
|
SecurityProfileVec profiles;
|
||||||
void to_json(Poco::JSON::Object &Obj) const;
|
void to_json(Poco::JSON::Object &Obj) const;
|
||||||
bool from_json(Poco::JSON::Object::Ptr Obj);
|
bool from_json(Poco::JSON::Object::Ptr &Obj);
|
||||||
|
};
|
||||||
|
|
||||||
|
enum LinkActions {
|
||||||
|
FORGOT_PASSWORD=1,
|
||||||
|
VERIFY_EMAIL
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ActionLink {
|
||||||
|
std::string id;
|
||||||
|
uint64_t action;
|
||||||
|
std::string userId;
|
||||||
|
std::string actionTemplate;
|
||||||
|
Types::StringPairVec variables;
|
||||||
|
std::string locale;
|
||||||
|
std::string message;
|
||||||
|
uint64_t sent=0;
|
||||||
|
uint64_t created=std::time(nullptr);
|
||||||
|
uint64_t expires=0;
|
||||||
|
uint64_t completed=0;
|
||||||
|
uint64_t canceled=0;
|
||||||
|
|
||||||
|
void to_json(Poco::JSON::Object &Obj) const;
|
||||||
|
bool from_json(Poco::JSON::Object::Ptr &Obj);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,16 +14,18 @@
|
|||||||
#include "framework/MicroService.h"
|
#include "framework/MicroService.h"
|
||||||
|
|
||||||
namespace OpenWifi {
|
namespace OpenWifi {
|
||||||
class SMSSender * SMSSender::instance_ = nullptr;
|
|
||||||
|
|
||||||
int SMSSender::Start() {
|
int SMSSender::Start() {
|
||||||
Provider_ = MicroService::instance().ConfigGetString("sms.provider","aws");
|
Enabled_ = MicroService::instance().ConfigGetBool("smssender.enabled",false);
|
||||||
|
if(Enabled_) {
|
||||||
|
Provider_ = MicroService::instance().ConfigGetString("smssender.provider","aws");
|
||||||
if(Provider_=="aws") {
|
if(Provider_=="aws") {
|
||||||
ProviderImpl_ = std::make_unique<SMS_provider_aws>(Logger_);
|
ProviderImpl_ = std::make_unique<SMS_provider_aws>(Logger_);
|
||||||
} else if(Provider_=="twilio") {
|
} else if(Provider_=="twilio") {
|
||||||
ProviderImpl_ = std::make_unique<SMS_provider_twilio>(Logger_);
|
ProviderImpl_ = std::make_unique<SMS_provider_twilio>(Logger_);
|
||||||
}
|
}
|
||||||
Enabled_ = ProviderImpl_->Initialize();
|
Enabled_ = ProviderImpl_->Initialize();
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,16 +18,14 @@ namespace OpenWifi {
|
|||||||
std::string Number;
|
std::string Number;
|
||||||
std::string Code;
|
std::string Code;
|
||||||
std::string UserName;
|
std::string UserName;
|
||||||
uint64_t Created;
|
uint64_t Created = std::time(nullptr);
|
||||||
bool Validated = false;
|
bool Validated = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SMSSender : public SubSystemServer {
|
class SMSSender : public SubSystemServer {
|
||||||
public:
|
public:
|
||||||
static SMSSender *instance() {
|
static SMSSender *instance() {
|
||||||
if (instance_ == nullptr) {
|
static auto *instance_ = new SMSSender;
|
||||||
instance_ = new SMSSender;
|
|
||||||
}
|
|
||||||
return instance_;
|
return instance_;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,7 +37,6 @@ namespace OpenWifi {
|
|||||||
bool IsNumberValid(const std::string &Number, const std::string &UserName);
|
bool IsNumberValid(const std::string &Number, const std::string &UserName);
|
||||||
[[nodiscard]] bool Send(const std::string &PhoneNumber, const std::string &Message);
|
[[nodiscard]] bool Send(const std::string &PhoneNumber, const std::string &Message);
|
||||||
private:
|
private:
|
||||||
static SMSSender * instance_;
|
|
||||||
std::string Provider_;
|
std::string Provider_;
|
||||||
bool Enabled_=false;
|
bool Enabled_=false;
|
||||||
std::vector<SMSValidationCacheEntry> Cache_;
|
std::vector<SMSValidationCacheEntry> Cache_;
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ namespace OpenWifi {
|
|||||||
if(!Running_)
|
if(!Running_)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
try {
|
||||||
Aws::SNS::SNSClient sns(AwsCreds_,AwsConfig_);
|
Aws::SNS::SNSClient sns(AwsCreds_,AwsConfig_);
|
||||||
Aws::SNS::Model::PublishRequest psms_req;
|
Aws::SNS::Model::PublishRequest psms_req;
|
||||||
psms_req.SetMessage(Message.c_str());
|
psms_req.SetMessage(Message.c_str());
|
||||||
@@ -56,6 +57,11 @@ namespace OpenWifi {
|
|||||||
std::string ErrMsg{psms_out.GetError().GetMessage()};
|
std::string ErrMsg{psms_out.GetError().GetMessage()};
|
||||||
Logger_.debug(Poco::format("SMS NOT sent to %s: %s",PhoneNumber, ErrMsg));
|
Logger_.debug(Poco::format("SMS NOT sent to %s: %s",PhoneNumber, ErrMsg));
|
||||||
return false;
|
return false;
|
||||||
|
} catch (...) {
|
||||||
|
|
||||||
|
}
|
||||||
|
Logger_.debug(Poco::format("SMS NOT sent to %s: failure in SMS service",PhoneNumber));
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -9,21 +9,19 @@
|
|||||||
#include "Poco/Net/SMTPClientSession.h"
|
#include "Poco/Net/SMTPClientSession.h"
|
||||||
#include "Poco/Net/SecureSMTPClientSession.h"
|
#include "Poco/Net/SecureSMTPClientSession.h"
|
||||||
#include "Poco/Net/StringPartSource.h"
|
#include "Poco/Net/StringPartSource.h"
|
||||||
#include "Poco/Path.h"
|
|
||||||
#include "Poco/Exception.h"
|
#include "Poco/Exception.h"
|
||||||
#include "Poco/Net/SSLManager.h"
|
#include "Poco/Net/SSLManager.h"
|
||||||
#include "Poco/Net/Context.h"
|
#include "Poco/Net/Context.h"
|
||||||
#include "Poco/Net/InvalidCertificateHandler.h"
|
|
||||||
#include "Poco/Net/AcceptCertificateHandler.h"
|
|
||||||
|
|
||||||
#include "SMTPMailerService.h"
|
#include "SMTPMailerService.h"
|
||||||
#include "framework/MicroService.h"
|
#include "framework/MicroService.h"
|
||||||
|
#include "AuthService.h"
|
||||||
|
|
||||||
namespace OpenWifi {
|
namespace OpenWifi {
|
||||||
|
|
||||||
class SMTPMailerService * SMTPMailerService::instance_ = nullptr;
|
|
||||||
|
|
||||||
void SMTPMailerService::LoadMyConfig() {
|
void SMTPMailerService::LoadMyConfig() {
|
||||||
|
Enabled_ = MicroService::instance().ConfigGetBool("mailer.enabled",false);
|
||||||
|
if(Enabled_) {
|
||||||
MailHost_ = MicroService::instance().ConfigGetString("mailer.hostname");
|
MailHost_ = MicroService::instance().ConfigGetString("mailer.hostname");
|
||||||
SenderLoginUserName_ = MicroService::instance().ConfigGetString("mailer.username");
|
SenderLoginUserName_ = MicroService::instance().ConfigGetString("mailer.username");
|
||||||
SenderLoginPassword_ = MicroService::instance().ConfigGetString("mailer.password");
|
SenderLoginPassword_ = MicroService::instance().ConfigGetString("mailer.password");
|
||||||
@@ -31,8 +29,11 @@ namespace OpenWifi {
|
|||||||
LoginMethod_ = MicroService::instance().ConfigGetString("mailer.loginmethod");
|
LoginMethod_ = MicroService::instance().ConfigGetString("mailer.loginmethod");
|
||||||
MailHostPort_ = (int) MicroService::instance().ConfigGetInt("mailer.port");
|
MailHostPort_ = (int) MicroService::instance().ConfigGetInt("mailer.port");
|
||||||
TemplateDir_ = MicroService::instance().ConfigPath("mailer.templates", MicroService::instance().DataDir());
|
TemplateDir_ = MicroService::instance().ConfigPath("mailer.templates", MicroService::instance().DataDir());
|
||||||
|
MailRetry_ = (int) MicroService::instance().ConfigGetInt("mailer.retry",2*60);
|
||||||
|
MailAbandon_ = (int) MicroService::instance().ConfigGetInt("mailer.abandon",2*60*60);
|
||||||
Enabled_ = (!MailHost_.empty() && !SenderLoginPassword_.empty() && !SenderLoginUserName_.empty());
|
Enabled_ = (!MailHost_.empty() && !SenderLoginPassword_.empty() && !SenderLoginUserName_.empty());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int SMTPMailerService::Start() {
|
int SMTPMailerService::Start() {
|
||||||
LoadMyConfig();
|
LoadMyConfig();
|
||||||
@@ -54,57 +55,46 @@ namespace OpenWifi {
|
|||||||
|
|
||||||
bool SMTPMailerService::SendMessage(const std::string &Recipient, const std::string &Name, const MessageAttributes &Attrs) {
|
bool SMTPMailerService::SendMessage(const std::string &Recipient, const std::string &Name, const MessageAttributes &Attrs) {
|
||||||
std::lock_guard G(Mutex_);
|
std::lock_guard G(Mutex_);
|
||||||
|
PendingMessages_.push_back(MessageEvent{.Posted=(uint64_t )std::time(nullptr),
|
||||||
/*
|
|
||||||
uint64_t Now = std::time(nullptr);
|
|
||||||
std::string RecipientLower = Poco::toLower(Recipient);
|
|
||||||
auto CE = Cache_.find(RecipientLower);
|
|
||||||
if(CE!=Cache_.end()) {
|
|
||||||
// only allow messages to the same user within 2 minutes
|
|
||||||
if(!((CE->second.LastRequest-Now)<30 && CE->second.HowManyRequests<10))
|
|
||||||
return false;
|
|
||||||
if(CE->second.LastRequest-Now>30) {
|
|
||||||
CE->second.LastRequest = Now;
|
|
||||||
CE->second.HowManyRequests=0;
|
|
||||||
} else {
|
|
||||||
CE->second.HowManyRequests++;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Cache_[RecipientLower] = MessageCacheEntry{.LastRequest=Now, .HowManyRequests=0};
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
Messages_.push_back(MessageEvent{.Posted=(uint64_t )std::time(nullptr),
|
|
||||||
.LastTry=0,
|
.LastTry=0,
|
||||||
.Sent=0,
|
.Sent=0,
|
||||||
.File=Poco::File(TemplateDir_ + "/" +Name),
|
.File=Poco::File(TemplateDir_ + "/" +Name),
|
||||||
.Attrs=Attrs});
|
.Attrs=Attrs});
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SMTPMailerService::run() {
|
void SMTPMailerService::run() {
|
||||||
|
|
||||||
Running_ = true;
|
Running_ = true;
|
||||||
while(Running_) {
|
while(Running_) {
|
||||||
|
|
||||||
Poco::Thread::trySleep(10000);
|
Poco::Thread::trySleep(10000);
|
||||||
if(!Running_)
|
if(!Running_)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
{
|
{
|
||||||
std::lock_guard G(Mutex_);
|
std::lock_guard G(Mutex_);
|
||||||
|
Messages_.splice(Messages_.end(),PendingMessages_);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(auto i=Messages_.begin();i!=Messages_.end();) {
|
||||||
|
if(!Running_)
|
||||||
|
break;
|
||||||
|
auto Recipient = i->Attrs.find(RECIPIENT_EMAIL)->second;
|
||||||
uint64_t Now = std::time(nullptr);
|
uint64_t Now = std::time(nullptr);
|
||||||
|
if((i->LastTry==0 || (Now-i->LastTry)>MailRetry_)) {
|
||||||
for(auto &i:Messages_) {
|
if (SendIt(*i)) {
|
||||||
if(i.Sent==0 && (i.LastTry==0 || (Now-i.LastTry)>120)) {
|
Logger_.information(Poco::format("Attempting to deliver for mail '%s'.", Recipient));
|
||||||
if (SendIt(i)) {
|
i = Messages_.erase(i);
|
||||||
i.LastTry = i.Sent = std::time(nullptr);
|
} else {
|
||||||
} else
|
i->LastTry = Now;
|
||||||
i.LastTry = std::time(nullptr);
|
++i;
|
||||||
}
|
}
|
||||||
|
} else if ((Now-i->Posted)>MailAbandon_) {
|
||||||
|
Logger_.information(Poco::format("Mail for '%s' has timed out and will not be sent.", Recipient));
|
||||||
|
i = Messages_.erase(i);
|
||||||
|
} else {
|
||||||
|
++i;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clean the list
|
|
||||||
std::remove_if(Messages_.begin(),Messages_.end(),[Now](MessageEvent &E){ return (E.Sent!=0 || ((Now-E.LastTry)>(15*60)));});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -116,10 +106,12 @@ namespace OpenWifi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool SMTPMailerService::SendIt(const MessageEvent &Msg) {
|
bool SMTPMailerService::SendIt(const MessageEvent &Msg) {
|
||||||
|
std::string Recipient;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Poco::Net::MailMessage Message;
|
Poco::Net::MailMessage Message;
|
||||||
std::string Recipient = Msg.Attrs.find(RECIPIENT_EMAIL)->second;
|
Recipient = Msg.Attrs.find(RECIPIENT_EMAIL)->second;
|
||||||
|
|
||||||
auto H1 = Msg.Attrs.find(SENDER);
|
auto H1 = Msg.Attrs.find(SENDER);
|
||||||
std::string TheSender;
|
std::string TheSender;
|
||||||
@@ -130,7 +122,6 @@ namespace OpenWifi {
|
|||||||
}
|
}
|
||||||
Message.setSender( TheSender );
|
Message.setSender( TheSender );
|
||||||
Logger_.information(Poco::format("Sending message to:%s from %s",Recipient,TheSender));
|
Logger_.information(Poco::format("Sending message to:%s from %s",Recipient,TheSender));
|
||||||
|
|
||||||
Message.addRecipient(Poco::Net::MailRecipient(Poco::Net::MailRecipient::PRIMARY_RECIPIENT, Recipient));
|
Message.addRecipient(Poco::Net::MailRecipient(Poco::Net::MailRecipient::PRIMARY_RECIPIENT, Recipient));
|
||||||
Message.setSubject(Msg.Attrs.find(SUBJECT)->second);
|
Message.setSubject(Msg.Attrs.find(SUBJECT)->second);
|
||||||
|
|
||||||
@@ -147,21 +138,26 @@ namespace OpenWifi {
|
|||||||
|
|
||||||
auto Logo = Msg.Attrs.find(LOGO);
|
auto Logo = Msg.Attrs.find(LOGO);
|
||||||
if(Logo!=Msg.Attrs.end()) {
|
if(Logo!=Msg.Attrs.end()) {
|
||||||
Poco::File LogoFile(TemplateDir_ + "/" + Logo->second);
|
try {
|
||||||
|
Poco::File LogoFile(AuthService::GetLogoAssetFileName());
|
||||||
std::ifstream IF(LogoFile.path());
|
std::ifstream IF(LogoFile.path());
|
||||||
std::ostringstream OS;
|
std::ostringstream OS;
|
||||||
Poco::StreamCopier::copyStream(IF, OS);
|
Poco::StreamCopier::copyStream(IF, OS);
|
||||||
Message.addAttachment("logo", new Poco::Net::StringPartSource(OS.str(), "image/jpeg"));
|
Message.addAttachment("logo", new Poco::Net::StringPartSource(OS.str(), "image/png"));
|
||||||
|
} catch (...) {
|
||||||
|
Logger_.warning(Poco::format("Cannot add '%s' logo in email",AuthService::GetLogoAssetFileName()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Poco::SharedPtr<Poco::Net::AcceptCertificateHandler> ptrHandler_ = new Poco::Net::AcceptCertificateHandler(false);
|
||||||
|
|
||||||
Poco::Net::SecureSMTPClientSession session(MailHost_,MailHostPort_);
|
Poco::Net::SecureSMTPClientSession session(MailHost_,MailHostPort_);
|
||||||
Poco::Net::Context::Params P;
|
|
||||||
auto ptrContext = Poco::AutoPtr<Poco::Net::Context>
|
auto ptrContext = Poco::AutoPtr<Poco::Net::Context>
|
||||||
(new Poco::Net::Context(Poco::Net::Context::CLIENT_USE, "", "", "",
|
(new Poco::Net::Context(Poco::Net::Context::CLIENT_USE, "", "", "",
|
||||||
Poco::Net::Context::VERIFY_RELAXED, 9, true,
|
Poco::Net::Context::VERIFY_RELAXED, 9, true,
|
||||||
"ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"));
|
"ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"));
|
||||||
Poco::Net::SSLManager::instance().initializeClient(nullptr,
|
Poco::Net::SSLManager::instance().initializeClient(nullptr,
|
||||||
&ptrHandler_,
|
ptrHandler_,
|
||||||
ptrContext);
|
ptrContext);
|
||||||
session.login();
|
session.login();
|
||||||
session.startTLS(ptrContext);
|
session.startTLS(ptrContext);
|
||||||
@@ -178,6 +174,9 @@ namespace OpenWifi {
|
|||||||
{
|
{
|
||||||
Logger_.log(E);
|
Logger_.log(E);
|
||||||
}
|
}
|
||||||
|
catch (const std::exception &E) {
|
||||||
|
Logger_.warning(Poco::format("Cannot send message to:%s, error: %s",Recipient, E.what()));
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -59,9 +59,7 @@ namespace OpenWifi {
|
|||||||
class SMTPMailerService : public SubSystemServer, Poco::Runnable {
|
class SMTPMailerService : public SubSystemServer, Poco::Runnable {
|
||||||
public:
|
public:
|
||||||
static SMTPMailerService *instance() {
|
static SMTPMailerService *instance() {
|
||||||
if (instance_ == nullptr) {
|
static auto * instance_ = new SMTPMailerService;
|
||||||
instance_ = new SMTPMailerService;
|
|
||||||
}
|
|
||||||
return instance_;
|
return instance_;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,42 +71,35 @@ namespace OpenWifi {
|
|||||||
MessageAttributes Attrs;
|
MessageAttributes Attrs;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MessageCacheEntry {
|
|
||||||
uint64_t LastRequest=0;
|
|
||||||
uint64_t HowManyRequests=0;
|
|
||||||
};
|
|
||||||
|
|
||||||
void run() override;
|
void run() override;
|
||||||
|
|
||||||
int Start() override;
|
int Start() override;
|
||||||
void Stop() override;
|
void Stop() override;
|
||||||
|
|
||||||
bool SendMessage(const std::string &Recipient, const std::string &Name, const MessageAttributes &Attrs);
|
bool SendMessage(const std::string &Recipient, const std::string &Name, const MessageAttributes &Attrs);
|
||||||
bool SendIt(const MessageEvent &Msg);
|
bool SendIt(const MessageEvent &Msg);
|
||||||
void LoadMyConfig();
|
void LoadMyConfig();
|
||||||
void reinitialize(Poco::Util::Application &self) override;
|
void reinitialize(Poco::Util::Application &self) override;
|
||||||
bool Enabled() const { return Enabled_; }
|
bool Enabled() const { return Enabled_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static SMTPMailerService * instance_;
|
|
||||||
std::string MailHost_;
|
std::string MailHost_;
|
||||||
std::string Sender_;
|
std::string Sender_;
|
||||||
int MailHostPort_=25;
|
int MailHostPort_=25;
|
||||||
|
int MailRetry_=2*60;
|
||||||
|
int MailAbandon_=2*60*20;
|
||||||
std::string SenderLoginUserName_;
|
std::string SenderLoginUserName_;
|
||||||
std::string SenderLoginPassword_;
|
std::string SenderLoginPassword_;
|
||||||
std::string LoginMethod_ = "login";
|
std::string LoginMethod_ = "login";
|
||||||
std::string LogoFileName_;
|
|
||||||
std::string TemplateDir_;
|
std::string TemplateDir_;
|
||||||
std::list<MessageEvent> Messages_;
|
std::list<MessageEvent> Messages_;
|
||||||
std::map<std::string,MessageCacheEntry> Cache_;
|
std::list<MessageEvent> PendingMessages_;
|
||||||
Poco::Thread SenderThr_;
|
Poco::Thread SenderThr_;
|
||||||
std::atomic_bool Running_=false;
|
std::atomic_bool Running_=false;
|
||||||
bool Enabled_=false;
|
bool Enabled_=false;
|
||||||
Poco::Net::AcceptCertificateHandler ptrHandler_;
|
|
||||||
|
|
||||||
SMTPMailerService() noexcept:
|
SMTPMailerService() noexcept:
|
||||||
SubSystemServer("SMTPMailer", "MAILER-SVR", "smtpmailer"),
|
SubSystemServer("SMTPMailer", "MAILER-SVR", "smtpmailer")
|
||||||
ptrHandler_(false)
|
|
||||||
{
|
{
|
||||||
std::string E{"SHA512"};
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -10,19 +10,34 @@
|
|||||||
|
|
||||||
namespace OpenWifi {
|
namespace OpenWifi {
|
||||||
|
|
||||||
class Storage *Storage::instance_ = nullptr;
|
|
||||||
|
|
||||||
int Storage::Start() {
|
int Storage::Start() {
|
||||||
std::lock_guard Guard(Mutex_);
|
std::lock_guard Guard(Mutex_);
|
||||||
|
|
||||||
StorageClass::Start();
|
StorageClass::Start();
|
||||||
Create_Tables();
|
Create_Tables();
|
||||||
|
InitializeDefaultUser();
|
||||||
|
|
||||||
|
Archivercallback_ = std::make_unique<Poco::TimerCallback<Archiver>>(Archiver_,&Archiver::onTimer);
|
||||||
|
Timer_.setStartInterval( 5 * 60 * 1000); // first run in 5 minutes
|
||||||
|
Timer_.setPeriodicInterval(1 * 60 * 60 * 1000); // 1 hours
|
||||||
|
Timer_.start(*Archivercallback_);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Storage::Stop() {
|
void Storage::Stop() {
|
||||||
Logger_.notice("Stopping.");
|
Logger_.notice("Stopping.");
|
||||||
|
Timer_.stop();
|
||||||
StorageClass::Stop();
|
StorageClass::Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Archiver::onTimer(Poco::Timer &timer) {
|
||||||
|
Poco::Logger &logger = Poco::Logger::get("STORAGE-ARCHIVER");
|
||||||
|
logger.information("Squiggy the DB: removing old tokens.");
|
||||||
|
StorageService()->CleanExpiredTokens();
|
||||||
|
logger.information("Squiggy the DB: removing old actionLinks.");
|
||||||
|
StorageService()->CleanOldActionLinks();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
// namespace
|
// namespace
|
||||||
@@ -13,36 +13,10 @@
|
|||||||
#include "framework/StorageClass.h"
|
#include "framework/StorageClass.h"
|
||||||
#include "AuthService.h"
|
#include "AuthService.h"
|
||||||
|
|
||||||
|
#include "Poco/Timer.h"
|
||||||
|
|
||||||
namespace OpenWifi {
|
namespace OpenWifi {
|
||||||
|
|
||||||
static const std::string AllActionLinksFieldsForSelect {
|
|
||||||
"Id, "
|
|
||||||
"Action,"
|
|
||||||
"UserId,"
|
|
||||||
"template,"
|
|
||||||
"locale,"
|
|
||||||
"message,"
|
|
||||||
"sent,"
|
|
||||||
"created,"
|
|
||||||
"expires,"
|
|
||||||
"completed,"
|
|
||||||
"canceled"
|
|
||||||
};
|
|
||||||
|
|
||||||
static const std::string AllActionLinksFieldsForUpdate {
|
|
||||||
"Id=?, "
|
|
||||||
"Action=?,"
|
|
||||||
"UserId=?,"
|
|
||||||
"template=?,"
|
|
||||||
"locale=?,"
|
|
||||||
"message=?,"
|
|
||||||
"sent=?,"
|
|
||||||
"created=?,"
|
|
||||||
"expires=?,"
|
|
||||||
"completed=?,"
|
|
||||||
"canceled=?"
|
|
||||||
};
|
|
||||||
|
|
||||||
static const std::string AllEmailTemplatesFieldsForCreation {
|
static const std::string AllEmailTemplatesFieldsForCreation {
|
||||||
|
|
||||||
};
|
};
|
||||||
@@ -55,6 +29,12 @@ namespace OpenWifi {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Archiver {
|
||||||
|
public:
|
||||||
|
void onTimer(Poco::Timer & timer);
|
||||||
|
private:
|
||||||
|
};
|
||||||
|
|
||||||
class Storage : public StorageClass {
|
class Storage : public StorageClass {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@@ -90,7 +70,7 @@ namespace OpenWifi {
|
|||||||
return UNKNOWN;
|
return UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const std::string from_userType(USER_TYPE U) {
|
static std::string from_userType(USER_TYPE U) {
|
||||||
switch(U) {
|
switch(U) {
|
||||||
case ROOT: return "root";
|
case ROOT: return "root";
|
||||||
case ADMIN: return "admin";
|
case ADMIN: return "admin";
|
||||||
@@ -104,9 +84,7 @@ namespace OpenWifi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Storage *instance() {
|
static Storage *instance() {
|
||||||
if (instance_ == nullptr) {
|
static auto * instance_ = new Storage;
|
||||||
instance_ = new Storage;
|
|
||||||
}
|
|
||||||
return instance_;
|
return instance_;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,7 +94,8 @@ namespace OpenWifi {
|
|||||||
/*
|
/*
|
||||||
* All user management functions
|
* All user management functions
|
||||||
*/
|
*/
|
||||||
bool CreateUser(const std::string & Admin, SecurityObjects::UserInfo & NewUser);
|
bool InitializeDefaultUser();
|
||||||
|
bool CreateUser(const std::string & Admin, SecurityObjects::UserInfo & NewUser, bool PasswordHashedAlready = false);
|
||||||
bool GetUserByEmail(std::string & email, SecurityObjects::UserInfo & User);
|
bool GetUserByEmail(std::string & email, SecurityObjects::UserInfo & User);
|
||||||
bool GetUserById(USER_ID_TYPE & Id, SecurityObjects::UserInfo & User);
|
bool GetUserById(USER_ID_TYPE & Id, SecurityObjects::UserInfo & User);
|
||||||
bool DeleteUser(const std::string & Admin, USER_ID_TYPE & Id);
|
bool DeleteUser(const std::string & Admin, USER_ID_TYPE & Id);
|
||||||
@@ -133,28 +112,38 @@ namespace OpenWifi {
|
|||||||
bool GetAvatar(const std::string & Admin, std::string &Id, Poco::TemporaryFile &FileName, std::string &Type, std::string & Name);
|
bool GetAvatar(const std::string & Admin, std::string &Id, Poco::TemporaryFile &FileName, std::string &Type, std::string & Name);
|
||||||
bool DeleteAvatar(const std::string & Admin, std::string &Id);
|
bool DeleteAvatar(const std::string & Admin, std::string &Id);
|
||||||
|
|
||||||
bool AddToken(std::string &UserName, std::string &Token, std::string &RefreshToken, std::string & TokenType, uint64_t Expires, uint64_t TimeOut);
|
bool AddToken(std::string &UserId, std::string &Token, std::string &RefreshToken, std::string & TokenType, uint64_t Expires, uint64_t TimeOut);
|
||||||
bool RevokeToken( std::string & Token );
|
bool RevokeToken( std::string & Token );
|
||||||
bool IsTokenRevoked( std::string & Token );
|
bool IsTokenRevoked( std::string & Token );
|
||||||
bool CleanRevokedTokens( uint64_t Oldest );
|
bool CleanExpiredTokens();
|
||||||
bool RevokeAllTokens( std::string & UserName );
|
bool RevokeAllTokens( std::string & UserName );
|
||||||
bool GetToken(std::string &Token, SecurityObjects::UserInfoAndPolicy &UInfo);
|
bool GetToken(std::string &Token, SecurityObjects::UserInfoAndPolicy &UInfo, uint64_t &RevocationDate);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* All ActionLinks functions
|
* All ActionLinks functions
|
||||||
*/
|
*/
|
||||||
bool CreateAction(std::string &ActionId, std::string &Action, USER_ID_TYPE & Id, Types::StringPairVec & Elements );
|
bool CreateAction( SecurityObjects::ActionLink & A);
|
||||||
bool DeleteAction(std::string &ActionId);
|
bool DeleteAction(std::string &ActionId);
|
||||||
bool CompleteAction(std::string &ActionId);
|
bool CompleteAction(std::string &ActionId);
|
||||||
bool CancelAction(std::string &ActionId);
|
bool CancelAction(std::string &ActionId);
|
||||||
|
bool SentAction(std::string &ActionId);
|
||||||
|
bool GetActionLink(std::string &ActionId, SecurityObjects::ActionLink &A);
|
||||||
|
bool GetActions(std::vector<SecurityObjects::ActionLink> &Links, uint64_t Max=200);
|
||||||
|
void CleanOldActionLinks();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static Storage *instance_;
|
|
||||||
|
|
||||||
int Create_Tables();
|
int Create_Tables();
|
||||||
int Create_UserTable();
|
int Create_UserTable();
|
||||||
int Create_AvatarTable();
|
int Create_AvatarTable();
|
||||||
int Create_TokensTable();
|
int Create_TokensTable();
|
||||||
|
int Create_ActionLinkTable();
|
||||||
|
|
||||||
|
Poco::Timer Timer_;
|
||||||
|
Archiver Archiver_;
|
||||||
|
std::unique_ptr<Poco::TimerCallback<Archiver>> Archivercallback_;
|
||||||
|
|
||||||
|
/// This is to support a mistake that was deployed...
|
||||||
|
void ReplaceOldDefaultUUID();
|
||||||
};
|
};
|
||||||
|
|
||||||
inline Storage * StorageService() { return Storage::instance(); };
|
inline Storage * StorageService() { return Storage::instance(); };
|
||||||
|
|||||||
2479
src/framework/ConfigurationValidator.cpp
Normal file
2479
src/framework/ConfigurationValidator.cpp
Normal file
File diff suppressed because it is too large
Load Diff
46
src/framework/ConfigurationValidator.h
Normal file
46
src/framework/ConfigurationValidator.h
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
//
|
||||||
|
// Created by stephane bourque on 2021-09-14.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef OWPROV_CONFIGURATIONVALIDATOR_H
|
||||||
|
#define OWPROV_CONFIGURATIONVALIDATOR_H
|
||||||
|
|
||||||
|
#include <nlohmann/json-schema.hpp>
|
||||||
|
#include "framework/MicroService.h"
|
||||||
|
|
||||||
|
using nlohmann::json;
|
||||||
|
using nlohmann::json_schema::json_validator;
|
||||||
|
|
||||||
|
namespace OpenWifi {
|
||||||
|
class ConfigurationValidator : public SubSystemServer {
|
||||||
|
public:
|
||||||
|
|
||||||
|
static ConfigurationValidator *instance() {
|
||||||
|
if(instance_== nullptr)
|
||||||
|
instance_ = new ConfigurationValidator;
|
||||||
|
return instance_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Validate(const std::string &C, std::string &Error);
|
||||||
|
static void my_format_checker(const std::string &format, const std::string &value);
|
||||||
|
int Start() override;
|
||||||
|
void Stop() override;
|
||||||
|
void reinitialize(Poco::Util::Application &self) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static ConfigurationValidator * instance_;
|
||||||
|
bool Initialized_=false;
|
||||||
|
bool Working_=false;
|
||||||
|
void Init();
|
||||||
|
std::unique_ptr<json_validator> Validator_=std::make_unique<json_validator>(nullptr, my_format_checker);
|
||||||
|
|
||||||
|
ConfigurationValidator():
|
||||||
|
SubSystemServer("configvalidator", "CFG-VALIDATOR", "config.validator") {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline ConfigurationValidator * ConfigurationValidator() { return ConfigurationValidator::instance(); }
|
||||||
|
inline bool ValidateUCentralConfiguration(const std::string &C, std::string &Error) { return ConfigurationValidator::instance()->Validate(C, Error); }
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //OWPROV_CONFIGURATIONVALIDATOR_H
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -47,13 +47,19 @@ namespace OpenWifi::RESTAPI::Errors {
|
|||||||
static const std::string IdMustBe0{"To create a user, you must set the ID to 0"};
|
static const std::string IdMustBe0{"To create a user, you must set the ID to 0"};
|
||||||
static const std::string InvalidUserRole{"Invalid userRole."};
|
static const std::string InvalidUserRole{"Invalid userRole."};
|
||||||
static const std::string InvalidEmailAddress{"Invalid email address."};
|
static const std::string InvalidEmailAddress{"Invalid email address."};
|
||||||
static const std::string InvalidPassword{"Invalid password."};
|
|
||||||
static const std::string PasswordRejected{"Password was rejected. This maybe an old password."};
|
static const std::string PasswordRejected{"Password was rejected. This maybe an old password."};
|
||||||
static const std::string InvalidIPRanges{"Invalid IP range specifications."};
|
static const std::string InvalidIPRanges{"Invalid IP range specifications."};
|
||||||
static const std::string InvalidLOrderBy{"Invalid orderBy specification."};
|
static const std::string InvalidLOrderBy{"Invalid orderBy specification."};
|
||||||
static const std::string NeedMobileNumber{"You must provide at least one validated phone number."};
|
static const std::string NeedMobileNumber{"You must provide at least one validated phone number."};
|
||||||
static const std::string BadMFAMethod{"MFA only supports sms or email."};
|
static const std::string BadMFAMethod{"MFA only supports sms or email."};
|
||||||
|
static const std::string InvalidCredentials{"Invalid credentials (username/password)."};
|
||||||
|
static const std::string InvalidPassword{"Password does not conform to basic password rules."};
|
||||||
|
static const std::string UserPendingVerification{"User access denied pending email verification."};
|
||||||
|
static const std::string PasswordMustBeChanged{"Password must be changed."};
|
||||||
|
static const std::string UnrecognizedRequest{"Ill-formed request. Please consult documentation."};
|
||||||
|
static const std::string MissingAuthenticationInformation{"Missing authentication information."};
|
||||||
|
static const std::string InsufficientAccessRights{"Insufficient access rights to complete the operation."};
|
||||||
|
static const std::string ExpiredToken{"Token has expired, user must login."};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //OWPROV_RESTAPI_ERRORS_H
|
#endif //OWPROV_RESTAPI_ERRORS_H
|
||||||
|
|||||||
@@ -26,13 +26,6 @@ namespace OpenWifi {
|
|||||||
|
|
||||||
class StorageClass : public SubSystemServer {
|
class StorageClass : public SubSystemServer {
|
||||||
public:
|
public:
|
||||||
/* static StorageClass *instance() {
|
|
||||||
if (instance_ == nullptr) {
|
|
||||||
instance_ = new StorageClass;
|
|
||||||
}
|
|
||||||
return instance_;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
StorageClass() noexcept:
|
StorageClass() noexcept:
|
||||||
SubSystemServer("StorageClass", "STORAGE-SVR", "storage")
|
SubSystemServer("StorageClass", "STORAGE-SVR", "storage")
|
||||||
{
|
{
|
||||||
@@ -56,7 +49,7 @@ namespace OpenWifi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Stop() override {
|
void Stop() override {
|
||||||
|
Pool_->shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] inline std::string ComputeRange(uint64_t From, uint64_t HowMany) {
|
[[nodiscard]] inline std::string ComputeRange(uint64_t From, uint64_t HowMany) {
|
||||||
@@ -96,15 +89,13 @@ namespace OpenWifi {
|
|||||||
inline int Setup_PostgreSQL();
|
inline int Setup_PostgreSQL();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::unique_ptr<Poco::Data::SessionPool> Pool_;
|
Poco::SharedPtr<Poco::Data::SessionPool> Pool_;
|
||||||
std::unique_ptr<Poco::Data::SQLite::Connector> SQLiteConn_;
|
Poco::Data::SQLite::Connector SQLiteConn_;
|
||||||
std::unique_ptr<Poco::Data::PostgreSQL::Connector> PostgresConn_;
|
Poco::Data::PostgreSQL::Connector PostgresConn_;
|
||||||
std::unique_ptr<Poco::Data::MySQL::Connector> MySQLConn_;
|
Poco::Data::MySQL::Connector MySQLConn_;
|
||||||
DBType dbType_ = sqlite;
|
DBType dbType_ = sqlite;
|
||||||
};
|
};
|
||||||
|
|
||||||
// inline StorageClass * Storage() { return StorageClass::instance(); }
|
|
||||||
|
|
||||||
#ifdef SMALL_BUILD
|
#ifdef SMALL_BUILD
|
||||||
int Service::Setup_MySQL() { Daemon()->exit(Poco::Util::Application::EXIT_CONFIG); return 0; }
|
int Service::Setup_MySQL() { Daemon()->exit(Poco::Util::Application::EXIT_CONFIG); return 0; }
|
||||||
int Service::Setup_PostgreSQL() { Daemon()->exit(Poco::Util::Application::EXIT_CONFIG); return 0; }
|
int Service::Setup_PostgreSQL() { Daemon()->exit(Poco::Util::Application::EXIT_CONFIG); return 0; }
|
||||||
@@ -116,9 +107,8 @@ namespace OpenWifi {
|
|||||||
auto DBName = MicroService::instance().DataDir() + "/" + MicroService::instance().ConfigGetString("storage.type.sqlite.db");
|
auto DBName = MicroService::instance().DataDir() + "/" + MicroService::instance().ConfigGetString("storage.type.sqlite.db");
|
||||||
auto NumSessions = MicroService::instance().ConfigGetInt("storage.type.sqlite.maxsessions", 64);
|
auto NumSessions = MicroService::instance().ConfigGetInt("storage.type.sqlite.maxsessions", 64);
|
||||||
auto IdleTime = MicroService::instance().ConfigGetInt("storage.type.sqlite.idletime", 60);
|
auto IdleTime = MicroService::instance().ConfigGetInt("storage.type.sqlite.idletime", 60);
|
||||||
SQLiteConn_ = std::make_unique<Poco::Data::SQLite::Connector>();
|
SQLiteConn_.registerConnector();
|
||||||
SQLiteConn_->registerConnector();
|
Pool_ = Poco::SharedPtr<Poco::Data::SessionPool>(new Poco::Data::SessionPool(SQLiteConn_.name(), DBName, 4, NumSessions, IdleTime));
|
||||||
Pool_ = std::make_unique<Poco::Data::SessionPool>(SQLiteConn_->name(), DBName, 4, NumSessions, IdleTime);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,9 +131,8 @@ namespace OpenWifi {
|
|||||||
";port=" + Port +
|
";port=" + Port +
|
||||||
";compress=true;auto-reconnect=true";
|
";compress=true;auto-reconnect=true";
|
||||||
|
|
||||||
MySQLConn_ = std::make_unique<Poco::Data::MySQL::Connector>();
|
MySQLConn_.registerConnector();
|
||||||
MySQLConn_->registerConnector();
|
Pool_ = Poco::SharedPtr<Poco::Data::SessionPool>(new Poco::Data::SessionPool(MySQLConn_.name(), ConnectionStr, 4, NumSessions, IdleTime));
|
||||||
Pool_ = std::make_unique<Poco::Data::SessionPool>(MySQLConn_->name(), ConnectionStr, 4, NumSessions, IdleTime);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -168,9 +157,8 @@ namespace OpenWifi {
|
|||||||
" port=" + Port +
|
" port=" + Port +
|
||||||
" connect_timeout=" + ConnectionTimeout;
|
" connect_timeout=" + ConnectionTimeout;
|
||||||
|
|
||||||
PostgresConn_ = std::make_unique<Poco::Data::PostgreSQL::Connector>();
|
PostgresConn_.registerConnector();
|
||||||
PostgresConn_->registerConnector();
|
Pool_ = Poco::SharedPtr<Poco::Data::SessionPool>(new Poco::Data::SessionPool(PostgresConn_.name(), ConnectionStr, 4, NumSessions, IdleTime));
|
||||||
Pool_ = std::make_unique<Poco::Data::SessionPool>(PostgresConn_->name(), ConnectionStr, 4, NumSessions, IdleTime);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
201
src/storage/storage_actionLinks.cpp
Normal file
201
src/storage/storage_actionLinks.cpp
Normal file
@@ -0,0 +1,201 @@
|
|||||||
|
//
|
||||||
|
// Created by stephane bourque on 2021-11-08.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "storage_actionLinks.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "StorageService.h"
|
||||||
|
#include "RESTObjects/RESTAPI_SecurityObjects.h"
|
||||||
|
#include "framework/MicroService.h"
|
||||||
|
|
||||||
|
namespace OpenWifi {
|
||||||
|
|
||||||
|
bool Convert(const ActionLinkRecord &T, SecurityObjects::ActionLink &U) {
|
||||||
|
U.id = T.get<0>();
|
||||||
|
U.action = T.get<1>();
|
||||||
|
U.userId = T.get<2>();
|
||||||
|
U.actionTemplate = T.get<3>();
|
||||||
|
U.variables = RESTAPI_utils::to_stringpair_array(T.get<4>());
|
||||||
|
U.locale = T.get<5>();
|
||||||
|
U.message = T.get<6>();
|
||||||
|
U.sent = T.get<7>();
|
||||||
|
U.created = T.get<8>();
|
||||||
|
U.expires = T.get<9>();
|
||||||
|
U.completed = T.get<10>();
|
||||||
|
U.canceled = T.get<11>();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Convert(const SecurityObjects::ActionLink &U, ActionLinkRecord &T) {
|
||||||
|
T.set<0>(U.id);
|
||||||
|
T.set<1>(U.action);
|
||||||
|
T.set<2>(U.userId);
|
||||||
|
T.set<3>(U.actionTemplate);
|
||||||
|
T.set<4>(RESTAPI_utils::to_string(U.variables));
|
||||||
|
T.set<5>(U.locale);
|
||||||
|
T.set<6>(U.message);
|
||||||
|
T.set<7>(U.sent);
|
||||||
|
T.set<8>(U.created);
|
||||||
|
T.set<9>(U.expires);
|
||||||
|
T.set<10>(U.completed);
|
||||||
|
T.set<11>(U.canceled);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Storage::CreateAction( SecurityObjects::ActionLink & A) {
|
||||||
|
try {
|
||||||
|
Poco::Data::Session Sess = Pool_->get();
|
||||||
|
Poco::Data::Statement Insert(Sess);
|
||||||
|
std::string St2{
|
||||||
|
"INSERT INTO ActionLinks (" + AllActionLinksFieldsForSelect + ") VALUES(" + AllActionLinksValuesForSelect + ")"};
|
||||||
|
ActionLinkRecord AR;
|
||||||
|
Convert(A, AR);
|
||||||
|
Insert << ConvertParams(St2),
|
||||||
|
Poco::Data::Keywords::use(AR);
|
||||||
|
Insert.execute();
|
||||||
|
return true;
|
||||||
|
} catch (const Poco::Exception &E) {
|
||||||
|
Logger_.log(E);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Storage::GetActions(std::vector<SecurityObjects::ActionLink> &Links, uint64_t Max) {
|
||||||
|
try {
|
||||||
|
Poco::Data::Session Sess = Pool_->get();
|
||||||
|
Poco::Data::Statement Select(Sess);
|
||||||
|
|
||||||
|
ActionLinkRecordList ARL;
|
||||||
|
|
||||||
|
std::string S{
|
||||||
|
"SELECT " + AllActionLinksFieldsForSelect + " From ActionLinks where sent=0 and canceled=0 and completed=0"};
|
||||||
|
Select << ConvertParams(S),
|
||||||
|
Poco::Data::Keywords::into(ARL);
|
||||||
|
Select.execute();
|
||||||
|
|
||||||
|
for(const auto &i:ARL) {
|
||||||
|
SecurityObjects::ActionLink L;
|
||||||
|
Convert(i,L);
|
||||||
|
Links.emplace_back(L);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
|
||||||
|
} catch (const Poco::Exception &E) {
|
||||||
|
Logger_.log(E);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Storage::GetActionLink(std::string &ActionId, SecurityObjects::ActionLink &A) {
|
||||||
|
try {
|
||||||
|
Poco::Data::Session Sess = Pool_->get();
|
||||||
|
Poco::Data::Statement Select(Sess);
|
||||||
|
|
||||||
|
ActionLinkRecord AR;
|
||||||
|
|
||||||
|
std::string St2{
|
||||||
|
"SELECT " + AllActionLinksFieldsForSelect + " From ActionLinks where id=?"};
|
||||||
|
Select << ConvertParams(St2),
|
||||||
|
Poco::Data::Keywords::into(AR),
|
||||||
|
Poco::Data::Keywords::use(ActionId);
|
||||||
|
Select.execute();
|
||||||
|
|
||||||
|
if(Select.rowsExtracted()==1) {
|
||||||
|
Convert(AR, A);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} catch (const Poco::Exception &E) {
|
||||||
|
Logger_.log(E);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Storage::SentAction(std::string &ActionId) {
|
||||||
|
try {
|
||||||
|
Poco::Data::Session Sess = Pool_->get();
|
||||||
|
Poco::Data::Statement Update(Sess);
|
||||||
|
|
||||||
|
uint64_t Sent = std::time(nullptr);
|
||||||
|
std::string St{"UPDATE ActionLinks set Sent=? where id=?"};
|
||||||
|
Update << ConvertParams(St),
|
||||||
|
Poco::Data::Keywords::use(Sent),
|
||||||
|
Poco::Data::Keywords::use(ActionId);
|
||||||
|
Update.execute();
|
||||||
|
return true;
|
||||||
|
} catch (const Poco::Exception &E) {
|
||||||
|
Logger_.log(E);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Storage::DeleteAction(std::string &ActionId) {
|
||||||
|
try {
|
||||||
|
Poco::Data::Session Sess = Pool_->get();
|
||||||
|
Poco::Data::Statement Delete(Sess);
|
||||||
|
|
||||||
|
uint64_t Sent = std::time(nullptr);
|
||||||
|
std::string St{"DELETE FROM ActionLinks where id=?"};
|
||||||
|
Delete << ConvertParams(St),
|
||||||
|
Poco::Data::Keywords::use(ActionId);
|
||||||
|
Delete.execute();
|
||||||
|
return true;
|
||||||
|
} catch (const Poco::Exception &E) {
|
||||||
|
Logger_.log(E);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Storage::CompleteAction(std::string &ActionId) {
|
||||||
|
try {
|
||||||
|
Poco::Data::Session Sess = Pool_->get();
|
||||||
|
Poco::Data::Statement Update(Sess);
|
||||||
|
|
||||||
|
uint64_t completed = std::time(nullptr);
|
||||||
|
std::string St{"UPDATE ActionLinks set completed=? where id=?"};
|
||||||
|
Update << ConvertParams(St),
|
||||||
|
Poco::Data::Keywords::use(completed),
|
||||||
|
Poco::Data::Keywords::use(ActionId);
|
||||||
|
Update.execute();
|
||||||
|
return true;
|
||||||
|
} catch (const Poco::Exception &E) {
|
||||||
|
Logger_.log(E);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Storage::CancelAction(std::string &ActionId) {
|
||||||
|
try {
|
||||||
|
Poco::Data::Session Sess = Pool_->get();
|
||||||
|
Poco::Data::Statement Update(Sess);
|
||||||
|
|
||||||
|
uint64_t canceled = std::time(nullptr);
|
||||||
|
std::string St{"UPDATE ActionLinks set canceled=? where id=?"};
|
||||||
|
Update << ConvertParams(St),
|
||||||
|
Poco::Data::Keywords::use(canceled),
|
||||||
|
Poco::Data::Keywords::use(ActionId);
|
||||||
|
Update.execute();
|
||||||
|
return true;
|
||||||
|
} catch (const Poco::Exception &E) {
|
||||||
|
Logger_.log(E);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Storage::CleanOldActionLinks() {
|
||||||
|
try {
|
||||||
|
Poco::Data::Session Sess = Pool_->get();
|
||||||
|
Poco::Data::Statement Delete(Sess);
|
||||||
|
|
||||||
|
uint64_t CutOff = std::time(nullptr) - (30 * 24 * 60 * 60);
|
||||||
|
std::string St{"DELETE from ActionLinks where Created<=?"};
|
||||||
|
Delete << ConvertParams(St),
|
||||||
|
Poco::Data::Keywords::use(CutOff);
|
||||||
|
Delete.execute();
|
||||||
|
} catch (const Poco::Exception &E) {
|
||||||
|
Logger_.log(E);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
79
src/storage/storage_actionLinks.h
Normal file
79
src/storage/storage_actionLinks.h
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
//
|
||||||
|
// Created by stephane bourque on 2021-11-08.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef OWSEC_STORAGE_ACTIONLINKS_H
|
||||||
|
#define OWSEC_STORAGE_ACTIONLINKS_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include "Poco/Tuple.h"
|
||||||
|
|
||||||
|
namespace OpenWifi {
|
||||||
|
static const std::string AllActionLinksFieldsForCreation{
|
||||||
|
"Id varchar(36),"
|
||||||
|
"Action bigint,"
|
||||||
|
"UserId text,"
|
||||||
|
"template text,"
|
||||||
|
"variables text,"
|
||||||
|
"locale varchar,"
|
||||||
|
"message text,"
|
||||||
|
"sent bigint,"
|
||||||
|
"created bigint,"
|
||||||
|
"expires bigint,"
|
||||||
|
"completed bigint,"
|
||||||
|
"canceled bigint"
|
||||||
|
};
|
||||||
|
|
||||||
|
static const std::string AllActionLinksFieldsForSelect {
|
||||||
|
"Id, "
|
||||||
|
"Action,"
|
||||||
|
"UserId,"
|
||||||
|
"template,"
|
||||||
|
"variables,"
|
||||||
|
"locale,"
|
||||||
|
"message,"
|
||||||
|
"sent,"
|
||||||
|
"created,"
|
||||||
|
"expires,"
|
||||||
|
"completed,"
|
||||||
|
"canceled"
|
||||||
|
};
|
||||||
|
|
||||||
|
static const std::string AllActionLinksValuesForSelect{ "?,?,?,?,?,?,?,?,?,?,?,?" };
|
||||||
|
|
||||||
|
static const std::string AllActionLinksFieldsForUpdate {
|
||||||
|
"Id=?, "
|
||||||
|
"Action=?,"
|
||||||
|
"UserId=?,"
|
||||||
|
"template=?,"
|
||||||
|
"variables=?,"
|
||||||
|
"locale=?,"
|
||||||
|
"message=?,"
|
||||||
|
"sent=?,"
|
||||||
|
"created=?,"
|
||||||
|
"expires=?,"
|
||||||
|
"completed=?,"
|
||||||
|
"canceled=?"
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef Poco::Tuple <
|
||||||
|
std::string, // id
|
||||||
|
uint64_t, // action
|
||||||
|
std::string, // userId
|
||||||
|
std::string, // actionTemplate
|
||||||
|
std::string, // variables
|
||||||
|
std::string, // locale
|
||||||
|
std::string, // message
|
||||||
|
uint64_t, // sent
|
||||||
|
uint64_t, // created
|
||||||
|
uint64_t, // expires
|
||||||
|
uint64_t, // completed
|
||||||
|
uint64_t // canceled
|
||||||
|
> ActionLinkRecord;
|
||||||
|
typedef std::vector <ActionLinkRecord> ActionLinkRecordList;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif //OWSEC_STORAGE_ACTIONLINKS_H
|
||||||
@@ -35,8 +35,7 @@ namespace OpenWifi {
|
|||||||
|
|
||||||
uint64_t Now = std::time(nullptr);
|
uint64_t Now = std::time(nullptr);
|
||||||
|
|
||||||
std::string St2{
|
std::string St2{"INSERT INTO Avatars (" + AllAvatarFieldsForSelect + ") VALUES( " + AllAvatarValuesForSelect + " )"};
|
||||||
"INSERT INTO Avatars (Id,Type,Created,Name,Avatar) VALUES(?,?,?,?,?)"};
|
|
||||||
|
|
||||||
Insert << ConvertParams(St2),
|
Insert << ConvertParams(St2),
|
||||||
Poco::Data::Keywords::use(Id),
|
Poco::Data::Keywords::use(Id),
|
||||||
@@ -58,13 +57,19 @@ namespace OpenWifi {
|
|||||||
Poco::Data::Session Sess = Pool_->get();
|
Poco::Data::Session Sess = Pool_->get();
|
||||||
Poco::Data::Statement Select(Sess);
|
Poco::Data::Statement Select(Sess);
|
||||||
|
|
||||||
std::string St2{"SELECT Avatar, Type, Name FROM Avatars WHERE Id=?"};
|
std::string St2{"SELECT " + AllAvatarFieldsForSelect + " FROM Avatars WHERE Id=?"};
|
||||||
|
|
||||||
Poco::Data::Statement Select2(Sess);
|
Poco::Data::Statement Select2(Sess);
|
||||||
|
|
||||||
|
std::string TId;
|
||||||
|
uint64_t Created;
|
||||||
|
|
||||||
Select2 << ConvertParams(St2),
|
Select2 << ConvertParams(St2),
|
||||||
Poco::Data::Keywords::into(L),
|
Poco::Data::Keywords::into(TId),
|
||||||
Poco::Data::Keywords::into(Type),
|
Poco::Data::Keywords::into(Type),
|
||||||
|
Poco::Data::Keywords::into(Created),
|
||||||
Poco::Data::Keywords::into(Name),
|
Poco::Data::Keywords::into(Name),
|
||||||
|
Poco::Data::Keywords::into(L),
|
||||||
Poco::Data::Keywords::use(Id);
|
Poco::Data::Keywords::use(Id);
|
||||||
Select2.execute();
|
Select2.execute();
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,33 @@
|
|||||||
|
|
||||||
namespace OpenWifi {
|
namespace OpenWifi {
|
||||||
|
|
||||||
|
static const std::string AllAvatarFieldsForCreation_sqlite{
|
||||||
|
"Id VARCHAR(36) PRIMARY KEY, "
|
||||||
|
"Type VARCHAR, "
|
||||||
|
"Created BIGINT, "
|
||||||
|
"Name VARCHAR, "
|
||||||
|
"Avatar BLOB"
|
||||||
|
};
|
||||||
|
|
||||||
|
static const std::string AllAvatarFieldsForCreation_mysql{
|
||||||
|
"Id VARCHAR(36) PRIMARY KEY, "
|
||||||
|
"Type VARCHAR, "
|
||||||
|
"Created BIGINT, "
|
||||||
|
"Name VARCHAR, "
|
||||||
|
"Avatar LONGBLOB"
|
||||||
|
};
|
||||||
|
|
||||||
|
static const std::string AllAvatarFieldsForCreation_pgsql{
|
||||||
|
"Id VARCHAR(36) PRIMARY KEY, "
|
||||||
|
"Type VARCHAR, "
|
||||||
|
"Created BIGINT, "
|
||||||
|
"Name VARCHAR, "
|
||||||
|
"Avatar BYTEA"
|
||||||
|
};
|
||||||
|
|
||||||
|
static const std::string AllAvatarFieldsForSelect{ " Id,Type,Created,Name,Avatar " };
|
||||||
|
static const std::string AllAvatarValuesForSelect{ "?,?,?,?,?" };
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
#include "StorageService.h"
|
#include "StorageService.h"
|
||||||
#include "storage_users.h"
|
#include "storage_users.h"
|
||||||
#include "storage_avatar.h"
|
#include "storage_avatar.h"
|
||||||
|
#include "storage_actionLinks.h"
|
||||||
|
#include "storage_tokens.h"
|
||||||
|
|
||||||
namespace OpenWifi {
|
namespace OpenWifi {
|
||||||
|
|
||||||
@@ -12,6 +14,7 @@ namespace OpenWifi {
|
|||||||
Create_UserTable();
|
Create_UserTable();
|
||||||
Create_AvatarTable();
|
Create_AvatarTable();
|
||||||
Create_TokensTable();
|
Create_TokensTable();
|
||||||
|
Create_ActionLinkTable();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,83 +43,51 @@ namespace OpenWifi {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Storage::Create_ActionLinkTable() {
|
||||||
|
try {
|
||||||
|
Poco::Data::Session Sess = Pool_->get();
|
||||||
|
|
||||||
|
Sess << "CREATE TABLE IF NOT EXISTS ActionLinks ( "
|
||||||
|
+ AllActionLinksFieldsForCreation + " ) ",
|
||||||
|
Poco::Data::Keywords::now;
|
||||||
|
return 0;
|
||||||
|
} catch(const Poco::Exception &E) {
|
||||||
|
Logger_.log(E);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
int Storage::Create_AvatarTable() {
|
int Storage::Create_AvatarTable() {
|
||||||
try {
|
try {
|
||||||
Poco::Data::Session Sess = Pool_->get();
|
Poco::Data::Session Sess = Pool_->get();
|
||||||
|
|
||||||
if(dbType_==sqlite) {
|
if(dbType_==sqlite) {
|
||||||
Sess << "CREATE TABLE IF NOT EXISTS Avatars ("
|
Sess << "CREATE TABLE IF NOT EXISTS Avatars (" + AllAvatarFieldsForCreation_sqlite +
|
||||||
"Id VARCHAR(36) PRIMARY KEY, "
|
|
||||||
"Type VARCHAR, "
|
|
||||||
"Created BIGINT, "
|
|
||||||
"Name VARCHAR, "
|
|
||||||
"Avatar BLOB"
|
|
||||||
") ", Poco::Data::Keywords::now;
|
") ", Poco::Data::Keywords::now;
|
||||||
} else if(dbType_==mysql) {
|
} else if(dbType_==mysql) {
|
||||||
Sess << "CREATE TABLE IF NOT EXISTS Avatars ("
|
Sess << "CREATE TABLE IF NOT EXISTS Avatars (" + AllAvatarFieldsForCreation_mysql +
|
||||||
"Id VARCHAR(36) PRIMARY KEY, "
|
|
||||||
"Type VARCHAR, "
|
|
||||||
"Created BIGINT, "
|
|
||||||
"Name VARCHAR, "
|
|
||||||
"Avatar LONGBLOB"
|
|
||||||
") ", Poco::Data::Keywords::now;
|
") ", Poco::Data::Keywords::now;
|
||||||
} else if(dbType_==pgsql) {
|
} else if(dbType_==pgsql) {
|
||||||
Sess << "CREATE TABLE IF NOT EXISTS Avatars ("
|
Sess << "CREATE TABLE IF NOT EXISTS Avatars (" + AllAvatarFieldsForCreation_pgsql +
|
||||||
"Id VARCHAR(36) PRIMARY KEY, "
|
|
||||||
"Type VARCHAR, "
|
|
||||||
"Created BIGINT, "
|
|
||||||
"Name VARCHAR, "
|
|
||||||
"Avatar BYTEA"
|
|
||||||
") ", Poco::Data::Keywords::now;
|
") ", Poco::Data::Keywords::now;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
} catch(const Poco::Exception &E) {
|
} catch(const Poco::Exception &E) {
|
||||||
Logger_.log(E);
|
Logger_.log(E);
|
||||||
}
|
}
|
||||||
return 0;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Storage::Create_TokensTable() {
|
int Storage::Create_TokensTable() {
|
||||||
try {
|
try {
|
||||||
Poco::Data::Session Sess = Pool_->get();
|
Poco::Data::Session Sess = Pool_->get();
|
||||||
if(dbType_==sqlite) {
|
Sess << "CREATE TABLE IF NOT EXISTS Tokens (" +
|
||||||
Sess << "CREATE TABLE IF NOT EXISTS Tokens ("
|
AllTokensFieldsForCreation +
|
||||||
"Token TEXT PRIMARY KEY, "
|
|
||||||
"RefreshToken TEXT, "
|
|
||||||
"TokenType TEXT, "
|
|
||||||
"UserName TEXT, "
|
|
||||||
"Created BIGINT, "
|
|
||||||
"Expires BIGINT, "
|
|
||||||
"IdleTimeOut BIGINT, "
|
|
||||||
"RevocationDate BIGINT "
|
|
||||||
") ", Poco::Data::Keywords::now;
|
") ", Poco::Data::Keywords::now;
|
||||||
} else if(dbType_==mysql) {
|
|
||||||
Sess << "CREATE TABLE IF NOT EXISTS Tokens ("
|
|
||||||
"Token TEXT PRIMARY KEY, "
|
|
||||||
"RefreshToken TEXT, "
|
|
||||||
"TokenType TEXT, "
|
|
||||||
"UserName TEXT, "
|
|
||||||
"Created BIGINT, "
|
|
||||||
"Expires BIGINT, "
|
|
||||||
"IdleTimeOut BIGINT, "
|
|
||||||
"RevocationDate BIGINT "
|
|
||||||
") ", Poco::Data::Keywords::now;
|
|
||||||
} else if(dbType_==pgsql) {
|
|
||||||
Sess << "CREATE TABLE IF NOT EXISTS Tokens ("
|
|
||||||
"Token TEXT PRIMARY KEY, "
|
|
||||||
"RefreshToken TEXT, "
|
|
||||||
"TokenType TEXT, "
|
|
||||||
"UserName TEXT, "
|
|
||||||
"Created BIGINT, "
|
|
||||||
"Expires BIGINT, "
|
|
||||||
"IdleTimeOut BIGINT, "
|
|
||||||
"RevocationDate BIGINT "
|
|
||||||
") ", Poco::Data::Keywords::now;
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
} catch(const Poco::Exception &E) {
|
} catch(const Poco::Exception &E) {
|
||||||
Logger_.log(E);
|
Logger_.log(E);
|
||||||
}
|
}
|
||||||
return 0;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
|
|
||||||
#include "../StorageService.h"
|
#include "StorageService.h"
|
||||||
|
#include "storage/storage_tokens.h"
|
||||||
|
|
||||||
namespace OpenWifi {
|
namespace OpenWifi {
|
||||||
|
|
||||||
@@ -14,7 +15,7 @@ namespace OpenWifi {
|
|||||||
"RevocationDate BIGINT "
|
"RevocationDate BIGINT "
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool Storage::AddToken(std::string &UserName, std::string &Token, std::string &RefreshToken, std::string & TokenType, uint64_t Expires, uint64_t TimeOut) {
|
bool Storage::AddToken(std::string &UserID, std::string &Token, std::string &RefreshToken, std::string & TokenType, uint64_t Expires, uint64_t TimeOut) {
|
||||||
try {
|
try {
|
||||||
Poco::Data::Session Sess = Pool_->get();
|
Poco::Data::Session Sess = Pool_->get();
|
||||||
Poco::Data::Statement Insert(Sess);
|
Poco::Data::Statement Insert(Sess);
|
||||||
@@ -22,13 +23,13 @@ namespace OpenWifi {
|
|||||||
uint64_t Z = 0;
|
uint64_t Z = 0;
|
||||||
|
|
||||||
std::string St2{
|
std::string St2{
|
||||||
"INSERT INTO Tokens (Token, RefreshToken, TokenType, Username, Created, Expires, IdleTimeOut, RevocationDate) VALUES(?,?,?,?,?,?,?,?)"};
|
"INSERT INTO Tokens (" + AllTokensFieldsForSelect + ") VALUES(" + AllTokensValuesForSelect + ")"};
|
||||||
|
|
||||||
Insert << ConvertParams(St2),
|
Insert << ConvertParams(St2),
|
||||||
Poco::Data::Keywords::use(Token),
|
Poco::Data::Keywords::use(Token),
|
||||||
Poco::Data::Keywords::use(RefreshToken),
|
Poco::Data::Keywords::use(RefreshToken),
|
||||||
Poco::Data::Keywords::use(TokenType),
|
Poco::Data::Keywords::use(TokenType),
|
||||||
Poco::Data::Keywords::use(UserName),
|
Poco::Data::Keywords::use(UserID),
|
||||||
Poco::Data::Keywords::use(Now),
|
Poco::Data::Keywords::use(Now),
|
||||||
Poco::Data::Keywords::use(Expires),
|
Poco::Data::Keywords::use(Expires),
|
||||||
Poco::Data::Keywords::use(TimeOut),
|
Poco::Data::Keywords::use(TimeOut),
|
||||||
@@ -41,29 +42,24 @@ namespace OpenWifi {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Storage::GetToken(std::string &Token, SecurityObjects::UserInfoAndPolicy &UInfo) {
|
bool Storage::GetToken(std::string &Token, SecurityObjects::UserInfoAndPolicy &UInfo, uint64_t &RevocationDate) {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
Poco::Data::Session Sess = Pool_->get();
|
Poco::Data::Session Sess = Pool_->get();
|
||||||
Poco::Data::Statement Select(Sess);
|
Poco::Data::Statement Select(Sess);
|
||||||
|
RevocationDate = 0 ;
|
||||||
uint32_t RevocationDate = 0 ;
|
std::string St2{"SELECT " + AllTokensFieldsForSelect + " From Tokens WHERE Token=?"};
|
||||||
|
|
||||||
std::string St2{"SELECT Token, RefreshToken, TokenType, Username, Created, Expires, IdleTimeOut, RevocationDate From Tokens WHERE Token=?"};
|
|
||||||
Select << ConvertParams(St2),
|
Select << ConvertParams(St2),
|
||||||
Poco::Data::Keywords::into(UInfo.webtoken.access_token_),
|
Poco::Data::Keywords::into(UInfo.webtoken.access_token_),
|
||||||
Poco::Data::Keywords::into(UInfo.webtoken.refresh_token_),
|
Poco::Data::Keywords::into(UInfo.webtoken.refresh_token_),
|
||||||
Poco::Data::Keywords::into(UInfo.webtoken.token_type_),
|
Poco::Data::Keywords::into(UInfo.webtoken.token_type_),
|
||||||
Poco::Data::Keywords::into(UInfo.userinfo.email),
|
Poco::Data::Keywords::into(UInfo.userinfo.Id),
|
||||||
Poco::Data::Keywords::into(UInfo.webtoken.created_),
|
Poco::Data::Keywords::into(UInfo.webtoken.created_),
|
||||||
Poco::Data::Keywords::into(UInfo.webtoken.expires_in_),
|
Poco::Data::Keywords::into(UInfo.webtoken.expires_in_),
|
||||||
Poco::Data::Keywords::into(UInfo.webtoken.idle_timeout_),
|
Poco::Data::Keywords::into(UInfo.webtoken.idle_timeout_),
|
||||||
Poco::Data::Keywords::into(RevocationDate),
|
Poco::Data::Keywords::into(RevocationDate),
|
||||||
Poco::Data::Keywords::use(Token);
|
Poco::Data::Keywords::use(Token);
|
||||||
Select.execute();
|
Select.execute();
|
||||||
|
|
||||||
if(RevocationDate>0)
|
|
||||||
return false;
|
|
||||||
return true;
|
return true;
|
||||||
} catch (const Poco::Exception &E) {
|
} catch (const Poco::Exception &E) {
|
||||||
Logger_.log(E);
|
Logger_.log(E);
|
||||||
@@ -115,15 +111,15 @@ namespace OpenWifi {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Storage::CleanRevokedTokens(uint64_t Oldest) {
|
bool Storage::CleanExpiredTokens() {
|
||||||
try {
|
try {
|
||||||
Poco::Data::Session Sess = Pool_->get();
|
Poco::Data::Session Sess = Pool_->get();
|
||||||
Poco::Data::Statement Delete(Sess);
|
Poco::Data::Statement Delete(Sess);
|
||||||
uint64_t Now = std::time(nullptr);
|
uint64_t Now = std::time(nullptr);
|
||||||
|
|
||||||
std::string St2{"DELETE From Tokens WHERE Created <= ?"};
|
std::string St2{"DELETE From Tokens WHERE (Created+Expires) <= ?"};
|
||||||
Delete << ConvertParams(St2),
|
Delete << ConvertParams(St2),
|
||||||
Poco::Data::Keywords::use(Oldest);
|
Poco::Data::Keywords::use(Now);
|
||||||
Delete.execute();
|
Delete.execute();
|
||||||
return true;
|
return true;
|
||||||
} catch (const Poco::Exception &E) {
|
} catch (const Poco::Exception &E) {
|
||||||
@@ -132,14 +128,14 @@ namespace OpenWifi {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Storage::RevokeAllTokens(std::string & username) {
|
bool Storage::RevokeAllTokens(std::string & UserId) {
|
||||||
try {
|
try {
|
||||||
Poco::Data::Session Sess = Pool_->get();
|
Poco::Data::Session Sess = Pool_->get();
|
||||||
Poco::Data::Statement Delete(Sess);
|
Poco::Data::Statement Delete(Sess);
|
||||||
|
|
||||||
std::string St2{"DELETE From Tokens WHERE Username=?"};
|
std::string St2{"DELETE From Tokens WHERE Username=?"};
|
||||||
Delete << ConvertParams(St2),
|
Delete << ConvertParams(St2),
|
||||||
Poco::Data::Keywords::use(username);
|
Poco::Data::Keywords::use(UserId);
|
||||||
Delete.execute();
|
Delete.execute();
|
||||||
return true;
|
return true;
|
||||||
} catch(const Poco::Exception &E) {
|
} catch(const Poco::Exception &E) {
|
||||||
|
|||||||
30
src/storage/storage_tokens.h
Normal file
30
src/storage/storage_tokens.h
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
//
|
||||||
|
// Created by stephane bourque on 2021-11-08.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef OWSEC_STORAGE_TOKENS_H
|
||||||
|
#define OWSEC_STORAGE_TOKENS_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include "Poco/Tuple.h"
|
||||||
|
|
||||||
|
namespace OpenWifi {
|
||||||
|
|
||||||
|
static std::string AllTokensFieldsForCreation{ "Token TEXT PRIMARY KEY, "
|
||||||
|
"RefreshToken TEXT, "
|
||||||
|
"TokenType TEXT, "
|
||||||
|
"UserName TEXT, "
|
||||||
|
"Created BIGINT, "
|
||||||
|
"Expires BIGINT, "
|
||||||
|
"IdleTimeOut BIGINT, "
|
||||||
|
"RevocationDate BIGINT "
|
||||||
|
};
|
||||||
|
static std::string AllTokensFieldsForSelect {"Token, RefreshToken, TokenType, Username, Created, Expires, IdleTimeOut, RevocationDate"};
|
||||||
|
static std::string AllTokensValuesForSelect{"?,?,?,?,?,?,?,?"};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //OWSEC_STORAGE_TOKENS_H
|
||||||
@@ -80,7 +80,52 @@ namespace OpenWifi {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Storage::CreateUser(const std::string & Admin, SecurityObjects::UserInfo & NewUser) {
|
std::string OldDefaultUseridStockUUID{"DEFAULT-USER-UUID-SHOULD-BE-DELETED!!!"};
|
||||||
|
std::string NewDefaultUseridStockUUID{"11111111-0000-0000-6666-999999999999"};
|
||||||
|
|
||||||
|
void Storage::ReplaceOldDefaultUUID() {
|
||||||
|
try {
|
||||||
|
Poco::Data::Session Sess = Pool_->get();
|
||||||
|
std::string St1{"update users set id=? where id=?"};
|
||||||
|
|
||||||
|
Poco::Data::Statement Update(Sess);
|
||||||
|
Update << ConvertParams(St1),
|
||||||
|
Poco::Data::Keywords::use(NewDefaultUseridStockUUID),
|
||||||
|
Poco::Data::Keywords::use(OldDefaultUseridStockUUID);
|
||||||
|
Update.execute();
|
||||||
|
} catch (...) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we do not find a default user, then we need to create one based on the
|
||||||
|
// property file. We must set its flag to "must change password", this user has root privilege.
|
||||||
|
// if the "DEFAULT-USER-UUID", we keep the UUID of that user. We want to hide the UUID of the default root user
|
||||||
|
bool Storage::InitializeDefaultUser() {
|
||||||
|
SecurityObjects::UserInfo U;
|
||||||
|
bool DefaultUserCreated = false;
|
||||||
|
|
||||||
|
ReplaceOldDefaultUUID();
|
||||||
|
AppServiceRegistry().Get("defaultusercreated",DefaultUserCreated);
|
||||||
|
if(!GetUserById(NewDefaultUseridStockUUID,U) && !DefaultUserCreated) {
|
||||||
|
U.currentPassword = MicroService::instance().ConfigGetString("authentication.default.password","");
|
||||||
|
U.lastPasswords.push_back(U.currentPassword);
|
||||||
|
U.email = MicroService::instance().ConfigGetString("authentication.default.username","");
|
||||||
|
U.Id = NewDefaultUseridStockUUID;
|
||||||
|
U.userRole = SecurityObjects::ROOT;
|
||||||
|
U.creationDate = std::time(nullptr);
|
||||||
|
U.validated = true;
|
||||||
|
U.name = "Default User";
|
||||||
|
U.description = "Default user should be deleted.";
|
||||||
|
U.changePassword = true;
|
||||||
|
CreateUser("SYSTEM",U, true);
|
||||||
|
AppServiceRegistry().Set("defaultusercreated",true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Storage::CreateUser(const std::string & Admin, SecurityObjects::UserInfo & NewUser, bool PasswordHashedAlready ) {
|
||||||
try {
|
try {
|
||||||
Poco::Data::Session Sess = Pool_->get();
|
Poco::Data::Session Sess = Pool_->get();
|
||||||
|
|
||||||
@@ -103,20 +148,24 @@ namespace OpenWifi {
|
|||||||
if(!Records.empty())
|
if(!Records.empty())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
NewUser.Id = MicroService::instance().CreateUUID();
|
if(!PasswordHashedAlready) {
|
||||||
|
NewUser.Id = MicroService::CreateUUID();
|
||||||
NewUser.creationDate = std::time(nullptr);
|
NewUser.creationDate = std::time(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
// if there is a password, we assume that we do not want email verification,
|
// if there is a password, we assume that we do not want email verification,
|
||||||
// if there is no password, we will do email verification
|
// if there is no password, we will do email verification
|
||||||
if(NewUser.currentPassword.empty()) {
|
if(NewUser.currentPassword.empty()) {
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
NewUser.currentPassword = AuthService()->ComputePasswordHash(NewUser.email,NewUser.currentPassword);
|
if(!PasswordHashedAlready) {
|
||||||
|
NewUser.currentPassword = AuthService()->ComputeNewPasswordHash(NewUser.email,NewUser.currentPassword);
|
||||||
NewUser.lastPasswords.clear();
|
NewUser.lastPasswords.clear();
|
||||||
NewUser.lastPasswords.push_back(NewUser.currentPassword);
|
NewUser.lastPasswords.push_back(NewUser.currentPassword);
|
||||||
NewUser.lastPasswordChange = std::time(nullptr);
|
NewUser.lastPasswordChange = std::time(nullptr);
|
||||||
NewUser.validated = true;
|
NewUser.validated = true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auto Notes = RESTAPI_utils::to_string(NewUser.notes);
|
auto Notes = RESTAPI_utils::to_string(NewUser.notes);
|
||||||
auto UserType = SecurityObjects::UserTypeToString(NewUser.userRole);
|
auto UserType = SecurityObjects::UserTypeToString(NewUser.userRole);
|
||||||
|
|||||||
@@ -105,20 +105,6 @@ namespace OpenWifi {
|
|||||||
"oauthType=?, "
|
"oauthType=?, "
|
||||||
"oauthUserInfo=? "};
|
"oauthUserInfo=? "};
|
||||||
|
|
||||||
static const std::string AllActionLinksFieldsForCreation{
|
|
||||||
"Id varchar(36),"
|
|
||||||
"Action varchar,"
|
|
||||||
"UserId varchar,"
|
|
||||||
"template varchar,"
|
|
||||||
"locale varchar,"
|
|
||||||
"message text,"
|
|
||||||
"sent bigint,"
|
|
||||||
"created bigint,"
|
|
||||||
"expires bigint,"
|
|
||||||
"completed bigint,"
|
|
||||||
"canceled bigint"
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef Poco::Tuple <
|
typedef Poco::Tuple <
|
||||||
std::string, // Id = 0;
|
std::string, // Id = 0;
|
||||||
std::string, // name;
|
std::string, // name;
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ fi
|
|||||||
token=""
|
token=""
|
||||||
result_file=result.json
|
result_file=result.json
|
||||||
username="tip@ucentral.com"
|
username="tip@ucentral.com"
|
||||||
password="openwifi"
|
password="Snoopy99!!!"
|
||||||
#username="stephb@incognito.com"
|
#username="stephb@incognito.com"
|
||||||
#password="Snoopy98!"
|
#password="Snoopy98!"
|
||||||
browser_list=(firefox sensible-browser xdg-open w3m links links2 lynx youtube-dl)
|
browser_list=(firefox sensible-browser xdg-open w3m links links2 lynx youtube-dl)
|
||||||
@@ -58,8 +58,8 @@ testlogin() {
|
|||||||
curl ${FLAGS} -X POST "https://${OWSEC}/api/v1/oauth2" \
|
curl ${FLAGS} -X POST "https://${OWSEC}/api/v1/oauth2" \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
-d "$payload" > ${result_file}
|
-d "$payload" > ${result_file}
|
||||||
userMustChangePassword=$(cat ${result_file} | jq -r '.userMustChangePassword')
|
userMustChangePassword=$(cat ${result_file} | jq -r '.ErrorCode')
|
||||||
if [[ ${userMustChangePassword} == "true" ]]
|
if [[ ${userMustChangePassword} == "1" ]]
|
||||||
then
|
then
|
||||||
echo "User must change password to login..."
|
echo "User must change password to login..."
|
||||||
if [[ "$3" == "" ]]
|
if [[ "$3" == "" ]]
|
||||||
@@ -78,7 +78,10 @@ testlogin() {
|
|||||||
curl ${FLAGS} -X POST "https://${OWSEC}/api/v1/oauth2" \
|
curl ${FLAGS} -X POST "https://${OWSEC}/api/v1/oauth2" \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
-d "$payload" > ${result_file}
|
-d "$payload" > ${result_file}
|
||||||
jq < ${result_file}
|
token=$(cat ${result_file} | jq -r '.access_token')
|
||||||
|
else
|
||||||
|
payload="{ \"userId\" : \"$1\" , \"password\" : \"$2\" }"
|
||||||
|
token=$(curl ${FLAGS} -X POST -H "Content-Type: application/json" -d "$payload" "https://${OWSEC}/api/v1/oauth2" | jq -r '.access_token')
|
||||||
fi
|
fi
|
||||||
jq < ${result_file}
|
jq < ${result_file}
|
||||||
}
|
}
|
||||||
@@ -372,6 +375,7 @@ case "$1" in
|
|||||||
"getsubsystemnames") login; getsubsystemnames; logout ;;
|
"getsubsystemnames") login; getsubsystemnames; logout ;;
|
||||||
"reloadsubsystem") login; reloadsubsystem "$2"; logout ;;
|
"reloadsubsystem") login; reloadsubsystem "$2"; logout ;;
|
||||||
"systeminfo") login; systeminfo ; logout;;
|
"systeminfo") login; systeminfo ; logout;;
|
||||||
|
"testburst") login; login; login; login; login; login; login; login; login; login; login; login; login; login; login; login;;
|
||||||
"help") login; help ; logout ;;
|
"help") login; help ; logout ;;
|
||||||
*) help ;;
|
*) help ;;
|
||||||
esac
|
esac
|
||||||
|
|||||||
@@ -29,9 +29,38 @@
|
|||||||
opacity: 0.8;
|
opacity: 0.8;
|
||||||
}
|
}
|
||||||
|
|
||||||
.imgcontainer {
|
.img-container {
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 5%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin: 24px 0 12px 0;
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-card {
|
||||||
|
padding: 30px;
|
||||||
|
box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2);
|
||||||
|
display: block;
|
||||||
|
width: 50%;
|
||||||
|
border: 1em;
|
||||||
|
background-color: white;
|
||||||
|
width: 40%;
|
||||||
|
height: auto;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
margin-bottom: auto;
|
||||||
|
margin-top: 50px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-list {
|
||||||
|
width: 80%;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-title {
|
||||||
|
padding-bottom: 20px;
|
||||||
|
width: 80%;
|
||||||
|
margin: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
img.avatar {
|
img.avatar {
|
||||||
@@ -48,6 +77,10 @@
|
|||||||
padding-top: 16px;
|
padding-top: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
background-color: #ebedef;
|
||||||
|
}
|
||||||
|
|
||||||
/* Change styles for span and cancel button on extra small screens */
|
/* Change styles for span and cancel button on extra small screens */
|
||||||
@media screen and (max-width: 300px) {
|
@media screen and (max-width: 300px) {
|
||||||
span.password1 {
|
span.password1 {
|
||||||
@@ -62,13 +95,13 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<div class="imgcontainer">
|
<div class="img-container">
|
||||||
<img src="open-wifi.svg" alt="OpenWifi">
|
<img src="/wwwassets/the_logo.png" alt="OpenWifi">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div class="info-card">
|
||||||
<p>Site access rules:</p>
|
<h2 class="info-title">Site Access rules</h2>
|
||||||
<ul>
|
<ul class="info-list">
|
||||||
<li>Must be a TIP Member.</li>
|
<li>Must be a TIP Member.</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -30,8 +30,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.imgcontainer {
|
.imgcontainer {
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 5%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin: 24px 0 12px 0;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
img.avatar {
|
img.avatar {
|
||||||
@@ -43,6 +45,37 @@
|
|||||||
padding: 16px;
|
padding: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.info-card {
|
||||||
|
padding: 30px;
|
||||||
|
box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2);
|
||||||
|
display: block;
|
||||||
|
width: 50%;
|
||||||
|
border: 1em;
|
||||||
|
background-color: white;
|
||||||
|
width: 40%;
|
||||||
|
height: auto;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
margin-bottom: auto;
|
||||||
|
margin-top: 50px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-list {
|
||||||
|
width: 80%;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-title {
|
||||||
|
padding-bottom: 20px;
|
||||||
|
width: 80%;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.body {
|
||||||
|
background-color: #ebedef;
|
||||||
|
}
|
||||||
|
|
||||||
span.password1 {
|
span.password1 {
|
||||||
float: right;
|
float: right;
|
||||||
padding-top: 16px;
|
padding-top: 16px;
|
||||||
@@ -60,16 +93,17 @@
|
|||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body class="body">
|
||||||
|
|
||||||
<div class="imgcontainer">
|
<div class="imgcontainer">
|
||||||
<img src="open-wifi.svg" alt="OpenWifi">
|
<img src="/wwwassets/the_logo.png" alt="OpenWifi">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
|
||||||
<p>Password rules:</p>
|
<div class="info-card">
|
||||||
<ul>
|
<h2 class="info-title">Password rules</h2>
|
||||||
<li>Must be at least 8 characters long.</li>
|
<ul class="info-list">
|
||||||
|
<li>Must be at least 8 characters long</li>
|
||||||
<li>Must contain 1 uppercase letter</li>
|
<li>Must contain 1 uppercase letter</li>
|
||||||
<li>Must contain 1 lowercase letter</li>
|
<li>Must contain 1 lowercase letter</li>
|
||||||
<li>Must contain 1 digit</li>
|
<li>Must contain 1 digit</li>
|
||||||
@@ -78,5 +112,6 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
@@ -3,8 +3,15 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<style>
|
<style>
|
||||||
body {font-family: Arial, Helvetica, sans-serif;}
|
body {
|
||||||
form {border: 3px solid #f1f1f1;}
|
font-family: Arial,
|
||||||
|
Helvetica, sans-serif;
|
||||||
|
background-color: #ebedef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.body {
|
||||||
|
background-color: #ebedef;
|
||||||
|
}
|
||||||
|
|
||||||
input[type=text], input[type=password] {
|
input[type=text], input[type=password] {
|
||||||
width: 90%;
|
width: 90%;
|
||||||
@@ -31,15 +38,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.imgcontainer {
|
.imgcontainer {
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 5%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin: 5px 0 5px 0;
|
display: block;
|
||||||
grid-column-start: 2;
|
|
||||||
grid-column-end: 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.passwordlabel {
|
|
||||||
grid-column-start: 2;
|
|
||||||
grid-column-end: 2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
img.avatar {
|
img.avatar {
|
||||||
@@ -50,16 +52,22 @@
|
|||||||
.grid-container {
|
.grid-container {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 15% 70% 15%;
|
grid-template-columns: 15% 70% 15%;
|
||||||
background-color: #f3db21;
|
|
||||||
grid-column-gap: 5px;
|
grid-column-gap: 5px;
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid-container > div {
|
|
||||||
background-color: rgba(255, 255, 255, 0.8);
|
background-color: rgba(255, 255, 255, 0.8);
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 20px 0;
|
padding: 30px;
|
||||||
font-size: 30px;
|
box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2);
|
||||||
|
display: block;
|
||||||
|
width: 50%;
|
||||||
|
border: 1em;
|
||||||
|
background-color: white;
|
||||||
|
width: 40%;
|
||||||
|
height: auto;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
margin-bottom: auto;
|
||||||
|
margin-top: 50px;
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.passwordtext {
|
.passwordtext {
|
||||||
@@ -67,7 +75,13 @@
|
|||||||
margin-left: 5%;
|
margin-left: 5%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.password-input {
|
||||||
|
margin-top: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
.rulestext {
|
.rulestext {
|
||||||
|
width: 95%;
|
||||||
|
margin: auto;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
text-justify: none;
|
text-justify: none;
|
||||||
@@ -101,17 +115,18 @@
|
|||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
|
<div class="imgcontainer">
|
||||||
|
<img src="/wwwassets/the_logo.png" alt="OpenWifi">
|
||||||
|
</div>
|
||||||
|
|
||||||
<form action="/api/v1/actionLink?action=password_reset" method="post" onsubmit="return validatePassword()">
|
<form action="/api/v1/actionLink?action=password_reset" method="post" onsubmit="return validatePassword()">
|
||||||
<input type="hidden" id="custId" name="id" value="${UUID}">
|
<input type="hidden" id="custId" name="id" value="${UUID}">
|
||||||
<div class="grid-container">
|
<div class="grid-container">
|
||||||
|
<h2>Reset Password</h2>
|
||||||
<div class="imgcontainer">
|
|
||||||
<img src="/wwwassets/open-wifi.svg" alt="Logo" class="logo">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="passwordlabel">
|
<div class="passwordlabel">
|
||||||
<label class="passwordtext" for="password1" ><b>New Password</b></label>
|
<label class="passwordtext" for="password1" ><b>New Password</b></label>
|
||||||
<input id="password1" type="password" placeholder="New Password" name="password1" pattern="${PASSWORD_VALIDATION}" required>
|
<input className="password-input" id="password1" type="password" placeholder="New Password" name="password1" pattern="${PASSWORD_VALIDATION}" required>
|
||||||
</div>
|
</div>
|
||||||
<div class="passwordlabel">
|
<div class="passwordlabel">
|
||||||
<label class="passwordtext" for="password2"><b>Retype Password</b></label>
|
<label class="passwordtext" for="password2"><b>Retype Password</b></label>
|
||||||
|
|||||||
@@ -1,11 +1,107 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>Reset Password Failed</title>
|
<style>
|
||||||
|
body {font-family: Arial, Helvetica, sans-serif;}
|
||||||
|
form {border: 3px solid #f1f1f1;}
|
||||||
|
|
||||||
|
input[type=text], input[type=password] {
|
||||||
|
width: 100%;
|
||||||
|
padding: 12px 20px;
|
||||||
|
margin: 8px 0;
|
||||||
|
display: inline-block;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
background-color: #04AA6D;
|
||||||
|
color: white;
|
||||||
|
padding: 14px 20px;
|
||||||
|
margin: 8px 0;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:hover {
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.imgcontainer {
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 5%;
|
||||||
|
text-align: center;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
img.avatar {
|
||||||
|
width: 40%;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
padding: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-card {
|
||||||
|
padding: 30px;
|
||||||
|
box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2);
|
||||||
|
display: block;
|
||||||
|
width: 50%;
|
||||||
|
border: 1em;
|
||||||
|
background-color: white;
|
||||||
|
width: 40%;
|
||||||
|
height: auto;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
margin-bottom: auto;
|
||||||
|
margin-top: 50px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-list {
|
||||||
|
width: 80%;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-title {
|
||||||
|
padding-bottom: 20px;
|
||||||
|
width: 80%;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.body {
|
||||||
|
background-color: #ebedef;
|
||||||
|
}
|
||||||
|
|
||||||
|
span.password1 {
|
||||||
|
float: right;
|
||||||
|
padding-top: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Change styles for span and cancel button on extra small screens */
|
||||||
|
@media screen and (max-width: 300px) {
|
||||||
|
span.password1 {
|
||||||
|
display: block;
|
||||||
|
float: none;
|
||||||
|
}
|
||||||
|
.cancelbtn {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body class="body">
|
||||||
<h1>Password reset failed...</h1>
|
|
||||||
|
<div class="imgcontainer">
|
||||||
|
<img src="/wwwassets/the_logo.png" alt="OpenWifi">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="info-card">
|
||||||
|
<h1 class="info-title">Reset Password Failed</h1>
|
||||||
<div>
|
<div>
|
||||||
<h3>ID</h3>
|
<h3>ID</h3>
|
||||||
<b>${UUID}</b>
|
<b>${UUID}</b>
|
||||||
@@ -14,5 +110,7 @@
|
|||||||
<h3>Error</h3>
|
<h3>Error</h3>
|
||||||
<b>${ERROR_TEXT}</b>
|
<b>${ERROR_TEXT}</b>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
@@ -62,8 +62,9 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="imgcontainer">
|
<div class="imgcontainer">
|
||||||
<img src="/wwwassets/avatar.jpg" alt="Avatar" class="avatar">
|
<img src="/wwwassets/the_logo.png" alt="Avatar" class="avatar">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h1>Password was successfully reset</h1>
|
<h1>Password was successfully reset</h1>
|
||||||
<div>
|
<div>
|
||||||
<h3>Thank you ${USERNAME} for resetting your password.</h3>
|
<h3>Thank you ${USERNAME} for resetting your password.</h3>
|
||||||
|
|||||||
BIN
wwwassets/the_logo.png
Normal file
BIN
wwwassets/the_logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.8 KiB |
Reference in New Issue
Block a user