New licensing.

This commit is contained in:
Konstantin Krivopustov 2015-03-12 12:58:21 +00:00
parent c9f9dccce2
commit 6dc9c060d0
10 changed files with 169 additions and 118 deletions

View File

@ -6,6 +6,8 @@ package com.haulmont.cuba.security.app;
import com.haulmont.bali.db.QueryRunner;
import com.haulmont.bali.db.ResultSetHandler;
import com.haulmont.bali.util.Dom4j;
import com.haulmont.chile.core.model.MetaModel;
import com.haulmont.cuba.core.Persistence;
import com.haulmont.cuba.core.app.ClusterListener;
import com.haulmont.cuba.core.app.ClusterManagerAPI;
@ -19,9 +21,12 @@ import com.haulmont.cuba.security.entity.User;
import com.haulmont.cuba.security.entity.UserSessionEntity;
import com.haulmont.cuba.security.global.UserSession;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Document;
import org.dom4j.Element;
import javax.annotation.ManagedBean;
import javax.annotation.PostConstruct;
@ -37,6 +42,7 @@ import java.security.spec.RSAPublicKeySpec;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
@ -49,6 +55,8 @@ import java.util.concurrent.ConcurrentHashMap;
@ManagedBean(UserSessionsAPI.NAME)
public final class UserSessions implements UserSessionsAPI {
public static final String NOT_RESTRICTED = "Not restricted";
static class UserSessionInfo implements Serializable {
private static final long serialVersionUID = -4834267718111570841L;
@ -190,31 +198,29 @@ public final class UserSessions implements UserSessionsAPI {
log.error("\n======================================================"
+ "\nInvalid license path: " + serverConfig.getLicensePath()
+ "\n======================================================");
return;
} else {
Object[] objects;
try {
bytes = Base64.decodeBase64(encodedStr);
} catch (Exception ignored) {
}
objects = decode();
if (objects != null) {
StringBuilder sb = new StringBuilder();
sb.append("\n======================================================");
sb.append("\nCUBA platform license");
sb.append("\nType: ").append(objects[0]);
sb.append("\nLicense ID: ").append(objects[1]);
sb.append("\nLicensed to: ").append(objects[2]);
sb.append("\nApplication: ").append(objects[3]);
sb.append("\nValid for CUBA platform releases up to: ").append(objects[4]);
sb.append("\nMaximum number of sessions: ").append(((int) objects[5]) == 0 ? NOT_RESTRICTED : objects[5]);
sb.append("\nMaximum number of entities: ").append(((int) objects[6]) == 0 ? NOT_RESTRICTED : objects[6]);
sb.append("\n======================================================");
log.warn(sb.toString());
}
}
Object[] objects;
try {
bytes = Base64.decodeBase64(encodedStr);
} catch (Exception e) {
//
}
objects = decode();
if (objects == null) {
log.error("\n======================================================"
+ "\nInvalid license data at " + serverConfig.getLicensePath()
+ "\n======================================================");
return;
}
StringBuilder sb = new StringBuilder();
sb.append("\n======================================================")
.append("\nCUBA platform license type: ").append(objects[0])
.append("\nLicensed To: ").append(objects[1])
.append("\nNumber of licensed sessions: ").append(((int) objects[2]) == 0 ? "unlimited" : objects[2])
.append("\n======================================================");
log.warn(sb.toString());
if (!globalConfig.getTestMode()) {
Timer timer = new Timer(true);
timer.schedule(
@ -269,12 +275,107 @@ public final class UserSessions implements UserSessionsAPI {
String str = new String(decoded, Charset.forName("UTF-8"));
String[] split = str.split("\\^");
Object[] arr = new Object[3];
arr[0] = split[0].trim();
arr[1] = split[1].trim();
arr[2] = Integer.valueOf(split[2].trim());
Object[] arr = new Object[7];
if (split.length == 7) {
arr[0] = split[0].trim(); // type
arr[1] = split[1].trim(); // id
arr[2] = split[2].trim(); // to
arr[3] = split[3].trim(); // app
arr[4] = split[4].trim(); // platform date
arr[5] = Integer.valueOf(split[5].trim()); // sessions
arr[6] = Integer.valueOf(split[6].trim()); // entities
} else if (split.length == 3) {
arr[0] = "Commercial"; // type
arr[1] = "1400001"; // id
arr[2] = split[1].trim(); // to
arr[3] = NOT_RESTRICTED; // app
arr[4] = NOT_RESTRICTED; // platform date
arr[5] = Integer.valueOf(split[2].trim()); // sessions
arr[6] = 0; // entities
} else
throw new RuntimeException();
if (!arr[3].equals(NOT_RESTRICTED)) {
boolean found = false;
String config = AppContext.getProperty("cuba.metadataConfig");
String[] files = config.split("\\s");
String file = files[files.length - 1];
InputStream stream = resources.getResourceAsStream(file);
if (stream == null) {
log.error("Cannot load '" + file + "' to check application name");
throw new RuntimeException();
}
try {
Document document = Dom4j.readDocument(stream);
Element root = document.getRootElement();
for (Element element : (List<Element>) root.elements("metadata-model")) {
if (arr[3].equals(element.attributeValue("root-package"))) {
found = true;
break;
}
}
} finally {
IOUtils.closeQuietly(stream);
}
if (!found) {
log.error("\n======================================================"
+ "\nInvalid license file at " + serverConfig.getLicensePath()
+ "\napplication name mismatch"
+ "\n======================================================");
return null;
}
}
if (!arr[4].equals(NOT_RESTRICTED)) {
InputStream stream = getClass().getResourceAsStream("/com/haulmont/cuba/core/global/release.timestamp");
if (stream == null) {
log.error("Cannot load platform release timestamp");
throw new RuntimeException();
}
String relStr = IOUtils.toString(stream);
SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd");
Date relDate = fmt.parse(relStr.substring(0, 10));
Date licDate = fmt.parse((String) arr[4]);
if (relDate.after(licDate)) {
log.error("\n======================================================"
+ "\nInvalid license file at " + serverConfig.getLicensePath()
+ "\nunsupported platform release (licensed for releases"
+ "\nup to " + arr[4] + ", current release: " + relStr.substring(0, 10) + ")"
+ "\n======================================================");
return null;
}
}
if ((int)arr[6] != 0) {
int count = 0;
for (MetaModel metaModel : metadata.getSession().getModels()) {
String name = metaModel.getName();
if (!name.equals("com.haulmont.cuba")
&& !name.equals("com.haulmont.reports")
&& !name.equals("com.haulmont.workflow")
&& !name.equals("com.haulmont.fts")
&& !name.equals("com.haulmont.ccpayments")
&& !name.equals("com.haulmont.bpmn"))
{
count += metaModel.getClasses().size();
}
}
if (count > (int)arr[6]) {
log.error("\n======================================================"
+ "\nInvalid license file at " + serverConfig.getLicensePath()
+ "\nmaximum number of entities exceeded "
+ "\n(licensed: " + arr[6] + ", actual: " + count + ")"
+ "\n======================================================");
return null;
}
}
return arr;
} catch (Exception e) {
log.error("\n======================================================"
+ "\nInvalid license data at " + serverConfig.getLicensePath()
+ "\n======================================================");
return null;
}
}
@ -287,7 +388,7 @@ public final class UserSessions implements UserSessionsAPI {
clusterManager.send(usi);
Object[] objects = decode();
if (objects != null) {
int licensed = (int) objects[2];
int licensed = (int) objects[5];
if (licensed != 0 && count > licensed) {
LogFactory.getLog("com.haulmont.cuba.security.app.LoginWorkerBean").warn(
String.format("Active sessions: %d, licensed: %d", count, licensed));
@ -355,16 +456,14 @@ public final class UserSessions implements UserSessionsAPI {
@Override
public Map<String, Object> getLicenseInfo() {
Object[] objects = decode();
Map<String, Object> info = new HashMap<>();
if (objects != null) {
info.put("licenseType", objects[0]);
info.put("licensedTo", objects[1]);
info.put("licensedSessions", objects[2]);
} else {
info.put("licenseType", "invalid data");
info.put("licensedTo", "invalid data");
info.put("licensedSessions", -1);
}
Map<String, Object> info = new LinkedHashMap<>();
info.put("licenseType", objects != null ? objects[0] : "invalid data");
info.put("licenseId", objects != null ? objects[1] : "invalid data");
info.put("licensedTo", objects != null ? objects[2] : "invalid data");
info.put("rootPackage", objects != null ? objects[3] : "invalid data");
info.put("licensedReleaseDate", objects != null ? objects[4] : "invalid data");
info.put("licensedSessions", objects != null ? objects[5] : -1);
info.put("licensedEntities", objects != null ? objects[6] : -1);
info.put("activeSessions", count);
return info;
}

View File

@ -1,5 +1,5 @@
h1y9vmZ9x0bLe18vHnPmgKrCzZVaeTO/4fndvrp5i0nC994ipEAlvq9c7bwBByG1bs53Bl4DRSKh
H2uqcRRMZ5Nyhhsz5T6P8cAH0F0lfkAmXjLKz4PtjJOEbTiO4JXwIdcGzJCQ9GYS621TjtHP72o5
w9r0SZxoVu9en780FugCopzu+IJUIgUclxLiTxGRfdJWAFe9cIh47GLqQhDEP9eY9nYdjdbeyTho
5b2cN67NzFpJRcZ07FullVD1GGPdmc1nZ+M936rWoUcvKLAD1CFdAZFN0u8+pUBaIucS78M/k0qC
nG8VpF72EflnqwTl6SZqmYGfRHtwtlBlRm/yeQ==
F7dmnmILoOTZ81l1gKAoQOPYf8BGGHtlmfTqsluwr/VCqXbzzR9Uci7e4QB3iSo+F82OWQ3yBjpB
+kpPKIN+UUJWTXwWZaJao4BnBLhyOCfCABAQjXOnsV2c74q4wycLeZ1m+5zXm62VMF+65out3rDD
f/gwJ9YffopK7KIy50tpgqK+fF5XQ4ckkgaMecr6CxHHPnOjierQY9HvpYpeK9D6/M8GxBhToEzB
JgYKoHtgE2e1vfvWR1KoE0UCb9495YMtEWH65sdOrp5x2MmCLMqn/YytPRCdrezwIZ6+r+Tu5KrO
XUyTd2k3nyDyU+z6lXvHsFbj9EvKsBakYCLmVw==

View File

@ -663,12 +663,13 @@ public class App implements ConnectionListener {
Map<String, Object> info = userSessionService.getLicenseInfo();
Integer licensed = (Integer) info.get("licensedSessions");
if (licensed < 0) {
mainFrame.showNotification("Invalid CUBA platform license", IFrame.NotificationType.WARNING);
mainFrame.showNotification("Invalid CUBA platform license. See server log for details.",
IFrame.NotificationType.ERROR);
} else {
Integer active = (Integer) info.get("activeSessions");
if (licensed != 0 && active > licensed) {
mainFrame.showNotification("Number of licensed sessions exceeded", "active: " + active + ", licensed: " + licensed,
IFrame.NotificationType.WARNING);
IFrame.NotificationType.ERROR);
}
}
}

View File

@ -5,10 +5,9 @@
package com.haulmont.cuba.gui.app.core.license;
import com.haulmont.cuba.core.global.Resources;
import com.haulmont.cuba.gui.components.*;
import com.haulmont.cuba.gui.components.AbstractFrame;
import com.haulmont.cuba.gui.components.TextArea;
import com.haulmont.cuba.security.app.UserSessionService;
import com.haulmont.cuba.security.global.UserSession;
import javax.inject.Inject;
import java.util.Map;
@ -19,60 +18,22 @@ import java.util.Map;
*/
public class LicenseFrame extends AbstractFrame {
@Inject
private Resources resources;
@Inject
private UserSession userSession;
@Inject
private UserSessionService uss;
@Inject
private TextArea licenseTxtField;
@Inject
private LinkButton licenseLink;
@Inject
private TextField licensedToField;
@Inject
private Label licensedSessions;
@Inject
private Label activeSessions;
private String linkAddressMsg;
@Override
public void init(Map<String, Object> params) {
Map<String, Object> info = uss.getLicenseInfo();
String licenseType = (String) info.get("licenseType");
licenseTxtField.setValue(getMessage(licenseType));
StringBuilder sb = new StringBuilder();
for (Map.Entry<String, Object> entry : info.entrySet()) {
sb.append(getMessage(entry.getKey())).append(": ").append(entry.getValue()).append("\n");
}
licenseTxtField.setValue(sb.toString());
licenseTxtField.setEditable(false);
String linkKey = licenseType + "Link";
String linkMsg = getMessage(linkKey);
if (!linkMsg.equals(linkKey)) {
licenseLink.setVisible(true);
licenseLink.setCaption(linkMsg);
String linkAddressKey = licenseType + "LinkAddress";
linkAddressMsg = getMessage(linkAddressKey);
}
if (!licenseType.equals("starter")) {
licensedToField.setVisible(true);
licensedToField.setValue(info.get("licensedTo"));
licensedToField.setEditable(false);
}
Integer licensed = (Integer) info.get("licensedSessions");
String licensedStr = licensed == 0 ? getMessage("unlimited") : String.valueOf(licensed);
licensedSessions.setValue(messages.formatMessage(getMessagesPack(), "licensedSessions", licensedStr));
activeSessions.setValue(messages.formatMessage(getMessagesPack(), "activeSessions", info.get("activeSessions")));
}
public void showLicense() {
if (linkAddressMsg != null) {
showWebPage(linkAddressMsg, null);
}
}
}

View File

@ -8,12 +8,9 @@
messagesPack="com.haulmont.cuba.gui.app.core.license">
<layout>
<groupBox caption="msg://licenseTitle" spacing="true" expand="licenseTxtField" height="100%">
<textArea id="licenseTxtField" width="100%" rows="2"/>
<linkButton id="licenseLink" invoke="showLicense" visible="false"/>
<textField id="licensedToField" caption="msg://licensedTo" width="100%" visible="false"/>
<label id="licensedSessions"/>
<label id="activeSessions"/>
<groupBox caption="msg://licenseTitle" spacing="true" height="100%" expand="licenseTxtField">
<textArea id="licenseTxtField" width="100%"/>
<link caption="License text" url="https://www.cuba-platform.com/license" target="_blank"/>
</groupBox>
</layout>

View File

@ -4,11 +4,11 @@
#
licenseTitle = CUBA platform license
licenseType = License Type
licenseId = License ID
licensedTo = Licensed To
licensedSessions = Licensed number of sessions: %s
activeSessions = Current number of sessions: %d
unlimited = unlimited
starter = Starter license.
starterLink = See license details
starterLinkAddress = http://www.cuba-platform.com/license
commercial = Commercial license.
rootPackage = Root package
licensedReleaseDate = Valid for CUBA platform releases up to
licensedSessions = Maximum number of sessions
licensedEntities = Maximum number of entities
activeSessions = Current number of sessions

View File

@ -4,11 +4,3 @@
#
licenseTitle = Лицензия на платформу CUBA
licensedTo = Лицензиат
licensedSessions = Лицензированное количество сессий: %s
activeSessions = Текущее количество сессий: %d
unlimited = не ограничено
starter = Начальная лицензия.
starterLink = Посмотреть условия лицензионного соглашения
starterLinkAddress = http://www.cuba-platform.com/license
commercial = Коммерческая лицензия.

View File

@ -4,7 +4,7 @@
#
cuba.gui.AboutWindow.width=450
cuba.gui.AboutWindow.height=300
cuba.gui.AboutWindow.height=350
cuba.gui.AbstractCustomConditionEditDlg.field.width=250px
cuba.gui.AbstractCustomConditionEditDlg.joinText.height=80px

View File

@ -267,12 +267,13 @@ public class AppWindow extends UIView implements UserSubstitutionListener, CubaH
Map<String, Object> info = userSessionService.getLicenseInfo();
Integer licensed = (Integer) info.get("licensedSessions");
if (licensed < 0) {
Notification.show("Invalid CUBA platform license", Notification.Type.WARNING_MESSAGE);
Notification.show("Invalid CUBA platform license. See server log for details.",
Notification.Type.ERROR_MESSAGE);
} else {
Integer active = (Integer) info.get("activeSessions");
if (licensed != 0 && active > licensed) {
Notification.show("Number of licensed sessions exceeded", "active: " + active + ", licensed: " + licensed,
Notification.Type.WARNING_MESSAGE);
Notification.Type.ERROR_MESSAGE);
}
}
}

View File

@ -242,12 +242,12 @@ public class AppWindow extends FocusHandlerWindow implements UserSubstitutionLis
Map<String, Object> info = userSessionService.getLicenseInfo();
Integer licensed = (Integer) info.get("licensedSessions");
if (licensed < 0) {
showNotification("Invalid CUBA platform license", Notification.TYPE_WARNING_MESSAGE);
showNotification("Invalid CUBA platform license. See server log for details.", Notification.TYPE_ERROR_MESSAGE);
} else {
Integer active = (Integer) info.get("activeSessions");
if (licensed != 0 && active > licensed) {
showNotification("Number of licensed sessions exceeded", "active: " + active + ", licensed: " + licensed,
Notification.TYPE_WARNING_MESSAGE);
Notification.TYPE_ERROR_MESSAGE);
}
}
}