Skip to content

Commit c08f0d6

Browse files
samtsterndevpeerapong
authored andcommitted
setRules endpoint for Storage Emulator (firebase#3332)
1 parent b9c0981 commit c08f0d6

File tree

2 files changed

+53
-4
lines changed

2 files changed

+53
-4
lines changed

src/emulator/storage/index.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { StorageLayer } from "./files";
77
import * as chokidar from "chokidar";
88
import { EmulatorLogger } from "../emulatorLogger";
99
import * as fs from "fs";
10-
import { StorageRulesetInstance, StorageRulesRuntime } from "./rules/runtime";
10+
import { StorageRulesetInstance, StorageRulesRuntime, StorageRulesIssues } from "./rules/runtime";
1111
import { Source } from "./rules/types";
1212
import { FirebaseError } from "../../error";
1313
import { getDownloadDetails } from "../downloadableEmulators";
@@ -104,10 +104,17 @@ export class StorageEmulator implements EmulatorInstance {
104104
};
105105
}
106106

107-
private async loadRuleset(): Promise<void> {
107+
public async loadRuleset(source?: Source): Promise<StorageRulesIssues> {
108+
if (source) {
109+
this._rulesetSource = source;
110+
}
111+
108112
if (!this._rulesetSource) {
109-
this._logger.log("WARN", "Attempting to update ruleset without a source.");
110-
return;
113+
const msg = "Attempting to update ruleset without a source.";
114+
this._logger.log("WARN", msg);
115+
116+
const error = JSON.stringify({ error: msg });
117+
return new StorageRulesIssues([error], []);
111118
}
112119

113120
const { ruleset, issues } = await this._rulesRuntime.loadRuleset(this._rulesetSource);
@@ -137,6 +144,8 @@ export class StorageEmulator implements EmulatorInstance {
137144
} else {
138145
this._rules = ruleset;
139146
}
147+
148+
return issues;
140149
}
141150

142151
async connect(): Promise<void> {

src/emulator/storage/server.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,46 @@ export function createApp(
7373
res.sendStatus(200);
7474
});
7575

76+
app.put("/internal/setRules", async (req, res) => {
77+
// Payload:
78+
// {
79+
// rules: {
80+
// files: [{ name:<string> content: <string> }]
81+
// }
82+
// }
83+
// TODO: Add a bucket parameter for per-bucket rules support
84+
85+
const rules = req.body.rules;
86+
if (!(rules && Array.isArray(rules.files) && rules.files.length > 0)) {
87+
res.status(400).send("Request body must include 'rules.files' array .");
88+
return;
89+
}
90+
91+
const file = rules.files[0];
92+
if (!(file.name && file.content)) {
93+
res
94+
.status(400)
95+
.send(
96+
"Request body must include 'rules.files' array where each member contains 'name' and 'content'."
97+
);
98+
return;
99+
}
100+
101+
const name = file.name;
102+
const content = file.content;
103+
const issues = await emulator.loadRuleset({ files: [{ name, content }] });
104+
105+
if (issues.errors.length > 0) {
106+
res.status(400).json({
107+
message: "There was an error updating rules, see logs for more details",
108+
});
109+
}
110+
111+
res.sendStatus(200).json({
112+
message: "Rules updated successfully",
113+
});
114+
});
115+
76116
app.post("/internal/reset", (req, res) => {
77117
storageLayer.reset();
78118
res.sendStatus(200);

0 commit comments

Comments
 (0)