<commit_before>module.exports = function(mongo) {
  if(!mongo) {
    throw 'Missing mongo';
  }

  var url = 'http://' + (process.env.NODE_ENV === 'production' ? 'kpjs.azurewebsites.net' : 'localhost:1337');
  var passport = require('passport');
  var GoogleStrategy = require('passport-google-oauth').OAuth2Strategy;
  var GithubStrategy = require('passport-github').Strategy;
  var TwitterStrategy = require('passport-twitter').Strategy;
  var FacebookStrategy = require('passport-facebook').Strategy;

  passport.use(new GoogleStrategy({
      clientID: process.env.GOOGLE_CLIENT_ID,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET,
      callbackURL: url + '/login/google/callback',
      state: true
    },
    authCallback(function(p) { return p.photos[0].value; })
  ));

  passport.use(new GithubStrategy({
      clientID: process.env.GITHUB_CLIENT_ID,
      clientSecret: process.env.GITHUB_CLIENT_SECRET,
      callbackURL: url + '/login/github/callback',
      state: true
    },
    //jscs:disable requireCamelCaseOrUpperCaseIdentifiers
    authCallback(function(p) { return p._json.avatar_url; })
    //jscs:enable requireCamelCaseOrUpperCaseIdentifiers
  ));

  passport.use(new TwitterStrategy({
      consumerKey: process.env.TWITTER_CLIENT_ID,
      consumerSecret: process.env.TWITTER_CLIENT_SECRET,
      callbackURL: url + '/login/twitter/callback',
      state: true
    },
    authCallback(function(p) { return p.photos[0].value; })
  ));

  passport.use(new FacebookStrategy({
      clientID: process.env.FACEBOOK_CLIENT_ID,
      clientSecret: process.env.FACEBOOK_CLIENT_SECRET,
      callbackURL: url + '/login/facebook/callback',
      profileFields: [ 'displayName', 'photos' ],
      state: true
    },
    authCallback(function(p) { return p.photos[0].value; })
  ));

  passport.serializeUser(function(user, done) {
    done(null, user);
  });

  passport.deserializeUser(function(obj, done) {
    done(null, obj);
  });

  return {
    setup: setup,
<<<<<<< HEAD
    ensureAuthenticated: ensureAuthenticated,
    ensureOwner: ensureOwner
||||||| merged common ancestors
    ensureAuthenticated: ensureAuthenticated
=======
    ensureZombie: ensureRoleReguestHandlerWrapper(0),
    ensureCitizen: ensureRoleReguestHandlerWrapper(1),
    ensureRuler: ensureRoleReguestHandlerWrapper(2)
>>>>>>> master
  };

  function authCallback(avatarCallback){
    return function(token, tokenSecret, profile, done) {
      mongo.collection('users').findAndModify({ provider: profile.provider, providerId: profile.id }, [], { $setOnInsert: { name: profile.displayName, role: 0 } }, { new: true, upsert: true },
        function(err, item){
          if(err){ return done(err); }
          var avatarUrl;
          try { avatarUrl = avatarCallback(profile); } catch(e) {}
          return done(null, { id: item.value._id, name: item.value.name, avatarUrl: avatarUrl });
        });
    };
  }

  function setup(expressApp){
    if(!expressApp)
    {
      throw 'Missing express app';
    }
    expressApp.use(passport.initialize());
    expressApp.use(passport.session());
    expressApp.get('/login/google', passport.authenticate('google', { scope: 'profile' }));
    expressApp.get('/login/github', passport.authenticate('github'));
    expressApp.get('/login/twitter', passport.authenticate('twitter'));
    expressApp.get('/login/facebook', passport.authenticate('facebook'));
    expressApp.get('/login/google/callback',
      passport.authenticate('google', { failureRedirect: '/loginFail', successRedirect: '/' })
    );
    expressApp.get('/login/github/callback',
      passport.authenticate('github', { failureRedirect: '/loginFail', successRedirect: '/' })
    );
    expressApp.get('/login/twitter/callback',
      passport.authenticate('twitter', { failureRedirect: '/loginFail', successRedirect: '/' })
    );
    expressApp.get('/login/facebook/callback',
      passport.authenticate('facebook', { failureRedirect: '/loginFail', successRedirect: '/' })
    );
    expressApp.get('/logout', function(req, res){
      req.logout();
      req.session.regenerate(function(){
         res.redirect('/');
       });
     });
     expressApp.get('/loginFail', function(req, res){ res.end('login failed'); });
  }

  function verifyRole(userId, role, callback){
    var ObjectID = require('mongodb').ObjectID;
    mongo.collection('users').findOne({ _id: new ObjectID(userId) }, { role: 1 }, function(err, item){
      if(err){
        return callback(err);
      }
      if(item.role >= role){
        callback(null, true);
      }
      else{
        callback(null, false);
      }
    });
  }

  function ensureRoleReguestHandlerWrapper(role){
    return function(req, res, next){
      if(!req.isAuthenticated()){
        return notLoggedIn(next);
      }
      verifyRole(req.user.id, role, function(err, hasRole){
        if(err){
          return next(err);
        }
        if(hasRole){
          next();
        }
        else{
          var error = new Error("Not authorized");
          error.statusCode = 403;
          next(error);
        }
      });
    };
  }

  function ensureOwner(req, res, next){
    if(!req.isAuthenticated()){
      return notLoggedIn(next);
    }
    var ObjectID = require('mongodb').ObjectID;
    mongo.collection('posts').count({ users_id: new ObjectID(req.user.id), uri: req.params.uri }, function(err, count){
      if(count > 0)
        return next();
      return notLoggedIn(next);
    });
  }

  function notLoggedIn(next){
    var error = new Error("Not logged in");
    error.statusCode = 401;
    return next(error);
  }
};
<commit_msg>fixed wrong merge<commit_after>module.exports = function(mongo) {
  if(!mongo) {
    throw 'Missing mongo';
  }

  var url = 'http://' + (process.env.NODE_ENV === 'production' ? 'kpjs.azurewebsites.net' : 'localhost:1337');
  var passport = require('passport');
  var GoogleStrategy = require('passport-google-oauth').OAuth2Strategy;
  var GithubStrategy = require('passport-github').Strategy;
  var TwitterStrategy = require('passport-twitter').Strategy;
  var FacebookStrategy = require('passport-facebook').Strategy;

  passport.use(new GoogleStrategy({
      clientID: process.env.GOOGLE_CLIENT_ID,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET,
      callbackURL: url + '/login/google/callback',
      state: true
    },
    authCallback(function(p) { return p.photos[0].value; })
  ));

  passport.use(new GithubStrategy({
      clientID: process.env.GITHUB_CLIENT_ID,
      clientSecret: process.env.GITHUB_CLIENT_SECRET,
      callbackURL: url + '/login/github/callback',
      state: true
    },
    //jscs:disable requireCamelCaseOrUpperCaseIdentifiers
    authCallback(function(p) { return p._json.avatar_url; })
    //jscs:enable requireCamelCaseOrUpperCaseIdentifiers
  ));

  passport.use(new TwitterStrategy({
      consumerKey: process.env.TWITTER_CLIENT_ID,
      consumerSecret: process.env.TWITTER_CLIENT_SECRET,
      callbackURL: url + '/login/twitter/callback',
      state: true
    },
    authCallback(function(p) { return p.photos[0].value; })
  ));

  passport.use(new FacebookStrategy({
      clientID: process.env.FACEBOOK_CLIENT_ID,
      clientSecret: process.env.FACEBOOK_CLIENT_SECRET,
      callbackURL: url + '/login/facebook/callback',
      profileFields: [ 'displayName', 'photos' ],
      state: true
    },
    authCallback(function(p) { return p.photos[0].value; })
  ));

  passport.serializeUser(function(user, done) {
    done(null, user);
  });

  passport.deserializeUser(function(obj, done) {
    done(null, obj);
  });

  return {
    setup: setup,
    ensureOwner: ensureOwner,
    ensureZombie: ensureRoleReguestHandlerWrapper(0),
    ensureCitizen: ensureRoleReguestHandlerWrapper(1),
    ensureRuler: ensureRoleReguestHandlerWrapper(2)
  };

  function authCallback(avatarCallback){
    return function(token, tokenSecret, profile, done) {
      mongo.collection('users').findAndModify({ provider: profile.provider, providerId: profile.id }, [], { $setOnInsert: { name: profile.displayName, role: 0 } }, { new: true, upsert: true },
        function(err, item){
          if(err){ return done(err); }
          var avatarUrl;
          try { avatarUrl = avatarCallback(profile); } catch(e) {}
          return done(null, { id: item.value._id, name: item.value.name, avatarUrl: avatarUrl });
        });
    };
  }

  function setup(expressApp){
    if(!expressApp)
    {
      throw 'Missing express app';
    }
    expressApp.use(passport.initialize());
    expressApp.use(passport.session());
    expressApp.get('/login/google', passport.authenticate('google', { scope: 'profile' }));
    expressApp.get('/login/github', passport.authenticate('github'));
    expressApp.get('/login/twitter', passport.authenticate('twitter'));
    expressApp.get('/login/facebook', passport.authenticate('facebook'));
    expressApp.get('/login/google/callback',
      passport.authenticate('google', { failureRedirect: '/loginFail', successRedirect: '/' })
    );
    expressApp.get('/login/github/callback',
      passport.authenticate('github', { failureRedirect: '/loginFail', successRedirect: '/' })
    );
    expressApp.get('/login/twitter/callback',
      passport.authenticate('twitter', { failureRedirect: '/loginFail', successRedirect: '/' })
    );
    expressApp.get('/login/facebook/callback',
      passport.authenticate('facebook', { failureRedirect: '/loginFail', successRedirect: '/' })
    );
    expressApp.get('/logout', function(req, res){
      req.logout();
      req.session.regenerate(function(){
         res.redirect('/');
       });
     });
     expressApp.get('/loginFail', function(req, res){ res.end('login failed'); });
  }

  function verifyRole(userId, role, callback){
    var ObjectID = require('mongodb').ObjectID;
    mongo.collection('users').findOne({ _id: new ObjectID(userId) }, { role: 1 }, function(err, item){
      if(err){
        return callback(err);
      }
      if(item.role >= role){
        callback(null, true);
      }
      else{
        callback(null, false);
      }
    });
  }

  function ensureRoleReguestHandlerWrapper(role){
    return function(req, res, next){
      if(!req.isAuthenticated()){
        return notLoggedIn(next);
      }
      verifyRole(req.user.id, role, function(err, hasRole){
        if(err){
          return next(err);
        }
        if(hasRole){
          next();
        }
        else{
          var error = new Error("Not authorized");
          error.statusCode = 403;
          next(error);
        }
      });
    };
  }

  function ensureOwner(req, res, next){
    if(!req.isAuthenticated()){
      return notLoggedIn(next);
    }
    var ObjectID = require('mongodb').ObjectID;
    mongo.collection('posts').count({ users_id: new ObjectID(req.user.id), uri: req.params.uri }, function(err, count){
      if(count > 0)
        return next();
      return notLoggedIn(next);
    });
  }

  function notLoggedIn(next){
    var error = new Error("Not logged in");
    error.statusCode = 401;
    return next(error);
  }
};
<|endoftext|>


<commit_before>const webglCanvas = document.body.appendChild(document.createElement('canvas'))
const fit = require('canvas-fit')
const regl = require('../regl')(webglCanvas)
const mat4 = require('gl-mat4')
const camera = require('canvas-orbit-camera')(webglCanvas)
window.addEventListener('resize', fit(webglCanvas), false)
const bunny = require('bunny')
const normals = require('angle-normals')

// configure intial camera view.
camera.rotate([0.0, 0.0], [0.0, -0.4])
camera.zoom(300.0)

