<commit_before>const fse = require('fs-extra');
const path = require('path');
const get = require('lodash.get');
const set = require('lodash.set');
const {spawnSync} = require('child_process');
const {quote} = require('shell-quote');
const values = require('lodash.values');
const {buildImage, getBindPath} = require('./docker');

/**
 * Install requirements described in requirementsPath to targetPath
 * @param {string} requirementsPath
 * @param {string} targetFolder
 * @param {Object} serverless
 * @param {string} servicePath
 * @param {Object} options
 * @return {undefined}
 */
function installRequirements(requirementsPath, targetFolder, serverless, servicePath, options) {
  // Create target folder if it does not exist
  const targetRequirementsFolder = path.join(targetFolder, 'requirements');
  fse.ensureDirSync(targetRequirementsFolder);

  const dotSlsReqs = path.join(targetFolder, 'requirements.txt');
  let fileName = requirementsPath;
  if (options.usePipenv && fse.existsSync(path.join(servicePath, 'Pipfile'))) {
    fileName = dotSlsReqs;
  }

  serverless.cli.log(`Installing requirements of ${requirementsPath} in ${targetFolder}...`);

  // In case the requirements file is a symlink, copy it to targetFolder
  // if using docker to avoid errors
  if (options.dockerizePip && fileName !== dotSlsReqs) {
    fse.copySync(fileName, dotSlsReqs);
    fileName = dotSlsReqs;
  }

  let cmd;
  let cmdOptions;
  let pipCmd = [
    options.pythonBin, '-m', 'pip', '--isolated', 'install',
    '-t', targetRequirementsFolder, '-r', fileName,
    ...options.pipCmdExtraArgs,
  ];
  if (!options.dockerizePip) {
    // Check if pip has Debian's --system option and set it if so
    const pipTestRes = spawnSync(
      options.pythonBin, ['-m', 'pip', 'help', 'install']);
    if (pipTestRes.error) {
      if (pipTestRes.error.code === 'ENOENT') {
        throw new Error(
          `${options.pythonBin} not found! ` +
          'Try the pythonBin option.');
      }
      throw pipTestRes.error;
    }
    if (pipTestRes.stdout.toString().indexOf('--system') >= 0) {
      pipCmd.push('--system');
    }
  }
  if (options.dockerizePip) {
    cmd = 'docker';

    // Build docker image if required
    let dockerImage;
    if (options.dockerFile) {
      serverless.cli.log(`Building custom docker image from ${options.dockerFile}...`);
      dockerImage = buildImage(options.dockerFile);
    } else {
      dockerImage = options.dockerImage;
    }
    serverless.cli.log(`Docker Image: ${dockerImage}`);

    // Prepare bind path depending on os platform
    const bindPath = getBindPath(servicePath);

    cmdOptions = [
      'run', '--rm',
      '-v', `${bindPath}:/var/task:z`,
    ];
    if (options.dockerSsh) {
      // Mount necessary ssh files to work with private repos
      cmdOptions.push('-v', `${process.env.HOME}/.ssh/id_rsa:/root/.ssh/id_rsa:z`);
      cmdOptions.push('-v', `${process.env.HOME}/.ssh/known_hosts:/root/.ssh/known_hosts:z`);
      cmdOptions.push('-v', `${process.env.SSH_AUTH_SOCK}:/tmp/ssh_sock:z`);
      cmdOptions.push('-e', 'SSH_AUTH_SOCK=/tmp/ssh_sock');
    }
    if (process.platform === 'linux') {
      // Set the ownership of the .serverless/requirements folder to current user
      pipCmd = quote(pipCmd);
      const chownCmd = quote([
        'chown', '-R', `${process.getuid()}:${process.getgid()}`,
        targetRequirementsFolder,
      ]);
      pipCmd = ['/bin/bash', '-c', '"' + pipCmd + ' && ' + chownCmd + '"'];
      // const stripCmd = quote([
      //   'find', targetRequirementsFolder,
      //   '-name', '"*.so"',
      //   '-exec', 'strip', '{}', '\;',
      // ]);
      // pipCmd = ['/bin/bash', '-c', '"' + pipCmd + ' && ' + stripCmd + ' && ' + chownCmd + '"'];
    }
    cmdOptions.push(dockerImage);
    cmdOptions.push(...pipCmd);
  } else {
    cmd = pipCmd[0];
    cmdOptions = pipCmd.slice(1);
  }
  const res = spawnSync(cmd, cmdOptions, {cwd: servicePath, shell: true});
  if (res.error) {
    if (res.error.code === 'ENOENT') {
      if (options.dockerizePip) {
        throw new Error('docker not found! Please install it.');
      }
      throw new Error(`${options.pythonBin} not found! Try the pythonBin option.`);
    }
    throw res.error;
  }
  if (res.status !== 0) {
    throw new Error(res.stderr);
  }
};

/**
 * pip install the requirements to the .serverless/requirements directory
 * @return {undefined}
 */
function installAllRequirements() {
  fse.ensureDirSync(path.join(this.servicePath, '.serverless'));
  if (this.serverless.service.package.individually) {
    let doneModules = [];
    values(this.serverless.service.functions)
      .forEach((f) => {
        if (!get(f, 'module')) {
          set(f, ['module'], '.');
        }
        if (!doneModules.includes(f.module)) {
          installRequirements(
            path.join(f.module, this.options.fileName),
            path.join('.serverless', f.module),
            this.serverless,
            this.servicePath,
            this.options
          );
          doneModules.push(f.module);
        }
      });
  } else {
    installRequirements(
      this.options.fileName,
      '.serverless',
      this.serverless,
      this.servicePath,
      this.options
    );
  }
};

module.exports = {installAllRequirements};
<commit_msg>Fix --cache-dir with Docker Without supplying a user Docker defaulted to root That caused pip to refuse to use any specified --cache-dir because it's owned by the user Run Docker as the user so it has proper access to any -cache-dir<commit_after>const fse = require('fs-extra');
const path = require('path');
const get = require('lodash.get');
const set = require('lodash.set');
const {spawnSync} = require('child_process');
const values = require('lodash.values');
const {buildImage, getBindPath} = require('./docker');

/**
 * Install requirements described in requirementsPath to targetPath
 * @param {string} requirementsPath
 * @param {string} targetFolder
 * @param {Object} serverless
 * @param {string} servicePath
 * @param {Object} options
 * @return {undefined}
 */
function installRequirements(requirementsPath, targetFolder, serverless, servicePath, options) {
  // Create target folder if it does not exist
  const targetRequirementsFolder = path.join(targetFolder, 'requirements');
  fse.ensureDirSync(targetRequirementsFolder);

  const dotSlsReqs = path.join(targetFolder, 'requirements.txt');
  let fileName = requirementsPath;
  if (options.usePipenv && fse.existsSync(path.join(servicePath, 'Pipfile'))) {
    fileName = dotSlsReqs;
  }

  serverless.cli.log(`Installing requirements of ${requirementsPath} in ${targetFolder}...`);

  // In case the requirements file is a symlink, copy it to targetFolder
  // if using docker to avoid errors
  if (options.dockerizePip && fileName !== dotSlsReqs) {
    fse.copySync(fileName, dotSlsReqs);
    fileName = dotSlsReqs;
  }

  let cmd;
  let cmdOptions;
  let pipCmd = [
    options.pythonBin, '-m', 'pip', '--isolated', 'install',
    '-t', targetRequirementsFolder, '-r', fileName,
    ...options.pipCmdExtraArgs,
  ];
  if (!options.dockerizePip) {
    // Check if pip has Debian's --system option and set it if so
    const pipTestRes = spawnSync(
      options.pythonBin, ['-m', 'pip', 'help', 'install']);
    if (pipTestRes.error) {
      if (pipTestRes.error.code === 'ENOENT') {
        throw new Error(
          `${options.pythonBin} not found! ` +
          'Try the pythonBin option.');
      }
      throw pipTestRes.error;
    }
    if (pipTestRes.stdout.toString().indexOf('--system') >= 0) {
      pipCmd.push('--system');
    }
  }
  if (options.dockerizePip) {
    cmd = 'docker';

    // Build docker image if required
    let dockerImage;
    if (options.dockerFile) {
      serverless.cli.log(`Building custom docker image from ${options.dockerFile}...`);
      dockerImage = buildImage(options.dockerFile);
    } else {
      dockerImage = options.dockerImage;
    }
    serverless.cli.log(`Docker Image: ${dockerImage}`);

    // Prepare bind path depending on os platform
    const bindPath = getBindPath(servicePath);

    cmdOptions = [
      'run', '--rm',
      '-v', `${bindPath}:/var/task:z`,
    ];
    if (options.dockerSsh) {
      // Mount necessary ssh files to work with private repos
      cmdOptions.push('-v', `${process.env.HOME}/.ssh/id_rsa:/root/.ssh/id_rsa:z`);
      cmdOptions.push('-v', `${process.env.HOME}/.ssh/known_hosts:/root/.ssh/known_hosts:z`);
      cmdOptions.push('-v', `${process.env.SSH_AUTH_SOCK}:/tmp/ssh_sock:z`);
      cmdOptions.push('-e', 'SSH_AUTH_SOCK=/tmp/ssh_sock');
    }
    if (process.platform === 'linux') {
      // Use same user so requirements folder is not root and so --cache-dir works
      cmdOptions.push('-u', `${process.getuid()}`);
      // const stripCmd = quote([
      //   'find', targetRequirementsFolder,
      //   '-name', '"*.so"',
      //   '-exec', 'strip', '{}', '\;',
      // ]);
      // pipCmd = ['/bin/bash', '-c', '"' + pipCmd + ' && ' + stripCmd + ' && ' + chownCmd + '"'];
    } else if (process.platform === 'win32') {
      // Use same user so --cache-dir works
      cmdOptions.push('-u', '1000'); // TODO is this always the case?
    }
    cmdOptions.push(dockerImage);
    cmdOptions.push(...pipCmd);
  } else {
    cmd = pipCmd[0];
    cmdOptions = pipCmd.slice(1);
  }
  const res = spawnSync(cmd, cmdOptions, {cwd: servicePath, shell: true});
  if (res.error) {
    if (res.error.code === 'ENOENT') {
      if (options.dockerizePip) {
        throw new Error('docker not found! Please install it.');
      }
      throw new Error(`${options.pythonBin} not found! Try the pythonBin option.`);
    }
    throw res.error;
  }
  if (res.status !== 0) {
    throw new Error(res.stderr);
  }
};

/**
 * pip install the requirements to the .serverless/requirements directory
 * @return {undefined}
 */
function installAllRequirements() {
  fse.ensureDirSync(path.join(this.servicePath, '.serverless'));
  if (this.serverless.service.package.individually) {
    let doneModules = [];
    values(this.serverless.service.functions)
      .forEach((f) => {
        if (!get(f, 'module')) {
          set(f, ['module'], '.');
        }
        if (!doneModules.includes(f.module)) {
          installRequirements(
            path.join(f.module, this.options.fileName),
            path.join('.serverless', f.module),
            this.serverless,
            this.servicePath,
            this.options
          );
          doneModules.push(f.module);
        }
      });
  } else {
    installRequirements(
      this.options.fileName,
      '.serverless',
      this.serverless,
      this.servicePath,
      this.options
    );
  }
};

module.exports = {installAllRequirements};
<|endoftext|>


