aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/app/controllers/system.js
blob: a09f51714eff94b572f10aa3b6450bfb19a8015a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388

/**
 * Module dependencies
 */

var mongoose = require('mongoose')
  , env = process.env.NODE_ENV || 'development'
  , config = require('../../config/config.js')[env]
  , Project = mongoose.model('Project')
  , Access = mongoose.model('Access')
  , User = mongoose.model('User')
  , pPost = mongoose.model('pPost')
  , Validator = require('validator').Validator
  , v = new Validator()
  , sanitize = require('validator').sanitize;


// validation error handling. This collects all errors before pushing them out in getErrors()
Validator.prototype.error = function(msg) {
    this._errors.push(msg);
    return this;
}
Validator.prototype.getErrors = function() {
    var returnThis = this._errors;
    this._errors = ''; // need to reset errors between sessions because of object model that retains errors
    return returnThis;
}


/**
 * Before the user log in
 * ===============================================================
*/


/**
 * GET '/'
 */

exports.index = function(req, res) {
    if (req.user !== undefined) return res.redirect('/dashboard'); // if the user is logged in, redirect to dashboard
    res.render('index', {
        title: 'Divid'
      , user:req.user
    });
}


/**
 * GET '/faq'
 */

exports.faq = function(req, res) {
    res.render('faq', {
        title: 'FAQ'
      , user: req.user
    });
}


/**
 * GET '/contact'
 */

exports.contact = function(req, res) {
    res.render('contact', {
        title: 'Kontakt'
      , user: req.user
    });
}



/**
 * After the user has logged in
 * ===============================================================
*/


/**
 * GET '/dashboard'
 */

exports.dashboard = function(req, res) {

    // check if user is actually registered
    if (req.user.status < 3) {
        if (req.header('Referer') === undefined) { return res.status(403).render('error', { title: 403, text: 'Du har ikke tilgang til denne siden. Du må registrere deg først. Sjekk mailen din for å se invitekode.' }); }
        else { return res.redirect('back'); }
    }

    // start by loading all the projects the current user has access to
    Access.loadUser(req.user._id, function(err, projects) {
        if (err) return res.status(500).render('error', { title: '500', text: 'En serverfeil oppstod', error: err.stack });

        var projectIDs = [];
        var pro = { project: [] };

        // Time to initiate some projects so we can calculate how much the user owes / is owned
        projects.forEach(function(project) {
            projectIDs.push(project.project._id); // fills an array with all the project IDs
            pro.project[project.project._id] = { // initiates an object for each project, where we can store some data
                total:  0  // total for project
              , user:   0  // what req-user has spent on project
              , users:  0  // number of users on project
            };
        });

        // loads all the users for the projects the current user has access to
        // this is necessary so we can calculate what the user owes based on how many users each project has
        Access.loadProjects(projectIDs, function(err, participants) {
            if (err) return res.status(500).render('error', { title: '500', text: 'En serverfeil oppstod', error: err.stack });

            // counts the users in each project
            participants.forEach(function(p) {
                pro.project[p.project].users++;
            });

            // loads ALL posts for EVERY project the user has access to
            pPost.loadByProjects(projectIDs, function(err, posts) {
                if (err) return res.status(500).render('error', { title: '500', text: 'En serverfeil oppstod', error: err.stack });

                // FUN FUN FUN CALCULATIONS
                posts.forEach(function(p) {
                    if (String(p.user._id) === String(req.user._id)) pro.project[p.project._id].user += p.value;
                    pro.project[p.project._id].total += p.value;
                });

                res.render('dashboard', {
                    title: 'Dashboard'
                  , user: req.user
                  , projects: projects
                  , posts: posts
                  , participants: participants
                     , pro: pro
                });
            });
        });
    });
}


/**
 * GET '/project/:short'
 * :short = shortURL for project
 */