function createStatsWidget () {
  var container = document.createElement('div')
  container.style.cssText = 'position:fixed;top:0;left:0;opacity:0.8;z-index:10000;'
  var pr = Math.round(window.devicePixelRatio || 1)

  // TODO: all the text wont fit if we try to send too many drawCalls to `update`
  // we need to dynamically compute the height from the number of drawCalls.
  var WIDTH = 160
  var HEIGHT = 200
  var HEADER_SIZE = 20
  var TEXT_SIZE = 10
  var TEXT_START = [7, 44]
  var HEADER_POS = [3, 3]
  var BG = '#000'
  var FG = '#bbb'

  var canvas = document.createElement('canvas')
  canvas.width = WIDTH * pr
  canvas.height = HEIGHT * pr
  canvas.style.cssText = 'width:' + WIDTH + 'px;height:' + HEIGHT + 'px'

  var context = canvas.getContext('2d')

  // make background.
  context.fillStyle = BG
  context.fillRect(0, 0, WIDTH * pr, HEIGHT * pr)

  context.font = 'bold ' + (HEADER_SIZE * pr) + 'px Helvetica,Arial,sans-serif'
  context.textBaseline = 'top'
  context.fillStyle = FG
  context.fillText('Stats', HEADER_POS[0] * pr, HEADER_POS[1] * pr)

  container.appendChild(canvas)
  document.body.appendChild(container)

  var totalTime = 2.0 // first time `update` is called we always update.

  return {
    update: function (drawCalls, deltaTime) {
      totalTime += deltaTime

      if (totalTime > 1.0) {
        totalTime = 0

        context.fillStyle = BG
        context.fillRect(
          TEXT_START[0] * pr,
          TEXT_START[1] * pr,
          (WIDTH - TEXT_START[0]) * pr,
          (HEIGHT - TEXT_START[1]) * pr)

        context.font = 'bold ' + (TEXT_SIZE * pr) + 'px Helvetica,Arial,sans-serif'
        context.fillStyle = FG

        var drawCall
        var str
        var textCursor = [TEXT_START[0], TEXT_START[1]]
        for (var i = 0; i < drawCalls.length; i++) {
          drawCall = drawCalls[i]
          str = drawCall[1] + ' : ' + Math.round(100.0 * drawCall[0].stats.gpuTime) / 100.0 + 'ms'

          context.fillText(str, textCursor[0] * pr, textCursor[1] * pr)
          textCursor[1] += TEXT_SIZE
        }
      }
    }
  }
}

var statsWidget = createStatsWidget()

const planeElements = []
var planePosition = []
var planeNormal = []

planePosition.push([-0.5, 0.0, -0.5])
planePosition.push([+0.5, 0.0, -0.5])
planePosition.push([-0.5, 0.0, +0.5])
planePosition.push([+0.5, 0.0, +0.5])

planeNormal.push([0.0, 1.0, 0.0])
planeNormal.push([0.0, 1.0, 0.0])
planeNormal.push([0.0, 1.0, 0.0])
planeNormal.push([0.0, 1.0, 0.0])

planeElements.push([3, 1, 0])
planeElements.push([0, 2, 3])

// create box geometry

var boxPosition = [
  // side faces
  [-0.5, +0.5, +0.5], [+0.5, +0.5, +0.5], [+0.5, -0.5, +0.5], [-0.5, -0.5, +0.5], // positive z face.
  [+0.5, +0.5, +0.5], [+0.5, +0.5, -0.5], [+0.5, -0.5, -0.5], [+0.5, -0.5, +0.5], // positive x face
  [+0.5, +0.5, -0.5], [-0.5, +0.5, -0.5], [-0.5, -0.5, -0.5], [+0.5, -0.5, -0.5], // negative z face
  [-0.5, +0.5, -0.5], [-0.5, +0.5, +0.5], [-0.5, -0.5, +0.5], [-0.5, -0.5, -0.5], // negative x face.
  [-0.5, +0.5, -0.5], [+0.5, +0.5, -0.5], [+0.5, +0.5, +0.5], [-0.5, +0.5, +0.5],  // top face
  [-0.5, -0.5, -0.5], [+0.5, -0.5, -0.5], [+0.5, -0.5, +0.5], [-0.5, -0.5, +0.5]  // bottom face
]

const boxElements = [
  [2, 1, 0], [2, 0, 3],
  [6, 5, 4], [6, 4, 7],
  [10, 9, 8], [10, 8, 11],
  [14, 13, 12], [14, 12, 15],
  [18, 17, 16], [18, 16, 19],
  [20, 21, 22], [23, 20, 22]
]

// all the normals of a single block.
var boxNormal = [
  // side faces
  [0.0, 0.0, +1.0], [0.0, 0.0, +1.0], [0.0, 0.0, +1.0], [0.0, 0.0, +1.0],
  [+1.0, 0.0, 0.0], [+1.0, 0.0, 0.0], [+1.0, 0.0, 0.0], [+1.0, 0.0, 0.0],
  [0.0, 0.0, -1.0], [0.0, 0.0, -1.0], [0.0, 0.0, -1.0], [0.0, 0.0, -1.0],
  [-1.0, 0.0, 0.0], [-1.0, 0.0, 0.0], [-1.0, 0.0, 0.0], [-1.0, 0.0, 0.0],
  // top
  [0.0, +1.0, 0.0], [0.0, +1.0, 0.0], [0.0, +1.0, 0.0], [0.0, +1.0, 0.0],
  // bottom
  [0.0, -1.0, 0.0], [0.0, -1.0, 0.0], [0.0, -1.0, 0.0], [0.0, -1.0, 0.0]
]

function createModel (position, scale) {
  var m = mat4.identity([])

  mat4.translate(m, m, position)

  var s = scale
  mat4.scale(m, m, [s, s, s])
  return m
}

/*
  This function encapsulates all the common state
  */
const setupDefault = regl({
  cull: {
    enable: true
  },
  uniforms: {
    // View Projection matrices.
    view: () => camera.view(),
    projection: ({viewportWidth, viewportHeight}) =>
      mat4.perspective([],
                       Math.PI / 4,
                       viewportWidth / viewportHeight,
                       0.01,
                       2000),

    // light settings. These can of course by tweaked to your likings.
    lightDir: [0.39, 0.87, 0.29],
    ambientLightAmount: 0.3,
    diffuseLightAmount: 0.7
  },
  frag: `
  precision mediump float;
  varying vec3 vNormal;
  uniform vec3 lightDir;
  uniform float ambientLightAmount;
  uniform float diffuseLightAmount;
  uniform vec3 color;
  void main () {
    vec3 tex = color;
    vec3 ambient = ambientLightAmount * tex;
    vec3 diffuse = diffuseLightAmount * tex * clamp( dot(vNormal, lightDir ), 0.0, 1.0 );
    gl_FragColor = vec4(ambient + diffuse, 1.0);
  }`,
  vert: `
  // the size of the world on the x and z-axes.
  precision mediump float;
  attribute vec3 position;
  attribute vec3 normal;
  varying vec3 vPosition;
  varying vec3 vNormal;
  uniform mat4 projection, view, model;
  void main() {
    vPosition = position;
    vNormal = normal;
    gl_Position = projection * view * model * vec4(position, 1);
  }`
})

const drawPlane = regl({

  uniforms: {
    color: [0.7, 0.7, 0.7],
    model: (_, props, batchId) => {
      return createModel(props.position, props.scale)
    }
  },
  attributes: {
    position: planePosition,
    normal: planeNormal

  },
  elements: planeElements
})

const drawBunny = regl({
  attributes: {
    position: bunny.positions,
    normal: normals(bunny.cells, bunny.positions)
  },
  elements: bunny.cells,
  uniforms: {
    model: (_, props, batchId) => {
      return createModel(props.position, props.scale)
    },
    color: [0.5, 0.0, 0.0]
  }
})

const drawBox = regl({
  attributes: {
    position: boxPosition,
    normal: boxNormal
  },
  elements: boxElements,
  uniforms: {
    model: (_, props, batchId) => {
      return createModel(props.position, props.scale)
    },
    color: [0.0, 0.6, 0.0]
  }
})

regl.frame(() => {
  regl.clear({
    color: [0, 0, 0, 255],
    depth: 1
  })

  const deltaTime = 0.017

  statsWidget.update([
    [drawPlane, 'drawPlane'],
    [drawBunny, 'drawBunny'],
    [drawBox, 'drawBox']], deltaTime)

  setupDefault({}, () => {
    drawPlane({scale: 2000.0, position: [0.0, 0.0, 0.0]})

    var bunnies = []

    var X_COUNT = 5
    var Z_COUNT = 5

    var x
    var z
    var SPACING = 100
    for (x = 0; x < X_COUNT; x++) {
      for (z = 0; z < Z_COUNT; z++) {
        bunnies.push({scale: 5.2, position: [x * SPACING, 3.3, -80.0 + z * SPACING]})
      }
    }
    drawBunny(bunnies)

    var boxes = []

    SPACING = -100
    for (x = 0; x < X_COUNT; x++) {
      for (z = 0; z < Z_COUNT; z++) {
        boxes.push({scale: 50.7, position: [-200.0 + x * SPACING, 40, 200 + z * SPACING]})
      }
    }
    drawBox(boxes)
    camera.tick()
  })
})
<commit_msg>Now the height of the stats widget is computed dynamically.<commit_after>const webglCanvas = document.body.appendChild(document.createElement('canvas'))
const fit = require('canvas-fit')
const regl = require('../regl')(webglCanvas)
const mat4 = require('gl-mat4')
const camera = require('canvas-orbit-camera')(webglCanvas)
window.addEventListener('resize', fit(webglCanvas), false)
const bunny = require('bunny')
const normals = require('angle-normals')

// configure intial camera view.
camera.rotate([0.0, 0.0], [0.0, -0.4])
camera.zoom(300.0)

function createStatsWidget () {
  // the widget is contained in a <div>
  var container = document.createElement('div')
  container.style.cssText = 'position:fixed;top:20px;left:20px;opacity:0.8;z-index:10000;'

  var pr = Math.round(window.devicePixelRatio || 1)

  // widget styling constants.
  var WIDTH = 160
  var HEADER_SIZE = 20
  var TEXT_SIZE = 10
  var TEXT_START = [7, 37]
  var TEXT_SPACING = 6
  var BOTTOM_SPACING = 20
  var HEADER_POS = [3, 3]
  var BG = '#000'
  var FG = '#bbb'

  // we later compute this dynamically from the number of drawCalls.
  var HEIGHT

  // we draw the widget on a canvas.
  var canvas = document.createElement('canvas')
  var context = canvas.getContext('2d')

  var totalTime = 2.0 // first time `update` is called we always update.
  var isInitialized = false

  return {
    update: function (drawCalls, deltaTime) {
      if (!isInitialized) {
        isInitialized = true
        // we initialize the widget the first time `update` is called.

        HEIGHT = drawCalls.length * TEXT_SIZE + (drawCalls.length - 1) * TEXT_SPACING + TEXT_START[1] + BOTTOM_SPACING

        canvas.width = WIDTH * pr
        canvas.height = HEIGHT * pr
        canvas.style.cssText = 'width:' + WIDTH + 'px;height:' + HEIGHT + 'px'

        // draw background.
        context.fillStyle = BG
        context.fillRect(0, 0, WIDTH * pr, HEIGHT * pr)

        // draw header.
        context.font = 'bold ' + (HEADER_SIZE * pr) + 'px Helvetica,Arial,sans-serif'
        context.textBaseline = 'top'
        context.fillStyle = FG
        context.fillText('Stats', HEADER_POS[0] * pr, HEADER_POS[1] * pr)

        container.appendChild(canvas)
        document.body.appendChild(container)
      }

      totalTime += deltaTime
      if (totalTime > 1.0) {
        totalTime = 0

        // make sure that we clear the old text before drawing new text.
        context.fillStyle = BG
        context.fillRect(
          TEXT_START[0] * pr,
          TEXT_START[1] * pr,
          (WIDTH - TEXT_START[0]) * pr,
          (HEIGHT - TEXT_START[1]) * pr)

        context.font = 'bold ' + (TEXT_SIZE * pr) + 'px Helvetica,Arial,sans-serif'
        context.fillStyle = FG

        var drawCall
        var str
        var textCursor = [TEXT_START[0], TEXT_START[1]]
        for (var i = 0; i < drawCalls.length; i++) {
          drawCall = drawCalls[i]
          str = drawCall[1] + ' : ' + Math.round(100.0 * drawCall[0].stats.gpuTime) / 100.0 + 'ms'

          context.fillText(str, textCursor[0] * pr, textCursor[1] * pr)
          textCursor[1] += TEXT_SIZE + TEXT_SPACING
        }
      }
    }
  }
}