<commit_before>/*jshint node:true*/
module.exports = {
  description: 'Add LiquidFire to the consumers app',

  // So we don't see the entity name error
  normalizeEntityName: function() {},

  afterInstall: function() {
    return this.addAddonToProject({
      name: 'liquid-fire',
      version: '0.22.1'
    });
  }
};
<commit_msg>Update liquid-fire version in blueprint<commit_after>/*jshint node:true*/
module.exports = {
  description: 'Add LiquidFire to the consumers app',

  // So we don't see the entity name error
  normalizeEntityName: function() {},

  afterInstall: function() {
    return this.addAddonToProject({
      name: 'liquid-fire',
      version: '0.23.0'
    });
  }
};
<|endoftext|>


<commit_before>require('dotenv').config();
const express = require('express')
const app = require('express')()
const port = 1337

const MongoClient = require("mongodb").MongoClient;
const MONGODB_URI = process.env.MONGODB_URI;
console.log(MONGODB_URI)

MongoClient.connect(MONGODB_URI, (err, database) => {
	if (err) return console.log(err)
	db = database
});

app
	.get('/', (req, res) => {

	})
	.listen(process.env.PORT || port, () => {
		console.log('api server on http://localhost:' + port)
	})

app.get('/init/generator/:generator', (req, res) => {
	const generator = req.params.generator
	initGenerator(generator)
});

app.get('/init/generator/:generator/stand/:stand', (req, res) => {
	const generator = req.params.generator
	const stand = req.params.stand
	initStand(generator, stand)
});

app.get('/grid/:id', (req, res) => {

});

app.get('/generator/:id', (req, res) => {

});

const generate = () => {
	setInterval(function() {
		const generatorCollection = db.collection('generators');

		generatorCollection.find({}, {}).toArray(function(err, generators) {
			generators.map(function(generator) {
				generateMessage(generator)
			});

		});
	}, 1000);
}

// generate()

const initGenerator = (generator) => {
	const generatorCollection = db.collection('generators');
	const data = {
		name: generator,
		created_at: Date.now()
	}

	generatorCollection.save(data, (err, result) => {
		if (err) return console.log(err);
	});
}

const initStand = (generator, stand) => {
	const generatorCollection = db.collection('generators');
	const standCollection = db.collection('stands');

	generatorCollection.findOne({
		name: generator
	}, function(err, generator) {
		if (err) return console.log(err);
		const data = {
			name: stand,
			generator: generator._id,
			created_at: Date.now()
		}

		standCollection.save(data, (err, result) => {
			if (err) return console.log(err);
			console.info('created stand called `' + data.name + '` that is connected to generator `' + generator.name + '`')
		});
	})

}

const generateMessage = (generator) => {
	const generatorCollection = db.collection('generators');
	const messageCollection = db.collection('messages');

	const data = {
		generatorId: generator._id,
		timestamp: Date.now(),
		avr_va: randomNumnodem(90500, 90600),
		min_va: randomNumnodem(86500, 86700),
		max_va: randomNumnodem(95400, 95600),
	}

	console.log(data)
	messageCollection.save(data, (err, result) => {
		if (err) return console.log(err);
	});
}

const randomNumnodem = (min, max) => {
	return Math.floor(Math.random() * (max - min)) + min;
}<commit_msg>generating stand data<commit_after>require('dotenv').config();
const express = require('express')
const app = require('express')()
const port = 1337

const MongoClient = require("mongodb").MongoClient;
const MONGODB_URI = process.env.MONGODB_URI;
console.log(MONGODB_URI)

MongoClient.connect(MONGODB_URI, (err, database) => {
	if (err) return console.log(err)
	db = database
});

app
	.get('/', (req, res) => {

	})
	.listen(process.env.PORT || port, () => {
		console.log('api server on http://localhost:' + port)
	})

app.get('/init/generator/:generator', (req, res) => {
	const generator = req.params.generator
	initGenerator(generator)
});

app.get('/init/generator/:generator/stand/:stand', (req, res) => {
	const generator = req.params.generator
	const stand = req.params.stand
	initStand(generator, stand)
});

app.get('/grid/:id', (req, res) => {

});

app.get('/generator/:id', (req, res) => {

});

const generate = () => {
	setInterval(function() {
		const generatorCollection = db.collection('generators');
		const standCollection = db.collection('stands');

		standCollection.find({}, {}).toArray(function(err, stands) {
			stands.map(function(stand) {
				generateMessage(stand)
			});

		});
	}, 3000);
}

generate()

const initGenerator = (generator) => {
	const generatorCollection = db.collection('generators');
	const data = {
		name: generator,
		created_at: Date.now()
	}

	generatorCollection.save(data, (err, result) => {
		if (err) return console.log(err);
	});
}

const initStand = (generator, stand) => {
	const generatorCollection = db.collection('generators');
	const standCollection = db.collection('stands');

	generatorCollection.findOne({
		name: generator
	}, function(err, generator) {
		if (err) return console.log(err);
		const data = {
			name: stand,
			generator: generator._id,
			created_at: Date.now()
		}

		standCollection.save(data, (err, result) => {
			if (err) return console.log(err);
			console.info('Created stand called `' + data.name + '` that is connected to generator `' + generator.name + '`')
		});
	})

}

const generateMessage = (stand) => {
	const generatorCollection = db.collection('generators');
	const messageCollection = db.collection('messages');

	const data = {
		stand: stand._id,
		generator: stand.generator,
		timestamp: Date.now(),
		avr_va: randomNumnodem(90500, 90600),
		min_va: randomNumnodem(86500, 86700),
		max_va: randomNumnodem(95400, 95600),
	}

	messageCollection.save(data, (err, result) => {
		if (err) return console.log(err);
		console.info('Create message for stand `' + stand.name + '` that is connected to generator `' + stand.generator + '`')
	});
}

const randomNumnodem = (min, max) => {
	return Math.floor(Math.random() * (max - min)) + min;
}<|endoftext|>


<commit_before>import { readFileSync } from 'fs'
import { graphqlHTTP } from 'express-graphql'
import { join } from 'path'
import setupBridge from '../../lib/graphql-bookshelf-bridge'
import { presentQuerySet } from '../../lib/graphql-bookshelf-bridge/util'
import {
  acceptGroupRelationshipInvite,
  acceptJoinRequest,
  addModerator,
  addPeopleToProjectRole,
  addSkill,
  addSkillToLearn,
  addSuggestedSkillToGroup,
  allowGroupInvites,
  blockUser,
  cancelGroupRelationshipInvite,
  cancelJoinRequest,
  createAffiliation,
  createComment,
  createGroup,
  createInvitation,
  createJoinRequest,
  createMessage,
  createPost,
  createProject,
  createProjectRole,
  createSavedSearch,
  createTopic,
  declineJoinRequest,
  deleteAffiliation,
  deleteComment,
  deleteGroup,
  deleteGroupRelationship,
  deleteGroupTopic,
  deletePost,
  deleteProjectRole,
  deleteSavedSearch,
  expireInvitation,
  findOrCreateLinkPreviewByUrl,
  findOrCreateLocation,
  findOrCreateThread,
  flagInappropriateContent,
  fulfillPost,
  inviteGroupToGroup,
  invitePeopleToEvent,
  joinGroup,
  joinProject,
  leaveGroup,
  leaveProject,
  markActivityRead,
  markAllActivitiesRead,
  pinPost,
  processStripeToken,
  regenerateAccessCode,
  registerDevice,
  registerStripeAccount,
  reinviteAll,
  rejectGroupRelationshipInvite,
  removeMember,
  removeModerator,
  removePost,
  removeSkill,
  removeSkillToLearn,
  removeSuggestedSkillFromGroup,
  resendInvitation,
  respondToEvent,
  subscribe,
  toggleGroupWidgetVisibility,
  unblockUser,
  unfulfillPost,
  unlinkAccount,
  updateComment,
  updateGroup,
  updateGroupHiddenSetting,
  updateGroupTopic,
  updateGroupTopicFollow,
  updateMe,
  updateMembership,
  updatePost,
  updateStripeAccount,
  updateWidget,
  useInvitation,
  vote
} from './mutations'
import InvitationService from '../services/InvitationService'
import makeModels from './makeModels'
import { makeExecutableSchema } from 'graphql-tools'
import { inspect } from 'util'
import { red } from 'chalk'
import { mapValues, merge, reduce } from 'lodash'

const schemaText = readFileSync(join(__dirname, 'schema.graphql')).toString()

async function createSchema (userId, isAdmin) {
  const models = await makeModels(userId, isAdmin)
  const { resolvers, fetchOne, fetchMany } = setupBridge(models)

  let allResolvers = Object.assign({
    Query: userId ? makeAuthenticatedQueries(userId, fetchOne, fetchMany) : makePublicQueries(userId, fetchOne, fetchMany),
    Mutation: userId ? makeMutations(userId, isAdmin) : {},

    FeedItemContent: {
      __resolveType (data, context, info) {
        if (data instanceof bookshelf.Model) {
          return info.schema.getType('Post')
        }
        throw new Error('Post is the only implemented FeedItemContent type')
      }
    },

    SearchResultContent: {
      __resolveType (data, context, info) {
        return getTypeForInstance(data, models)
      }
    }
  }, resolvers)

  return makeExecutableSchema({
    typeDefs: [schemaText],
    resolvers: allResolvers
  })
}

// Queries that non-logged in users can make
export function makePublicQueries (userId, fetchOne, fetchMany) {
  return {
    checkInvitation: (root, { invitationToken, accessCode }) =>
      InvitationService.check(userId, invitationToken, accessCode),
    // Can only access public communities and posts
    group: async (root, { id, slug }) => fetchOne('Group', slug || id, slug ? 'slug' : 'id', { visibility: Group.Visibility.PUBLIC }),
    groups: (root, args) => fetchMany('Group', Object.assign(args, { visibility: Group.Visibility.PUBLIC })),
    posts: (root, args) => fetchMany('Post', Object.assign(args, { isPublic: true }))
  }
}

