Socket
Socket
Sign inDemoInstall

spel2js

Package Overview
Dependencies
0
Maintainers
1
Versions
9
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.2.3 to 0.2.4

.babelrc

52

package.json
{
"name": "spel2js",
"version": "0.2.3",
"version": "0.2.4",
"description": "Parse Spring Expression Language in JavaScript",

@@ -27,3 +27,7 @@ "author": {

"scripts": {
"test": "grunt"
"build": "webpack --progress",
"build:dev": "webpack -d --progress --devtool cheap-module-source-map",
"test": "karma start test/karma.conf.js",
"lint": "eslint src/ test/",
"release": "npm test && npm run build && release-it"
},

@@ -42,24 +46,36 @@ "keywords": [

"devDependencies": {
"babelify": "^6.1.2",
"grunt": "^0.4.5",
"grunt-browserify": "^3.8.0",
"grunt-complexity": "^0.3.0",
"grunt-contrib-concat": "^0.5.1",
"grunt-contrib-jshint": "^0.11.2",
"grunt-contrib-uglify": "^0.9.1",
"grunt-karma": "^0.11.0",
"grunt-release": "^0.13.0",
"babel": "6.23.0",
"babel-core": "6.26.0",
"babel-eslint": "8.0.1",
"babel-istanbul-loader": "0.1.0",
"babel-loader": "7.1.2",
"babel-preset-es2015": "6.24.1",
"babel-preset-es2017": "6.24.1",
"babel-register": "6.26.0",
"eslint": "4.7.2",
"eslint-config-airbnb-base": "12.0.0",
"eslint-config-prettier": "2.6.0",
"eslint-import-resolver-webpack": "0.8.3",
"eslint-loader": "1.9.0",
"eslint-plugin-import": "2.7.0",
"eslint-plugin-prettier": "2.3.1",
"jasmine-core": "2.8.0",
"karma": "1.7.1",
"karma-browserify": "^4.2.1",
"karma-coverage": "^0.4.2",
"karma-jasmine": "^0.3.5",
"karma-phantomjs-launcher": "^0.2.0",
"load-grunt-tasks": "^3.2.0",
"karma-browserify": "4.2.1",
"karma-coverage": "1.1.1",
"karma-jasmine": "0.3.5",
"karma-phantomjs-launcher": "1.0.4",
"karma-source-map-support": "1.2.0",
"karma-sourcemap-loader": "0.3.7",
"karma-webpack": "2.0.4",
"phantomjs": "2.1.7",
"time-grunt": "^1.2.1"
"prettier": "1.7.0",
"release-it": "3.0.0",
"webpack": "3.6.0",
"webpack-bower-externals": "1.5.4",
"webpack-node-externals": "1.6.0"
},
"engines": {
"node": ">=0.10.0"
"node": ">=8"
}
}

@@ -20,2 +20,91 @@ # spel2js

## Getting Started
Install SpEL2JS:
```sh
$ npm i -S spel2js
# or
$ bower i -S spel2js
```
Or [download the zip](https://github.com/benmarch/spel2js/archive/master.zip)
Include the dependency using a module loader or script tag.
## Usage
SpEL2JS exports a singleton with two members:
```js
import spel2js from 'spel2js';
console.log(spel2js);
/*
{
StandardContext,
SpelExpressionEvaluator
}
*/
```
### `StandardContext`
The `StandardContext` is a factory that creates a evaluation context for an expression.
**NOTE:** This is not the same as the Java `EvaluationContext` class, though it serves a similar purpose.
```js
let spelContext = spel2js.StandardContext.create(authentication, principal);
```
The `create()` method takes two arguments: `authentication` and `principal`
`authentication` is an instance of Spring's [`Authentication`](https://docs.spring.io/spring-security/site/docs/current/apidocs/org/springframework/security/core/Authentication.html) class from Spring Security.
`principal` is any object representing the user (this is just used for reference, and can be any value or structure)
### `SpelExpressionEvaluator`
The heavy lifting is done using the `SpelExpressionEvaluator` which exposes two functions: `compile()` and `eval()`
`compile()` pre-compiles a SpEL expression, and returns an object with an `eval()` method that takes a context and optional locals:
```js
import { StandardContext, SpelExpressionEvaluator } from 'spel2js';
const expression = '#toDoList.owner == authentication.details.name';
const spelContext = StandardContext.create(authentication, principal);
const locals = {
toDoList: {
owner: 'Darth Vader'
}
};
const compiledExpression = SpelExpressionEvaluator.compile(expression);
compiledExpression.eval(spelContext, locals); // true
```
`eval()` is just a shortcut for immediately evaluating an expression instead of pre-compiling:
```js
import { StandardContext, SpelExpressionEvaluator } from 'spel2js';
const expression = '#toDoList.owner == authentication.details.name';
const spelContext = StandardContext.create(authentication, principal);
const locals = {
toDoList: {
owner: 'Darth Vader'
}
};
SpelExpressionEvaluator.eval(expression, spelContext, locals); // true
```
### Recommended Usage
Create a single context that contains information about the current user and reuse it for all evaluations.
This way, you only have to supply an expression and locals when evaluating.
Always pre-compile your expressions! Compilation takes much longer than evaluation; doing it up-front saves CPU when evaluating later.
## Example

@@ -46,3 +135,37 @@

```javascript
```js
//spel-service.js
import { StandardContext, SpelExpressionEvaluator } from 'spel2js';
// wraps spel2js in a stateful service that simplifies evaluation
angular.module('ToDo').factory('SpelService', function () {
return {
context: null,
// assume this is called on page load
setContext(authentication, principal) {
this.context = StandardContext.create(authentication, principal);
},
getContext() { return this.context; },
compile(expression) {
const compiledExpression = SpelExpressionEvaluator.compile(expression);
return {
eval(locals) {
return compiledExpression.eval(this.getContext(), locals);
}
};
},
eval(expression, locals) {
return SpelExpressionEvaluator.eval(expression, this.getContext(), locals);
}
};
});
//list-controller.js

@@ -52,2 +175,3 @@

// retrieve all permissions and pre-compile them
$http.get('/api/permissions').success(function (permissions) {

@@ -59,2 +183,3 @@ angular.forEach(permissions, function (spelExpression, key) {

// $scope will be used as locals
$scope.list = {

@@ -70,4 +195,5 @@ name: 'My List',

// EXPAMPLE 1: authorize a request before making it
$scope.addListItem = function (list, newListItem) {
if ($scope.permissions.ADD_LIST_ITEM_PERMISSION.eval(SpelService.getContext(), $scope)) {
if ($scope.permissions.ADD_LIST_ITEM_PERMISSION.eval($scope)) {
$http.post('/todolists/' + list.id + '/items', item).success(function () {...});

@@ -89,3 +215,5 @@ }

<input type="text" ng-model="newListItem.text" />
<button ng-click="addListItem(list, newListItem)" spel-if="permissions.ADD_LIST_ITEM_PERMISSION">Add</button>
<!-- EXAMPLE 2: Hide the button if the user does not have permission -->
<button ng-click="addListItem(list, newListItem)" ng-if="permissions.ADD_LIST_ITEM_PERMISSION.eval(this)">Add</button>
</li>

@@ -96,6 +224,3 @@ ...

Seems like it might be a lot of work for such a simple piece of functionality; however, what happens when you add role-based
permissions as a new feature? If you already have this set up, it's as simple as adding " or hasRole('SuperUser')" to
the SpEL, and exposing a minimal projection of the Authentication to the browser or Node app (which it probably already
has access to.) Now the UI can always stay in sync with the server-side authorities.
Now the UI can always stay in sync with the server-side authorities.

@@ -127,24 +252,13 @@ ## Features

There are a few AngularJS directives (I just need to put them on GH):
- spelShow
- spelHide
- spelIf
If someone wants to implement a REST-compliant way in Spring to expose the permissions (and maybe the custom
PermissionEvaluators) that would be awesome.
## Building Locally
## Install Choices
- `bower install spel2js`
- `npm install spel2js`
- [download the zip](https://github.com/benmarch/spel2js/archive/master.zip)
```sh
$ npm i
$ npm run build
$ npm test
```
## Tasks
All tasks can be run by simply running `grunt` or with the `npm test` command, or individually:
* `grunt lint` will lint source code for syntax errors and anti-patterns.
* `grunt test` will run the jasmine unit tests against the source code.
## Credits

@@ -151,0 +265,0 @@

@@ -10,3 +10,3 @@ var addSorting = (function () {

// returns the summary table element
function getTable() { return document.querySelector('.coverage-summary table'); }
function getTable() { return document.querySelector('.coverage-summary'); }
// returns the thead element of the summary table

@@ -136,3 +136,5 @@ function getTableHeader() { return getTable().querySelector('thead tr'); }

if (cols[i].sortable) {
el = getNthColumn(i).querySelector('.sorter');
// add the click event handler on the th so users
// dont have to click on those tiny arrows
el = getNthColumn(i).querySelector('.sorter').parentElement;
if (el.addEventListener) {

@@ -139,0 +141,0 @@ el.addEventListener('click', ithSorter(i));

@@ -12,3 +12,16 @@ /**

'use strict';
require('babel-register');
var webpackConfig = require('../webpack.config.babel').default;
webpackConfig.externals = {};
webpackConfig.module.rules.unshift(
//get coverage info from precompiled source code
{
test: /\.js$/,
enforce: 'pre',
exclude: /(test|node_modules|bower_components)\//,
use: 'babel-istanbul-loader',
}
);
module.exports = function (config) {

@@ -22,7 +35,12 @@ config.set({

/*
Test results reporter to use:
dots, progress, nyan, story, coverage etc.
Test framework to use:
jasmine, mocha, qunit etc.
*/
reporters: ['dots', 'coverage'],
frameworks: ['jasmine', 'source-map-support'],
files: [
'src/main.js',
'test/spec/**/*.spec.js'
],
/*

@@ -32,7 +50,18 @@ Test pre-processors

preprocessors: {
'src/**/*.js': ['browserify'],
'test/**/*spec.js': ['browserify']
'src/**/*.js': ['webpack', 'sourcemap'],
'test/**/*spec.js': ['webpack', 'sourcemap']
},
webpack: webpackConfig,
webpackMiddleware: {
noInfo: true,
},
/*
Test results reporter to use:
dots, progress, nyan, story, coverage etc.
*/
reporters: ['dots', 'coverage'],
/*
Test coverage reporters:

@@ -51,7 +80,2 @@ html, lcovonly, lcov, cobertura, text-summary, text, teamcity, clover etc.

browserify: {
debug: true,
transform: [ 'babelify' ]
},
/*

@@ -89,14 +113,3 @@ Locally installed browsers

logLevel: 'INFO',
/*
Test framework to use:
jasmine, mocha, qunit etc.
*/
frameworks: ['browserify', 'jasmine'],
files: [
'src/**/*.js',
'test/spec/**/*.spec.js'
]
});
};

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc