Add a rules engine so I can be notified when I forget to close my garage door.

This commit is contained in:
MarkBryanMilligan
2021-07-15 23:34:15 -05:00
parent de50645a2c
commit 3d5cd6500f
81 changed files with 2044 additions and 231 deletions

View File

@@ -1,7 +1,7 @@
package com.lanternsoftware.dataaccess.currentmonitor;
import com.lanternsoftware.datamodel.currentmonitor.Account;
import com.lanternsoftware.datamodel.currentmonitor.AuthCode;
import com.lanternsoftware.util.dao.auth.AuthCode;
import com.lanternsoftware.datamodel.currentmonitor.BreakerConfig;
import com.lanternsoftware.datamodel.currentmonitor.BreakerGroup;
import com.lanternsoftware.datamodel.currentmonitor.BreakerGroupEnergy;

View File

@@ -1,7 +1,7 @@
package com.lanternsoftware.dataaccess.currentmonitor;
import com.lanternsoftware.datamodel.currentmonitor.Account;
import com.lanternsoftware.datamodel.currentmonitor.AuthCode;
import com.lanternsoftware.util.dao.auth.AuthCode;
import com.lanternsoftware.datamodel.currentmonitor.Breaker;
import com.lanternsoftware.datamodel.currentmonitor.BreakerConfig;
import com.lanternsoftware.datamodel.currentmonitor.BreakerGroup;
@@ -14,9 +14,7 @@ import com.lanternsoftware.datamodel.currentmonitor.Sequence;
import com.lanternsoftware.util.CollectionUtils;
import com.lanternsoftware.util.DateUtils;
import com.lanternsoftware.util.DebugTimer;
import com.lanternsoftware.util.LanternFiles;
import com.lanternsoftware.util.NullUtils;
import com.lanternsoftware.util.ResourceLoader;
import com.lanternsoftware.util.cryptography.AESTool;
import com.lanternsoftware.util.dao.DaoEntity;
import com.lanternsoftware.util.dao.DaoQuery;
@@ -42,7 +40,7 @@ import java.util.concurrent.Executors;
public class MongoCurrentMonitorDao implements CurrentMonitorDao {
private static final Logger logger = LoggerFactory.getLogger(MongoCurrentMonitorDao.class);
private static final AESTool aes = new AESTool(ResourceLoader.loadFile(LanternFiles.OPS_PATH + "authKey.dat"));
private static final AESTool aes = AESTool.authTool();
private static final int BCRYPT_ROUNDS = 11;
private final Timer delayTimer = new Timer();
private final ExecutorService executor = Executors.newCachedThreadPool();

View File

@@ -1,49 +0,0 @@
package com.lanternsoftware.datamodel.currentmonitor;
import com.lanternsoftware.util.CollectionUtils;
import com.lanternsoftware.util.dao.annotations.DBSerializable;
import java.util.ArrayList;
import java.util.List;
@DBSerializable(autogen = false)
public class AuthCode {
private int accountId;
private List<Integer> auxiliaryAccountIds;
public AuthCode() {
}
public AuthCode(int _accountId, List<Integer> _auxiliaryAccountIds) {
accountId = _accountId;
auxiliaryAccountIds = _auxiliaryAccountIds;
}
public int getAccountId() {
return accountId;
}
public void setAccountId(int _accountId) {
accountId = _accountId;
}
public List<Integer> getAuxiliaryAccountIds() {
return auxiliaryAccountIds;
}
public void setAuxiliaryAccountIds(List<Integer> _auxiliaryAccountIds) {
auxiliaryAccountIds = _auxiliaryAccountIds;
}
public List<Integer> getAllAccountIds() {
List<Integer> ids = new ArrayList<>();
ids.add(accountId);
if (auxiliaryAccountIds != null)
ids.addAll(auxiliaryAccountIds);
return ids;
}
public boolean isAuthorized(int _accountId) {
return accountId == _accountId || CollectionUtils.contains(auxiliaryAccountIds, _accountId);
}
}

View File

@@ -1,46 +0,0 @@
package com.lanternsoftware.datamodel.currentmonitor.dao;
import com.lanternsoftware.datamodel.currentmonitor.AuthCode;
import com.lanternsoftware.util.CollectionUtils;
import com.lanternsoftware.util.dao.AbstractDaoSerializer;
import com.lanternsoftware.util.dao.DaoEntity;
import com.lanternsoftware.util.dao.DaoProxyType;
import com.lanternsoftware.util.dao.DaoSerializer;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class AuthCodeSerializer extends AbstractDaoSerializer<AuthCode>
{
@Override
public Class<AuthCode> getSupportedClass()
{
return AuthCode.class;
}
@Override
public List<DaoProxyType> getSupportedProxies() {
return Collections.singletonList(DaoProxyType.MONGO);
}
@Override
public DaoEntity toDaoEntity(AuthCode _o)
{
DaoEntity d = new DaoEntity();
d.put("account_id", _o.getAccountId());
if (CollectionUtils.isNotEmpty(_o.getAuxiliaryAccountIds()))
d.put("aux_account_ids", CollectionUtils.toByteArray(_o.getAuxiliaryAccountIds()));
return d;
}
@Override
public AuthCode fromDaoEntity(DaoEntity _d)
{
AuthCode o = new AuthCode();
o.setAccountId(DaoSerializer.getInteger(_d, "account_id"));
o.setAuxiliaryAccountIds(CollectionUtils.fromByteArrayOfIntegers(DaoSerializer.getByteArray(_d, "aux_account_ids")));
return o;
}
}

View File

@@ -1,5 +1,4 @@
com.lanternsoftware.datamodel.currentmonitor.dao.AccountSerializer
com.lanternsoftware.datamodel.currentmonitor.dao.AuthCodeSerializer
com.lanternsoftware.datamodel.currentmonitor.dao.BreakerConfigSerializer
com.lanternsoftware.datamodel.currentmonitor.dao.BreakerGroupEnergySerializer
com.lanternsoftware.datamodel.currentmonitor.dao.BreakerGroupSerializer

View File

@@ -12,6 +12,18 @@
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.google.api-client</groupId>
<artifactId>google-api-client-bom</artifactId>
<version>1.32.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>com.lanternsoftware.currentmonitor</groupId>
@@ -23,10 +35,14 @@
<artifactId>lantern-util-servlet</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>com.lanternsoftware.rules</groupId>
<artifactId>lantern-service-rules</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>com.google.api-client</groupId>
<artifactId>google-api-client</artifactId>
<version>1.30.4</version>
</dependency>
<dependency>
<groupId>javax</groupId>

View File

@@ -2,6 +2,7 @@ package com.lanternsoftware.currentmonitor.context;
import com.lanternsoftware.dataaccess.currentmonitor.CurrentMonitorDao;
import com.lanternsoftware.dataaccess.currentmonitor.MongoCurrentMonitorDao;
import com.lanternsoftware.rules.RulesEngine;
import com.lanternsoftware.util.LanternFiles;
import com.lanternsoftware.util.dao.mongo.MongoConfig;
@@ -14,10 +15,12 @@ public class Globals implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
dao = new MongoCurrentMonitorDao(MongoConfig.fromDisk(LanternFiles.OPS_PATH + "mongo.cfg"));
RulesEngine.instance().start();
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
dao.shutdown();
RulesEngine.shutdown();
}
}

