aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugene Sokolov <eug-vs@keemail.me>2020-07-05 13:38:33 +0300
committerGitHub <noreply@github.com>2020-07-05 13:38:33 +0300
commit96398e544463651413ea80821c09ae7573f46cb1 (patch)
treedf77b6f65247d87dbfde8000e918c83985624fc3
parentda76bb1bd8797c4e1dc657c489f597bf64918ceb (diff)
parent1c2f3c9e5b39826266d64f4227e53fff139ea948 (diff)
downloadwhich-api-96398e544463651413ea80821c09ae7573f46cb1.tar.gz
Merge pull request #17 from which-ecosystem/security
Prepare release-level backend security
-rw-r--r--config/default.json3
-rw-r--r--hooks/tryAuthenticate.ts5
-rw-r--r--populateDb.ts11
-rw-r--r--services/feedback/feedback.hooks.ts23
-rw-r--r--services/polls/polls.hooks.ts6
-rw-r--r--services/users/users.hooks.ts16
-rw-r--r--services/votes/votes.hooks.ts6
7 files changed, 57 insertions, 13 deletions
diff --git a/config/default.json b/config/default.json
index 278b076..7d1ef26 100644
--- a/config/default.json
+++ b/config/default.json
@@ -10,6 +10,9 @@
"local": {
"usernameField": "\\username",
"passwordField": "password"
+ },
+ "jwtOptions": {
+ "expiresIn": "10 days"
}
}
}
diff --git a/hooks/tryAuthenticate.ts b/hooks/tryAuthenticate.ts
index e179417..71306ba 100644
--- a/hooks/tryAuthenticate.ts
+++ b/hooks/tryAuthenticate.ts
@@ -3,6 +3,9 @@ import { authenticate } from '@feathersjs/authentication';
export default async (context: HookContext): Promise<HookContext> => {
- return authenticate('jwt')(context).catch(() => context);
+ if (context.params?.headers?.authorization && context.path !== 'authentication') {
+ return authenticate('jwt')(context);
+ }
+ return context;
};
diff --git a/populateDb.ts b/populateDb.ts
index e25005d..1565f44 100644
--- a/populateDb.ts
+++ b/populateDb.ts
@@ -56,9 +56,8 @@ const createPoll = (authorId: string): Promise<Poll> => {
contents: {
left: generateImageData(),
right: generateImageData()
- },
- authorId
- });
+ }
+ }, { user: { _id: authorId }, authenticated: true });
};
const createUser = (username: string): Promise<User> => {
@@ -69,18 +68,18 @@ const createUser = (username: string): Promise<User> => {
});
};
-const createVote = (userId: string, pollId: string): Promise<Vote> => {
+const createVote = (authorId: string, pollId: string): Promise<Vote> => {
return app.service('votes').create({
pollId,
which: _.sample(choices)
- }, { user: { _id: userId }, authenticated: true });
+ }, { user: { _id: authorId }, authenticated: true });
};
const createFeedback = (userId: string): Promise<Feedback> => {
return app.service('feedback').create({
version: 'v1.0.0',
score: _.sample([1, 2, 3, 4, 5]),
- content: 'Absolutely amazing!'
+ contents: 'Absolutely amazing!'
}, { user: { _id: userId }, authenticated: true });
};
diff --git a/services/feedback/feedback.hooks.ts b/services/feedback/feedback.hooks.ts
index 56e9000..5bc2552 100644
--- a/services/feedback/feedback.hooks.ts
+++ b/services/feedback/feedback.hooks.ts
@@ -1,9 +1,30 @@
+import { populate, discard, disallow } from 'feathers-hooks-common';
import requireAuth from '../../hooks/requireAuth';
import signAuthority from '../../hooks/signAuthority';
+import sortByDate from '../../hooks/sortByDate';
+
+
+const populateAuthor = populate({
+ schema: {
+ include: {
+ service: 'users',
+ nameAs: 'author',
+ parentField: 'authorId',
+ childField: '_id'
+ }
+ }
+});
export default {
before: {
- create: [requireAuth, signAuthority]
+ create: [requireAuth, signAuthority],
+ find: sortByDate,
+ remove: disallow('external'),
+ patch: disallow('external'),
+ update: disallow('external')
+ },
+ after: {
+ all: [populateAuthor, discard('authorId')]
}
};
diff --git a/services/polls/polls.hooks.ts b/services/polls/polls.hooks.ts
index e3d04e7..35eae29 100644
--- a/services/polls/polls.hooks.ts
+++ b/services/polls/polls.hooks.ts
@@ -1,4 +1,5 @@
import { HookContext } from '@feathersjs/feathers';
+import { disallow } from 'feathers-hooks-common';
import { Types } from 'mongoose';
import bluebird from 'bluebird'; import _ from 'lodash';
import { Poll } from 'which-types';
@@ -46,7 +47,10 @@ const convertPoll = async (context: HookContext): Promise<HookContext> => {
export default {
before: {
find: sortByDate,
- create: signAuthority
+ create: signAuthority,
+ remove: disallow('external'),
+ update: disallow('external'),
+ patch: disallow('external')
},
after: {
all: convertPoll
diff --git a/services/users/users.hooks.ts b/services/users/users.hooks.ts
index 48843be..125f418 100644
--- a/services/users/users.hooks.ts
+++ b/services/users/users.hooks.ts
@@ -1,7 +1,9 @@
import _ from 'lodash';
import { hooks } from '@feathersjs/authentication-local';
-import { discard } from 'feathers-hooks-common';
+import { discard, disallow } from 'feathers-hooks-common';
import { HookContext } from '@feathersjs/feathers';
+import { NotAuthenticated } from '@feathersjs/errors';
+import requireAuth from '../../hooks/requireAuth';
const hashPassword = hooks.hashPassword('password');
@@ -12,6 +14,13 @@ const ignoreCaseRegex = async (context: HookContext): Promise<HookContext> => {
return context;
};
+const compareUser = async (context: HookContext): Promise<HookContext> => {
+ if (context.arguments[0] !== context.params.user._id) {
+ throw new NotAuthenticated('You can only PATCH/UPDATE your own user!');
+ }
+ return context;
+};
+
export default {
after: {
all: hooks.protect('password'),
@@ -20,8 +29,9 @@ export default {
before: {
find: ignoreCaseRegex,
create: hashPassword,
- patch: hashPassword,
- update: hashPassword
+ patch: [hashPassword, requireAuth, compareUser],
+ update: [hashPassword, requireAuth, compareUser],
+ remove: disallow('external')
}
};
diff --git a/services/votes/votes.hooks.ts b/services/votes/votes.hooks.ts
index 56e9000..923e897 100644
--- a/services/votes/votes.hooks.ts
+++ b/services/votes/votes.hooks.ts
@@ -1,9 +1,13 @@
+import { disallow } from 'feathers-hooks-common';
import requireAuth from '../../hooks/requireAuth';
import signAuthority from '../../hooks/signAuthority';
export default {
before: {
- create: [requireAuth, signAuthority]
+ create: [requireAuth, signAuthority],
+ remove: disallow('external'),
+ update: disallow('external'),
+ patch: disallow('external')
}
};