I'm having an interesting challenge and can't figure out how to go about solving it. I'm pulling a list of subscribers from my mailchimp and populating a members' page on my website with the data. One of the field in my sign up for says, "Website or LinkedIn profile url."
What I'd like to do is, check if they have provided a linkedin address, and if so drop their url in the linkedin member plugin, if not use the other data to create a simpler profile, name website, headline etc.
My problem is I can't say if data.websiteField.match(/linkedin/) within jade, so I either need to pass the data to some client side javascript which I'm having trouble with or do something else.
Here's a sample of data returned from mailchimp
[ // this first bit is just the fields
[
"email address",
"first name",
"last name",
"role",
"organization",
"headline",
"website",
"areas of interest",
"please email me about:",
"member_rating",
"optin_time",
"optin_ip",
"confirm_time",
"confirm_ip",
"latitude",
"longitude",
"gmtoff",
"dstoff",
"timezone",
"cc",
"region",
"last_changed"
],
[ // and here's the first user
"woop#booomshakala.com", // haha, just hiding some data
"Woop",
"Shak",
"Tester",
"ShakaCo",
"Whooooooper",
"http://linkedin.com/in/costamichailidis", // hit me up sometime
"Creativity, Innovation, Ideas and Science",
"Job Placement, Internships, Recruitment & Retention, Technology & MOOCs, Measurement & Evaluation, Documentation & Dissemination",
2,
"2013-03-28 19:28:55",
"173.52.122.111",
"2013-03-28 19:29:12",
"173.52.122.111",
"40.7648000",
"-73.7775000",
"-5",
"-4",
"America/New_York", "US", "NY", "2013-03-28 19:29:12"
]
]
Any help would rock!
Also, I'm using express. Does express make locals available in client side javascript?
Client Side Regex
Jade allows you execute arbitrary javascript using the - modifier at the start of the line
- if (profile.websiteField.match(/linkedin/)
// render linkedin profile here
- else
// render simple profile here
Server Side Regex
I think it would be simpler to format the profile information server-side and set a renderLinkedIn boolean field to true or false
function displaySignUpPage(req, res) {
var profile = formatMailChimpData()
// profile now looks like
// {
// "email address": "woop#booomshakala.com",
// "first name": "Noah",
// ...
// }
var linkedInRegex = /linkedin/;
profile.renderLinkedIn = linkedInRegex.test(profile.website) // set renderLinkedIn to true or false
// say your jade view is called signUpPage.jade
var pageData = {
title: 'Register',
profile: profile
}
res.render('signUpPage', pageData)
}
function formatMailChimpData() {
var mailChimpData = [
[
"email address",
"first name",
"last name",
"role",
"organization",
"headline",
"website"
// other fields truncated
],
[
"woop#booomshakala.com", // haha, just hiding some data
"Noah",
"Isaacson",
"Tester",
"ShakaCo",
"Whooooooper",
"http://www.linkedin.com/pub/noah-isaacson/59/6a2/553"
]
]
// mailChimp puts the keys as the first entry
var mailChimpFields = mailChimpData[0]
var mailChimpProfile = mailChimpData[1]
// make profile into key-value pairs
var keyValuePairs = mailChimpFields.map(function (field, index) {
var profileValue = mailChimpProfile[index]
var keyValuePair = [field, profileValue]
return keyValuePair
})
var profile = keyValuePairs.reduce(function(prev, pair) {
var key = pair[0]
var value = pair[1]
prev[key] = value
return prev
}, {})
return profile
}
Related
i have an array of nested objects that give each user a permission.
const UserList = [{
0: {
users: {
"email": "user1#gmail.com"
},
permission: {
"id": 1,
"access": "Edit"
}
},
1: {
users: {
"email": "user2#gmail.com"
},
permission: {
"id": 2,
"access": "Read Only"
}
},
2: {
users: {
"email": "user3#gmail.com"
},
permission: {
"id": 1,
"access": "Edit"
}
},
}]
My problem: I want to be able to match a email string to the email in the object and then grab object with the access "read only'. This is all to disable a button. So if the current user's email matches one in the object and the access equals "read only" then pull it out. Im not sure if i want to create a function/prop for this condition but the disable button is in another file.
So lets say this is my email
const myEmail = user2#gmail.com. How do i compare it to UserList and create that condition above. Then transfer it to a button in another file <button disabled={solution goes here}></button>
Edit: I want to find the object that has the current users email, then if that object's access = read only, then disable.
Maybe a .include(myEmail)? Not sure
Thanks for your help!
You can use Object.values(UserList) to get an array with just the values (the user object in this case). Then you can use that list to do your rendering (seems you are using react), so you can just map over the list, and then use the information to check whether a value is `Read Only" etc.
in your HTML, that looks something like:
<button disabled={userObj.permissions.access !== "Read Only"}>
I am not quite following the question about matching email strings.
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.
I am working on a function to send emails to users, I already have my send mail function and it sends to a single user. I am trying to send to multiple users in an array now.
I am writing in Typescript and I am using mailgun as my email service provider
This is a sample send mail function:
const data = {
from: 'example#from.com',
to: 'example#reciever.com',
subject: 'Sample subject',
html: await email(), // I am getting the email template here
}
await mailgun.messages().send(data)
With the code above, I am sending email to a single user. The json below shows how I am receiving the list of emails:
[
{
"name": "User 1",
"email": "user1#gmail.com"
},
{
"name": "user 2",
"email": "user2#gmail.com"
}
]
I want to be able to send to multiple users and I want to do it the smart way. Please suggest the best solution with code if possible.
Thank you.
Assuming the send function is async and returns a promise:
async function sendMail(){
const myRecipients = [
{
"name": "User 1",
"email": "user1#gmail.com"
},
{
"name": "user 2",
"email": "user2#gmail.com"
}
]
const fromAddress = "my#email.address"
// map our recipient array to the message format expected by `send`
const myMessages = myRecipients.map(r => ({
from: fromAddress,
to: r.email,
subject: "somesubject",
html: "some html"
}))
// map our messages to a bunch of "in-flight" promises
const promises = myMessages.map(m => mailgun.messages().send(m))
// wait for all the promises to complete
await Promise.all(promises)
}
I assume you're using mailgun-js, which seems to have something called mailing list which you possibly could utilize. If not, then I would suggest that rather than simply iterating the users list and sending one email at the time (synchronously with await), trigger all emails to be sent asynchronously and then use Promise.all to know when all has been sent. Sample below is by no means tested (as i've never used mailgun) but it should give you an idea on how to implement it.
const users = [
{
"name": "User 1",
"email": "user1#gmail.com"
},
{
"name": "user 2",
"email": "user2#gmail.com"
}
];
const sendEmailToUser = async (user) => {
const data = {
from: 'example#from.com',
to: 'example#reciever.com',
subject: 'Sample subject',
html: 'await email()'
};
await mailgun.messages().send(data);
};
(async () => {
const sendEmailPromises = [];
for(const user of users) {
// Start sending all emails
sendEmailPromises.push(sendEmailToUser(user));
}
// Wait for all emails to be sent
await Promise.all(sendEmailPromises);
// Do something
})()
You will have to iterate the data structure anyway.
var users = [
{
"name": "User 1",
"email": "user1#gmail.com"
},
{
"name": "user 2",
"email": "user2#gmail.com"
}
];
users.forEach(function(user){
name = user.name;
email = user.email;
var data = {
from: 'example#from.com',
to: email,
subject: 'Sample subject',
html: await email(),
}
await mailgun.messages().send(data);
});
use a array map
i dont know about typescript.
you can get all elements like this
for ES6
user_list.map(user => console.log(user.name, user.email))
I have quite an interesting question (I hope) for all you AngularJS gurus out there. I am looking to create a dynamic list of form input fields based on a SELECT dropdown. As an example, we have a number of categories with each category having a set of specifications which are unique to that category. To help with the explanation we have the following:
Firstly, in the controller we start by initializing the models.
$scope.category = {};
$scope.category.specs = [];
Next we ready the data to be used in the form (actually retrieved from the server via $http). We also initialize a variable to the first element in the categories array.
$scope.categories = [
{ "id": "1", "name": "mobile", specs: [
{ "id": "1", "label": "Operating System" },
{ "id": "2", "label": "Camera type" } ] },
{ "id": "2", "name": "laptop", specs: [
{ "id": "1", "label": "Operating System" },
{ "id": "2", "label": "Graphics Card" } ] }
};
$scope.selectedCategory = $scope.categories[0];
In the form, we have a dropdown which when selected loads the appropriate input fields specific to that category. We use the ngRepeat directive to accomplish this. This is a dynamic list of fields based on $scope.categories.specs. (please note the ???)
<select ng-model="selectedCategory" ng-options="category.name for category in categories"></select>
<div ng-repeat="spec in selectedCategory.specs">
<label>{{spec.label}}</label>
<input type="text" ng-model="???">
</div>
Ultimately, when the user clicks the submit button, we would like to extract the category he/she has selected and then package it together with the specifications they have filled in. The post request should contain something like the following for instance (of course, I only included one spec item, but in reality there would be many):
{ "id": "1", specs [ { "id": "2", "details": "RADEON HD 8970M" } ] }
Unfortunately I am not really sure how to accomplish this. I need to somehow create an array for the spec model, and then ensure that both the ID and user entered data are appropriately extracted... what goes in the ??? and what do we do after? Any help would be much appreciated.
this is how I do it. I make a form, validate it with angular, and then when its valid I submit it with a function.
<form name="signup_form" novalidate ng-submit="signupForm()"></form>
$scope.signupForm = function() {
var data = $scope.signup;
$http({
method : 'POST',
url : 'http://yoursite.com/mail.php',
data : $.param(data), // pass in data as strings
headers : { 'Content-Type': 'application/x-www-form-urlencoded' } // set the headers so angular passing info as form data (not request payload)
})
.success(function(data) {
});
}
also if you want to look at another form validation system for angular check out http://nimbly.github.io/angular-formly/#!/ It may help you solve your current form system.
In the controller, initialize $scope.specDetails as follows:
$scope.specDetails = {};
angular.forEach($scope.categories, function (category, index1) {
$scope.specDetails[category.id] = {};
angular.forEach(category.specs, function (spec, index2) {
$scope.specDetails[category.id][spec.id] = '';
});
});
In the html, replace "???" with specDetails[selectedCategory.id][spec.id]
How do we obtain an argument from QueryString and then apply this to the JSON object.I have the following JS file, I would like to update the dashboard-metrics-target elements on fly on basis of querystring.. "target": "sumSeries(SERVER1.metric)", must be changed to SERVER2.metric on fly using the given template.
ex.. http://testdashabord.com/sla-network.incoming.bytes-2013.11.02/logs/test&server=192.168.1.103 must obtain my metrics for '192.168.1.103'
var graphite_url = "demo"; // enter your graphite url, e.g. http://your.graphite.com
var dashboards =
[
{ "name": "Users", // give your dashboard a name (required!)
"refresh": 5000, // each dashboard has its own refresh interval (in ms)
,
"metrics": // metrics is an array of charts on the dashboard
[
{
"alias": "signups", // display name for this metric
"target": "sumSeries(SERVER1.metric)", // enter your graphite barebone target expression here
"description": "New signups to the website", // enter your metric description here
"summary": "sum", // available options: [sum|min|max|avg|last|<function>]
"summary_formatter": d3.format(",f"), // customize your summary format function. see d3 formatting docs for more options
},
{
"alias": "signup breakdown",
"target": "sumSeries(stats.*.event)", // target can use any graphite-supported wildcards
"description": "signup breakdown based on site location",
"renderer": "area", // use any rickshaw-supported renderer
"unstack": true // other parameters like unstack, interpolation, stroke are also available (see rickshaw documentation for more info)
"colspan": 3 // the graph can span across 1,2 or 3 columns
},
]
}, ...
My Approach:
..1. Obtain the parameter from URL
var first = getUrlVars()["server"];
function getUrlVars() {
var vars = {};
var parts = window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(m,key,value) {
vars[key] = value;
});
return vars;
}
..2. Update the elements of the array.
I would be thankful if a better approach is suggested.
Thanks