How to identify "insert" vs "update" diff in Azure Cosmos DB trigger? - azure

I have created a function triggered by Azure Cosmos DB by following https://learn.microsoft.com/en-us/azure/azure-functions/functions-create-cosmos-db-triggered-function which is working.
Upon seeing logs, I am unable to identify if this trigger is for INSERT or UPDATE. I know that in AWS, when you add lambda as the dynamo trigger, you could identify that easily. You can even see what was original record vs updated one (for update)
Question:
How to identify INSERT vs UPDATE vs DELETE action?
I am new to Azure, so it is possible that I am missing something in my function code.
Function Code:
module.exports = async function (context, documents) {
context.log('1');
if (!!documents && documents.length > 0) {
context.log('Document Id: ', documents[0].id); <-- SHOWS ID OF THE RECORD
context.log('Document[0]', documents[0]); <-- ENTIRE RECORD
context.log('Documents', documents); <-- ALL RECORDS
}
}
context object from above:
{
invocationId: '3ee0136e-d005-4517-a11e-c43ec9ca7c67',
traceContext: {
traceparent: '00-4938136b13476845524c7ae5059d84f3-badfbc56b5ef0067-00',
tracestate: '',
attributes: {
OperationName: 'CosmosTrigger1'
}
},
executionContext: {
invocationId: '3ee0136e-d005-4517-a11e-c43ec9ca7c67',
functionName: 'CosmosTrigger1',
functionDirectory: 'C:\\home\\site\\wwwroot\\CosmosTrigger1',
retryContext: null
},
bindings: {
documents: [
[
Object
]
]
},
log: [
Function(anonymous)
]{
error: [
Function: error
],
warn: [
Function: warn
],
info: [
Function: info
],
verbose: [
Function: verbose
]
},
bindingData: {
invocationId: '3ee0136e-d005-4517-a11e-c43ec9ca7c67'
},
bindingDefinitions: [
{
name: 'documents',
type: 'cosmosDBTrigger',
direction: 'in'
}
],
done: [
Function(anonymous)
]
}
Function Log:

Unfortunately, you can't distinguish between the two types (insert & update). The trigger consumes the Change Feed, and you can't filter it for a specific type of operation.
Today, you see all inserts and updates in the change feed. You can't
filter the change feed for a specific type of operation.

Related

Gremlin - How to return a property of an edge alongside a node result?

