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