Meteor Js limiting access to my meteor app - meteor

I have a meteor app and I want to host it, but I only want a few people to login to it and have access to it, at most 5 people. How Do I accomplish that?

You can create 5 accounts like these:
Meteor.startup(function () {
if (Meteor.users.find().count() === 0) {
Accounts.createUser({
username: 'xxxxx',
email: 'xxxx#xxxx.xx',
password: 'xxxxxxx',
profile: {}
});
...
}
});
And avoid possiblity to create new user:
AccountsTemplates.configure({
forbidClientAccountCreation: true,
});

You can block the creation of new users with:
Accounts.config({ forbidClientAccountCreation : true });
Checking the number of users in Meteor.startup will prevent creation of users when you restart you app and already 5 users have been created.
When 5 users have been created, you can throw an error in Accounts.onCreateUser. onCreateUser is called every time a new user is about to be created. Throwing the error will cancel user creation.
if (Meteor.isServer) {
Meteor.startup(function () {
if (Meteor.users.find().count() >= 5)
Accounts.config({
forbidClientAccountCreation : true
});
});
Accounts.onCreateUser(function (options, user) {
var numberOfUsers = Meteor.users.find().count();
if (numberOfUsers >= 4) {
Accounts.config({
forbidClientAccountCreation : true
});
};
if (numberOfUsers >= 5)
throw new Meteor.Error(403, "Signup forbidden");
return user;
});
}

Related

Next JS User session data successfully saves locally, but fails to save when deployed to AWS

In an app I'm building, a user logins in (validates through Magic Auth), and we save the user data in the session variable (using Iron for session management):
export default withSessionRoute(async (req, res) => {
try {
const didToken = req.headers?.authorization?.substr(7);
if (didToken) {
magic.token.validate(didToken);
const metadata: any = await magic.users.getMetadataByToken(didToken);
const response = await createUser({ email: metadata.email });
req.session.user = response.data.user;
req.session.userMetadata = metadata;
await req.session.save();
return res.send({ user: response.data.user, authenticated: true });
} else {
res.status(200).json({ authenticated: false });
}
} catch (error: any) {
console.log(error);
res.status(500).json({ error: error.message });
}
});
This works totally fine locally (req.session.user remains filled with user data), but for some reason on my deployed app, it does not work at all. It still returns the user data in "req.send", but the session variable is empty, so it does not seem to have saved.
Any ideas on what the issue could be?

Prevent Firebase auth from remembering Google account?

So I'm using Firebase-UI to authenticate and sign in users, I need to use the account chooser in order for them to sign in to a different Google account (not using the account chooser results in it auto-signing them in), however, I want to either prevent it from displaying + saving accounts, or remove them on sign out.
And this is the Firebase-UI web I'm using: Firebase UI web
This isn't a huge issue when the application is running on a user's machine, however, it will also be running on a public machine with many users signing in an out, and we can't have them saved as an easy one-click sign in. The biggest security issue is the fact that I can also log into their emails once they've authenticated with Google. We want it to forget them once they sign out.
My sign-in flow:
<script type="text/javascript">
// FirebaseUI config.
var uiConfig = {
callbacks: {
signInSuccess: function (user, credential, redirectUrl) {
var userSignIn = {
displayName: user.displayName,
email: user.email,
emailVerified: user.emailVerified,
photoURL: user.photoURL,
uid: user.uid,
phoneNumber: user.phoneNumber
};
/* POST signed in user to Login Controller*/
var csrfToken = $('input[name="csrfToken"]').attr('value');
$.ajaxSetup({
beforeSend: function(xhr) {
xhr.setRequestHeader('Csrf-Token', csrfToken);
}
});
$.ajax({
url: '/signedIn',
type: 'POST',
data: JSON.stringify(userSignIn),
contentType: 'application/json',
error: function(err) {
console.log(err);
}
});
return true;
}
},
signInSuccessUrl: '/Dashboard',
signInOptions: [{
provider: firebase.auth.GoogleAuthProvider.PROVIDER_ID,
scopes: ['https://www.googleapis.com/auth/calendar']
}],
// Terms of service url.
tosUrl: '/Terms'
};
// Initialize the FirebaseUI Widget using FirestoreDB.
var ui = new firebaseui.auth.AuthUI(firebase.auth());
// The start method will wait until the DOM is loaded.
ui.start('#firebaseui-auth-container', uiConfig);
</script>
Sign-out flow:
initApp = function () {
firebase.auth().onAuthStateChanged(function (user) {
if (user) {
// User is signed in.
if (window.location.pathname === "/Login" || window.location.pathname === "/") {
window.location.href = '/Dashboard';
}
$('#sign-out').show();
} else {
// User is signed out.
$('#sign-out').hide();
disableLinks();
switch(window.location.pathname){
case "/Login":
case "/Terms":
case "/Help":
break;
default:
window.location.href = '/Login';
}
}
}, function (error) {
console.log(error);
});
};
window.addEventListener('load', function () {
initApp();
document.getElementById('sign-out').addEventListener('click', function () {
firebase.auth().signOut().then(function() {
sessionStorage.clear();
localStorage.clear();
window.location = "/Logout";
}).catch(function(error) {
console.log(error);
});
});
});
On sign out from Firebase Auth, redirect to Google single sign out URL:
firebase.auth().signOut()
.then(function() {
window.location.assign('https://accounts.google.com/Logout');
})
.catch(function(error) {
console.log(error);
});