I would like to know how to add to the result a property of the edge that links a node to another node
I'm using node.js to make queries to a Neptune database through Gremlin. Then I send the result to Javascript through an API.
let data = [];
const id_vertex = "1"
data = await g.V().has(id,id_vertex)
.out()
.valueMap()
.with_('~tinkerpop.valueMap.tokens'))
.toList();
This is how data looks like:
[
{
name: [ 'Colt Bogan II' ],
label: 'User',
notification: [ 'Both' ],
usercity: [ 'Wardburgh' ],
id: '1',
RegisteredDate: [ '2010-10-14' ]
},
{
name: [ 'Webster Sanford' ],
label: 'User',
notification: [ 'SMS' ],
usercity: [ 'Nanniefurt' ],
id: '2',
RegisteredDate: [ '2006-02-03' ]
}
]
Then I use JSON.stringify to make the body of what I send back to javascript
body: JSON.stringify(data)
"body":
"[{\"name\":[\"Colt Bogan II\"],\"label\":\"User\",\"notification\":[\"Both\"],\"usercity\":[\"Wardburgh\"],\"id\":\"1\",\"RegisteredDate\":[\"2010-10-14\"]},
{\"name\":[\"Webster Sanford\"],\"label\":\"User\",\"notification\":[\"SMS\"],\"usercity\":[\"Nanniefurt\"],\"id\":\"2\",\"RegisteredDate\":[\"2006-02-03\"]}]"
I would like to add the property of the edge that connects my node that has the id id_vertex to another node (when returning all the properties of that node) in the body. Either while I'm making the Gremlin query or after that. Let's say that the edge property I'm interested in is color, then in the end the body I would like to look like this:
"body":
"[{\"edgeColor\":[\"Green\"], \"name\":[\"Colt Bogan II\"],\"label\":\"User\",\"notification\":[\"Both\"],\"usercity\":[\"Wardburgh\"],\"id\":\"1\",\"RegisteredDate\":[\"2010-10-14\"]},
{\"edgeColor\":[\"Blue\"], \"name\":[\"Webster Sanford\"],\"label\":\"User\",\"notification\":[\"SMS\"],\"usercity\":[\"Nanniefurt\"],\"id\":\"2\",\"RegisteredDate\":[\"2006-02-03\"]}]"
Also, I have maximum one edge from one node to another, if this helps
If you modify your query slightly you can include edge properties in the result.
let data = [];
const id_vertex = "1"
data = await g.V().has(id,id_vertex)
.outE()
.project('edge','vertex')
.by(valueMap('edgeColor'))
.by(inV().valueMap().with_('~tinkerpop.valueMap.tokens'))
.toList();

How to use scope in loopback filter in json format

I am trying to make call from my angular service to loopback api. I have a parcelStatuses collection that contains a parcelId so i am able to include parcel collection too but I also need to check against a particular vendorId and that vendorId exists in parcel collection. I am trying to make use of scope to check against particular vendorId but i think i am not writing correct json syntax/call. Here is my function inside service
private getParcelsByFilter(
limit: number,
skip: number,
vendorId: string,
filter: string
) {
const checkFilter = {
"where": {
"and": [{"statusRepositoryId": filter}]
},
"include": [
{
"parcel": [
{
"scope": {"vendorId": vendorId}
},
"parcelStatuses",
{"customerData":"customer"}
]
}
],
"limit": limit,
"skip": skip,
}
return this._http.get<IParcel[]>(
`${environment.url}/ParcelStatuses?filter=${encodeURIComponent(JSON.stringify(checkFilter))}`
);
}
Here is my demo view of parcelStatus collection object
[{
"id":"lbh24214",
"statusRepositoryId":"3214fsad",
"parcelId":"LH21421"
}]
Demo json of parcel
[{
"id":"LHE21421",
"customerDataId":"214fdsas",
"customerId":"412dsf",
"vendorId":"123421"
}]
Please help me with writing correct call
Formatting aside, there's several issues with the query:
Unnecessary and
This line:
where: {
and: [{statusRepositoryId: filter}]
}
Can be simplified to:
where: {
statusRepositoryId: filter
}
As there is only 1 where condition, and becomes redundant.
Misuse of include and scope
include is used to include relations while scope applies filters to those relations. They can work in tandem to create a comprehensive query:
include: [
{
relation: "parcels",
scope: {
where: {vendorId: vendorId},
}
}
],
This will include the parcels relation as part of the response, while filtering the parcels relation with a where filter.
That means the final code should look similar to the following:
private getParcelsByFilter(
limit: number,
skip: number,
vendorId: string,
filter: string
) {
const checkFilter = {
where: {statusRepositoryId: filter},
include: [
{
relation: "parcels",
scope: {
where: {vendorId: vendorId},
}
}
],
limit: limit,
skip: skip,
}
return this._http.get<IParcel[]>(
`${environment.url}/ParcelStatuses?filter=${encodeURIComponent(JSON.stringify(checkFilter))}`
);
}
Further reading
Please review these resources to get a better understanding on how to use filters.
https://loopback.io/doc/en/lb4/Include-filter.html

Azure storage REST API response includes BOM (” ) at that start of the XML file

I am developing a custom vsts extension for a release task which have a picklist which has values populated from the REST endpoint data source ( my storage account ). I am following this blow link as reference.
https://learn.microsoft.com/en-us/vsts/extend/develop/service-endpoints?view=vsts
I have uploaded my extension but the picklist is not populating with values in the task.
Below are the configurations that I have done.
vss-extension.json:
{
“manifestVersion”: 1,
“id”: “build-release-task”,
“name”: “My Custom release task”,
“version”: “0.0.1”,
“publisher”: “custext”,
“public”: false,
“targets”: [
{
“id”: “Microsoft.VisualStudio.Services”
}
],
“description”: “A picklist which has values populated from the REST
endpoint data source. Includes one build/release task.”,
“categories”: [
“Build and release”
],
“icons”: {
“default”: “images/extension-icon.png”
},
“files”: [
{
“path”: “buildAndReleaseTask”
}
],
“contributions”: [
{
“id”: “service-endpoint”,
“description”: “Service Endpoint type for custom Storage connection”,
“type”: “ms.vss-endpoint.service-endpoint-type”,
“targets”: [ “ms.vss-endpoint.endpoint-types” ],
“properties”: {
“name”: “custom”,
“displayName”: “Custom server connection”,
“url”: {
“displayName”: “Server Url”,
“helpText”: “storage end point url.”
},
“dataSources”: [
{
“name”: “Storage Account”,
“endpointUrl”: “{{endpoint.url}}test/?restype=container&comp=list”,
“resultSelector”: “xpath://EnumerationResults/Blobs/Blob/Name”
}
],
]
}
],
“helpMarkDown”: “Learn More”
}
},
{
“id”: “custom-build-release-task”,
“type”: “ms.vss-distributed-task.task”,
“description”: “Task with a dynamic property getting data from an
endpoint REST data source”,
“targets”: [
“ms.vss-distributed-task.tasks”
],
“properties”: {
“name”: “buildAndReleaseTask”
}
}
]
}
task.json:
{
“id”: “325958a0-63b7-11e6-88a5-f7c7f66e6264”,
“name”: “dropdownlist”,
“friendlyName”: “Drop down list”,
“description”: “Lists the db files”,
“helpMarkDown”: “Custom release task.Drop down list”,
“category”: “Utility”,
“visibility”: [
“Release”
],
“author”: “satyam”,
“version”: {
“Major”: 0,
“Minor”: 1,
“Patch”: 0
},
“instanceNameFormat”: “dropdownlist $(message)”,
“groups”: [
{
“name”: “advanced”,
“displayName”: “Advanced”,
“isExpanded”: false
}
],
“inputs”: [
{
“name”: “CustomService”,
“type”: “connectedService:custom”,
“label”: “Storage end point”,
“defaultValue”: “”,
“required”: true,
“helpMarkDown”: “Select the storage account to use. If needed,
click on ‘manage’, and add a new Service Endpoint of type
‘Custom server connection'”
},
{
“name”: “Scripts”,
“type”: “pickList”,
“label”: “saasscripts”,
“required”: true,
“helpMarkDown”: “Select the name of the saas script.”,
“properties”: {
“EditableOptions”: “True”
}
}
],
“dataSourceBindings”: [
{
“target”: “Scripts”,
“endpointId”: “$(CustomService)”,
“dataSourceName”: “Storage Account”
}
],
“outputVariables”: [
{
“name”: “dbfile”,
“description”: “Application URL of the selected App
Service.”
}
],
“execution”: {
“Node”: {
“target”: “powershell.js”
}
}
}
endpointUrl: I tried with following ways in endpointUrl in datasources (vss-extension.json)
{{endpoint.url}}test/?restype=container&comp=list
2.https://mycontainername.blob.core.windows.net/test/restype=container&comp=list
The picklist is not populated with the blob contents.
I guess problem in above issue might be unable to parse the azure storage blob list response type. the rest api response includes BOM (” ) at that start of the XML file which might be cause of the parsing.

