How to set a Angular config var to set server address? - javascript

How can I do some centralized solution to store strings on AngularJS? I've asked a similar question regarding NodeJS, but I don't know how to use the same approach to Angular as I've used to Node.
I've thought of 2 approaches:
1 - Setting a Angular Constant
app.constant('config',
{
serverUrl: 'http://localhost:8080'
});
This is my actual solution, but it comes with the downside that I need to update my code with the server address every time I send the code to the cloud.
2 - Using something like Node's process.env
And I have no idea how.
3 - Using something like require('./config.js')
I'm thinking on the Node like approach. Don't know how.
Well, is there a good, effective way of accomplishing this?

I do not think that there is one right answer. I prefer your first approach:
app.constant('config',
{
serverUrl: 'http://localhost:8080'
});
It is because I think about node.js backend and angular frontend as separete applications. For example I can add to node.js second version of api and connect other angular application (or event in another technology) to new api, but also use old angular app with previous api version.
In short in my opinion it is more flexible
Edit:
So, I need to update this line everytime I upload my come to Git
I don't add configuration file to repository. I create example config file which we add to repository. But actual config is ignored.
Edit2:
In one of mine project we use this module https://www.npmjs.com/package/gulp-ng-constant for build app.constant from config.json

This is how we switch the server url without rewriting it every time
var hostname = window.location.hostname;
if (hostname.indexOf("our.live.url") > -1) {
usedEnvironment = availableEnvironments.LIVE;
} else if (hostname.indexOf("localhost") > -1) {
usedEnvironment = availableEnvironments.LOCAL;
} else {
usedEnvironment = availableEnvironments.TEST;
}
switch (usedEnvironment) {
case availableEnvironments.LIVE:
angular.module('app')
.value('apiHost', 'https://our.live.backend.com');
angular.module('app')
.value('IntercomConfig', {
Enabled: true,
AppId: ''
});
break;
case availableEnvironments.TEST:
angular.module('app')
.value('apiHost', 'our.test.backend');
angular.module('app')
.value('IntercomConfig', {
Enabled: false,
});
break;
default:
angular.module('app')
.value('apiHost', 'http://localhost:8080');
angular.module('app')
.value('IntercomConfig', {
Enabled: false,
});
}

Related

How to create a custom route in Sails JS

