mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-16 06:07:21 +01:00
Reorganize files under /src, separate express app in two apps, one for api v1 and v2 and the other \
for the upcoming api v3 Reorganize files under /src, separate express app in two apps, one for api v1 and v2 and the other for the upcoming api v3 move api v2 routes in a separate folder, rename apiv1 file for better readability, remove auth routes for api v1 move api-v2 controllers in subdirectory move unorganized files to /libs fix gulp requires and separate server in old (api v1 and v2) and new (api v3) app fix require paths fix require paths fix require paths put api v1 back Reorganize files under /src and separate express app in one for api v1 and v2 and the other for v3
This commit is contained in:
@@ -140,7 +140,7 @@ module.exports = function(grunt) {
|
||||
|
||||
grunt.registerTask('test:prepare:translations', function() {
|
||||
require('coffee-script');
|
||||
var i18n = require('./website/src/i18n'),
|
||||
var i18n = require('./website/src/libs/i18n'),
|
||||
fs = require('fs');
|
||||
fs.writeFileSync('test/spec/mocks/translations.js',
|
||||
"if(!window.env) window.env = {};\n" +
|
||||
|
||||
@@ -2,9 +2,9 @@ import 'coffee-script';
|
||||
|
||||
import mongoose from 'mongoose';
|
||||
import autoinc from 'mongoose-id-autoinc';
|
||||
import logging from '../website/src/logging';
|
||||
import logging from '../website/src/libs/logging';
|
||||
import nconf from 'nconf';
|
||||
import utils from '../website/src/utils';
|
||||
import utils from '../website/src/libs/utils';
|
||||
import repl from 'repl';
|
||||
import gulp from 'gulp';
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ describe "Push-Notifications", ->
|
||||
done()
|
||||
|
||||
context "Challenges", ->
|
||||
challenges = rewire("../../website/src/controllers/challenges")
|
||||
challenges = rewire("../../website/src/controllers/api-v2/challenges")
|
||||
challenges.__set__('pushNotify', pushSpy)
|
||||
challengeMock = {
|
||||
findById: (arg, cb) ->
|
||||
@@ -65,7 +65,7 @@ describe "Push-Notifications", ->
|
||||
|
||||
recipient = null
|
||||
|
||||
groups = rewire("../../website/src/controllers/groups")
|
||||
groups = rewire("../../website/src/controllers/api-v2/groups")
|
||||
groups.__set__('pushNotify', pushSpy)
|
||||
|
||||
before (done) ->
|
||||
@@ -226,7 +226,7 @@ describe "Push-Notifications", ->
|
||||
, false
|
||||
|
||||
context "sending gems from balance", ->
|
||||
members = rewire("../../website/src/controllers/members")
|
||||
members = rewire("../../website/src/controllers/api-v2/members")
|
||||
members.sendMessage = -> true
|
||||
|
||||
members.__set__('pushNotify', pushSpy)
|
||||
|
||||
@@ -3,7 +3,7 @@ expect = require 'expect.js'
|
||||
sinon = require 'sinon'
|
||||
moment = require 'moment'
|
||||
shared = require '../../common/script/index.coffee'
|
||||
shared.i18n.translations = require('../../website/src/i18n.js').translations
|
||||
shared.i18n.translations = require('../../website/src/libs/i18n.js').translations
|
||||
test_helper = require './test_helper'
|
||||
test_helper.addCustomMatchers()
|
||||
$w = (s)->s.split(' ')
|
||||
|
||||
@@ -3,7 +3,7 @@ expect = require 'expect.js'
|
||||
sinon = require 'sinon'
|
||||
moment = require 'moment'
|
||||
shared = require '../../common/script/index.coffee'
|
||||
shared.i18n.translations = require('../../website/src/i18n.js').translations
|
||||
shared.i18n.translations = require('../../website/src/libs/i18n.js').translations
|
||||
|
||||
repeatWithoutLastWeekday = ()->
|
||||
repeat = {su:true,m:true,t:true,w:true,th:true,f:true,s:true}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
var shared = require('../../common/script/index.coffee');
|
||||
shared.i18n.translations = require('../../website/src/i18n.js').translations
|
||||
shared.i18n.translations = require('../../website/src/libs/i18n.js').translations
|
||||
|
||||
require('./test_helper');
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import {v4 as generateUUID} from 'uuid';
|
||||
import superagent from 'superagent';
|
||||
import i18n from '../../common/script/src/i18n';
|
||||
require('coffee-script');
|
||||
i18n.translations = require('../../website/src/i18n.js').translations;
|
||||
i18n.translations = require('../../website/src/libs/i18n.js').translations;
|
||||
|
||||
const API_TEST_SERVER_PORT = 3003;
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import {each} from 'lodash';
|
||||
|
||||
import i18n from '../../common/script/src/i18n';
|
||||
require('coffee-script');
|
||||
i18n.translations = require('../../website/src/i18n.js').translations;
|
||||
i18n.translations = require('../../website/src/libs/i18n.js').translations;
|
||||
|
||||
export const STRING_ERROR_MSG = 'Error processing the string. Please see Help > Report a Bug.';
|
||||
export const STRING_DOES_NOT_EXIST_MSG = /^String '.*' not found.$/;
|
||||
|
||||
@@ -30,7 +30,7 @@ describe('analytics', function() {
|
||||
});
|
||||
|
||||
describe('init', function() {
|
||||
var analytics = rewire('../../website/src/analytics');
|
||||
var analytics = rewire('../../website/src/libs/analytics');
|
||||
|
||||
it('throws an error if no options are passed in', function() {
|
||||
expect(analytics).to.throw('No options provided');
|
||||
@@ -62,7 +62,7 @@ describe('analytics', function() {
|
||||
describe('track', function() {
|
||||
|
||||
var analyticsData, event_type;
|
||||
var analytics = rewire('../../website/src/analytics');
|
||||
var analytics = rewire('../../website/src/libs/analytics');
|
||||
var initializedAnalytics;
|
||||
|
||||
beforeEach(function() {
|
||||
@@ -370,7 +370,7 @@ describe('analytics', function() {
|
||||
|
||||
var purchaseData;
|
||||
|
||||
var analytics = rewire('../../website/src/analytics');
|
||||
var analytics = rewire('../../website/src/libs/analytics');
|
||||
var initializedAnalytics;
|
||||
|
||||
beforeEach(function() {
|
||||
|
||||
@@ -5,10 +5,10 @@ var expect = chai.expect;
|
||||
|
||||
var Q = require('q');
|
||||
var Group = require('../../../website/src/models/group').model;
|
||||
var groupsController = require('../../../website/src/controllers/groups');
|
||||
var groupsController = require('../../../website/src/controllers/api-v2/groups');
|
||||
|
||||
describe('Groups Controller', function() {
|
||||
var utils = require('../../../website/src/utils');
|
||||
var utils = require('../../../website/src/libs/utils');
|
||||
|
||||
describe('#invite', function() {
|
||||
var res, req, user, group;
|
||||
|
||||
@@ -4,7 +4,7 @@ chai.use(require("sinon-chai"))
|
||||
var expect = chai.expect
|
||||
var rewire = require('rewire');
|
||||
|
||||
var userController = rewire('../../../website/src/controllers/user');
|
||||
var userController = rewire('../../../website/src/controllers/api-v2/user');
|
||||
|
||||
describe('User Controller', function() {
|
||||
|
||||
@@ -359,7 +359,7 @@ describe('User Controller', function() {
|
||||
});
|
||||
|
||||
it('sends webhooks', function() {
|
||||
var webhook = require('../../../website/src/webhook');
|
||||
var webhook = require('../../../website/src/libs/webhook');
|
||||
sinon.spy(webhook, 'sendTaskWebhook');
|
||||
|
||||
userController.score(req, res);
|
||||
|
||||
@@ -4,7 +4,7 @@ chai.use(require("sinon-chai"))
|
||||
var expect = chai.expect
|
||||
var rewire = require('rewire');
|
||||
|
||||
var webhook = rewire('../../website/src/webhook');
|
||||
var webhook = rewire('../../website/src/libs/webhook');
|
||||
|
||||
describe('webhooks', function() {
|
||||
var postSpy;
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
var _ = require('lodash');
|
||||
var validator = require('validator');
|
||||
var passport = require('passport');
|
||||
var shared = require('../../../common');
|
||||
var shared = require('../../../../common');
|
||||
var async = require('async');
|
||||
var utils = require('../utils');
|
||||
var utils = require('../../libs/utils');
|
||||
var nconf = require('nconf');
|
||||
var request = require('request');
|
||||
var FirebaseTokenGenerator = require('firebase-token-generator');
|
||||
var User = require('../models/user').model;
|
||||
var EmailUnsubscription = require('../models/emailUnsubscription').model;
|
||||
var User = require('../../models/user').model;
|
||||
var EmailUnsubscription = require('../../models/emailUnsubscription').model;
|
||||
var analytics = utils.analytics;
|
||||
var i18n = require('./../i18n');
|
||||
var i18n = require('./../../libs/i18n');
|
||||
|
||||
var isProd = nconf.get('NODE_ENV') === 'production';
|
||||
|
||||
@@ -3,15 +3,15 @@
|
||||
var _ = require('lodash');
|
||||
var nconf = require('nconf');
|
||||
var async = require('async');
|
||||
var shared = require('../../../common');
|
||||
var User = require('./../models/user').model;
|
||||
var Group = require('./../models/group').model;
|
||||
var Challenge = require('./../models/challenge').model;
|
||||
var logging = require('./../logging');
|
||||
var shared = require('../../../../common');
|
||||
var User = require('./../../models/user').model;
|
||||
var Group = require('./../../models/group').model;
|
||||
var Challenge = require('./../../models/challenge').model;
|
||||
var logging = require('./../../libs/logging');
|
||||
var csv = require('express-csv');
|
||||
var utils = require('../utils');
|
||||
var utils = require('../../libs/utils');
|
||||
var api = module.exports;
|
||||
var pushNotify = require('./pushNotifications');
|
||||
var pushNotify = require('./../pushNotifications');
|
||||
|
||||
/*
|
||||
------------------------------------------------------------------------
|
||||
@@ -1,5 +1,5 @@
|
||||
var _ = require('lodash');
|
||||
var Coupon = require('./../models/coupon').model;
|
||||
var Coupon = require('./../../models/coupon').model;
|
||||
var api = module.exports;
|
||||
var csv = require('express-csv');
|
||||
var async = require('async');
|
||||
@@ -9,17 +9,17 @@ var _ = require('lodash');
|
||||
var nconf = require('nconf');
|
||||
var async = require('async');
|
||||
var Q = require('q');
|
||||
var utils = require('./../utils');
|
||||
var shared = require('../../../common');
|
||||
var User = require('./../models/user').model;
|
||||
var Group = require('./../models/group').model;
|
||||
var Challenge = require('./../models/challenge').model;
|
||||
var EmailUnsubscription = require('./../models/emailUnsubscription').model;
|
||||
var utils = require('./../../libs/utils');
|
||||
var shared = require('../../../../common');
|
||||
var User = require('./../../models/user').model;
|
||||
var Group = require('./../../models/group').model;
|
||||
var Challenge = require('./../../models/challenge').model;
|
||||
var EmailUnsubscription = require('./../../models/emailUnsubscription').model;
|
||||
var isProd = nconf.get('NODE_ENV') === 'production';
|
||||
var api = module.exports;
|
||||
var pushNotify = require('./pushNotifications');
|
||||
var pushNotify = require('./../pushNotifications');
|
||||
var analytics = utils.analytics;
|
||||
var firebase = require('../libs/firebase');
|
||||
var firebase = require('../../libs/firebase');
|
||||
|
||||
/*
|
||||
------------------------------------------------------------------------
|
||||
@@ -1,9 +1,9 @@
|
||||
var _ = require('lodash');
|
||||
var nconf = require('nconf');
|
||||
var async = require('async');
|
||||
var shared = require('../../../common');
|
||||
var User = require('./../models/user').model;
|
||||
var Group = require('./../models/group').model;
|
||||
var shared = require('../../../../common');
|
||||
var User = require('./../../models/user').model;
|
||||
var Group = require('./../../models/group').model;
|
||||
var api = module.exports;
|
||||
|
||||
api.ensureAdmin = function(req, res, next) {
|
||||
@@ -1,13 +1,13 @@
|
||||
var User = require('mongoose').model('User');
|
||||
var groups = require('../models/group');
|
||||
var groups = require('../../models/group');
|
||||
var partyFields = require('./groups').partyFields
|
||||
var api = module.exports;
|
||||
var async = require('async');
|
||||
var _ = require('lodash');
|
||||
var shared = require('../../../common');
|
||||
var utils = require('../utils');
|
||||
var shared = require('../../../../common');
|
||||
var utils = require('../../libs/utils');
|
||||
var nconf = require('nconf');
|
||||
var pushNotify = require('./pushNotifications');
|
||||
var pushNotify = require('./../pushNotifications');
|
||||
|
||||
var fetchMember = function(uuid, restrict){
|
||||
return function(cb){
|
||||
@@ -1,7 +1,7 @@
|
||||
var User = require('../models/user').model;
|
||||
var EmailUnsubscription = require('../models/emailUnsubscription').model;
|
||||
var utils = require('../utils');
|
||||
var i18n = require('../../../common').i18n;
|
||||
var User = require('../../models/user').model;
|
||||
var EmailUnsubscription = require('../../models/emailUnsubscription').model;
|
||||
var utils = require('../../libs/utils');
|
||||
var i18n = require('../../../../common').i18n;
|
||||
|
||||
var api = module.exports = {};
|
||||
|
||||
@@ -5,19 +5,19 @@ var ipn = require('paypal-ipn');
|
||||
var _ = require('lodash');
|
||||
var nconf = require('nconf');
|
||||
var async = require('async');
|
||||
var shared = require('../../../common');
|
||||
var User = require('./../models/user').model;
|
||||
var utils = require('./../utils');
|
||||
var shared = require('../../../../common');
|
||||
var User = require('./../../models/user').model;
|
||||
var utils = require('./../../libs/utils');
|
||||
var analytics = utils.analytics;
|
||||
var Group = require('./../models/group').model;
|
||||
var Challenge = require('./../models/challenge').model;
|
||||
var Group = require('./../../models/group').model;
|
||||
var Challenge = require('./../../models/challenge').model;
|
||||
var moment = require('moment');
|
||||
var logging = require('./../logging');
|
||||
var logging = require('./../../libs/logging');
|
||||
var acceptablePUTPaths;
|
||||
var api = module.exports;
|
||||
var qs = require('qs');
|
||||
var firebase = require('../libs/firebase');
|
||||
var webhook = require('../webhook');
|
||||
var firebase = require('../../libs/firebase');
|
||||
var webhook = require('../../libs/webhook');
|
||||
|
||||
// api.purchase // Shared.ops
|
||||
|
||||
@@ -290,7 +290,7 @@ api.getUserAnonymized = function(req, res, next) {
|
||||
* The trick here is to only accept leaf paths, not root/intermediate paths (see http://goo.gl/OEzkAs)
|
||||
* FIXME - one-by-one we want to widdle down this list, instead replacing each needed set path with API operations
|
||||
*/
|
||||
acceptablePUTPaths = _.reduce(require('./../models/user').schema.paths, function(m,v,leaf){
|
||||
acceptablePUTPaths = _.reduce(require('./../../models/user').schema.paths, function(m,v,leaf){
|
||||
var found= _.find('achievements filters flags invitations lastCron party preferences profile stats inbox'.split(' '), function(root){
|
||||
return leaf.indexOf(root) == 0;
|
||||
});
|
||||
@@ -2,13 +2,13 @@
|
||||
var _ = require('lodash');
|
||||
var shared = require('../../../../common');
|
||||
var nconf = require('nconf');
|
||||
var utils = require('./../../utils');
|
||||
var utils = require('./../../libs/utils');
|
||||
var moment = require('moment');
|
||||
var isProduction = nconf.get("NODE_ENV") === "production";
|
||||
var stripe = require('./stripe');
|
||||
var paypal = require('./paypal');
|
||||
var amazon = require('./amazon');
|
||||
var members = require('../members')
|
||||
var members = require('../api-v2/members')
|
||||
var async = require('async');
|
||||
var iap = require('./iap');
|
||||
var mongoose= require('mongoose');
|
||||
|
||||
@@ -5,7 +5,7 @@ var _ = require('lodash');
|
||||
var url = require('url');
|
||||
var User = require('mongoose').model('User');
|
||||
var payments = require('./index');
|
||||
var logger = require('../../logging');
|
||||
var logger = require('../../libs/logging');
|
||||
var ipn = require('paypal-ipn');
|
||||
var paypal = require('paypal-rest-sdk');
|
||||
var shared = require('../../../../common');
|
||||
|
||||
@@ -2,7 +2,7 @@ require('coffee-script');
|
||||
require('./i18n');
|
||||
|
||||
var _ = require('lodash');
|
||||
var Content = require('../../common').content;
|
||||
var Content = require('../../../common').content;
|
||||
var Amplitude = require('amplitude');
|
||||
var googleAnalytics = require('universal-analytics');
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
var fs = require('fs'),
|
||||
path = require('path'),
|
||||
_ = require('lodash'),
|
||||
User = require('./models/user').model,
|
||||
shared = require('../../common'),
|
||||
User = require('../models/user').model,
|
||||
shared = require('../../../common'),
|
||||
translations = {};
|
||||
|
||||
var localePath = path.join(__dirname, "/../../common/locales/")
|
||||
var localePath = path.join(__dirname, "/../../../common/locales/")
|
||||
|
||||
var loadTranslations = function(locale){
|
||||
var files = fs.readdirSync(path.join(localePath, locale));
|
||||
@@ -54,7 +54,7 @@ _.each(langCodes, function(code){
|
||||
lang.momentLangCode = (momentLangsMapping[code] || code);
|
||||
try{
|
||||
// MomentJS lang files are JS files that has to be executed in the browser so we load them as plain text files
|
||||
var f = fs.readFileSync(path.join(__dirname, '/../../node_modules/moment/locale/' + lang.momentLangCode + '.js'), 'utf8');
|
||||
var f = fs.readFileSync(path.join(__dirname, '/../../../node_modules/moment/locale/' + lang.momentLangCode + '.js'), 'utf8');
|
||||
momentLangs[code] = f;
|
||||
}catch (e){}
|
||||
});
|
||||
@@ -170,7 +170,7 @@ module.exports.setupConfig = function(){
|
||||
nconf.argv()
|
||||
.env()
|
||||
//.file('defaults', path.join(path.resolve(__dirname, '../config.json.example')))
|
||||
.file('user', path.join(path.resolve(__dirname, './../../config.json')));
|
||||
.file('user', path.join(path.resolve(__dirname, './../../../config.json')));
|
||||
|
||||
if (nconf.get('NODE_ENV') === "development")
|
||||
Error.stackTraceLimit = Infinity;
|
||||
@@ -1,4 +1,4 @@
|
||||
var logging = require('../logging');
|
||||
var logging = require('../libs/logging');
|
||||
|
||||
module.exports = function(err, req, res, next) {
|
||||
//res.locals.domain.emit('error', err);
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
var nconf = require('nconf');
|
||||
var _ = require('lodash');
|
||||
var utils = require('../utils');
|
||||
var utils = require('../libs/utils');
|
||||
var shared = require('../../../common');
|
||||
var i18n = require('../i18n.js');
|
||||
var i18n = require('../libs/i18n');
|
||||
var buildManifest = require('../libs/buildManifest');
|
||||
var shared = require('../../../common');
|
||||
var forceRefresh = require('./forceRefresh');
|
||||
|
||||
@@ -4,7 +4,7 @@ var User = require('./user').model;
|
||||
var shared = require('../../../common');
|
||||
var _ = require('lodash');
|
||||
var async = require('async');
|
||||
var logging = require('../logging');
|
||||
var logging = require('../libs/logging');
|
||||
var Challenge = require('./../models/challenge').model;
|
||||
var firebase = require('../libs/firebase');
|
||||
|
||||
|
||||
@@ -3,10 +3,10 @@ var router = new express.Router();
|
||||
var _ = require('lodash');
|
||||
var async = require('async');
|
||||
var icalendar = require('icalendar');
|
||||
var api = require('./../controllers/user');
|
||||
var auth = require('./../controllers/auth');
|
||||
var logging = require('./../logging');
|
||||
var i18n = require('./../i18n');
|
||||
var api = require('./../controllers/api-v2/user');
|
||||
var auth = require('./../controllers/api-v2/auth');
|
||||
var logging = require('./../libs/logging');
|
||||
var i18n = require('./../libs/i18n');
|
||||
var forceRefresh = require('../middlewares/forceRefresh').middleware;
|
||||
|
||||
/* ---------- Deprecated API ------------*/
|
||||
@@ -170,4 +170,4 @@ router.get('*', i18n.getUserLanguage, deprecated);
|
||||
router.post('*', i18n.getUserLanguage, deprecated);
|
||||
router.put('*', i18n.getUserLanguage, deprecated);
|
||||
|
||||
module.exports = router;
|
||||
module.exports = router;
|
||||
@@ -1,6 +1,6 @@
|
||||
var auth = require('../controllers/auth');
|
||||
var auth = require('../../controllers/api-v2/auth');
|
||||
var express = require('express');
|
||||
var i18n = require('../i18n');
|
||||
var i18n = require('../../libs/i18n');
|
||||
var router = new express.Router();
|
||||
|
||||
/* auth.auth*/
|
||||
@@ -15,8 +15,7 @@ router.post('/api/v2/user/change-username', i18n.getUserLanguage, auth.auth, aut
|
||||
router.post('/api/v2/user/change-email', i18n.getUserLanguage, auth.auth, auth.changeEmail);
|
||||
router.post('/api/v2/user/auth/firebase', i18n.getUserLanguage, auth.auth, auth.getFirebaseToken);
|
||||
|
||||
router.post('/api/v1/register', i18n.getUserLanguage, auth.registerUser);
|
||||
router.post('/api/v1/user/auth/local', i18n.getUserLanguage, auth.loginLocal);
|
||||
router.post('/api/v1/user/auth/social', i18n.getUserLanguage, auth.loginSocial);
|
||||
|
||||
router.post('/api/v1/register', i18n.getUserLanguage, auth.registerUser);
|
||||
router.post('/api/v1/user/auth/local', i18n.getUserLanguage, auth.loginLocal);
|
||||
router.post('/api/v1/user/auth/social', i18n.getUserLanguage, auth.loginSocial);
|
||||
module.exports = router;
|
||||
@@ -1,9 +1,9 @@
|
||||
var nconf = require('nconf');
|
||||
var express = require('express');
|
||||
var router = new express.Router();
|
||||
var auth = require('../controllers/auth');
|
||||
var coupon = require('../controllers/coupon');
|
||||
var i18n = require('../i18n');
|
||||
var auth = require('../../controllers/api-v2/auth');
|
||||
var coupon = require('../../controllers/api-v2/coupon');
|
||||
var i18n = require('../../libs/i18n');
|
||||
|
||||
router.get('/api/v2/coupons', auth.authWithUrl, i18n.getUserLanguage, coupon.ensureAdmin, coupon.getCoupons);
|
||||
router.post('/api/v2/coupons/generate/:event', auth.auth, i18n.getUserLanguage, coupon.ensureAdmin, coupon.generateCoupons);
|
||||
777
website/src/routes/api-v2/swagger.js
Normal file
777
website/src/routes/api-v2/swagger.js
Normal file
@@ -0,0 +1,777 @@
|
||||
/*
|
||||
---------- /api/v2 API ------------
|
||||
see https://github.com/wordnik/swagger-node-express
|
||||
Every url added to router is prefaced by /api/v2
|
||||
Note: Many user-route ops exist in ../../common/script/index.coffee#user.ops, so that they can (1) be called both
|
||||
client and server.
|
||||
v1 user. Requires x-api-user (user id) and x-api-key (api key) headers, Test with:
|
||||
$ mocha test/user.mocha.coffee
|
||||
*/
|
||||
|
||||
require('coffee-script');
|
||||
var user = require("../../controllers/api-v2/user");
|
||||
var groups = require("../../controllers/api-v2/groups");
|
||||
var members = require("../../controllers/api-v2/members");
|
||||
var auth = require("../../controllers/api-v2/auth");
|
||||
var hall = require("../../controllers/api-v2/hall");
|
||||
var challenges = require("../../controllers/api-v2/challenges");
|
||||
var dataexport = require("../../controllers/dataexport");
|
||||
var nconf = require("nconf");
|
||||
var cron = user.cron;
|
||||
var _ = require('lodash');
|
||||
var content = require('../../../../common').content;
|
||||
var i18n = require('../../libs/i18n');
|
||||
var forceRefresh = require('../../middlewares/forceRefresh').middleware;
|
||||
|
||||
module.exports = function(swagger, v2) {
|
||||
var path = swagger.pathParam;
|
||||
var body = swagger.bodyParam;
|
||||
var query = swagger.queryParam;
|
||||
|
||||
swagger.setAppHandler(v2);
|
||||
swagger.setErrorHandler("next");
|
||||
swagger.setHeaders = function() {};
|
||||
swagger.configureSwaggerPaths("", "/api-docs", "");
|
||||
|
||||
var api = {
|
||||
'/status': {
|
||||
spec: {
|
||||
description: "Returns the status of the server (up or down). Does not require authentication."
|
||||
},
|
||||
action: function(req, res) {
|
||||
return res.json({
|
||||
status: "up"
|
||||
});
|
||||
}
|
||||
},
|
||||
'/content': {
|
||||
spec: {
|
||||
description: "Get all available content objects. This is essential, since Habit often depends on item keys (eg, when purchasing a weapon). Does not require authentication.",
|
||||
parameters: [query("language", "Optional language to use for content's strings. Default is english.", "string")]
|
||||
},
|
||||
action: user.getContent
|
||||
},
|
||||
'/content/paths': {
|
||||
spec: {
|
||||
description: "Show user model tree. Does not require authentication."
|
||||
},
|
||||
action: user.getModelPaths
|
||||
},
|
||||
"/export/history": {
|
||||
spec: {
|
||||
description: "Export user history",
|
||||
method: 'GET'
|
||||
},
|
||||
middleware: [auth.auth, i18n.getUserLanguage],
|
||||
action: dataexport.history
|
||||
},
|
||||
"/user/tasks/{id}/{direction}": {
|
||||
spec: {
|
||||
description: "Simple scoring of a task (Habit, Daily, To-Do, or Reward). This is most-likely the only API route you'll be using as a 3rd-party developer. The most common operation is for the user to gain or lose points based on some action (browsing Reddit, running a mile, 1 Pomodor, etc). Call this route, if the task you're trying to score doesn't exist, it will be created for you. When random events occur, the <b>user._tmp</b> variable will be filled. Critical hits can be accessed through <b>user._tmp.crit</b>. The Streakbonus can be accessed through <b>user._tmp.streakBonus</b>. Both will contain the multiplier value. When random drops occur, the following values are available: <b>user._tmp.drop = {text,type,dialog,value,key,notes}</b>",
|
||||
parameters: [path("id", "ID of the task to score. If this task doesn't exist, a task will be created automatically", "string"), path("direction", "Either 'up' or 'down'", "string"), body('', "If you're creating a 3rd-party task, pass up any task attributes in the body (see TaskSchema).", 'object')],
|
||||
method: 'POST'
|
||||
},
|
||||
action: user.score
|
||||
},
|
||||
"/user/tasks:GET": {
|
||||
spec: {
|
||||
path: '/user/tasks',
|
||||
description: "Get all user's tasks"
|
||||
},
|
||||
action: user.getTasks
|
||||
},
|
||||
"/user/tasks:POST": {
|
||||
spec: {
|
||||
path: '/user/tasks',
|
||||
description: "Create a task",
|
||||
method: 'POST',
|
||||
parameters: [body("", "Send up the whole task (see TaskSchema)", "object")]
|
||||
},
|
||||
action: user.addTask
|
||||
},
|
||||
"/user/tasks/{id}:GET": {
|
||||
spec: {
|
||||
path: '/user/tasks/{id}',
|
||||
description: "Get an individual task",
|
||||
parameters: [path("id", "Task ID", "string")]
|
||||
},
|
||||
action: user.getTask
|
||||
},
|
||||
"/user/tasks/{id}:PUT": {
|
||||
spec: {
|
||||
path: '/user/tasks/{id}',
|
||||
description: "Update a user's task",
|
||||
method: 'PUT',
|
||||
parameters: [path("id", "Task ID", "string"), body("", "Send up the whole task (see TaskSchema)", "object")]
|
||||
},
|
||||
action: user.updateTask
|
||||
},
|
||||
"/user/tasks/{id}:DELETE": {
|
||||
spec: {
|
||||
path: '/user/tasks/{id}',
|
||||
description: "Delete a task",
|
||||
method: 'DELETE',
|
||||
parameters: [path("id", "Task ID", "string")]
|
||||
},
|
||||
action: user.deleteTask
|
||||
},
|
||||
"/user/tasks/{id}/sort": {
|
||||
spec: {
|
||||
method: 'POST',
|
||||
description: 'Sort tasks',
|
||||
parameters: [path("id", "Task ID", "string"), query("from", "Index where you're sorting from (0-based)", "integer"), query("to", "Index where you're sorting to (0-based)", "integer")]
|
||||
},
|
||||
action: user.sortTask
|
||||
},
|
||||
"/user/tasks/clear-completed": {
|
||||
spec: {
|
||||
method: 'POST',
|
||||
description: "Clears competed To-Dos (needed periodically for performance)."
|
||||
},
|
||||
action: user.clearCompleted
|
||||
},
|
||||
"/user/tasks/{id}/unlink": {
|
||||
spec: {
|
||||
method: 'POST',
|
||||
description: 'Unlink a task from its challenge',
|
||||
parameters: [path("id", "Task ID", "string"), query('keep', "When unlinking a challenge task, how to handle the orphans?", 'string', ['keep', 'keep-all', 'remove', 'remove-all'])]
|
||||
},
|
||||
middleware: [auth.auth, i18n.getUserLanguage],
|
||||
action: challenges.unlink
|
||||
},
|
||||
"/user/inventory/buy": {
|
||||
spec: {
|
||||
description: "Get a list of buyable gear"
|
||||
},
|
||||
action: user.getBuyList
|
||||
},
|
||||
"/user/inventory/buy/{key}": {
|
||||
spec: {
|
||||
method: 'POST',
|
||||
description: "Buy a gear piece and equip it automatically",
|
||||
parameters: [path('key', "The key of the item to buy (call /content route for available keys)", 'string', _.keys(content.gear.flat))]
|
||||
},
|
||||
action: user.buy
|
||||
},
|
||||
"/user/inventory/sell/{type}/{key}": {
|
||||
spec: {
|
||||
method: 'POST',
|
||||
description: "Sell inventory items back to Alexander",
|
||||
parameters: [path('type', "The type of object you're selling back.", 'string', ['eggs', 'hatchingPotions', 'food']), path('key', "The object key you're selling back (call /content route for available keys)", 'string')]
|
||||
},
|
||||
action: user.sell
|
||||
},
|
||||
"/user/inventory/purchase/{type}/{key}": {
|
||||
spec: {
|
||||
method: 'POST',
|
||||
description: "Purchase a Gem-purchasable item from Alexander",
|
||||
parameters: [path('type', "The type of object you're purchasing.", 'string', ['eggs', 'hatchingPotions', 'food', 'quests', 'special']), path('key', "The object key you're purchasing (call /content route for available keys)", 'string')]
|
||||
},
|
||||
action: user.purchase
|
||||
},
|
||||
"/user/inventory/hourglass/{type}/{key}": {
|
||||
spec: {
|
||||
method: 'POST',
|
||||
description: "Purchase a pet or mount using a Mystic Hourglass",
|
||||
parameters: [path('type', "The type of object you're purchasing.", 'string', ['pets', 'mounts']), path('key', "The object key you're purchasing (call /content route for available keys)", 'string')]
|
||||
},
|
||||
action: user.hourglassPurchase
|
||||
},
|
||||
"/user/inventory/mystery/{key}": {
|
||||
spec: {
|
||||
method: 'POST',
|
||||
description: "Purchase a Mystery Item Set using a Mystic Hourglass",
|
||||
parameters: [path('key', "The key for the Mystery Set you're purchasing (call /content route for available keys)", 'string')]
|
||||
},
|
||||
action: user.buyMysterySet
|
||||
},
|
||||
"/user/inventory/feed/{pet}/{food}": {
|
||||
spec: {
|
||||
method: 'POST',
|
||||
description: "Feed your pet some food",
|
||||
parameters: [path('pet', "The key of the pet you're feeding", 'string', _.keys(content.pets)), path('food', "The key of the food to feed your pet", 'string', _.keys(content.food))]
|
||||
},
|
||||
action: user.feed
|
||||
},
|
||||
"/user/inventory/equip/{type}/{key}": {
|
||||
spec: {
|
||||
method: 'POST',
|
||||
description: "Equip an item (either pet, mount, equipped or costume)",
|
||||
parameters: [path('type', "Type to equip", 'string', ['pet', 'mount', 'equipped', 'costume']), path('key', "The object key you're equipping (call /content route for available keys)", 'string')]
|
||||
},
|
||||
action: user.equip
|
||||
},
|
||||
"/user/inventory/hatch/{egg}/{hatchingPotion}": {
|
||||
spec: {
|
||||
method: 'POST',
|
||||
description: "Pour a hatching potion on an egg",
|
||||
parameters: [path('egg', "The egg key to hatch", 'string', _.keys(content.eggs)), path('hatchingPotion', "The hatching potion to pour", 'string', _.keys(content.hatchingPotions))]
|
||||
},
|
||||
action: user.hatch
|
||||
},
|
||||
"/user:GET": {
|
||||
spec: {
|
||||
path: '/user',
|
||||
description: "Get the full user object"
|
||||
},
|
||||
action: user.getUser
|
||||
},
|
||||
"/user/anonymized": {
|
||||
spec: {
|
||||
description: "Get the user object without any personal data"
|
||||
},
|
||||
action: user.getUserAnonymized
|
||||
},
|
||||
"/user:PUT": {
|
||||
spec: {
|
||||
path: '/user',
|
||||
method: 'PUT',
|
||||
description: "Update the user object (only certain attributes are supported)",
|
||||
parameters: [body('', 'The user object (see UserSchema)', 'object')]
|
||||
},
|
||||
action: user.update
|
||||
},
|
||||
"/user:DELETE": {
|
||||
spec: {
|
||||
path: '/user',
|
||||
method: 'DELETE',
|
||||
description: "Delete a user object entirely, USE WITH CAUTION!"
|
||||
},
|
||||
middleware: [auth.auth, i18n.getUserLanguage],
|
||||
action: user["delete"]
|
||||
},
|
||||
"/user/revive": {
|
||||
spec: {
|
||||
method: 'POST',
|
||||
description: "Revive your dead user"
|
||||
},
|
||||
action: user.revive
|
||||
},
|
||||
"/user/reroll": {
|
||||
spec: {
|
||||
method: 'POST',
|
||||
description: 'Drink the Fortify Potion (Note, it used to be called re-roll)'
|
||||
},
|
||||
action: user.reroll
|
||||
},
|
||||
"/user/reset": {
|
||||
spec: {
|
||||
method: 'POST',
|
||||
description: "Completely reset your account"
|
||||
},
|
||||
action: user.reset
|
||||
},
|
||||
"/user/sleep": {
|
||||
spec: {
|
||||
method: 'POST',
|
||||
description: "Toggle whether you're resting in the inn"
|
||||
},
|
||||
action: user.sleep
|
||||
},
|
||||
"/user/rebirth": {
|
||||
spec: {
|
||||
method: 'POST',
|
||||
description: "Rebirth your avatar"
|
||||
},
|
||||
action: user.rebirth
|
||||
},
|
||||
"/user/class/change": {
|
||||
spec: {
|
||||
method: 'POST',
|
||||
description: "Either remove your avatar's class, or change it to something new",
|
||||
parameters: [query('class', "The key of the class to change to. If not provided, user's class is removed.", 'string', ['warrior', 'healer', 'rogue', 'wizard', ''])]
|
||||
},
|
||||
action: user.changeClass
|
||||
},
|
||||
"/user/class/allocate": {
|
||||
spec: {
|
||||
method: 'POST',
|
||||
description: "Allocate one point towards an attribute",
|
||||
parameters: [query('stat', 'The stat to allocate towards', 'string', ['str', 'per', 'int', 'con'])]
|
||||
},
|
||||
action: user.allocate
|
||||
},
|
||||
"/user/class/cast/{spell}": {
|
||||
spec: {
|
||||
method: 'POST',
|
||||
description: "Casts a spell on a target.",
|
||||
parameters: [path('spell', "The key of the spell to cast (see ../../common#content/index.coffee)", 'string'), query('targetType', "The type of object you're targeting", 'string', ['party', 'self', 'user', 'task']), query('targetId', "The ID of the object you're targeting", 'string')]
|
||||
},
|
||||
action: user.cast
|
||||
},
|
||||
"/user/unlock": {
|
||||
spec: {
|
||||
method: 'POST',
|
||||
description: "Unlock a certain gem-purchaseable path (or multiple paths)",
|
||||
parameters: [query('path', "The path to unlock, such as hair.green or shirts.red,shirts.blue", 'string')]
|
||||
},
|
||||
action: user.unlock
|
||||
},
|
||||
"/user/batch-update": {
|
||||
spec: {
|
||||
method: 'POST',
|
||||
description: "This is an advanced route which is useful for apps which might for example need offline support. You can send a whole batch of user-based operations, which allows you to queue them up offline and send them all at once. The format is {op:'nameOfOperation',parameters:{},body:{},query:{}}",
|
||||
parameters: [body('', 'The array of batch-operations to perform', 'object')]
|
||||
},
|
||||
middleware: [forceRefresh, auth.auth, i18n.getUserLanguage, cron, user.sessionPartyInvite],
|
||||
action: user.batchUpdate
|
||||
},
|
||||
"/user/tags/{id}:GET": {
|
||||
spec: {
|
||||
path: '/user/tags/{id}',
|
||||
method: 'GET',
|
||||
description: "Get a tag",
|
||||
parameters: [path('id', 'The id of the tag to get', 'string')]
|
||||
},
|
||||
action: user.getTag
|
||||
},
|
||||
"/user/tags:POST": {
|
||||
spec: {
|
||||
path: "/user/tags",
|
||||
method: 'POST',
|
||||
description: 'Create a new tag',
|
||||
parameters: [body('', 'New tag (see UserSchema.tags)', 'object')]
|
||||
},
|
||||
action: user.addTag
|
||||
},
|
||||
"/user/tags:GET": {
|
||||
spec: {
|
||||
path: "/user/tags",
|
||||
method: 'GET',
|
||||
description: 'List all of a user\'s tags'
|
||||
},
|
||||
action: user.getTags
|
||||
},
|
||||
"/user/tags/sort": {
|
||||
spec: {
|
||||
method: 'POST',
|
||||
description: 'Sort tags',
|
||||
parameters: [query("from", "Index where you're sorting from (0-based)", "integer"), query("to", "Index where you're sorting to (0-based)", "integer")]
|
||||
},
|
||||
action: user.sortTag
|
||||
},
|
||||
"/user/tags/{id}:PUT": {
|
||||
spec: {
|
||||
path: '/user/tags/{id}',
|
||||
method: 'PUT',
|
||||
description: "Edit a tag",
|
||||
parameters: [path('id', 'The id of the tag to edit', 'string'), body('', 'Tag edits (see UserSchema.tags)', 'object')]
|
||||
},
|
||||
action: user.updateTag
|
||||
},
|
||||
"/user/tags/{id}:DELETE": {
|
||||
spec: {
|
||||
path: '/user/tags/{id}',
|
||||
method: 'DELETE',
|
||||
description: 'Delete a tag',
|
||||
parameters: [path('id', 'Id of tag to delete', 'string')]
|
||||
},
|
||||
action: user.deleteTag
|
||||
},
|
||||
"/user/webhooks": {
|
||||
spec: {
|
||||
method: 'POST',
|
||||
description: 'Create a new webhook',
|
||||
parameters: [body('', 'New Webhook {url:"webhook endpoint (required)", id:"id of webhook (shared.uuid(), optional)", enabled:"whether webhook is enabled (true by default, optional)"}', 'object')]
|
||||
},
|
||||
action: user.addWebhook
|
||||
},
|
||||
"/user/webhooks/{id}:PUT": {
|
||||
spec: {
|
||||
path: '/user/webhooks/{id}',
|
||||
method: 'PUT',
|
||||
description: "Edit a webhook",
|
||||
parameters: [path('id', 'The id of the webhook to edit', 'string'), body('', 'New Webhook {url:"webhook endpoint (required)", id:"id of webhook (shared.uuid(), optional)", enabled:"whether webhook is enabled (true by default, optional)"}', 'object')]
|
||||
},
|
||||
action: user.updateWebhook
|
||||
},
|
||||
"/user/webhooks/{id}:DELETE": {
|
||||
spec: {
|
||||
path: '/user/webhooks/{id}',
|
||||
method: 'DELETE',
|
||||
description: 'Delete a webhook',
|
||||
parameters: [path('id', 'Id of webhook to delete', 'string')]
|
||||
},
|
||||
action: user.deleteWebhook
|
||||
},
|
||||
"/user/pushDevice": {
|
||||
spec: {
|
||||
method: 'POST',
|
||||
description: 'Add a new push devices registration ID',
|
||||
parameters: [body('', 'New push registration { regId: "123123", type: "android"}', 'object')]
|
||||
},
|
||||
action: user.addPushDevice
|
||||
},
|
||||
"/groups:GET": {
|
||||
spec: {
|
||||
path: '/groups',
|
||||
description: "Get a list of groups",
|
||||
parameters: [query('type', "Comma-separated types of groups to return, eg 'party,guilds,public,tavern'", 'string')]
|
||||
},
|
||||
middleware: [auth.auth, i18n.getUserLanguage],
|
||||
action: groups.list
|
||||
},
|
||||
"/groups:POST": {
|
||||
spec: {
|
||||
path: '/groups',
|
||||
method: 'POST',
|
||||
description: 'Create a group',
|
||||
parameters: [body('', 'Group object (see GroupSchema)', 'object')]
|
||||
},
|
||||
middleware: [auth.auth, i18n.getUserLanguage],
|
||||
action: groups.create
|
||||
},
|
||||
"/groups/{gid}:GET": {
|
||||
spec: {
|
||||
path: '/groups/{gid}',
|
||||
description: "Get a group. The party the user currently is in can be accessed with the gid 'party'.",
|
||||
parameters: [path('gid', 'Group ID', 'string')]
|
||||
},
|
||||
middleware: [auth.auth, i18n.getUserLanguage],
|
||||
action: groups.get
|
||||
},
|
||||
"/groups/{gid}:POST": {
|
||||
spec: {
|
||||
path: '/groups/{gid}',
|
||||
method: 'POST',
|
||||
description: "Edit a group",
|
||||
parameters: [body('', 'Group object (see GroupSchema)', 'object')]
|
||||
},
|
||||
middleware: [auth.auth, i18n.getUserLanguage, groups.attachGroup],
|
||||
action: groups.update
|
||||
},
|
||||
"/groups/{gid}/join": {
|
||||
spec: {
|
||||
method: 'POST',
|
||||
description: 'Join a group',
|
||||
parameters: [path('gid', 'Id of the group to join', 'string')]
|
||||
},
|
||||
middleware: [auth.auth, i18n.getUserLanguage, groups.attachGroup],
|
||||
action: groups.join
|
||||
},
|
||||
"/groups/{gid}/leave": {
|
||||
spec: {
|
||||
method: 'POST',
|
||||
description: 'Leave a group',
|
||||
parameters: [path('gid', 'ID of the group to leave', 'string')]
|
||||
},
|
||||
middleware: [auth.auth, i18n.getUserLanguage, groups.attachGroup],
|
||||
action: groups.leave
|
||||
},
|
||||
"/groups/{gid}/invite": {
|
||||
spec: {
|
||||
method: 'POST',
|
||||
description: "Invite a user to a group",
|
||||
parameters: [path('gid', 'Group id', 'string'), body('', 'a payload of invites either under body.uuids or body.emails, only one of them!', 'object')]
|
||||
},
|
||||
middleware: [auth.auth, i18n.getUserLanguage, groups.attachGroup],
|
||||
action: groups.invite
|
||||
},
|
||||
"/groups/{gid}/removeMember": {
|
||||
spec: {
|
||||
method: 'POST',
|
||||
description: "Remove / boot a member from a group",
|
||||
parameters: [path('gid', 'Group id', 'string'), query('uuid', 'User id to boot', 'string')]
|
||||
},
|
||||
middleware: [auth.auth, i18n.getUserLanguage, groups.attachGroup],
|
||||
action: groups.removeMember
|
||||
},
|
||||
"/groups/{gid}/questAccept": {
|
||||
spec: {
|
||||
method: 'POST',
|
||||
description: "Accept a quest invitation",
|
||||
parameters: [path('gid', "Group id", 'string'), query('key', "optional. if provided, trigger new invite, if not, accept existing invite", 'string')]
|
||||
},
|
||||
middleware: [auth.auth, i18n.getUserLanguage, groups.attachGroup],
|
||||
action: groups.questAccept
|
||||
},
|
||||
"/groups/{gid}/questReject": {
|
||||
spec: {
|
||||
method: 'POST',
|
||||
description: 'Reject quest invitation',
|
||||
parameters: [path('gid', 'Group id', 'string')]
|
||||
},
|
||||
middleware: [auth.auth, i18n.getUserLanguage, groups.attachGroup],
|
||||
action: groups.questReject
|
||||
},
|
||||
"/groups/{gid}/questCancel": {
|
||||
spec: {
|
||||
method: 'POST',
|
||||
description: 'Cancel quest before it starts (in invitation stage)',
|
||||
parameters: [path('gid', 'Group to cancel quest in', 'string')]
|
||||
},
|
||||
middleware: [auth.auth, i18n.getUserLanguage, groups.attachGroup],
|
||||
action: groups.questCancel
|
||||
},
|
||||
"/groups/{gid}/questAbort": {
|
||||
spec: {
|
||||
method: 'POST',
|
||||
description: 'Abort quest after it has started (all progress will be lost)',
|
||||
parameters: [path('gid', 'Group to abort quest in', 'string')]
|
||||
},
|
||||
middleware: [auth.auth, i18n.getUserLanguage, groups.attachGroup],
|
||||
action: groups.questAbort
|
||||
},
|
||||
"/groups/{gid}/questLeave": {
|
||||
spec: {
|
||||
method: 'POST',
|
||||
description: 'Leave an active quest (Quest leaders cannot leave active quests. They must abort the quest to leave)',
|
||||
parameters: [path('gid', 'Group to leave quest in', 'string')]
|
||||
},
|
||||
middleware: [auth.auth, i18n.getUserLanguage, groups.attachGroup],
|
||||
action: groups.questLeave
|
||||
},
|
||||
"/groups/{gid}/chat:GET": {
|
||||
spec: {
|
||||
path: "/groups/{gid}/chat",
|
||||
description: "Get all chat messages",
|
||||
parameters: [path('gid', 'Group to return the chat from ', 'string')]
|
||||
},
|
||||
middleware: [auth.auth, i18n.getUserLanguage, groups.attachGroup],
|
||||
action: groups.getChat
|
||||
},
|
||||
"/groups/{gid}/chat:POST": {
|
||||
spec: {
|
||||
method: 'POST',
|
||||
path: "/groups/{gid}/chat",
|
||||
description: "Send a chat message",
|
||||
parameters: [query('message', 'Chat message', 'string'), path('gid', 'Group id', 'string')]
|
||||
},
|
||||
middleware: [auth.auth, i18n.getUserLanguage, groups.attachGroup],
|
||||
action: groups.postChat
|
||||
},
|
||||
"/groups/{gid}/chat/seen": {
|
||||
spec: {
|
||||
method: 'POST',
|
||||
description: "Flag chat messages for a particular group as seen",
|
||||
parameters: [path('gid', 'Group id', 'string')]
|
||||
},
|
||||
action: groups.seenMessage
|
||||
},
|
||||
"/groups/{gid}/chat/{messageId}": {
|
||||
spec: {
|
||||
method: 'DELETE',
|
||||
description: 'Delete a chat message in a given group',
|
||||
parameters: [path('gid', 'ID of the group containing the message to be deleted', 'string'), path('messageId', 'ID of message to be deleted', 'string')]
|
||||
},
|
||||
middleware: [auth.auth, i18n.getUserLanguage, groups.attachGroup],
|
||||
action: groups.deleteChatMessage
|
||||
},
|
||||
"/groups/{gid}/chat/{mid}/like": {
|
||||
spec: {
|
||||
method: 'POST',
|
||||
description: "Like a chat message",
|
||||
parameters: [path('gid', 'Group id', 'string'), path('mid', 'Message id', 'string')]
|
||||
},
|
||||
middleware: [auth.auth, i18n.getUserLanguage, groups.attachGroup],
|
||||
action: groups.likeChatMessage
|
||||
},
|
||||
"/groups/{gid}/chat/{mid}/flag": {
|
||||
spec: {
|
||||
method: 'POST',
|
||||
description: "Flag a chat message",
|
||||
parameters: [path('gid', 'Group id', 'string'), path('mid', 'Message id', 'string')]
|
||||
},
|
||||
middleware: [auth.auth, i18n.getUserLanguage, groups.attachGroup],
|
||||
action: groups.flagChatMessage
|
||||
},
|
||||
"/groups/{gid}/chat/{mid}/clearflags": {
|
||||
spec: {
|
||||
method: 'POST',
|
||||
description: "Clear flag count from message and unhide it",
|
||||
parameters: [path('gid', 'Group id', 'string'), path('mid', 'Message id', 'string')]
|
||||
},
|
||||
middleware: [auth.auth, i18n.getUserLanguage, groups.attachGroup],
|
||||
action: groups.clearFlagCount
|
||||
},
|
||||
"/members/{uuid}:GET": {
|
||||
spec: {
|
||||
path: '/members/{uuid}',
|
||||
description: "Get a member.",
|
||||
parameters: [path('uuid', 'Member ID', 'string')]
|
||||
},
|
||||
middleware: [i18n.getUserLanguage],
|
||||
action: members.getMember
|
||||
},
|
||||
"/members/{uuid}/message": {
|
||||
spec: {
|
||||
method: 'POST',
|
||||
description: 'Send a private message to a member',
|
||||
parameters: [path('uuid', 'The UUID of the member to message', 'string'), body('', '{"message": "The private message to send"}', 'object')]
|
||||
},
|
||||
middleware: [auth.auth],
|
||||
action: members.sendPrivateMessage
|
||||
},
|
||||
"/members/{uuid}/block": {
|
||||
spec: {
|
||||
method: 'POST',
|
||||
description: 'Block a member from sending private messages',
|
||||
parameters: [path('uuid', 'The UUID of the member to message', 'string')]
|
||||
},
|
||||
middleware: [auth.auth],
|
||||
action: user.blockUser
|
||||
},
|
||||
"/members/{uuid}/gift": {
|
||||
spec: {
|
||||
method: 'POST',
|
||||
description: 'Send a gift to a member',
|
||||
parameters: [path('uuid', 'The UUID of the member', 'string'), body('', '{"type": "gems or subscription", "gems":{"amount":Number, "fromBalance":Boolean}, "subscription":{"months":Number}}', 'object')]
|
||||
},
|
||||
middleware: [auth.auth],
|
||||
action: members.sendGift
|
||||
},
|
||||
"/hall/heroes": {
|
||||
spec: {},
|
||||
middleware: [auth.auth, i18n.getUserLanguage],
|
||||
action: hall.getHeroes
|
||||
},
|
||||
"/hall/heroes/{uid}:GET": {
|
||||
spec: {
|
||||
path: "/hall/heroes/{uid}"
|
||||
},
|
||||
middleware: [auth.auth, i18n.getUserLanguage, hall.ensureAdmin],
|
||||
action: hall.getHero
|
||||
},
|
||||
"/hall/heroes/{uid}:POST": {
|
||||
spec: {
|
||||
method: 'POST',
|
||||
path: "/hall/heroes/{uid}"
|
||||
},
|
||||
middleware: [auth.auth, i18n.getUserLanguage, hall.ensureAdmin],
|
||||
action: hall.updateHero
|
||||
},
|
||||
"/hall/patrons": {
|
||||
spec: {
|
||||
parameters: [query('page', 'Page number to fetch (this list is long)', 'string')]
|
||||
},
|
||||
middleware: [auth.auth, i18n.getUserLanguage],
|
||||
action: hall.getPatrons
|
||||
},
|
||||
"/challenges:GET": {
|
||||
spec: {
|
||||
path: '/challenges',
|
||||
description: "Get a list of challenges"
|
||||
},
|
||||
middleware: [auth.auth, i18n.getUserLanguage],
|
||||
action: challenges.list
|
||||
},
|
||||
"/challenges:POST": {
|
||||
spec: {
|
||||
path: '/challenges',
|
||||
method: 'POST',
|
||||
description: "Create a challenge",
|
||||
parameters: [body('', 'Challenge object (see ChallengeSchema)', 'object')]
|
||||
},
|
||||
middleware: [auth.auth, i18n.getUserLanguage],
|
||||
action: challenges.create
|
||||
},
|
||||
"/challenges/{cid}:GET": {
|
||||
spec: {
|
||||
path: '/challenges/{cid}',
|
||||
description: 'Get a challenge',
|
||||
parameters: [path('cid', 'Challenge id', 'string')]
|
||||
},
|
||||
middleware: [auth.auth, i18n.getUserLanguage],
|
||||
action: challenges.get
|
||||
},
|
||||
"/challenges/{cid}/csv": {
|
||||
spec: {
|
||||
description: 'Get a challenge (csv format)',
|
||||
parameters: [path('cid', 'Challenge id', 'string')]
|
||||
},
|
||||
action: challenges.csv
|
||||
},
|
||||
"/challenges/{cid}:POST": {
|
||||
spec: {
|
||||
path: '/challenges/{cid}',
|
||||
method: 'POST',
|
||||
description: "Update a challenge",
|
||||
parameters: [path('cid', 'Challenge id', 'string'), body('', 'Challenge object (see ChallengeSchema)', 'object')]
|
||||
},
|
||||
middleware: [auth.auth, i18n.getUserLanguage],
|
||||
action: challenges.update
|
||||
},
|
||||
"/challenges/{cid}:DELETE": {
|
||||
spec: {
|
||||
path: '/challenges/{cid}',
|
||||
method: 'DELETE',
|
||||
description: "Delete a challenge",
|
||||
parameters: [path('cid', 'Challenge id', 'string')]
|
||||
},
|
||||
middleware: [auth.auth, i18n.getUserLanguage],
|
||||
action: challenges["delete"]
|
||||
},
|
||||
"/challenges/{cid}/close": {
|
||||
spec: {
|
||||
method: 'POST',
|
||||
description: 'Close a challenge',
|
||||
parameters: [path('cid', 'Challenge id', 'string'), query('uid', 'User ID of the winner', 'string', true)]
|
||||
},
|
||||
middleware: [auth.auth, i18n.getUserLanguage],
|
||||
action: challenges.selectWinner
|
||||
},
|
||||
"/challenges/{cid}/join": {
|
||||
spec: {
|
||||
method: 'POST',
|
||||
description: "Join a challenge",
|
||||
parameters: [path('cid', 'Challenge id', 'string')]
|
||||
},
|
||||
middleware: [auth.auth, i18n.getUserLanguage],
|
||||
action: challenges.join
|
||||
},
|
||||
"/challenges/{cid}/leave": {
|
||||
spec: {
|
||||
method: 'POST',
|
||||
description: 'Leave a challenge',
|
||||
parameters: [path('cid', 'Challenge id', 'string')]
|
||||
},
|
||||
middleware: [auth.auth, i18n.getUserLanguage],
|
||||
action: challenges.leave
|
||||
},
|
||||
"/challenges/{cid}/member/{uid}": {
|
||||
spec: {
|
||||
description: "Get a member's progress in a particular challenge",
|
||||
parameters: [path('cid', 'Challenge id', 'string'), path('uid', 'User id', 'string')]
|
||||
},
|
||||
middleware: [auth.auth, i18n.getUserLanguage],
|
||||
action: challenges.getMember
|
||||
}
|
||||
};
|
||||
if (nconf.get("NODE_ENV") === "development") {
|
||||
api["/user/addTenGems"] = {
|
||||
spec: {
|
||||
method: 'POST'
|
||||
},
|
||||
action: user.addTenGems
|
||||
};
|
||||
api["/user/addHourglass"] = {
|
||||
spec: {
|
||||
method: 'POST'
|
||||
},
|
||||
action: user.addHourglass
|
||||
};
|
||||
};
|
||||
|
||||
_.each(api, function(route, path) {
|
||||
var base;
|
||||
if ((base = route.spec).description == null) {
|
||||
base.description = '';
|
||||
}
|
||||
_.defaults(route.spec, {
|
||||
path: path,
|
||||
nickname: path,
|
||||
notes: route.spec.description,
|
||||
summary: route.spec.description,
|
||||
parameters: [],
|
||||
errorResponses: [],
|
||||
method: 'GET'
|
||||
});
|
||||
if (route.middleware == null) {
|
||||
route.middleware = path.indexOf('/user') === 0 ? [auth.auth, i18n.getUserLanguage, cron] : [i18n.getUserLanguage];
|
||||
}
|
||||
swagger["add" + route.spec.method](route);
|
||||
return true;
|
||||
});
|
||||
|
||||
return swagger.configure((nconf.get('BASE_URL')) + "/api/v2", "2");
|
||||
};
|
||||
@@ -1,7 +1,7 @@
|
||||
var express = require('express');
|
||||
var router = new express.Router();
|
||||
var i18n = require('../i18n');
|
||||
var unsubscription = require('../controllers/unsubscription');
|
||||
var i18n = require('../../libs/i18n');
|
||||
var unsubscription = require('../../controllers/api-v2/unsubscription');
|
||||
|
||||
router.get('/unsubscribe', i18n.getUserLanguage, unsubscription.unsubscribe);
|
||||
|
||||
@@ -1,853 +0,0 @@
|
||||
###
|
||||
---------- /api/v2 API ------------
|
||||
see https://github.com/wordnik/swagger-node-express
|
||||
Every url added to router is prefaced by /api/v2
|
||||
Note: Many user-route ops exist in ../../common/script/index.coffee#user.ops, so that they can (1) be called both
|
||||
client and server.
|
||||
v1 user. Requires x-api-user (user id) and x-api-key (api key) headers, Test with:
|
||||
$ mocha test/user.mocha.coffee
|
||||
###
|
||||
|
||||
user = require("../controllers/user")
|
||||
groups = require("../controllers/groups")
|
||||
members = require("../controllers/members")
|
||||
auth = require("../controllers/auth")
|
||||
hall = require("../controllers/hall")
|
||||
challenges = require("../controllers/challenges")
|
||||
dataexport = require("../controllers/dataexport")
|
||||
nconf = require("nconf")
|
||||
cron = user.cron
|
||||
_ = require('lodash')
|
||||
content = require('../../../common').content
|
||||
i18n = require('../i18n')
|
||||
forceRefresh = require('../middlewares/forceRefresh').middleware
|
||||
|
||||
module.exports = (swagger, v2) ->
|
||||
[path,body,query] = [swagger.pathParam, swagger.bodyParam, swagger.queryParam]
|
||||
|
||||
swagger.setAppHandler(v2)
|
||||
swagger.setErrorHandler("next")
|
||||
swagger.setHeaders = -> #disable setHeaders, since we have our own thing going on in middleware.js (and which requires `req`, which swagger doesn't pass in)
|
||||
swagger.configureSwaggerPaths("", "/api-docs", "")
|
||||
|
||||
api =
|
||||
|
||||
'/status':
|
||||
spec:
|
||||
description: "Returns the status of the server (up or down). Does not require authentication."
|
||||
action: (req, res) ->
|
||||
res.json status: "up"
|
||||
|
||||
'/content':
|
||||
spec:
|
||||
description: "Get all available content objects. This is essential, since Habit often depends on item keys (eg, when purchasing a weapon). Does not require authentication."
|
||||
parameters: [
|
||||
query("language","Optional language to use for content's strings. Default is english.","string")
|
||||
]
|
||||
action: user.getContent
|
||||
|
||||
'/content/paths':
|
||||
spec:
|
||||
description: "Show user model tree. Does not require authentication."
|
||||
action: user.getModelPaths
|
||||
|
||||
"/export/history":
|
||||
spec:
|
||||
description: "Export user history"
|
||||
method: 'GET'
|
||||
middleware: [auth.auth, i18n.getUserLanguage]
|
||||
action: dataexport.history #[todo] encode data output options in the data controller and use these to build routes
|
||||
|
||||
# ---------------------------------
|
||||
# User
|
||||
# ---------------------------------
|
||||
|
||||
# Scoring
|
||||
|
||||
"/user/tasks/{id}/{direction}":
|
||||
spec:
|
||||
#notes: "Simple scoring of a task."
|
||||
description: "Simple scoring of a task (Habit, Daily, To-Do, or Reward). This is most-likely the only API route you'll be using as a 3rd-party developer. The most common operation is for the user to gain or lose points based on some action (browsing Reddit, running a mile, 1 Pomodor, etc). Call this route, if the task you're trying to score doesn't exist, it will be created for you. When random events occur, the <b>user._tmp</b> variable will be filled. Critical hits can be accessed through <b>user._tmp.crit</b>. The Streakbonus can be accessed through <b>user._tmp.streakBonus</b>. Both will contain the multiplier value. When random drops occur, the following values are available: <b>user._tmp.drop = {text,type,dialog,value,key,notes}</b>"
|
||||
parameters: [
|
||||
path("id", "ID of the task to score. If this task doesn't exist, a task will be created automatically", "string")
|
||||
path("direction", "Either 'up' or 'down'", "string")
|
||||
body '',"If you're creating a 3rd-party task, pass up any task attributes in the body (see TaskSchema).",'object'
|
||||
]
|
||||
method: 'POST'
|
||||
action: user.score
|
||||
|
||||
# Tasks
|
||||
"/user/tasks:GET":
|
||||
spec:
|
||||
path: '/user/tasks'
|
||||
description: "Get all user's tasks"
|
||||
action: user.getTasks
|
||||
|
||||
"/user/tasks:POST":
|
||||
spec:
|
||||
path: '/user/tasks'
|
||||
description: "Create a task"
|
||||
method: 'POST'
|
||||
parameters: [ body "","Send up the whole task (see TaskSchema)","object" ]
|
||||
action: user.addTask
|
||||
|
||||
"/user/tasks/{id}:GET":
|
||||
spec:
|
||||
path: '/user/tasks/{id}'
|
||||
description: "Get an individual task"
|
||||
parameters: [
|
||||
path("id", "Task ID", "string")
|
||||
]
|
||||
action: user.getTask
|
||||
|
||||
"/user/tasks/{id}:PUT":
|
||||
spec:
|
||||
path: '/user/tasks/{id}'
|
||||
description: "Update a user's task"
|
||||
method: 'PUT'
|
||||
parameters: [
|
||||
path "id", "Task ID", "string"
|
||||
body "","Send up the whole task (see TaskSchema)","object"
|
||||
]
|
||||
action: user.updateTask
|
||||
|
||||
"/user/tasks/{id}:DELETE":
|
||||
spec:
|
||||
path: '/user/tasks/{id}'
|
||||
description: "Delete a task"
|
||||
method: 'DELETE'
|
||||
parameters: [ path("id", "Task ID", "string") ]
|
||||
action: user.deleteTask
|
||||
|
||||
|
||||
"/user/tasks/{id}/sort":
|
||||
spec:
|
||||
method: 'POST'
|
||||
description: 'Sort tasks'
|
||||
parameters: [
|
||||
path("id", "Task ID", "string")
|
||||
query("from","Index where you're sorting from (0-based)","integer")
|
||||
query("to","Index where you're sorting to (0-based)","integer")
|
||||
]
|
||||
action: user.sortTask
|
||||
|
||||
|
||||
"/user/tasks/clear-completed":
|
||||
spec:
|
||||
method: 'POST'
|
||||
description: "Clears competed To-Dos (needed periodically for performance)."
|
||||
action: user.clearCompleted
|
||||
|
||||
|
||||
"/user/tasks/{id}/unlink":
|
||||
spec:
|
||||
method: 'POST'
|
||||
description: 'Unlink a task from its challenge'
|
||||
parameters: [
|
||||
path("id", "Task ID", "string")
|
||||
query 'keep',"When unlinking a challenge task, how to handle the orphans?",'string',['keep','keep-all','remove','remove-all']
|
||||
]
|
||||
middleware: [auth.auth, i18n.getUserLanguage] ## removing cron since they may want to remove task first
|
||||
action: challenges.unlink
|
||||
|
||||
|
||||
# Inventory
|
||||
"/user/inventory/buy":
|
||||
spec:
|
||||
description: "Get a list of buyable gear"
|
||||
action: user.getBuyList
|
||||
|
||||
"/user/inventory/buy/{key}":
|
||||
spec:
|
||||
method: 'POST'
|
||||
description: "Buy a gear piece and equip it automatically"
|
||||
parameters:[
|
||||
path 'key',"The key of the item to buy (call /content route for available keys)",'string', _.keys(content.gear.flat)
|
||||
]
|
||||
action: user.buy
|
||||
|
||||
"/user/inventory/sell/{type}/{key}":
|
||||
spec:
|
||||
method: 'POST'
|
||||
description: "Sell inventory items back to Alexander"
|
||||
parameters: [
|
||||
#TODO verify these are the correct types
|
||||
path('type',"The type of object you're selling back.",'string',['eggs','hatchingPotions','food'])
|
||||
path('key',"The object key you're selling back (call /content route for available keys)",'string')
|
||||
]
|
||||
action: user.sell
|
||||
|
||||
"/user/inventory/purchase/{type}/{key}":
|
||||
spec:
|
||||
method: 'POST'
|
||||
description: "Purchase a Gem-purchasable item from Alexander"
|
||||
parameters:[
|
||||
path('type',"The type of object you're purchasing.",'string',['eggs','hatchingPotions','food','quests','special'])
|
||||
path('key',"The object key you're purchasing (call /content route for available keys)",'string')
|
||||
]
|
||||
action: user.purchase
|
||||
|
||||
"/user/inventory/hourglass/{type}/{key}":
|
||||
spec:
|
||||
method: 'POST'
|
||||
description: "Purchase a pet or mount using a Mystic Hourglass"
|
||||
parameters:[
|
||||
path('type',"The type of object you're purchasing.",'string',['pets','mounts'])
|
||||
path('key',"The object key you're purchasing (call /content route for available keys)",'string')
|
||||
]
|
||||
action: user.hourglassPurchase
|
||||
|
||||
"/user/inventory/mystery/{key}":
|
||||
spec:
|
||||
method: 'POST'
|
||||
description: "Purchase a Mystery Item Set using a Mystic Hourglass"
|
||||
parameters:[
|
||||
path('key',"The key for the Mystery Set you're purchasing (call /content route for available keys)",'string')
|
||||
]
|
||||
action: user.buyMysterySet
|
||||
|
||||
"/user/inventory/feed/{pet}/{food}":
|
||||
spec:
|
||||
method: 'POST'
|
||||
description: "Feed your pet some food"
|
||||
parameters: [
|
||||
path 'pet',"The key of the pet you're feeding",'string',_.keys(content.pets)
|
||||
path 'food',"The key of the food to feed your pet",'string',_.keys(content.food)
|
||||
]
|
||||
action: user.feed
|
||||
|
||||
"/user/inventory/equip/{type}/{key}":
|
||||
spec:
|
||||
method: 'POST'
|
||||
description: "Equip an item (either pet, mount, equipped or costume)"
|
||||
parameters: [
|
||||
path 'type',"Type to equip",'string',['pet','mount','equipped', 'costume']
|
||||
path 'key',"The object key you're equipping (call /content route for available keys)",'string'
|
||||
]
|
||||
action: user.equip
|
||||
|
||||
"/user/inventory/hatch/{egg}/{hatchingPotion}":
|
||||
spec:
|
||||
method: 'POST'
|
||||
description: "Pour a hatching potion on an egg"
|
||||
parameters: [
|
||||
path 'egg',"The egg key to hatch",'string',_.keys(content.eggs)
|
||||
path 'hatchingPotion',"The hatching potion to pour",'string',_.keys(content.hatchingPotions)
|
||||
]
|
||||
action: user.hatch
|
||||
|
||||
|
||||
# User
|
||||
"/user:GET":
|
||||
spec:
|
||||
path: '/user'
|
||||
description: "Get the full user object"
|
||||
action: user.getUser
|
||||
|
||||
"/user/anonymized":
|
||||
spec:
|
||||
description: "Get the user object without any personal data"
|
||||
action: user.getUserAnonymized
|
||||
|
||||
"/user:PUT":
|
||||
spec:
|
||||
path: '/user'
|
||||
method: 'PUT'
|
||||
description: "Update the user object (only certain attributes are supported)"
|
||||
parameters: [
|
||||
body '','The user object (see UserSchema)','object'
|
||||
]
|
||||
action: user.update
|
||||
|
||||
"/user:DELETE":
|
||||
spec:
|
||||
path: '/user'
|
||||
method: 'DELETE'
|
||||
description: "Delete a user object entirely, USE WITH CAUTION!"
|
||||
middleware: [auth.auth, i18n.getUserLanguage]
|
||||
action: user.delete
|
||||
|
||||
"/user/revive":
|
||||
spec:
|
||||
method: 'POST'
|
||||
description: "Revive your dead user"
|
||||
action: user.revive
|
||||
|
||||
"/user/reroll":
|
||||
spec:
|
||||
method: 'POST'
|
||||
description: 'Drink the Fortify Potion (Note, it used to be called re-roll)'
|
||||
action: user.reroll
|
||||
|
||||
"/user/reset":
|
||||
spec:
|
||||
method: 'POST'
|
||||
description: "Completely reset your account"
|
||||
action: user.reset
|
||||
|
||||
"/user/sleep":
|
||||
spec:
|
||||
method: 'POST'
|
||||
description: "Toggle whether you're resting in the inn"
|
||||
action: user.sleep
|
||||
|
||||
"/user/rebirth":
|
||||
spec:
|
||||
method: 'POST'
|
||||
description: "Rebirth your avatar"
|
||||
action: user.rebirth
|
||||
|
||||
"/user/class/change":
|
||||
spec:
|
||||
method: 'POST'
|
||||
description: "Either remove your avatar's class, or change it to something new"
|
||||
parameters: [
|
||||
query 'class',"The key of the class to change to. If not provided, user's class is removed.",'string',['warrior','healer','rogue','wizard','']
|
||||
]
|
||||
action: user.changeClass
|
||||
|
||||
"/user/class/allocate":
|
||||
spec:
|
||||
method: 'POST'
|
||||
description: "Allocate one point towards an attribute"
|
||||
parameters: [
|
||||
query 'stat','The stat to allocate towards','string',['str','per','int','con']
|
||||
]
|
||||
action:user.allocate
|
||||
|
||||
"/user/class/cast/{spell}":
|
||||
spec:
|
||||
method: 'POST'
|
||||
description: "Casts a spell on a target."
|
||||
parameters: [
|
||||
path 'spell',"The key of the spell to cast (see ../../common#content/index.coffee)",'string'
|
||||
query 'targetType',"The type of object you're targeting",'string',['party','self','user','task']
|
||||
query 'targetId',"The ID of the object you're targeting",'string'
|
||||
|
||||
]
|
||||
action: user.cast
|
||||
|
||||
"/user/unlock":
|
||||
spec:
|
||||
method: 'POST'
|
||||
description: "Unlock a certain gem-purchaseable path (or multiple paths)"
|
||||
parameters: [
|
||||
query 'path',"The path to unlock, such as hair.green or shirts.red,shirts.blue",'string'
|
||||
]
|
||||
action: user.unlock
|
||||
|
||||
"/user/batch-update":
|
||||
spec:
|
||||
method: 'POST'
|
||||
description: "This is an advanced route which is useful for apps which might for example need offline support. You can send a whole batch of user-based operations, which allows you to queue them up offline and send them all at once. The format is {op:'nameOfOperation',parameters:{},body:{},query:{}}"
|
||||
parameters:[
|
||||
body '','The array of batch-operations to perform','object'
|
||||
]
|
||||
middleware: [forceRefresh, auth.auth, i18n.getUserLanguage, cron, user.sessionPartyInvite]
|
||||
action: user.batchUpdate
|
||||
|
||||
# Tags
|
||||
"/user/tags/{id}:GET":
|
||||
spec:
|
||||
path: '/user/tags/{id}'
|
||||
method: 'GET'
|
||||
description: "Get a tag"
|
||||
parameters: [
|
||||
path 'id','The id of the tag to get','string'
|
||||
]
|
||||
action: user.getTag
|
||||
|
||||
"/user/tags:POST":
|
||||
spec:
|
||||
path: "/user/tags"
|
||||
method: 'POST'
|
||||
description: 'Create a new tag'
|
||||
parameters: [
|
||||
body '','New tag (see UserSchema.tags)','object'
|
||||
]
|
||||
action: user.addTag
|
||||
|
||||
"/user/tags:GET":
|
||||
spec:
|
||||
path: "/user/tags"
|
||||
method: 'GET'
|
||||
description: 'List all of a user\'s tags'
|
||||
action: user.getTags
|
||||
|
||||
"/user/tags/sort":
|
||||
spec:
|
||||
method: 'POST'
|
||||
description: 'Sort tags'
|
||||
parameters: [
|
||||
query("from","Index where you're sorting from (0-based)","integer")
|
||||
query("to","Index where you're sorting to (0-based)","integer")
|
||||
]
|
||||
action: user.sortTag
|
||||
|
||||
"/user/tags/{id}:PUT":
|
||||
spec:
|
||||
path: '/user/tags/{id}'
|
||||
method: 'PUT'
|
||||
description: "Edit a tag"
|
||||
parameters: [
|
||||
path 'id','The id of the tag to edit','string'
|
||||
body '','Tag edits (see UserSchema.tags)','object'
|
||||
]
|
||||
action: user.updateTag
|
||||
|
||||
"/user/tags/{id}:DELETE":
|
||||
spec:
|
||||
path: '/user/tags/{id}'
|
||||
method: 'DELETE'
|
||||
description: 'Delete a tag'
|
||||
parameters: [
|
||||
path 'id','Id of tag to delete','string'
|
||||
]
|
||||
action: user.deleteTag
|
||||
|
||||
# Webhooks
|
||||
"/user/webhooks":
|
||||
spec:
|
||||
method: 'POST'
|
||||
description: 'Create a new webhook'
|
||||
parameters: [
|
||||
body '','New Webhook {url:"webhook endpoint (required)", id:"id of webhook (shared.uuid(), optional)", enabled:"whether webhook is enabled (true by default, optional)"}','object'
|
||||
]
|
||||
action: user.addWebhook
|
||||
|
||||
"/user/webhooks/{id}:PUT":
|
||||
spec:
|
||||
path: '/user/webhooks/{id}'
|
||||
method: 'PUT'
|
||||
description: "Edit a webhook"
|
||||
parameters: [
|
||||
path 'id','The id of the webhook to edit','string'
|
||||
body '','New Webhook {url:"webhook endpoint (required)", id:"id of webhook (shared.uuid(), optional)", enabled:"whether webhook is enabled (true by default, optional)"}','object'
|
||||
]
|
||||
action: user.updateWebhook
|
||||
|
||||
"/user/webhooks/{id}:DELETE":
|
||||
spec:
|
||||
path: '/user/webhooks/{id}'
|
||||
method: 'DELETE'
|
||||
description: 'Delete a webhook'
|
||||
parameters: [
|
||||
path 'id','Id of webhook to delete','string'
|
||||
]
|
||||
action: user.deleteWebhook
|
||||
|
||||
# Push Notifications
|
||||
"/user/pushDevice":
|
||||
spec:
|
||||
method: 'POST'
|
||||
description: 'Add a new push devices registration ID'
|
||||
parameters: [
|
||||
body '','New push registration { regId: "123123", type: "android"}','object'
|
||||
]
|
||||
action: user.addPushDevice
|
||||
|
||||
# ---------------------------------
|
||||
# Groups
|
||||
# ---------------------------------
|
||||
"/groups:GET":
|
||||
spec:
|
||||
path: '/groups'
|
||||
description: "Get a list of groups"
|
||||
parameters: [
|
||||
query 'type',"Comma-separated types of groups to return, eg 'party,guilds,public,tavern'",'string'
|
||||
]
|
||||
middleware: [auth.auth, i18n.getUserLanguage]
|
||||
action: groups.list
|
||||
|
||||
|
||||
"/groups:POST":
|
||||
spec:
|
||||
path: '/groups'
|
||||
method: 'POST'
|
||||
description: 'Create a group'
|
||||
parameters: [
|
||||
body '','Group object (see GroupSchema)','object'
|
||||
]
|
||||
middleware: [auth.auth, i18n.getUserLanguage]
|
||||
action: groups.create
|
||||
|
||||
"/groups/{gid}:GET":
|
||||
spec:
|
||||
path: '/groups/{gid}'
|
||||
description: "Get a group. The party the user currently is in can be accessed with the gid 'party'."
|
||||
parameters: [path('gid','Group ID','string')]
|
||||
middleware: [auth.auth, i18n.getUserLanguage]
|
||||
action: groups.get
|
||||
|
||||
"/groups/{gid}:POST":
|
||||
spec:
|
||||
path: '/groups/{gid}'
|
||||
method: 'POST'
|
||||
description: "Edit a group"
|
||||
parameters: [body('','Group object (see GroupSchema)','object')]
|
||||
middleware: [auth.auth, i18n.getUserLanguage, groups.attachGroup]
|
||||
action: groups.update
|
||||
|
||||
"/groups/{gid}/join":
|
||||
spec:
|
||||
method: 'POST'
|
||||
description: 'Join a group'
|
||||
parameters: [path('gid','Id of the group to join','string')]
|
||||
middleware: [auth.auth, i18n.getUserLanguage, groups.attachGroup]
|
||||
action: groups.join
|
||||
|
||||
"/groups/{gid}/leave":
|
||||
spec:
|
||||
method: 'POST'
|
||||
description: 'Leave a group'
|
||||
parameters: [path('gid','ID of the group to leave','string')]
|
||||
middleware: [auth.auth, i18n.getUserLanguage, groups.attachGroup]
|
||||
action: groups.leave
|
||||
|
||||
"/groups/{gid}/invite":
|
||||
spec:
|
||||
method: 'POST'
|
||||
description: "Invite a user to a group"
|
||||
parameters: [
|
||||
path 'gid','Group id','string'
|
||||
body '','a payload of invites either under body.uuids or body.emails, only one of them!','object'
|
||||
]
|
||||
middleware: [auth.auth, i18n.getUserLanguage, groups.attachGroup]
|
||||
action:groups.invite
|
||||
|
||||
"/groups/{gid}/removeMember":
|
||||
spec:
|
||||
method: 'POST'
|
||||
description: "Remove / boot a member from a group"
|
||||
parameters: [
|
||||
path 'gid','Group id','string'
|
||||
query 'uuid','User id to boot','string'
|
||||
]
|
||||
middleware: [auth.auth, i18n.getUserLanguage, groups.attachGroup]
|
||||
action:groups.removeMember
|
||||
|
||||
"/groups/{gid}/questAccept":
|
||||
spec:
|
||||
method: 'POST'
|
||||
description: "Accept a quest invitation"
|
||||
parameters: [
|
||||
path 'gid',"Group id",'string'
|
||||
query 'key',"optional. if provided, trigger new invite, if not, accept existing invite",'string'
|
||||
]
|
||||
middleware: [auth.auth, i18n.getUserLanguage, groups.attachGroup]
|
||||
action:groups.questAccept
|
||||
|
||||
"/groups/{gid}/questReject":
|
||||
spec:
|
||||
method: 'POST'
|
||||
description: 'Reject quest invitation'
|
||||
parameters: [
|
||||
path 'gid','Group id','string'
|
||||
]
|
||||
middleware: [auth.auth, i18n.getUserLanguage, groups.attachGroup]
|
||||
action: groups.questReject
|
||||
|
||||
"/groups/{gid}/questCancel":
|
||||
spec:
|
||||
method: 'POST'
|
||||
description: 'Cancel quest before it starts (in invitation stage)'
|
||||
parameters: [path('gid','Group to cancel quest in','string')]
|
||||
middleware: [auth.auth, i18n.getUserLanguage, groups.attachGroup]
|
||||
action: groups.questCancel
|
||||
|
||||
"/groups/{gid}/questAbort":
|
||||
spec:
|
||||
method: 'POST'
|
||||
description: 'Abort quest after it has started (all progress will be lost)'
|
||||
parameters: [path('gid','Group to abort quest in','string')]
|
||||
middleware: [auth.auth, i18n.getUserLanguage, groups.attachGroup]
|
||||
action: groups.questAbort
|
||||
|
||||
"/groups/{gid}/questLeave":
|
||||
spec:
|
||||
method: 'POST'
|
||||
description: 'Leave an active quest (Quest leaders cannot leave active quests. They must abort the quest to leave)'
|
||||
parameters: [path('gid','Group to leave quest in','string')]
|
||||
middleware: [auth.auth, i18n.getUserLanguage, groups.attachGroup]
|
||||
action: groups.questLeave
|
||||
|
||||
#TODO PUT /groups/:gid/chat/:messageId
|
||||
|
||||
"/groups/{gid}/chat:GET":
|
||||
spec:
|
||||
path: "/groups/{gid}/chat"
|
||||
description: "Get all chat messages"
|
||||
parameters: [path('gid','Group to return the chat from ','string')]
|
||||
middleware: [auth.auth, i18n.getUserLanguage, groups.attachGroup]
|
||||
action: groups.getChat
|
||||
|
||||
|
||||
"/groups/{gid}/chat:POST":
|
||||
spec:
|
||||
method: 'POST'
|
||||
path: "/groups/{gid}/chat"
|
||||
description: "Send a chat message"
|
||||
parameters: [
|
||||
query 'message', 'Chat message','string'
|
||||
path 'gid','Group id','string'
|
||||
]
|
||||
middleware: [auth.auth, i18n.getUserLanguage, groups.attachGroup]
|
||||
action: groups.postChat
|
||||
|
||||
# placing before route below, so that if !=='seen' it goes to next()
|
||||
"/groups/{gid}/chat/seen":
|
||||
spec:
|
||||
method: 'POST'
|
||||
description: "Flag chat messages for a particular group as seen"
|
||||
parameters: [
|
||||
path 'gid','Group id','string'
|
||||
]
|
||||
action: groups.seenMessage
|
||||
|
||||
"/groups/{gid}/chat/{messageId}":
|
||||
spec:
|
||||
method: 'DELETE'
|
||||
description: 'Delete a chat message in a given group'
|
||||
parameters: [
|
||||
path 'gid', 'ID of the group containing the message to be deleted', 'string'
|
||||
path 'messageId', 'ID of message to be deleted', 'string'
|
||||
]
|
||||
middleware: [auth.auth, i18n.getUserLanguage, groups.attachGroup]
|
||||
action: groups.deleteChatMessage
|
||||
|
||||
"/groups/{gid}/chat/{mid}/like":
|
||||
spec:
|
||||
method: 'POST'
|
||||
description: "Like a chat message"
|
||||
parameters: [
|
||||
path 'gid','Group id','string'
|
||||
path 'mid','Message id','string'
|
||||
]
|
||||
middleware: [auth.auth, i18n.getUserLanguage, groups.attachGroup]
|
||||
action: groups.likeChatMessage
|
||||
|
||||
"/groups/{gid}/chat/{mid}/flag":
|
||||
spec:
|
||||
method: 'POST'
|
||||
description: "Flag a chat message"
|
||||
parameters: [
|
||||
path 'gid','Group id','string'
|
||||
path 'mid','Message id','string'
|
||||
]
|
||||
middleware: [auth.auth, i18n.getUserLanguage, groups.attachGroup]
|
||||
action: groups.flagChatMessage
|
||||
|
||||
"/groups/{gid}/chat/{mid}/clearflags":
|
||||
spec:
|
||||
method: 'POST'
|
||||
description: "Clear flag count from message and unhide it"
|
||||
parameters: [
|
||||
path 'gid','Group id','string'
|
||||
path 'mid','Message id','string'
|
||||
]
|
||||
middleware: [auth.auth, i18n.getUserLanguage, groups.attachGroup]
|
||||
action: groups.clearFlagCount
|
||||
|
||||
# ---------------------------------
|
||||
# Members
|
||||
# ---------------------------------
|
||||
"/members/{uuid}:GET":
|
||||
spec:
|
||||
path: '/members/{uuid}'
|
||||
description: "Get a member."
|
||||
parameters: [path('uuid','Member ID','string')]
|
||||
middleware: [i18n.getUserLanguage] # removed auth.auth, so anon users can view shared avatars
|
||||
action: members.getMember
|
||||
"/members/{uuid}/message":
|
||||
spec:
|
||||
method: 'POST'
|
||||
description: 'Send a private message to a member'
|
||||
parameters: [
|
||||
path 'uuid', 'The UUID of the member to message', 'string'
|
||||
body '', '{"message": "The private message to send"}', 'object'
|
||||
]
|
||||
middleware: [auth.auth]
|
||||
action: members.sendPrivateMessage
|
||||
"/members/{uuid}/block":
|
||||
spec:
|
||||
method: 'POST'
|
||||
description: 'Block a member from sending private messages'
|
||||
parameters: [
|
||||
path 'uuid', 'The UUID of the member to message', 'string'
|
||||
]
|
||||
middleware: [auth.auth]
|
||||
action: user.blockUser
|
||||
"/members/{uuid}/gift":
|
||||
spec:
|
||||
method: 'POST'
|
||||
description: 'Send a gift to a member'
|
||||
parameters: [
|
||||
path 'uuid', 'The UUID of the member', 'string'
|
||||
body '', '{"type": "gems or subscription", "gems":{"amount":Number, "fromBalance":Boolean}, "subscription":{"months":Number}}', 'object'
|
||||
]
|
||||
middleware: [auth.auth]
|
||||
action: members.sendGift
|
||||
|
||||
# ---------------------------------
|
||||
# Hall of Heroes / Patrons
|
||||
# ---------------------------------
|
||||
"/hall/heroes":
|
||||
spec: {}
|
||||
middleware:[auth.auth, i18n.getUserLanguage]
|
||||
action: hall.getHeroes
|
||||
|
||||
"/hall/heroes/{uid}:GET":
|
||||
spec: path: "/hall/heroes/{uid}"
|
||||
middleware:[auth.auth, i18n.getUserLanguage, hall.ensureAdmin]
|
||||
action: hall.getHero
|
||||
|
||||
"/hall/heroes/{uid}:POST":
|
||||
spec:
|
||||
method: 'POST'
|
||||
path: "/hall/heroes/{uid}"
|
||||
middleware: [auth.auth, i18n.getUserLanguage, hall.ensureAdmin]
|
||||
action: hall.updateHero
|
||||
|
||||
"/hall/patrons":
|
||||
spec:
|
||||
parameters: [
|
||||
query 'page','Page number to fetch (this list is long)','string'
|
||||
]
|
||||
middleware:[auth.auth, i18n.getUserLanguage]
|
||||
action: hall.getPatrons
|
||||
|
||||
|
||||
# ---------------------------------
|
||||
# Challenges
|
||||
# ---------------------------------
|
||||
|
||||
# Note: while challenges belong to groups, and would therefore make sense as a nested resource
|
||||
# (eg /groups/:gid/challenges/:cid), they will also be referenced by users from the "challenges" tab
|
||||
# without knowing which group they belong to. So to prevent unecessary lookups, we have them as a top-level resource
|
||||
"/challenges:GET":
|
||||
spec:
|
||||
path: '/challenges'
|
||||
description: "Get a list of challenges"
|
||||
middleware: [auth.auth, i18n.getUserLanguage]
|
||||
action: challenges.list
|
||||
|
||||
|
||||
"/challenges:POST":
|
||||
spec:
|
||||
path: '/challenges'
|
||||
method: 'POST'
|
||||
description: "Create a challenge"
|
||||
parameters: [body('','Challenge object (see ChallengeSchema)','object')]
|
||||
middleware: [auth.auth, i18n.getUserLanguage]
|
||||
action: challenges.create
|
||||
|
||||
"/challenges/{cid}:GET":
|
||||
spec:
|
||||
path: '/challenges/{cid}'
|
||||
description: 'Get a challenge'
|
||||
parameters: [path('cid','Challenge id','string')]
|
||||
middleware: [auth.auth, i18n.getUserLanguage]
|
||||
action: challenges.get
|
||||
|
||||
"/challenges/{cid}/csv":
|
||||
spec:
|
||||
description: 'Get a challenge (csv format)'
|
||||
parameters: [path('cid','Challenge id','string')]
|
||||
action: challenges.csv
|
||||
|
||||
"/challenges/{cid}:POST":
|
||||
spec:
|
||||
path: '/challenges/{cid}'
|
||||
method: 'POST'
|
||||
description: "Update a challenge"
|
||||
parameters: [
|
||||
path 'cid','Challenge id','string'
|
||||
body('','Challenge object (see ChallengeSchema)','object')
|
||||
]
|
||||
middleware: [auth.auth, i18n.getUserLanguage]
|
||||
action: challenges.update
|
||||
|
||||
"/challenges/{cid}:DELETE":
|
||||
spec:
|
||||
path: '/challenges/{cid}'
|
||||
method: 'DELETE'
|
||||
description: "Delete a challenge"
|
||||
parameters: [path('cid','Challenge id','string')]
|
||||
middleware: [auth.auth, i18n.getUserLanguage]
|
||||
action: challenges.delete
|
||||
|
||||
"/challenges/{cid}/close":
|
||||
spec:
|
||||
method: 'POST'
|
||||
description: 'Close a challenge'
|
||||
parameters: [
|
||||
path 'cid','Challenge id','string'
|
||||
query 'uid','User ID of the winner','string',true
|
||||
]
|
||||
middleware: [auth.auth, i18n.getUserLanguage]
|
||||
action: challenges.selectWinner
|
||||
|
||||
"/challenges/{cid}/join":
|
||||
spec:
|
||||
method: 'POST'
|
||||
description: "Join a challenge"
|
||||
parameters: [path('cid','Challenge id','string')]
|
||||
middleware: [auth.auth, i18n.getUserLanguage]
|
||||
action: challenges.join
|
||||
|
||||
"/challenges/{cid}/leave":
|
||||
spec:
|
||||
method: 'POST'
|
||||
description: 'Leave a challenge'
|
||||
parameters: [path('cid','Challenge id','string')]
|
||||
middleware: [auth.auth, i18n.getUserLanguage]
|
||||
action: challenges.leave
|
||||
|
||||
"/challenges/{cid}/member/{uid}":
|
||||
spec:
|
||||
description: "Get a member's progress in a particular challenge"
|
||||
parameters: [
|
||||
path 'cid','Challenge id','string'
|
||||
path 'uid','User id','string'
|
||||
]
|
||||
middleware: [auth.auth, i18n.getUserLanguage]
|
||||
action: challenges.getMember
|
||||
|
||||
|
||||
if nconf.get("NODE_ENV") is "development"
|
||||
api["/user/addTenGems"] =
|
||||
spec: method:'POST'
|
||||
action: user.addTenGems
|
||||
|
||||
api["/user/addHourglass"] =
|
||||
spec: method:'POST'
|
||||
action: user.addHourglass
|
||||
|
||||
_.each api, (route, path) ->
|
||||
## Spec format is:
|
||||
# spec:
|
||||
# path: "/pet/{petId}"
|
||||
# description: "Operations about pets"
|
||||
# notes: "Returns a pet based on ID"
|
||||
# summary: "Find pet by ID"
|
||||
# method: "GET"
|
||||
# parameters: [path("petId", "ID of pet that needs to be fetched", "string")]
|
||||
# type: "Pet"
|
||||
# errorResponses: [swagger.errors.invalid("id"), swagger.errors.notFound("pet")]
|
||||
# nickname: "getPetById"
|
||||
|
||||
route.spec.description ?= ''
|
||||
_.defaults route.spec,
|
||||
path: path
|
||||
nickname: path
|
||||
notes: route.spec.description
|
||||
summary: route.spec.description
|
||||
parameters: []
|
||||
#type: 'Pet'
|
||||
errorResponses: []
|
||||
method: 'GET'
|
||||
route.middleware ?= if path.indexOf('/user') is 0 then [auth.auth, i18n.getUserLanguage, cron] else [i18n.getUserLanguage]
|
||||
swagger["add#{route.spec.method}"](route);true
|
||||
|
||||
|
||||
swagger.configure("#{nconf.get('BASE_URL')}/api/v2", "2")
|
||||
@@ -1,9 +1,9 @@
|
||||
var express = require('express');
|
||||
var router = new express.Router();
|
||||
var dataexport = require('../controllers/dataexport');
|
||||
var auth = require('../controllers/auth');
|
||||
var auth = require('../controllers/api-v2/auth');
|
||||
var nconf = require('nconf');
|
||||
var i18n = require('../i18n');
|
||||
var i18n = require('../libs/i18n');
|
||||
var locals = require('../middlewares/locals');
|
||||
|
||||
/* Data export */
|
||||
|
||||
@@ -3,9 +3,7 @@ var express = require('express');
|
||||
var router = new express.Router();
|
||||
var _ = require('lodash');
|
||||
var locals = require('../middlewares/locals');
|
||||
var user = require('../controllers/user');
|
||||
var auth = require('../controllers/auth');
|
||||
var i18n = require('../i18n');
|
||||
var i18n = require('../libs/i18n');
|
||||
|
||||
// -------- App --------
|
||||
router.get('/', i18n.getUserLanguage, locals, function(req, res) {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
var nconf = require('nconf');
|
||||
var express = require('express');
|
||||
var router = new express.Router();
|
||||
var auth = require('../controllers/auth');
|
||||
var auth = require('../controllers/api-v2/auth');
|
||||
var payments = require('../controllers/payments');
|
||||
var i18n = require('../i18n');
|
||||
var i18n = require('../libs/i18n');
|
||||
|
||||
router.get('/paypal/checkout', auth.authWithUrl, i18n.getUserLanguage, payments.paypalCheckout);
|
||||
router.get('/paypal/checkout/success', i18n.getUserLanguage, payments.paypalCheckoutSuccess);
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
/*
|
||||
* This script is no longer required due to this code in src/models/group.js:
|
||||
* // initialize tavern if !exists (fresh installs)
|
||||
* Group.count({_id:'habitrpg'},function(err,ct){
|
||||
* ...
|
||||
* })
|
||||
*
|
||||
* However we're keeping this script in case future seed updates are needed.
|
||||
*
|
||||
* Reference: https://github.com/HabitRPG/habitrpg/issues/3852#issuecomment-55334572
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
|
||||
require('coffee-script') // for habitrpg-shared
|
||||
var nconf = require('nconf');
|
||||
var utils = require('./utils');
|
||||
var logging = require('./logging');
|
||||
utils.setupConfig();
|
||||
var async = require('async');
|
||||
var mongoose = require('mongoose');
|
||||
User = require('./models/user').model;
|
||||
Group = require('./models/group').model;
|
||||
|
||||
async.waterfall([
|
||||
function(cb){
|
||||
mongoose.connect(nconf.get('NODE_DB_URI'), cb);
|
||||
},
|
||||
function(cb){
|
||||
Group.findById('habitrpg', cb);
|
||||
},
|
||||
function(tavern, cb){
|
||||
logging.info({tavern:tavern,cb:cb});
|
||||
if (!tavern) {
|
||||
tavern = new Group({
|
||||
_id: 'habitrpg',
|
||||
chat: [],
|
||||
leader: '9',
|
||||
name: 'HabitRPG',
|
||||
type: 'guild',
|
||||
privacy:'public'
|
||||
});
|
||||
tavern.save(cb)
|
||||
} else {
|
||||
cb();
|
||||
}
|
||||
}
|
||||
],function(err){
|
||||
if (err) throw err;
|
||||
logging.info("Done initializing database");
|
||||
mongoose.disconnect();
|
||||
})
|
||||
|
||||
*/
|
||||
@@ -2,9 +2,9 @@
|
||||
var cluster = require("cluster");
|
||||
var _ = require('lodash');
|
||||
var nconf = require('nconf');
|
||||
var utils = require('./utils');
|
||||
var utils = require('./libs/utils');
|
||||
utils.setupConfig();
|
||||
var logging = require('./logging');
|
||||
var logging = require('./libs/logging');
|
||||
var isProd = nconf.get('NODE_ENV') === 'production';
|
||||
var isDev = nconf.get('NODE_ENV') === 'development';
|
||||
var DISABLE_LOGGING = nconf.get('DISABLE_REQUEST_LOGGING');
|
||||
@@ -29,7 +29,7 @@ if (cores!==0 && cluster.isMaster && (isDev || isProd)) {
|
||||
var shared = require('../../common');
|
||||
|
||||
// Setup translations
|
||||
var i18n = require('./i18n');
|
||||
var i18n = require('./libs/i18n');
|
||||
|
||||
var TWO_WEEKS = 1000 * 60 * 60 * 24 * 14;
|
||||
var app = express();
|
||||
@@ -90,54 +90,68 @@ if (cores!==0 && cluster.isMaster && (isDev || isProd)) {
|
||||
var publicDir = path.join(__dirname, "/../public");
|
||||
|
||||
app.set("port", nconf.get('PORT'));
|
||||
require('./middlewares/apiThrottle')(app);
|
||||
app.use(require('./middlewares/domain')(server,mongoose));
|
||||
if (!isProd && !DISABLE_LOGGING) app.use(express.logger("dev"));
|
||||
app.use(express.compress());
|
||||
app.set("views", __dirname + "/../views");
|
||||
app.set("view engine", "jade");
|
||||
app.use(express.favicon(publicDir + '/favicon.ico'));
|
||||
app.use(require('./middlewares/cors'));
|
||||
|
||||
// Setup two different Express apps, one that matches everything except '/api/v3'
|
||||
// and the other for /api/v3 routes, so we can keep the old an new api versions completely separate
|
||||
// not sharing a single middleware if we don't want to
|
||||
var oldApp = express(); // api v1 and v2, and not scoped routes
|
||||
var newApp = express(); // api v3
|
||||
|
||||
// Route requests to the right app
|
||||
app.use(app.router);
|
||||
// Matches all request except the ones going to /api/v3/**
|
||||
app.all(/^(?!\/api\/v3).+/i, oldApp);
|
||||
// Matches all requests going to /api/v3
|
||||
app.all('/api/v3', newApp);
|
||||
|
||||
require('./middlewares/apiThrottle')(oldApp);
|
||||
oldApp.use(require('./middlewares/domain')(server,mongoose));
|
||||
if (!isProd && !DISABLE_LOGGING) oldApp.use(express.logger("dev"));
|
||||
oldApp.use(express.compress());
|
||||
oldApp.set("views", __dirname + "/../views");
|
||||
oldApp.set("view engine", "jade");
|
||||
oldApp.use(express.favicon(publicDir + '/favicon.ico'));
|
||||
oldApp.use(require('./middlewares/cors'));
|
||||
|
||||
var redirects = require('./middlewares/redirects');
|
||||
app.use(redirects.forceHabitica);
|
||||
app.use(redirects.forceSSL);
|
||||
app.use(express.urlencoded());
|
||||
app.use(express.json());
|
||||
app.use(require('method-override')());
|
||||
//app.use(express.cookieParser(nconf.get('SESSION_SECRET')));
|
||||
app.use(express.cookieParser());
|
||||
app.use(express.cookieSession({ secret: nconf.get('SESSION_SECRET'), httpOnly: false, cookie: { maxAge: TWO_WEEKS }}));
|
||||
//app.use(express.session());
|
||||
oldApp.use(redirects.forceHabitica);
|
||||
oldApp.use(redirects.forceSSL);
|
||||
oldApp.use(express.urlencoded());
|
||||
oldApp.use(express.json());
|
||||
oldApp.use(require('method-override')());
|
||||
//oldApp.use(express.cookieParser(nconf.get('SESSION_SECRET')));
|
||||
oldApp.use(express.cookieParser());
|
||||
oldApp.use(express.cookieSession({ secret: nconf.get('SESSION_SECRET'), httpOnly: false, cookie: { maxAge: TWO_WEEKS }}));
|
||||
//oldApp.use(express.session());
|
||||
|
||||
// Initialize Passport! Also use passport.session() middleware, to support
|
||||
// persistent login sessions (recommended).
|
||||
app.use(passport.initialize());
|
||||
app.use(passport.session());
|
||||
oldApp.use(passport.initialize());
|
||||
oldApp.use(passport.session());
|
||||
|
||||
app.use(app.router);
|
||||
oldApp.use(oldApp.router);
|
||||
|
||||
var maxAge = isProd ? 31536000000 : 0;
|
||||
// Cache emojis without copying them to build, they are too many
|
||||
app.use(express['static'](path.join(__dirname, "/../build"), { maxAge: maxAge }));
|
||||
app.use('/common/dist', express['static'](publicDir + "/../../common/dist", { maxAge: maxAge }));
|
||||
app.use('/common/audio', express['static'](publicDir + "/../../common/audio", { maxAge: maxAge }));
|
||||
app.use('/common/script/public', express['static'](publicDir + "/../../common/script/public", { maxAge: maxAge }));
|
||||
app.use('/common/img', express['static'](publicDir + "/../../common/img", { maxAge: maxAge }));
|
||||
app.use(express['static'](publicDir));
|
||||
oldApp.use(express['static'](path.join(__dirname, "/../build"), { maxAge: maxAge }));
|
||||
oldApp.use('/common/dist', express['static'](publicDir + "/../../common/dist", { maxAge: maxAge }));
|
||||
oldApp.use('/common/audio', express['static'](publicDir + "/../../common/audio", { maxAge: maxAge }));
|
||||
oldApp.use('/common/script/public', express['static'](publicDir + "/../../common/script/public", { maxAge: maxAge }));
|
||||
oldApp.use('/common/img', express['static'](publicDir + "/../../common/img", { maxAge: maxAge }));
|
||||
oldApp.use(express['static'](publicDir));
|
||||
|
||||
// Custom Directives
|
||||
app.use(require('./routes/pages').middleware);
|
||||
app.use(require('./routes/payments').middleware);
|
||||
app.use(require('./routes/auth').middleware);
|
||||
app.use(require('./routes/coupon').middleware);
|
||||
app.use(require('./routes/unsubscription').middleware);
|
||||
oldApp.use(require('./routes/pages').middleware);
|
||||
oldApp.use(require('./routes/payments').middleware);
|
||||
oldApp.use(require('./routes/api-v2/auth').middleware);
|
||||
oldApp.use(require('./routes/api-v2/coupon').middleware);
|
||||
oldApp.use(require('./routes/api-v2/unsubscription').middleware);
|
||||
var v2 = express();
|
||||
app.use('/api/v2', v2);
|
||||
app.use('/api/v1', require('./routes/apiv1').middleware);
|
||||
app.use('/export', require('./routes/dataexport').middleware);
|
||||
require('./routes/apiv2.coffee')(swagger, v2);
|
||||
app.use(require('./middlewares/errorHandler'));
|
||||
oldApp.use('/api/v2', v2);
|
||||
oldApp.use('/api/v1', require('./routes/api-v1').middleware);
|
||||
oldApp.use('/export', require('./routes/dataexport').middleware);
|
||||
require('./routes/api-v2/swagger')(swagger, v2);
|
||||
oldApp.use(require('./middlewares/errorHandler'));
|
||||
|
||||
server.on('request', app);
|
||||
server.listen(app.get("port"), function() {
|
||||
|
||||
Reference in New Issue
Block a user