CTLE-436: added variant endpoint, refactored variant code a bit

This commit is contained in:
Tim Chamberlain
2023-06-28 19:45:37 -05:00
parent b75fd29a57
commit 2039c727b5
8 changed files with 534 additions and 147 deletions

View File

@ -1224,11 +1224,10 @@ public class QInstanceValidator
QScheduleMetaData schedule = process.getSchedule(); QScheduleMetaData schedule = process.getSchedule();
assertCondition(schedule.getRepeatMillis() != null || schedule.getRepeatSeconds() != null, "Either repeat millis or repeat seconds must be set on schedule in process " + processName); assertCondition(schedule.getRepeatMillis() != null || schedule.getRepeatSeconds() != null, "Either repeat millis or repeat seconds must be set on schedule in process " + processName);
if(schedule.getBackendVariant() != null) if(schedule.getVariantBackend() != null)
{ {
assertCondition(schedule.getVariantRunStrategy() != null, "A variant strategy was not set for " + schedule.getBackendVariant() + " on schedule in process " + processName); assertCondition(qInstance.getBackend(schedule.getVariantBackend()) != null, "A variant backend was not found for " + schedule.getVariantBackend());
assertCondition(schedule.getVariantTableName() != null, "A variant table name was not set for " + schedule.getBackendVariant() + " on schedule in process " + processName); assertCondition(schedule.getVariantRunStrategy() != null, "A variant run strategy was not set for " + schedule.getVariantBackend() + " on schedule in process " + processName);
assertCondition(schedule.getVariantFieldName() != null, "A variant field name was not set for " + schedule.getBackendVariant() + " on schedule in process " + processName);
} }
} }

View File