View File

@@ -4,7 +4,7 @@ import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeToken
import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken;
import com.google.api.client.googleapis.auth.oauth2.GoogleTokenResponse;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.client.json.gson.GsonFactory;
import com.lanternsoftware.currentmonitor.context.Globals;
import com.lanternsoftware.util.DateUtils;
import com.lanternsoftware.util.LanternFiles;
@@ -13,6 +13,7 @@ import com.lanternsoftware.util.ResourceLoader;
import com.lanternsoftware.util.dao.DaoEntity;
import com.lanternsoftware.util.dao.DaoSerializer;
import com.lanternsoftware.util.servlet.BasicAuth;
import com.lanternsoftware.util.servlet.LanternServlet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -21,9 +22,8 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/auth/*")
public class AuthServlet extends CMServlet {
public class AuthServlet extends LanternServlet {
private static final NetHttpTransport transport = new NetHttpTransport();
private static final JacksonFactory jsonFactory = new JacksonFactory();
private static final Logger logger = LoggerFactory.getLogger(AuthServlet.class);
private static final String googleClientId;
private static final String googleClientSecret;
@@ -41,7 +41,7 @@ public class AuthServlet extends CMServlet {
if (NullUtils.isEqual(auth.getUsername(), "googlesso")) {
logger.info("Attempting google SSO");
try {
GoogleTokenResponse tokenResponse = new GoogleAuthorizationCodeTokenRequest(transport, jsonFactory, "https://oauth2.googleapis.com/token", googleClientId, googleClientSecret, auth.getPassword(), "").execute();
GoogleTokenResponse tokenResponse = new GoogleAuthorizationCodeTokenRequest(transport, new GsonFactory(), "https://oauth2.googleapis.com/token", googleClientId, googleClientSecret, auth.getPassword(), "").execute();
if (tokenResponse != null) {
GoogleIdToken idToken = tokenResponse.parseIdToken();
if (idToken != null) {

View File

@@ -8,13 +8,14 @@ import com.lanternsoftware.util.csv.CSVWriter;
import com.lanternsoftware.util.dao.DaoEntity;
import com.lanternsoftware.util.dao.DaoQuery;
import com.lanternsoftware.util.dao.DaoSerializer;
import com.lanternsoftware.util.servlet.LanternServlet;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/bom/*")
public class BomServlet extends CMServlet {
public class BomServlet extends LanternServlet {
@Override
protected void doGet(HttpServletRequest _req, HttpServletResponse _rep) {
String[] path = path(_req);

View File

@@ -1,101 +0,0 @@
package com.lanternsoftware.currentmonitor.servlet;
import com.lanternsoftware.util.CollectionUtils;
import com.lanternsoftware.util.NullUtils;
import com.lanternsoftware.util.dao.DaoEntity;
import com.lanternsoftware.util.dao.DaoSerializer;
import org.apache.commons.io.IOUtils;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.core.MediaType;
import java.io.InputStream;
import java.io.OutputStream;
public abstract class CMServlet extends HttpServlet {
public static void setResponseHtml(HttpServletResponse _response, String _sHtml) {
setResponseEntity(_response, MediaType.TEXT_HTML, _sHtml);
}
public static void setResponseEntity(HttpServletResponse _response, String _sContentType, String _sEntity) {
setResponseEntity(_response, 200, _sContentType, _sEntity);
}
public static void setResponseEntity(HttpServletResponse _response, String _sContentType, byte[] _btData) {
setResponseEntity(_response, 200, _sContentType, _btData);
}
public static void setResponseEntity(HttpServletResponse _response, int _iStatus, String _sContentType, String _sEntity) {
setResponseEntity(_response, _iStatus, _sContentType, NullUtils.toByteArray(_sEntity));
}
public static void setResponseEntity(HttpServletResponse _response, int _iStatus, String _sContentType, byte[] _btData) {
OutputStream os = null;
try {
_response.setStatus(_iStatus);
_response.setCharacterEncoding("UTF-8");
_response.setContentType(_sContentType);
if ((_btData != null) && (_btData.length > 0)) {
_response.setContentLength(_btData.length);
os = _response.getOutputStream();
os.write(_btData);
} else
_response.setContentLength(0);
} catch (Exception e) {
e.printStackTrace();
} finally {
IOUtils.closeQuietly(os);
}
}
protected void zipBsonResponse(HttpServletResponse _response, Object _object)
{
setResponseEntity(_response, 200, MediaType.APPLICATION_OCTET_STREAM, DaoSerializer.toZipBson(_object));
}
protected void jsonResponse(HttpServletResponse _response, Object _object)
{
setResponseEntity(_response, 200, MediaType.APPLICATION_JSON, DaoSerializer.toJson(_object));
}
protected void jsonResponse(HttpServletResponse _response, String _json)
{
setResponseEntity(_response, 200, MediaType.APPLICATION_JSON, _json);
}
protected String getRequestPayloadAsString(HttpServletRequest _req) {
return NullUtils.toString(getRequestPayload(_req));
}
protected byte[] getRequestPayload(HttpServletRequest _req) {
InputStream is = null;
try {
is = _req.getInputStream();
return IOUtils.toByteArray(is);
}
catch (Exception e) {
e.printStackTrace();
return null;
}
finally {
IOUtils.closeQuietly(is);
}
}
protected DaoEntity getRequestZipBson(HttpServletRequest _req) {
return DaoSerializer.fromZipBson(getRequestPayload(_req));
}
protected <T> T getRequestPayload(HttpServletRequest _req, Class<T> _retClass) {
return DaoSerializer.fromZipBson(getRequestPayload(_req), _retClass);
}
protected String[] path(HttpServletRequest _req) {
return NullUtils.cleanSplit(NullUtils.makeNotNull(_req.getPathInfo()), "/");
}
protected boolean isPath(HttpServletRequest _req, int _index, String _path) {
return NullUtils.isEqual(_path, CollectionUtils.get(path(_req), _index));
}
}

View File

@@ -1,6 +1,6 @@
package com.lanternsoftware.currentmonitor.servlet;
import com.lanternsoftware.datamodel.currentmonitor.AuthCode;
import com.lanternsoftware.util.dao.auth.AuthCode;
import com.lanternsoftware.util.CollectionUtils;
import com.lanternsoftware.util.LanternFiles;
import com.lanternsoftware.util.NullUtils;

View File

@@ -1,11 +1,8 @@
package com.lanternsoftware.currentmonitor.servlet;
import com.lanternsoftware.currentmonitor.context.Globals;
import com.lanternsoftware.dataaccess.currentmonitor.MongoCurrentMonitorDao;
import com.lanternsoftware.datamodel.currentmonitor.AuthCode;
import com.lanternsoftware.util.dao.auth.AuthCode;
import com.lanternsoftware.datamodel.currentmonitor.BreakerConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
@@ -13,13 +10,8 @@ import javax.servlet.http.HttpServletResponse;
@WebServlet("/config/*")
public class ConfigServlet extends SecureServlet {
private static final Logger logger = LoggerFactory.getLogger(ConfigServlet.class);
@Override
protected void get(AuthCode _authCode, HttpServletRequest _req, HttpServletResponse _rep) {
if (_authCode.getAccountId() == 100) {
logger.error("my ip: " + _req.getRemoteAddr());
}
if (isPath(_req, 0, "bin"))
zipBsonResponse(_rep, Globals.dao.getMergedConfig(_authCode));
else

View File

@@ -1,7 +1,7 @@
package com.lanternsoftware.currentmonitor.servlet;
import com.lanternsoftware.currentmonitor.context.Globals;
import com.lanternsoftware.datamodel.currentmonitor.AuthCode;
import com.lanternsoftware.util.dao.auth.AuthCode;
import com.lanternsoftware.util.dao.DaoEntity;
import javax.servlet.annotation.WebServlet;

View File

@@ -1,7 +1,7 @@
package com.lanternsoftware.currentmonitor.servlet;
import com.lanternsoftware.currentmonitor.context.Globals;
import com.lanternsoftware.datamodel.currentmonitor.AuthCode;
import com.lanternsoftware.util.dao.auth.AuthCode;
import com.lanternsoftware.datamodel.currentmonitor.BreakerGroupEnergy;
import com.lanternsoftware.datamodel.currentmonitor.EnergyBlockViewMode;
import com.lanternsoftware.util.CollectionUtils;

View File

@@ -1,15 +1,9 @@
package com.lanternsoftware.currentmonitor.servlet;
import com.lanternsoftware.currentmonitor.context.Globals;
import com.lanternsoftware.datamodel.currentmonitor.AuthCode;
import com.lanternsoftware.datamodel.currentmonitor.Breaker;
import com.lanternsoftware.datamodel.currentmonitor.BreakerPower;
import com.lanternsoftware.datamodel.currentmonitor.BreakerGroup;
import com.lanternsoftware.util.CollectionUtils;
import com.lanternsoftware.util.NullUtils;
import com.lanternsoftware.util.dao.auth.AuthCode;
import com.lanternsoftware.util.dao.DaoEntity;
import com.lanternsoftware.util.dao.DaoSerializer;
import org.bson.Document;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;

View File

@@ -1,7 +1,7 @@
package com.lanternsoftware.currentmonitor.servlet;
import com.lanternsoftware.currentmonitor.context.Globals;
import com.lanternsoftware.datamodel.currentmonitor.AuthCode;
import com.lanternsoftware.util.dao.auth.AuthCode;
import com.lanternsoftware.datamodel.currentmonitor.BreakerPower;
import com.lanternsoftware.datamodel.currentmonitor.HubPowerMinute;
import com.lanternsoftware.util.CollectionUtils;
@@ -31,7 +31,9 @@ public class PowerServlet extends SecureServlet {
protected void post(AuthCode _authCode, HttpServletRequest _req, HttpServletResponse _rep) {
String[] path = path(_req);
if ((path.length > 0) && NullUtils.isEqual(CollectionUtils.get(path, 0), "hub")) {
Globals.dao.putHubPowerMinute(getRequestPayload(_req, HubPowerMinute.class));
HubPowerMinute m = getRequestPayload(_req, HubPowerMinute.class);
m.setAccountId(_authCode.getAccountId());
Globals.dao.putHubPowerMinute(m);
return;
}
if ((path.length > 0) && NullUtils.isEqual(CollectionUtils.get(path, 0), "batch")) {

View File

@@ -1,12 +1,13 @@
package com.lanternsoftware.currentmonitor.servlet;
import com.lanternsoftware.currentmonitor.context.Globals;
import com.lanternsoftware.datamodel.currentmonitor.AuthCode;
import com.lanternsoftware.util.dao.auth.AuthCode;
import com.lanternsoftware.util.servlet.LanternServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public abstract class SecureServlet extends CMServlet {
public abstract class SecureServlet extends LanternServlet {
@Override
protected void doGet(HttpServletRequest _req, HttpServletResponse _rep) {
AuthCode authCode = Globals.dao.decryptAuthCode(_req.getHeader("auth_code"));

View File

@@ -7,13 +7,14 @@ import com.lanternsoftware.util.DateUtils;
import com.lanternsoftware.util.NullUtils;
import com.lanternsoftware.util.email.EmailValidator;
import com.lanternsoftware.util.servlet.BasicAuth;
import com.lanternsoftware.util.servlet.LanternServlet;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/signup")
public class SignupServlet extends CMServlet {
public class SignupServlet extends LanternServlet {
@Override
protected void doGet(HttpServletRequest _req, HttpServletResponse _rep) {
BasicAuth auth = new BasicAuth(_req);

View File

@@ -3,6 +3,7 @@ package com.lanternsoftware.currentmonitor.servlet;
import com.lanternsoftware.util.LanternFiles;
import com.lanternsoftware.util.ResourceLoader;
import com.lanternsoftware.util.dao.DaoSerializer;
import com.lanternsoftware.util.servlet.LanternServlet;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
@@ -11,7 +12,7 @@ import javax.ws.rs.core.MediaType;
import java.io.File;
@WebServlet("/update/*")
public class UpdateServlet extends CMServlet {
public class UpdateServlet extends LanternServlet {
@Override
protected void doGet(HttpServletRequest _req, HttpServletResponse _rep) {
if (isPath(_req, 0, "version"))