var statsWidget = createStatsWidget()

const planeElements = []
var planePosition = []
var planeNormal = []

planePosition.push([-0.5, 0.0, -0.5])
planePosition.push([+0.5, 0.0, -0.5])
planePosition.push([-0.5, 0.0, +0.5])
planePosition.push([+0.5, 0.0, +0.5])

planeNormal.push([0.0, 1.0, 0.0])
planeNormal.push([0.0, 1.0, 0.0])
planeNormal.push([0.0, 1.0, 0.0])
planeNormal.push([0.0, 1.0, 0.0])

planeElements.push([3, 1, 0])
planeElements.push([0, 2, 3])

// create box geometry

var boxPosition = [
  // side faces
  [-0.5, +0.5, +0.5], [+0.5, +0.5, +0.5], [+0.5, -0.5, +0.5], [-0.5, -0.5, +0.5], // positive z face.
  [+0.5, +0.5, +0.5], [+0.5, +0.5, -0.5], [+0.5, -0.5, -0.5], [+0.5, -0.5, +0.5], // positive x face
  [+0.5, +0.5, -0.5], [-0.5, +0.5, -0.5], [-0.5, -0.5, -0.5], [+0.5, -0.5, -0.5], // negative z face
  [-0.5, +0.5, -0.5], [-0.5, +0.5, +0.5], [-0.5, -0.5, +0.5], [-0.5, -0.5, -0.5], // negative x face.
  [-0.5, +0.5, -0.5], [+0.5, +0.5, -0.5], [+0.5, +0.5, +0.5], [-0.5, +0.5, +0.5],  // top face
  [-0.5, -0.5, -0.5], [+0.5, -0.5, -0.5], [+0.5, -0.5, +0.5], [-0.5, -0.5, +0.5]  // bottom face
]

const boxElements = [
  [2, 1, 0], [2, 0, 3],
  [6, 5, 4], [6, 4, 7],
  [10, 9, 8], [10, 8, 11],
  [14, 13, 12], [14, 12, 15],
  [18, 17, 16], [18, 16, 19],
  [20, 21, 22], [23, 20, 22]
]

// all the normals of a single block.
var boxNormal = [
  // side faces
  [0.0, 0.0, +1.0], [0.0, 0.0, +1.0], [0.0, 0.0, +1.0], [0.0, 0.0, +1.0],
  [+1.0, 0.0, 0.0], [+1.0, 0.0, 0.0], [+1.0, 0.0, 0.0], [+1.0, 0.0, 0.0],
  [0.0, 0.0, -1.0], [0.0, 0.0, -1.0], [0.0, 0.0, -1.0], [0.0, 0.0, -1.0],
  [-1.0, 0.0, 0.0], [-1.0, 0.0, 0.0], [-1.0, 0.0, 0.0], [-1.0, 0.0, 0.0],
  // top
  [0.0, +1.0, 0.0], [0.0, +1.0, 0.0], [0.0, +1.0, 0.0], [0.0, +1.0, 0.0],
  // bottom
  [0.0, -1.0, 0.0], [0.0, -1.0, 0.0], [0.0, -1.0, 0.0], [0.0, -1.0, 0.0]
]

function createModel (position, scale) {
  var m = mat4.identity([])

  mat4.translate(m, m, position)

  var s = scale
  mat4.scale(m, m, [s, s, s])
  return m
}

/*
  This function encapsulates all the common state
  */
const setupDefault = regl({
  cull: {
    enable: true
  },
  uniforms: {
    // View Projection matrices.
    view: () => camera.view(),
    projection: ({viewportWidth, viewportHeight}) =>
      mat4.perspective([],
                       Math.PI / 4,
                       viewportWidth / viewportHeight,
                       0.01,
                       2000),

    // light settings. These can of course by tweaked to your likings.
    lightDir: [0.39, 0.87, 0.29],
    ambientLightAmount: 0.3,
    diffuseLightAmount: 0.7
  },
  frag: `
  precision mediump float;
  varying vec3 vNormal;
  uniform vec3 lightDir;
  uniform float ambientLightAmount;
  uniform float diffuseLightAmount;
  uniform vec3 color;
  void main () {
    vec3 tex = color;
    vec3 ambient = ambientLightAmount * tex;
    vec3 diffuse = diffuseLightAmount * tex * clamp( dot(vNormal, lightDir ), 0.0, 1.0 );
    gl_FragColor = vec4(ambient + diffuse, 1.0);
  }`,
  vert: `
  // the size of the world on the x and z-axes.
  precision mediump float;
  attribute vec3 position;
  attribute vec3 normal;
  varying vec3 vPosition;
  varying vec3 vNormal;
  uniform mat4 projection, view, model;
  void main() {
    vPosition = position;
    vNormal = normal;
    gl_Position = projection * view * model * vec4(position, 1);
  }`
})

const drawPlane = regl({

  uniforms: {
    color: [0.7, 0.7, 0.7],
    model: (_, props, batchId) => {
      return createModel(props.position, props.scale)
    }
  },
  attributes: {
    position: planePosition,
    normal: planeNormal

  },
  elements: planeElements
})

const drawBunny = regl({
  attributes: {
    position: bunny.positions,
    normal: normals(bunny.cells, bunny.positions)
  },
  elements: bunny.cells,
  uniforms: {
    model: (_, props, batchId) => {
      return createModel(props.position, props.scale)
    },
    color: [0.5, 0.0, 0.0]
  }
})

const drawBox = regl({
  attributes: {
    position: boxPosition,
    normal: boxNormal
  },
  elements: boxElements,
  uniforms: {
    model: (_, props, batchId) => {
      return createModel(props.position, props.scale)
    },
    color: [0.0, 0.6, 0.0]
  }
})

regl.frame(() => {
  regl.clear({
    color: [0, 0, 0, 255],
    depth: 1
  })

  const deltaTime = 0.017

  statsWidget.update([
    [drawPlane, 'drawPlane'],
    [drawBunny, 'drawBunny'],
    [drawBox, 'drawBox']], deltaTime)

  setupDefault({}, () => {
    drawPlane({scale: 2000.0, position: [0.0, 0.0, 0.0]})

    var bunnies = []

    var X_COUNT = 5
    var Z_COUNT = 5

    var x
    var z
    var SPACING = 100
    for (x = 0; x < X_COUNT; x++) {
      for (z = 0; z < Z_COUNT; z++) {
        bunnies.push({scale: 5.2, position: [x * SPACING, 3.3, -80.0 + z * SPACING]})
      }
    }
    drawBunny(bunnies)

    var boxes = []

    SPACING = -100
    for (x = 0; x < X_COUNT; x++) {
      for (z = 0; z < Z_COUNT; z++) {
        boxes.push({scale: 50.7, position: [-200.0 + x * SPACING, 40, 200 + z * SPACING]})
      }
    }
    drawBox(boxes)
    camera.tick()
  })
})
<|endoftext|>


<commit_before>test
<commit_msg>Delete test.js<commit_after><|endoftext|>


<commit_before>describe("Template Tag", function () {

    it("has text sibling，mix inner text node", function (done) {
        var MyComponent = san.defineComponent({
            template: 'test<template>{{name}}
ppp
{{name}}</template>aaaa'
        });

        var myComponent = new MyComponent({
            data: {
                name: 'HelloSan'
            }
        });

        var wrap = document.createElement('div');
        document.body.appendChild(wrap);
        myComponent.attach(wrap);

        var a = wrap.getElementsByTagName('a')[0];

        var html = a.innerHTML.toLowerCase();
        expect(html).toContain('test');
        expect(html).toContain('aaaa');

        expect(/<\/p>\s*hellosan/i.test(html)).toBeTruthy();
        expect(/hellosan\s*<p/i.test(html)).toBeTruthy();
        myComponent.data.set('name', 'ByeER');

        san.nextTick(function () {

            var html = a.innerHTML.toLowerCase();
            expect(/<\/p>\s*byeer/i.test(html)).toBeTruthy();
            expect(/byeer\s*<p/i.test(html)).toBeTruthy();
            expect(html).toContain('test');
            expect(html).toContain('aaaa');

            myComponent.dispose();
            document.body.removeChild(wrap);
            done();
        });
    });

    it("has text sibling，mix inner text node, init with empty string", function (done) {
        var MyComponent = san.defineComponent({
            template: 'test<template>{{name}}
ppp
{{name}}</template>aaaa'
        });

        var myComponent = new MyComponent({
            data: {
                name: ''
            }
        });

        var wrap = document.createElement('div');
        document.body.appendChild(wrap);
        myComponent.attach(wrap);

        var a = wrap.getElementsByTagName('a')[0];

        expect(a.innerHTML).toContain('test');
        expect(a.innerHTML).toContain('aaaa');
        myComponent.data.set('name', 'ByeER');

        san.nextTick(function () {
            var html = a.innerHTML.toLowerCase();
            expect(/<\/p>\s*byeer/i.test(html)).toBeTruthy();
            expect(/byeer\s*<p/i.test(html)).toBeTruthy();

            expect(html).toContain('test');
            expect(html).toContain('aaaa');

            myComponent.dispose();
            document.body.removeChild(wrap);
            done();
        });
    });
});
<commit_msg>#343 spec<commit_after>describe("Template Tag", function () {

    it("has text sibling，mix inner text node", function (done) {
        var MyComponent = san.defineComponent({
            template: 'test<template>{{name}}
ppp
{{name}}</template>aaaa'
        });

        var myComponent = new MyComponent({
            data: {
                name: 'HelloSan'
            }
        });

        var wrap = document.createElement('div');
        document.body.appendChild(wrap);
        myComponent.attach(wrap);

        var a = wrap.getElementsByTagName('a')[0];

        var html = a.innerHTML.toLowerCase();
        expect(html).toContain('test');
        expect(html).toContain('aaaa');

        expect(/<\/p>\s*hellosan/i.test(html)).toBeTruthy();
        expect(/hellosan\s*<p/i.test(html)).toBeTruthy();
        myComponent.data.set('name', 'ByeER');

        san.nextTick(function () {

            var html = a.innerHTML.toLowerCase();
            expect(/<\/p>\s*byeer/i.test(html)).toBeTruthy();
            expect(/byeer\s*<p/i.test(html)).toBeTruthy();
            expect(html).toContain('test');
            expect(html).toContain('aaaa');

            myComponent.dispose();
            document.body.removeChild(wrap);
            done();
        });
    });

    it("has text sibling，mix inner text node, init with empty string", function (done) {
        var MyComponent = san.defineComponent({
            template: 'test<template>{{name}}
ppp
{{name}}</template>aaaa'
        });

        var myComponent = new MyComponent({
            data: {
                name: ''
            }
        });

        var wrap = document.createElement('div');
        document.body.appendChild(wrap);
        myComponent.attach(wrap);

        var a = wrap.getElementsByTagName('a')[0];

        expect(a.innerHTML).toContain('test');
        expect(a.innerHTML).toContain('aaaa');
        myComponent.data.set('name', 'ByeER');

        san.nextTick(function () {
            var html = a.innerHTML.toLowerCase();
            expect(/<\/p>\s*byeer/i.test(html)).toBeTruthy();
            expect(/byeer\s*<p/i.test(html)).toBeTruthy();

            expect(html).toContain('test');
            expect(html).toContain('aaaa');

            myComponent.dispose();
            document.body.removeChild(wrap);
            done();
        });
    });

    it("with if", function (done) {
        var MyComponent = san.defineComponent({
            template: '
Hello {{name}}!<template s-if="num">11111</template> <template s-else>22222</template>
'
        });

        var myComponent = new MyComponent();

        var wrap = document.createElement('div');
        document.body.appendChild(wrap);
        myComponent.attach(wrap);

        expect(wrap.innerHTML).toContain('22222');
        expect(wrap.innerHTML).not.toContain('11111');
        myComponent.data.set('num', 100);

        san.nextTick(function () {
            expect(wrap.innerHTML).not.toContain('22222');
            expect(wrap.innerHTML).toContain('11111');

            myComponent.data.set('num', 0);

            san.nextTick(function () {
                expect(wrap.innerHTML).toContain('22222');
                expect(wrap.innerHTML).not.toContain('11111');

                myComponent.dispose();
                document.body.removeChild(wrap);
                done();
            })
        });
    });
});
<|endoftext|>