// Queries that logged in users can make
export function makeAuthenticatedQueries (userId, fetchOne, fetchMany) {
  return {
    activity: (root, { id }) => fetchOne('Activity', id),
    checkInvitation: (root, { invitationToken, accessCode }) =>
      InvitationService.check(userId, invitationToken, accessCode),
    comment: (root, { id }) => fetchOne('Comment', id),
    connections: (root, args) => fetchMany('PersonConnection', args),
    group: async (root, { id, slug, updateLastViewed }) => {
      // you can specify id or slug, but not both
      const group = await fetchOne('Group', slug || id, slug ? 'slug' : 'id')
      if (updateLastViewed && group) {
        const membership = await GroupMembership.forPair(userId, group).fetch()
        if (membership) {
          await membership.addSetting({ lastReadAt: new Date() }, true)
        }
      }
      return group
    },
    groupExists: (root, { slug }) => {
      if (Group.isSlugValid(slug)) {
        return Group.where(bookshelf.knex.raw('slug = ?', slug))
        .count()
        .then(count => {
          if (count > 0) return {exists: true}
          return {exists: false}
        })
      }
      throw new Error('Slug is invalid')
    },
    groupTopic: (root, { topicName, groupSlug }) =>
      GroupTag.findByTagAndGroup(topicName, groupSlug),
    groupTopics: (root, args) => fetchMany('GroupTopic', args),
    groups: (root, args) => fetchMany('Group', args),
    joinRequests: (root, args) => fetchMany('JoinRequest', args),
    me: () => fetchOne('Me', userId),
    messageThread: (root, { id }) => fetchOne('MessageThread', id),
    notifications: (root, { first, offset, resetCount, order = 'desc' }) => {
      return fetchMany('Notification', { first, offset, order })
      .tap(() => resetCount && User.resetNewNotificationCount(userId))
    },
    people: (root, args) => fetchMany('Person', args),
    person: (root, { id }) => fetchOne('Person', id),
    post: (root, { id }) => fetchOne('Post', id),
    posts: (root, args) => fetchMany('Post', args),
    savedSearches: (root, args) => fetchMany('SavedSearch', args),
    search: (root, args) => {
      if (!args.first) args.first = 20
      return Search.fullTextSearch(userId, args)
      .then(({ models, total }) => {
        // FIXME this shouldn't be used directly here -- there should be some
        // way of integrating this into makeModels and using the presentation
        // logic that's already in the fetcher
        return presentQuerySet(models, merge(args, {total}))
      })
    },
    skills: (root, args) => fetchMany('Skill', args),
    topic: (root, { id, name }) => // you can specify id or name, but not both
      fetchOne('Topic', name || id, name ? 'name' : 'id'),
    topics: (root, args) => fetchMany('Topic', args)
  }
}

export function makeMutations (userId, isAdmin) {
  return {
    acceptGroupRelationshipInvite: (root, { groupRelationshipInviteId }) => acceptGroupRelationshipInvite(userId, groupRelationshipInviteId),

    acceptJoinRequest: (root, { joinRequestId }) => acceptJoinRequest(userId, joinRequestId),

    addModerator: (root, { personId, groupId }) =>
      addModerator(userId, personId, groupId),

    addPeopleToProjectRole: (root, { peopleIds, projectRoleId }) =>
      addPeopleToProjectRole(userId, peopleIds, projectRoleId),

    addSkill: (root, { name }) => addSkill(userId, name),
    addSkillToLearn: (root, { name }) => addSkillToLearn(userId, name),
    addSuggestedSkillToGroup: (root, { groupId, name }) => addSuggestedSkillToGroup(userId, groupId, name),

    allowGroupInvites: (root, { groupId, data }) => allowGroupInvites(groupId, data),

    blockUser: (root, { blockedUserId }) => blockUser(userId, blockedUserId),

    cancelGroupRelationshipInvite: (root, { groupRelationshipInviteId }) => cancelGroupRelationshipInvite(userId, groupRelationshipInviteId),

    cancelJoinRequest: (root, { joinRequestId }) => cancelJoinRequest(userId, joinRequestId),

    createAffiliation: (root, { data }) => createAffiliation(userId, data),

    createComment: (root, { data }) => createComment(userId, data),

    createGroup: (root, { data }) => createGroup(userId, data),

    createInvitation: (root, {groupId, data}) =>
      createInvitation(userId, groupId, data),

    createJoinRequest: (root, {groupId, questionAnswers}) => createJoinRequest(userId, groupId, questionAnswers),

    createMessage: (root, { data }) => createMessage(userId, data),

    createPost: (root, { data }) => createPost(userId, data),

    createProject: (root, { data }) => createProject(userId, data),

    createProjectRole: (root, { projectId, roleName }) => createProjectRole(userId, projectId, roleName),

    createSavedSearch: (root, { data }) => createSavedSearch(data),

    joinGroup: (root, {groupId}) => joinGroup(groupId, userId),

    joinProject: (root, { id }) => joinProject(id, userId),

    createTopic: (root, { topicName, groupId, isDefault, isSubscribing }) => createTopic(userId, topicName, groupId, isDefault, isSubscribing),

    declineJoinRequest: (root, { joinRequestId }) => declineJoinRequest(userId, joinRequestId),

    deleteAffiliation: (root, { id }) => deleteAffiliation(userId, id),

    deleteComment: (root, { id }) => deleteComment(userId, id),

    deleteGroup: (root, { id }) => deleteGroup(userId, id),

    deleteGroupRelationship: (root, { parentId, childId }) => deleteGroupRelationship(userId, parentId, childId),

    deleteGroupTopic: (root, { id }) => deleteGroupTopic(userId, id),

    deletePost: (root, { id }) => deletePost(userId, id),

    deleteProjectRole: (root, { id }) => deleteProjectRole(userId, id),

    deleteSavedSearch: (root, { id }) => deleteSavedSearch(id),

    expireInvitation: (root, {invitationId}) =>
      expireInvitation(userId, invitationId),

    findOrCreateThread: (root, { data }) => findOrCreateThread(userId, data),

    findOrCreateLinkPreviewByUrl: (root, { data }) =>
      findOrCreateLinkPreviewByUrl(data),

    findOrCreateLocation: (root, { data }) => findOrCreateLocation(data),

    flagInappropriateContent: (root, { data }) =>
      flagInappropriateContent(userId, data),

    fulfillPost: (root, { postId }) => fulfillPost(userId, postId),

    inviteGroupToJoinParent: (root, { parentId, childId }) =>
      inviteGroupToGroup(userId, parentId, childId, GroupRelationshipInvite.TYPE.ParentToChild),

    invitePeopleToEvent: (root, {eventId, inviteeIds}) =>
      invitePeopleToEvent(userId, eventId, inviteeIds),

    leaveGroup: (root, { id }) => leaveGroup(userId, id),

    leaveProject: (root, { id }) => leaveProject(id, userId),

    markActivityRead: (root, { id }) => markActivityRead(userId, id),

    markAllActivitiesRead: (root) => markAllActivitiesRead(userId),

    pinPost: (root, { postId, groupId }) =>
      pinPost(userId, postId, groupId),

    processStripeToken: (root, { postId, token, amount }) =>
      processStripeToken(userId, postId, token, amount),

    regenerateAccessCode: (root, { groupId }) =>
      regenerateAccessCode(userId, groupId),

    registerDevice: (root, { playerId, platform, version }) =>
      registerDevice(userId, { playerId, platform, version }),

    registerStripeAccount: (root, { authorizationCode }) =>
      registerStripeAccount(userId, authorizationCode),

    reinviteAll: (root, {groupId}) => reinviteAll(userId, groupId),

    rejectGroupRelationshipInvite: (root, { groupRelationshipInviteId }) => rejectGroupRelationshipInvite(userId, groupRelationshipInviteId),

    removeMember: (root, { personId, groupId }) =>
      removeMember(userId, personId, groupId),

    removeModerator: (root, { personId, groupId, isRemoveFromGroup }) =>
      removeModerator(userId, personId, groupId, isRemoveFromGroup),

    removePost: (root, { postId, groupId, slug }) =>
      removePost(userId, postId, groupId || slug),

    removeSkill: (root, { id, name }) => removeSkill(userId, id || name),
    removeSkillToLearn: (root, { id, name }) => removeSkillToLearn(userId, id || name),
    removeSuggestedSkillFromGroup: (root, { groupId, id, name }) => removeSuggestedSkillFromGroup(userId, groupId, id || name),

    requestToAddGroupToParent: (root, { parentId, childId }) =>
      inviteGroupToGroup(userId, childId, parentId, GroupRelationshipInvite.TYPE.ChildToParent),

    resendInvitation: (root, {invitationId}) =>
      resendInvitation(userId, invitationId),

    respondToEvent: (root, {id, response}) =>
      respondToEvent(userId, id, response),

    subscribe: (root, { groupId, topicId, isSubscribing }) =>
      subscribe(userId, topicId, groupId, isSubscribing),

    unblockUser: (root, { blockedUserId }) => unblockUser(userId, blockedUserId),

    unfulfillPost: (root, { postId }) => unfulfillPost(userId, postId),

    unlinkAccount: (root, { provider }) =>
      unlinkAccount(userId, provider),

    updateGroupSettings: (root, { id, changes }) =>
      updateGroup(userId, id, changes),

    updateGroupHiddenSetting: (root, { id, hidden }) =>
      updateGroupHiddenSetting({ userId, isAdmin }, id, hidden),

    updateGroupTopic: (root, { id, data }) => updateGroupTopic(id, data),

    // TODO: need this and the one above?
    updateGroupTopicFollow: (root, args) => updateGroupTopic(userId, args),

    updateMe: (root, { changes }) => updateMe(userId, changes),

    updateMembership: (root, args) => updateMembership(userId, args),

    updatePost: (root, args) => updatePost(userId, args),
    updateComment: (root, args) => updateComment(userId, args),

    updateStripeAccount: (root, { accountId }) => updateStripeAccount(userId, accountId),

    updateWidget: (root, { id, changes }) => updateWidget(id, changes),

    useInvitation: (root, { invitationToken, accessCode }) =>
      useInvitation(userId, invitationToken, accessCode),

    vote: (root, { postId, isUpvote }) => vote(userId, postId, isUpvote)
  }
}

export const createRequestHandler = () =>
  graphqlHTTP(async (req, res) => {
    if (process.env.DEBUG_GRAPHQL) {
      sails.log.info('\n' +
        red('graphql query start') + '\n' +
        req.body.query + '\n' +
        red('graphql query end')
      )
      sails.log.info(inspect(req.body.variables))
    }

    // TODO: since this function can return a promise, we could run through some
    // policies based on the current user here and assign them to context, so
    // that the resolvers can use them to deny or restrict access...
    //
    // ideally we would be able to associate paths with policies, analyze the
    // query to find the policies which should be tested, and run them to allow
    // or deny access to those paths

    await User.query().where({ id: req.session.userId }).update({ last_active_at: new Date() })

    const schema = await createSchema(req.session.userId, Admin.isSignedIn(req))
    return {
      schema,
      graphiql: true,
      customFormatErrorFn: process.env.NODE_ENV === 'development' ? logError : null
    }
  })

var modelToTypeMap

function getTypeForInstance (instance, models) {
  if (!modelToTypeMap) {
    modelToTypeMap = reduce(models, (m, v, k) => {
      const tableName = v.model.forge().tableName
      if (!m[tableName] || v.isDefaultTypeForTable) {
        m[tableName] = k
      }
      return m
    }, {})
  }

  return modelToTypeMap[instance.tableName]
}