Is there any way or workaround to change the azure blob rest api response to exclude BOM (” ) or changing the response to JSON format.

Feathers - restrict service response to data owned by current user only

In Feathers the goal is to restrict the data accessible on a certain service to the data owned by the currently logged in user only.
Assuming that I am using Feathers authentication, the data available on this service is stored in a database table, and the table column that contains the user ID is called user_id, will this hook achieve the goal?
If not then what needs to change?
In case it is important to be able to answer the question then I am using Sequelize and Postgres.
const { authenticate } = require('feathers-authentication').hooks;
const { queryWithCurrentUser } = require('feathers-authentication-hooks');
const { associateCurrentUser } = require('feathers-authentication-hooks');
const readRestrict = [
queryWithCurrentUser({
idField: 'id',
as: 'user_id'
})
];
const modRestrict = [
associateCurrentUser({
idField: 'id',
as: 'user_id'
})
];
module.exports = {
before: {
all: [ authenticate('jwt') ],
find: [ ...readRestrict ],
get: [ ...readRestrict ],
create: [ ...modRestrict ],
update: [ ...modRestrict ],
patch: [ ...modRestrict ],
remove: [ ...modRestrict ]
},
after: {
all: [],
find: [],
get: [],
create: [],
update: [],
patch: [],
remove: []
},
error: {
all: [],
find: [],
get: [],
create: [],
update: [],
patch: [],
remove: []
}
};
It seems to work but since I'm a Feathers noob I thought I'd better check before this is put into the wild to make sure there are no cases that I am unaware of that will cause leaks.
As a totoal beginner to feathers and express, I am unsure. Now, all works as stated above.
Old Answer
For remove, I used restrictToOwner. (I also think for patch and update because they operate on the existing data. I did not test that though.)
Otherwise I was able to cross-delete data by specifying the id. Maybe you can check if this is the case for you, too.
This is the test case:
user 1 creates an model object with
user id to check authorization
object id to identify the object
user 2 deletes the object with object id
test ok: 404 expected
test fail: 204 or 200 worked
user 1 tries to get the object
test ok: object is there, 200
test fail: object is absent, 404
Test code:
test_cannot_cross_delete
Thank you very much, you post was really helpful to me!