<commit_before>const jwt = require('jsonwebtoken');
const api = require('../api');
const permissionsHelper = require('./permissions');

const rolesDisplayName = {
	teacher: 'Lehrer',
	student: 'Schüler',
	administrator: 'Administrator',
	superhero: 'Schul-Cloud Admin',
	demo: 'Demo',
	demoTeacher: 'Demo',
	demoStudent: 'Demo',
	helpdesk: 'Helpdesk',
	betaTeacher: 'Beta',
	expert: 'Experte',
};

const isJWT = req => (req && req.cookies && req.cookies.jwt);

const cookieDomain = (res) => {
	if (res.locals.domain && process.env.NODE_ENV === 'production') {
		return { domain: res.locals.domain };
	}
	return {};
};

const isAuthenticated = (req) => {
	if (!isJWT(req)) {
		return Promise.resolve(false);
	}

	return api(req).post('/authentication', {
		json: {
			strategy: 'jwt',
			accessToken: req.cookies.jwt,
		},
	}).then(() => true).catch(() => false);
};

const populateCurrentUser = (req, res) => {
	let payload = {};
	if (isJWT(req)) {
		// eslint-disable-next-line prefer-destructuring
		payload = (jwt.decode(req.cookies.jwt, { complete: true }) || {}).payload;
		res.locals.currentPayload = payload;
	}

	// separates users in two groups for AB testing
	function setTestGroup(user) {
		if (process.env.SW_ENABLED) {
			const lChar = user._id.substr(user._id.length - 1);
			const group = parseInt(lChar, 16) % 2 ? 1 : 0;
			user.testGroup = group;
		} else {
			user.testGroup = 0;
		}
	}

	if (payload && payload.userId) {
		return api(req).get(`/users/${payload.userId}`, {
			qs: {
				$populate: ['roles'],
			},
		}).then((data) => {
			res.locals.currentUser = data;
			setTestGroup(res.locals.currentUser);
			res.locals.currentRole = rolesDisplayName[data.roles[0].name];
			res.locals.roleNames = data.roles.map(r => rolesDisplayName[r.name]);
			return api(req).get(`/schools/${res.locals.currentUser.schoolId}`, {
				qs: {
					$populate: ['federalState'],
				},
			}).then((data2) => {
				res.locals.currentSchool = res.locals.currentUser.schoolId;
				res.locals.currentSchoolData = data2;
				res.locals.currentSchoolData.isExpertSchool = data2.purpose === 'expert';
				return data2;
			});
		}).catch((e) => {
			// 401 for invalid jwt, not-found for deleted user
			if (e.statusCode === 401 || e.error.className === 'not-found') {
				res.clearCookie('jwt', cookieDomain(res));
			}
		});
	}

	return Promise.resolve();
};

const checkConsent = (req, res) => {
	if (
		((res.locals.currentUser || {}).preferences || {}).firstLogin	// do not exist if 3. system login
		|| req.path.startsWith('/login/success')
		|| req.baseUrl.startsWith('/firstLogin')) {
		return Promise.resolve();
	}
	// eslint-disable-next-line prefer-promise-reject-errors
	return Promise.reject('firstLogin was not completed, redirecting...');
};

const restrictSidebar = (req, res) => {
	res.locals.sidebarItems = res.locals.sidebarItems.filter((item) => {
		if (!item.permission) return true;

		const hasRequiredPermission = permissionsHelper.userHasPermission(res.locals.currentUser, item.permission);
		const hasExcludedPermission = permissionsHelper.userHasPermission(res.locals.currentUser,
			item.excludedPermission);
		return hasRequiredPermission && !hasExcludedPermission;
		// excludedPermission is used to prevent the case that an Admin has both: Verwaltung and Administration
	});
};

const authChecker = (req, res, next) => {
	isAuthenticated(req)
		.then((isAuthenticated2) => {
			const redirectUrl = `/login?challenge=${req.query.challenge}`;
			if (isAuthenticated2) {
				// fetch user profile
				populateCurrentUser(req, res)
					.then(() => checkConsent(req, res))
					.then(() => restrictSidebar(req, res))
					.then(() => {
						next();
						return null;
					})
					.catch((err) => {
						if (err === 'firstLogin was not completed, redirecting...') {
							// print message?
							res.redirect('/firstLogin');
						} else {
							res.redirect(redirectUrl);
						}
					});
			} else {
				res.redirect(redirectUrl);
			}
		});
};

module.exports = {
	isJWT,
	cookieDomain,
	authChecker,
	isAuthenticated,
	restrictSidebar,
	populateCurrentUser,
};
<commit_msg>added error handling for missing information in jwt<commit_after>const jwt = require('jsonwebtoken');
const api = require('../api');
const permissionsHelper = require('./permissions');

const rolesDisplayName = {
	teacher: 'Lehrer',
	student: 'Schüler',
	administrator: 'Administrator',
	superhero: 'Schul-Cloud Admin',
	demo: 'Demo',
	demoTeacher: 'Demo',
	demoStudent: 'Demo',
	helpdesk: 'Helpdesk',
	betaTeacher: 'Beta',
	expert: 'Experte',
};

const isJWT = req => (req && req.cookies && req.cookies.jwt);

const cookieDomain = (res) => {
	if (res.locals.domain && process.env.NODE_ENV === 'production') {
		return { domain: res.locals.domain };
	}
	return {};
};

const isAuthenticated = (req) => {
	if (!isJWT(req)) {
		return Promise.resolve(false);
	}

	return api(req).post('/authentication', {
		json: {
			strategy: 'jwt',
			accessToken: req.cookies.jwt,
		},
	}).then(() => true).catch(() => false);
};

const populateCurrentUser = (req, res) => {
	let payload = {};
	if (isJWT(req)) {
		// eslint-disable-next-line prefer-destructuring
		payload = (jwt.decode(req.cookies.jwt, { complete: true }) || {}).payload;
		res.locals.currentPayload = payload;
	}

	// separates users in two groups for AB testing
	function setTestGroup(user) {
		if (process.env.SW_ENABLED) {
			const lChar = user._id.substr(user._id.length - 1);
			const group = parseInt(lChar, 16) % 2 ? 1 : 0;
			user.testGroup = group;
		} else {
			user.testGroup = 0;
		}
	}

	if (payload && payload.userId) {
		return api(req).get(`/users/${payload.userId}`, {
			qs: {
				$populate: ['roles'],
			},
		}).then((data) => {
			res.locals.currentUser = data;
			setTestGroup(res.locals.currentUser);
			res.locals.currentRole = rolesDisplayName[data.roles[0].name];
			res.locals.roleNames = data.roles.map(r => rolesDisplayName[r.name]);
			return api(req).get(`/schools/${res.locals.currentUser.schoolId}`, {
				qs: {
					$populate: ['federalState'],
				},
			}).then((data2) => {
				res.locals.currentSchool = res.locals.currentUser.schoolId;
				res.locals.currentSchoolData = data2;
				res.locals.currentSchoolData.isExpertSchool = data2.purpose === 'expert';
				return data2;
			});
		}).catch((e) => {
			// 400 for missing information in jwt, 401 for invalid jwt, not-found for deleted user
			if (e.statusCode === 400 || e.statusCode === 401 || e.error.className === 'not-found') {
				res.clearCookie('jwt', cookieDomain(res));
			}
		});
	}

	return Promise.resolve();
};

const checkConsent = (req, res) => {
	if (
		((res.locals.currentUser || {}).preferences || {}).firstLogin	// do not exist if 3. system login
		|| req.path.startsWith('/login/success')
		|| req.baseUrl.startsWith('/firstLogin')) {
		return Promise.resolve();
	}
	// eslint-disable-next-line prefer-promise-reject-errors
	return Promise.reject('firstLogin was not completed, redirecting...');
};

const restrictSidebar = (req, res) => {
	res.locals.sidebarItems = res.locals.sidebarItems.filter((item) => {
		if (!item.permission) return true;

		const hasRequiredPermission = permissionsHelper.userHasPermission(res.locals.currentUser, item.permission);
		const hasExcludedPermission = permissionsHelper.userHasPermission(res.locals.currentUser,
			item.excludedPermission);
		return hasRequiredPermission && !hasExcludedPermission;
		// excludedPermission is used to prevent the case that an Admin has both: Verwaltung and Administration
	});
};

const authChecker = (req, res, next) => {
	isAuthenticated(req)
		.then((isAuthenticated2) => {
			const redirectUrl = `/login?challenge=${req.query.challenge}`;
			if (isAuthenticated2) {
				// fetch user profile
				populateCurrentUser(req, res)
					.then(() => checkConsent(req, res))
					.then(() => restrictSidebar(req, res))
					.then(() => {
						next();
						return null;
					})
					.catch((err) => {
						if (err === 'firstLogin was not completed, redirecting...') {
							// print message?
							res.redirect('/firstLogin');
						} else {
							res.redirect(redirectUrl);
						}
					});
			} else {
				res.redirect(redirectUrl);
			}
		});
};

module.exports = {
	isJWT,
	cookieDomain,
	authChecker,
	isAuthenticated,
	restrictSidebar,
	populateCurrentUser,
};
<|endoftext|>


<commit_before>const express = require('express')
require('dotenv').config({ path: `.env.${process.env.NODE_ENV}` })

const app = express()
app.use(express.json())
app.set('view engine', 'pug')
const PORT = 3000
const demoHomeUrl = process.env.DEMO_HOME_URL
const publisherUrl = process.env.PUBLISHER_URL
const advertiserUrl = process.env.ADVERTISER_URL
const adtechUrl = process.env.ADTECH_URL

app.use(express.static('static'))

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

/* -------------------------------------------------------------------------- */
/*                                 Ad serving                                 */
/* -------------------------------------------------------------------------- */

app.get('/register-source', (req, res) => {
  // Send a response with the header Attribution-Reporting-Register-Source in order to ask the browser to register a source event
  const attributionDestination = process.env.ADVERTISER_URL
  // For demo purposes, sourceEventId is a random ID. In a real system, this ID would be tied to a unique serving-time identifier mapped to any information an adtech provider may need
  const sourceEventId = Math.floor(Math.random() * 1000000000000000)
  res.set(
    'Attribution-Reporting-Register-Source',
    JSON.stringify({
      source_event_id: `${sourceEventId}`,
      destination: attributionDestination,
      expiry: '604800000'
    })
  )
  res.status(200).send('OK')
})

app.get('/ad-click', (req, res) => {
  const href = `${process.env.ADVERTISER_URL}`
  const attributionDestination = process.env.ADVERTISER_URL
  const attributionReportTo = process.env.ADTECH_URL
  res.render('ad-click', {
    href,
    attributiondestination: attributionDestination,
    attributionreportto: attributionReportTo
  })
})

app.get('/ad-click-js', (req, res) => {
  const href = `${process.env.ADVERTISER_URL}`
  const attributionDestination = process.env.ADVERTISER_URL
  const attributionReportTo = process.env.ADTECH_URL
  res.render('ad-click-js', {
    href,
    attributiondestination: attributionDestination,
    attributionreportto: attributionReportTo
  })
})

app.get('/ad-script-click-element', (req, res) => {
  res.set('Content-Type', 'text/javascript')
  const adClickUrl = `${process.env.ADTECH_URL}/ad-click`
  const iframe = `<iframe src='${adClickUrl}' allow='attribution-reporting' width=190 height=190 scrolling=no frameborder=1 padding=0></iframe>`
  res.send(`document.write("${iframe}");`)
})

app.get('/ad-script-click-js', (req, res) => {
  res.set('Content-Type', 'text/javascript')
  const adClickNoLinkUrl = `${process.env.ADTECH_URL}/ad-click-js`
  const iframe = `<iframe src='${adClickNoLinkUrl}' allow='attribution-reporting' width=190 height=190 scrolling=no frameborder=1 padding=0></iframe>`
  res.send(`document.write("${iframe}");`)
})

/* -------------------------------------------------------------------------- */
/*                     Attribution trigger (conversion)                       */
/* -------------------------------------------------------------------------- */

const CHECKOUT_COMPLETED = 'checkout-completed'
const ADD_TO_CART = 'add-to-cart'
const VISIT_PRODUCT_PAGE = 'visit-product-page'
const SIGNUP_NEWSLETTER = 'signup-newsletter'

const conversionValuesClick = {
  [CHECKOUT_COMPLETED]: 1,
  [ADD_TO_CART]: 2,
  [VISIT_PRODUCT_PAGE]: 3,
  [SIGNUP_NEWSLETTER]: 4
}

function getTriggerData(conversionType) {
  return conversionValues[conversionType]
}

function getPriority(conversionType, usePriorities) {
  if (!usePriorities) {
    // false: No conversion should be prioritized specifically => always return a prio of 0
    return 0
  } else {
    // Assign a priority of 100 to checkouts, and of 0 to other conversion types
    return conversionType === CHECKOUT_COMPLETED ? 100 : 0
  }
}

app.get('/conversion', (req, res) => {
  const conversionType = req.query['conversion-type']
  const triggerData = getTriggerData(conversionType)

  const usePriorities = req.query['prio-checkout'] === 'true'
  const priority = getPriority(conversionType, usePriorities)

  const deduplicationKey = req.query['purchase-id']
  const useDeduplication = req.query['dedup'] === 'true' && deduplicationKey

  // Instruct the browser to schedule-send a report
  res.set(
    'Attribution-Reporting-Register-Event-Trigger',
    // ⚠ Note the enclosing []!
    JSON.stringify([
      {
        trigger_data: `${triggerData}`,
        // if priorities are on, specify the priority
        ...(usePriorities && { priority: `${priority}` }),
        // if deduplication is on, specify the deduplication-key
        ...(useDeduplication && { 'deduplication-key': deduplicationKey })
      }
    ])
  )
  res.sendStatus(200)
})

/* -------------------------------------------------------------------------- */
/*                                 Reports                                    */
/* -------------------------------------------------------------------------- */

let reports = []

app.get('/reports', (req, res) => {
  res.send(JSON.stringify(reports))
})

app.post(
  '/.well-known/attribution-reporting/report-event-attribution',
  async (req, res) => {
    console.log('body', req.body)
    const newReport = { ...req.body, date: new Date() }
    reports = [newReport, ...reports]
    console.log(
      '\x1b[1;31m%s\x1b[0m',
      `🚀 Adtech has received a report from the browser`
    )
    res.sendStatus(200)
  }
)

const listener = app.listen(process.env.PORT || PORT, () => {
  console.log(
    '\x1b[1;31m%s\x1b[0m',
    `🚀 Adtech server is listening on port ${listener.address().port}`
  )
})
<commit_msg>Feat: added header-based registration<commit_after>const express = require('express')
require('dotenv').config({ path: `.env.${process.env.NODE_ENV}` })

const app = express()
app.use(express.json())
app.set('view engine', 'pug')
const PORT = 3000
const demoHomeUrl = process.env.DEMO_HOME_URL
const publisherUrl = process.env.PUBLISHER_URL
const advertiserUrl = process.env.ADVERTISER_URL
const adtechUrl = process.env.ADTECH_URL

app.use(express.static('static'))

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

/* -------------------------------------------------------------------------- */
/*                                 Ad serving                                 */
/* -------------------------------------------------------------------------- */

app.get('/register-source', (req, res) => {
  // Send a response with the header Attribution-Reporting-Register-Source in order to ask the browser to register a source event
  const attributionDestination = process.env.ADVERTISER_URL
  // For demo purposes, sourceEventId is a random ID. In a real system, this ID would be tied to a unique serving-time identifier mapped to any information an adtech provider may need
  const sourceEventId = Math.floor(Math.random() * 1000000000000000)
  res.set(
    'Attribution-Reporting-Register-Source',
    JSON.stringify({
      source_event_id: `${sourceEventId}`,
      destination: attributionDestination,
      expiry: '604800000'
    })
  )
  res.status(200).send('OK')
})

app.get('/ad-click', (req, res) => {
  const href = `${process.env.ADVERTISER_URL}`
  res.render('ad-click', {
    href,
    attributionsrc: `${adtechUrl}/register-source`
  })
})

app.get('/ad-click-js', (req, res) => {
  const href = `${process.env.ADVERTISER_URL}`
  res.render('ad-click-js', {
    href,
    attributionsrc: `${adtechUrl}/register-source`
  })
})

app.get('/ad-view-anchor', (req, res) => {
  const href = `${process.env.ADVERTISER_URL}`
  res.render('ad-view-anchor', {
    href,
    attributionsrc: `${adtechUrl}/register-source`
  })
})

app.get('/ad-view-img', (req, res) => {
  const href = `${process.env.ADVERTISER_URL}`
  res.render('ad-view-img', {
    href,
    attributionsrc: `${adtechUrl}/register-source`
  })
})

app.get('/ad-view-js', (req, res) => {
  const href = `${process.env.ADVERTISER_URL}`
  res.render('ad-view-js', {
    href,
    attributionsrc: `${adtechUrl}/register-source`
  })
})

app.get('/ad-script-view-img', (req, res) => {
  res.set('Content-Type', 'text/javascript')
  const adClickUrl = `${process.env.ADTECH_URL}/ad-view-img`
  const iframe = `<iframe src='${adClickUrl}' allow='attribution-reporting' width=190 height=190 scrolling=no frameborder=1 padding=0></iframe>`
  res.send(`document.write("${iframe}");`)
})

app.get('/ad-script-click-element', (req, res) => {
  res.set('Content-Type', 'text/javascript')
  const adClickUrl = `${process.env.ADTECH_URL}/ad-click`
  const iframe = `<iframe src='${adClickUrl}' allow='attribution-reporting' width=190 height=190 scrolling=no frameborder=1 padding=0></iframe>`
  res.send(`document.write("${iframe}");`)
})

app.get('/ad-script-click-js', (req, res) => {
  res.set('Content-Type', 'text/javascript')
  const adClickNoLinkUrl = `${process.env.ADTECH_URL}/ad-click-js`
  const iframe = `<iframe src='${adClickNoLinkUrl}' allow='attribution-reporting' width=190 height=190 scrolling=no frameborder=1 padding=0></iframe>`
  res.send(`document.write("${iframe}");`)
})

/* -------------------------------------------------------------------------- */
/*                     Attribution trigger (conversion)                       */
/* -------------------------------------------------------------------------- */

const CHECKOUT_COMPLETED = 'checkout-completed'
const ADD_TO_CART = 'add-to-cart'
const VISIT_PRODUCT_PAGE = 'visit-product-page'
const SIGNUP_NEWSLETTER = 'signup-newsletter'

const conversionValuesClick = {
  [CHECKOUT_COMPLETED]: 1,
  [ADD_TO_CART]: 2,
  [VISIT_PRODUCT_PAGE]: 3,
  [SIGNUP_NEWSLETTER]: 4
}

function getTriggerData(conversionType) {
  return conversionValues[conversionType]
}

function getPriority(conversionType, usePriorities) {
  if (!usePriorities) {
    // false: No conversion should be prioritized specifically => always return a prio of 0
    return 0
  } else {
    // Assign a priority of 100 to checkouts, and of 0 to other conversion types
    return conversionType === CHECKOUT_COMPLETED ? 100 : 0
  }
}

app.get('/conversion', (req, res) => {
  const conversionType = req.query['conversion-type']
  const triggerData = getTriggerData(conversionType)

  const usePriorities = req.query['prio-checkout'] === 'true'
  const priority = getPriority(conversionType, usePriorities)

  const deduplicationKey = req.query['purchase-id']
  const useDeduplication = req.query['dedup'] === 'true' && deduplicationKey

  // Instruct the browser to schedule-send a report
  res.set(
    'Attribution-Reporting-Register-Event-Trigger',
    // ⚠ Note the enclosing []!
    JSON.stringify([
      {
        trigger_data: `${triggerData}`,
        // if priorities are on, specify the priority
        ...(usePriorities && { priority: `${priority}` }),
        // if deduplication is on, specify the deduplication-key
        ...(useDeduplication && { 'deduplication-key': deduplicationKey })
      }
    ])
  )
  res.sendStatus(200)
})

/* -------------------------------------------------------------------------- */
/*                                 Reports                                    */
/* -------------------------------------------------------------------------- */

let reports = []

app.get('/reports', (req, res) => {
  res.send(JSON.stringify(reports))
})

app.post(
  '/.well-known/attribution-reporting/report-event-attribution',
  async (req, res) => {
    console.log('body', req.body)
    const newReport = { ...req.body, date: new Date() }
    reports = [newReport, ...reports]
    console.log(
      '\x1b[1;31m%s\x1b[0m',
      `🚀 Adtech has received a report from the browser`
    )
    res.sendStatus(200)
  }
)

const listener = app.listen(process.env.PORT || PORT, () => {
  console.log(
    '\x1b[1;31m%s\x1b[0m',
    `🚀 Adtech server is listening on port ${listener.address().port}`
  )
})
<|endoftext|>


<commit_before>/*global describe, beforeEach, it*/
'use strict';

var path    = require('path');
var helpers = require('yeoman-generator').test;

describe('front generator', function () {
    beforeEach(function (done) {
        helpers.testDirectory(path.join(__dirname, 'temp'), function (err) {
            if (err) {
                return done(err);
            }

            this.app = helpers.createGenerator('front:app', [
                '../../app'
            ]);
            done();
        }.bind(this));
    });

    it('creates expected files', function (done) {
        var expected = [
            // add files you expect to exist here.
            // '.jshintrc',
            // '.editorconfig',
            'package.json',
            'bower.json',
            'composer.json'
        ];

        var componentChoices = [
          { name: 'html5shiv', value: 'html5shiv', checked: true },
          { name: 'jquery.ui', value: 'jqueryui', checked: true },
          { name: 'requirejs', value: 'requirejs', checked: true },
        ];

        helpers.mockPrompt(this.app, {
            // 'someOption': true,
            'bowerComponents': componentChoices
        });

        this.app.options['skip-install'] = true;

        this.app.run({}, function () {
            helpers.assertFiles(expected);
            done();
        });
    });
});
<commit_msg>Update expected files in test-creation.js<commit_after>/*global describe, beforeEach, it*/
'use strict';

var path    = require('path');
var helpers = require('yeoman-generator').test;

describe('front generator', function () {
    beforeEach(function (done) {
        helpers.testDirectory(path.join(__dirname, 'temp'), function (err) {
            if (err) {
                return done(err);
            }

            this.app = helpers.createGenerator('front:app', [
                '../../app'
            ]);
            done();
        }.bind(this));
    });

    it('creates expected files', function (done) {
        var expected = [
            // add files you expect to exist here.
            // '.jshintrc',
            // '.editorconfig',

            'package.json',
            'bower.json',
            'composer.json',
            '.gitignore',
            'Gruntfile.js',
            'dploy.yaml',
            'web.php',

            'sass/_config.scss',
            'sass/_init.scss',
            'sass/main.scss',
            'sass/_temp.scss',

            'js/modules/main.js',

            'views/layout.twig',
            'views/home.twig'
        ];

        var componentChoices = [
          { name: 'html5shiv', value: 'html5shiv', checked: true },
          { name: 'jquery.ui', value: 'jqueryui', checked: true },
          { name: 'requirejs', value: 'requirejs', checked: true },
        ];

        helpers.mockPrompt(this.app, {
            // 'someOption': true,
            'bowerComponents': componentChoices
        });

        this.app.options['skip-install'] = true;

        this.app.run({}, function () {
            helpers.assertFiles(expected);
            done();
        });
    });
});
<|endoftext|>


<commit_before>const jwt = require('jsonwebtoken');
const api = require('../api');
const permissionsHelper = require('./permissions');
const logger = require('./logger');
const { Configuration } = require('@schul-cloud/commons');

const rolesDisplayName = {
	teacher: 'Lehrer',
	student: 'Schüler',
	administrator: 'Administrator',
	superhero: 'Schul-Cloud Admin',
	demo: 'Demo',
	demoTeacher: 'Demo',
	demoStudent: 'Demo',
	helpdesk: 'Helpdesk',
	betaTeacher: 'Beta',
	expert: 'Experte',
};