function logError (error) {
  console.error(error.stack)

  return {
    message: error.message,
    locations: error.locations,
    stack: error.stack,
    path: error.path
  }
}
<commit_msg>Fix bug that broke non-logged in access to public map<commit_after>import { readFileSync } from 'fs'
import { graphqlHTTP } from 'express-graphql'
import { join } from 'path'
import setupBridge from '../../lib/graphql-bookshelf-bridge'
import { presentQuerySet } from '../../lib/graphql-bookshelf-bridge/util'
import {
  acceptGroupRelationshipInvite,
  acceptJoinRequest,
  addModerator,
  addPeopleToProjectRole,
  addSkill,
  addSkillToLearn,
  addSuggestedSkillToGroup,
  allowGroupInvites,
  blockUser,
  cancelGroupRelationshipInvite,
  cancelJoinRequest,
  createAffiliation,
  createComment,
  createGroup,
  createInvitation,
  createJoinRequest,
  createMessage,
  createPost,
  createProject,
  createProjectRole,
  createSavedSearch,
  createTopic,
  declineJoinRequest,
  deleteAffiliation,
  deleteComment,
  deleteGroup,
  deleteGroupRelationship,
  deleteGroupTopic,
  deletePost,
  deleteProjectRole,
  deleteSavedSearch,
  expireInvitation,
  findOrCreateLinkPreviewByUrl,
  findOrCreateLocation,
  findOrCreateThread,
  flagInappropriateContent,
  fulfillPost,
  inviteGroupToGroup,
  invitePeopleToEvent,
  joinGroup,
  joinProject,
  leaveGroup,
  leaveProject,
  markActivityRead,
  markAllActivitiesRead,
  pinPost,
  processStripeToken,
  regenerateAccessCode,
  registerDevice,
  registerStripeAccount,
  reinviteAll,
  rejectGroupRelationshipInvite,
  removeMember,
  removeModerator,
  removePost,
  removeSkill,
  removeSkillToLearn,
  removeSuggestedSkillFromGroup,
  resendInvitation,
  respondToEvent,
  subscribe,
  toggleGroupWidgetVisibility,
  unblockUser,
  unfulfillPost,
  unlinkAccount,
  updateComment,
  updateGroup,
  updateGroupHiddenSetting,
  updateGroupTopic,
  updateGroupTopicFollow,
  updateMe,
  updateMembership,
  updatePost,
  updateStripeAccount,
  updateWidget,
  useInvitation,
  vote
} from './mutations'
import InvitationService from '../services/InvitationService'
import makeModels from './makeModels'
import { makeExecutableSchema } from 'graphql-tools'
import { inspect } from 'util'
import { red } from 'chalk'
import { mapValues, merge, reduce } from 'lodash'

const schemaText = readFileSync(join(__dirname, 'schema.graphql')).toString()

async function createSchema (userId, isAdmin) {
  const models = await makeModels(userId, isAdmin)
  const { resolvers, fetchOne, fetchMany } = setupBridge(models)

  let allResolvers = Object.assign({
    Query: userId ? makeAuthenticatedQueries(userId, fetchOne, fetchMany) : makePublicQueries(userId, fetchOne, fetchMany),
    Mutation: userId ? makeMutations(userId, isAdmin) : {},

    FeedItemContent: {
      __resolveType (data, context, info) {
        if (data instanceof bookshelf.Model) {
          return info.schema.getType('Post')
        }
        throw new Error('Post is the only implemented FeedItemContent type')
      }
    },

    SearchResultContent: {
      __resolveType (data, context, info) {
        return getTypeForInstance(data, models)
      }
    }
  }, resolvers)

  return makeExecutableSchema({
    typeDefs: [schemaText],
    resolvers: allResolvers
  })
}

// Queries that non-logged in users can make
export function makePublicQueries (userId, fetchOne, fetchMany) {
  return {
    checkInvitation: (root, { invitationToken, accessCode }) =>
      InvitationService.check(userId, invitationToken, accessCode),
    // Can only access public communities and posts
    group: async (root, { id, slug }) => fetchOne('Group', slug || id, slug ? 'slug' : 'id', { visibility: Group.Visibility.PUBLIC }),
    groups: (root, args) => fetchMany('Group', Object.assign(args, { visibility: Group.Visibility.PUBLIC })),
    posts: (root, args) => fetchMany('Post', Object.assign(args, { isPublic: true }))
  }
}

// Queries that logged in users can make
export function makeAuthenticatedQueries (userId, fetchOne, fetchMany) {
  return {
    activity: (root, { id }) => fetchOne('Activity', id),
    checkInvitation: (root, { invitationToken, accessCode }) =>
      InvitationService.check(userId, invitationToken, accessCode),
    comment: (root, { id }) => fetchOne('Comment', id),
    connections: (root, args) => fetchMany('PersonConnection', args),
    group: async (root, { id, slug, updateLastViewed }) => {
      // you can specify id or slug, but not both
      const group = await fetchOne('Group', slug || id, slug ? 'slug' : 'id')
      if (updateLastViewed && group) {
        const membership = await GroupMembership.forPair(userId, group).fetch()
        if (membership) {
          await membership.addSetting({ lastReadAt: new Date() }, true)
        }
      }
      return group
    },
    groupExists: (root, { slug }) => {
      if (Group.isSlugValid(slug)) {
        return Group.where(bookshelf.knex.raw('slug = ?', slug))
        .count()
        .then(count => {
          if (count > 0) return {exists: true}
          return {exists: false}
        })
      }
      throw new Error('Slug is invalid')
    },
    groupTopic: (root, { topicName, groupSlug }) =>
      GroupTag.findByTagAndGroup(topicName, groupSlug),
    groupTopics: (root, args) => fetchMany('GroupTopic', args),
    groups: (root, args) => fetchMany('Group', args),
    joinRequests: (root, args) => fetchMany('JoinRequest', args),
    me: () => fetchOne('Me', userId),
    messageThread: (root, { id }) => fetchOne('MessageThread', id),
    notifications: (root, { first, offset, resetCount, order = 'desc' }) => {
      return fetchMany('Notification', { first, offset, order })
      .tap(() => resetCount && User.resetNewNotificationCount(userId))
    },
    people: (root, args) => fetchMany('Person', args),
    person: (root, { id }) => fetchOne('Person', id),
    post: (root, { id }) => fetchOne('Post', id),
    posts: (root, args) => fetchMany('Post', args),
    savedSearches: (root, args) => fetchMany('SavedSearch', args),
    search: (root, args) => {
      if (!args.first) args.first = 20
      return Search.fullTextSearch(userId, args)
      .then(({ models, total }) => {
        // FIXME this shouldn't be used directly here -- there should be some
        // way of integrating this into makeModels and using the presentation
        // logic that's already in the fetcher
        return presentQuerySet(models, merge(args, {total}))
      })
    },
    skills: (root, args) => fetchMany('Skill', args),
    topic: (root, { id, name }) => // you can specify id or name, but not both
      fetchOne('Topic', name || id, name ? 'name' : 'id'),
    topics: (root, args) => fetchMany('Topic', args)
  }
}

export function makeMutations (userId, isAdmin) {
  return {
    acceptGroupRelationshipInvite: (root, { groupRelationshipInviteId }) => acceptGroupRelationshipInvite(userId, groupRelationshipInviteId),

    acceptJoinRequest: (root, { joinRequestId }) => acceptJoinRequest(userId, joinRequestId),

    addModerator: (root, { personId, groupId }) =>
      addModerator(userId, personId, groupId),

    addPeopleToProjectRole: (root, { peopleIds, projectRoleId }) =>
      addPeopleToProjectRole(userId, peopleIds, projectRoleId),

    addSkill: (root, { name }) => addSkill(userId, name),
    addSkillToLearn: (root, { name }) => addSkillToLearn(userId, name),
    addSuggestedSkillToGroup: (root, { groupId, name }) => addSuggestedSkillToGroup(userId, groupId, name),

    allowGroupInvites: (root, { groupId, data }) => allowGroupInvites(groupId, data),

    blockUser: (root, { blockedUserId }) => blockUser(userId, blockedUserId),

    cancelGroupRelationshipInvite: (root, { groupRelationshipInviteId }) => cancelGroupRelationshipInvite(userId, groupRelationshipInviteId),

    cancelJoinRequest: (root, { joinRequestId }) => cancelJoinRequest(userId, joinRequestId),

    createAffiliation: (root, { data }) => createAffiliation(userId, data),

    createComment: (root, { data }) => createComment(userId, data),

    createGroup: (root, { data }) => createGroup(userId, data),

    createInvitation: (root, {groupId, data}) =>
      createInvitation(userId, groupId, data),

    createJoinRequest: (root, {groupId, questionAnswers}) => createJoinRequest(userId, groupId, questionAnswers),

    createMessage: (root, { data }) => createMessage(userId, data),

    createPost: (root, { data }) => createPost(userId, data),

    createProject: (root, { data }) => createProject(userId, data),

    createProjectRole: (root, { projectId, roleName }) => createProjectRole(userId, projectId, roleName),

    createSavedSearch: (root, { data }) => createSavedSearch(data),

    joinGroup: (root, {groupId}) => joinGroup(groupId, userId),

    joinProject: (root, { id }) => joinProject(id, userId),

    createTopic: (root, { topicName, groupId, isDefault, isSubscribing }) => createTopic(userId, topicName, groupId, isDefault, isSubscribing),

    declineJoinRequest: (root, { joinRequestId }) => declineJoinRequest(userId, joinRequestId),

    deleteAffiliation: (root, { id }) => deleteAffiliation(userId, id),

    deleteComment: (root, { id }) => deleteComment(userId, id),

    deleteGroup: (root, { id }) => deleteGroup(userId, id),

    deleteGroupRelationship: (root, { parentId, childId }) => deleteGroupRelationship(userId, parentId, childId),

    deleteGroupTopic: (root, { id }) => deleteGroupTopic(userId, id),

    deletePost: (root, { id }) => deletePost(userId, id),

    deleteProjectRole: (root, { id }) => deleteProjectRole(userId, id),

    deleteSavedSearch: (root, { id }) => deleteSavedSearch(id),

    expireInvitation: (root, {invitationId}) =>
      expireInvitation(userId, invitationId),

    findOrCreateThread: (root, { data }) => findOrCreateThread(userId, data),

    findOrCreateLinkPreviewByUrl: (root, { data }) =>
      findOrCreateLinkPreviewByUrl(data),

    findOrCreateLocation: (root, { data }) => findOrCreateLocation(data),

    flagInappropriateContent: (root, { data }) =>
      flagInappropriateContent(userId, data),

    fulfillPost: (root, { postId }) => fulfillPost(userId, postId),

    inviteGroupToJoinParent: (root, { parentId, childId }) =>
      inviteGroupToGroup(userId, parentId, childId, GroupRelationshipInvite.TYPE.ParentToChild),

    invitePeopleToEvent: (root, {eventId, inviteeIds}) =>
      invitePeopleToEvent(userId, eventId, inviteeIds),

    leaveGroup: (root, { id }) => leaveGroup(userId, id),

    leaveProject: (root, { id }) => leaveProject(id, userId),

    markActivityRead: (root, { id }) => markActivityRead(userId, id),

    markAllActivitiesRead: (root) => markAllActivitiesRead(userId),

    pinPost: (root, { postId, groupId }) =>
      pinPost(userId, postId, groupId),

    processStripeToken: (root, { postId, token, amount }) =>
      processStripeToken(userId, postId, token, amount),

    regenerateAccessCode: (root, { groupId }) =>
      regenerateAccessCode(userId, groupId),

    registerDevice: (root, { playerId, platform, version }) =>
      registerDevice(userId, { playerId, platform, version }),

    registerStripeAccount: (root, { authorizationCode }) =>
      registerStripeAccount(userId, authorizationCode),

    reinviteAll: (root, {groupId}) => reinviteAll(userId, groupId),

    rejectGroupRelationshipInvite: (root, { groupRelationshipInviteId }) => rejectGroupRelationshipInvite(userId, groupRelationshipInviteId),

    removeMember: (root, { personId, groupId }) =>
      removeMember(userId, personId, groupId),

    removeModerator: (root, { personId, groupId, isRemoveFromGroup }) =>
      removeModerator(userId, personId, groupId, isRemoveFromGroup),

    removePost: (root, { postId, groupId, slug }) =>
      removePost(userId, postId, groupId || slug),

    removeSkill: (root, { id, name }) => removeSkill(userId, id || name),
    removeSkillToLearn: (root, { id, name }) => removeSkillToLearn(userId, id || name),
    removeSuggestedSkillFromGroup: (root, { groupId, id, name }) => removeSuggestedSkillFromGroup(userId, groupId, id || name),

    requestToAddGroupToParent: (root, { parentId, childId }) =>
      inviteGroupToGroup(userId, childId, parentId, GroupRelationshipInvite.TYPE.ChildToParent),

    resendInvitation: (root, {invitationId}) =>
      resendInvitation(userId, invitationId),

    respondToEvent: (root, {id, response}) =>
      respondToEvent(userId, id, response),

    subscribe: (root, { groupId, topicId, isSubscribing }) =>
      subscribe(userId, topicId, groupId, isSubscribing),

    unblockUser: (root, { blockedUserId }) => unblockUser(userId, blockedUserId),

    unfulfillPost: (root, { postId }) => unfulfillPost(userId, postId),

    unlinkAccount: (root, { provider }) =>
      unlinkAccount(userId, provider),

    updateGroupSettings: (root, { id, changes }) =>
      updateGroup(userId, id, changes),

    updateGroupHiddenSetting: (root, { id, hidden }) =>
      updateGroupHiddenSetting({ userId, isAdmin }, id, hidden),

    updateGroupTopic: (root, { id, data }) => updateGroupTopic(id, data),

    // TODO: need this and the one above?
    updateGroupTopicFollow: (root, args) => updateGroupTopic(userId, args),

    updateMe: (root, { changes }) => updateMe(userId, changes),

    updateMembership: (root, args) => updateMembership(userId, args),

    updatePost: (root, args) => updatePost(userId, args),
    updateComment: (root, args) => updateComment(userId, args),

    updateStripeAccount: (root, { accountId }) => updateStripeAccount(userId, accountId),

    updateWidget: (root, { id, changes }) => updateWidget(id, changes),

    useInvitation: (root, { invitationToken, accessCode }) =>
      useInvitation(userId, invitationToken, accessCode),

    vote: (root, { postId, isUpvote }) => vote(userId, postId, isUpvote)
  }
}

