<commit_before>const util = require('util')
const unixtimeFromDate = require('../lib/unixtime-from-date')
const sha256 = require('../lib/hash').sha256
const Badges = require('../models/badge')
const ClaimCodes = require('../models/claim-codes')
const Webhooks = require('../models/webhook')
const BadgeInstances = require('../models/badge-instance')
const errorHelper = require('../lib/error-helper')
const middleware = require('../lib/middleware')
const log = require('../lib/logger')

const findSystemBadge = [
  middleware.findSystem(),
  middleware.findBadge({
    relationships: true,
    where: {systemId: ['system', 'id']},
  }),
]
const findIssuerBadge = [
  middleware.findSystem(),
  middleware.findIssuer({where: {systemId: ['system', 'id']}}),
  middleware.findBadge({
    relationships: true,
    where: {
      systemId: ['system', 'id'],
      issuerId: ['issuer', 'id'],
    },
  }),
]
const findProgramBadge = [
  middleware.findSystem(),
  middleware.findIssuer({where: {systemId: ['system', 'id']}}),
  middleware.findProgram({where: {issuerId: ['issuer', 'id']}}),
  middleware.findBadge({
    relationships: true,
    where: {
      systemId: ['system', 'id'],
      issuerId: ['issuer', 'id'],
      programId: ['program', 'id'],
    },
  }),
]

const prefix = {
  system: '/systems/:systemSlug',
  issuer: '/systems/:systemSlug/issuers/:issuerSlug',
  program: '/systems/:systemSlug/issuers/:issuerSlug/programs/:programSlug',
}
const publicPrefix = {
  system: '/public/' + prefix.system,
  issuer: '/public/' + prefix.issuer,
  program: '/public/' + prefix.program,
}