const clearCookie = async (req, res, options = { destroySession: false }) => {
	if (options.destroySession && req.session && req.session.destroy) {
		await new Promise((resolve, reject) => {
			req.session.destroy((err) => {
				if (err) {
					reject(err);
					return;
				}
				resolve();
			});
		});
	}
	res.clearCookie('jwt');
	if (res.locals && res.locals.domain) {
		res.clearCookie('jwt', { domain: res.locals.domain });
	}
};

const isJWT = req => (req && req.cookies && req.cookies.jwt);

const cookieDomain = (res) => {
	if (res.locals.domain && process.env.NODE_ENV === 'production') {
		return { domain: res.locals.domain };
	}
	return {};
};

const isAuthenticated = (req) => {
	if (!isJWT(req)) {
		return Promise.resolve(false);
	}

	return api(req).post('/authentication', {
		json: {
			strategy: 'jwt',
			accessToken: req.cookies.jwt,
		},
	}).then(() => true).catch(() => false);
};

const populateCurrentUser = (req, res) => {
	let payload = {};
	if (isJWT(req)) {
		try {
			// eslint-disable-next-line prefer-destructuring
			payload = (jwt.decode(req.cookies.jwt, { complete: true }) || {}).payload;
			res.locals.currentPayload = payload;
		} catch (err) {
			logger.error('Broken JWT / JWT decoding failed', { error: err });
			return clearCookie(req, res, { destroySession: true })
				.catch((err) => { logger.error('clearCookie failed during jwt check', { error: err.toString() }); })
				.finally(() => res.redirect('/'));
		}
	}

	// separates users in two groups for AB testing
	function setTestGroup(user) {
		if (process.env.SW_ENABLED) {
			const lChar = user._id.substr(user._id.length - 1);
			const group = parseInt(lChar, 16) % 2 ? 1 : 0;
			user.testGroup = group;
		} else {
			user.testGroup = 0;
		}
	}

	if (payload && payload.userId) {
		return api(req).get(`/users/${payload.userId}`, {
			qs: {
				$populate: ['roles'],
			},
		}).then((data) => {
			res.locals.currentUser = data;
			setTestGroup(res.locals.currentUser);
			res.locals.currentRole = rolesDisplayName[data.roles[0].name];
			res.locals.roles = data.roles.map(({ name }) => name);
			res.locals.roleNames = data.roles.map(r => rolesDisplayName[r.name]);
			return api(req).get(`/schools/${res.locals.currentUser.schoolId}`, {
				qs: {
					$populate: ['federalState'],
				},
			}).then((data2) => {
				res.locals.currentSchool = res.locals.currentUser.schoolId;
				res.locals.currentSchoolData = data2;
				res.locals.currentSchoolData.isExpertSchool = data2.purpose === 'expert';
				return data2;
			});
		}).catch((e) => {
			// 400 for missing information in jwt, 401 for invalid jwt, not-found for deleted user
			if (e.statusCode === 400 || e.statusCode === 401 || e.error.className === 'not-found') {
				return clearCookie(req, res, { destroySession: true })
					.catch((err) => { logger.error('clearCookie failed during populateUser', { error: err.toString() }); })
					.finally(() => res.redirect('/'));
			}
			throw e;
		});
	}

	return Promise.resolve();
};

const checkConsent = (req, res) => {
	if (
		((res.locals.currentUser || {}).preferences || {}).firstLogin	// do not exist if 3. system login
		|| req.path.startsWith('/login/success')
		|| req.baseUrl.startsWith('/firstLogin')) {
		return Promise.resolve();
	}
	// eslint-disable-next-line prefer-promise-reject-errors
	return Promise.reject('firstLogin was not completed, redirecting...');
};

const restrictSidebar = (req, res) => {
	res.locals.sidebarItems = res.locals.sidebarItems.filter((item) => {
		if (!item.permission) return true;

		const hasRequiredPermission = permissionsHelper.userHasPermission(res.locals.currentUser, item.permission);
		const hasExcludedPermission = permissionsHelper.userHasPermission(res.locals.currentUser,
			item.excludedPermission);
		return hasRequiredPermission && !hasExcludedPermission;
		// excludedPermission is used to prevent the case that an Admin has both: Verwaltung and Administration
	});
};

const authChecker = (req, res, next) => {
	isAuthenticated(req)
		.then((isAuthenticated2) => {
			const redirectUrl = Configuration.get('NOT_AUTHENTICATED_REDIRECT_URL');
			if (isAuthenticated2) {
				// fetch user profile
				populateCurrentUser(req, res)
					.then(() => checkConsent(req, res))
					.then(() => restrictSidebar(req, res))
					.then(() => {
						next();
						return null;
					})
					.catch((err) => {
						if (err === 'firstLogin was not completed, redirecting...') {
							// print message?
							res.redirect('/firstLogin');
						} else {
							res.redirect(redirectUrl);
						}
					});
			} else {
				res.redirect(`${redirectUrl}?redirect=${req.originalUrl}`);
			}
		});
};

const login = (payload = {}, req, res, next) => {
	const { redirect } = payload;
	delete payload.redirect;
	return api(req).post('/authentication', { json: payload }).then((data) => {
		res.cookie('jwt', data.accessToken,
			Object.assign({},
				{
					expires: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000),
					httpOnly: false, // can't be set to true with nuxt client
					hostOnly: true,
					secure: process.env.NODE_ENV === 'production',
				},
				cookieDomain(res)));
		let redirectUrl = '/login/success';
		if (redirect) {
			redirectUrl = `${redirectUrl}?redirect=${redirect}`;
		}
		res.redirect(redirectUrl);
	}).catch((e) => {
		res.locals.notification = {
			type: 'danger',
			message: 'Login fehlgeschlagen.',
			statusCode: e.statusCode,
			timeToWait: process.env.LOGIN_BLOCK_TIME || 15,
		};
		if (e.statusCode === 429) {
			res.locals.notification.timeToWait = e.error.data.timeToWait;
		}
		next();
	});
};

module.exports = {
	clearCookie,
	isJWT,
	cookieDomain,
	authChecker,
	isAuthenticated,
	restrictSidebar,
	populateCurrentUser,
	login,
};
<commit_msg>Propagate error<commit_after>const jwt = require('jsonwebtoken');
const api = require('../api');
const permissionsHelper = require('./permissions');
const logger = require('./logger');
const { Configuration } = require('@schul-cloud/commons');

const rolesDisplayName = {
	teacher: 'Lehrer',
	student: 'Schüler',
	administrator: 'Administrator',
	superhero: 'Schul-Cloud Admin',
	demo: 'Demo',
	demoTeacher: 'Demo',
	demoStudent: 'Demo',
	helpdesk: 'Helpdesk',
	betaTeacher: 'Beta',
	expert: 'Experte',
};

const clearCookie = async (req, res, options = { destroySession: false }) => {
	if (options.destroySession && req.session && req.session.destroy) {
		await new Promise((resolve, reject) => {
			req.session.destroy((err) => {
				if (err) {
					reject(err);
					return;
				}
				resolve();
			});
		});
	}
	res.clearCookie('jwt');
	if (res.locals && res.locals.domain) {
		res.clearCookie('jwt', { domain: res.locals.domain });
	}
};

const isJWT = req => (req && req.cookies && req.cookies.jwt);

const cookieDomain = (res) => {
	if (res.locals.domain && process.env.NODE_ENV === 'production') {
		return { domain: res.locals.domain };
	}
	return {};
};

const isAuthenticated = (req) => {
	if (!isJWT(req)) {
		return Promise.resolve(false);
	}

	return api(req).post('/authentication', {
		json: {
			strategy: 'jwt',
			accessToken: req.cookies.jwt,
		},
	}).then(() => true).catch(() => false);
};

const populateCurrentUser = (req, res) => {
	let payload = {};
	if (isJWT(req)) {
		try {
			// eslint-disable-next-line prefer-destructuring
			payload = (jwt.decode(req.cookies.jwt, { complete: true }) || {}).payload;
			res.locals.currentPayload = payload;
		} catch (err) {
			logger.error('Broken JWT / JWT decoding failed', { error: err });
			return clearCookie(req, res, { destroySession: true })
				.catch((err) => { logger.error('clearCookie failed during jwt check', { error: err.toString() }); })
				.finally(() => res.redirect('/'));
		}
	}

	// separates users in two groups for AB testing
	function setTestGroup(user) {
		if (process.env.SW_ENABLED) {
			const lChar = user._id.substr(user._id.length - 1);
			const group = parseInt(lChar, 16) % 2 ? 1 : 0;
			user.testGroup = group;
		} else {
			user.testGroup = 0;
		}
	}

	if (payload && payload.userId) {
		return api(req).get(`/users/${payload.userId}`, {
			qs: {
				$populate: ['roles'],
			},
		}).then((data) => {
			res.locals.currentUser = data;
			setTestGroup(res.locals.currentUser);
			res.locals.currentRole = rolesDisplayName[data.roles[0].name];
			res.locals.roles = data.roles.map(({ name }) => name);
			res.locals.roleNames = data.roles.map(r => rolesDisplayName[r.name]);
			return api(req).get(`/schools/${res.locals.currentUser.schoolId}`, {
				qs: {
					$populate: ['federalState'],
				},
			}).then((data2) => {
				res.locals.currentSchool = res.locals.currentUser.schoolId;
				res.locals.currentSchoolData = data2;
				res.locals.currentSchoolData.isExpertSchool = data2.purpose === 'expert';
				return data2;
			});
		}).catch((e) => {
			// 400 for missing information in jwt, 401 for invalid jwt, not-found for deleted user
			if (e.statusCode === 400 || e.statusCode === 401 || e.error.className === 'not-found') {
				return clearCookie(req, res, { destroySession: true })
					.catch((err) => { logger.error('clearCookie failed during populateUser', { error: err.toString() }); })
					.finally(() => res.redirect('/'));
			}
			throw e;
		});
	}

	return Promise.resolve();
};

const checkConsent = (req, res) => {
	if (
		((res.locals.currentUser || {}).preferences || {}).firstLogin	// do not exist if 3. system login
		|| req.path.startsWith('/login/success')
		|| req.baseUrl.startsWith('/firstLogin')) {
		return Promise.resolve();
	}
	// eslint-disable-next-line prefer-promise-reject-errors
	return Promise.reject('firstLogin was not completed, redirecting...');
};

const restrictSidebar = (req, res) => {
	res.locals.sidebarItems = res.locals.sidebarItems.filter((item) => {
		if (!item.permission) return true;

		const hasRequiredPermission = permissionsHelper.userHasPermission(res.locals.currentUser, item.permission);
		const hasExcludedPermission = permissionsHelper.userHasPermission(res.locals.currentUser,
			item.excludedPermission);
		return hasRequiredPermission && !hasExcludedPermission;
		// excludedPermission is used to prevent the case that an Admin has both: Verwaltung and Administration
	});
};

const authChecker = (req, res, next) => {
	isAuthenticated(req)
		.then((isAuthenticated2) => {
			const redirectUrl = Configuration.get('NOT_AUTHENTICATED_REDIRECT_URL');
			if (isAuthenticated2) {
				// fetch user profile
				populateCurrentUser(req, res)
					.then(() => checkConsent(req, res))
					.then(() => restrictSidebar(req, res))
					.then(() => {
						next();
						return null;
					})
					.catch((err) => {
						if (err === 'firstLogin was not completed, redirecting...') {
							// print message?
							res.redirect('/firstLogin');
						} else {
							res.redirect(redirectUrl);
						}
					});
			} else {
				res.redirect(`${redirectUrl}?redirect=${req.originalUrl}`);
			}
		});
};

const login = (payload = {}, req, res, next) => {
	const { redirect } = payload;
	delete payload.redirect;
	return api(req).post('/authentication', { json: payload }).then((data) => {
		res.cookie('jwt', data.accessToken,
			Object.assign({},
				{
					expires: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000),
					httpOnly: false, // can't be set to true with nuxt client
					hostOnly: true,
					secure: process.env.NODE_ENV === 'production',
				},
				cookieDomain(res)));
		let redirectUrl = '/login/success';
		if (redirect) {
			redirectUrl = `${redirectUrl}?redirect=${redirect}`;
		}
		res.redirect(redirectUrl);
	}).catch((e) => {
		res.locals.notification = {
			type: 'danger',
			message: 'Login fehlgeschlagen.',
			statusCode: e.statusCode,
			timeToWait: process.env.LOGIN_BLOCK_TIME || 15,
		};
		if (e.statusCode === 429) {
			res.locals.notification.timeToWait = e.error.data.timeToWait;
		}
		next(e);
	});
};