I'm trying to create a custom route in Sails and according to their documentation, if I add the following in config/routes.js:
'post /api/signin': 'AuthController.index',
The request would be dealt with by the index action in the AuthController but that doesn't seems to work at all. When I try the /api/login in Postman, I get nothing back.
Please note that I've added restPrefix: '/api' in my config/blueprints.js. Please note I'm using Sails 0.12.x
What am I missing here?
Since you are pointing to a controller with method index on it, you need to add it to your controllers and send a JSON response from there, (since you are using post). here is a simple example
config/routes.js
'post /api/signin': 'AuthController.index',
api/controllers/AuthController.js
module.exports = {
index: function(req, res) {
var id = req.param('id');
if(!id) {
return res.json(400, { error: 'invalid company name or token'});
}
/* validate login..*/
res.json(200, {data: "success"};
}
}
Update
Since you already have the above its probably caused by the blueprints you have.
Blueprint shortcut routes
Shortcut routes are activated by default in new Sails apps, and can be
turned off by setting sails.config.blueprints.shortcuts to false
typically in /config/blueprints.js.
Sails creates shortcut routes for any controller/model pair with the
same identity. Note that the same action is executed for similar
RESTful/shortcut routes. For example, the POST /user and GET
/user/create routes that Sails creates when it loads
api/controllers/UserController.js and api/models/User.js will
respond by running the same code (even if you override the blueprint
action)
with that being said from sails blueprint documentation, maybe turning off shortcuts and remove the prefix you've added.
possibly the shortcuts are looking elsewhere other than your controllers thus returning 404.
the prefix is being added to your blueprint connected route, hence you need /api/api/signin to access it?
Note
I am unable to replicate your issue on my computer as its working fine over here. but i have all blueprint settings turned off.
module.exports.blueprints = {
actions: false,
rest: false,
shortcuts: false,
// prefix: '',
pluralize: false,
populate: false,
autoWatch: false,
};

Proper Angularjs way to use JSON maintain RESTful urls

I am building an Angularjs web application by the books I guess you could say. I am following the John Papa Angular Styleguide and things have been going well so far. I now have a need to keep all of the RESTful host urls in some sort of configuration file in JSON format. These host endpoints change frequently depending on the client or change of AWS machines, so to keep all of the urls in one place could be beneficial for ease of change.
Currently in the javascript files in my application that deal with making the REST calls things are setup like this:
function ModelViewService($http, $q, exception, logger) {
var HOST = 'http://xxxxxxxxxxxxxxxxxx.amazonaws.com';
var MODULE = '/modelview/service/rest';
...
And then when a call is made to get some data for example it looks like this:
function getGroups() {
return $http.get(HOST + MODULE + '/group/retrieveAll')
.then(success)
.catch(fail);
...
I then have other files with different services and different HOSTs so I basically want to house JSON objects somewhere that look like:
{
'modelviewservice': {
'HOST': 'http://xxxxxxxxxxxxxxxxxx.amazonaws.com',
'MODULE': '/modelview/service/rest'
},
... //other service
}
And then back in the javascript file do something like $http.get(config.modelviewservice.host + config.modelviewservice.MODULE + '/group/retrieveAll').
I don't know the best way to achieve this and follow the angular style guide. I found something called requre.js that apparently would inject the config.json file into the javascript via something like var config = require('config.json')('./config.json'); where the first config.json refers to the config.json npm module, and the second ./config.json refers to my local configuration JSON file. This seemed like an ok solution but since I couldn't get it to work it had me second guessing if there was an easier or more proper way to do this.
Well, this is how I do it to make my endpoints organize. Add constant to main module of the application .
(function() {
'use strict';
angular
.module('apiConstant', [])
.constant('apiConstant', constant());
function constant() {
return {
HOST: 'http://xxxxxxxxxxxxxxxxxx.amazonaws.com',
modules: {
MODULE_1: '/modelview/service/rest',
MODULE_2: '/modelview/factory/rest',
MODULE_3: '/modelview/sample/rest'
},
endpoints: {
GET_GROUPS: '/group/retrieveAll',
GET_USERS: '/users/retrieveAll',
POST_GROUP: '/group/add'
}
};
}
})();
And then in your service
function ModelViewService($http, $q, exception, logger, apiConstant) {
var HOST = apiConstant.HOST;
var MODULE = apiConstant.modules.MODULE_1;
...
function getGroups() {
return $http.get(HOST + MODULE + apiConstant.endpoints.GET_GROUPS)
.then(success)
.catch(fail);
...

Meteor: Limiting DDP Connections with ddp-rate-limiter package

I am trying to prevent a user to be able to call a Meteor method too often with the Meteor package ddp-rate-limiter (For example to prevent spamming or a DOS attack), but I can not get it to work.
Does anybody have an idea?
server/ddpRateLimiter.js:
Meteor.methods({
dosAttack: function() {console.log("dos");}
});
var preventDosAttack= {
userId: function() {return true;},
type: 'method',
method: 'dosAttack'
}
DDPRateLimiter.addRule(preventDosAttack, 5, 1000);
With this code I can still run the method from the client console as often as I want to. (Tested with a for loop 100 times)
You can find the entire sourcecode here: opensource project
And this certain commit here: commit
Thank you very much for your help,
Max
My mistake is simple: It is not 'method': 'dosAttack' but 'name': 'dosAttack'. Seems like the example in the documentation MeteorDoc DDPRateLimiter does the same mistake. I created an issue on the meteor GitHub page
Rate limiting is now offered as a vendor-supported Meteor package. I've recently used it to create Meteor Candy, the admin panel for Meteor. Here's how I did it.
First, add the package:
meteor add ddp-rate-limiter.
Second, define the method:
Meteor.methods({
myFancyMethod: function () {
return true;
}
})
Finally, define the rate limiting rules for it:
import { DDPRateLimiter } from 'meteor/ddp-rate-limiter';
var requestLimit = 5;
var requestTimeout = 5000;
DDPRateLimiter.addRule({
type: "method",
name: "myFancyMethod",
}, requestLimit, requestTimeout);

Where to add role based authentication to MeanJS app?

I have a meanjs starter template (with yeoman generator).
Where can I add specific permissions to my modules? For instance,
'use strict';
// Configuring the Articles module
angular.module('adminpanel').run(['Menus',
function(Menus) {
// Set top bar menu items
//Menus.addMenuItem('topbar', 'admin panel', 'adminpanel/', 'adminpanel');
Menus.addMenuItem('topbar', 'Admin Panel', 'adminpanel', 'dropdown', '/buildings(/create)?');
Menus.addSubMenuItem('topbar', 'adminpanel', 'List Collections', 'adminpanel/collections');
}
]);
and the routes like so
'use strict';
//Setting up route
angular.module('adminpanel').config(['$stateProvider',
function($stateProvider) {
// Adminpanels state routing
$stateProvider.
state('listCollections', {
url: '/adminpanel/collections',
templateUrl: 'modules/adminpanels/views/list-collections.client.view.html'
}).
state('showCollection', {
url: '/adminpanel/collections/:collectionName',
templateUrl: 'modules/adminpanels/views/show-collection.client.view.html'
}).
state('showCollectionItem', {
url: '/adminpanel/collections/:collectionName/:itemId',
templateUrl: 'modules/adminpanels/views/show-item.client.view.html'
});
}
]);
Are these the correct places to add role-based authentication (on the client side), with added measure on the serverside (I've already done that)?
Does anybody know how I can add an option to the Menus.(some function), such as 'admin.hasPermission', without breaking it? Any resources on this sort of thing?
Thanks for the help!
I don't believe it is right practice to put your authentication, authorization code at the client side as well as server side. They should be on the server side only.
The point is, you have to replicate your authentication and authorization code in the client, anyone can read your mechanism to handle these situation and once a loophole is discovered, it would simply be followed by your server code as well.
I believe authentication and authorization logic should be restricted to server side only. If I am up against someone professional, it would at least make his task tougher.
In case you insist, you can create a wrapper around $http service, maintain a key value pair of what role can do what, and ensure all AJAX request go through your wrapper service where you can check whether it should be allowed. If yes, you can simply forward the request using $http and if not, throw an error.
Not sure about any previous version, but with version 0.4.0 there are parameter in the client config to control the visibility:
If you set isPublic: false and add a roles array you can set the user that can see the menu entry:
// Add the dropdown listCollentcions item
Menus.addSubMenuItem('topbar', 'adminpanel', {
title: 'listCollections',
isPublic: false,
roles:['admin'],
state: 'adminpanel.listCollections'
});
The implementation is in the core module (menu.client.services.js):
// A private function for rendering decision
var shouldRender = function(user) {
if (user) {
if (!!~this.roles.indexOf('*')) {
return true;
} else {
for (var userRoleIndex in user.roles) {
for (var roleIndex in this.roles) {
if (this.roles[roleIndex] === user.roles[userRoleIndex]) {
return true;
}
}
}
}
} else {
return this.isPublic;
}
return false;
};
Maybe you can give version 0.4.0 a try or have a look at the code and try to implement it urself.

publish application settings (not documents) in Meteor

I have a couple settings which I need in my application. Now I want to make a couple of them available on the client. So I did:
Meteor.startup(function () {
Meteor.publish('settings', function () {
return {
isAuth: false
}
});
And I've a subscription like
Meteor.subscribe('settings');
This doesn't work at all, somehow I have the feeling this only works for Collections. So the question is how can I get these settings in the client. Also, these settings are needed to render stuff, so I need this data during init!
Save the settings in a shared js file
/shared/const.js:
Global.settings = {
'Something'
};
The publish/subscribe system is only ment to be used for collections.
Although on a side note isAuth doesn't really sound like a setting but a session variable./
If it's okay to put those configuration settings in code, then just do what Marco says.
If you want to specify them in a JSON configuration file, use Meteor.settings - anything in the public field in the configuration file is available on the client in Meteor.settings.public.
It is possible to do this with publish/subscribe, but it's probably overkill:
// On the server
Meteor.publish("applicationSettings", function () {
this.added("settings", "arbitrary_string", {isAuth: true});
this.ready();
});
// On the client
Settings = new Meteor.Collection("settings"); // ONLY on the client
Meteor.subscribe("applicationSettings");
// after subscription is ready,
// Settings.findOne() returns {_id: "arbitrary_string", isAuth: true}

Categories