export const createRequestHandler = () =>
  graphqlHTTP(async (req, res) => {
    if (process.env.DEBUG_GRAPHQL) {
      sails.log.info('\n' +
        red('graphql query start') + '\n' +
        req.body.query + '\n' +
        red('graphql query end')
      )
      sails.log.info(inspect(req.body.variables))
    }

    // TODO: since this function can return a promise, we could run through some
    // policies based on the current user here and assign them to context, so
    // that the resolvers can use them to deny or restrict access...
    //
    // ideally we would be able to associate paths with policies, analyze the
    // query to find the policies which should be tested, and run them to allow
    // or deny access to those paths

    if (req.session.userId) {
      await User.query().where({ id: req.session.userId }).update({ last_active_at: new Date() })
    }

    const schema = await createSchema(req.session.userId, Admin.isSignedIn(req))
    return {
      schema,
      graphiql: true,
      customFormatErrorFn: process.env.NODE_ENV === 'development' ? logError : null
    }
  })

var modelToTypeMap

function getTypeForInstance (instance, models) {
  if (!modelToTypeMap) {
    modelToTypeMap = reduce(models, (m, v, k) => {
      const tableName = v.model.forge().tableName
      if (!m[tableName] || v.isDefaultTypeForTable) {
        m[tableName] = k
      }
      return m
    }, {})
  }

  return modelToTypeMap[instance.tableName]
}

function logError (error) {
  console.error(error.stack)

  return {
    message: error.message,
    locations: error.locations,
    stack: error.stack,
    path: error.path
  }
}
<|endoftext|>


<commit_before>// pump.js
//
// Entrypoint for the pump.io client UI
//
// Copyright 2011-2012, E14N https://e14n.com/
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Make sure this exists

if (!window.Pump) {
    window.Pump = {};
}