Azure Storage Table Query - result vs response

I'm using node.js as my Server and have an account on Azure where my storage table resides. I'm retrieving all records for a specific partition by using the following :
var query= new azure.TableQuery().where('PartitionKey eq ?',username);
tableSvc.queryEntities(localTableName,query, null, function(error, result, response) {
}
When this call comes back, I want to access the values for the rest of the fields of table. But when I do that using result.entries, it kinda looks weird. Alternatively I think I can access the results via response.body.value.userID.
Here is how the structure of "result.entries" vs "response" object looks like:
result.entries :
[ { PartitionKey: { '$': 'Edm.String', _: '048tfbne' },
RowKey: { '$': 'Edm.String', _: '145610564488450166' },
Timestamp:
{ '$': 'Edm.DateTime',
_: Mon Feb 22 2016 01:47:26 GMT+0000 (UTC) },
username: { _: '048tfbne' },
userID: { _: '145610564488450166' },
deleteAfter: { _: 'not set yet' },
'.metadata': { etag: 'W/"datetime\'2016-02-22T01%3A47%3A26.4394133Z\'"' } } ]
response :
{ isSuccessful: true,
statusCode: 200,
body:
{ 'odata.metadata': 'https://photoshareuserdata.table.core.windows.net/$metadata#userIdentifier',
value:
[ { 'odata.etag': 'W/"datetime\'2016-02-22T01%3A47%3A26.4394133Z\'"',
PartitionKey: '048tfbne',
RowKey: '145610564488450166',
Timestamp: '2016-02-22T01:47:26.4394133Z',
username: '048tfbne',
userID: '145610564488450166',
deleteAfter: 'not set yet' } ] },
I thought results.entries would be a better way to access the records, but I am sort of weirded out by the nested objects and Edm.String here.
Which is a better way to access the records ?
Table Node Sample shows how to access entities in a table as result of a query. See method "runPageQuery".
Actually, according the official Section: Query a set of entities, there is a paragraph as following:
If successful, result.entries will contain an array of entities that match the query. If the query was unable to return all entities, result.continuationToken will be non-null and can be used as the third parameter of queryEntities to retrieve more results.
And we also can refer to the sample at Azure-storage-for-node repository on GitHub. Which has told us the answer.

Resources