0.0.6
This commit is contained in:
parent
a4fa416dfe
commit
315709e39a
8 changed files with 87 additions and 26 deletions
|
@ -1,5 +1,5 @@
|
|||
# security
|
||||
[![version 0.0.5](https://img.shields.io/badge/pub-v0.0.5-red.svg)](https://pub.dartlang.org/packages/angel_security)
|
||||
[![version 0.0.6](https://img.shields.io/badge/pub-v0.0.6-red.svg)](https://pub.dartlang.org/packages/angel_security)
|
||||
[![build status](https://travis-ci.org/angel-dart/security.svg)](https://travis-ci.org/angel-dart/security)
|
||||
|
||||
Angel middleware designed to enhance application security by patching common Web security
|
||||
|
|
|
@ -1,20 +1,23 @@
|
|||
import 'dart:mirrors';
|
||||
import 'package:angel_framework/angel_framework.dart';
|
||||
import 'errors.dart';
|
||||
import 'is_server_side.dart';
|
||||
|
||||
/// Adds the authed user's id to `data`.
|
||||
///
|
||||
/// Default [as] is `'userId'`.
|
||||
///Default [idField] is `'id'`.
|
||||
/// Default [ownerField] is `'userId'`.
|
||||
/// Default [userKey] is `'user'`.
|
||||
HookedServiceEventListener associateCurrentUser(
|
||||
{String as,
|
||||
{String idField,
|
||||
String ownerField,
|
||||
String userKey,
|
||||
String errorMessage,
|
||||
bool allowNullUserId: false,
|
||||
getId(user),
|
||||
setId(id, user)}) {
|
||||
assignUserId(id, obj)}) {
|
||||
return (HookedServiceEvent e) async {
|
||||
var fieldName = as?.isNotEmpty == true ? as : 'userId';
|
||||
var fieldName = ownerField?.isNotEmpty == true ? ownerField : 'userId';
|
||||
var user = e.request?.grab(userKey ?? 'user');
|
||||
|
||||
if (user == null) {
|
||||
|
@ -25,7 +28,18 @@ HookedServiceEventListener associateCurrentUser(
|
|||
return;
|
||||
}
|
||||
|
||||
_getId(user) => getId == null ? user?.id : getId(user);
|
||||
_getId(user) {
|
||||
if (getId != null)
|
||||
return getId(user);
|
||||
else if (user is Map)
|
||||
return user[idField ?? 'id'];
|
||||
else if (user is Extensible)
|
||||
return user.properties[idField ?? 'id'];
|
||||
else if (idField == null || idField == 'id')
|
||||
return user.id;
|
||||
else
|
||||
return reflect(user).getField(new Symbol(idField ?? 'id')).reflectee;
|
||||
}
|
||||
|
||||
var id = await _getId(user);
|
||||
|
||||
|
@ -33,15 +47,19 @@ HookedServiceEventListener associateCurrentUser(
|
|||
throw new AngelHttpException.notProcessable(
|
||||
message: 'Current user is missing a $fieldName field.');
|
||||
|
||||
_setId(id, user) {
|
||||
if (setId != null)
|
||||
return setId(id, user);
|
||||
else if (user is Map)
|
||||
user[fieldName] = id;
|
||||
_assignUserId(id, obj) {
|
||||
if (assignUserId != null)
|
||||
return assignUserId(id, obj);
|
||||
else if (obj is Map)
|
||||
obj[fieldName] = id;
|
||||
else if (obj is Extensible)
|
||||
obj.properties[fieldName] = id;
|
||||
else if (fieldName == 'userId')
|
||||
obj.userId = id;
|
||||
else
|
||||
user.userId = id;
|
||||
reflect(obj).setField(new Symbol(fieldName), id);
|
||||
}
|
||||
|
||||
await _setId(id, e.data);
|
||||
await _assignUserId(id, e.data);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import 'dart:async';
|
||||
import 'dart:mirrors';
|
||||
import 'package:crypto/crypto.dart';
|
||||
import 'package:angel_framework/angel_framework.dart';
|
||||
|
||||
|
@ -19,8 +20,12 @@ HookedServiceEventListener hashPassword(
|
|||
return getPassword(user);
|
||||
else if (user is Map)
|
||||
return user[passwordField ?? 'password'];
|
||||
else
|
||||
else if (user is Extensible)
|
||||
return user.properties[passwordField ?? 'password'];
|
||||
else if (passwordField == 'password')
|
||||
return user?.password;
|
||||
else
|
||||
return reflect(user).getField(new Symbol(passwordField ?? 'password')).reflectee;
|
||||
}
|
||||
|
||||
_setPassword(password, user) {
|
||||
|
@ -28,8 +33,11 @@ HookedServiceEventListener hashPassword(
|
|||
return setPassword(password, user);
|
||||
else if (user is Map)
|
||||
user[passwordField ?? 'password'] = password;
|
||||
else if (user is Extensible)
|
||||
user.properties[passwordField ?? password] = password;
|
||||
else
|
||||
user?.password = password;
|
||||
reflect(user)
|
||||
.setField(new Symbol(passwordField ?? 'password'), password);
|
||||
}
|
||||
|
||||
if (e.data != null) {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import 'dart:mirrors';
|
||||
import 'package:angel_framework/angel_framework.dart';
|
||||
import 'errors.dart';
|
||||
import 'is_server_side.dart';
|
||||
|
@ -8,12 +9,13 @@ import 'is_server_side.dart';
|
|||
/// Default [userKey] is `'user'`.
|
||||
HookedServiceEventListener queryWithCurrentUser(
|
||||
{String as,
|
||||
String idField,
|
||||
String userKey,
|
||||
String errorMessage,
|
||||
bool allowNullUserId: false,
|
||||
getId(user)}) {
|
||||
return (HookedServiceEvent e) async {
|
||||
var fieldName = as?.isNotEmpty == true ? as : 'userId';
|
||||
var fieldName = idField?.isNotEmpty == true ? idField : 'id';
|
||||
var user = e.request?.grab(userKey ?? 'user');
|
||||
|
||||
if (user == null) {
|
||||
|
@ -24,15 +26,26 @@ HookedServiceEventListener queryWithCurrentUser(
|
|||
return;
|
||||
}
|
||||
|
||||
_getId(user) => getId == null ? user?.id : getId(user);
|
||||
_getId(user) {
|
||||
if (getId != null)
|
||||
return getId(user);
|
||||
else if (user is Map)
|
||||
return user[fieldName];
|
||||
else if (user is Extensible)
|
||||
return user.properties[fieldName];
|
||||
else if (fieldName == 'id')
|
||||
return user.id;
|
||||
else
|
||||
return reflect(user).getField(new Symbol(fieldName)).reflectee;
|
||||
}
|
||||
|
||||
var id = await _getId(user);
|
||||
|
||||
if (id == null && allowNullUserId != true)
|
||||
throw new AngelHttpException.notProcessable(
|
||||
message: 'Current user is missing a $fieldName field.');
|
||||
message: 'Current user is missing a \'$fieldName\' field.');
|
||||
|
||||
var data = {fieldName: id};
|
||||
var data = {as?.isNotEmpty == true ? as : 'userId': id};
|
||||
|
||||
e.params['query'] = e.params.containsKey('query')
|
||||
? (e.params['query']..addAll(data))
|
||||
|
|
|
@ -1,10 +1,16 @@
|
|||
import 'dart:mirrors';
|
||||
import 'package:angel_framework/angel_framework.dart';
|
||||
import 'errors.dart';
|
||||
import 'is_server_side.dart';
|
||||
|
||||
/// Restricts users to accessing only their own resources.
|
||||
HookedServiceEventListener restrictToOwner(
|
||||
{String userKey, String errorMessage, getId(user), getOwner(obj)}) {
|
||||
{String idField,
|
||||
String ownerField,
|
||||
String userKey,
|
||||
String errorMessage,
|
||||
getId(user),
|
||||
getOwner(obj)}) {
|
||||
return (HookedServiceEvent e) async {
|
||||
if (!isServerSide(e)) {
|
||||
var user = e.request?.grab(userKey ?? 'user');
|
||||
|
@ -18,9 +24,13 @@ HookedServiceEventListener restrictToOwner(
|
|||
if (getId != null)
|
||||
return getId(user);
|
||||
else if (user is Map)
|
||||
return user['id'];
|
||||
else
|
||||
return user[idField ?? 'id'];
|
||||
else if (user is Extensible)
|
||||
return user.properties[idField ?? 'id'];
|
||||
else if (idField == null || idField == 'id')
|
||||
return user.id;
|
||||
else
|
||||
return reflect(user).getField(new Symbol(idField ?? 'id')).reflectee;
|
||||
}
|
||||
|
||||
var id = await _getId(user);
|
||||
|
@ -38,9 +48,15 @@ HookedServiceEventListener restrictToOwner(
|
|||
if (getOwner != null)
|
||||
return getOwner(obj);
|
||||
else if (obj is Map)
|
||||
return obj['userId'];
|
||||
else
|
||||
return obj[ownerField ?? 'userId'];
|
||||
else if (obj is Extensible)
|
||||
return obj.properties[ownerField ?? 'userId'];
|
||||
else if (ownerField == null || ownerField == 'userId')
|
||||
return obj.userId;
|
||||
else
|
||||
return reflect(obj)
|
||||
.getField(new Symbol(ownerField ?? 'userId'))
|
||||
.reflectee;
|
||||
}
|
||||
|
||||
var ownerId = await _getOwner(resource);
|
||||
|
|
|
@ -16,6 +16,8 @@ HookedServiceEventListener variantPermission(
|
|||
return (HookedServiceEvent e) async {
|
||||
var permission = await createPermission(e);
|
||||
|
||||
if (permission is PermissionBuilder) permission = permission.toPermission();
|
||||
|
||||
if (permission is! Permission)
|
||||
throw new ArgumentError(
|
||||
'createPermission must generate a Permission, whether synchronously or asynchronously.');
|
||||
|
|
|
@ -18,9 +18,11 @@ class Permission {
|
|||
/// permission, or if they are the resource [owner].
|
||||
///
|
||||
/// [getId] and [getOwner] are passed to [restrictToOwner], along with
|
||||
/// [userKey] and [errorMessage].
|
||||
/// [idField], [ownerField], [userKey] and [errorMessage].
|
||||
HookedServiceEventListener toHook(
|
||||
{String errorMessage,
|
||||
String idField,
|
||||
String ownerField,
|
||||
String userKey,
|
||||
bool owner: false,
|
||||
getRoles(user),
|
||||
|
@ -41,6 +43,8 @@ class Permission {
|
|||
// Try owner if the roles are not in-place
|
||||
if (owner == true) {
|
||||
var listener = restrictToOwner(
|
||||
idField: idField,
|
||||
ownerField: ownerField,
|
||||
userKey: userKey,
|
||||
errorMessage: errorMessage,
|
||||
getId: getId,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
name: angel_security
|
||||
version: 0.0.5
|
||||
version: 0.0.6
|
||||
description: Angel middleware designed to enhance application security by patching common Web security holes.
|
||||
author: Tobe O <thosakwe@gmail.com>
|
||||
environment:
|
||||
|
|
Loading…
Reference in a new issue