(function(_, $, Backbone, Pump) {

    // This is overwritten by inline script in layout.utml

    Pump.config = {};

    // Main entry point

    $(document).ready(function() {

        // Set up router

        Pump.router   = new Pump.Router();

        // Set up initial view

        Pump.body     = new Pump.BodyView({el: $("body")});
        Pump.body.nav = new Pump.AnonymousNav({el: ".navbar-inner .container"});

        // XXX: Make this more complete

        Pump.initialContentView();

        $("abbr.easydate").easydate();

        Backbone.history.start({pushState: true, silent: true});

        Pump.setupWysiHTML5();

        // Refresh the streams automatically every 60 seconds
        // This is a fallback in case something gets lost in the
        // SockJS conversation

        Pump.refreshStreamsID = setInterval(Pump.refreshStreams, 60000);

        // Connect to current server

        if (Pump.config.sockjs) {
            Pump.setupSocket();
        }

        Pump.setupInfiniteScroll();

        if (Pump.principalUser) {
            Pump.principalUser = Pump.User.unique(Pump.principalUser);
            Pump.principal = Pump.Person.unique(Pump.principal);
            Pump.body.nav = new Pump.UserNav({el: Pump.body.$(".navbar-inner .container"),
                                              model: Pump.principalUser,
                                              data: {
                                                  messages: Pump.principalUser.majorDirectInbox,
                                                  notifications: Pump.principalUser.minorDirectInbox
                                              }});
        } else if (Pump.principal) {
            Pump.principal = Pump.Person.unique(Pump.principal);
            Pump.body.nav = new Pump.RemoteNav({el: Pump.body.$(".navbar-inner .container"),
                                                model: Pump.principal});
        } else {
            // Check if we have stored OAuth credentials

            Pump.ensureCred(function(err, cred) {

                var nickname, pair;

                if (err) {
                    Pump.error(err.message);
                    return;
                }

                pair = Pump.getUserCred();

                if (pair) {

                    // We need to renew the session, for images and objects and so on.

                    Pump.renewSession(function(err, data) {

                        var user, major, minor;

                        if (err) {
                            Pump.error(err);
                            Pump.clearUserCred();
                            return;
                        }

                        user = Pump.principalUser = Pump.User.unique(data);
                        Pump.principal = Pump.principalUser.profile;

                        major = user.majorDirectInbox;
                        minor = user.minorDirectInbox;

                        Pump.fetchObjects([major, minor], function(err, objs) {
                            var sp, continueTo;

                            if (err) {
                                Pump.clearUserCred();
                                Pump.error(err);
                                return;
                            }

                            Pump.principalUser = user;

                            Pump.body.nav = new Pump.UserNav({el: ".navbar-inner .container",
                                                              model: user,
                                                              data: {
                                                                  messages: major,
                                                                  notifications: minor
                                                              }});
                            Pump.body.nav.render();

                            // If we're on the login page, and there's a current
                            // user, redirect to the actual page

                            switch (window.location.pathname) {
                            case "/main/login":
                                Pump.body.content = new Pump.LoginContent();
                                continueTo = Pump.getContinueTo();
                                Pump.router.navigate(continueTo, true);
                                break;
                            case "/":
                                Pump.router.home();
                                break;
                            }
                        });
                    });
                }
            });
        }
    });

    // Renew the cookie session

    Pump.renewSession = function(callback) {

        var options = {
            dataType: "json",
            type: "POST",
            url: "/main/renew",
            success: function(data, textStatus, jqXHR) {
                callback(null, data);
            },
            error: function(jqXHR, textStatus, errorThrown) {
                callback(new Error("Failed to renew"), null);
            }
        };

        Pump.ajax(options);
    };

    // When errors happen, and you don't know what to do with them,
    // send them here and I'll figure it out.

    Pump.error = function(err) {
        console.log(err);
        if (err.stack) {
            console.log(err.stack);
        }
    };

    // Given a relative URL like /main/register, make a fully-qualified
    // URL on the current server

    Pump.fullURL = function(url) {

        var here = window.location;

        if (url.indexOf(':') == -1) {
            if (url.substr(0, 1) == '/') {
                url = here.protocol + '//' + here.host + url;
            } else {
                url = here.href.substr(0, here.href.lastIndexOf('/') + 1) + url;
            }
        }

        return url;
    };

    // Add some OAuth magic to the arguments for a $.ajax() call

    Pump.oauthify = function(options) {

        options.url = Pump.fullURL(options.url);

        var message = {action: options.url,
                       method: options.type,
                       parameters: [["oauth_version", "1.0"],
                                    ["oauth_consumer_key", options.consumerKey]]};

        if (options.token) {
            message.parameters.push(["oauth_token", options.token]);
        }

        OAuth.setTimestampAndNonce(message);
        OAuth.SignatureMethod.sign(message,
                                   {consumerSecret: options.consumerSecret,
                                    tokenSecret: options.tokenSecret});

        var header =  OAuth.getAuthorizationHeader("OAuth", message.parameters);

        options.headers = {Authorization: header};

        return options;
    };

    Pump.fetchObjects = function(orig, callback) {
        var fetched = 0,
            objs = (orig.length) > 0 ? orig.slice(0) : [], // make a dupe in case arg is changed
            count = objs.length,
            done = false,
            onSuccess = function() {
                if (!done) {
                    fetched++;
                    if (fetched >= count) {
                        done = true;
                        callback(null, objs);
                    }
                }
            },
            onError = function(xhr, status, thrown) {
                if (!done) {
                    done = true;
                    if (thrown) {
                        callback(thrown, null);
                    } else {
                        callback(new Error(status), null);
                    }
                }
            };

        _.each(objs, function(obj) {
            try {
                if (_.isFunction(obj.prevLink) && obj.prevLink()) {
                    obj.getPrev(function(err) {
                        if (err) {
                            onError(null, null, err);
                        } else {
                            onSuccess();
                        }
                    });
                } else {
                    obj.fetch({update: true,
                               success: onSuccess,
                               error: onError});
                }
            } catch (e) {
                onError(null, null, e);
            }
        });
    };

    // Not the most lovely, but it works
    // XXX: change this to use UTML templating instead

    Pump.wysihtml5Tmpl = {
        "emphasis": function(locale) {
            return "
" +
                "
" +
                "" +
                "" +
                "_" +
                "
" +
                "
";
        }
    };

    // Most long-form descriptions and notes use this lib for editing

    Pump.setupWysiHTML5 = function() {

        // Set wysiwyg defaults

        $.fn.wysihtml5.defaultOptions["font-styles"] = false;
        $.fn.wysihtml5.defaultOptions["image"] = false;
        $.fn.wysihtml5.defaultOptions["customTemplates"] = Pump.wysihtml5Tmpl;
    };

    // Turn the querystring into an object

    Pump.searchParams = function(str) {
        var params = {},
            pl     = /\+/g,
            decode = function (s) { return decodeURIComponent(s.replace(pl, " ")); },
            pairs;

        if (!str) {
            str = window.location.search;
        }

        pairs = str.substr(1).split("&");

        _.each(pairs, function(pairStr) {
            var pair = pairStr.split("=", 2),
                key = decode(pair[0]),
                value = (pair.length > 1) ? decode(pair[1]) : null;

            params[key] = value;
        });

        return params;
    };

    Pump.continueTo = null;

    // Get the "continue" param

    Pump.getContinueTo = function() {
        var sp = Pump.searchParams(),
            continueTo = (_.has(sp, "continue")) ? sp["continue"] : null;

        if (continueTo && continueTo.length > 0 && continueTo[0] == "/") {
            return continueTo;
        } else if (Pump.continueTo) {
            continueTo = Pump.continueTo;
            return continueTo;
        } else {
            return "";
        }
    };

    Pump.saveContinueTo = function() {
        Pump.continueTo = window.location.pathname + window.location.search;
    };

    Pump.clearContinueTo = function() {
        Pump.continueTo = null;
    };

    // We clear out cached stuff when login state changes

    Pump.clearCaches = function() {
        Pump.Model.clearCache();
        Pump.User.clearCache();
    };

    Pump.ajax = function(options) {
        // For remote users, we use session auth
        if (Pump.principal && !Pump.principalUser && options.type == "GET") {
            $.ajax(options);
        } else {
            Pump.ensureCred(function(err, cred) {
                var pair;
                if (err) {
                    Pump.error("Couldn't get OAuth credentials. :(");
                } else {
                    options.consumerKey = cred.clientID;
                    options.consumerSecret = cred.clientSecret;
                    pair = Pump.getUserCred();

                    if (pair) {
                        options.token = pair.token;
                        options.tokenSecret = pair.secret;
                    }

                    options = Pump.oauthify(options);
                    $.ajax(options);
                }
            });
        }
    };

    Pump.setupInfiniteScroll = function() {

        var didScroll = false;

        // scroll fires too fast, so just use the handler
        // to set a flag, and check that flag with an interval

        // From http://ejohn.org/blog/learning-from-twitter/

        $(window).scroll(function() {
            didScroll = true;
        });

        setInterval(function() {
            var streams;
            if (didScroll) {
                didScroll = false;
                if ($(window).scrollTop() >= $(document).height() - $(window).height() - 10) {
                    streams = Pump.getStreams();
                    if (streams.major && streams.major.nextLink) {
                        Pump.body.startLoad();
                        streams.major.getNext(function(err) {
                            Pump.body.endLoad();
                        });
                    }
                }
            }
        }, 250);
    };

    // XXX: this is cheeseball.

    Pump.rel = function(url) {

        var a = document.createElement('a'),
            pathname;

        a.href = url;
        pathname = a.pathname;

        return pathname;
    };

    Pump.htmlEncode = function(value) {
        return $('
').text(value).html();
    };

    Pump.htmlDecode = function(value) {
        return $('
').html(value).text();
    };

    // Sets up the initial view and sub-views

    Pump.initialContentView = function() {

        var $content = $("#content"),
            selectorToView = {
                "#main": {View: Pump.MainContent},
                "#loginpage": {View: Pump.LoginContent},
                "#register": {View: Pump.RegisterContent},
                "#inbox": {View: Pump.InboxContent, models: {major: Pump.ActivityStream, minor: Pump.ActivityStream}},
                ".object-page": {View: Pump.ObjectContent, models: {object: Pump.ActivityObject}},
                ".major-activity-page": {View: Pump.ActivityContent, models: {activity: Pump.Activity}},
                ".user-activities": {View: Pump.UserPageContent, models: {profile: Pump.Person,
                                                                          major: Pump.ActivityStream,
                                                                          minor: Pump.ActivityStream}},
                ".user-favorites": {View: Pump.FavoritesContent, models: {profile: Pump.Person,
                                                                          favorites: Pump.ActivityObjectStream}},
                ".user-followers": {View: Pump.FollowersContent, models: {profile: Pump.Person,
                                                                          followers: Pump.PeopleStream}},
                ".user-following": {View: Pump.FollowingContent, models: {profile: Pump.Person,
                                                                          following: Pump.PeopleStream}},
                ".user-lists": {View: Pump.ListsContent, models: {profile: Pump.Person,
                                                                  lists: Pump.ActivityObjectStream}},
                ".user-list": {View: Pump.ListContent, models: {profile: Pump.Person,
                                                                lists: Pump.ActivityObjectStream,
                                                                list: Pump.ActivityObject}}
            },
            selector,
            $el,
            model,
            options,
            def,
            data,
            View;

        // When I say "view" the crowd say "selector"

        for (selector in selectorToView) {
            if (_.has(selectorToView, selector)) {
                $el = $content.find(selector);
                if ($el.length > 0) {
                    def = selectorToView[selector];
                    View = def.View;
                    options = {el: $el, data: {}};
                    data = Pump.initialData;
                    _.each(data, function(value, name) {
                        if (name == View.prototype.modelName) {
                            options.model = def.models[name].unique(value);
                        } else if (def.models[name]) {
                            options.data[name] = def.models[name].unique(value);
                        } else {
                            options.data[name] = value;
                        }
                    });
                    Pump.body.content = new View(options);
                    Pump.initialData = null;
                    break;
                }
            }
        }

        // XXX: set up initial data
    };

    Pump.newMinorActivity = function(act, callback) {
        if (Pump.principalUser) {
            Pump.addToStream(Pump.principalUser.minorStream, act, callback);
        } else {
            Pump.proxyActivity(act, callback);
        }
    };

    Pump.newMajorActivity = function(act, callback) {
        if (Pump.principalUser) {
            Pump.addToStream(Pump.principalUser.majorStream, act, callback);
        } else {
            Pump.proxyActivity(act, callback);
        }
    };

    Pump.addToStream = function(stream, act, callback) {
        stream.items.create(act, {
            success: function(act) {
                callback(null, act);
            },
            error: function(jqXHR, textStatus, errorThrown) {
                var type, response;
                type = jqXHR.getResponseHeader("Content-Type");
                if (type && type.indexOf("application/json") !== -1) {
                    response = JSON.parse(jqXHR.responseText);
                    callback(new Error(response.error), null);
                } else {
                    callback(new Error(errorThrown), null);
                }
            }
        });
    };

    // XXX: This POSTs with session auth; subject to XSS.

    Pump.proxyActivity = function(act, callback) {
        $.ajax({
            contentType: "application/json",
            data: JSON.stringify(act),
            dataType: "json",
            type: "POST",
            url: "/main/proxy",
            success: function(act) {
                callback(null, act);
            },
            error: function(jqXHR, textStatus, errorThrown) {
                var type, response;
                type = jqXHR.getResponseHeader("Content-Type");
                if (type && type.indexOf("application/json") !== -1) {
                    response = JSON.parse(jqXHR.responseText);
                    callback(new Error(response.error), null);
                } else {
                    callback(new Error(errorThrown), null);
                }
            }
        });
    };

    Pump.setTitle = function(title) {
        $("title").html(title + " - " + Pump.config.site);
    };

})(window._, window.$, window.Backbone, window.Pump);
<commit_msg>Don't use getPrev() for now<commit_after>// pump.js
//
// Entrypoint for the pump.io client UI
//
// Copyright 2011-2012, E14N https://e14n.com/
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Make sure this exists

if (!window.Pump) {
    window.Pump = {};
}

(function(_, $, Backbone, Pump) {

    // This is overwritten by inline script in layout.utml

    Pump.config = {};

    // Main entry point

    $(document).ready(function() {

        // Set up router

        Pump.router   = new Pump.Router();

        // Set up initial view

        Pump.body     = new Pump.BodyView({el: $("body")});
        Pump.body.nav = new Pump.AnonymousNav({el: ".navbar-inner .container"});

        // XXX: Make this more complete

        Pump.initialContentView();

        $("abbr.easydate").easydate();

        Backbone.history.start({pushState: true, silent: true});

        Pump.setupWysiHTML5();

        // Refresh the streams automatically every 60 seconds
        // This is a fallback in case something gets lost in the
        // SockJS conversation

        Pump.refreshStreamsID = setInterval(Pump.refreshStreams, 60000);

        // Connect to current server

        if (Pump.config.sockjs) {
            Pump.setupSocket();
        }

        Pump.setupInfiniteScroll();

        if (Pump.principalUser) {
            Pump.principalUser = Pump.User.unique(Pump.principalUser);
            Pump.principal = Pump.Person.unique(Pump.principal);
            Pump.body.nav = new Pump.UserNav({el: Pump.body.$(".navbar-inner .container"),
                                              model: Pump.principalUser,
                                              data: {
                                                  messages: Pump.principalUser.majorDirectInbox,
                                                  notifications: Pump.principalUser.minorDirectInbox
                                              }});
        } else if (Pump.principal) {
            Pump.principal = Pump.Person.unique(Pump.principal);
            Pump.body.nav = new Pump.RemoteNav({el: Pump.body.$(".navbar-inner .container"),
                                                model: Pump.principal});
        } else {
            // Check if we have stored OAuth credentials

            Pump.ensureCred(function(err, cred) {

                var nickname, pair;

                if (err) {
                    Pump.error(err.message);
                    return;
                }

                pair = Pump.getUserCred();

                if (pair) {

                    // We need to renew the session, for images and objects and so on.

                    Pump.renewSession(function(err, data) {

                        var user, major, minor;

                        if (err) {
                            Pump.error(err);
                            Pump.clearUserCred();
                            return;
                        }

                        user = Pump.principalUser = Pump.User.unique(data);
                        Pump.principal = Pump.principalUser.profile;

                        major = user.majorDirectInbox;
                        minor = user.minorDirectInbox;

                        Pump.fetchObjects([major, minor], function(err, objs) {
                            var sp, continueTo;

                            if (err) {
                                Pump.clearUserCred();
                                Pump.error(err);
                                return;
                            }

                            Pump.principalUser = user;

                            Pump.body.nav = new Pump.UserNav({el: ".navbar-inner .container",
                                                              model: user,
                                                              data: {
                                                                  messages: major,
                                                                  notifications: minor
                                                              }});
                            Pump.body.nav.render();

                            // If we're on the login page, and there's a current
                            // user, redirect to the actual page

                            switch (window.location.pathname) {
                            case "/main/login":
                                Pump.body.content = new Pump.LoginContent();
                                continueTo = Pump.getContinueTo();
                                Pump.router.navigate(continueTo, true);
                                break;
                            case "/":
                                Pump.router.home();
                                break;
                            }
                        });
                    });
                }
            });
        }
    });

    // Renew the cookie session

    Pump.renewSession = function(callback) {

        var options = {
            dataType: "json",
            type: "POST",
            url: "/main/renew",
            success: function(data, textStatus, jqXHR) {
                callback(null, data);
            },
            error: function(jqXHR, textStatus, errorThrown) {
                callback(new Error("Failed to renew"), null);
            }
        };

        Pump.ajax(options);
    };

    // When errors happen, and you don't know what to do with them,
    // send them here and I'll figure it out.

    Pump.error = function(err) {
        console.log(err);
        if (err.stack) {
            console.log(err.stack);
        }
    };

    // Given a relative URL like /main/register, make a fully-qualified
    // URL on the current server

    Pump.fullURL = function(url) {

        var here = window.location;

        if (url.indexOf(':') == -1) {
            if (url.substr(0, 1) == '/') {
                url = here.protocol + '//' + here.host + url;
            } else {
                url = here.href.substr(0, here.href.lastIndexOf('/') + 1) + url;
            }
        }

        return url;
    };

    // Add some OAuth magic to the arguments for a $.ajax() call

    Pump.oauthify = function(options) {

        options.url = Pump.fullURL(options.url);

        var message = {action: options.url,
                       method: options.type,
                       parameters: [["oauth_version", "1.0"],
                                    ["oauth_consumer_key", options.consumerKey]]};

        if (options.token) {
            message.parameters.push(["oauth_token", options.token]);
        }

        OAuth.setTimestampAndNonce(message);
        OAuth.SignatureMethod.sign(message,
                                   {consumerSecret: options.consumerSecret,
                                    tokenSecret: options.tokenSecret});

        var header =  OAuth.getAuthorizationHeader("OAuth", message.parameters);

        options.headers = {Authorization: header};

        return options;
    };

    Pump.fetchObjects = function(orig, callback) {
        var fetched = 0,
            objs = (orig.length) > 0 ? orig.slice(0) : [], // make a dupe in case arg is changed
            count = objs.length,
            done = false,
            onSuccess = function() {
                if (!done) {
                    fetched++;
                    if (fetched >= count) {
                        done = true;
                        callback(null, objs);
                    }
                }
            },
            onError = function(xhr, status, thrown) {
                if (!done) {
                    done = true;
                    if (thrown) {
                        callback(thrown, null);
                    } else {
                        callback(new Error(status), null);
                    }
                }
            };

        _.each(objs, function(obj) {
            try {
                obj.fetch({update: true,
                           success: onSuccess,
                           error: onError});
            } catch (e) {
                onError(null, null, e);
            }
        });
    };

    // Not the most lovely, but it works
    // XXX: change this to use UTML templating instead

    Pump.wysihtml5Tmpl = {
        "emphasis": function(locale) {
            return "
" +
                "
" +
                "" +
                "" +
                "_" +
                "
" +
                "
";
        }
    };

    // Most long-form descriptions and notes use this lib for editing

    Pump.setupWysiHTML5 = function() {

        // Set wysiwyg defaults

        $.fn.wysihtml5.defaultOptions["font-styles"] = false;
        $.fn.wysihtml5.defaultOptions["image"] = false;
        $.fn.wysihtml5.defaultOptions["customTemplates"] = Pump.wysihtml5Tmpl;
    };

    // Turn the querystring into an object

    Pump.searchParams = function(str) {
        var params = {},
            pl     = /\+/g,
            decode = function (s) { return decodeURIComponent(s.replace(pl, " ")); },
            pairs;

        if (!str) {
            str = window.location.search;
        }

        pairs = str.substr(1).split("&");

        _.each(pairs, function(pairStr) {
            var pair = pairStr.split("=", 2),
                key = decode(pair[0]),
                value = (pair.length > 1) ? decode(pair[1]) : null;

            params[key] = value;
        });

        return params;
    };

    Pump.continueTo = null;

    // Get the "continue" param

    Pump.getContinueTo = function() {
        var sp = Pump.searchParams(),
            continueTo = (_.has(sp, "continue")) ? sp["continue"] : null;

        if (continueTo && continueTo.length > 0 && continueTo[0] == "/") {
            return continueTo;
        } else if (Pump.continueTo) {
            continueTo = Pump.continueTo;
            return continueTo;
        } else {
            return "";
        }
    };

    Pump.saveContinueTo = function() {
        Pump.continueTo = window.location.pathname + window.location.search;
    };

    Pump.clearContinueTo = function() {
        Pump.continueTo = null;
    };

    // We clear out cached stuff when login state changes

    Pump.clearCaches = function() {
        Pump.Model.clearCache();
        Pump.User.clearCache();
    };

    Pump.ajax = function(options) {
        // For remote users, we use session auth
        if (Pump.principal && !Pump.principalUser && options.type == "GET") {
            $.ajax(options);
        } else {
            Pump.ensureCred(function(err, cred) {
                var pair;
                if (err) {
                    Pump.error("Couldn't get OAuth credentials. :(");
                } else {
                    options.consumerKey = cred.clientID;
                    options.consumerSecret = cred.clientSecret;
                    pair = Pump.getUserCred();

                    if (pair) {
                        options.token = pair.token;
                        options.tokenSecret = pair.secret;
                    }

                    options = Pump.oauthify(options);
                    $.ajax(options);
                }
            });
        }
    };

    Pump.setupInfiniteScroll = function() {

        var didScroll = false;

        // scroll fires too fast, so just use the handler
        // to set a flag, and check that flag with an interval

        // From http://ejohn.org/blog/learning-from-twitter/

        $(window).scroll(function() {
            didScroll = true;
        });

        setInterval(function() {
            var streams;
            if (didScroll) {
                didScroll = false;
                if ($(window).scrollTop() >= $(document).height() - $(window).height() - 10) {
                    streams = Pump.getStreams();
                    if (streams.major && streams.major.nextLink) {
                        Pump.body.startLoad();
                        streams.major.getNext(function(err) {
                            Pump.body.endLoad();
                        });
                    }
                }
            }
        }, 250);
    };

    // XXX: this is cheeseball.

    Pump.rel = function(url) {

        var a = document.createElement('a'),
            pathname;

        a.href = url;
        pathname = a.pathname;

        return pathname;
    };

    Pump.htmlEncode = function(value) {
        return $('
').text(value).html();
    };

    Pump.htmlDecode = function(value) {
        return $('
').html(value).text();
    };

    // Sets up the initial view and sub-views

    Pump.initialContentView = function() {

        var $content = $("#content"),
            selectorToView = {
                "#main": {View: Pump.MainContent},
                "#loginpage": {View: Pump.LoginContent},
                "#register": {View: Pump.RegisterContent},
                "#inbox": {View: Pump.InboxContent, models: {major: Pump.ActivityStream, minor: Pump.ActivityStream}},
                ".object-page": {View: Pump.ObjectContent, models: {object: Pump.ActivityObject}},
                ".major-activity-page": {View: Pump.ActivityContent, models: {activity: Pump.Activity}},
                ".user-activities": {View: Pump.UserPageContent, models: {profile: Pump.Person,
                                                                          major: Pump.ActivityStream,
                                                                          minor: Pump.ActivityStream}},
                ".user-favorites": {View: Pump.FavoritesContent, models: {profile: Pump.Person,
                                                                          favorites: Pump.ActivityObjectStream}},
                ".user-followers": {View: Pump.FollowersContent, models: {profile: Pump.Person,
                                                                          followers: Pump.PeopleStream}},
                ".user-following": {View: Pump.FollowingContent, models: {profile: Pump.Person,
                                                                          following: Pump.PeopleStream}},
                ".user-lists": {View: Pump.ListsContent, models: {profile: Pump.Person,
                                                                  lists: Pump.ActivityObjectStream}},
                ".user-list": {View: Pump.ListContent, models: {profile: Pump.Person,
                                                                lists: Pump.ActivityObjectStream,
                                                                list: Pump.ActivityObject}}
            },
            selector,
            $el,
            model,
            options,
            def,
            data,
            View;

        // When I say "view" the crowd say "selector"

        for (selector in selectorToView) {
            if (_.has(selectorToView, selector)) {
                $el = $content.find(selector);
                if ($el.length > 0) {
                    def = selectorToView[selector];
                    View = def.View;
                    options = {el: $el, data: {}};
                    data = Pump.initialData;
                    _.each(data, function(value, name) {
                        if (name == View.prototype.modelName) {
                            options.model = def.models[name].unique(value);
                        } else if (def.models[name]) {
                            options.data[name] = def.models[name].unique(value);
                        } else {
                            options.data[name] = value;
                        }
                    });
                    Pump.body.content = new View(options);
                    Pump.initialData = null;
                    break;
                }
            }
        }

        // XXX: set up initial data
    };

    Pump.newMinorActivity = function(act, callback) {
        if (Pump.principalUser) {
            Pump.addToStream(Pump.principalUser.minorStream, act, callback);
        } else {
            Pump.proxyActivity(act, callback);
        }
    };

    Pump.newMajorActivity = function(act, callback) {
        if (Pump.principalUser) {
            Pump.addToStream(Pump.principalUser.majorStream, act, callback);
        } else {
            Pump.proxyActivity(act, callback);
        }
    };

    Pump.addToStream = function(stream, act, callback) {
        stream.items.create(act, {
            success: function(act) {
                callback(null, act);
            },
            error: function(jqXHR, textStatus, errorThrown) {
                var type, response;
                type = jqXHR.getResponseHeader("Content-Type");
                if (type && type.indexOf("application/json") !== -1) {
                    response = JSON.parse(jqXHR.responseText);
                    callback(new Error(response.error), null);
                } else {
                    callback(new Error(errorThrown), null);
                }
            }
        });
    };

    // XXX: This POSTs with session auth; subject to XSS.

    Pump.proxyActivity = function(act, callback) {
        $.ajax({
            contentType: "application/json",
            data: JSON.stringify(act),
            dataType: "json",
            type: "POST",
            url: "/main/proxy",
            success: function(act) {
                callback(null, act);
            },
            error: function(jqXHR, textStatus, errorThrown) {
                var type, response;
                type = jqXHR.getResponseHeader("Content-Type");
                if (type && type.indexOf("application/json") !== -1) {
                    response = JSON.parse(jqXHR.responseText);
                    callback(new Error(response.error), null);
                } else {
                    callback(new Error(errorThrown), null);
                }
            }
        });
    };

    Pump.setTitle = function(title) {
        $("title").html(title + " - " + Pump.config.site);
    };

})(window._, window.$, window.Backbone, window.Pump);
<|endoftext|>


<commit_before>'use strict';

/*
 * Tanura main script.
 *
 * This script defines Tanura's high level features.
 */

/*
 * Check if an event exists.
 *
 * When given an event name, this function will check, if there is an entry in
 * tanura.eventHandler.events for that name, that has the methods required.
 */
tanura.eventHandler.check = function(_) {
    return !! this[_] && Array.isArray(this[_]);
}.bind(tanura.eventHandler.events)

/*
 * Safely perform something on an event.
 *
 * This will check if a given event exists and call a given function on it, if
 * it does. The return value indicates if the event was found.
 */
tanura.eventHandler.safe = function(_, f) {
    return this.check(_) && ! f(this.events[_]) || true;
}.bind(tanura.eventHandler)

/*
 * Fire an event.
 *
 * When given an event name, this function will run all callbacks for that
 * event. Exit is true on success, false otherwise.
 */
tanura.eventHandler.fire = (_) =>
    tanura.eventHandler.safe(_, (_) => _.forEach((i) => i()));

/*
 * Register a callback for an event.
 *
 * This will add a function to be called whenever a given event occurs. Exit is
 * true on success, false otherwise.
 */
tanura.eventHandler.register = (_, f) =>
    tanura.eventHandler.safe(_, (_) => _.push(f));

<commit_msg>Add a callback parameter to Tanura's events.<commit_after>'use strict';

/*
 * Tanura main script.
 *
 * This script defines Tanura's high level features.
 */

/*
 * Check if an event exists.
 *
 * When given an event name, this function will check, if there is an entry in
 * tanura.eventHandler.events for that name, that has the methods required.
 */
tanura.eventHandler.check = function(_) {
    return !! this[_] && Array.isArray(this[_]);
}.bind(tanura.eventHandler.events)

/*
 * Safely perform something on an event.
 *
 * This will check if a given event exists and call a given function on it, if
 * it does. The return value indicates if the event was found.
 */
tanura.eventHandler.safe = function(_, f) {
    return this.check(_) && ! f(this.events[_]) || true;
}.bind(tanura.eventHandler)

/*
 * Fire an event.
 *
 * When given an event name, this function will run all callbacks for that
 * event. A single parameter for the callback may be passed. Exit is true on
 * success, false otherwise.
 */
tanura.eventHandler.fire = (_, x) =>
    tanura.eventHandler.safe(_, (_) => _.forEach((i) => i(x)));

/*
 * Register a callback for an event.
 *
 * This will add a function to be called whenever a given event occurs. Exit is
 * true on success, false otherwise.
 */
tanura.eventHandler.register = (_, f) =>
    tanura.eventHandler.safe(_, (_) => _.push(f));

<|endoftext|>


<commit_before>/**
 *  Copyright 2013 Ionică Bizău
 *
 *  A Node.JS module, which provides an object oriented wrapper for the Youtube v3 API.
 *  Author: Ionică Bizău <bizauionica@gmail.com>
 *
 **/

var Util = require("../../util");

function getRating (options, callback) {
    var self = this;

    var url = Util.createUrl.apply(self, ["videos/getRating", options]);
    var reqOptions = {
        url: url,
    };

    self.Client.request(reqOptions, callback);
}

function list (options, callback) {
    var self = this;

    var url = Util.createUrl.apply(self, ["channels", options]);
    var reqOptions = {
        url: url,
    };

    self.Client.request(reqOptions, callback);
}

function insert (options, callback) {
    callback(null, {"error": "Not yet implemented"});
}

function update (options, callback) {
    callback(null, {"error": "Not yet implemented"});
}
function deleteItem (options, callback) {
    callback(null, {"error": "Not yet implemented"});
}
function rate (options, callback) {
    callback(null, {"error": "Not yet implemented"});
}

module.exports = {
    getRating: getRating,
    list: list,
    insert: insert,
    update: update,
    delete: deleteItem,
    rate: rate
};
<commit_msg>Updating video api request<commit_after>/**
 *  Copyright 2013 Ionică Bizău
 *
 *  A Node.JS module, which provides an object oriented wrapper for the Youtube v3 API.
 *  Author: Ionică Bizău <bizauionica@gmail.com>
 *
 **/

var Util = require("../../util");

function getRating (options, callback) {
    var self = this;

    var url = Util.createUrl.apply(self, ["videos/getRating", options]);
    var reqOptions = {
        url: url,
    };

    self.Client.request(reqOptions, callback);
}

function list (options, callback) {
    var self = this;

    var url = Util.createUrl.apply(self, ["videos", options]);
    var reqOptions = {
        url: url,
    };

    self.Client.request(reqOptions, callback);
}

function insert (options, callback) {
    callback(null, {"error": "Not yet implemented"});
}

function update (options, callback) {
    callback(null, {"error": "Not yet implemented"});
}
function deleteItem (options, callback) {
    callback(null, {"error": "Not yet implemented"});
}
function rate (options, callback) {
    callback(null, {"error": "Not yet implemented"});
}

module.exports = {
    getRating: getRating,
    list: list,
    insert: insert,
    update: update,
    delete: deleteItem,
    rate: rate
};
<|endoftext|>


<commit_before>import React from 'react'
import PropTypes from 'prop-types'
import { FormattedMessage, intlShape, injectIntl } from 'react-intl'
import { asField } from 'informed'
import { isOnchain, isLn } from '@zap/utils/crypto'
import TextArea from './TextArea'
import Message from './Message'
import messages from './messages'

/**
 * @render react
 * @name LightningInvoiceInput
 * @example
 * <LightningInvoiceInput
     network="testnet"
     field="testnet"
     id="testnet"
     validateOnChange
     validateOnBlur />
 */
class LightningInvoiceInput extends React.Component {
  static displayName = 'LightningInvoiceInput'

  static propTypes = {
    chain: PropTypes.oneOf(['bitcoin', 'litecoin']),
    intl: intlShape.isRequired,
    isRequired: PropTypes.bool,
    network: PropTypes.oneOf(['mainnet', 'testnet', 'regtest']),
  }

  static defaultProps = {
    isRequired: false,
  }

  validate = value => {
    const { intl } = this.props
    const { network, chain, isRequired } = this.props

    let chainName = `${chain}/lightning`
    if (network !== 'mainnet') {
      chainName += ` (${network})`
    }

    if (isRequired && (!value || value.trim() === '')) {
      return intl.formatMessage({ ...messages.required_field })
    }
    if (value && !isLn(value, chain, network) && !isOnchain(value, chain, network)) {
      return intl.formatMessage({ ...messages.invalid_request }, { chain: chainName })
    }
  }

  render() {
    const { chain, intl } = this.props

    return (
      <InformedTextArea
        placeholder={intl.formatMessage(
          {
            ...messages.payreq_placeholder,
          },
          { chain }
        )}
        rows={5}
        {...this.props}
        spellCheck="false"
        validate={this.validate}
      />
    )
  }
}

const InformedTextArea = asField(({ fieldState, fieldApi, ...props }) => {
  const { value } = fieldState
  const { chain, network, ...rest } = props

  let chainName = isLn(value, chain, network) ? 'lightning' : chain
  if (network !== 'mainnet') {
    chainName += ` (${network})`
  }
  return (
    <React.Fragment>
      <TextArea {...rest} />
      {value && !fieldState.error && (
        <Message mt={2} variant="success">
          <FormattedMessage
            {...messages.valid_request}
            values={{
              chain: chainName,
            }}
          />
        </Message>
      )}
    </React.Fragment>
  )
})

export default injectIntl(LightningInvoiceInput)
<commit_msg>refactor(ui): export non-as field LightningInvoiceInput version<commit_after>import React from 'react'
import PropTypes from 'prop-types'
import { FormattedMessage, intlShape, injectIntl } from 'react-intl'
import { asField } from 'informed'
import { isOnchain, isLn } from '@zap/utils/crypto'
import { BasicTextArea } from './TextArea'
import Message from './Message'
import messages from './messages'

/**
 * @render react
 * @name LightningInvoiceInput
 * @example
 * <LightningInvoiceInput
     network="testnet"
     field="testnet"
     id="testnet"
     validateOnChange
     validateOnBlur />
 */
class LightningInvoiceInput extends React.Component {
  static displayName = 'LightningInvoiceInput'

  static propTypes = {
    chain: PropTypes.oneOf(['bitcoin', 'litecoin']),
    intl: intlShape.isRequired,
    isRequired: PropTypes.bool,
    network: PropTypes.oneOf(['mainnet', 'testnet', 'regtest']),
  }

  static defaultProps = {
    isRequired: false,
  }

  validate = value => {
    const { intl } = this.props
    const { network, chain, isRequired } = this.props

    let chainName = `${chain}/lightning`
    if (network !== 'mainnet') {
      chainName += ` (${network})`
    }

    if (isRequired && (!value || value.trim() === '')) {
      return intl.formatMessage({ ...messages.required_field })
    }
    if (value && !isLn(value, chain, network) && !isOnchain(value, chain, network)) {
      return intl.formatMessage({ ...messages.invalid_request }, { chain: chainName })
    }
  }

  render() {
    const { chain, intl } = this.props

    return (
      <InformedTextArea
        placeholder={intl.formatMessage(
          {
            ...messages.payreq_placeholder,
          },
          { chain }
        )}
        rows={5}
        {...this.props}
        spellCheck="false"
        validate={this.validate}
      />
    )
  }
}

const InformedTextArea = asField(({ fieldState, fieldApi, ...props }) => {
  const { value } = fieldState
  const { chain, network, ...rest } = props

  let chainName = isLn(value, chain, network) ? 'lightning' : chain
  if (network !== 'mainnet') {
    chainName += ` (${network})`
  }
  return (
    <React.Fragment>
      <BasicTextArea {...rest} fieldApi={fieldApi} fieldState={fieldState} />
      {value && !fieldState.error && (
        <Message mt={2} variant="success">
          <FormattedMessage
            {...messages.valid_request}
            values={{
              chain: chainName,
            }}
          />
        </Message>
      )}
    </React.Fragment>
  )
})

export default injectIntl(LightningInvoiceInput)
<|endoftext|>


<commit_before>// Raw
// -------
var _ = require('lodash');
var inherits = require('inherits');
var EventEmitter = require('events').EventEmitter;

function Raw(sql, bindings) {
  if (sql && sql.toSQL) {
    var output = sql.toSQL();
    sql = output.sql;
    bindings = output.bindings;
  }
  this.sql = sql;
  this.bindings = _.isArray(bindings) ? bindings :
    bindings ? [bindings] : [];
  this._debug = void 0;
  this._transacting = void 0;
}
inherits(Raw, EventEmitter);

// Wraps the current sql with `before` and `after`.
Raw.prototype.wrap = function(before, after) {
  this.sql = before + this.sql + after;
  return this;
};

// Calls `toString` on the Knex object.
Raw.prototype.toString = function() {
  return this.toQuery();
};

// Returns the raw sql for the query.
Raw.prototype.toSQL = function() {
  return {
    sql: this.sql,
    method: 'raw',
    bindings: this.bindings
  };
};

// Allow the `Raw` object to be utilized with full access to the relevant
// promise API.
require('./interface')(Raw);

module.exports = Raw;<commit_msg>Allow nested Raw queries<commit_after>// Raw
// -------
var _ = require('lodash');
var inherits = require('inherits');
var EventEmitter = require('events').EventEmitter;

function Raw(sql, bindings) {
  if (sql && sql.toSQL) {
    var output = sql.toSQL();
    sql = output.sql;
    bindings = output.bindings;
  }
  this.sql = sql;
  this.bindings = _.isArray(bindings) ? bindings :
    bindings ? [bindings] : [];

  var replacements = [];
  this.bindings = _.reduce(this.bindings, function(accum, param, index) {
    var innerBindings = [param];
    if (param instanceof Raw) {
      var result = this.splicer(param, index);
      innerBindings = result.bindings;
      replacements.push(result.replacer);
    }
    return accum.concat(innerBindings);
  }.bind(this), []);

  // we don't need to care about replacements adding more '?'s
  // and disrupting the indices, because we split first, join later
  this.sql = _.reduce(replacements, function(accum, fn) {
    return fn(accum);
  }, this.sql.split('?')).join('?');

  this._debug = void 0;
  this._transacting = void 0;
}
inherits(Raw, EventEmitter);

// Wraps the current sql with `before` and `after`.
Raw.prototype.wrap = function(before, after) {
  this.sql = before + this.sql + after;
  return this;
};

// Calls `toString` on the Knex object.
Raw.prototype.toString = function() {
  return this.toQuery();
};

// Returns a replacer function that splices into the i'th
// ? in the sql string the inner raw's sql,
// and the bindings associated with it
Raw.prototype.splicer = function(raw, i) {
  var obj = raw.toSQL();

  // the replacer function assumes that the sql has been
  // already sql.split('?') and will be arr.join('?')
  var replacer = function(arr) {
    arr[i] = arr[i] + obj.sql + arr[i+1];
    arr.splice(i+1,1);
    return arr;
  };

  return {
    replacer: replacer,
    bindings: obj.bindings
  };
};

// Returns the raw sql for the query.
Raw.prototype.toSQL = function() {
  return {
    sql: this.sql,
    method: 'raw',
    bindings: this.bindings
  };
};

// Allow the `Raw` object to be utilized with full access to the relevant
// promise API.
require('./interface')(Raw);

module.exports = Raw;<|endoftext|>