@ -43,12 +43,19 @@ public class QBackendMetaData
private String name; private String name;
private String backendType; private String backendType;
private Boolean usesVariants = false;
private String variantOptionsTableName;
private Set<Capability> enabledCapabilities = new HashSet<>(); private Set<Capability> enabledCapabilities = new HashSet<>();
private Set<Capability> disabledCapabilities = new HashSet<>(); private Set<Capability> disabledCapabilities = new HashSet<>();
private Boolean usesVariants = false;
private String variantOptionsTableIdField;
private String variantOptionsTableNameField;
private String variantOptionsTableTypeField;
private String variantOptionsTableTypeValue;
private String variantOptionsTableUsernameField;
private String variantOptionsTablePasswordField;
private String variantOptionsTableApiKeyField;
private String variantOptionsTableName;
// todo - at some point, we may want to apply this to secret properties on subclasses? // todo - at some point, we may want to apply this to secret properties on subclasses?
// @JsonFilter("secretsFilter") // @JsonFilter("secretsFilter")
@ -381,7 +388,224 @@ public class QBackendMetaData
/******************************************************************************* /*******************************************************************************
** Getter for variantsOptionTableName ** Getter for variantOptionsTableIdField
*******************************************************************************/
public String getVariantOptionsTableIdField()
{
return (this.variantOptionsTableIdField);
}
/*******************************************************************************
** Setter for variantOptionsTableIdField
*******************************************************************************/
public void setVariantOptionsTableIdField(String variantOptionsTableIdField)
{
this.variantOptionsTableIdField = variantOptionsTableIdField;
}
/*******************************************************************************
** Fluent setter for variantOptionsTableIdField
*******************************************************************************/
public QBackendMetaData withVariantOptionsTableIdField(String variantOptionsTableIdField)
{
this.variantOptionsTableIdField = variantOptionsTableIdField;
return (this);
}
/*******************************************************************************
** Getter for variantOptionsTableNameField
*******************************************************************************/
public String getVariantOptionsTableNameField()
{
return (this.variantOptionsTableNameField);
}
/*******************************************************************************
** Setter for variantOptionsTableNameField
*******************************************************************************/
public void setVariantOptionsTableNameField(String variantOptionsTableNameField)
{
this.variantOptionsTableNameField = variantOptionsTableNameField;
}
/*******************************************************************************
** Fluent setter for variantOptionsTableNameField
*******************************************************************************/
public QBackendMetaData withVariantOptionsTableNameField(String variantOptionsTableNameField)
{
this.variantOptionsTableNameField = variantOptionsTableNameField;
return (this);
}
/*******************************************************************************
** Getter for variantOptionsTableTypeField
*******************************************************************************/
public String getVariantOptionsTableTypeField()
{
return (this.variantOptionsTableTypeField);
}
/*******************************************************************************
** Setter for variantOptionsTableTypeField
*******************************************************************************/
public void setVariantOptionsTableTypeField(String variantOptionsTableTypeField)
{
this.variantOptionsTableTypeField = variantOptionsTableTypeField;
}
/*******************************************************************************
** Fluent setter for variantOptionsTableTypeField
*******************************************************************************/
public QBackendMetaData withVariantOptionsTableTypeField(String variantOptionsTableTypeField)
{
this.variantOptionsTableTypeField = variantOptionsTableTypeField;
return (this);
}
/*******************************************************************************
** Getter for variantOptionsTableTypeValue
*******************************************************************************/
public String getVariantOptionsTableTypeValue()
{
return (this.variantOptionsTableTypeValue);
}
/*******************************************************************************
** Setter for variantOptionsTableTypeValue
*******************************************************************************/
public void setVariantOptionsTableTypeValue(String variantOptionsTableTypeValue)
{
this.variantOptionsTableTypeValue = variantOptionsTableTypeValue;
}
/*******************************************************************************
** Fluent setter for variantOptionsTableTypeValue
*******************************************************************************/
public QBackendMetaData withVariantOptionsTableTypeValue(String variantOptionsTableTypeValue)
{
this.variantOptionsTableTypeValue = variantOptionsTableTypeValue;
return (this);
}
/*******************************************************************************
** Getter for variantOptionsTableUsernameField
*******************************************************************************/
public String getVariantOptionsTableUsernameField()
{
return (this.variantOptionsTableUsernameField);
}
/*******************************************************************************
** Setter for variantOptionsTableUsernameField
*******************************************************************************/
public void setVariantOptionsTableUsernameField(String variantOptionsTableUsernameField)
{
this.variantOptionsTableUsernameField = variantOptionsTableUsernameField;
}
/*******************************************************************************
** Fluent setter for variantOptionsTableUsernameField
*******************************************************************************/
public QBackendMetaData withVariantOptionsTableUsernameField(String variantOptionsTableUsernameField)
{
this.variantOptionsTableUsernameField = variantOptionsTableUsernameField;
return (this);
}
/*******************************************************************************
** Getter for variantOptionsTablePasswordField
*******************************************************************************/
public String getVariantOptionsTablePasswordField()
{
return (this.variantOptionsTablePasswordField);
}
/*******************************************************************************
** Setter for variantOptionsTablePasswordField
*******************************************************************************/
public void setVariantOptionsTablePasswordField(String variantOptionsTablePasswordField)
{
this.variantOptionsTablePasswordField = variantOptionsTablePasswordField;
}
/*******************************************************************************
** Fluent setter for variantOptionsTablePasswordField
*******************************************************************************/
public QBackendMetaData withVariantOptionsTablePasswordField(String variantOptionsTablePasswordField)
{
this.variantOptionsTablePasswordField = variantOptionsTablePasswordField;
return (this);
}
/*******************************************************************************
** Getter for variantOptionsTableApiKeyField
*******************************************************************************/
public String getVariantOptionsTableApiKeyField()
{
return (this.variantOptionsTableApiKeyField);
}
/*******************************************************************************
** Setter for variantOptionsTableApiKeyField
*******************************************************************************/
public void setVariantOptionsTableApiKeyField(String variantOptionsTableApiKeyField)
{
this.variantOptionsTableApiKeyField = variantOptionsTableApiKeyField;
}
/*******************************************************************************
** Fluent setter for variantOptionsTableApiKeyField
*******************************************************************************/
public QBackendMetaData withVariantOptionsTableApiKeyField(String variantOptionsTableApiKeyField)
{
this.variantOptionsTableApiKeyField = variantOptionsTableApiKeyField;
return (this);
}
/*******************************************************************************
** Getter for variantOptionsTableName
*******************************************************************************/ *******************************************************************************/
public String getVariantOptionsTableName() public String getVariantOptionsTableName()
{ {
@ -391,7 +615,7 @@ public class QBackendMetaData
/******************************************************************************* /*******************************************************************************
** Setter for variantsOptionTableName ** Setter for variantOptionsTableName
*******************************************************************************/ *******************************************************************************/
public void setVariantOptionsTableName(String variantOptionsTableName) public void setVariantOptionsTableName(String variantOptionsTableName)
{ {
@ -401,11 +625,11 @@ public class QBackendMetaData
/******************************************************************************* /*******************************************************************************
** Fluent setter for variantsOptionTableName ** Fluent setter for variantOptionsTableName
*******************************************************************************/ *******************************************************************************/
public QBackendMetaData withVariantsOptionTableName(String variantsOptionTableName) public QBackendMetaData withVariantOptionsTableName(String variantOptionsTableName)
{ {
this.variantOptionsTableName = variantsOptionTableName; this.variantOptionsTableName = variantOptionsTableName;
return (this); return (this);
} }

View File

@ -72,6 +72,9 @@ public class QFrontendTableMetaData
private boolean editPermission; private boolean editPermission;
private boolean deletePermission; private boolean deletePermission;
private boolean usesVariants;
private String variantTableLabel;
////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////
// do not add setters. take values from the source-object in the constructor!! // // do not add setters. take values from the source-object in the constructor!! //
////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////
@ -135,6 +138,13 @@ public class QFrontendTableMetaData
insertPermission = PermissionsHelper.hasTablePermission(actionInput, tableMetaData.getName(), TablePermissionSubType.INSERT); insertPermission = PermissionsHelper.hasTablePermission(actionInput, tableMetaData.getName(), TablePermissionSubType.INSERT);
editPermission = PermissionsHelper.hasTablePermission(actionInput, tableMetaData.getName(), TablePermissionSubType.EDIT); editPermission = PermissionsHelper.hasTablePermission(actionInput, tableMetaData.getName(), TablePermissionSubType.EDIT);
deletePermission = PermissionsHelper.hasTablePermission(actionInput, tableMetaData.getName(), TablePermissionSubType.DELETE); deletePermission = PermissionsHelper.hasTablePermission(actionInput, tableMetaData.getName(), TablePermissionSubType.DELETE);
QBackendMetaData backend = actionInput.getInstance().getBackend(tableMetaData.getBackendName());
if(backend != null && backend.getUsesVariants())
{
usesVariants = true;
variantTableLabel = actionInput.getInstance().getTable(backend.getVariantOptionsTableName()).getLabel();
}
} }
@ -294,6 +304,17 @@ public class QFrontendTableMetaData
/*******************************************************************************
** Getter for usesVariants
**
*******************************************************************************/
public boolean getUsesVariants()
{
return usesVariants;
}
/******************************************************************************* /*******************************************************************************
** Getter for exposedJoins ** Getter for exposedJoins
** **
@ -302,4 +323,15 @@ public class QFrontendTableMetaData
{ {
return exposedJoins; return exposedJoins;
} }
/*******************************************************************************
** Getter for variantTableLabel
*******************************************************************************/
public String getVariantTableLabel()
{
return (this.variantTableLabel);
}
} }

