nodejs encoding to base64 string is not working - javascript

I am trying to send a calendar event as an attachment (.ics) file in nodejs.
I am using ical-generator library to create an event.
The code below is generating an .ics file and attaching it with the email but file always comes as empty.
I am not sure why the event content is not converting to base64. when I log the converted content it shows the same content (not converting to base64)
const cal = ical({ domain: "github.com", name: "my first iCal" });
// overwrite domain
cal.domain("example.net");
cal.createEvent({
start: moment(),
end: moment().add(1, "hour"),
summary: "Example Event",
description: "It works ;)",
location: "my room",
url: "http://example.net/",
});
console.log('result :', cal.toString("base64"));
// result :
BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//example.net//ical-generator//EN
NAME:my first iCal
X-WR-CALNAME:my first iCal
BEGIN:VEVENT
UID:000-tnmyae#example.net
SEQUENCE:0
DTSTAMP:20210403T212902Z
DTSTART:20210403T212902Z
DTEND:20210403T222902Z
SUMMARY:Example Event
LOCATION:my room
DESCRIPTION:It works \;)
URL;VALUE=URI:http://example.net/
END:VEVENT
END:VCALENDAR
var message = {
html: emailBody,
subject: "test",
from_email: "from email",
from_name: "sender name",
to: [
{
email: "receiver email",
},
],
tags: ["test"],
attachments: [
{
type: "text/calendar",
content: cal.toString("base64"),
name: "fileName.ics",
},
],
};
I found this encoded to base64 content from the other thread and it works just fine. "QkVHSU46VkNBTEVOREFSDQpWRVJTSU9OOjIuMA0KUFJPRElEOi0vL01lZXRlci9tZWV0ZXIvL05PTlNHTUwgdjEuMC8vRU4NCkNBTFNDQUxFOkdSRUdPUklBTg0KTUVUSE9EOlJFUVVFU1QNCkJFR0lOOlZFVkVOVA0KRFRTVEFSVDoyMDE0MTAxOFQyMDMwMDBaDQpEVEVORDoyMDE0MTAxOFQyMTAwMDBaDQpVSUQ6MjAxNDEwMTVUMDAyODEzLTIyMzc4ODg2OEBtZWV0ZXIuY29tDQpEVFNUQU1QOjIwMTQxMDE0VDIxMjgxM1oNCk9SR0FOSVpFUjtDTj0ic25hZ2dzQGdtYWlsLmNvbSI7U0VOVC1CWT0iTUFJTFRPOnNvbWVhcHBAZ21haWwuY29tIjtMQU5HVUFHRT1zZTpNQUlMVE86c25hZ2dzQGdtYWlsLmNvbQ0KQVRURU5ERUU7Q1VUWVBFPUlORElWSURVQUw7Uk9MRT1SRVEtUEFSVElDSVBBTlQ7UEFSVFNUQVQ9TkVFRFMtQUNUSU9OO1JTVlA9VFJVRTtDTj1GZXNzeSBNO1gtTlVNLUdVRVNUUz0wOk1BSUxUTzpzbmFnZ3MyQGdtYWlsLmNvbQ0KREVTQ1JJUFRJT046ZGRkZCBtYW5kcmlsbA0KTE9DQVRJT046ZGRkZGRkIG1hbmRyaWxsDQpTVU1NQVJZOkNhbiBJIGxheSBsb3c/IENvb2sgc29tZSB5YXkteW8gMg0KVFJBTlNQOk9QQVFVRQ0KU0VRVUVOQ0U6MA0KU1RBVFVTOkNPTkZJUk1FRA0KRU5EOlZFVkVOVA0KRU5EOlZDQUxFTkRBUg=="
If I try abover encoded string, my calendar event works fine. the file.ics also works fine.. so my guess is problem while converting that event content to base64.

