Use update handler for document delete - couchdb

I need to delete a document from CouchDB, but first I need to check if a condition is met. The first thing that comes to mind is using an update handler instead, iterating manually over all keys in the update handler and deleting those without a _ prefix and setting the _delete field to true.
I guess this should produce the same result as a normal DELETE, am I right?
Update:
Using #Kxepal's suggestion, this is what the update handler looks like:
function (doc, req) {
if (req.query.account_id != doc.account_id) {
return [doc, '{"error": "invalid account id"}'];
}
return [{
_id: doc._id,
_rev: doc._rev,
_deleted: true
}, 'ok'];
}

Not really.
When you DELETE document, CouchDB removes any fields from it except _id and _rev (sure, _deleted is also there). This information is also known as tombstone.
When you just adds _deleted: true to document, it becomes marked as deleted, but all other fields are still there:
http --json http://localhost:5984/recipes/SpaghettiWithMeatballs:
HTTP/1.1 404 Object Not Found
Cache-Control: must-revalidate
Content-Length: 41
Content-Type: application/json
Date: Sat, 17 Aug 2013 14:49:17 GMT
Server: CouchDB/1.4.0+build.c843cef (Erlang OTP/R16B)
{
"error": "not_found",
"reason": "deleted"
}
http --json http://localhost:5984/recipes/SpaghettiWithMeatballs\?rev\=9-ac84157c2206793b7d142f5d8e2c97d0:
HTTP/1.1 200 OK
Cache-Control: must-revalidate
Content-Length: 425
Content-Type: application/json
Date: Sat, 17 Aug 2013 14:48:55 GMT
ETag: "9-ac84157c2206793b7d142f5d8e2c97d0"
Server: CouchDB/1.4.0+build.c843cef (Erlang OTP/R16B)
{
"_attachments": {
"my_recipe.txt": {
"content_type": "text/plain",
"digest": "md5-198BPPNiT5fqlLxoYYbjBA==",
"length": 85,
"revpos": 2,
"stub": true
}
},
"_deleted": true,
"_id": "SpaghettiWithMeatballs",
"_rev": "9-ac84157c2206793b7d142f5d8e2c97d0",
"description": "An Italian-American dish that usually consists of spaghetti, tomato sauce and meatballs.",
"ingredients": [
"spaghetti",
"tomato sauce",
"meatballs"
],
"name": "Spaghetti with meatballs"
}
However, during compaction, this document will be converted to tombstone with only _id, _rev and _deleted fields. Until then, this is good trick to keep data within document to easily undo delete operation without requesting document's previous revision since all content available for the latest one.

Related

Which method would be more appropriate here POST or PATCH?

Let's say I have a db collection with users and I want to ADD an object to an array inside one document.
It was like this:
{
_id: "636e8e1dd710eed71565741c",
username: "test",
password: "$2b$10$/s9.kRYSax380Xrxf3xyVO9Z6Otc/WVx5kBSLKfu43/wYP.TSnzvW",
tasks: [{name: task1, status: "finished"}]
}
And I am going to make it look like this:
{
_id: "636e8e1dd710eed71565741c",
username: "test",
password: "$2b$10$/s9.kRYSax380Xrxf3xyVO9Z6Otc/WVx5kBSLKfu43/wYP.TSnzvW",
tasks: [{name: task1, status: "finished"}, {name: task2, status: "unfinished"}]
}
So which method would be more appropriate here since I'm adding a new object to an embedded array and not updating one which already exists? Thank you.
The choice between POST and PATCH depends on the path of the URL. If the path contains the _id, I'd prefer
POST /collection/636e8e1dd710eed71565741c/tasks
Content-Type: application/json
{"name": "task2", "status": "unfinished"}
However, if the _id is part of the payload, I'd prefer
PATCH /collection
Content-Type: application/json
{"_id": "636e8e1dd710eed71565741c",
"tasks#add": [{"name": "task2", "status": "unfinished"}]}
But this payload format relies on "naming conventions":
The _id serves to identify the entry to be patched.
The suffix #add means that the tasks are added to the existing array.
"tasks#change": [{"name": "task1", "status": "archived"}] would instead update the existing task.
If the server knows that each task is identified by its name, the suffixes would not be necessary:
PATCH /collection
Content-Type: application/json
{"_id": "636e8e1dd710eed71565741c",
"tasks": [{"name": "task1", "status": "archived"},
{"name": "task2", "status": "unfinished"}]}
updates the existing task and adds a new one. Or even
PATCH /collection/636e8e1dd710eed71565741c/tasks
Content-Type: application/json
[{"name": "task1", "status": "archived"},
{"name": "task2", "status": "unfinished"}]
I hope these examples help you find a suitable pattern.