module.exports = {
	clearCookie,
	isJWT,
	cookieDomain,
	authChecker,
	isAuthenticated,
	restrictSidebar,
	populateCurrentUser,
	login,
};
<|endoftext|>


<commit_before>/*

Required Variables:

	smartRepeater:
		prefix:               stat prefix (prepended to all outgoing stats)
		batchSize:            max message size to send downstream
		hosts:                array of host data to repeat information to
			hostname:         hostname or ip address
			port:             TCP port
			protocol:         udp4, udp6, tcp4, tcp6

Optional Variables:

	smartRepeater:
		prefix:               stat prefix (prepended to all outgoing stats)
		checkExistingPrefix:  true to not prepend the prefix if it's already there
		batchSize:            max message size to send downstream
		blacklist:            array of regexes for blacklisting metrics

*/

{
	/* ---------------------------------- */
	/* insert original statsd config here */
	/* ---------------------------------- */

	smartRepeater: {
		prefix: '',
		checkExistingPrefix: false,
		batchSize: 1024,
		hosts: [
			{ hostname: 'localhost', port: 8125, protocol: 'tcp6' },
			{ hostname: '127.0.0.1', port: 8127, protocol: 'udp4' }
		],
		blacklist: [
			/^statsd/
		]
	}
}
<commit_msg>fix duplicate entries in exampleConfig.js<commit_after>/*

Required Variables:

	smartRepeater:
		hosts:                array of host data to repeat information to
			hostname:         hostname or ip address
			port:             TCP port
			protocol:         udp4, udp6, tcp4, tcp6

Optional Variables:

	smartRepeater:
		prefix:               stat prefix (prepended to all outgoing stats)
		checkExistingPrefix:  true to not prepend the prefix if it's already there
		batchSize:            max message size to send downstream
		blacklist:            array of regexes for blacklisting metrics

*/

{
	/* ---------------------------------- */
	/* insert original statsd config here */
	/* ---------------------------------- */

	smartRepeater: {
		prefix: '',
		checkExistingPrefix: false,
		batchSize: 1024,
		hosts: [
			{ hostname: 'localhost', port: 8125, protocol: 'tcp6' },
			{ hostname: '127.0.0.1', port: 8127, protocol: 'udp4' }
		],
		blacklist: [
			/^statsd/
		]
	}
}
<|endoftext|>


<commit_before>$(document).ready(function() {
	window.moveCounter = 0;

	swal({
		title: "Tower of Hanoi",
		text: "How many disks do you want?",
		type: "input",
		showCancelButton: true,
		closeOnConfirm: false,
		animation: "slide-from-top",
		inputPlaceholder: "Write a number"
	}, function(inputValue) {
		var input_number = parseInt(inputValue);
		if (inputValue === false || inputValue === "" || isNaN(input_number) || input_number < 1 || 20 < input_number) {
			swal.showInputError("You need to write a number between 1 and 20!");
			return false;
		}

		window.pegs = createPegs(
			/*  pegCount = */ 3,
			/* diskCount = */ input_number);
		initHtml(pegs,
			/* pegMinWidth = */ 30);

		swal("Good luck!", inputValue + " disks have been generated for you.", "info");

		$('#btn_solve').click(function() {
			if (!this.hasBeenClicked) {
				this.hasBeenClicked = true;
				$('div.disk').draggable('disable');
				calculateBestSolution(input_number);
				$(this).html('Perform next move');
				$('#btn_auto_solve').show();
				$('#btn_auto_solve').click(function() {
					(function auto_solve() {
						$('#btn_solve').click();
						if (moves.length > 0) {
							setTimeout(function() {
								auto_solve();
							}, Math.max(5, 15000 / (Math.pow(2, input_number) - 1)));
						}
					})();
				});
				swal("The solution has been calculated!", "Press 'Perform next move' to step through the solution or 'Solve automatically' to see the solution.", "info");
			} else if (moves.length > 0) {
				moveDiskElement($('div.peg:nth-child(' + (moves[0][0] + 1) + ') div.disk:first-child'), moves[0][0], moves[0][1], input_number);
				moves.splice(0,1); // remove move
			}
		});
	});
	adjustMoveCounterFontSize();
	/*$('#btn_hint').click(function() {
		var move = calculateBestNextMove(pegs);
		var pegFrom = $('div.peg:nth-child('+ (move.from + 1) + ')');
		var pegTo = $('div.peg:nth-child('+ (move.to + 1) + ')');

		pegFrom.css({
			'border-bottom': '10px solid #e00000'
		});
		pegTo.css({
			'border-bottom': '10px solid #00e000'
		});
		setTimeout(function() {
			pegFrom.css({
				'border-bottom': 'none'
			});
			pegTo.css({
				'border-bottom': 'none'
			});
		}, 1000);
	});*/
});

$(window).resize(function() {
	adjustMoveCounterFontSize();
});

function adjustMoveCounterFontSize() {
	var moveCounter = $('#movecounter').parent();
	moveCounter.css({
		'font-size': $('#footer').height() + 'px'
	});
}