exports = module.exports = function applyBadgeRoutes (server) {
  const createNewInstanceSuffix = '/badges/:badgeSlug/instances'
  server.post(prefix.system + createNewInstanceSuffix,
              findSystemBadge, createNewInstance)

  server.post(prefix.issuer + createNewInstanceSuffix,
              findIssuerBadge, createNewInstance)

  server.post(prefix.program + createNewInstanceSuffix,
              findProgramBadge, createNewInstance)

  function createNewInstance(req, res, next) {
    const row = BadgeInstances.formatUserInput(req.body)
    row.badgeId = req.badge.id

    const errs = BadgeInstances.validateRow(row)
    if (errs.length)
      return res.send(400, errorHelper.validation(errs));

    if (!row.claimCode)
      return saveBadgeInstance()

    const query = {code: row.claimCode, badgeId: row.badgeId}
    ClaimCodes.getOne(query, function (err, code) {
      if (err) {
        log.error(err, 'error trying to find claim code')
        return next(err)
      }

      if (code.claimed && !code.multiuse) {
        return res.send(400, {
          code: 'CodeAlreadyUsed',
          message: 'Claim code `'+code.code+'` has already been claimed'
        })
      }

      code.claimed = true
      code.email = row.email

      ClaimCodes.put(code, function (err, result) {
        if (err) {
          log.error(err, 'error trying to find claim code')
          return next(err)
        }
        return saveBadgeInstance()
      })
    })

    function saveBadgeInstance() {
      BadgeInstances.put(row, function (err, result) {
        if (err) {
          log.error(err, 'error trying to save badge instance')
          return next(err)
        }
        const instance = result.row
        const relativeAssertionUrl = '/public/assertions/' + instance.slug
        const assertionUrl = req.resolvePath(relativeAssertionUrl)


        res.header('Location', relativeAssertionUrl)
        res.send(201, {
          status: 'created',
          location: assertionUrl,
        })

        // Webhook stuff shouldn't hold up the request, so we call
        // `next()` before looking up any hooks we have to send off
        next()

        const system = req.system
        const hookData = {
          action: 'award',
          uid: instance.slug,
          email: instance.email,
          assertionUrl: assertionUrl,
          issuedOn: unixtimeFromDate(instance.issuedOn),
        }
        Webhooks.getOne({systemId: system.id}, function (err, hook) {
          if (err)
            return log.error(err, 'Could not retrieve webhook')

          if (!hook)
            return log.info({code: 'WebhookNotFound', system: system}, 'Webhook not found for system')

          hook.call(hookData, function (err, res, body) {
            if (res.statusCode != 200)
              return log.warn({code: 'WebhookBadResponse', status: res.statusCode, body: body})
          })
        })
      })
    }
  }

  server.get('/public/assertions/:instanceSlug', getAssertion)
  function getAssertion(req, res, next) {
    const instanceSlug = req.params.instanceSlug
    const query = {slug: instanceSlug}
    const options = {relationships: true}
    BadgeInstances.getOne(query, options, function (err, instance) {
      if (!instance)
        return next(errorHelper.notFound('Could not find badge instance'))<commit_msg>Use some promises in badgekit-instance.js<commit_after>const Promise = require('bluebird')
const util = require('util')
const unixtimeFromDate = require('../lib/unixtime-from-date')
const sha256 = require('../lib/hash').sha256
const Badges = require('../models/badge')
const ClaimCodes = require('../models/claim-codes')
const Webhooks = require('../models/webhook')
const BadgeInstances = require('../models/badge-instance')
const errorHelper = require('../lib/error-helper')
const middleware = require('../lib/middleware')
const log = require('../lib/logger')

const findSystemBadge = [
  middleware.findSystem(),
  middleware.findBadge({
    relationships: true,
    where: {systemId: ['system', 'id']},
  }),
]
const findIssuerBadge = [
  middleware.findSystem(),
  middleware.findIssuer({where: {systemId: ['system', 'id']}}),
  middleware.findBadge({
    relationships: true,
    where: {
      systemId: ['system', 'id'],
      issuerId: ['issuer', 'id'],
    },
  }),
]
const findProgramBadge = [
  middleware.findSystem(),
  middleware.findIssuer({where: {systemId: ['system', 'id']}}),
  middleware.findProgram({where: {issuerId: ['issuer', 'id']}}),
  middleware.findBadge({
    relationships: true,
    where: {
      systemId: ['system', 'id'],
      issuerId: ['issuer', 'id'],
      programId: ['program', 'id'],
    },
  }),
]

const prefix = {
  system: '/systems/:systemSlug',
  issuer: '/systems/:systemSlug/issuers/:issuerSlug',
  program: '/systems/:systemSlug/issuers/:issuerSlug/programs/:programSlug',
}
const publicPrefix = {
  system: '/public/' + prefix.system,
  issuer: '/public/' + prefix.issuer,
  program: '/public/' + prefix.program,
}

exports = module.exports = function applyBadgeRoutes (server) {
  const createNewInstanceSuffix = '/badges/:badgeSlug/instances'
  server.post(prefix.system + createNewInstanceSuffix,
              findSystemBadge, createNewInstance)

  server.post(prefix.issuer + createNewInstanceSuffix,
              findIssuerBadge, createNewInstance)

  server.post(prefix.program + createNewInstanceSuffix,
              findProgramBadge, createNewInstance)

  function createNewInstance(req, res, next) {
    const row = BadgeInstances.formatUserInput(req.body)
    row.badgeId = req.badge.id

    const errs = BadgeInstances.validateRow(row)
    if (errs.length)
      return res.send(400, errorHelper.validation(errs));

    if (!row.claimCode)
      return saveBadgeInstance()

    function errorHandler(err) {
      log.error(err, 'error interacting with database in route for creating a new badge instance')
      return next(err)
    }

    const query = {
      code: row.claimCode,
      badgeId: row.badgeId
    }

    ClaimCodes.getOne(query).then(function (code) {
      if (code.claimed && !code.multiuse) {
        const response = {
          code: 'CodeAlreadyUsed',
          message: 'Claim code `'+code.code+'` has already been claimed'
        }
        res.send(400, response)
        return Promise.reject(response)
      }
      code.claimed = true
      code.email = row.email
      return ClaimCodes.put(code)
    }).then(saveBadgeInstance)
      .error(function (err) {
        if (err.code !== 'CodeAlreadyUsed')
          return errorHandler(err)
      })

    function saveBadgeInstance(err) {
      var hookData, system
      BadgeInstances.put(row).then(function (result) {
        const instance = result.row
        const relativeAssertionUrl = '/public/assertions/' + instance.slug
        const assertionUrl = req.resolvePath(relativeAssertionUrl)


        res.header('Location', relativeAssertionUrl)
        res.send(201, {
          status: 'created',
          location: assertionUrl,
        })

        // Webhook stuff shouldn't hold up the request, so we call
        // `next()` before looking up any hooks we have to send off
        next()

        const system = req.system
        hookData = {
          action: 'award',
          uid: instance.slug,
          email: instance.email,
          assertionUrl: assertionUrl,
          issuedOn: unixtimeFromDate(instance.issuedOn),
        }
        return Webhooks.getOne({systemId: system.id})
      }).then(function (hook) {
        if (!hook)
          return log.info({code: 'WebhookNotFound', system: system}, 'Webhook not found for system')

        hook.call(hookData, function (err, res, body) {
          if (err)
            return log.warn({code: 'WebhookRequestError', error: err})
          if (res.statusCode != 200)
            return log.warn({code: 'WebhookBadResponse', status: res.statusCode, body: body})
        })
      }).error(function (err) {
        log.error(err, 'error dealing with webhooks when awarding badge')
      })
    }
  }

  server.get('/public/assertions/:instanceSlug', getAssertion)
  function getAssertion(req, res, next) {
    const instanceSlug = req.params.instanceSlug
    const query = {slug: instanceSlug}
    const options = {relationships: true}
    BadgeInstances.getOne(query, options, function (err, instance) {
      if (!instance)
        return next(errorHelper.notFound('Could not find badge instance'))
{'fraction_non_alphanumeric': 0.13555953090836811, 'fraction_numerical': 0.0035778175313059034, 'mean_word_length': 2.918613707165109, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4984766', 'n_tokens_mistral': 3085, 'n_tokens_neox': 3025, 'n_words': 683}