Meteor: Publish function requires a page refresh after user logs in

I have a meteor app and I'm calling all the publish functions at once in the iron router configuration like below. I only want to return the subscriptions once the user is logged in, so I check Meteor.userId():
Router.configure({
layoutTemplate: 'layout',
loadingTemplate: 'loading',
notFoundTemplate: '404',
waitOn: function () {
if (Meteor.userId()) {
return [Meteor.subscribe('users'),
Meteor.subscribe('company'),
Meteor.subscribe('projects'),
Meteor.subscribe('columns'),
Meteor.subscribe('cards'),
Meteor.subscribe('contents'),
Meteor.subscribe('labels'),
Meteor.subscribe('notifications')];
}
}
});
The publish functions have all the same structure, dependent on user.companyId, like this:
Meteor.publish('cards', function () {
if (this.userId) {
const user = Meteor.users.findOne({ _id: this.userId, companyId: { $exists: true } });
if (user) {
return Cards.find({ companyId: user.companyId });
}
} else {
this.ready();
}
});
My problem is, when the user registers, the account is created and the companyId is saved to the user, but when they now login, the only way for the data to show up is to refresh the browser. I want it to be reactive.
From the meteor guide:
On the client, if anything in a reactive function changes, the whole
function will re-run, and the results are fairly intuitive.
On the server however, the reactivity is limited to the behavior of
the cursors you return from your publish functions. You’ll see any
changes to the data that matches their queries, but their queries
will never change.
You can indeed use reywood:publish-composite as suggested, but for your simple case I think reactive-publish would be much easier to get up and running.
Install the package, and just wrap your publication in a this.autorun:
Meteor.publish('cards', function () {
this.autorun( function() {
if (this.userId) {
const user = Meteor.users.findOne({ _id: this.userId, companyId: { $exists: true } });
if (user) {
return Cards.find({ companyId: user.companyId });
}
} else {
this.ready();
}
});
});

Meteor showing Accounts.createUser errors