View File

@ -0,0 +1,130 @@
/*
* QQQ - Low-code Application Framework for Engineers.
* Copyright (C) 2021-2023. Kingsrook, LLC
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
* contact@kingsrook.com
* https://github.com/Kingsrook/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.kingsrook.qqq.backend.core.model.metadata.frontend;
import java.io.Serializable;
/*******************************************************************************
** Version of a variant for a frontend to see
*******************************************************************************/
public class QFrontendVariant
{
private Serializable id;
private String name;
private String type;
/*******************************************************************************
** Getter for id
*******************************************************************************/
public Serializable getId()
{
return (this.id);
}
/*******************************************************************************
** Setter for id
*******************************************************************************/
public void setId(Serializable id)
{
this.id = id;
}
/*******************************************************************************
** Fluent setter for id
*******************************************************************************/
public QFrontendVariant withId(Serializable id)
{
this.id = id;
return (this);
}
/*******************************************************************************
** Getter for name
*******************************************************************************/
public String getName()
{
return (this.name);
}
/*******************************************************************************
** Setter for name
*******************************************************************************/
public void setName(String name)
{
this.name = name;
}
/*******************************************************************************
** Fluent setter for name
*******************************************************************************/
public QFrontendVariant withName(String name)
{
this.name = name;
return (this);
}
/*******************************************************************************
** Getter for type
*******************************************************************************/
public String getType()
{
return (this.type);
}
/*******************************************************************************
** Setter for type
*******************************************************************************/
public void setType(String type)
{
this.type = type;
}
/*******************************************************************************
** Fluent setter for type
*******************************************************************************/
public QFrontendVariant withType(String type)
{
this.type = type;
return (this);
}
}