The ical-generator package's calendar class doesn't provide a toString() which takes the format as the parameter, like Buffer. You'll just need to convert it to Base 64 like you'd convert any other string.
const calStr = cal.toString()
const calB64 = Buffer.from(calStr).toString('base64')
console.log('result :', calB64);

Related

Extract specific variables from a mixed string/JSON data

I am using Tagify with a custom AngularJS directive that I built, Tagify mixed input returns the JSON objects of selected tags and text in one single string, for example:
var tagify = new Tagify(myElement, {
mode: 'mix',
pattern: /#/,
whitelist: [{ value: "User Name", code: '$name' }, { value: "Phone Number", code: '$phone' }],
enforceWhitelist: true,
dropdown: {
maxItems: 20,
classname: "tags-look",
enabled: 0,
closeOnSelect: true
}
});
tagify.on('change', () => console.log(tagify.DOM.input.value))
The user input would be:
Hello User Name ×, the SMS has been sent to your phone Phone Number ×.
This simple example returns:
Hello [[{ value: "User Name", code: '$name' }]], the SMS has been
sent to your phone [[{ value: "Phone Number", code: '$phone' }]].
(and the JSON returned is escaped)
What I am doing later is replacing the tags that the user selected (by typing the # character and selecting them from the dropdown) with my own dynamic variables.
I was able to get a nice result with tagify.DOM.input.textContent as it rendered the following result:
Hello User Name, the SMS has been sent to your phone Phone Number.
However, since the whitelist is translatable and can be in other languages that I can't find and replace easily later, what I need is the code attribute from the JSON whitelist and not the value. The expected result that I couldn't find a way to reach yet is:
Hello $name, the SMS has been sent to your phone $phone.
Thanks.
You can create your custom transform function, to transform it the way you like, you can do something like this.
function transformer(value) {
return value.replace(/\[\[(.*?)\]\]/g, (arr => {
let json = JSON.parse(arr);
return json[0].map(e => e.code).join(', ');
}))
}
And then you can call it on change (or rather on/or before submit), like this:
tagify.on('change', (e) => transformer(e.detail.value));

MS Teams adaptive card "herocard" not work on mobile

I`m creating bot for MS Teams and using JS Microsoft Bot Framework V4 SDK.
In my work, I use search message extension and to work with it, I implemented the onSelectItem method that returns a adaptive card. I will give an example of the code below.
return Promise.resolve({
type: "result",
attachmentLayout: "list",
attachments: [CardFactory.heroCard(
`${file.name}`,
`${text}`,
undefined,
CardFactory.actions([
{
type: "openUrl",
title: "Open",
value: `${openLink}`
},
{
type: "openUrl",
title: "Download",
value: `${downloadLink}`
},
]),
)]
});
Where I pass undefined, this should be the path to the picture, but in my implementation I don't need it. So and this code works great in the browser and on the desktop version here is a screenshot
however, on the mobile version, I get the following result
this is absolutely not the right card, it has no content or buttons
I think I found the answer myself. When the message extension search is triggered, the onQuery method is called and suppose you made a query and received an array of values ​​that you want to display. And here, in the same method, iterating over the array, you must draw two cards at once. For example
files.forEach((file: IDocumentInfo): void => {
const card: any = CardFactory.heroCard(
cutString(file.name, LIMIT),
text,
undefined,
[
{
type: "openUrl",
title: "Open",
value: "", // some value
},
{
type: "openUrl",
title: "Download",
value: "" //some value,
},
]
);
const preview: any = {
contentType: "application/vnd.microsoft.card.thumbnail",
content: {
title: `${cutString(file.name, LIMIT)}`,
text: "", // some text
}
};
And here the variable preview in my case will respond to a small view of information after the search and the variable card will be responsible for the view after selection. And after the card is selected, the onSelectItem method is triggered, which I need to get more information about the document
It turns out that the adaptive heroCard is not to blame here, the onSelectItem method is not called in the mobile application, or I am doing something wrong

webauthn authentication javascript formatting assistance

I have been trying to figure out how to do 2fa with webauthn and I have the registration part working. The details are really poorly documented, especially all of the encoding payloads in javascript. I am able to register a device to a user, but I am not able to authenticate with that device. For reference, I'm using these resources:
https://github.com/cedarcode/webauthn-ruby
https://www.passwordless.dev/js/mfa.register.js
And specifically, for authentication, I'm trying to mimic this js functionality:
https://www.passwordless.dev/js/mfa.register.js
In my user model, I have a webauthn_id, and several u2f devices, each of which has a public_key and a webauthn_id.
In my Rails app, I do:
options = WebAuthn::Credential.options_for_get(allow: :webauthn_id)
session[:webauthn_options] = options
In my javascript, I try to mimic the js file above and I do (this is embedded ruby):
options = <%= raw #options.as_json.to_json %>
options.challenge = WebAuthnHelpers.coerceToArrayBuffer(options.challenge);
options.allowCredentials = options.allowCredentials.map((c) => {
c.id = WebAuthnHelpers.coerceToArrayBuffer(c.id);
return c;
});
navigator.credentials.get({ "publicKey": options }).then(function (credentialInfoAssertion)
{
// send assertion response back to the server
// to proceed with the control of the credential
alert('here');
}).catch(function (err)
{
debugger
console.error(err); /* THIS IS WHERE THE ERROR IS THROWN */
});
The problem is, I cannot get past navigator.credentials.get, I get this error in the javascript console:
TypeError: CredentialsContainer.get: Element of 'allowCredentials' member of PublicKeyCredentialRequestOptions can't be converted to a dictionary
options at the time navigator.credentials.get is called looks like this:
I've tried every which way to convert my db-stored user and device variables into javascript properly encoded and parsed variables but cannot seem to get it to work. Anything obvious about what I'm doing wrong?
Thanks for any help,
Kevin
UPDATE -
Adding options json generated by the server:
"{\"challenge\":\"SSDYi4I7kRWt5wc5KjuAvgJ3dsQhjy7IPOJ0hvR5tMg\",\"timeout\":120000,\"allowCredentials\":[{\"type\":\"public-key\",\"id\":\"OUckfxGNLGGASUfGiX-1_8FzehlXh3fKvJ98tm59mVukJkKb_CGk1avnorL4sQQASVO9aGqmgn01jf629Jt0Z0SmBpDKd9sL1T5Z9loDrkLTTCIzrIRqhwPC6yrkfBFi\"},{\"type\":\"public-key\",\"id\":\"Fj5T-WPmEMTz139mY-Vo0DTfsNmjwy_mUx6jn5rUEPx-LsY51mxNYidprJ39_cHeAOieg-W12X47iJm42K0Tsixj4_Fl6KjdgYoxQtEYsNF-LPhwtoKwYsy1hZgVojp3\"}]}"
This is an example of the serialised JSON data returned by our implementation:
{
"challenge": "MQ1S8MBSU0M2kiJqJD8wnQ",
"timeout": 60000,
"rpId": "identity.acme.com",
"allowCredentials": [
{
"type": "public-key",
"id": "k5Ti8dLdko1GANsBT-_NZ5L_-8j_8TnoNOYe8mUcs4o",
"transports": [
"internal"
]
},
{
"type": "public-key",
"id": "LAqkKEO99XPCQ7fsUa3stz7K76A_mE5dQwX4S3QS6jdbI9ttSn9Hu37BA31JUGXqgyhTtskL5obe6uZxitbIfA",
"transports": [
"usb"
]
},
{
"type": "public-key",
"id": "nbN3S08Wv2GElRsW9AmK70J1INEpwIywQcOl6rp_DWLm4mcQiH96TmAXSrZRHciZBENVB9rJdE94HPHbeVjtZg",
"transports": [
"usb"
]
}
],
"userVerification": "discouraged",
"extensions": {
"txAuthSimple": "Sign in to your ACME account",
"exts": true,
"uvi": true,
"loc": true,
"uvm": true
}
}
This is parsed to an object and the code used to coerce those base64url encoded values is:
credentialRequestOptions.challenge = WebAuthnHelpers.coerceToArrayBuffer(credentialRequestOptions.challenge);
credentialRequestOptions.allowCredentials = credentialRequestOptions.allowCredentials.map((c) => {
c.id = WebAuthnHelpers.coerceToArrayBuffer(c.id);
return c;
});
Hope that helps. The JSON data is retreived via a fetch() call and the byte[] fields are encoded as base64url on the serverside.

swagger array of objects not validating in nodejs

I have a swagger.yaml file in nodejs application given below
/updateuser/{userId}:
x-swagger-router-controller: User
put:
tags:
- User
summary: Update User
description: Update User
operationId: updateUser
parameters:
- name: userId
in: path
description: userId for which subscription needs to be updated
type: string
required: true
- name: subData
in: body
description: Subscription To be updated
schema:
type: array
items:
$ref: "#/definitions/userDataInput"
responses:
"200":
description: Success
schema:
$ref: "#/definitions/Response"
"500":
description: Error
schema:
$ref: "#/definitions/ErrorResponse"
definitions:
userDataInput:
required:
- productId
- subscriptionId
properties:
productId:
type: string
subscriptionId:
type: string
Now I'm validating subData in my user controller using nodejs module swagger-model-validator for example given below code
var yaml = require('js-yaml')
var fs = require('fs')
var swaggerObject
try {
swaggerObject = yaml.safeLoad(fs.readFileSync('swagger.yaml'), 'utf8')
} catch (err) {
// Error here
}
var Validator = require('swagger-model-validator')
var validator = new Validator(swaggerObject)
var validation = validator.swagger.validateModel('subData', body,
false, true)
if (validation.valid) {
// logic here
} else {
// show error
}
User will call this API like PUT /updateuser/{userId} and body parameter
subData
[{
"userId": "DSHS333FHFHD",
"productId": "465454445",
},
"userId": "RYY48433FHFHD",
"productId": "435654125",
}
]
But the problem is, it is not validating array of objects userDataInput, I have given productId and subscriptionId required field, if I omit productId it's not giving any error and also if put some extra field for ex productId1 it's not validating also. Any help.
I think the problem is in the Swagger Object you are creating. You might be better off using the validator directly and passing in your models manually.
validator.validate(object, swaggerModel, swaggerModels, allowBlankTarget, disallowExtraProperties);
You appear to be passing in the Swagger Definition and not the swagger client which generally has already decoded your definition.
The swaggerModel would be your subData schema section and the swaggerModels would be your definitions section.

how to generate thumbnail image given the url?

For the application I am currently building, there is a dataset of links associated with certain customer profiles and the user receives a list, which looks like the following:
function getList(customItems){
var messageData = {
recipient: {
id: recipientId
},
message: {
attachment: {
type: "template",
payload: {
template_type: "generic",
elements: []
}
}
}
};
customItems.forEach(function(item) {
var url = item._id;
var listItem = {
title: item.title,
subtitle: "",
item_url: url,
image_url: "http://random.image.com",
buttons: [{
type: "postback",
title: "Get other items",
payload: "TEST",
}]
};
messageData.message.attachment.payload.elements.push(listItem);
Anyway, I would like to generate some image from given url the same way it appears in messenger if the link is pasted directly into the text box and haven't figured out yet how to do it. Also, by the way, if I try to display some random image for testing purpposes (http://random.image.com replaced by some valid image url), the image doesn't appear.
Does anyone know how to generate images to be displayed for given urls dynamically?
You either have to implement your own (or open source) thumbnail image processor (with something like ImageMagick, GraphicsMagick, G'MIC, gd, PhantomJS + HTML5 Canvas), or use a SaaS solution like imgix.com

Categories