I have the following code in my Meteor app where I create new users, assign them 'basic' role. Yet I am having a trouble showing on the client side errors returned while processing Accounts.createUser, can someone please tell me how I can return errors returned by Accounts.createUser while having it on the server as my code below. Thanks
/server/users.js
Meteor.methods({
'createMemberAccount': function (data, role) {
var userId;
Meteor.call('createNewAccount', data, function(err, result) {
if (err) {
return err;
}
console.log('New account id: '+ result);
Roles.addUsersToRoles(result, role);
return userId = result;
});
return userId;
},
'createNewAccount': function (adminData) {
return Accounts.createUser({email: adminData.email, password : adminData.password, roles: adminData.roles});
}
});
/client/signup.js
Template.signupForm.events({
'submit #signup-form': function(e, t){
e.preventDefault();
var userData = {};
userData.email = $(e.target).find('[name=email]').val();
userData.password = $(e.target).find('[name=password]').val();
userData.roles = ['basic'];
Meteor.call('createMemberAccount', userData, 'basic', function(err, userId) {
if (!err) {
console.log('All OK');
} else {
console.log('Error: ' + err.message);
}
});
return false;
}
});
Since You are creating an static rol "basic", you don't need to do that pair of methods, and Meteor.calls, instead you can use
So, use the v on the client side, just like this.
Template.register.events({
'submit #register-form' : function(e, t) {
e.preventDefault();
var email = t.find('#account-email').value
, password = t.find('#account-password').value;
// Trim and validate the input
Accounts.createUser({email: email, password : password}, function(err){
if (err) {
// Inform the user that account creation failed
} else {
// Success. Account has been created and the user
// has logged in successfully.
}
});
return false;
}
});
If you see there is not any role yet incude, so now on the server.js use the onCreateUser method.
//Server.js
Accounts.onCreateUser(function(options, user) {
if (options.profile)
user.profile = options.profile;
user.role = "basic"
return user;
});
Now thats is more easy, and with less code, if you are trying to create 2 differents roles like "Admin" and "Basic", just on the client side create a profile field named "profile.roles" and do a if statement on the onCreateUser.
return Accounts.createUser({email: adminData.email, password : adminData.password, roles: adminData.roles});
This part returns the userId once it is created, it doesn't return any errors when it fails.
When it fails, the returned value will be undefined
Also, in the server, we cannot use callbacks with Accounts.createUser
If you want find the errors, you have to use Accounts.createUser in client side.
Coming to this late, but on the server side, you can assign the createUser to a variable and it will return the new user’s _id; then you can check if that exists. For example (server side only):
let email = 'foo#bar.com';
let password = 'bar';
let profile = {firstName: 'foo', lastName: 'bar'};
let newId = Accounts.createUser({
password: password,
email: email,
profile: profile
});
if (!newId) {
// New _id did not get created, reason is likely EMail Already Exists
throw new Meteor.Error(403, "Cannot create user: " + error.reason);
}
else {
// Stuff here to do after creating the user
}
The Meteor.Error line will be passed back as an error in the callback on the client side, so you can reflect that error to the browser.

create user method error in `meteor Js`?

I am new to meteor Js, i had develop the meteor app the below error is came in server console please verify my code and suggest me how to solve the error.HERE IS MY SERVER JS AND CLIENT JS IS THERE WHERE I DID A MISTAKE PLEASE VERIFY AND GIVE ME SUGGESTION.
eRROR:
TypeError: Object #<Object> has no method 'createUser'
SERVER JS:
if (Meteor.isServer)
{
Meteor.startup(function ()
{
// code to run on server at startup
if ( Meteor.users.find().count() === 0 )
{
Accounts.createUser
({
username: 'admin',
email: 'admin#hcare.com',
password: '000000',
profile:
{
first_name: 'admin',
last_name: 'admin',
company: '3CubeTech',
}
}) //Added close parenthesis.
}
});
}
cLIENT js:
Template.body.events
({
'submit #login-form' : function (e,t)
{
/* template data, if any, is available in 'this'*/
if (typeof console !== 'undefined')
console.log("You pressed Login the button");
e.preventDefault();
/*retrieve the input field values*/
var username = t.find('#username').value
, password = t.find('#password').value;
console.log(password);
Meteor.loginWithPassword(username, password, function (err)
{
if (err)
{
console.log(err);
alert(err.reason);
Session.set("loginError", true);
}
else
{
console.log(" Login Success ");
console.log( ">>>>>>>>>>>>>>>>>>>>>>> userid="+Meteor.userId() );
var adminUser = Meteor.users.findOne({username:"admin"});
console.log( ">>>>>>>>>>>>>>>>>>>>>>> adminUser()="+adminUser +" AND "+adminUser._id);
}
});
}
});
Run mrt test-packages For me it turned out, that I had to run mrt add accounts-password

Resources