View File

@ -22,9 +22,6 @@
package com.kingsrook.qqq.backend.core.model.metadata.scheduleing; package com.kingsrook.qqq.backend.core.model.metadata.scheduleing;
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter;
/******************************************************************************* /*******************************************************************************
** Meta-data to define scheduled actions within QQQ. ** Meta-data to define scheduled actions within QQQ.
** **
@ -46,11 +43,8 @@ public class QScheduleMetaData
private Integer initialDelaySeconds; private Integer initialDelaySeconds;
private Integer initialDelayMillis; private Integer initialDelayMillis;
private RunStrategy variantRunStrategy; private RunStrategy variantRunStrategy;
private String backendVariant; private String variantBackend;
private String variantTableName;
private QQueryFilter variantFilter;
private String variantFieldName;
@ -191,124 +185,31 @@ public class QScheduleMetaData
/******************************************************************************* /*******************************************************************************
** Getter for backendVariant ** Getter for variantBackend
*******************************************************************************/ *******************************************************************************/
public String getBackendVariant() public String getVariantBackend()
{ {
return (this.backendVariant); return (this.variantBackend);
} }
/******************************************************************************* /*******************************************************************************
** Setter for backendVariant ** Setter for variantBackend
*******************************************************************************/ *******************************************************************************/
public void setBackendVariant(String backendVariant) public void setVariantBackend(String variantBackend)
{ {
this.backendVariant = backendVariant; this.variantBackend = variantBackend;
} }
/******************************************************************************* /*******************************************************************************
** Fluent setter for backendVariant ** Fluent setter for variantBackend
*******************************************************************************/ *******************************************************************************/
public QScheduleMetaData withBackendVariant(String backendVariant) public QScheduleMetaData withBackendVariant(String backendVariant)
{ {
this.backendVariant = backendVariant; this.variantBackend = backendVariant;
return (this);
}
/*******************************************************************************
** Getter for variantTableName
*******************************************************************************/
public String getVariantTableName()
{
return (this.variantTableName);
}
/*******************************************************************************
** Setter for variantTableName
*******************************************************************************/
public void setVariantTableName(String variantTableName)
{
this.variantTableName = variantTableName;
}
/*******************************************************************************
** Fluent setter for variantTableName
*******************************************************************************/
public QScheduleMetaData withVariantTableName(String variantTableName)
{
this.variantTableName = variantTableName;
return (this);
}
/*******************************************************************************
** Getter for variantFilter
*******************************************************************************/
public QQueryFilter getVariantFilter()
{
return (this.variantFilter);
}
/*******************************************************************************
** Setter for variantFilter
*******************************************************************************/
public void setVariantFilter(QQueryFilter variantFilter)
{
this.variantFilter = variantFilter;
}
/*******************************************************************************
** Fluent setter for variantFilter
*******************************************************************************/
public QScheduleMetaData withVariantFilter(QQueryFilter variantFilter)
{
this.variantFilter = variantFilter;
return (this);
}
/*******************************************************************************
** Getter for variantFieldName
*******************************************************************************/
public String getVariantFieldName()
{
return (this.variantFieldName);
}
/*******************************************************************************
** Setter for variantFieldName
*******************************************************************************/
public void setVariantFieldName(String variantFieldName)
{
this.variantFieldName = variantFieldName;
}
/*******************************************************************************
** Fluent setter for variantFieldName
*******************************************************************************/
public QScheduleMetaData withVariantFieldName(String variantFieldName)
{
this.variantFieldName = variantFieldName;
return (this); return (this);
} }

View File

