This question already has an answer here:
How to extend lifetime of password, generated by ref.resetPassword()?
(1 answer)
Closed 6 years ago.
I'm using angularJS and firebase as backend to create my simple web app.
When .resetPassword() method is called, an email which contains a temporary password is sent to user, so he can login into an app.
According to the following resource, lifetime of the temporary password is 24 hours:
https://www.firebase.com/docs/web/api/firebase/resetpassword.html
So, I have a question - what happens after the temporary password expires? Is it just discarded and an old password can be used again?..
Thanks in advance
Basically you can change the users password, and then email it to him manually.. So lets say when they register to your app it becomes in the following order:
username---
Username
Password
Email
UID
So then when the user clicks on resetPassword you have to generate a random password, and send him a email... So first lets tackle sending the email:
First of register for Mandrill
1. register for Mandrill to get an API key
2. load jQuery
3. use $.ajax to send an email
So this is how it will be layed out :
function randomPassword(){
var length = 8,
charset = "abcdefghijklnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789",
retVal = "";
for (var i = 0, n = charset.length; i < length; ++i) {
retVal += charset.charAt(Math.floor(Math.random() * n));
}
return retVal;
}
Dont forget to add this to your script tag:
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
So you can send emails:
And:
$.ajax({
type: “POST”,
url: “https://mandrillapp.com/api/1.0/messages/send.json”,
data: {
‘key’: ‘YOUR API KEY HERE’,
‘message’: {
‘from_email’: ‘YOUR#EMAIL.HERE’,
‘to’: [
{
‘email’: ‘RECIPIENT_NO_1#EMAIL.HERE’,
‘name’: ‘RECIPIENT NAME (OPTIONAL)’,
‘type’: ‘to’
},
{
‘email’: ‘RECIPIENT_NO_2#EMAIL.HERE’,
‘name’: ‘ANOTHER RECIPIENT NAME (OPTIONAL)’,
‘type’: ‘to’
}
],
‘autotext’: ‘true’,
‘subject’: ‘Password generated’,
‘html’: ‘This is your Newly generated password’ + randomPassword
}
}
}).done(function(response) {
console.log(response);
});
More info on the sending email part here
If you are trying to do this only using firebase, that is not possible as frank said here: How to extend lifetime of password, generated by ref.resetPassword()?
Related
Using the google apis flutter package, I get back the email message object. For example, snippet is a property of this object. It returns a short plaintext of the email message. I would like to parse the email to return a plaintext. How do I parse the email message?
final list = await gmailApi.users.messages.list("me", maxResults: 10, q:"subject:receipt",);
for (var message in list.messages!) {
final m = await gmailApi.users.messages
.get(_currentUser!.id, message.id ?? "", format: "full");
final decoded = base64Url.decode(m.payload?.body?.data ?? "");
utf8.decode(decoded); // supposed to return plaintext (like m.snippet does) not html
}
I have a custom page, created with Shopify liquid -> https://shop.betterbody.co/pages/nazreen-joel-video-sales-letter-16-july
I have set the timer to load within 3seconds for the sales element to appear.
The question is, I would like to set an if/else condition to immediately show these sales element for repeat visitors. There is a timer.js that sets the time for the sales element to appear. If its a new visitor, timer will trigger, else server will not load the timer. I can't seem to find any solution online. Do I detect visitor IP? or is there any best solution to do this?
Here is the code inside theme.liquid,
{{ 'timer.js' | asset_url | script_tag }} .
Timer.js code:
$(document).ready(function(){
setTimeout(function() {
$(".refference").css({paddingTop: "350px"});
// $("#early-cta, #guarentee, #payments, #info, #details").show();
$("#early-cta, #guarentee, #payments, #info, #details").fadeIn(3000);
}, 3000);
});
Pls help.
You could look into localStorage to do this.
https://www.w3schools.com/htmL/html5_webstorage.asp
Localstorage is used to store data within the browser without any expiration date.
When a visitor visits the site for the first time, you could use localStorage to detect if the user has been to your site, if the user hasn’t, you run the timer, and set a variable that the user has visited.
Upon revisiting the site, you use localStorage and check against the variable to see if the user has been to your site or not, and trigger the script accordingly.
Expounding on #Jacob's answer and my comment, you can do what you need to do with JavaScript and localStorage.
So something like this to add:
function setVisited() {
// object to be added to localStorage
let obj = {
timestamp: new Date().getTime()
// add more stuff here if you need
// someValue: "foo",
// anotherValue: "bar"
}
// add object to localStorage
localStorage.setItem(
"hasVisited", // key that you will use to retrieve data
JSON.stringify(obj)
);
}
and something like this to retrieve:
function getVisited() {
return JSON.parse(localStorage.getItem("hasVisited"));
}
// returns: {timestamp: 1533398672593} or null
Also, as an additional condition to your event, you can choose to "expire" the user's localStorage value by checking the timestamp against the current timestamp and comparing it against a predefined expiration duration.
For example, if I wish to consider a visitor who has not returned 7 days as a new visitor:
let expiration = 86400 * 1000 * 7; // 7 days in milliseconds
function isNewVisitor() {
// get current timestamp
let timeNow = new Date().getTime();
let expired = true;
// if getVisited doesn't return null..
if (getVisited()) {
let timeDiff = timeNow - getVisited().timestamp;
expired = timeDiff > expiration;
}
// if the visitor is old and not expire, return true
if (!getVisited() || expired) {
return true;
} else {
return false;
}
}
So, to integrate with your current function, we will just check the condition before setting the timeout:
// let timeout be 3000 if the visitor is new
let timeout = isNewVisitor() ? 3000 : 0;
setTimeout(function() {
$(".refference").css({paddingTop: "350px"});
$("#early-cta, #guarentee, #payments, #info, #details").fadeIn(3000);
}, timeout);
// set the visited object for new visitors, update for old visitors
setVisited();
Check out the fiddle here: https://jsfiddle.net/fr9hjvc5/15/
How do I get the full message and not just the metadata using gmail api?
I have a service account and I am able to retrieve a message but only in the metadata, raw and minimal formats. How do I retrieve the full message in the full format? The following code works fine
var request = service.Users.Messages.Get(userId, messageId);
request.Format = UsersResource.MessagesResource.GetRequest.FormatEnum.Metadata;
Message message = request.Execute();
However, when I omit the format (hence I use the default format which is FULL) or I change the format to UsersResource.MessagesResource.GetRequest.FormatEnum.Full
I get the error: Metadata scope doesn't allow format FULL
I have included the following scopes:
https://www.googleapis.com/auth/gmail.readonly,
https://www.googleapis.com/auth/gmail.metadata,
https://www.googleapis.com/auth/gmail.modify,
https://mail.google.com/
How do I get the full message?
I had to remove the scope for the metadata to be able to get the full message format.
The user from the SO post have the same error.
Try this out first.
Go to https://security.google.com/settings/security/permissions
Choose the app you are working with.
Click Remove > OK
Next time, just request exactly which permissions you need.
Another thing, try to use gmailMessage.payload.parts[0].body.dataand to decode it into readable text, do the following from the SO post:
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.StringUtils;
System.out.println(StringUtils.newStringUtf8(Base64.decodeBase64(gmailMessage.payload.parts[0].body.data)));
You can also check this for further reference.
try something like this
public String getMessage(string user_id, string message_id)
{
Message temp =service.Users.Messages.Get(user_id,message_id).Execute();
var parts = temp.Payload.Parts;
string s = "";
foreach (var part in parts) {
byte[] data = FromBase64ForUrlString(part.Body.Data);
s += Encoding.UTF8.GetString(data);
}
return s
}
public static byte[] FromBase64ForUrlString(string base64ForUrlInput)
{
int padChars = (base64ForUrlInput.Length % 4) == 0 ? 0 : (4 - (base64ForUrlInput.Length % 4));
StringBuilder result = new StringBuilder(base64ForUrlInput, base64ForUrlInput.Length + padChars);
result.Append(String.Empty.PadRight(padChars, '='));
result.Replace('-', '+');
result.Replace('_', '/');
return Convert.FromBase64String(result.ToString());
}
How to write a angularjs code to check if the value passing is already exist in the array and if exists, user should be given access rights, if not, he should not be given rights
I think this should work
In your HTML you need to bind the ng-click with a button that will check the privilege and perform accordingly. Lets say the button is like this
<button type="button" ng-click="checkPrivilege();">Check Privilege</button>
Inside your controller you need to do some operations like this
//say, this is our privilege JSON
$scope.privilege = [
{
accessName: "ACCOUNT_ADD",
roles:['ADMIN','MANAGER']
},
{
accessName: "ACCOUNT_DELETE",
roles:['ADMIN']
}
];
$scope.checkPrivilege = function(){
//first you need to find out the role of the logged in user, lets say
//you get the role value from getLoggedInUserRole() function
$scope.userRole = getLoggedInUserRole();
//lets say the selected access name is 'ACCOUNT_ADD'
$scope.allowedAccessName = "ACCOUNT_ADD";
angular.forEach($scope.privilege, function(value, key) {
var privilegedRoles = privilege[key].roles;
var privilegedAccessName = privilege[key].accessName;
//check if the json object contains the same accessName which we need
if($scope.allowedAccessName === privilegedAccessName){
//check if the role is allowed or not for this user
if( privilegedRoles.indexOf(userRole) > -1 ){
//the logged in user has this privilege to accessName
break;
}else{
// the logged in user has no access to this accessName
}
}
});
}
You can look at the comment and understand. This code may not be exactly the same which you are expecting but you will surely get an idea about how you can achieve your goal.
You can get the child count via
firebase_node.once('value', function(snapshot) { alert('Count: ' + snapshot.numChildren()); });
But I believe this fetches the entire sub-tree of that node from the server. For huge lists, that seems RAM and latency intensive. Is there a way of getting the count (and/or a list of child names) without fetching the whole thing?
The code snippet you gave does indeed load the entire set of data and then counts it client-side, which can be very slow for large amounts of data.
Firebase doesn't currently have a way to count children without loading data, but we do plan to add it.
For now, one solution would be to maintain a counter of the number of children and update it every time you add a new child. You could use a transaction to count items, like in this code tracking upvodes:
var upvotesRef = new Firebase('https://docs-examples.firebaseio.com/android/saving-data/fireblog/posts/-JRHTHaIs-jNPLXOQivY/upvotes');
upvotesRef.transaction(function (current_value) {
return (current_value || 0) + 1;
});
For more info, see https://www.firebase.com/docs/transactions.html
UPDATE:
Firebase recently released Cloud Functions. With Cloud Functions, you don't need to create your own Server. You can simply write JavaScript functions and upload it to Firebase. Firebase will be responsible for triggering functions whenever an event occurs.
If you want to count upvotes for example, you should create a structure similar to this one:
{
"posts" : {
"-JRHTHaIs-jNPLXOQivY" : {
"upvotes_count":5,
"upvotes" : {
"userX" : true,
"userY" : true,
"userZ" : true,
...
}
}
}
}
And then write a javascript function to increase the upvotes_count when there is a new write to the upvotes node.
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.countlikes = functions.database.ref('/posts/$postid/upvotes').onWrite(event => {
return event.data.ref.parent.child('upvotes_count').set(event.data.numChildren());
});
You can read the Documentation to know how to Get Started with Cloud Functions.
Also, another example of counting posts is here:
https://github.com/firebase/functions-samples/blob/master/child-count/functions/index.js
Update January 2018
The firebase docs have changed so instead of event we now have change and context.
The given example throws an error complaining that event.data is undefined. This pattern seems to work better:
exports.countPrescriptions = functions.database.ref(`/prescriptions`).onWrite((change, context) => {
const data = change.after.val();
const count = Object.keys(data).length;
return change.after.ref.child('_count').set(count);
});
```
This is a little late in the game as several others have already answered nicely, but I'll share how I might implement it.
This hinges on the fact that the Firebase REST API offers a shallow=true parameter.
Assume you have a post object and each one can have a number of comments:
{
"posts": {
"$postKey": {
"comments": {
...
}
}
}
}
You obviously don't want to fetch all of the comments, just the number of comments.
Assuming you have the key for a post, you can send a GET request to
https://yourapp.firebaseio.com/posts/[the post key]/comments?shallow=true.
This will return an object of key-value pairs, where each key is the key of a comment and its value is true:
{
"comment1key": true,
"comment2key": true,
...,
"comment9999key": true
}
The size of this response is much smaller than requesting the equivalent data, and now you can calculate the number of keys in the response to find your value (e.g. commentCount = Object.keys(result).length).
This may not completely solve your problem, as you are still calculating the number of keys returned, and you can't necessarily subscribe to the value as it changes, but it does greatly reduce the size of the returned data without requiring any changes to your schema.
Save the count as you go - and use validation to enforce it. I hacked this together - for keeping a count of unique votes and counts which keeps coming up!. But this time I have tested my suggestion! (notwithstanding cut/paste errors!).
The 'trick' here is to use the node priority to as the vote count...
The data is:
vote/$issueBeingVotedOn/user/$uniqueIdOfVoter = thisVotesCount, priority=thisVotesCount
vote/$issueBeingVotedOn/count = 'user/'+$idOfLastVoter, priority=CountofLastVote
,"vote": {
".read" : true
,".write" : true
,"$issue" : {
"user" : {
"$user" : {
".validate" : "!data.exists() &&
newData.val()==data.parent().parent().child('count').getPriority()+1 &&
newData.val()==newData.GetPriority()"
user can only vote once && count must be one higher than current count && data value must be same as priority.
}
}
,"count" : {
".validate" : "data.parent().child(newData.val()).val()==newData.getPriority() &&
newData.getPriority()==data.getPriority()+1 "
}
count (last voter really) - vote must exist and its count equal newcount, && newcount (priority) can only go up by one.
}
}
Test script to add 10 votes by different users (for this example, id's faked, should user auth.uid in production). Count down by (i--) 10 to see validation fail.
<script src='https://cdn.firebase.com/v0/firebase.js'></script>
<script>
window.fb = new Firebase('https:...vote/iss1/');
window.fb.child('count').once('value', function (dss) {
votes = dss.getPriority();
for (var i=1;i<10;i++) vote(dss,i+votes);
} );
function vote(dss,count)
{
var user='user/zz' + count; // replace with auth.id or whatever
window.fb.child(user).setWithPriority(count,count);
window.fb.child('count').setWithPriority(user,count);
}
</script>
The 'risk' here is that a vote is cast, but the count not updated (haking or script failure). This is why the votes have a unique 'priority' - the script should really start by ensuring that there is no vote with priority higher than the current count, if there is it should complete that transaction before doing its own - get your clients to clean up for you :)
The count needs to be initialised with a priority before you start - forge doesn't let you do this, so a stub script is needed (before the validation is active!).
write a cloud function to and update the node count.
// below function to get the given node count.
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.userscount = functions.database.ref('/users/')
.onWrite(event => {
console.log('users number : ', event.data.numChildren());
return event.data.ref.parent.child('count/users').set(event.data.numChildren());
});
Refer :https://firebase.google.com/docs/functions/database-events
root--|
|-users ( this node contains all users list)
|
|-count
|-userscount :
(this node added dynamically by cloud function with the user count)