Skip to content

Commit 2054dca

Browse files
authored
Merge pull request #29 from demokratie-live/sprint#6/user-activity
ActivityIndex
2 parents cf13bdd + b0f5e8a commit 2054dca

File tree

15 files changed

+357
-10
lines changed

15 files changed

+357
-10
lines changed

package.json

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@
77
"private": true,
88
"scripts": {
99
"start": "babel-node src/index.js",
10-
"dev":
11-
"nodemon -L -e js,graphql src/index.js --exec \"node --require dotenv/config --require babel-register\"",
10+
"dev": "nodemon -L -e js,graphql src/index.js --exec \"node --require dotenv/config --require babel-register\"",
1211
"lint": "eslint .",
1312
"build": "babel src -d dist -s",
1413
"serve": "node dist/index.js"
@@ -27,11 +26,15 @@
2726
"graphql-date": "^1.0.3",
2827
"graphql-tag": "^2.7.3",
2928
"graphql-tools": "^2.0.0",
29+
"jsonwebtoken": "^8.2.0",
3030
"lodash": "^4.17.4",
3131
"merge-graphql-schemas": "^1.3.0",
3232
"mongoose": "^5.0.3",
3333
"node-fetch": "^2.0.0",
34-
"prettier-eslint": "^8.2.0"
34+
"passport": "^0.4.0",
35+
"passport-jwt": "^4.0.0",
36+
"prettier-eslint": "^8.2.0",
37+
"react-native-rsa": "^0.0.3"
3538
},
3639
"devDependencies": {
3740
"babel-cli": "^6.26.0",

scripts/importAll.js

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
import ProgressBar from 'cli-progress'; // eslint-disable-line
2-
import program from 'commander'; // eslint-disable-line
3-
41
import client from '../src/graphql/client';
52
import Procedure from '../src/models/Procedure';
63
import getAllProcedures from '../src/graphql/queries/getAllProcedures';

src/express/auth/index.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import mongoose from 'mongoose';
2+
import passport from 'passport';
3+
4+
import jwt from './jsonWebToken';
5+
6+
export default (app) => {
7+
const User = mongoose.model('User');
8+
9+
app.use(passport.initialize());
10+
// app.use(passport.session());
11+
12+
passport.serializeUser((user, done) => {
13+
done(null, user.id);
14+
});
15+
16+
passport.deserializeUser(async (id, done) => {
17+
done(null, await User.findById(id));
18+
});
19+
20+
jwt(app);
21+
};

src/express/auth/jsonWebToken.js

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/* eslint no-underscore-dangle: ["error", { "allow": ["_id"] }] */
2+
import { Strategy, ExtractJwt } from 'passport-jwt';
3+
import passport from 'passport';
4+
import mongoose from 'mongoose';
5+
6+
export default (app) => {
7+
const UserModel = mongoose.model('User');
8+
9+
passport.use(new Strategy(
10+
{
11+
jwtFromRequest: ExtractJwt.fromExtractors([
12+
ExtractJwt.fromUrlQueryParameter('auth_token'),
13+
ExtractJwt.fromAuthHeaderAsBearerToken(),
14+
]),
15+
secretOrKey: process.env.AUTH_JWT_SECRET,
16+
},
17+
async (jwtPayload, done) => {
18+
try {
19+
const user = await UserModel.findById(jwtPayload._id);
20+
if (!user) {
21+
return done(null, false);
22+
}
23+
return done(null, user);
24+
} catch (err) {
25+
return done(err, false);
26+
}
27+
},
28+
));
29+
30+
app.use((req, res, next) => {
31+
passport.authenticate('jwt', { session: true }, (err, user) => {
32+
// console.log(info);
33+
if (user) {
34+
req.user = user;
35+
}
36+
next();
37+
})(req, res, next);
38+
});
39+
40+
app.get('/test', (req, res) => {
41+
res.send({ query: req.query, user: req.user });
42+
});
43+
};

src/graphql/resolvers/Activity.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/* eslint no-underscore-dangle: ["error", { "allow": ["_id"] }] */
2+
3+
export default {
4+
Query: {
5+
activityIndex: async (parent, { procedureId }, { ProcedureModel, ActivityModel, user }) => {
6+
if (!user) {
7+
throw new Error('No auth');
8+
}
9+
const procedure = await ProcedureModel.findOne({ procedureId });
10+
const activityIndex = await ActivityModel.find({ procedure }).count();
11+
const active = await ActivityModel.findOne({
12+
user,
13+
procedure,
14+
});
15+
return {
16+
activityIndex,
17+
active: !!active,
18+
};
19+
},
20+
},
21+
22+
Mutation: {
23+
increaseActivity: async (parent, { procedureId }, { ProcedureModel, ActivityModel, user }) => {
24+
if (!user) {
25+
throw new Error('No auth');
26+
}
27+
const procedure = await ProcedureModel.findOne({ procedureId });
28+
if (!procedure) {
29+
throw new Error('Procedure not found');
30+
}
31+
let active = await ActivityModel.findOne({
32+
user,
33+
procedure,
34+
});
35+
if (!active) {
36+
active = await ActivityModel.create({ user, procedure });
37+
}
38+
const activityIndex = await ActivityModel.find({ procedure }).count();
39+
return { activityIndex, active };
40+
},
41+
},
42+
};

src/graphql/resolvers/Procedure.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ export default {
8080
.limit(pageSize - activeVotings.length)
8181
.then(finishedVotings => [...activeVotings, ...finishedVotings]);
8282
},
83+
8384
procedure: async (parent, { id }, { ProcedureModel }) =>
8485
ProcedureModel.findOne({ procedureId: id }),
8586

@@ -89,4 +90,18 @@ export default {
8990
{ score: { $meta: 'textScore' } },
9091
).sort({ score: { $meta: 'textScore' } }),
9192
},
93+
94+
Procedure: {
95+
activityIndex: async (procedure, args, { ActivityModel, user }) => {
96+
const activityIndex = await ActivityModel.find({ procedure }).count();
97+
const active = await ActivityModel.findOne({
98+
user,
99+
procedure,
100+
});
101+
return {
102+
activityIndex,
103+
active: !!active,
104+
};
105+
},
106+
},
92107
};