exports.project = function(req, res) {
    // loads the project based on the :short part of the url
    Project.loadShort(req.params.short, function(err, project) {
        if (err || !project) return res.status(500).render('error', { title: '500', text: 'En serverfeil oppstod', error: err });

        //loads all users in project
        Access.loadProject(project._id, function(err, access) {
            if (err) return res.status(500).render('error', { title: '500', text: 'En serverfeil oppstod', error: err.stack });

            // loads all posts in project
            pPost.loadProject(project._id, function(err, posts) {
                if (err) return res.status(500).render('error', { title: '500', text: 'En serverfeil oppstod', error: err.stack });

                // ALRIGHT! This is where the FUN starts!

               // first we create an object that will hold all the calculational data
                var pro = {
                        users:  0   // number of users
                      , user:   []  // this array will contain every user. Every user will then have it's own object inside this.
                      , total:  0   // the overall total.
                      , each:   0   // what each person has to pay
                      , otot:   0   // how much is owned in total!
                    };

                // then we calculate how many users we have, and initiate objects foreach user
                access.forEach(function(a) {
                    if (String(a.user._id) === String(req.user._id)) req.user.permissions = a.permissions; //sets YOUR permissions in this project

                    pro.users++;
                    pro.user[a.user._id] = {
                            total:  0
                          , diff:   0
                          , coeff:  0   // the coefficient of hom much you are owned
                          , name:   a.user.name
                        };
                });

                // now we must collect all the money!
                posts.forEach(function(p) {
                    pro.total += parseFloat(p.value);
                    pro.user[p.user._id].total += parseFloat(p.value);
                });

                // then calculate how much each user must pay in total
                pro.each = pro.total / pro.users;

                // then calculate how much each person owe and is owned
                for(var i in pro.user) {
                    pro.user[i].diff = parseFloat(pro.user[i].total - pro.each).toFixed(2);
                    if (pro.user[i].diff > 0) pro.otot += parseFloat(pro.user[i].diff);
                }

                // sets the coefficient if the user is owed money
                for (var i in pro.user) {
                    if (pro.user[i].diff > 0) pro.user[i].coeff = pro.user[i].diff / pro.otot;
                }

                res.render('project/project', {
                    title: project.name
                  , user: req.user
                  , req: req
                  , project: project
                  , access: access
                  , posts: posts
                  , pro: pro
                });
            });
        });
    });
}


/**
 * GET '/project/:short/participants'
 *
 * POST is in app/controllers/users.js
 */

exports.projectParticipants = function(req, res) {
    // check if user is actually registered
    if (req.user.status < 3) {
        if (req.header('Referer') === undefined) { return res.status(403).render('error', { title: 403, text: 'Du har ikke tilgang til denne siden. Du må registrere deg først. Sjekk mailen din for å se invitekode.' }); }
        else { return res.redirect('back'); }
    }

    res.render('project/participants', {
        title: 'Prosjektdeltakere'
      , user: req.user
    });
}


/**
 * GET '/projet/:short/post'
 */

exports.projectPost = function(req, res) {

    Project.loadShort(req.params.short, function(err, project) {
        if (err) return res.status(500).render('error', { title: '500', text: 'En serverfeil oppstod', error: err.stack });
        req.project = project;
        res.render('project/post', {
            title: 'Legg til utgift'
          , user: req.user
          , req: req
          , project: project
        });
    });
}


/**
 * POST '/project:short/post'
 */