@ -38,9 +38,13 @@ import com.kingsrook.qqq.backend.core.instances.QMetaDataVariableInterpreter;
import com.kingsrook.qqq.backend.core.logging.LogPair; import com.kingsrook.qqq.backend.core.logging.LogPair;
import com.kingsrook.qqq.backend.core.logging.QLogger; import com.kingsrook.qqq.backend.core.logging.QLogger;
import com.kingsrook.qqq.backend.core.model.actions.processes.RunProcessInput; import com.kingsrook.qqq.backend.core.model.actions.processes.RunProcessInput;
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QCriteriaOperator;
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QFilterCriteria;
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter;
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryInput; import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryInput;
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryOutput; import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryOutput;
import com.kingsrook.qqq.backend.core.model.data.QRecord; import com.kingsrook.qqq.backend.core.model.data.QRecord;
import com.kingsrook.qqq.backend.core.model.metadata.QBackendMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.QInstance; import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
import com.kingsrook.qqq.backend.core.model.metadata.automation.QAutomationProviderMetaData; import com.kingsrook.qqq.backend.core.model.metadata.automation.QAutomationProviderMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.processes.QProcessMetaData; import com.kingsrook.qqq.backend.core.model.metadata.processes.QProcessMetaData;
@ -142,7 +146,7 @@ public class ScheduleManager
if(process.getSchedule() != null && allowedToStart(process.getName())) if(process.getSchedule() != null && allowedToStart(process.getName()))
{ {
QScheduleMetaData scheduleMetaData = process.getSchedule(); QScheduleMetaData scheduleMetaData = process.getSchedule();
if(process.getSchedule().getBackendVariant() == null || QScheduleMetaData.RunStrategy.SERIAL.equals(process.getSchedule().getVariantRunStrategy())) if(process.getSchedule().getVariantBackend() == null || QScheduleMetaData.RunStrategy.SERIAL.equals(process.getSchedule().getVariantRunStrategy()))
{ {
/////////////////////////////////////////////// ///////////////////////////////////////////////
// if no variants, or variant is serial mode // // if no variants, or variant is serial mode //
@ -156,11 +160,12 @@ public class ScheduleManager
// running at the same time, get the variant records and schedule each separately // // running at the same time, get the variant records and schedule each separately //
///////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////
QContext.init(qInstance, sessionSupplier.get()); QContext.init(qInstance, sessionSupplier.get());
QBackendMetaData backendMetaData = qInstance.getBackend(scheduleMetaData.getVariantBackend());
for(QRecord qRecord : CollectionUtils.nonNullList(getBackendVariantFilteredRecords(process))) for(QRecord qRecord : CollectionUtils.nonNullList(getBackendVariantFilteredRecords(process)))
{ {
try try
{ {
startProcess(process, MapBuilder.of(scheduleMetaData.getBackendVariant(), qRecord.getValue(scheduleMetaData.getVariantFieldName()))); startProcess(process, MapBuilder.of(backendMetaData.getVariantOptionsTableTypeValue(), qRecord.getValue(backendMetaData.getVariantOptionsTableIdField())));
} }
catch(Exception e) catch(Exception e)
{ {
@ -170,7 +175,7 @@ public class ScheduleManager
} }
else else
{ {
LOG.error("Unsupported Schedule Run Strategy [" + process.getSchedule().getVariantFilter() + "] was provided."); LOG.error("Unsupported Schedule Run Strategy [" + process.getSchedule().getVariantRunStrategy() + "] was provided.");
} }
} }
} }
@ -187,10 +192,11 @@ public class ScheduleManager
try try
{ {
QScheduleMetaData scheduleMetaData = processMetaData.getSchedule(); QScheduleMetaData scheduleMetaData = processMetaData.getSchedule();
QBackendMetaData backendMetaData = qInstance.getBackend(scheduleMetaData.getVariantBackend());
QueryInput queryInput = new QueryInput(); QueryInput queryInput = new QueryInput();
queryInput.setTableName(scheduleMetaData.getVariantTableName()); queryInput.setTableName(backendMetaData.getVariantOptionsTableName());
queryInput.setFilter(scheduleMetaData.getVariantFilter()); queryInput.setFilter(new QQueryFilter(new QFilterCriteria(backendMetaData.getVariantOptionsTableTypeField(), QCriteriaOperator.EQUALS, backendMetaData.getVariantOptionsTableTypeValue())));
QContext.init(qInstance, sessionSupplier.get()); QContext.init(qInstance, sessionSupplier.get());
QueryOutput queryOutput = new QueryAction().execute(queryInput); QueryOutput queryOutput = new QueryAction().execute(queryInput);
@ -325,7 +331,7 @@ public class ScheduleManager
try try
{ {
if(process.getSchedule().getBackendVariant() == null || QScheduleMetaData.RunStrategy.PARALLEL.equals(process.getSchedule().getVariantRunStrategy())) if(process.getSchedule().getVariantBackend() == null || QScheduleMetaData.RunStrategy.PARALLEL.equals(process.getSchedule().getVariantRunStrategy()))
{ {
QContext.init(qInstance, sessionSupplier.get()); QContext.init(qInstance, sessionSupplier.get());
executeSingleProcess(process, backendVariantData); executeSingleProcess(process, backendVariantData);
@ -342,7 +348,8 @@ public class ScheduleManager
{ {
QContext.init(qInstance, sessionSupplier.get()); QContext.init(qInstance, sessionSupplier.get());
QScheduleMetaData scheduleMetaData = process.getSchedule(); QScheduleMetaData scheduleMetaData = process.getSchedule();
executeSingleProcess(process, MapBuilder.of(scheduleMetaData.getBackendVariant(), qRecord.getValue(scheduleMetaData.getVariantFieldName()))); QBackendMetaData backendMetaData = qInstance.getBackend(scheduleMetaData.getVariantBackend());
executeSingleProcess(process, MapBuilder.of(backendMetaData.getVariantOptionsTableTypeValue(), qRecord.getValue(backendMetaData.getVariantOptionsTableIdField())));
} }
catch(Exception e) catch(Exception e)
{ {

View File

@ -32,6 +32,7 @@ import java.util.Base64;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import com.kingsrook.qqq.backend.core.actions.tables.GetAction;
import com.kingsrook.qqq.backend.core.actions.tables.InsertAction; import com.kingsrook.qqq.backend.core.actions.tables.InsertAction;
import com.kingsrook.qqq.backend.core.context.QContext; import com.kingsrook.qqq.backend.core.context.QContext;
import com.kingsrook.qqq.backend.core.exceptions.QException; import com.kingsrook.qqq.backend.core.exceptions.QException;
@ -624,28 +625,57 @@ public class BaseAPIActionUtil
** **
** Can be overridden if an API uses an authorization type we don't natively support. ** Can be overridden if an API uses an authorization type we don't natively support.
*******************************************************************************/ *******************************************************************************/
protected void setupAuthorizationInRequest(HttpRequestBase request) throws QException public void setupAuthorizationInRequest(HttpRequestBase request) throws QException
{ {
///////////////////////////////////////////////////////////////////////////////////
// if backend specifies that it uses variants, look for that data in the session //
///////////////////////////////////////////////////////////////////////////////////
if(backendMetaData.getUsesVariants())
{
QSession session = QContext.getQSession();
if(session.getBackendVariants() == null || !session.getBackendVariants().containsKey(backendMetaData.getVariantOptionsTableTypeValue()))
{
throw (new QException("Could not find Backend Variant information for Backend '" + backendMetaData.getName() + "'"));
}
Serializable variantId = session.getBackendVariants().get(backendMetaData.getVariantOptionsTableTypeValue());
GetInput getInput = new GetInput();
getInput.setShouldMaskPasswords(false);
getInput.setTableName(backendMetaData.getVariantOptionsTableName());
getInput.setPrimaryKey(variantId);
GetOutput getOutput = new GetAction().execute(getInput);
QRecord record = getOutput.getRecord();
if(record == null)
{
throw (new QException("Could not find Backend Variant in table " + backendMetaData.getVariantOptionsTableName() + " with id '" + variantId + "'"));
}
if(backendMetaData.getAuthorizationType().equals(AuthorizationType.BASIC_AUTH_USERNAME_PASSWORD))
{
request.addHeader("Authorization", getBasicAuthenticationHeader(record.getValueString(backendMetaData.getVariantOptionsTableUsernameField()), record.getValueString(backendMetaData.getVariantOptionsTablePasswordField())));
}
else if(backendMetaData.getAuthorizationType().equals(AuthorizationType.API_KEY_HEADER))
{
request.addHeader("API-Key", record.getValueString(backendMetaData.getVariantOptionsTableApiKeyField()));
}
else
{
throw (new IllegalArgumentException("Unexpected variant authorization type specified: " + backendMetaData.getAuthorizationType()));
}
return;
}
///////////////////////////////////////////////////////////////////////////////////////////
// if not using variants, the authorization data will be in the backend meta data object //
///////////////////////////////////////////////////////////////////////////////////////////
switch(backendMetaData.getAuthorizationType()) switch(backendMetaData.getAuthorizationType())
{ {
case BASIC_AUTH_API_KEY: case BASIC_AUTH_API_KEY -> request.addHeader("Authorization", getBasicAuthenticationHeader(backendMetaData.getApiKey()));
request.addHeader("Authorization", getBasicAuthenticationHeader(backendMetaData.getApiKey())); case BASIC_AUTH_USERNAME_PASSWORD -> request.addHeader("Authorization", getBasicAuthenticationHeader(backendMetaData.getUsername(), backendMetaData.getPassword()));
break; case API_KEY_HEADER -> request.addHeader("API-Key", backendMetaData.getApiKey());
case OAUTH2 -> request.setHeader("Authorization", "Bearer " + getOAuth2Token());
case BASIC_AUTH_USERNAME_PASSWORD: default -> throw new IllegalArgumentException("Unexpected authorization type: " + backendMetaData.getAuthorizationType());
request.addHeader("Authorization", getBasicAuthenticationHeader(backendMetaData.getUsername(), backendMetaData.getPassword()));
break;
case API_KEY_HEADER:
request.addHeader("API-Key", backendMetaData.getApiKey());
break;
case OAUTH2:
request.setHeader("Authorization", "Bearer " + getOAuth2Token());
break;
default:
throw new IllegalArgumentException("Unexpected authorization type: " + backendMetaData.getAuthorizationType());
} }
} }

View File

@ -87,6 +87,8 @@ import com.kingsrook.qqq.backend.core.model.actions.tables.get.GetInput;
import com.kingsrook.qqq.backend.core.model.actions.tables.get.GetOutput; import com.kingsrook.qqq.backend.core.model.actions.tables.get.GetOutput;
import com.kingsrook.qqq.backend.core.model.actions.tables.insert.InsertInput; import com.kingsrook.qqq.backend.core.model.actions.tables.insert.InsertInput;
import com.kingsrook.qqq.backend.core.model.actions.tables.insert.InsertOutput; import com.kingsrook.qqq.backend.core.model.actions.tables.insert.InsertOutput;
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QCriteriaOperator;
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QFilterCriteria;
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter; import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter;
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryInput; import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryInput;
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryJoin; import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryJoin;
@ -98,11 +100,13 @@ import com.kingsrook.qqq.backend.core.model.actions.values.SearchPossibleValueSo
import com.kingsrook.qqq.backend.core.model.actions.widgets.RenderWidgetInput; import com.kingsrook.qqq.backend.core.model.actions.widgets.RenderWidgetInput;
import com.kingsrook.qqq.backend.core.model.actions.widgets.RenderWidgetOutput; import com.kingsrook.qqq.backend.core.model.actions.widgets.RenderWidgetOutput;
import com.kingsrook.qqq.backend.core.model.data.QRecord; import com.kingsrook.qqq.backend.core.model.data.QRecord;
import com.kingsrook.qqq.backend.core.model.metadata.QBackendMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.QInstance; import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
import com.kingsrook.qqq.backend.core.model.metadata.fields.AdornmentType; import com.kingsrook.qqq.backend.core.model.metadata.fields.AdornmentType;
import com.kingsrook.qqq.backend.core.model.metadata.fields.FieldAdornment; import com.kingsrook.qqq.backend.core.model.metadata.fields.FieldAdornment;
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData; import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldType; import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldType;
import com.kingsrook.qqq.backend.core.model.metadata.frontend.QFrontendVariant;
import com.kingsrook.qqq.backend.core.model.metadata.processes.QProcessMetaData; import com.kingsrook.qqq.backend.core.model.metadata.processes.QProcessMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData; import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
import com.kingsrook.qqq.backend.core.model.session.QSession; import com.kingsrook.qqq.backend.core.model.session.QSession;
@ -114,6 +118,7 @@ import com.kingsrook.qqq.backend.core.utils.ExceptionUtils;
import com.kingsrook.qqq.backend.core.utils.JsonUtils; import com.kingsrook.qqq.backend.core.utils.JsonUtils;
import com.kingsrook.qqq.backend.core.utils.StringUtils; import com.kingsrook.qqq.backend.core.utils.StringUtils;
import com.kingsrook.qqq.backend.core.utils.ValueUtils; import com.kingsrook.qqq.backend.core.utils.ValueUtils;
import com.kingsrook.qqq.backend.core.utils.collections.MapBuilder;
import com.kingsrook.qqq.backend.core.utils.lambdas.UnsafeConsumer; import com.kingsrook.qqq.backend.core.utils.lambdas.UnsafeConsumer;
import com.kingsrook.qqq.backend.core.utils.lambdas.UnsafeFunction; import com.kingsrook.qqq.backend.core.utils.lambdas.UnsafeFunction;
import io.javalin.Javalin; import io.javalin.Javalin;
@ -348,6 +353,7 @@ public class QJavalinImplementation
post("/", QJavalinImplementation::dataInsert); post("/", QJavalinImplementation::dataInsert);
get("/count", QJavalinImplementation::dataCount); get("/count", QJavalinImplementation::dataCount);
post("/count", QJavalinImplementation::dataCount); post("/count", QJavalinImplementation::dataCount);
get("/variants", QJavalinImplementation::variants);
get("/export", QJavalinImplementation::dataExportWithoutFilename); get("/export", QJavalinImplementation::dataExportWithoutFilename);
post("/export", QJavalinImplementation::dataExportWithoutFilename); post("/export", QJavalinImplementation::dataExportWithoutFilename);
get("/export/{filename}", QJavalinImplementation::dataExportWithFilename); get("/export/{filename}", QJavalinImplementation::dataExportWithFilename);
@ -478,6 +484,13 @@ public class QJavalinImplementation
QSession session = authenticationModule.createSession(qInstance, authenticationContext); QSession session = authenticationModule.createSession(qInstance, authenticationContext);
QContext.init(qInstance, session, null, input); QContext.init(qInstance, session, null, input);
String tableVariant = StringUtils.hasContent(context.formParam("tableVariant")) ? context.formParam("tableVariant") : context.queryParam("tableVariant");
if(StringUtils.hasContent(tableVariant))
{
JSONObject variant = new JSONObject(tableVariant);
QContext.getQSession().setBackendVariants(MapBuilder.of(variant.getString("type"), variant.getInt("id")));
}
///////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////
// if we got a session id cookie in, then send it back with updated cookie age // // if we got a session id cookie in, then send it back with updated cookie age //
///////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////
@ -970,6 +983,57 @@ public class QJavalinImplementation
/*******************************************************************************
*
*******************************************************************************/
static void variants(Context context)
{
String table = context.pathParam("table");
List<QFrontendVariant> variants = new ArrayList<>();
try
{
QueryInput queryInput = new QueryInput();
setupSession(context, queryInput);
////////////////////////////////////
// get the backend for this table //
////////////////////////////////////
QTableMetaData tableMetaData = QContext.getQInstance().getTable(table);
QBackendMetaData backend = QContext.getQInstance().getBackend(tableMetaData.getBackendName());
/////////////////////////////////////////////////////////////////////////////////////
// if the backend uses variants, query for all possible variants of the given type //
/////////////////////////////////////////////////////////////////////////////////////
if(backend != null && backend.getUsesVariants())
{
queryInput.setTableName(backend.getVariantOptionsTableName());
queryInput.setFilter(new QQueryFilter(new QFilterCriteria(backend.getVariantOptionsTableTypeField(), QCriteriaOperator.EQUALS, backend.getVariantOptionsTableTypeValue())));
QueryOutput output = new QueryAction().execute(queryInput);
for(QRecord qRecord : output.getRecords())
{
variants.add(new QFrontendVariant()
.withId(qRecord.getValue(backend.getVariantOptionsTableIdField()))
.withType(backend.getVariantOptionsTableTypeValue())
.withName(qRecord.getValueString(backend.getVariantOptionsTableNameField()));
}
QJavalinAccessLogger.logStartSilent("variants");
PermissionsHelper.checkTablePermissionThrowing(queryInput, TablePermissionSubType.READ);
}
QJavalinAccessLogger.logEndSuccessIfSlow(SLOW_LOG_THRESHOLD_MS, logPair("table", table), logPair("input", queryInput));
context.result(JsonUtils.toJson(variants));
}
catch(Exception e)
{
QJavalinAccessLogger.logEndFail(e, logPair("table", table));
handleException(context, e);
}
}
/******************************************************************************* /*******************************************************************************
* *
* Filter parameter is a serialized QQueryFilter object, that is to say: * Filter parameter is a serialized QQueryFilter object, that is to say: