This repository has been archived on 2026-03-21. You can view files and clone it, but cannot push or open issues or pull requests.
payfrit-biz/api/dev/timeTravel.cfm
John Mizerek 1210249f54 Normalize database column and table names across entire codebase
Update all SQL queries, query result references, and ColdFusion code to match
the renamed database schema. Tables use plural CamelCase, PKs are all `ID`,
column prefixes stripped (e.g. BusinessName→Name, UserFirstName→FirstName).

Key changes:
- Strip table-name prefixes from all column references (Businesses, Users,
  Addresses, Hours, Menus, Categories, Items, Stations, Orders,
  OrderLineItems, Tasks, TaskCategories, TaskRatings, QuickTaskTemplates,
  ScheduledTaskDefinitions, ChatMessages, Beacons, ServicePoints, Employees,
  VisitorTrackings, ApiPerfLogs, tt_States, tt_Days, tt_AddressTypes,
  tt_OrderTypes, tt_TaskTypes)
- Rename PK references from {TableName}ID to ID in all queries
- Rewrite 7 admin beacon files to use ServicePoints.BeaconID instead of
  dropped lt_Beacon_Businesses_ServicePoints link table
- Rewrite beacon assignment files (list, save, delete) for new schema
- Fix FK references incorrectly changed to ID (OrderLineItems.OrderID,
  Categories.MenuID, Tasks.CategoryID, ServicePoints.BeaconID)
- Update Addresses: AddressLat→Latitude, AddressLng→Longitude
- Update Users: UserPassword→Password, UserIsEmailVerified→IsEmailVerified,
  UserIsActive→IsActive, UserBalance→Balance, etc.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 15:39:12 -08:00

146 lines
4.5 KiB
Text

<cfsetting showdebugoutput="false">
<cfsetting enablecfoutputonly="true">
<cfcontent type="application/json; charset=utf-8" reset="true">
<cfscript>
/**
* Time Travel Endpoint - DEV ONLY
*
* Allows manipulation of timestamps for testing time-based features.
* Examples: token expiry, trial periods, scheduled events.
*
* POST: { "action": "expireTokens", "userId": 123 }
* POST: { "action": "setUserCreated", "userId": 123, "daysAgo": 30 }
*/
function apiAbort(required struct payload) {
writeOutput(serializeJSON(payload));
abort;
}
// SAFETY: Only allow on dev environment
if (!structKeyExists(application, "isDevEnvironment") || !application.isDevEnvironment) {
apiAbort({
"OK": false,
"ERROR": "forbidden",
"MESSAGE": "This endpoint is only available in development"
});
}
function readJsonBody() {
var raw = getHttpRequestData().content;
if (isNull(raw)) raw = "";
if (!len(trim(raw))) return {};
try {
var data = deserializeJSON(raw);
if (isStruct(data)) return data;
} catch (any e) {}
return {};
}
try {
if (cgi.request_method != "POST") {
apiAbort({
"OK": false,
"ERROR": "method_not_allowed",
"MESSAGE": "POST required"
});
}
data = readJsonBody();
action = structKeyExists(data, "action") ? lcase(data.action) : "";
switch (action) {
case "expiretokens":
// Expire all tokens for a user (simulate session timeout)
if (!structKeyExists(data, "userId")) {
apiAbort({ "OK": false, "ERROR": "missing_userId" });
}
queryExecute("
UPDATE UserTokens
SET CreatedAt = DATE_SUB(NOW(), INTERVAL 30 DAY)
WHERE UserID = :userId
", {
userId: { value: data.userId, cfsqltype: "cf_sql_integer" }
}, { datasource: "payfrit" });
writeOutput(serializeJSON({
"OK": true,
"message": "Tokens expired for user " & data.userId
}));
break;
case "setusercreated":
// Backdate user creation (for testing trial periods, etc)
if (!structKeyExists(data, "userId") || !structKeyExists(data, "daysAgo")) {
apiAbort({ "OK": false, "ERROR": "missing_userId_or_daysAgo" });
}
queryExecute("
UPDATE Users
SET AddedOn = DATE_SUB(NOW(), INTERVAL :days DAY)
WHERE UserID = :userId
", {
userId: { value: data.userId, cfsqltype: "cf_sql_integer" },
days: { value: data.daysAgo, cfsqltype: "cf_sql_integer" }
}, { datasource: "payfrit" });
writeOutput(serializeJSON({
"OK": true,
"message": "User " & data.userId & " created date set to " & data.daysAgo & " days ago"
}));
break;
case "clearotps":
// Clear all OTPs (force re-request)
queryExecute("
UPDATE Users SET MobileVerifyCode = ''
", {}, { datasource: "payfrit" });
writeOutput(serializeJSON({
"OK": true,
"message": "All OTPs cleared"
}));
break;
case "resetuser":
// Reset a user to unverified state (for retesting signup)
if (!structKeyExists(data, "phone")) {
apiAbort({ "OK": false, "ERROR": "missing_phone" });
}
queryExecute("
UPDATE Users
SET IsContactVerified = 0,
IsActive = 0,
FirstName = NULL,
LastName = NULL,
MobileVerifyCode = '123456'
WHERE ContactNumber = :phone
", {
phone: { value: data.phone, cfsqltype: "cf_sql_varchar" }
}, { datasource: "payfrit" });
writeOutput(serializeJSON({
"OK": true,
"message": "User with phone " & data.phone & " reset to unverified"
}));
break;
default:
apiAbort({
"OK": false,
"ERROR": "unknown_action",
"MESSAGE": "Valid actions: expireTokens, setUserCreated, clearOTPs, resetUser"
});
}
} catch (any e) {
apiAbort({
"OK": false,
"ERROR": "server_error",
"MESSAGE": application.showDetailedErrors ? e.message : "An error occurred"
});
}
</cfscript>