exports.postProjectPost = function(req, res) {

    // Validation
    v.check(req.body.project, 'The project was lost').notEmpty();
    v.check(req.body.what, 'You need to fill in the what-field').notEmpty();
    v.check(req.body.value, 'The value must be a positive number').notEmpty().isInt().min(0);

    // error when validation fails
    var errors = v.getErrors();
    if (errors.length !== 0) return res.status(500).render('error', { title: '500', text: 'Det oppstod en valideringsfeil ' + errors, error: errors });

    Project.loadShort(req.params.short, function(err, project) {
        if (err) return res.status(500).render('error', { title: '500', text: 'En serverfeil oppstod', error: err.stack });

        // check if access
        Access.checkAccess(req.user._id, project._id, 0, function(err, access) {
            if (err || !access) return res.status(403).render('error', { title: '403', text: 'no sir.' });

            // Time to fill in the model!
            var ppost = new pPost();

            ppost.user         = req.user._id;
            ppost.for          = req.user._id;
            ppost.project      = project._id;
            ppost.what         = sanitize(req.body.what).escape();
            ppost.comment      = sanitize(req.body.comment).xss(); // xss will remove cross-site-scripting in the textfield.
            ppost.participants = sanitize(req.body.participants).escape();
            ppost.value        = sanitize(req.body.value).toInt(); // this will remove leading zeroes. '0123' => '123'
            ppost.when         = new Date(sanitize(req.body.date).escape() + ' ' + sanitize(req.body.time).escape() + ':00');

            ppost.save(function(err) {
                if (err) return res.render('project/post', { title: 'Legg til utgift - en feil oppstod', user: req.user, req: req, project: project });
                return res.redirect('/project/' + project.shortURL);
            });
        });
    });
}


/**
 * GET '/project/new'
 */

exports.newProject = function(req, res) {
    if (req.user.status < 3) {
        if (req.header('Referer') === undefined) { return res.status(403).render('error', { title: 403, text: 'Du har ikke tilgang til denne siden. Du må registrere deg først. Sjekk mailen din for å se invitekode.' }); }
        else { return res.redirect('back'); }
    }

    res.render('project/newProject', {
        title: 'Nytt prosjekt'
      , user: req.user
    });
}


/**
 * POST '/project/new'
 */

exports.postNewProject = function(req, res) {
    if (req.user.status < 3) {
        if (req.header('Referer') === undefined) { return res.status(403).render('error', { title: 403, text: 'Du har ikke tilgang til denne siden. Du må registrere deg først. Sjekk mailen din for å se invitekode.' }); }
        else { return res.redirect('back'); }
    }

    var project = new Project(req.body);
    project.user = req.user._id;
    project.save(function(err) {
        if (err) {
            console.log(err.errors);
            return res.render('project/newProject', { title: 'Nytt prosjekt - en feil oppstod', user: req.user, errors: err.errors, project: project });
        }
        var access = new Access();
        access.user = req.user._id;
        access.creator = req.user._id;
        access.project = project._id;
        access.permissions = 9;
        access.save(function(err) {
            if (err) {
                console.log(err.errors);
                return res.render('project/newProject', {
                    title: 'Nytt prosjekt - en feil oppstod'
                  , user: req.user
                });
            }
            return res.redirect('/dashboard');
        });
    });

}


/**
 * GET '/project/:short/delete/:post'
 */

exports.deleteProjectPost = function(req, res) {

    //Locate project
    Project.findOne({ shortURL: req.params.short }).select('_id').exec(function(err, project) {
        if (err) return res.status(500).render('error', { title: '500', text: 'En serverfeil oppstod', error: err.stack });

        //make sure you actually have access
        Access.findOne({project: project._id, user: req.user._id}, function(err, access) {
            if (err) return res.status(500).render('error', { title: '500', text: 'En serverfeil oppstod', error: err.stack });
            if (!access) return res.status(403).render('error', { title: '403', text: 'Du har ikke tilgang til å gjøre dette' });

            pPost.load(req.params.post, function(err, post) {
                if (err || !post) return res.status(500).render('error', { title: '500', text: 'En serverfeil oppstod', error: err });

                if (post.user._id === req.user._id || access.permissions >= 6) {

                    // delete! (only if access)
                    pPost.remove({ _id: post._id }, function(err) {
                        if (err) return res.status(500).render('error', { title: '500', text: 'En serverfeil oppstod', error: err.stack });

                        return res.redirect('back');
                    })
                } else { return res.status(403).render('error', { title: '403', text: 'Du har ikke tilgang til å gjøre dette' }); }
            })
        })
    });
}