firebase-tools 13.33.0 → 13.35.0
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/lib/apphosting/config.js +8 -6
- package/lib/apphosting/yaml.js +21 -48
- package/lib/commands/dataconnect-sdk-generate.js +4 -1
- package/lib/commands/dataconnect-sql-diff.js +1 -1
- package/lib/commands/dataconnect-sql-grant.js +2 -2
- package/lib/commands/dataconnect-sql-setup.js +40 -0
- package/lib/commands/functions-artifacts-setpolicy.js +125 -0
- package/lib/commands/index.js +3 -0
- package/lib/commands/open.js +3 -0
- package/lib/dataconnect/build.js +3 -1
- package/lib/dataconnect/fileUtils.js +8 -4
- package/lib/dataconnect/schemaMigration.js +38 -12
- package/lib/defaultCredentials.js +12 -1
- package/lib/deploy/dataconnect/prepare.js +1 -1
- package/lib/deploy/functions/containerCleaner.js +17 -2
- package/lib/deploy/functions/runtimes/discovery/index.js +3 -1
- package/lib/deploy/index.js +22 -20
- package/lib/emulator/ExpressBasedEmulator.js +1 -1
- package/lib/emulator/apphosting/index.js +1 -0
- package/lib/emulator/apphosting/serve.js +48 -7
- package/lib/emulator/controller.js +1 -0
- package/lib/emulator/dataconnect/pgliteServer.js +7 -2
- package/lib/emulator/dataconnectEmulator.js +15 -4
- package/lib/emulator/downloadableEmulators.js +9 -9
- package/lib/emulator/env.js +17 -1
- package/lib/emulator/functionsEmulator.js +2 -20
- package/lib/extensions/extensionsHelper.js +8 -4
- package/lib/frameworks/angular/utils.js +60 -42
- package/lib/functions/artifacts.js +104 -0
- package/lib/gcp/artifactregistry.js +27 -2
- package/lib/gcp/cloudsql/cloudsqladmin.js +22 -1
- package/lib/gcp/cloudsql/connect.js +21 -14
- package/lib/gcp/cloudsql/permissions.js +45 -99
- package/lib/gcp/cloudsql/permissions_setup.js +215 -0
- package/lib/init/features/dataconnect/index.js +1 -1
- package/lib/init/features/dataconnect/sdk.js +23 -3
- package/package.json +1 -1
- package/templates/init/dataconnect/connector.yaml +1 -1
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.hasCleanupOptOut = exports.hasSameCleanupPolicy = exports.setCleanupPolicy = exports.optOutRepository = exports.updateRepository = exports.generateCleanupPolicy = exports.parseDaysFromPolicy = exports.daysToSeconds = exports.findExistingPolicy = exports.makeRepoPath = exports.OPT_OUT_LABEL_KEY = exports.CLEANUP_POLICY_ID = exports.GCF_REPO_ID = void 0;
|
|
4
|
+
const artifactregistry = require("../gcp/artifactregistry");
|
|
5
|
+
const error_1 = require("../error");
|
|
6
|
+
exports.GCF_REPO_ID = "gcf-artifacts";
|
|
7
|
+
exports.CLEANUP_POLICY_ID = "firebase-functions-cleanup";
|
|
8
|
+
exports.OPT_OUT_LABEL_KEY = "firebase-functions-cleanup-opted-out";
|
|
9
|
+
const SECONDS_IN_DAY = 24 * 60 * 60;
|
|
10
|
+
function makeRepoPath(projectId, location, repoName = exports.GCF_REPO_ID) {
|
|
11
|
+
return `projects/${projectId}/locations/${location}/repositories/${repoName}`;
|
|
12
|
+
}
|
|
13
|
+
exports.makeRepoPath = makeRepoPath;
|
|
14
|
+
function findExistingPolicy(repository) {
|
|
15
|
+
var _a;
|
|
16
|
+
return (_a = repository === null || repository === void 0 ? void 0 : repository.cleanupPolicies) === null || _a === void 0 ? void 0 : _a[exports.CLEANUP_POLICY_ID];
|
|
17
|
+
}
|
|
18
|
+
exports.findExistingPolicy = findExistingPolicy;
|
|
19
|
+
function daysToSeconds(days) {
|
|
20
|
+
const seconds = days * SECONDS_IN_DAY;
|
|
21
|
+
return `${seconds}s`;
|
|
22
|
+
}
|
|
23
|
+
exports.daysToSeconds = daysToSeconds;
|
|
24
|
+
function parseDaysFromPolicy(olderThan) {
|
|
25
|
+
const match = olderThan.match(/^(\d+)s$/);
|
|
26
|
+
if (match && match[1]) {
|
|
27
|
+
const seconds = parseInt(match[1], 10);
|
|
28
|
+
return Math.floor(seconds / SECONDS_IN_DAY);
|
|
29
|
+
}
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
exports.parseDaysFromPolicy = parseDaysFromPolicy;
|
|
33
|
+
function generateCleanupPolicy(daysToKeep) {
|
|
34
|
+
return {
|
|
35
|
+
[exports.CLEANUP_POLICY_ID]: {
|
|
36
|
+
id: exports.CLEANUP_POLICY_ID,
|
|
37
|
+
condition: {
|
|
38
|
+
tagState: "ANY",
|
|
39
|
+
olderThan: daysToSeconds(daysToKeep),
|
|
40
|
+
},
|
|
41
|
+
action: "DELETE",
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
exports.generateCleanupPolicy = generateCleanupPolicy;
|
|
46
|
+
async function updateRepository(repo) {
|
|
47
|
+
try {
|
|
48
|
+
await artifactregistry.updateRepository(repo);
|
|
49
|
+
}
|
|
50
|
+
catch (err) {
|
|
51
|
+
if (err.status === 403) {
|
|
52
|
+
throw new error_1.FirebaseError(`You don't have permission to update this repository.\n` +
|
|
53
|
+
`To update repository settings, ask your administrator to grant you the ` +
|
|
54
|
+
`Artifact Registry Administrator (roles/artifactregistry.admin) IAM role on the repository project.`, { original: err, exit: 1 });
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
throw new error_1.FirebaseError("Failed to update artifact registry repository", {
|
|
58
|
+
original: err,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
exports.updateRepository = updateRepository;
|
|
64
|
+
async function optOutRepository(repository) {
|
|
65
|
+
const policies = Object.assign({}, repository.cleanupPolicies);
|
|
66
|
+
if (exports.CLEANUP_POLICY_ID in policies) {
|
|
67
|
+
delete policies[exports.CLEANUP_POLICY_ID];
|
|
68
|
+
}
|
|
69
|
+
const update = {
|
|
70
|
+
name: repository.name,
|
|
71
|
+
labels: Object.assign(Object.assign({}, repository.labels), { [exports.OPT_OUT_LABEL_KEY]: "true" }),
|
|
72
|
+
cleanupPolicies: policies,
|
|
73
|
+
};
|
|
74
|
+
await exports.updateRepository(update);
|
|
75
|
+
}
|
|
76
|
+
exports.optOutRepository = optOutRepository;
|
|
77
|
+
async function setCleanupPolicy(repository, daysToKeep) {
|
|
78
|
+
const labels = Object.assign({}, repository.labels);
|
|
79
|
+
delete labels[exports.OPT_OUT_LABEL_KEY];
|
|
80
|
+
const update = {
|
|
81
|
+
name: repository.name,
|
|
82
|
+
cleanupPolicies: Object.assign(Object.assign({}, repository.cleanupPolicies), generateCleanupPolicy(daysToKeep)),
|
|
83
|
+
labels,
|
|
84
|
+
};
|
|
85
|
+
await exports.updateRepository(update);
|
|
86
|
+
}
|
|
87
|
+
exports.setCleanupPolicy = setCleanupPolicy;
|
|
88
|
+
function hasSameCleanupPolicy(repository, daysToKeep) {
|
|
89
|
+
var _a, _b;
|
|
90
|
+
const existingPolicy = findExistingPolicy(repository);
|
|
91
|
+
if (!existingPolicy) {
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
if (((_a = existingPolicy.condition) === null || _a === void 0 ? void 0 : _a.tagState) !== "ANY" || !((_b = existingPolicy.condition) === null || _b === void 0 ? void 0 : _b.olderThan)) {
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
const existingSeconds = parseDaysFromPolicy(existingPolicy.condition.olderThan);
|
|
98
|
+
return existingSeconds === daysToKeep;
|
|
99
|
+
}
|
|
100
|
+
exports.hasSameCleanupPolicy = hasSameCleanupPolicy;
|
|
101
|
+
function hasCleanupOptOut(repo) {
|
|
102
|
+
return !!(repo.labels && repo.labels[exports.OPT_OUT_LABEL_KEY] === "true");
|
|
103
|
+
}
|
|
104
|
+
exports.hasCleanupOptOut = hasCleanupOptOut;
|
|
@@ -1,16 +1,41 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.deletePackage = exports.API_VERSION = void 0;
|
|
3
|
+
exports.updateRepository = exports.getRepository = exports.deletePackage = exports.ensureApiEnabled = exports.API_VERSION = void 0;
|
|
4
4
|
const apiv2_1 = require("../apiv2");
|
|
5
5
|
const api_1 = require("../api");
|
|
6
|
-
|
|
6
|
+
const metaprogramming_1 = require("../metaprogramming");
|
|
7
|
+
const api = require("../ensureApiEnabled");
|
|
8
|
+
const proto = require("./proto");
|
|
9
|
+
exports.API_VERSION = "v1";
|
|
7
10
|
const client = new apiv2_1.Client({
|
|
8
11
|
urlPrefix: (0, api_1.artifactRegistryDomain)(),
|
|
9
12
|
auth: true,
|
|
10
13
|
apiVersion: exports.API_VERSION,
|
|
11
14
|
});
|
|
15
|
+
function ensureApiEnabled(projectId) {
|
|
16
|
+
return api.ensure(projectId, (0, api_1.artifactRegistryDomain)(), "artifactregistry", true);
|
|
17
|
+
}
|
|
18
|
+
exports.ensureApiEnabled = ensureApiEnabled;
|
|
19
|
+
(0, metaprogramming_1.assertImplements)();
|
|
12
20
|
async function deletePackage(name) {
|
|
13
21
|
const res = await client.delete(name);
|
|
14
22
|
return res.body;
|
|
15
23
|
}
|
|
16
24
|
exports.deletePackage = deletePackage;
|
|
25
|
+
async function getRepository(repoPath) {
|
|
26
|
+
const res = await client.get(repoPath);
|
|
27
|
+
return res.body;
|
|
28
|
+
}
|
|
29
|
+
exports.getRepository = getRepository;
|
|
30
|
+
async function updateRepository(repo) {
|
|
31
|
+
const updateMask = proto.fieldMasks(repo, "cleanupPolicies", "labels");
|
|
32
|
+
if (updateMask.length === 0) {
|
|
33
|
+
const res = await client.get(repo.name);
|
|
34
|
+
return res.body;
|
|
35
|
+
}
|
|
36
|
+
const res = await client.patch(`/${repo.name}`, repo, {
|
|
37
|
+
queryParams: { updateMask: updateMask.join(",") },
|
|
38
|
+
});
|
|
39
|
+
return res.body;
|
|
40
|
+
}
|
|
41
|
+
exports.updateRepository = updateRepository;
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.listUsers = exports.deleteUser = exports.getUser = exports.createUser = exports.deleteDatabase = exports.createDatabase = exports.getDatabase = exports.listDatabases = exports.updateInstanceForDataConnect = exports.createInstance = exports.instanceConsoleLink = exports.getInstance = exports.listInstances = void 0;
|
|
3
|
+
exports.listUsers = exports.deleteUser = exports.getUser = exports.createUser = exports.deleteDatabase = exports.createDatabase = exports.getDatabase = exports.listDatabases = exports.updateInstanceForDataConnect = exports.createInstance = exports.instanceConsoleLink = exports.getInstance = exports.listInstances = exports.iamUserIsCSQLAdmin = void 0;
|
|
4
4
|
const apiv2_1 = require("../../apiv2");
|
|
5
5
|
const api_1 = require("../../api");
|
|
6
6
|
const operationPoller = require("../../operation-poller");
|
|
7
|
+
const projectUtils_1 = require("../../projectUtils");
|
|
8
|
+
const logger_1 = require("../../logger");
|
|
9
|
+
const iam_1 = require("../iam");
|
|
7
10
|
const error_1 = require("../../error");
|
|
8
11
|
const API_VERSION = "v1";
|
|
9
12
|
const client = new apiv2_1.Client({
|
|
@@ -11,6 +14,24 @@ const client = new apiv2_1.Client({
|
|
|
11
14
|
auth: true,
|
|
12
15
|
apiVersion: API_VERSION,
|
|
13
16
|
});
|
|
17
|
+
async function iamUserIsCSQLAdmin(options) {
|
|
18
|
+
const projectId = (0, projectUtils_1.needProjectId)(options);
|
|
19
|
+
const requiredPermissions = [
|
|
20
|
+
"cloudsql.instances.connect",
|
|
21
|
+
"cloudsql.instances.get",
|
|
22
|
+
"cloudsql.users.create",
|
|
23
|
+
"cloudsql.users.update",
|
|
24
|
+
];
|
|
25
|
+
try {
|
|
26
|
+
const iamResult = await (0, iam_1.testIamPermissions)(projectId, requiredPermissions);
|
|
27
|
+
return iamResult.passed;
|
|
28
|
+
}
|
|
29
|
+
catch (err) {
|
|
30
|
+
logger_1.logger.debug(`[iam] error while checking permissions, command may fail: ${err}`);
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
exports.iamUserIsCSQLAdmin = iamUserIsCSQLAdmin;
|
|
14
35
|
async function listInstances(projectId) {
|
|
15
36
|
var _a;
|
|
16
37
|
const res = await client.get(`projects/${projectId}/instances`);
|
|
@@ -11,7 +11,6 @@ const utils = require("../../utils");
|
|
|
11
11
|
const logger_1 = require("../../logger");
|
|
12
12
|
const error_1 = require("../../error");
|
|
13
13
|
const fbToolsAuthClient_1 = require("./fbToolsAuthClient");
|
|
14
|
-
const permissions_1 = require("./permissions");
|
|
15
14
|
async function execute(sqlStatements, opts) {
|
|
16
15
|
const logFn = opts.silent ? logger_1.logger.debug : logger_1.logger.info;
|
|
17
16
|
const instance = await cloudSqlAdminClient.getInstance(opts.projectId, opts.instanceId);
|
|
@@ -60,23 +59,35 @@ async function execute(sqlStatements, opts) {
|
|
|
60
59
|
break;
|
|
61
60
|
}
|
|
62
61
|
}
|
|
62
|
+
const cleanUpFn = async () => {
|
|
63
|
+
conn.release();
|
|
64
|
+
await pool.end();
|
|
65
|
+
connector.close();
|
|
66
|
+
};
|
|
63
67
|
const conn = await pool.connect();
|
|
68
|
+
const results = [];
|
|
64
69
|
logFn(`Logged in as ${opts.username}`);
|
|
70
|
+
if (opts.transaction) {
|
|
71
|
+
sqlStatements.unshift("BEGIN;");
|
|
72
|
+
sqlStatements.push("COMMIT;");
|
|
73
|
+
}
|
|
65
74
|
for (const s of sqlStatements) {
|
|
66
75
|
logFn(`Executing: '${s}'`);
|
|
67
76
|
try {
|
|
68
|
-
await conn.query(s);
|
|
77
|
+
results.push(await conn.query(s));
|
|
69
78
|
}
|
|
70
79
|
catch (err) {
|
|
80
|
+
logFn(`Rolling back transaction due to error ${err}}`);
|
|
81
|
+
await conn.query("ROLLBACK;");
|
|
82
|
+
await cleanUpFn();
|
|
71
83
|
throw new error_1.FirebaseError(`Error executing ${err}`);
|
|
72
84
|
}
|
|
73
85
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
connector.close();
|
|
86
|
+
await cleanUpFn();
|
|
87
|
+
return results;
|
|
77
88
|
}
|
|
78
89
|
exports.execute = execute;
|
|
79
|
-
async function executeSqlCmdsAsIamUser(options, instanceId, databaseId, cmds, silent = false) {
|
|
90
|
+
async function executeSqlCmdsAsIamUser(options, instanceId, databaseId, cmds, silent = false, transaction = false) {
|
|
80
91
|
const projectId = (0, projectUtils_1.needProjectId)(options);
|
|
81
92
|
const { user: iamUser } = await getIAMUser(options);
|
|
82
93
|
return await execute(cmds, {
|
|
@@ -85,21 +96,23 @@ async function executeSqlCmdsAsIamUser(options, instanceId, databaseId, cmds, si
|
|
|
85
96
|
databaseId,
|
|
86
97
|
username: iamUser,
|
|
87
98
|
silent: silent,
|
|
99
|
+
transaction: transaction,
|
|
88
100
|
});
|
|
89
101
|
}
|
|
90
102
|
exports.executeSqlCmdsAsIamUser = executeSqlCmdsAsIamUser;
|
|
91
|
-
async function executeSqlCmdsAsSuperUser(options, instanceId, databaseId, cmds, silent = false) {
|
|
103
|
+
async function executeSqlCmdsAsSuperUser(options, instanceId, databaseId, cmds, silent = false, transaction = false) {
|
|
92
104
|
const projectId = (0, projectUtils_1.needProjectId)(options);
|
|
93
105
|
const superuser = "firebasesuperuser";
|
|
94
106
|
const temporaryPassword = utils.generateId(20);
|
|
95
107
|
await cloudSqlAdminClient.createUser(projectId, instanceId, "BUILT_IN", superuser, temporaryPassword);
|
|
96
|
-
return await execute([`SET ROLE =
|
|
108
|
+
return await execute([`SET ROLE = '${superuser}'`, ...cmds], {
|
|
97
109
|
projectId,
|
|
98
110
|
instanceId,
|
|
99
111
|
databaseId,
|
|
100
112
|
username: superuser,
|
|
101
113
|
password: temporaryPassword,
|
|
102
114
|
silent: silent,
|
|
115
|
+
transaction: transaction,
|
|
103
116
|
});
|
|
104
117
|
}
|
|
105
118
|
exports.executeSqlCmdsAsSuperUser = executeSqlCmdsAsSuperUser;
|
|
@@ -122,12 +135,6 @@ async function setupIAMUsers(instanceId, databaseId, options) {
|
|
|
122
135
|
const projectNumber = await (0, projectUtils_1.needProjectNumber)(options);
|
|
123
136
|
const { user: fdcP4SAUser, mode: fdcP4SAmode } = toDatabaseUser(getDataConnectP4SA(projectNumber));
|
|
124
137
|
await cloudSqlAdminClient.createUser(projectId, instanceId, fdcP4SAmode, fdcP4SAUser);
|
|
125
|
-
await (0, permissions_1.setupSQLPermissions)(instanceId, databaseId, options, true);
|
|
126
|
-
const grants = [
|
|
127
|
-
`GRANT "${(0, permissions_1.firebaseowner)(databaseId)}" TO "${user}"`,
|
|
128
|
-
`GRANT "${(0, permissions_1.firebasewriter)(databaseId)}" TO "${fdcP4SAUser}"`,
|
|
129
|
-
];
|
|
130
|
-
await executeSqlCmdsAsSuperUser(options, instanceId, databaseId, grants, true);
|
|
131
138
|
return user;
|
|
132
139
|
}
|
|
133
140
|
exports.setupIAMUsers = setupIAMUsers;
|
|
@@ -1,89 +1,22 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const lodash_1 = require("lodash");
|
|
9
|
-
const error_1 = require("../../error");
|
|
10
|
-
function firebaseowner(databaseId) {
|
|
11
|
-
return `firebaseowner_${databaseId}_public`;
|
|
3
|
+
exports.defaultPermissions = exports.readerRolePermissions = exports.writerRolePermissions = exports.ownerRolePermissions = exports.firebasewriter = exports.firebasereader = exports.firebaseowner = exports.FIREBASE_SUPER_USER = exports.DEFAULT_SCHEMA = void 0;
|
|
4
|
+
exports.DEFAULT_SCHEMA = "public";
|
|
5
|
+
exports.FIREBASE_SUPER_USER = "firebasesuperuser";
|
|
6
|
+
function firebaseowner(databaseId, schema = exports.DEFAULT_SCHEMA) {
|
|
7
|
+
return `firebaseowner_${databaseId}_${schema}`;
|
|
12
8
|
}
|
|
13
9
|
exports.firebaseowner = firebaseowner;
|
|
14
|
-
function firebasereader(databaseId) {
|
|
15
|
-
return `firebasereader_${databaseId}
|
|
10
|
+
function firebasereader(databaseId, schema = exports.DEFAULT_SCHEMA) {
|
|
11
|
+
return `firebasereader_${databaseId}_${schema}`;
|
|
16
12
|
}
|
|
17
13
|
exports.firebasereader = firebasereader;
|
|
18
|
-
function firebasewriter(databaseId) {
|
|
19
|
-
return `firebasewriter_${databaseId}
|
|
14
|
+
function firebasewriter(databaseId, schema = exports.DEFAULT_SCHEMA) {
|
|
15
|
+
return `firebasewriter_${databaseId}_${schema}`;
|
|
20
16
|
}
|
|
21
17
|
exports.firebasewriter = firebasewriter;
|
|
22
|
-
exports.fdcSqlRoleMap = {
|
|
23
|
-
owner: firebaseowner,
|
|
24
|
-
writer: firebasewriter,
|
|
25
|
-
reader: firebasereader,
|
|
26
|
-
};
|
|
27
|
-
async function checkSQLRoleIsGranted(options, instanceId, databaseId, grantedRole, granteeRole) {
|
|
28
|
-
const checkCmd = `
|
|
29
|
-
DO $$
|
|
30
|
-
DECLARE
|
|
31
|
-
role_count INTEGER;
|
|
32
|
-
BEGIN
|
|
33
|
-
-- Count the number of rows matching the criteria
|
|
34
|
-
SELECT COUNT(*)
|
|
35
|
-
INTO role_count
|
|
36
|
-
FROM
|
|
37
|
-
pg_auth_members m
|
|
38
|
-
JOIN
|
|
39
|
-
pg_roles grantee ON grantee.oid = m.member
|
|
40
|
-
JOIN
|
|
41
|
-
pg_roles granted ON granted.oid = m.roleid
|
|
42
|
-
JOIN
|
|
43
|
-
pg_roles grantor ON grantor.oid = m.grantor
|
|
44
|
-
WHERE
|
|
45
|
-
granted.rolname = '${grantedRole}'
|
|
46
|
-
AND grantee.rolname = '${granteeRole}';
|
|
47
|
-
|
|
48
|
-
-- If no rows were found, raise an exception
|
|
49
|
-
IF role_count = 0 THEN
|
|
50
|
-
RAISE EXCEPTION 'Role "%", is not granted to role "%".', '${grantedRole}', '${granteeRole}';
|
|
51
|
-
END IF;
|
|
52
|
-
END $$;
|
|
53
|
-
`;
|
|
54
|
-
try {
|
|
55
|
-
await (0, connect_1.executeSqlCmdsAsIamUser)(options, instanceId, databaseId, [checkCmd], true);
|
|
56
|
-
return true;
|
|
57
|
-
}
|
|
58
|
-
catch (e) {
|
|
59
|
-
if (e instanceof error_1.FirebaseError && e.message.includes("not granted to role")) {
|
|
60
|
-
return false;
|
|
61
|
-
}
|
|
62
|
-
logger_1.logger.error(`Role Check Failed: ${e}`);
|
|
63
|
-
throw e;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
exports.checkSQLRoleIsGranted = checkSQLRoleIsGranted;
|
|
67
|
-
async function iamUserIsCSQLAdmin(options) {
|
|
68
|
-
const projectId = (0, projectUtils_1.needProjectId)(options);
|
|
69
|
-
const requiredPermissions = [
|
|
70
|
-
"cloudsql.instances.connect",
|
|
71
|
-
"cloudsql.instances.get",
|
|
72
|
-
"cloudsql.users.create",
|
|
73
|
-
"cloudsql.users.update",
|
|
74
|
-
];
|
|
75
|
-
try {
|
|
76
|
-
const iamResult = await (0, iam_1.testIamPermissions)(projectId, requiredPermissions);
|
|
77
|
-
return iamResult.passed;
|
|
78
|
-
}
|
|
79
|
-
catch (err) {
|
|
80
|
-
logger_1.logger.debug(`[iam] error while checking permissions, command may fail: ${err}`);
|
|
81
|
-
return false;
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
exports.iamUserIsCSQLAdmin = iamUserIsCSQLAdmin;
|
|
85
18
|
function ownerRolePermissions(databaseId, superuser, schema) {
|
|
86
|
-
const firebaseOwnerRole = firebaseowner(databaseId);
|
|
19
|
+
const firebaseOwnerRole = firebaseowner(databaseId, schema);
|
|
87
20
|
return [
|
|
88
21
|
`do
|
|
89
22
|
$$
|
|
@@ -102,8 +35,9 @@ function ownerRolePermissions(databaseId, superuser, schema) {
|
|
|
102
35
|
`GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA "${schema}" TO "${firebaseOwnerRole}"`,
|
|
103
36
|
];
|
|
104
37
|
}
|
|
38
|
+
exports.ownerRolePermissions = ownerRolePermissions;
|
|
105
39
|
function writerRolePermissions(databaseId, superuser, schema) {
|
|
106
|
-
const firebaseWriterRole = firebasewriter(databaseId);
|
|
40
|
+
const firebaseWriterRole = firebasewriter(databaseId, schema);
|
|
107
41
|
return [
|
|
108
42
|
`do
|
|
109
43
|
$$
|
|
@@ -120,15 +54,11 @@ function writerRolePermissions(databaseId, superuser, schema) {
|
|
|
120
54
|
`GRANT SELECT, INSERT, UPDATE, DELETE, TRUNCATE ON ALL TABLES IN SCHEMA "${schema}" TO "${firebaseWriterRole}"`,
|
|
121
55
|
`GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA "${schema}" TO "${firebaseWriterRole}"`,
|
|
122
56
|
`GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA "${schema}" TO "${firebaseWriterRole}"`,
|
|
123
|
-
`SET ROLE = '${firebaseowner(databaseId)}';`,
|
|
124
|
-
`ALTER DEFAULT PRIVILEGES IN SCHEMA "${schema}" GRANT SELECT, INSERT, UPDATE, DELETE, TRUNCATE ON TABLES TO "${firebaseWriterRole}";`,
|
|
125
|
-
`ALTER DEFAULT PRIVILEGES IN SCHEMA "${schema}" GRANT USAGE ON SEQUENCES TO "${firebaseWriterRole}";`,
|
|
126
|
-
`ALTER DEFAULT PRIVILEGES IN SCHEMA "${schema}" GRANT EXECUTE ON FUNCTIONS TO "${firebaseWriterRole}"`,
|
|
127
|
-
`SET ROLE = cloudsqlsuperuser`,
|
|
128
57
|
];
|
|
129
58
|
}
|
|
59
|
+
exports.writerRolePermissions = writerRolePermissions;
|
|
130
60
|
function readerRolePermissions(databaseId, superuser, schema) {
|
|
131
|
-
const firebaseReaderRole = firebasereader(databaseId);
|
|
61
|
+
const firebaseReaderRole = firebasereader(databaseId, schema);
|
|
132
62
|
return [
|
|
133
63
|
`do
|
|
134
64
|
$$
|
|
@@ -145,21 +75,37 @@ function readerRolePermissions(databaseId, superuser, schema) {
|
|
|
145
75
|
`GRANT SELECT ON ALL TABLES IN SCHEMA "${schema}" TO "${firebaseReaderRole}"`,
|
|
146
76
|
`GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA "${schema}" TO "${firebaseReaderRole}"`,
|
|
147
77
|
`GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA "${schema}" TO "${firebaseReaderRole}"`,
|
|
148
|
-
`SET ROLE = '${firebaseowner(databaseId)}';`,
|
|
149
|
-
`ALTER DEFAULT PRIVILEGES IN SCHEMA "${schema}" GRANT SELECT ON TABLES TO "${firebaseReaderRole}";`,
|
|
150
|
-
`ALTER DEFAULT PRIVILEGES IN SCHEMA "${schema}" GRANT SELECT, USAGE ON SEQUENCES TO "${firebaseReaderRole}";`,
|
|
151
|
-
`ALTER DEFAULT PRIVILEGES IN SCHEMA "${schema}" GRANT EXECUTE ON FUNCTIONS TO "${firebaseReaderRole}"`,
|
|
152
|
-
`SET ROLE = cloudsqlsuperuser`,
|
|
153
78
|
];
|
|
154
79
|
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
const
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
80
|
+
exports.readerRolePermissions = readerRolePermissions;
|
|
81
|
+
function defaultPermissions(databaseId, schema, ownerRole) {
|
|
82
|
+
const firebaseWriterRole = firebasewriter(databaseId, schema);
|
|
83
|
+
const firebaseReaderRole = firebasereader(databaseId, schema);
|
|
84
|
+
return [
|
|
85
|
+
`ALTER DEFAULT PRIVILEGES
|
|
86
|
+
FOR ROLE "${ownerRole}"
|
|
87
|
+
IN SCHEMA "${schema}"
|
|
88
|
+
GRANT SELECT, INSERT, UPDATE, DELETE, TRUNCATE ON TABLES TO "${firebaseWriterRole}";`,
|
|
89
|
+
`ALTER DEFAULT PRIVILEGES
|
|
90
|
+
FOR ROLE "${ownerRole}"
|
|
91
|
+
IN SCHEMA "${schema}"
|
|
92
|
+
GRANT USAGE ON SEQUENCES TO "${firebaseWriterRole}";`,
|
|
93
|
+
`ALTER DEFAULT PRIVILEGES
|
|
94
|
+
FOR ROLE "${ownerRole}"
|
|
95
|
+
IN SCHEMA "${schema}"
|
|
96
|
+
GRANT EXECUTE ON FUNCTIONS TO "${firebaseWriterRole}";`,
|
|
97
|
+
`ALTER DEFAULT PRIVILEGES
|
|
98
|
+
FOR ROLE "${ownerRole}"
|
|
99
|
+
IN SCHEMA "${schema}"
|
|
100
|
+
GRANT SELECT ON TABLES TO "${firebaseReaderRole}";`,
|
|
101
|
+
`ALTER DEFAULT PRIVILEGES
|
|
102
|
+
FOR ROLE "${ownerRole}"
|
|
103
|
+
IN SCHEMA "${schema}"
|
|
104
|
+
GRANT USAGE ON SEQUENCES TO "${firebaseReaderRole}";`,
|
|
105
|
+
`ALTER DEFAULT PRIVILEGES
|
|
106
|
+
FOR ROLE "${ownerRole}"
|
|
107
|
+
IN SCHEMA "${schema}"
|
|
108
|
+
GRANT EXECUTE ON FUNCTIONS TO "${firebaseReaderRole}";`,
|
|
109
|
+
];
|
|
164
110
|
}
|
|
165
|
-
exports.
|
|
111
|
+
exports.defaultPermissions = defaultPermissions;
|