src/graphql/resolvers/User.js

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/* eslint no-underscore-dangle: ["error", { "allow": ["_id"] }] */
2+
import RSAKey from 'react-native-rsa';
3+
4+
export default {
5+
Query: {
6+
me: (parent, args, { UserModel, user }) => {
7+
if (user) {
8+
return UserModel.findById(user._id);
9+
}
10+
return null;
11+
},
12+
},
13+
14+
Mutation: {
15+
signUp: async (parent, { deviceHashEncrypted }, { UserModel }) => {
16+
const rsa = new RSAKey();
17+
18+
rsa.setPrivateString(process.env.SECRET_KEY);
19+
const deviceHash = rsa.decrypt(deviceHashEncrypted);
20+
if (!deviceHash) {
21+
throw new Error('invalid deviceHash');
22+
}
23+
let user;
24+
user = await UserModel.findOne({ deviceHash });
25+
if (!user) {
26+
user = await UserModel.create({ deviceHash });
27+
}
28+
29+
return { token: user.createToken() };
30+
},
31+
32+
signIn: async (parent, { deviceHashEncrypted }, { UserModel }) => {
33+
const user = await UserModel.findOne({ deviceHashEncrypted });
34+
if (!user) {
35+
throw new Error('User does not exsit!');
36+
}
37+
38+
return { token: user.createToken() };
39+
},
40+
},
41+
};

src/graphql/schemas/Activity.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
export default `
2+
3+
type ActivityIndex {
4+
activityIndex: Int
5+
active: Boolean
6+
}
7+
8+
type Query {
9+
activityIndex(procedureId: String!): ActivityIndex
10+
}
11+
12+
type Mutation {
13+
increaseActivity(procedureId: String!): ActivityIndex
14+
}
15+
`;

src/graphql/schemas/Procedure.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ enum ProcedureType {
88
type Procedure {
99
_id: ID!
1010
title: String!
11-
procedureId: String
11+
procedureId: String!
1212
type: String
1313
period: Int
1414
currentStatus: String
@@ -17,6 +17,7 @@ type Procedure {
1717
voteDate: Date
1818
subjectGroups: [String]
1919
submissionDate: Date
20+
activityIndex: ActivityIndex
2021
importantDocuments: [Document]
2122
}
2223

src/graphql/schemas/User.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
export default `
2+
type User {
3+
_id: String!
4+
deviceHash: String!
5+
}
6+
7+
type Auth {
8+
token: String!
9+
}
10+
11+
type Mutation {
12+
signUp(deviceHashEncrypted: String!): Auth
13+
signIn(deviceHashEncrypted: String!): Auth
14+
}
15+
16+
type Query {
17+
me: User
18+
}
19+
`;

0 commit comments

Comments
 (0)