@base44-preview/cli 0.0.50-pr.484.031bd45 → 0.0.50-pr.484.1c556f7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +402 -173
- package/dist/cli/index.js.map +21 -11
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -219982,7 +219982,8 @@ var theme = {
|
|
|
219982
219982
|
bold: source_default.bold,
|
|
219983
219983
|
dim: source_default.dim,
|
|
219984
219984
|
error: source_default.red,
|
|
219985
|
-
warn: source_default.yellow
|
|
219985
|
+
warn: source_default.yellow,
|
|
219986
|
+
info: source_default.cyan
|
|
219986
219987
|
},
|
|
219987
219988
|
format: {
|
|
219988
219989
|
errorContext(ctx) {
|
|
@@ -242001,88 +242002,123 @@ async function pushCustomOAuthSecret(provider, clientSecret) {
|
|
|
242001
242002
|
[providerInfo.customOAuth.secretKey]: clientSecret
|
|
242002
242003
|
});
|
|
242003
242004
|
}
|
|
242004
|
-
// src/core/resources/auth-config/sso.ts
|
|
242005
|
-
var
|
|
242006
|
-
|
|
242007
|
-
"
|
|
242008
|
-
"
|
|
242009
|
-
"
|
|
242010
|
-
"
|
|
242011
|
-
];
|
|
242012
|
-
|
|
242013
|
-
|
|
242014
|
-
|
|
242015
|
-
|
|
242016
|
-
|
|
242017
|
-
|
|
242018
|
-
|
|
242019
|
-
|
|
242020
|
-
|
|
242021
|
-
|
|
242022
|
-
|
|
242023
|
-
|
|
242024
|
-
|
|
242025
|
-
|
|
242026
|
-
|
|
242027
|
-
|
|
242028
|
-
|
|
242029
|
-
|
|
242030
|
-
|
|
242031
|
-
|
|
242032
|
-
|
|
242033
|
-
|
|
242034
|
-
|
|
242005
|
+
// src/core/resources/auth-config/sso/secret-keys.ts
|
|
242006
|
+
var SSOSecretKey;
|
|
242007
|
+
((SSOSecretKey2) => {
|
|
242008
|
+
SSOSecretKey2["Name"] = "sso_name";
|
|
242009
|
+
SSOSecretKey2["ClientId"] = "sso_client_id";
|
|
242010
|
+
SSOSecretKey2["ClientSecret"] = "sso_client_secret";
|
|
242011
|
+
SSOSecretKey2["Scope"] = "sso_scope";
|
|
242012
|
+
SSOSecretKey2["DiscoveryUrl"] = "sso_discovery_url";
|
|
242013
|
+
SSOSecretKey2["TenantId"] = "sso_tenant_id";
|
|
242014
|
+
SSOSecretKey2["AuthEndpoint"] = "sso_auth_endpoint";
|
|
242015
|
+
SSOSecretKey2["TokenEndpoint"] = "sso_token_endpoint";
|
|
242016
|
+
SSOSecretKey2["UserinfoEndpoint"] = "sso_userinfo_endpoint";
|
|
242017
|
+
SSOSecretKey2["OktaDomain"] = "sso_okta_domain";
|
|
242018
|
+
SSOSecretKey2["JwksUri"] = "sso_jwks_uri";
|
|
242019
|
+
})(SSOSecretKey ||= {});
|
|
242020
|
+
var ALL_SSO_SECRET_KEYS = Object.values(SSOSecretKey);
|
|
242021
|
+
|
|
242022
|
+
// src/core/resources/auth-config/sso/providers/custom.ts
|
|
242023
|
+
var DEFAULT_SCOPE = "openid email profile";
|
|
242024
|
+
var customProvider = {
|
|
242025
|
+
requiredKeys: [
|
|
242026
|
+
"sso_auth_endpoint" /* AuthEndpoint */,
|
|
242027
|
+
"sso_token_endpoint" /* TokenEndpoint */,
|
|
242028
|
+
"sso_userinfo_endpoint" /* UserinfoEndpoint */,
|
|
242029
|
+
"sso_jwks_uri" /* JwksUri */
|
|
242030
|
+
],
|
|
242031
|
+
defaults: {
|
|
242032
|
+
["sso_scope" /* Scope */]: DEFAULT_SCOPE
|
|
242033
|
+
}
|
|
242034
|
+
};
|
|
242035
|
+
|
|
242036
|
+
// src/core/resources/auth-config/sso/providers/github.ts
|
|
242037
|
+
var githubProvider = {
|
|
242038
|
+
requiredKeys: [],
|
|
242039
|
+
defaults: {
|
|
242040
|
+
["sso_scope" /* Scope */]: "user:email",
|
|
242041
|
+
["sso_auth_endpoint" /* AuthEndpoint */]: "https://github.com/login/oauth/authorize",
|
|
242042
|
+
["sso_token_endpoint" /* TokenEndpoint */]: "https://github.com/login/oauth/access_token",
|
|
242043
|
+
["sso_userinfo_endpoint" /* UserinfoEndpoint */]: "https://api.github.com/user"
|
|
242044
|
+
}
|
|
242045
|
+
};
|
|
242046
|
+
|
|
242047
|
+
// src/core/resources/auth-config/sso/providers/google.ts
|
|
242048
|
+
var DEFAULT_SCOPE2 = "openid email profile";
|
|
242049
|
+
var googleProvider = {
|
|
242050
|
+
requiredKeys: [],
|
|
242051
|
+
defaults: {
|
|
242052
|
+
["sso_scope" /* Scope */]: DEFAULT_SCOPE2,
|
|
242053
|
+
["sso_discovery_url" /* DiscoveryUrl */]: "https://accounts.google.com/.well-known/openid-configuration"
|
|
242054
|
+
}
|
|
242055
|
+
};
|
|
242056
|
+
|
|
242057
|
+
// src/core/resources/auth-config/sso/providers/microsoft.ts
|
|
242058
|
+
var DEFAULT_SCOPE3 = "openid email profile";
|
|
242059
|
+
var microsoftProvider = {
|
|
242060
|
+
requiredKeys: ["sso_tenant_id" /* TenantId */],
|
|
242061
|
+
defaults: {
|
|
242062
|
+
["sso_scope" /* Scope */]: DEFAULT_SCOPE3
|
|
242035
242063
|
},
|
|
242036
|
-
|
|
242037
|
-
|
|
242038
|
-
|
|
242039
|
-
|
|
242040
|
-
|
|
242041
|
-
|
|
242042
|
-
sso_userinfo_endpoint: "https://api.github.com/user"
|
|
242064
|
+
deriveDefaults: (secrets) => {
|
|
242065
|
+
const tenantId = secrets["sso_tenant_id" /* TenantId */];
|
|
242066
|
+
if (tenantId) {
|
|
242067
|
+
return {
|
|
242068
|
+
["sso_discovery_url" /* DiscoveryUrl */]: `https://login.microsoftonline.com/${tenantId}/v2.0/.well-known/openid-configuration`
|
|
242069
|
+
};
|
|
242043
242070
|
}
|
|
242071
|
+
return {};
|
|
242072
|
+
}
|
|
242073
|
+
};
|
|
242074
|
+
|
|
242075
|
+
// src/core/resources/auth-config/sso/providers/okta.ts
|
|
242076
|
+
var DEFAULT_SCOPE4 = "openid email profile";
|
|
242077
|
+
var oktaProvider = {
|
|
242078
|
+
requiredKeys: ["sso_okta_domain" /* OktaDomain */],
|
|
242079
|
+
defaults: {
|
|
242080
|
+
["sso_scope" /* Scope */]: DEFAULT_SCOPE4
|
|
242044
242081
|
},
|
|
242045
|
-
|
|
242046
|
-
|
|
242047
|
-
|
|
242048
|
-
|
|
242049
|
-
|
|
242050
|
-
|
|
242051
|
-
const domain2 = options.sso_okta_domain;
|
|
242052
|
-
if (domain2) {
|
|
242053
|
-
return {
|
|
242054
|
-
sso_discovery_url: `https://${domain2}/.well-known/openid-configuration`
|
|
242055
|
-
};
|
|
242056
|
-
}
|
|
242057
|
-
return {};
|
|
242082
|
+
deriveDefaults: (secrets) => {
|
|
242083
|
+
const domain2 = secrets["sso_okta_domain" /* OktaDomain */];
|
|
242084
|
+
if (domain2) {
|
|
242085
|
+
return {
|
|
242086
|
+
["sso_discovery_url" /* DiscoveryUrl */]: `https://${domain2}/.well-known/openid-configuration`
|
|
242087
|
+
};
|
|
242058
242088
|
}
|
|
242059
|
-
|
|
242060
|
-
|
|
242061
|
-
|
|
242062
|
-
|
|
242063
|
-
|
|
242064
|
-
|
|
242065
|
-
|
|
242066
|
-
|
|
242067
|
-
|
|
242068
|
-
|
|
242069
|
-
|
|
242070
|
-
|
|
242071
|
-
|
|
242072
|
-
|
|
242073
|
-
var
|
|
242074
|
-
"
|
|
242075
|
-
"
|
|
242076
|
-
"
|
|
242077
|
-
"
|
|
242078
|
-
"
|
|
242079
|
-
|
|
242080
|
-
|
|
242081
|
-
|
|
242082
|
-
|
|
242083
|
-
"
|
|
242084
|
-
"
|
|
242085
|
-
|
|
242089
|
+
return {};
|
|
242090
|
+
}
|
|
242091
|
+
};
|
|
242092
|
+
|
|
242093
|
+
// src/core/resources/auth-config/sso/providers/index.ts
|
|
242094
|
+
var SSO_PROVIDER_SCHEMAS = {
|
|
242095
|
+
google: googleProvider,
|
|
242096
|
+
microsoft: microsoftProvider,
|
|
242097
|
+
github: githubProvider,
|
|
242098
|
+
okta: oktaProvider,
|
|
242099
|
+
custom: customProvider
|
|
242100
|
+
};
|
|
242101
|
+
|
|
242102
|
+
// src/core/resources/auth-config/sso/types.ts
|
|
242103
|
+
var KNOWN_SSO_PROVIDERS = {
|
|
242104
|
+
google: "google",
|
|
242105
|
+
microsoft: "microsoft",
|
|
242106
|
+
github: "github",
|
|
242107
|
+
okta: "okta",
|
|
242108
|
+
custom: "custom"
|
|
242109
|
+
};
|
|
242110
|
+
|
|
242111
|
+
// src/core/resources/auth-config/sso/operations.ts
|
|
242112
|
+
var OPTION_TO_SECRET_KEY = {
|
|
242113
|
+
scope: "sso_scope" /* Scope */,
|
|
242114
|
+
discoveryUrl: "sso_discovery_url" /* DiscoveryUrl */,
|
|
242115
|
+
tenantId: "sso_tenant_id" /* TenantId */,
|
|
242116
|
+
oktaDomain: "sso_okta_domain" /* OktaDomain */,
|
|
242117
|
+
authEndpoint: "sso_auth_endpoint" /* AuthEndpoint */,
|
|
242118
|
+
tokenEndpoint: "sso_token_endpoint" /* TokenEndpoint */,
|
|
242119
|
+
userinfoEndpoint: "sso_userinfo_endpoint" /* UserinfoEndpoint */,
|
|
242120
|
+
jwksUri: "sso_jwks_uri" /* JwksUri */
|
|
242121
|
+
};
|
|
242086
242122
|
async function updateSSOConfig(authDir, provider, enable) {
|
|
242087
242123
|
const current = await readAuthConfig(authDir) ?? DEFAULT_AUTH_CONFIG;
|
|
242088
242124
|
const merged = {
|
|
@@ -242099,22 +242135,12 @@ async function updateSSOConfig(authDir, provider, enable) {
|
|
|
242099
242135
|
await writeAuthConfig(authDir, merged);
|
|
242100
242136
|
return merged;
|
|
242101
242137
|
}
|
|
242102
|
-
var OPTION_TO_SECRET_KEY = {
|
|
242103
|
-
scope: "sso_scope",
|
|
242104
|
-
discoveryUrl: "sso_discovery_url",
|
|
242105
|
-
tenantId: "sso_tenant_id",
|
|
242106
|
-
oktaDomain: "sso_okta_domain",
|
|
242107
|
-
authEndpoint: "sso_auth_endpoint",
|
|
242108
|
-
tokenEndpoint: "sso_token_endpoint",
|
|
242109
|
-
userinfoEndpoint: "sso_userinfo_endpoint",
|
|
242110
|
-
jwksUri: "sso_jwks_uri"
|
|
242111
|
-
};
|
|
242112
242138
|
function buildSSOSecrets(provider, options) {
|
|
242113
242139
|
const schema3 = SSO_PROVIDER_SCHEMAS[provider];
|
|
242114
242140
|
const secrets = {};
|
|
242115
|
-
secrets
|
|
242116
|
-
secrets
|
|
242117
|
-
secrets
|
|
242141
|
+
secrets["sso_name" /* Name */] = options.ssoName ?? provider;
|
|
242142
|
+
secrets["sso_client_id" /* ClientId */] = options.clientId;
|
|
242143
|
+
secrets["sso_client_secret" /* ClientSecret */] = options.clientSecret;
|
|
242118
242144
|
for (const [optionKey, secretKey] of Object.entries(OPTION_TO_SECRET_KEY)) {
|
|
242119
242145
|
const value = options[optionKey];
|
|
242120
242146
|
if (typeof value === "string" && value.length > 0) {
|
|
@@ -242140,8 +242166,8 @@ function buildSSOSecrets(provider, options) {
|
|
|
242140
242166
|
missing.push(key);
|
|
242141
242167
|
}
|
|
242142
242168
|
}
|
|
242143
|
-
if (provider ===
|
|
242144
|
-
missing.push("sso_name");
|
|
242169
|
+
if (provider === KNOWN_SSO_PROVIDERS.custom && !options.ssoName) {
|
|
242170
|
+
missing.push("sso_name" /* Name */);
|
|
242145
242171
|
}
|
|
242146
242172
|
if (missing.length > 0) {
|
|
242147
242173
|
throw new InvalidInputError(`Missing required fields for ${provider}: ${missing.join(", ")}`);
|
|
@@ -243564,6 +243590,7 @@ var package_default = {
|
|
|
243564
243590
|
"@types/ejs": "^3.1.5",
|
|
243565
243591
|
"@types/express": "^5.0.6",
|
|
243566
243592
|
"@types/json-schema": "^7.0.15",
|
|
243593
|
+
"@types/jsonwebtoken": "^9.0.10",
|
|
243567
243594
|
"@types/lodash": "^4.17.24",
|
|
243568
243595
|
"@types/multer": "^2.0.0",
|
|
243569
243596
|
"@types/node": "^22.10.5",
|
|
@@ -243582,6 +243609,7 @@ var package_default = {
|
|
|
243582
243609
|
globby: "^16.1.0",
|
|
243583
243610
|
"http-proxy-middleware": "^3.0.5",
|
|
243584
243611
|
"json-schema-to-typescript": "^15.0.4",
|
|
243612
|
+
jsonwebtoken: "^9.0.3",
|
|
243585
243613
|
json5: "^2.2.3",
|
|
243586
243614
|
ky: "^1.14.2",
|
|
243587
243615
|
lodash: "^4.17.23",
|
|
@@ -243597,6 +243625,7 @@ var package_default = {
|
|
|
243597
243625
|
typescript: "^5.7.2",
|
|
243598
243626
|
vitest: "^4.0.16",
|
|
243599
243627
|
yaml: "^2.8.2",
|
|
243628
|
+
qs: "^6.12.3",
|
|
243600
243629
|
zod: "^4.3.5"
|
|
243601
243630
|
},
|
|
243602
243631
|
engines: {
|
|
@@ -251234,19 +251263,20 @@ function mergeFileWithFlags(fileConfig, options) {
|
|
|
251234
251263
|
ssoName: options.ssoName ?? fileConfig.ssoName
|
|
251235
251264
|
};
|
|
251236
251265
|
}
|
|
251266
|
+
var providerNames = Object.keys(KNOWN_SSO_PROVIDERS);
|
|
251237
251267
|
function validateProvider(provider) {
|
|
251238
251268
|
if (!provider) {
|
|
251239
251269
|
throw new InvalidInputError("Missing --provider.", {
|
|
251240
251270
|
hints: [
|
|
251241
251271
|
{
|
|
251242
|
-
message: `Valid providers: ${
|
|
251243
|
-
command: "base44 auth sso enable --provider
|
|
251272
|
+
message: `Valid providers: ${providerNames.join(", ")}`,
|
|
251273
|
+
command: "base44 auth sso enable --provider <provider> --client-id <id> --client-secret <secret>"
|
|
251244
251274
|
}
|
|
251245
251275
|
]
|
|
251246
251276
|
});
|
|
251247
251277
|
}
|
|
251248
|
-
if (!
|
|
251249
|
-
throw new InvalidInputError(`Unknown provider "${provider}". Valid providers: ${
|
|
251278
|
+
if (!(provider in KNOWN_SSO_PROVIDERS)) {
|
|
251279
|
+
throw new InvalidInputError(`Unknown provider "${provider}". Valid providers: ${providerNames.join(", ")}`);
|
|
251250
251280
|
}
|
|
251251
251281
|
return provider;
|
|
251252
251282
|
}
|
|
@@ -253367,9 +253397,12 @@ function getTypesCommand() {
|
|
|
253367
253397
|
return new Command("types").description("Manage TypeScript type generation").addCommand(getTypesGenerateCommand());
|
|
253368
253398
|
}
|
|
253369
253399
|
|
|
253400
|
+
// src/cli/commands/dev.ts
|
|
253401
|
+
import process21 from "node:process";
|
|
253402
|
+
|
|
253370
253403
|
// src/cli/dev/dev-server/main.ts
|
|
253371
253404
|
var import_cors = __toESM(require_lib4(), 1);
|
|
253372
|
-
var
|
|
253405
|
+
var import_express6 = __toESM(require_express(), 1);
|
|
253373
253406
|
import { dirname as dirname18, join as join25 } from "node:path";
|
|
253374
253407
|
|
|
253375
253408
|
// ../../node_modules/get-port/index.js
|
|
@@ -253933,7 +253966,9 @@ class Validator {
|
|
|
253933
253966
|
}
|
|
253934
253967
|
|
|
253935
253968
|
// src/cli/dev/dev-server/db/database.ts
|
|
253969
|
+
var PRIVATE_COLLECTION_PREFIX = "$";
|
|
253936
253970
|
var USER_COLLECTION = "user";
|
|
253971
|
+
var PRIVATE_USER_COLLECTION = PRIVATE_COLLECTION_PREFIX + USER_COLLECTION;
|
|
253937
253972
|
|
|
253938
253973
|
class Database {
|
|
253939
253974
|
collections = new Map;
|
|
@@ -253955,6 +253990,7 @@ class Database {
|
|
|
253955
253990
|
this.schemas.set(USER_COLLECTION, this.buildUserSchema(userEntity));
|
|
253956
253991
|
const collection = new import_nedb.default;
|
|
253957
253992
|
this.collections.set(USER_COLLECTION, collection);
|
|
253993
|
+
this.collections.set(PRIVATE_USER_COLLECTION, new import_nedb.default);
|
|
253958
253994
|
const userInfo = await readAuth();
|
|
253959
253995
|
const now = getNowISOTimestamp();
|
|
253960
253996
|
await collection.insertAsync({
|
|
@@ -253996,7 +254032,9 @@ class Database {
|
|
|
253996
254032
|
return this.collections.get(this.normalizeName(name2));
|
|
253997
254033
|
}
|
|
253998
254034
|
getCollectionNames() {
|
|
253999
|
-
return Array.from(this.collections.keys())
|
|
254035
|
+
return Array.from(this.collections.keys()).filter((name2) => {
|
|
254036
|
+
return !name2.startsWith(PRIVATE_COLLECTION_PREFIX);
|
|
254037
|
+
});
|
|
254000
254038
|
}
|
|
254001
254039
|
dropAll() {
|
|
254002
254040
|
for (const collection of this.collections.values()) {
|
|
@@ -254060,15 +254098,229 @@ function broadcastEntityEvent(io6, appId, entityName, event) {
|
|
|
254060
254098
|
});
|
|
254061
254099
|
}
|
|
254062
254100
|
|
|
254063
|
-
// src/cli/dev/dev-server/routes/
|
|
254064
|
-
var import_express3 = __toESM(require_express(), 1);
|
|
254065
|
-
|
|
254066
|
-
// src/cli/dev/dev-server/routes/entities/entities-user-router.ts
|
|
254101
|
+
// src/cli/dev/dev-server/routes/auth-router.ts
|
|
254067
254102
|
var import_express2 = __toESM(require_express(), 1);
|
|
254068
254103
|
var import_jsonwebtoken = __toESM(require_jsonwebtoken(), 1);
|
|
254069
|
-
|
|
254104
|
+
import { randomInt } from "node:crypto";
|
|
254105
|
+
var LOCAL_DEV_SECRET = "LOCAL_DEV_SECRET";
|
|
254106
|
+
var TEN_MINUTES = 10 * 60 * 1000;
|
|
254107
|
+
var generateCode = () => {
|
|
254108
|
+
return randomInt(1e5, 1e6).toString();
|
|
254109
|
+
};
|
|
254110
|
+
var createJwtToken = (email3) => {
|
|
254111
|
+
return import_jsonwebtoken.default.sign({ sub: email3 }, LOCAL_DEV_SECRET, {
|
|
254112
|
+
expiresIn: "360d"
|
|
254113
|
+
});
|
|
254114
|
+
};
|
|
254115
|
+
var LoginBody = object({ email: email2(), password: string2() });
|
|
254116
|
+
var VerifyOtpBody = object({ email: email2(), otp_code: string2() });
|
|
254117
|
+
function createAuthRouter(db2, logger2) {
|
|
254070
254118
|
const router = import_express2.Router({ mergeParams: true });
|
|
254071
254119
|
const parseBody = import_express2.json();
|
|
254120
|
+
router.post("/login", parseBody, async (req, res) => {
|
|
254121
|
+
const { email: email3, password } = LoginBody.parse(req.body);
|
|
254122
|
+
const result = await db2.getCollection(USER_COLLECTION)?.findOneAsync({ email: email3 });
|
|
254123
|
+
if (result) {
|
|
254124
|
+
const privateUserData = await db2.getCollection(PRIVATE_USER_COLLECTION)?.findOneAsync({ email: email3 });
|
|
254125
|
+
if (result.role === "admin" || privateUserData?.password === password) {
|
|
254126
|
+
res.json({
|
|
254127
|
+
access_token: createJwtToken(email3),
|
|
254128
|
+
success: true,
|
|
254129
|
+
user: {}
|
|
254130
|
+
});
|
|
254131
|
+
} else {
|
|
254132
|
+
res.status(400).json({
|
|
254133
|
+
detail: "Invalid email or password",
|
|
254134
|
+
error_type: "HTTPException",
|
|
254135
|
+
message: "Invalid email or password",
|
|
254136
|
+
request_id: null,
|
|
254137
|
+
traceback: ""
|
|
254138
|
+
});
|
|
254139
|
+
}
|
|
254140
|
+
return;
|
|
254141
|
+
}
|
|
254142
|
+
res.status(401).json({ error: "Unauthorized" });
|
|
254143
|
+
});
|
|
254144
|
+
router.post("/register", parseBody, async (req, res) => {
|
|
254145
|
+
const { email: email3, password } = LoginBody.parse(req.body);
|
|
254146
|
+
if ((password || "").length < 8) {
|
|
254147
|
+
res.status(400).json({
|
|
254148
|
+
detail: "Password must be at least 8 characters long",
|
|
254149
|
+
error_type: "HTTPException",
|
|
254150
|
+
message: "Password must be at least 8 characters long",
|
|
254151
|
+
request_id: null,
|
|
254152
|
+
traceback: ""
|
|
254153
|
+
});
|
|
254154
|
+
return;
|
|
254155
|
+
}
|
|
254156
|
+
const result = await db2.getCollection(USER_COLLECTION)?.findOneAsync({ email: email3 });
|
|
254157
|
+
if (result) {
|
|
254158
|
+
res.status(400).json({
|
|
254159
|
+
detail: "A user with this email already exists",
|
|
254160
|
+
error_type: "HTTPException",
|
|
254161
|
+
message: "A user with this email already exists",
|
|
254162
|
+
request_id: null,
|
|
254163
|
+
traceback: ""
|
|
254164
|
+
});
|
|
254165
|
+
return;
|
|
254166
|
+
}
|
|
254167
|
+
const privateUserCollection = db2.getCollection(PRIVATE_USER_COLLECTION);
|
|
254168
|
+
const privateUserData = await privateUserCollection?.findOneAsync({
|
|
254169
|
+
email: email3
|
|
254170
|
+
});
|
|
254171
|
+
const otpCode = generateCode();
|
|
254172
|
+
const id2 = privateUserData ? privateUserData.id : nanoid3();
|
|
254173
|
+
if (!privateUserData) {
|
|
254174
|
+
await privateUserCollection?.insertAsync({
|
|
254175
|
+
id: id2,
|
|
254176
|
+
email: email3,
|
|
254177
|
+
otpCode,
|
|
254178
|
+
password,
|
|
254179
|
+
createdAt: Date.now()
|
|
254180
|
+
});
|
|
254181
|
+
} else {
|
|
254182
|
+
await privateUserCollection?.updateAsync({
|
|
254183
|
+
email: email3
|
|
254184
|
+
}, {
|
|
254185
|
+
$set: {
|
|
254186
|
+
otpCode,
|
|
254187
|
+
createdAt: Date.now()
|
|
254188
|
+
}
|
|
254189
|
+
});
|
|
254190
|
+
}
|
|
254191
|
+
logger2.log(theme.styles.info(`
|
|
254192
|
+
In order to complete registration use this verification code: ${otpCode}
|
|
254193
|
+
`));
|
|
254194
|
+
res.json({
|
|
254195
|
+
id: id2,
|
|
254196
|
+
message: "Registration successful. Please check your email for the verification code.",
|
|
254197
|
+
otp_expires_in_minutes: 10
|
|
254198
|
+
});
|
|
254199
|
+
});
|
|
254200
|
+
router.post("/verify-otp", parseBody, async (req, res) => {
|
|
254201
|
+
const { email: email3, otp_code } = VerifyOtpBody.parse(req.body);
|
|
254202
|
+
const privateUserCollection = db2.getCollection(PRIVATE_USER_COLLECTION);
|
|
254203
|
+
const privateUserData = await privateUserCollection?.findOneAsync({
|
|
254204
|
+
email: email3
|
|
254205
|
+
});
|
|
254206
|
+
if (!privateUserData || privateUserData.otpCode !== otp_code) {
|
|
254207
|
+
const appId = req.params.appId;
|
|
254208
|
+
res.status(500).json({
|
|
254209
|
+
detail: `{'email': '${email3}', 'app_id': '${appId}}'} -> Object not found`,
|
|
254210
|
+
error_type: "ObjectNotFoundError",
|
|
254211
|
+
message: `{'email': '${email3}', 'app_id': '${appId}}'} -> Object not found`,
|
|
254212
|
+
request_id: null,
|
|
254213
|
+
traceback: ""
|
|
254214
|
+
});
|
|
254215
|
+
return;
|
|
254216
|
+
}
|
|
254217
|
+
if (+Date.now() - privateUserData.createdAt > TEN_MINUTES) {
|
|
254218
|
+
res.status(400).json({
|
|
254219
|
+
detail: "Verification code has expired",
|
|
254220
|
+
error_type: "HTTPException",
|
|
254221
|
+
message: "Verification code has expired",
|
|
254222
|
+
request_id: null,
|
|
254223
|
+
traceback: ""
|
|
254224
|
+
});
|
|
254225
|
+
} else {
|
|
254226
|
+
await privateUserCollection?.updateAsync({
|
|
254227
|
+
email: email3
|
|
254228
|
+
}, {
|
|
254229
|
+
$unset: { otpCode: true }
|
|
254230
|
+
});
|
|
254231
|
+
const collection = db2.getCollection(USER_COLLECTION);
|
|
254232
|
+
const now = getNowISOTimestamp();
|
|
254233
|
+
const nameFromEmailMatch = /^([^@]+)/.exec(email3);
|
|
254234
|
+
const fullName = nameFromEmailMatch ? nameFromEmailMatch[1] : email3;
|
|
254235
|
+
await collection?.insertAsync({
|
|
254236
|
+
id: privateUserData.id,
|
|
254237
|
+
email: email3,
|
|
254238
|
+
full_name: fullName,
|
|
254239
|
+
is_service: false,
|
|
254240
|
+
is_verified: true,
|
|
254241
|
+
disabled: null,
|
|
254242
|
+
role: "user",
|
|
254243
|
+
collaborator_role: "editor",
|
|
254244
|
+
created_date: now,
|
|
254245
|
+
updated_date: now
|
|
254246
|
+
});
|
|
254247
|
+
res.json({
|
|
254248
|
+
id: privateUserData.id,
|
|
254249
|
+
access_token: createJwtToken(email3),
|
|
254250
|
+
message: "Email verified successfully. You are now logged in.",
|
|
254251
|
+
success: true
|
|
254252
|
+
});
|
|
254253
|
+
}
|
|
254254
|
+
});
|
|
254255
|
+
return router;
|
|
254256
|
+
}
|
|
254257
|
+
|
|
254258
|
+
// src/cli/dev/dev-server/routes/entities/entities-router.ts
|
|
254259
|
+
var import_express4 = __toESM(require_express(), 1);
|
|
254260
|
+
|
|
254261
|
+
// src/cli/dev/dev-server/db/entity-queries.ts
|
|
254262
|
+
function parseSort(sort) {
|
|
254263
|
+
if (!sort) {
|
|
254264
|
+
return;
|
|
254265
|
+
}
|
|
254266
|
+
if (sort.startsWith("-")) {
|
|
254267
|
+
return { [sort.slice(1)]: -1 };
|
|
254268
|
+
}
|
|
254269
|
+
return { [sort]: 1 };
|
|
254270
|
+
}
|
|
254271
|
+
function parseFields(fields) {
|
|
254272
|
+
if (!fields) {
|
|
254273
|
+
return;
|
|
254274
|
+
}
|
|
254275
|
+
const projection = {};
|
|
254276
|
+
for (const field of fields.split(",")) {
|
|
254277
|
+
const trimmed = field.trim();
|
|
254278
|
+
if (trimmed) {
|
|
254279
|
+
projection[trimmed] = 1;
|
|
254280
|
+
}
|
|
254281
|
+
}
|
|
254282
|
+
return Object.keys(projection).length > 0 ? projection : undefined;
|
|
254283
|
+
}
|
|
254284
|
+
var queryEntity = async (collection, reqQuery) => {
|
|
254285
|
+
const { sort, limit, skip: skip2, fields, q: q13 } = reqQuery;
|
|
254286
|
+
let query = {};
|
|
254287
|
+
if (q13 && typeof q13 === "string") {
|
|
254288
|
+
try {
|
|
254289
|
+
query = JSON.parse(q13);
|
|
254290
|
+
} catch {
|
|
254291
|
+
throw new InvalidInputError("Invalid query parameter 'q'");
|
|
254292
|
+
}
|
|
254293
|
+
}
|
|
254294
|
+
let cursor3 = collection.findAsync(query);
|
|
254295
|
+
const sortObj = parseSort(sort);
|
|
254296
|
+
if (sortObj) {
|
|
254297
|
+
cursor3 = cursor3.sort(sortObj);
|
|
254298
|
+
}
|
|
254299
|
+
if (skip2) {
|
|
254300
|
+
const skipNum = Number.parseInt(skip2, 10);
|
|
254301
|
+
if (!Number.isNaN(skipNum)) {
|
|
254302
|
+
cursor3 = cursor3.skip(skipNum);
|
|
254303
|
+
}
|
|
254304
|
+
}
|
|
254305
|
+
if (limit) {
|
|
254306
|
+
const limitNum = Number.parseInt(limit, 10);
|
|
254307
|
+
if (!Number.isNaN(limitNum)) {
|
|
254308
|
+
cursor3 = cursor3.limit(limitNum);
|
|
254309
|
+
}
|
|
254310
|
+
}
|
|
254311
|
+
const projection = parseFields(fields);
|
|
254312
|
+
if (projection) {
|
|
254313
|
+
cursor3 = cursor3.projection(projection);
|
|
254314
|
+
}
|
|
254315
|
+
return cursor3;
|
|
254316
|
+
};
|
|
254317
|
+
|
|
254318
|
+
// src/cli/dev/dev-server/routes/entities/entities-user-router.ts
|
|
254319
|
+
var import_express3 = __toESM(require_express(), 1);
|
|
254320
|
+
var import_jsonwebtoken2 = __toESM(require_jsonwebtoken(), 1);
|
|
254321
|
+
function createUserRouter(db2, logger2) {
|
|
254322
|
+
const router = import_express3.Router({ mergeParams: true });
|
|
254323
|
+
const parseBody = import_express3.json();
|
|
254072
254324
|
function withAuth(handler) {
|
|
254073
254325
|
return async (req, res) => {
|
|
254074
254326
|
const auth2 = req.headers.authorization;
|
|
@@ -254077,7 +254329,7 @@ function createUserRouter(db2, logger2) {
|
|
|
254077
254329
|
return;
|
|
254078
254330
|
}
|
|
254079
254331
|
try {
|
|
254080
|
-
const { payload } =
|
|
254332
|
+
const { payload } = import_jsonwebtoken2.default.decode(auth2.replace("Bearer ", ""), { complete: true }) ?? {};
|
|
254081
254333
|
const result = await db2.getCollection(USER_COLLECTION)?.findOneAsync({ email: payload?.sub });
|
|
254082
254334
|
if (!result) {
|
|
254083
254335
|
res.status(404).json({ error: "Unable to read data for the current user" });
|
|
@@ -254110,6 +254362,28 @@ function createUserRouter(db2, logger2) {
|
|
|
254110
254362
|
...req.body
|
|
254111
254363
|
});
|
|
254112
254364
|
}));
|
|
254365
|
+
router.get("/", withAuth(async (req, res, currentUser) => {
|
|
254366
|
+
const collection = db2.getCollection(USER_COLLECTION);
|
|
254367
|
+
if (!collection) {
|
|
254368
|
+
res.status(404).json({ error: `Entity "${USER_COLLECTION}" not found` });
|
|
254369
|
+
return;
|
|
254370
|
+
}
|
|
254371
|
+
try {
|
|
254372
|
+
if (currentUser.role === "admin") {
|
|
254373
|
+
const result = await queryEntity(collection, req.query);
|
|
254374
|
+
res.json(stripInternalFields(result));
|
|
254375
|
+
} else {
|
|
254376
|
+
res.json([stripInternalFields(currentUser)]);
|
|
254377
|
+
}
|
|
254378
|
+
} catch (error48) {
|
|
254379
|
+
if (error48 instanceof InvalidInputError) {
|
|
254380
|
+
res.status(400).json({ error: error48.message });
|
|
254381
|
+
} else {
|
|
254382
|
+
logger2.error(`Error in GET /${USER_COLLECTION}:`, error48);
|
|
254383
|
+
res.status(500).json({ error: "Internal server error" });
|
|
254384
|
+
}
|
|
254385
|
+
}
|
|
254386
|
+
}));
|
|
254113
254387
|
router.post("/bulk", async (_req, res) => {
|
|
254114
254388
|
res.json({});
|
|
254115
254389
|
});
|
|
@@ -254159,31 +254433,9 @@ function createUserRouter(db2, logger2) {
|
|
|
254159
254433
|
}
|
|
254160
254434
|
|
|
254161
254435
|
// src/cli/dev/dev-server/routes/entities/entities-router.ts
|
|
254162
|
-
function parseSort(sort) {
|
|
254163
|
-
if (!sort) {
|
|
254164
|
-
return;
|
|
254165
|
-
}
|
|
254166
|
-
if (sort.startsWith("-")) {
|
|
254167
|
-
return { [sort.slice(1)]: -1 };
|
|
254168
|
-
}
|
|
254169
|
-
return { [sort]: 1 };
|
|
254170
|
-
}
|
|
254171
|
-
function parseFields(fields) {
|
|
254172
|
-
if (!fields) {
|
|
254173
|
-
return;
|
|
254174
|
-
}
|
|
254175
|
-
const projection = {};
|
|
254176
|
-
for (const field of fields.split(",")) {
|
|
254177
|
-
const trimmed = field.trim();
|
|
254178
|
-
if (trimmed) {
|
|
254179
|
-
projection[trimmed] = 1;
|
|
254180
|
-
}
|
|
254181
|
-
}
|
|
254182
|
-
return Object.keys(projection).length > 0 ? projection : undefined;
|
|
254183
|
-
}
|
|
254184
254436
|
async function createEntityRoutes(db2, logger2, broadcast) {
|
|
254185
|
-
const router =
|
|
254186
|
-
const parseBody =
|
|
254437
|
+
const router = import_express4.Router({ mergeParams: true });
|
|
254438
|
+
const parseBody = import_express4.json();
|
|
254187
254439
|
function withCollection(handler) {
|
|
254188
254440
|
return async (req, res) => {
|
|
254189
254441
|
const collection = db2.getCollection(req.params.entityName);
|
|
@@ -254228,42 +254480,14 @@ async function createEntityRoutes(db2, logger2, broadcast) {
|
|
|
254228
254480
|
router.get("/:entityName", withCollection(async (req, res, collection) => {
|
|
254229
254481
|
const { entityName } = req.params;
|
|
254230
254482
|
try {
|
|
254231
|
-
|
|
254232
|
-
let query = {};
|
|
254233
|
-
if (q13 && typeof q13 === "string") {
|
|
254234
|
-
try {
|
|
254235
|
-
query = JSON.parse(q13);
|
|
254236
|
-
} catch {
|
|
254237
|
-
res.status(400).json({ error: "Invalid query parameter 'q'" });
|
|
254238
|
-
return;
|
|
254239
|
-
}
|
|
254240
|
-
}
|
|
254241
|
-
let cursor3 = collection.findAsync(query);
|
|
254242
|
-
const sortObj = parseSort(sort);
|
|
254243
|
-
if (sortObj) {
|
|
254244
|
-
cursor3 = cursor3.sort(sortObj);
|
|
254245
|
-
}
|
|
254246
|
-
if (skip2) {
|
|
254247
|
-
const skipNum = Number.parseInt(skip2, 10);
|
|
254248
|
-
if (!Number.isNaN(skipNum)) {
|
|
254249
|
-
cursor3 = cursor3.skip(skipNum);
|
|
254250
|
-
}
|
|
254251
|
-
}
|
|
254252
|
-
if (limit) {
|
|
254253
|
-
const limitNum = Number.parseInt(limit, 10);
|
|
254254
|
-
if (!Number.isNaN(limitNum)) {
|
|
254255
|
-
cursor3 = cursor3.limit(limitNum);
|
|
254256
|
-
}
|
|
254257
|
-
}
|
|
254258
|
-
const projection = parseFields(fields);
|
|
254259
|
-
if (projection) {
|
|
254260
|
-
cursor3 = cursor3.projection(projection);
|
|
254261
|
-
}
|
|
254262
|
-
const docs = await cursor3;
|
|
254263
|
-
res.json(stripInternalFields(docs));
|
|
254483
|
+
res.json(stripInternalFields(await queryEntity(collection, req.query)));
|
|
254264
254484
|
} catch (error48) {
|
|
254265
|
-
|
|
254266
|
-
|
|
254485
|
+
if (error48 instanceof InvalidInputError) {
|
|
254486
|
+
res.status(400).json({ error: error48.message });
|
|
254487
|
+
} else {
|
|
254488
|
+
logger2.error(`Error in GET /${entityName}:`, error48);
|
|
254489
|
+
res.status(500).json({ error: "Internal server error" });
|
|
254490
|
+
}
|
|
254267
254491
|
}
|
|
254268
254492
|
}));
|
|
254269
254493
|
router.post("/:entityName", parseBody, withCollection(async (req, res, collection) => {
|
|
@@ -254382,7 +254606,7 @@ async function createEntityRoutes(db2, logger2, broadcast) {
|
|
|
254382
254606
|
}
|
|
254383
254607
|
|
|
254384
254608
|
// src/cli/dev/dev-server/routes/integrations.ts
|
|
254385
|
-
var
|
|
254609
|
+
var import_express5 = __toESM(require_express(), 1);
|
|
254386
254610
|
var import_multer = __toESM(require_multer(), 1);
|
|
254387
254611
|
import { createHash, randomUUID as randomUUID4 } from "node:crypto";
|
|
254388
254612
|
import fs28 from "node:fs";
|
|
@@ -254391,8 +254615,8 @@ function createFileToken(fileUri) {
|
|
|
254391
254615
|
return createHash("sha256").update(fileUri).digest("hex");
|
|
254392
254616
|
}
|
|
254393
254617
|
function createIntegrationRoutes(mediaFilesDir, baseUrl, remoteProxy, logger2) {
|
|
254394
|
-
const router =
|
|
254395
|
-
const parseBody =
|
|
254618
|
+
const router = import_express5.Router({ mergeParams: true });
|
|
254619
|
+
const parseBody = import_express5.json();
|
|
254396
254620
|
const privateFilesDir = path18.join(mediaFilesDir, "private");
|
|
254397
254621
|
fs28.mkdirSync(mediaFilesDir, { recursive: true });
|
|
254398
254622
|
fs28.mkdirSync(privateFilesDir, { recursive: true });
|
|
@@ -254462,7 +254686,7 @@ function createIntegrationRoutes(mediaFilesDir, baseUrl, remoteProxy, logger2) {
|
|
|
254462
254686
|
return router;
|
|
254463
254687
|
}
|
|
254464
254688
|
function createCustomIntegrationRoutes(remoteProxy, logger2) {
|
|
254465
|
-
const router =
|
|
254689
|
+
const router = import_express5.Router({ mergeParams: true });
|
|
254466
254690
|
router.post("/:slug/:operationId", (req, res, next) => {
|
|
254467
254691
|
logger2.warn(`"${req.originalUrl}" is not supported in local development, passing call to production`);
|
|
254468
254692
|
req.url = req.originalUrl;
|
|
@@ -256175,7 +256399,7 @@ async function createDevServer(options8) {
|
|
|
256175
256399
|
const port = userPort ?? await getPorts({ port: DEFAULT_PORT });
|
|
256176
256400
|
const baseUrl = `http://localhost:${port}`;
|
|
256177
256401
|
const { functions, entities, project: project2 } = await options8.loadResources();
|
|
256178
|
-
const app =
|
|
256402
|
+
const app = import_express6.default();
|
|
256179
256403
|
const remoteProxy = import_http_proxy_middleware2.createProxyMiddleware({
|
|
256180
256404
|
target: BASE44_APP_URL,
|
|
256181
256405
|
changeOrigin: true
|
|
@@ -256207,6 +256431,8 @@ async function createDevServer(options8) {
|
|
|
256207
256431
|
let emitEntityEvent = () => {};
|
|
256208
256432
|
const entityRoutes = await createEntityRoutes(db2, devLogger, (...args) => emitEntityEvent(...args));
|
|
256209
256433
|
app.use("/api/apps/:appId/entities", entityRoutes);
|
|
256434
|
+
const authRouter = createAuthRouter(db2, devLogger);
|
|
256435
|
+
app.use("/api/apps/:appId/auth", authRouter);
|
|
256210
256436
|
const { path: mediaFilesDir } = await $dir();
|
|
256211
256437
|
app.use("/media/private/:fileUri", (req, res, next) => {
|
|
256212
256438
|
const { fileUri } = req.params;
|
|
@@ -256226,13 +256452,15 @@ async function createDevServer(options8) {
|
|
|
256226
256452
|
}
|
|
256227
256453
|
next();
|
|
256228
256454
|
});
|
|
256229
|
-
app.use("/media",
|
|
256455
|
+
app.use("/media", import_express6.default.static(mediaFilesDir));
|
|
256230
256456
|
const integrationRoutes = createIntegrationRoutes(mediaFilesDir, baseUrl, remoteProxy, devLogger);
|
|
256231
256457
|
app.use("/api/apps/:appId/integration-endpoints", integrationRoutes);
|
|
256232
256458
|
const customIntegrationRoutes = createCustomIntegrationRoutes(remoteProxy, devLogger);
|
|
256233
256459
|
app.use("/api/apps/:appId/integrations/custom", customIntegrationRoutes);
|
|
256234
256460
|
app.use((req, res, next) => {
|
|
256235
|
-
|
|
256461
|
+
if (!req.originalUrl.endsWith("analytics/track/batch")) {
|
|
256462
|
+
devLogger.warn(`"${req.originalUrl}" is not supported in local development, passing call to production`);
|
|
256463
|
+
}
|
|
256236
256464
|
remoteProxy(req, res, next);
|
|
256237
256465
|
});
|
|
256238
256466
|
const server = await new Promise((resolve10, reject) => {
|
|
@@ -256303,6 +256531,7 @@ async function devAction({ log }, options8) {
|
|
|
256303
256531
|
const { port: resolvedPort } = await createDevServer({
|
|
256304
256532
|
log,
|
|
256305
256533
|
port,
|
|
256534
|
+
cwd: process21.cwd(),
|
|
256306
256535
|
denoWrapperPath: getDenoWrapperPath(),
|
|
256307
256536
|
loadResources: async () => {
|
|
256308
256537
|
const { functions, entities, project: project2 } = await readProjectConfig();
|
|
@@ -260779,4 +261008,4 @@ export {
|
|
|
260779
261008
|
CLIExitError
|
|
260780
261009
|
};
|
|
260781
261010
|
|
|
260782
|
-
//# debugId=
|
|
261011
|
+
//# debugId=939FB46B90B442D864756E2164756E21
|