function initHtml(pegs, pegMinWidth) {
	var diskCount = pegs[0][0];
	var pegContainer = $('#pegcontainer');
	pegContainer.html('');
	for (var i = 0; i < pegs.length; i++) {
		pegContainer.append('

');
	}

	var pegWidth = ((96 - 2.7 * (pegs.length - 1)) / pegs.length) + '%';
	$('div.peg').css({
		'width': pegWidth
	});

	var pegElements = $('div.peg');
	var firstPegMarginLeft = (pegContainer.width() + $(pegElements[0]).offset().left - $(pegElements[pegElements.length - 1]).offset().left - $(pegElements[pegElements.length - 1]).width())/2;
	$('div.peg:first-child').css({
		'margin-left': firstPegMarginLeft
	});

	for (var i = diskCount - 1; i >= 0; i--) {
		$(pegElements[0]).append('

');
	}

	var diskHeight = (100 / diskCount) + '%';
	$('div.disk').css({
		height: diskHeight
	});

	var diskElements = $('div.disk');
	for (var i = 0; i < diskCount; i++) {
		$(diskElements[i]).css({
			width: (pegMinWidth + (100 - pegMinWidth) * ((pegs[0][diskCount - i - 1] - 1) / (diskCount - 1))) + '%'
		});
	}

	$('div.disk').draggable({
		snap: 'div.peg',
		stop: function() {
			var oldPegIndex = parseInt($(this).attr('peg'));
			if ($('div.peg:nth-child(' + (oldPegIndex + 1) + ') div.disk:first-child').attr('value') != $(this).attr('value')) {
				swal('Invalid move!', 'You may only move the topmost disk.', 'error');
			} else {
				var newPegIndex;
				var diskOffsetLeft = $(this).offset().left + $(this).width() / 2;
				for (newPegIndex = pegElements.length - 1; newPegIndex >= 0; newPegIndex--) {
					if ($(pegElements[newPegIndex]).offset().left < diskOffsetLeft) {
						break;
					}
				}

				if (oldPegIndex != newPegIndex) {
					if (moveDisk(pegs[oldPegIndex], pegs[newPegIndex])) {
						moveDiskElement($(this), oldPegIndex, newPegIndex, diskCount);

						if (pegs[0].length == 0 && pegs[1].length == 0) { // finished
							swal("Good job!", "You solved the puzzle in " + moveCounter + " moves.", "success");
						}
					} else {
						swal('Invalid move!', 'A disk may not sit on top of a smaller disk.', 'error');
					}
				}
			}
			$(this).css({
				top: 0,
				left: 0
			});
		}
	});
}

function moveDiskElement(disk, oldPegIndex, newPegIndex, diskCount) {
	var diskHeight = $(disk).outerHeight();
	var newPeg = $('div.peg:nth-child(' + (newPegIndex + 1) + ')');
	newPeg.find('div.disk:first-child').css({
		'margin-top': 0
	});
	newPeg.prepend(disk);
	$(disk).attr({
		peg: newPegIndex
	});

	var oldPeg = $('div.peg:nth-child(' + (oldPegIndex + 1) + ')');
	oldPeg.find('div.disk:first-child').css({
		'margin-top': ((diskCount - oldPeg.find('div.disk').length) * diskHeight) + 'px'
	});
	$(disk).css({
		'margin-top': ((diskCount - newPeg.find('div.disk').length) * diskHeight) + 'px'
	});

	moveCounter++;
	$('#movecounter').html(moveCounter);
}<commit_msg>Hide auto-solve button on disk drag<commit_after>$(document).ready(function() {
	window.moveCounter = 0;

	swal({
		title: "Tower of Hanoi",
		text: "How many disks do you want?",
		type: "input",
		showCancelButton: true,
		closeOnConfirm: false,
		animation: "slide-from-top",
		inputPlaceholder: "Write a number"
	}, function(inputValue) {
		var input_number = parseInt(inputValue);
		if (inputValue === false || inputValue === "" || isNaN(input_number) || input_number < 1 || 20 < input_number) {
			swal.showInputError("You need to write a number between 1 and 20!");
			return false;
		}

		window.pegs = createPegs(
			/*  pegCount = */ 3,
			/* diskCount = */ input_number);
		initHtml(pegs,
			/* pegMinWidth = */ 30);

		swal("Good luck!", inputValue + " disks have been generated for you.", "info");

		$('#btn_solve').click(function() {
			if (!this.hasBeenClicked) {
				this.hasBeenClicked = true;
				$('div.disk').draggable('disable');
				calculateBestSolution(input_number);
				$(this).html('Perform next move');
				$('#btn_auto_solve').show();
				$('#btn_auto_solve').click(function() {
					(function auto_solve() {
						$('#btn_solve').click();
						if (moves.length > 0) {
							setTimeout(function() {
								auto_solve();
							}, Math.max(5, 15000 / (Math.pow(2, input_number) - 1)));
						}
					})();
				});
				swal("The solution has been calculated!", "Press 'Perform next move' to step through the solution or 'Solve automatically' to see the solution.", "info");
			} else if (moves.length > 0) {
				moveDiskElement($('div.peg:nth-child(' + (moves[0][0] + 1) + ') div.disk:first-child'), moves[0][0], moves[0][1], input_number);
				moves.splice(0,1); // remove move
			}
		});
	});
	adjustMoveCounterFontSize();
});

$(window).resize(function() {
	adjustMoveCounterFontSize();
});

function adjustMoveCounterFontSize() {
	var moveCounter = $('#movecounter').parent();
	moveCounter.css({
		'font-size': $('#footer').height() + 'px'
	});
}

function initHtml(pegs, pegMinWidth) {
	var diskCount = pegs[0][0];
	var pegContainer = $('#pegcontainer');
	pegContainer.html('');
	for (var i = 0; i < pegs.length; i++) {
		pegContainer.append('

');
	}

	var pegWidth = ((96 - 2.7 * (pegs.length - 1)) / pegs.length) + '%';
	$('div.peg').css({
		'width': pegWidth
	});

	var pegElements = $('div.peg');
	var firstPegMarginLeft = (pegContainer.width() + $(pegElements[0]).offset().left - $(pegElements[pegElements.length - 1]).offset().left - $(pegElements[pegElements.length - 1]).width())/2;
	$('div.peg:first-child').css({
		'margin-left': firstPegMarginLeft
	});

	for (var i = diskCount - 1; i >= 0; i--) {
		$(pegElements[0]).append('

');
	}

	var diskHeight = (100 / diskCount) + '%';
	$('div.disk').css({
		height: diskHeight
	});

	var diskElements = $('div.disk');
	for (var i = 0; i < diskCount; i++) {
		$(diskElements[i]).css({
			width: (pegMinWidth + (100 - pegMinWidth) * ((pegs[0][diskCount - i - 1] - 1) / (diskCount - 1))) + '%'
		});
	}

	$('div.disk').draggable({
		snap: 'div.peg',
		stop: function() {
			$('#btn_solve').hide();
			var oldPegIndex = parseInt($(this).attr('peg'));
			if ($('div.peg:nth-child(' + (oldPegIndex + 1) + ') div.disk:first-child').attr('value') != $(this).attr('value')) {
				swal('Invalid move!', 'You may only move the topmost disk.', 'error');
			} else {
				var newPegIndex;
				var diskOffsetLeft = $(this).offset().left + $(this).width() / 2;
				for (newPegIndex = pegElements.length - 1; newPegIndex >= 0; newPegIndex--) {
					if ($(pegElements[newPegIndex]).offset().left < diskOffsetLeft) {
						break;
					}
				}

				if (oldPegIndex != newPegIndex) {
					if (moveDisk(pegs[oldPegIndex], pegs[newPegIndex])) {
						moveDiskElement($(this), oldPegIndex, newPegIndex, diskCount);

						if (pegs[0].length == 0 && pegs[1].length == 0) { // finished
							swal("Good job!", "You solved the puzzle in " + moveCounter + " moves.", "success");
						}
					} else {
						swal('Invalid move!', 'A disk may not sit on top of a smaller disk.', 'error');
					}
				}
			}
			$(this).css({
				top: 0,
				left: 0
			});
		}
	});
}

function moveDiskElement(disk, oldPegIndex, newPegIndex, diskCount) {
	var diskHeight = $(disk).outerHeight();
	var newPeg = $('div.peg:nth-child(' + (newPegIndex + 1) + ')');
	newPeg.find('div.disk:first-child').css({
		'margin-top': 0
	});
	newPeg.prepend(disk);
	$(disk).attr({
		peg: newPegIndex
	});

	var oldPeg = $('div.peg:nth-child(' + (oldPegIndex + 1) + ')');
	oldPeg.find('div.disk:first-child').css({
		'margin-top': ((diskCount - oldPeg.find('div.disk').length) * diskHeight) + 'px'
	});
	$(disk).css({
		'margin-top': ((diskCount - newPeg.find('div.disk').length) * diskHeight) + 'px'
	});

	moveCounter++;
	$('#movecounter').html(moveCounter);
}<|endoftext|>


<commit_before><commit_msg>Create template.js<commit_after><|endoftext|>


<commit_before>import React, { Component } from 'react';
import $ from 'jquery';
import auth from '../auth';
import AddInput from './AddInput';
import List from './List';

export default class Programs extends Component {
	state = {
		programs: []
	}
	componentDidMount() {
		$.get('/api/programs/' + auth.getUserId(), ({ programs }) => {
      if (programs) {
  			this.setState({ programs });
      }
		});
	}
  addNew = (program) => {
    const data = {
      program,
      trainerId: auth.getUserId()
    };
    // Ajax post to save new program
    $.ajax({
      type: 'post',
      url: '/api/programs',
      data
    })
    .done(programs => {
      this.setState({ programs });
    })
    .fail(res => {
      console.log('Error.', res);
    });
  }
  render() {
    return (

Your Programs

            <AddInput
              placeholder="Add new program..."
              onSubmit={this.addNew} />
            <List data={this.state.programs} linkTo="programs" />

    );
  }
}
<commit_msg>Minor mistake.<commit_after>import React, { Component } from 'react';
import $ from 'jquery';
import auth from '../auth';
import AddInput from './AddInput';
import List from './List';

export default class Programs extends Component {
	state = {
		programs: []
	}
	componentDidMount() {
		$.get('/api/programs/' + auth.getUserId(), programs => {
      if (programs) {
  			this.setState({ programs });
      }
		});
	}
  addNew = (program) => {
    const data = {
      program,
      trainerId: auth.getUserId()
    };
    // Ajax post to save new program
    $.ajax({
      type: 'post',
      url: '/api/programs',
      data
    })
    .done(programs => {
      this.setState({ programs });
    })
    .fail(res => {
      console.log('Error.', res);
    });
  }
  render() {
    return (

Your Programs

            <AddInput
              placeholder="Add new program..."
              onSubmit={this.addNew} />
            <List data={this.state.programs} linkTo="programs" />

    );
  }
}
<|endoftext|>


<commit_before>/*global describe, beforeEach, it*/
'use strict';

var path    = require('path');
var helpers = require('yeoman-generator').test;

describe('magento generator', function () {
  beforeEach(function (done) {
    helpers.testDirectory(path.join(__dirname, 'temp'), function (err) {
      if (err) {
        return done(err);
      }

      this.app = helpers.createGenerator('magento:app', [
        '../../app'
      ]);
      done();
    }.bind(this));
  });

  it('creates expected files', function (done) {
    var expected = [
      // add files you expect to exist here.
      '.jshintrc',
      '.editorconfig',
      '.gitignore',
      'package.json',
      'bower.json'
    ];

    helpers.mockPrompt(this.app, {
      'magentoVersion': '1.8.0.0'
    });
    this.app.options['skip-install'] = true;
    this.app.run({}, function () {
      helpers.assertFiles(expected);
      done();
    });
  });
});
<commit_msg>Fix test by setting a large timeout<commit_after>/*global describe, beforeEach, it*/
'use strict';

var path    = require('path');
var helpers = require('yeoman-generator').test;

describe('magento generator', function () {
  this.timeout(120000);

  beforeEach(function (done) {
    helpers.testDirectory(path.join(__dirname, 'temp'), function (err) {
      if (err) {
        return done(err);
      }

      this.app = helpers.createGenerator('magento:app', [
        '../../app'
      ]);
      done();
    }.bind(this));
  });

  it('creates expected files', function (done) {
    var expected = [
      // add files you expect to exist here.
      '.jshintrc',
      '.editorconfig',
      '.gitignore',
      'package.json',
      'bower.json'
    ];

    helpers.mockPrompt(this.app, {
      'magentoVersion': '1.8.0.0'
    });

    this.app.options['skip-install'] = true;
    this.app.run({}, function () {
      helpers.assertFiles(expected);
      done();
    });
  });
});
<|endoftext|>


<commit_before>'use strict'

import React, { Component } from 'react';
import {
  View,
  StyleSheet,
  Text,
  TextInput,
  Image,
  ListView,
  Navigator,
  TouchableOpacity,
} from 'react-native';

const PULLDOWN_DISTANCE = 40;
import SendBird from 'sendbird'
const ContactsList = require('react-native-contacts');
import NavButton from './navButton';
import NavMenu from './navMenu';

export default class Contacts extends Component {
  constructor() {
    super();
    sb = SendBird.getInstance();
    this.state = {
      dataSource: new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2}),
      contactList: []
    };
  }

  navigate() {
    this.props.navigator.pop()
  }

  componentDidMount() {
    ContactsList.getAll((err, contacts) => {
      if(err && err.type === 'permissionDenied'){

      } else {
        console.log('before filter', contacts);

        const contactList = this.filterContacts(contacts);
        console.log(contactList, 'contact list')
        console.log(contactList, 'contact list 65')

        this.setState({
          contactList: contactList
        })
      }
    })
  }

  filterContacts(contacts) {
     fetch('https://temo-api.herokuapp.com/users/show', {
        method: 'post',
        headers: { 'Accept': 'application/json','Content-Type': 'application/json'},
        body: JSON.stringify({
        contacts: contacts,
      })
    })
    .then((response) => response.json())
    .then((responseJson) => {
      if (responseJson !== null) {
        this.setState({
          contactList: responseJson
        })
      }
    })
    .catch((error) => {
      throw new Error(error)
    })
  }

  handleContactChoice(rowData){
    const number = rowData['phoneNumbers'][0]['number']
    this.onContactPress(number)
  }

  render() {
    console.log(this.state.contactList)
    const dataSource = this.state.dataSource.cloneWithRows(this.state.contactList || [])
    console.log(dataSource)

    return (
      <View style={styles.container}>
        <ListView
          enableEmptySections
          dataSource={dataSource}
          renderRow={(rowData, sectionID, rowID) => (
              <TouchableOpacity
                onPress={() => this.handleContactChoice(rowData)}
              >
                <Text style={{ fontSize: 50, borderWidth: 1 }}>{rowData.familyName}</Text>
              </TouchableOpacity>
          )}
        />
      </View>
   );
  }

    onContactPress(usertwo_phone){
      var _self = this
      sb.OpenChannel.createChannel("rand", "", "", [sb.currentUser.userId], function (channel, error) {
        console.log("in here")

          if (error) {
              console.log("error");
              return;
          }
          channel.enter(function(response, error){
            console.log("now here")
              if (error) {
                  console.log(error);
                  console.log("error2");
                  return;
              }
              fetch('https://temo-api.herokuapp.com/conversations', {
                method: 'post',
                headers: { 'Accept': 'application/json','Content-Type': 'application/json'},
                body: JSON.stringify({
                channel_url: channel,
                user_one: sb.currentUser.nickname,
                user_two: usertwo_phone,
              })
            })
            .then((response) => response.json())
            .then((responseJson) => {
              if (responseJson) {
                debugger
                console.log("good");

                _self.props.navigator.push({name: 'chat'});
              } else {
                debugger
                console.error("bad");
              }

            })
          });
      });
    }
  }

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: 'white',
  },
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
  instructions: {
    textAlign: 'center',
    color: '#333333',
    marginBottom: 5,
  },
  listView: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  }
});
<commit_msg>contact to chat fix<commit_after>'use strict'

import React, { Component } from 'react';
import {
  View,
  StyleSheet,
  Text,
  TextInput,
  Image,
  ListView,
  Navigator,
  TouchableOpacity,
} from 'react-native';

const PULLDOWN_DISTANCE = 40;
import SendBird from 'sendbird'
const ContactsList = require('react-native-contacts');
import NavButton from './navButton';
import NavMenu from './navMenu';

export default class Contacts extends Component {
  constructor() {
    super();
    sb = SendBird.getInstance();
    this.state = {
      dataSource: new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2}),
      contactList: []
    };
  }

  navigate() {
    this.props.navigator.pop()
  }

  componentDidMount() {
    ContactsList.getAll((err, contacts) => {
      if(err && err.type === 'permissionDenied'){

      } else {
        console.log('before filter', contacts);

        const contactList = this.filterContacts(contacts);

        this.setState({
          contactList: contactList
        })
      }
    })
  }

  filterContacts(contacts) {
     fetch('https://temo-api.herokuapp.com/users/show', {
        method: 'post',
        headers: { 'Accept': 'application/json','Content-Type': 'application/json'},
        body: JSON.stringify({
        contacts: contacts,
      })
    })
    .then((response) => response.json())
    .then((responseJson) => {
      if (responseJson !== null) {
        this.setState({
          contactList: responseJson
        })
      }
    })
    .catch((error) => {
      throw new Error(error)
    })
  }

  handleContactChoice(rowData){
    const number = rowData['phoneNumbers'][0]['number']
    this.onContactPress(number)
  }

  render() {
    const dataSource = this.state.dataSource.cloneWithRows(this.state.contactList || [])
    return (
      <View style={styles.container}>
        <ListView
          enableEmptySections
          dataSource={dataSource}
          renderRow={(rowData, sectionID, rowID) => (
              <TouchableOpacity
                onPress={() => this.handleContactChoice(rowData)}
              >
                <Text style={{ fontSize: 50, borderWidth: 1 }}>{rowData.familyName}</Text>
              </TouchableOpacity>
          )}
        />
      </View>
   );
  }

    onContactPress(usertwo_phone){
      var _self = this
      sb.OpenChannel.createChannel("rand", "", "", [sb.currentUser.userId], function (channel, error) {
        console.log("in here")

          if (error) {
              console.log("error");
              return;
          }
          channel.enter(function(response, error){
            console.log("now here")
              if (error) {
                  console.log(error);
                  console.log("error2");
                  return;
              }
              fetch('https://temo-api.herokuapp.com/conversations', {
                method: 'post',
                headers: { 'Accept': 'application/json','Content-Type': 'application/json'},
                body: JSON.stringify({
                channel_url: channel,
                user_one: sb.currentUser.nickname,
                user_two: usertwo_phone,
              })
            })
            .then((response) => response.json())
            .then((responseJson) => {
              if (responseJson) {
                debugger
                console.log("good");

                _self.props.navigator.push({name: 'chat'});
              } else {
                debugger
                console.error("bad");
              }

            })
          });
      });
    }
  }

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: 'white',
  },
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
  instructions: {
    textAlign: 'center',
    color: '#333333',
    marginBottom: 5,
  },
  listView: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  }
});
<|endoftext|>