-
Notifications
You must be signed in to change notification settings - Fork 902
/
utils.ts
102 lines (90 loc) · 2.81 KB
/
utils.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
import { StorageRulesetInstance } from "./runtime";
import { RulesResourceMetadata } from "../metadata";
import { RulesetOperationMethod } from "./types";
import { EmulatorLogger } from "../../emulatorLogger";
import { Emulators } from "../../types";
/** Variable overrides to be passed to the rules evaluator. */
export type RulesVariableOverrides = {
before?: RulesResourceMetadata;
after?: RulesResourceMetadata;
};
/** Authorizes storage requests via Firebase Rules rulesets. */
export interface RulesValidator {
validate(
path: string,
bucketId: string,
method: RulesetOperationMethod,
variableOverrides: RulesVariableOverrides,
authorization?: string
): Promise<boolean>;
}
/** Authorizes storage requests via admin credentials. */
export interface AdminCredentialValidator {
validate(authorization?: string): boolean;
}
/** Provider for Storage security rules. */
export type RulesetProvider = (resource: string) => StorageRulesetInstance | undefined;
/**
* Returns a validator that pulls a Ruleset from a {@link RulesetProvider} on each run.
*/
export function getRulesValidator(rulesetProvider: RulesetProvider): RulesValidator {
return {
validate: async (
path: string,
bucketId: string,
method: RulesetOperationMethod,
variableOverrides: RulesVariableOverrides,
authorization?: string
) => {
return await isPermitted({
ruleset: rulesetProvider(bucketId),
file: variableOverrides,
path,
method,
authorization,
});
},
};
}
/** Returns a validator for admin credentials. */
export function getAdminCredentialValidator(): AdminCredentialValidator {
return { validate: isValidAdminCredentials };
}
/** Authorizes file access based on security rules. */
export async function isPermitted(opts: {
ruleset?: StorageRulesetInstance;
file: {
before?: RulesResourceMetadata;
after?: RulesResourceMetadata;
};
path: string;
method: RulesetOperationMethod;
authorization?: string;
}): Promise<boolean> {
if (!opts.ruleset) {
EmulatorLogger.forEmulator(Emulators.STORAGE).log(
"WARN",
`Can not process SDK request with no loaded ruleset`
);
return false;
}
// Skip auth for UI
if (isValidAdminCredentials(opts.authorization)) {
return true;
}
const { permitted, issues } = await opts.ruleset.verify({
method: opts.method,
path: opts.path,
file: opts.file,
token: opts.authorization ? opts.authorization.split(" ")[1] : undefined,
});
if (issues.exist()) {
issues.all.forEach((warningOrError) => {
EmulatorLogger.forEmulator(Emulators.STORAGE).log("WARN", warningOrError);
});
}
return !!permitted;
}
function isValidAdminCredentials(authorization?: string) {
return ["Bearer owner", "Firebase owner"].includes(authorization ?? "");
}