Skip to content

Commit

Permalink
Filter blob by tags
Browse files Browse the repository at this point in the history
  • Loading branch information
EmmaZhu committed Sep 8, 2024
1 parent 128ea41 commit e5a01a3
Show file tree
Hide file tree
Showing 38 changed files with 2,615 additions and 289 deletions.
105 changes: 82 additions & 23 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,22 @@
"request": "launch",
"name": "Azurite Service - Loki",
"cwd": "${workspaceFolder}",
"runtimeArgs": ["-r", "ts-node/register"],
"args": ["${workspaceFolder}/src/azurite.ts", "-d", "debug.log"],
"runtimeArgs": [
"-r",
"ts-node/register"
],
"args": [
"${workspaceFolder}/src/azurite.ts",
"-d",
"debug.log"
],
"env": {
"AZURITE_ACCOUNTS": ""
},
"skipFiles": ["node_modules/*/**", "<node_internals>/*/**"],
"skipFiles": [
"node_modules/*/**",
"<node_internals>/*/**"
],
"outputCapture": "std"
},
{
Expand All @@ -35,8 +45,16 @@
"request": "launch",
"name": "Azurite Service - Loki, Loose",
"cwd": "${workspaceFolder}",
"runtimeArgs": ["-r", "ts-node/register"],
"args": ["${workspaceFolder}/src/azurite.ts", "-d", "debug.log", "-L"],
"runtimeArgs": [
"-r",
"ts-node/register"
],
"args": [
"${workspaceFolder}/src/azurite.ts",
"-d",
"debug.log",
"-L"
],
"env": {
"AZURITE_ACCOUNTS": ""
},
Expand All @@ -47,7 +65,10 @@
"request": "launch",
"name": "Azurite Service - Loki, Loose, HTTPS, OAuth",
"cwd": "${workspaceFolder}",
"runtimeArgs": ["-r", "ts-node/register"],
"runtimeArgs": [
"-r",
"ts-node/register"
],
"args": [
"${workspaceFolder}/src/azurite.ts",
"-L",
Expand All @@ -70,7 +91,10 @@
"request": "launch",
"name": "Azurite Queue Service - Loki, HTTPS, OAuth",
"cwd": "${workspaceFolder}",
"runtimeArgs": ["-r", "ts-node/register"],
"runtimeArgs": [
"-r",
"ts-node/register"
],
"args": [
"${workspaceFolder}/src/queue/main.ts",
"-d",
Expand All @@ -92,7 +116,10 @@
"request": "launch",
"name": "Azurite Blob Service - Loki, HTTPS, OAuth",
"cwd": "${workspaceFolder}",
"runtimeArgs": ["-r", "ts-node/register"],
"runtimeArgs": [
"-r",
"ts-node/register"
],
"args": [
"${workspaceFolder}/src/blob/main.ts",
"-d",
Expand All @@ -114,8 +141,15 @@
"request": "launch",
"name": "Azurite Blob Service - SQL",
"cwd": "${workspaceFolder}",
"runtimeArgs": ["-r", "ts-node/register"],
"args": ["${workspaceFolder}/src/blob/main.ts", "-d", "debug.log"],
"runtimeArgs": [
"-r",
"ts-node/register"
],
"args": [
"${workspaceFolder}/src/blob/main.ts",
"-d",
"debug.log"
],
"env": {
"AZURITE_DB": "mysql://root:[email protected]:3306/azurite_blob",
"AZURITE_ACCOUNTS": ""
Expand All @@ -127,8 +161,15 @@
"request": "launch",
"name": "Azurite Table Service - Loki",
"cwd": "${workspaceFolder}",
"runtimeArgs": ["-r", "ts-node/register"],
"args": ["${workspaceFolder}/src/table/main.ts", "-d", "debug.log"],
"runtimeArgs": [
"-r",
"ts-node/register"
],
"args": [
"${workspaceFolder}/src/table/main.ts",
"-d",
"debug.log"
],
"env": {
"AZURITE_ACCOUNTS": ""
},
Expand All @@ -139,16 +180,24 @@
"request": "launch",
"name": "Current TS File",
"cwd": "${workspaceFolder}",
"runtimeArgs": ["-r", "ts-node/register"],
"args": ["${workspaceFolder}/${relativeFile}"],
"runtimeArgs": [
"-r",
"ts-node/register"
],
"args": [
"${workspaceFolder}/${relativeFile}"
],
"outputCapture": "std"
},
{
"type": "node",
"request": "launch",
"name": "Current Mocha TS File - Loki",
"cwd": "${workspaceFolder}",
"runtimeArgs": ["-r", "ts-node/register"],
"runtimeArgs": [
"-r",
"ts-node/register"
],
"args": [
"${workspaceFolder}/node_modules/mocha/bin/_mocha",
"-u",
Expand All @@ -162,7 +211,7 @@
"AZURITE_ACCOUNTS": "",
"AZURE_TABLE_STORAGE": "",
"DATATABLES_ACCOUNT_NAME": "<name of your storage account>",
"DATATABLES_ACCOUNT_KEY" : "<account key for your storage account>",
"DATATABLES_ACCOUNT_KEY": "<account key for your storage account>",
"AZURE_DATATABLES_STORAGE_STRING": "https://<your account name>.table.core.windows.net",
"AZURE_DATATABLES_SAS": "?<sas query string>",
"NODE_TLS_REJECT_UNAUTHORIZED": "0"
Expand All @@ -175,15 +224,18 @@
"request": "launch",
"name": "EXE Mocha TS File - Loki",
"cwd": "${workspaceFolder}",
"runtimeArgs": ["-r", "ts-node/register"],
"runtimeArgs": [
"-r",
"ts-node/register"
],
"args": [
"${workspaceFolder}/node_modules/mocha/bin/_mocha",
"-u",
"tdd",
"--timeout",
"999999",
"--colors",
"${workspaceFolder}/tests/exe.test.ts",
"${workspaceFolder}/tests/exe.test.ts",
"--exit"
],
"env": {
Expand All @@ -199,7 +251,10 @@
"request": "launch",
"name": "Current Mocha TS File - SQL",
"cwd": "${workspaceFolder}",
"runtimeArgs": ["-r", "ts-node/register"],
"runtimeArgs": [
"-r",
"ts-node/register"
],
"args": [
"${workspaceFolder}/node_modules/mocha/bin/_mocha",
"-u",
Expand All @@ -211,7 +266,7 @@
],
"env": {
"AZURITE_ACCOUNTS": "",
"AZURITE_TEST_DB": "mysql://root:my-secret-pw@127.0.0.1:3306/azurite_blob_test",
"AZURITE_TEST_DB": "mysql://root:!!123abc@127.0.0.1:3306/azurite_blob",
"NODE_TLS_REJECT_UNAUTHORIZED": "0"
},
"internalConsoleOptions": "openOnSessionStart",
Expand Down Expand Up @@ -250,9 +305,13 @@
"type": "extensionHost",
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": ["--extensionDevelopmentPath=${workspaceFolder}"],
"outFiles": ["${workspaceFolder}/dist/**/*.js"],
"args": [
"--extensionDevelopmentPath=${workspaceFolder}"
],
"outFiles": [
"${workspaceFolder}/dist/**/*.js"
],
"preLaunchTask": "npm: watch"
}
]
}
}
10 changes: 9 additions & 1 deletion src/blob/conditions/ConditionResourceAdapter.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { BlobModel, ContainerModel } from "../persistence/IBlobMetadataStore";
import { BlobModel, ContainerModel, FilterBlobModel } from "../persistence/IBlobMetadataStore";
import IConditionResource from "./IConditionResource";

export default class ConditionResourceAdapter implements IConditionResource {
public exist: boolean;
public etag: string;
public lastModified: Date;
public blobItemWithTags?: FilterBlobModel;

public constructor(resource: BlobModel | ContainerModel | undefined | null) {
if (
Expand Down Expand Up @@ -33,5 +34,12 @@ export default class ConditionResourceAdapter implements IConditionResource {

this.lastModified = new Date(resource.properties.lastModified);
this.lastModified.setMilliseconds(0); // Precision to seconds

const blobItem = resource as BlobModel;
this.blobItemWithTags = {
name: blobItem.name,
containerName: blobItem.containerName,
tags: blobItem.blobTags
};
}
}
3 changes: 3 additions & 0 deletions src/blob/conditions/ConditionalHeadersAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export default class ConditionalHeadersAdapter implements IConditionalHeaders {
public ifUnmodifiedSince?: Date;
public ifMatch?: string[];
public ifNoneMatch?: string[];
public ifTags?: string;

public constructor(
context: Context,
Expand Down Expand Up @@ -43,5 +44,7 @@ export default class ConditionalHeadersAdapter implements IConditionalHeaders {
if (this.ifUnmodifiedSince) {
this.ifUnmodifiedSince.setMilliseconds(0); // Precision to seconds
}

this.ifTags = modifiedAccessConditions.ifTags;
}
}
3 changes: 3 additions & 0 deletions src/blob/conditions/IConditionResource.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { FilterBlobModel } from "../persistence/IBlobMetadataStore";

export default interface IConditionResource {
/**
* Whether resource exists or not.
Expand All @@ -13,4 +15,5 @@ export default interface IConditionResource {
* last modified time for container or blob.
*/
lastModified: Date;
blobItemWithTags?: FilterBlobModel;
}
5 changes: 5 additions & 0 deletions src/blob/conditions/IConditionalHeaders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,9 @@ export interface IConditionalHeaders {
* If-None-Match etag list without quotes.
*/
ifNoneMatch?: string[];

/**
* Specify a SQL where clause on blob tags to operate only on blobs with a matching value.
*/
ifTags?: string;
}
3 changes: 2 additions & 1 deletion src/blob/conditions/IConditionalHeadersValidator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export interface IConditionalHeadersValidator {
validate(
context: Context,
conditionalHeaders: IConditionalHeaders,
resource: IConditionResource
resource: IConditionResource,
isSourceBlob?: boolean
): void;
}
23 changes: 19 additions & 4 deletions src/blob/conditions/ReadConditionalHeadersValidator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import StorageErrorFactory from "../errors/StorageErrorFactory";
import { ModifiedAccessConditions } from "../generated/artifacts/models";
import Context from "../generated/Context";
import { BlobModel, ContainerModel } from "../persistence/IBlobMetadataStore";
import { generateQueryBlobWithTagsWhereFunction } from "../persistence/QueryInterpreter/QueryInterpreter";
import ConditionalHeadersAdapter from "./ConditionalHeadersAdapter";
import ConditionResourceAdapter from "./ConditionResourceAdapter";
import { IConditionalHeaders } from "./IConditionalHeaders";
Expand All @@ -11,12 +12,14 @@ import IConditionResource from "./IConditionResource";
export function validateReadConditions(
context: Context,
conditionalHeaders?: ModifiedAccessConditions,
model?: BlobModel | ContainerModel | null
model?: BlobModel | ContainerModel | null,
isSourceBlob?: boolean
) {
new ReadConditionalHeadersValidator().validate(
context,
new ConditionalHeadersAdapter(context, conditionalHeaders),
new ConditionResourceAdapter(model)
new ConditionResourceAdapter(model),
isSourceBlob
);
}

Expand All @@ -30,11 +33,13 @@ export default class ReadConditionalHeadersValidator
* @param context
* @param conditionalHeaders
* @param resource
* @param isSourceBlob
*/
public validate(
context: Context,
conditionalHeaders: IConditionalHeaders,
resource: IConditionResource
resource: IConditionResource,
isSourceBlob?: boolean
): void {
// If-Match && If-Unmodified-Since && (If-None-Match || If-Modified-Since)

Expand Down Expand Up @@ -66,7 +71,7 @@ export default class ReadConditionalHeadersValidator
// If-Match
const ifMatchPass = conditionalHeaders.ifMatch
? conditionalHeaders.ifMatch.includes(resource.etag) ||
conditionalHeaders.ifMatch[0] === "*"
conditionalHeaders.ifMatch[0] === "*"
: undefined;

// If-Unmodified-Since
Expand Down Expand Up @@ -107,6 +112,16 @@ export default class ReadConditionalHeadersValidator
if (isModifiedSincePass === false && ifNoneMatchPass !== true) {
throw StorageErrorFactory.getNotModified(context.contextId!);
}

if (conditionalHeaders.ifTags) {
const againstSourceBlob = isSourceBlob === undefined ? false : isSourceBlob;
const validateFunction = generateQueryBlobWithTagsWhereFunction(context, conditionalHeaders.ifTags, againstSourceBlob ? 'x-ms-source-if-tags' : 'x-ms-if-tags');

if (conditionalHeaders?.ifTags !== undefined
&& validateFunction(resource.blobItemWithTags).length === 0) {
throw StorageErrorFactory.getConditionNotMet(context.contextId!);
}
}
}
}
}
Loading

0 comments on commit e5a01a3

Please sign in to comment.