Why is the output format from "Get file content using path" different for two different docs?

I'm using the action "Get file content using path" and I'm getting very different results for 2 different *.docx files which is causing problems when trying to use the output in a subsequent action.
In the one that's working properly, I get the expected output with "$content-type" and "$content" like so...
{
"$content-type": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
"$content": "UEsDBBQABgAIAA... blah blah blah"
}
In the one that's not working properly, I'm getting a result back, but the format is...
{
"statusCode": 200,
"headers": {
"Vary": "Origin",
"X-SharePointHealthScore": "1",
"X-MS-SPConnector": "1",
"X-SP-SERVERSTATE": "ReadOnly=0",
"DATASERVICEVERSION": "3.0",
"SPClientServiceRequestDuration": "65",
:
"X-AspNet-Version": "4.0.30319",
"X-Powered-By": "ASP.NET",
"Content-Length": "2670927",
"Content-Type": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
"Expires": "Wed, 22 Dec 2021 20:49:46 GMT",
"Last-Modified": "Thu, 06 Jan 2022 20:49:46 GMT"
},
"body": {
"$content-type": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
"$content": "UEsDBBQABgAIAAAAIQAIz... blah blah blah"
}
The issue is caused by $content being a child of the body node.
Both are *.docx files. So, why the difference in the output?
Why would one include the status code, headers, and body and the other just contains "$content-type" and "$content"?
So, I achieved the desired outcome by using a formula like such ...
if(equals(variables('JSON')?['$content'], null), variables('JSON')?['body']?['$content'], variables('JSON')?['$content'])
You just need to adapt the preceding actions to your own flow but this worked for me.
Basic Response
Extended Response

Creating a new SharePoint column using Graph REST API

I've been working on a function that puts a value in a list column if it exists. However, in the case that it doesn't exist (which I check using GET https://graph.microsoft.com/v1.0/drives/{driveID}/list/columns"), I'd like it to make a list column. How do I create a new column in SharePoint using Microsoft Graph's REST API? I've scoured the documentation but have thus far come up short.
Per the API documents, there is no such an endpoint to update a list. I believe the related functionality has not been released. You can submit the feedback on Microsoft Graph Feature Requests or turn to the old sharepoint rest api:
https://www.codesharepoint.com/rest-api/create-list-column-in-sharepoint-using-rest-api
HTTP :
POST https://graph.microsoft.com/v1.0/me/drive/items/{id}/workbook/tables/{id|name}/columns
Content-type: application/json
Content-length: 81
{
"id": 99,
"name": "name-value",
"index": 99,
"values": "values-value"
}
Response : HTTP
HTTP/1.1 201 Created
Content-type: application/json
Content-length: 81
{
"id": 99,
"name": "name-value",
"index": 99,
"values": "values-value"
}
Response :
If successful, this method returns 201 Created response code and WorkbookTableColumn object in the response body.
For more details : https://learn.microsoft.com/en-us/graph/api/table-post-columns?view=graph-rest-1.0&tabs=http

Creating a checkout session with a non-zero unit_amount_decimal returns an error message of a deprecated amount field

I seem to be experiencing an odd response behaviour from stripe when trying to create a checkout session if my unit_amount_decimal has a value of anything other than zero after the decimal.
Running this in postman (I've just replaced the key and urls for this example) where the unit_amount_decimal is 23.99 will give me an error response to do with a deprecated (according to their documentation) 'amount' field even though I'm not using that field in my POST:
POST /v1/checkout/sessions HTTP/1.1
Host: api.stripe.com
Authorization: Bearer sk_test_mytestenvironmentsecretkey
Content-Type: application/x-www-form-urlencoded
success_url=https://example.com/payment/success&cancel_url=https://example.com/payment/cancel&payment_method_types[0]=card&mode=subscription&line_items[0][quantity]=1&line_items[0][price_data][currency]=USD&line_items[0][price_data][product]=prod_HoG79Vj0HStdtG&line_items[0][price_data][unit_amount_decimal]=23.99&line_items[0][price_data][recurring][interval]=day&line_items[0][price_data][recurring][interval_count]=1&customer=cus_HoG7QB7kstWaWB
Response from Stripe will be:
{
"error": {
"message": "Checkout does not support plans with more than 2 decimals in the `amount` in `line_items[0]`.",
"param": "line_items[0]",
"type": "invalid_request_error"
}
}
If I do the same POST but change the unit_amount_decimal value to 23.00 / 23.0 / 23 for example, it's happy with the request and responds with a checkout session object:
POST /v1/checkout/sessions HTTP/1.1
Host: api.stripe.com
Authorization: Bearer sk_test_mytestenvironmentsecretkey
Content-Type: application/x-www-form-urlencoded
success_url=https://example.com/payment/success&cancel_url=https://example.com/payment/cancel&payment_method_types[0]=card&mode=subscription&line_items[0][quantity]=1&line_items[0][price_data][currency]=USD&line_items[0][price_data][product]=prod_HoG79Vj0HStdtG&line_items[0][price_data][unit_amount_decimal]=23.00&line_items[0][price_data][recurring][interval]=day&line_items[0][price_data][recurring][interval_count]=1&customer=cus_HoG7QB7kstWaWB
Response from Stripe:
{
"id": "cs_test_9FDuAIEyGuvb9RapQ0pOAs4240UHRhSqks1kezHYBhEaBX5tG59mOBqB",
"object": "checkout.session",
"allow_promotion_codes": null,
"amount_subtotal": 23,
"amount_total": 23,
"billing_address_collection": null,
"cancel_url": "https://example.com/payment/cancel",
"client_reference_id": null,
"currency": "usd",
"customer": "cus_HoG7QB7kstWaWB",
"customer_email": null,
"livemode": false,
"locale": null,
"metadata": {},
"mode": "subscription",
"payment_intent": null,
"payment_method_types": [
"card"
],
"setup_intent": null,
"shipping": null,
"shipping_address_collection": null,
"submit_type": null,
"subscription": null,
"success_url": "https://example.com/payment/success",
"total_details": {
"amount_discount": 0,
"amount_tax": 0
}
}
I've read the documentation around decimals amounts but haven't seen a reason why it wouldn't like a decimal amount with something other than a zero value after the decimal.
Is there anything obvious I'm doing incorrectly here? It doesn't make sense for me to be creating price objects before this POST in my scenario so I'm hoping I can just use this price_data to create a price object inline as their documentation suggests
I misread the documentation for decimal values - it's still for defining the minor unit (such as cents) which means me passing 23.99 still means 23.99 pence rather than £23.99 which is what I thought.
I've contacted Stripe support and they responded to say they don't support Prices with sub-cent amounts in Checkout (which is understandable). They have raised the issue and will be updating the documentation so the session object doesn't include the unit_amount_decimal property.

Envelope Recipient not matching when requesting view

When creating envelopes which are used later to generate a view URL for the signer to use instead of receiving an email, we are running into a problem where the user we are specifying isn't valid.
For example, here is an envelope with one recipient, "Peter Hughes Jr."
Request URL: https://na2.docusign.net/restapi/v2/accounts/4476693/envelopes/f3a45945-f1ff-4731-a407-963a32378d77/recipients
------
{"IntegratorKey":"***","Password":"***","Username":"onboarding#impellam.com"}
Request headers:
X-DocuSign-Authentication : {"IntegratorKey":"***","Password":"***","Username":"onboarding#impellam.com"}
Host : na2.docusign.net
Connection : Keep-Alive
------
Request body:
------
Response headers:
Strict-Transport-Security : max-age=7776000; includeSubDomains
Content-Length : 696
Cache-Control : no-cache
Content-Type : application/json; charset=utf-8
Date : Thu, 18 Dec 2014 15:26:42 GMT
------
Response body:
{
"signers": [
{
"name": "Peter Hughes Jr.",
"email": "pwhughes#verizon.net",
"recipientId": "1",
"recipientIdGuid": "2461be9a-69d3-420d-b5f3-2c327af2f5f6",
"requireIdLookup": "false",
"userId": "0d5035dc-b70f-4026-8283-5c8d8903385a",
"clientUserId": "1",
"routingOrder": "1",
"note": "",
"roleName": "Applicant",
"status": "sent",
"templateLocked": "false",
"templateRequired": "false"
}
],
"agents": [],
"editors": [],
"intermediaries": [],
"carbonCopies": [],
"certifiedDeliveries": [],
"inPersonSigners": [],
"recipientCount": "1",
"currentRoutingOrder": "1"
}
When we attempt to set up a view for this user, the following exception occurs:
Request URL: https://na2.docusign.net/restapi/v2/accounts/4476693/envelopes/f3a45945-f1ff-4731-a407-963a32378d77/views/recipient
------
{"IntegratorKey":"***","Password":"***","Username":"onboarding#impellam.com"}
------
EXCEPTION
System.Net.WebException: The remote server returned an error: (400) Bad Request.
at System.Net.HttpWebRequest.GetResponse()
at DocusignView.Request.Send[T](String body) in C:\Users\johnathank\Desktop\docusigntest\DocusignView.cs:line 293
------
Request headers:
X-DocuSign-Authentication : {"IntegratorKey":"***","Password":"***","Username":"onboarding#impellam.com"}
Content-Type : application/json
Host : na2.docusign.net
Content-Length : 143
Expect : 100-continue
------
Request body:
{"authenticationMethod":"email","clientUserId":"1","email":"pwhughes#verizon.net","returnUrl":"www.impellam.com","userName":"Peter Hughes Jr."}
------
Response headers:
Strict-Transport-Security : max-age=7776000; includeSubDomains
Content-Length : 152
Cache-Control : no-cache
Content-Type : application/json; charset=utf-8
Date : Thu, 18 Dec 2014 15:28:31 GMT
------
Response body:
{
"errorCode": "UNKNOWN_ENVELOPE_RECIPIENT",
"message": "The recipient you have identified is not a valid recipient of the specified envelope."
}
We've actually identified the problem, but haven't found a good way to implement a solution yet. When inspecting the envelope within Docusign, I can see that this user has adopted the name "Peter W. Hughes Jr".
So I attempted sending another view request with the name "Peter W. Hughes Jr." instead, and it worked...
However this poses a problem. How are we able to find out what the adopted name of the user is? It is not in the original envelope data, and from browsing the API at iodocs.docusign.com, none of the methods there seem to give me the user's adopted name.
I have read an alternate solution that says we can provide a userId in the view request instead of the userName, but when I attempt to do that, I receive an error indicating that userName is required.
Request URL: https://na2.docusign.net/restapi/v2/accounts/4476693/envelopes/f3a45945-f1ff-4731-a407-963a32378d77/views/recipient
------
{"IntegratorKey":"***","Password":"***","Username":"onboarding#impellam.com"}
------
EXCEPTION
System.Net.WebException: The remote server returned an error: (400) Bad Request.
at System.Net.HttpWebRequest.GetResponse()
at DocusignView.Request.Send[T](String body) in C:\Users\johnathank\Desktop\docusigntest\DocusignView.cs:line 295
------
Request headers:
X-DocuSign-Authentication : {"IntegratorKey":"***","Password":"***","Username":"onboarding#impellam.com"}
Content-Type : application/json
Host : na2.docusign.net
Content-Length : 191
Expect : 100-continue
------
Request body:
{"authenticationMethod":"email","clientUserId":"1","email":"pwhughes#verizon.net","returnUrl":"www.impellam.com","userId":"2461be9a-69d3-420d-b5f3-2c327af2f5f6","userName":"Peter Hughes Jr."}
------
Response headers:
Strict-Transport-Security : max-age=7776000; includeSubDomains
Content-Length : 167
Cache-Control : no-cache
Content-Type : application/json; charset=utf-8
Date : Thu, 18 Dec 2014 15:52:06 GMT
------
Response body:
{
"errorCode": "INVALID_REQUEST_PARAMETER",
"message": "The request contained at least one invalid parameter. A value was not found for parameter 'userName'."
}
This is only an issue when multiple envelopes are sent in flight to the same recipient name, email and clientUserId combination.
Once you send the recipienttoken and they sign with a different name, using the same request for the second envelope will fail because of the name change.
Best practice would be to generate a new clientUserId for each envelope or prevent the recipient from changing their name within the DocuSign Account Features. The feature is called "Signature Adoption Configuration".

Resources