Tag Archives: Javascript

Commands and Code Snippets I usually forget

Some commands and code snippets I use rarely during CTFs or my daily work, but still I need them from time to time and I’m very lazy to remember them. This note may grow over time.

Javascript

Playing with dec, hexa and bin (not really) in JS
String.fromCharCode(0x41) // 'A'

parseInt('0xf', 16) // 15

var n = 15

n.toString(16) // 'f'
n.toString(2) // '1111'
n.toString() // '15'

var n = 'A'
n.charCodeAt() // 65
// dec to hex
n.charCodeAt().toString(16) // '41'
// dec to bin
n.charCodeAt().toString(2) // '1000001'
// dec to hex
parseInt(255).toString(16) // 'ff'
// dec to bin
parseInt(5).toString(2) // '101'
Simple HTTP GET request using nodejs
const https = require('https');

https.get('https://www.alevsk.com', (resp) => {
  let data = '';
  resp.on('data', (chunk) => {
    data += chunk;
  });
  resp.on('end', () => {
    //DO something with data
  });
}).on("error", (err) => {
  console.log("Error: " + err.message);
});
Simple HTTP POST request using nodejs
const https = require('https')

const data = JSON.stringify({
  todo: 'Buy the milk'
})

const options = {
  hostname: 'whatever.com',
  port: 443,
  path: '/todos',
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Content-Length': data.length
  }
}

const req = https.request(options, res => {
  res.on('data', d => {
    process.stdout.write(d)
  })
})

req.on('error', error => {
  console.error(error)
})

req.write(data)

req.end()
Extract content between regular expression patterns using JS
const message =  data.match(/<p>([^<]+)<\/p>/)[1];
const lat =  data.match(/name="lat" value="([^<]+)" min=/)[1];
const long =  data.match(/name="lon" value="([^<]+)" min=/)[1];
const token =  data.match(/name="token" value="([^<]+)"/)[1];

Linux

Mount NTFS on Linux
mount -t ntfs [FILE] [PATH]
mount -t type device directory
Extract extended attributes from NTFS disk
getfattr --only-values [FILE] -n [ATTR-NAME] > file
Parsing file with awk and run xargs
cat [FILE] | awk '{print $1 .. $n}' | xargs

Python

Start Simple HTTP server with Python
python -m SimpleHTTPServer
Inline Python commands
python -c 'print "\x41" * 20'

PHP

Run PHP interactive mode
php -a

Implementación teórica con BlockChain para un sistema de votaciones

Ha inicios de este año recibí un mensaje en Linkedin donde me preguntaban si estaba interesado en comenzar un proceso de reclutamiento, lo cual no es nada raro ya que siendo ingeniero de software (una de las industrias con más de profesionales en la actualidad) te llegan correos con propuestas laborales todos los días, sin embargo esta propuesta me pareció bastante interesante ya que necesitaban un Senior BlockChain Engineer, el mensaje en cuestión era:

Si bien no tengo experiencia desarrollando BlockChain como tal, si tengo bastante experiencia con sistemas distribuidos, así que me di a la tarea de comenzar a aprender el funcionamiento de esta tecnología desde un punto de vista técnico, sus conceptos básicos y sobre todo tratar de entender por que se volvió tan popular y sera el “futuro”.

Disclaimer: El código mostrado en el articulo a continuación no es una implementación real de BlockChain (no esta ni cerca del 1% de ser un proyecto real) la intención es resaltar y explicar las partes mas importantes y hacer hincapié en los conceptos básicos de lo que es BlockChain, el código dista de ser perfecto y no debe ser usado en producción.

Bueno ya estan advertidos hehe, comenzamos.

El bloque

Para entender lo que es la cadena de bloques primero tenemos que entender lo que es un bloque, el bloque puede ser representado como un objeto que contiene un identificador único, un timestamp, información en cualquier formato que queramos, un hash o checksum que representa la información que contiene y lo mas importante es que debe tener una referencia al bloque anterior, como si de una lista enlazada se tratara.

Con un lenguaje tan sencillo como Javascript podemos representar al bloque de la siguiente forma:

class Block {
  constructor(index, timestamp, data, previousHash = '') {
    this.index = index;
    this.timestamp = timestamp;
    this.data = data;
    this.previousHash = previousHash;
    this.hash = this.calculateHash();
  }

  calculateHash() {
    return SHA256(this.index + this.timestamp + JSON.stringify(this.data) + this.previousHash).toString();
  }
}

La clase bloque contiene una función muy especial llamada calculateHash, esta función toma toda la información del bloque (index, timestamp, data, previousHash), la concatena y le aplica un algoritmo de hashing para generar un checkSum que despues sera almacenado en el mismo bloque, la parte interesante y una de las razones por las que BlockChain es seguro es precisamente el uso de estas funciones criptográficas, ya que su integridad esta respaldada de forma matemáticamente.

Detengamonos por unos segundos y pensemos, si todo bloque debe de tener una referencia al hash del bloque anterior, y ese dato (previousHash) se utiliza para calcular el hash del bloque actual eso significa que si alguien hackea/modifica/elimina uno de los bloques anteriores todos los siguientes bloques quedarían invalidados 🙂 , seria un efecto domino de fallas en la integridad de los bloques.

Esta es la representación mas básica que se me ocurre de un bloque, en la vida real son estructuras de datos mucho mas complejas y en la parte de los datos pueden contener muchísimas mas piezas de información y no solo una, como lo es el caso de las transacciones en la BlockChain de Bitcoin.

La cadena

Habiendo entendido un poco lo que es el bloque ahora toca el turno de la cadena, esta es otra estructura de datos que funciona alrededor de los bloques y realiza operaciones con ellos, mencione que esta tecnología es muy parecida a una lista enlazada, si el bloque es uno de los nodos entonces la cadena serian las operaciones de agregar, eliminar, modificar, etc nodos, aunque en BlockChain solo podemos agregar bloques y nunca eliminarlos por lo que mencionaba sobre la integridad de los hashes.

En Javascript podemos representar la cadena de la siguiente forma:

class BlockChain {
  constructor() {
    this.chain = [this.createGenesisBlock()];
  }

  createGenesisBlock() {
    return new Block(0, new Date(), "Genesis block");
  }

  getLatestBlock() {
    return this.chain[this.chain.length - 1];
  }

  addBlock(block) {
    block.previousHash = this.getLatestBlock().hash;
    block.hash = block.calculateHash();
    this.chain.push(block);
  }

  isChainValid() {
    for(let i = 1; i < this.chain.length; i++) {
      const currentBlock = this.chain[i];
      const previousBlock = this.chain[i - 1];
      if (currentBlock.hash !== currentBlock.calculateHash()) {
        return false;
      }
      if(currentBlock.previousHash !== previousBlock.hash) {
        return false;
      } 
    }
    return true;
  }
}

Tenemos varias funciones interesantes como addBlock (agregar nuevo bloque), getLatestBlock (obtener el ultimo bloque), isChainValid (valida la integridad de la cadena de bloques) y createGenesisBlock, estas dos ultimas son las mas interesantes.

Mencione que cada bloque debe tener una referencia al bloque anterior ¿Pero entonces cuál fue el primer bloque 🙂 ?

Toda cadena de bloques inicia con un bloque llamado Bloque Genesis, ese nombre no es nada mas que una convención, es la forma de inicializar la cadena.

La función isChainValid verifica la integridad de la cadena utilizando los hashes de cada uno de los bloques, comienza revisando a partir del segundo bloque (uno después del bloque génesis) y primero revisa que el hash actual efectivamente corresponda con la información del bloque

if (currentBlock.hash !== currentBlock.calculateHash()) {
  return false;
}

Después revisa que la referencia (previousHash) al bloque anterior sea la correcta:

if(currentBlock.previousHash !== previousBlock.hash) {
  return false;
} 

Así hasta llegar al ultimo bloque y si todo sale bien la cadena es valida :). Sin embargo si entendieron bien el concepto de verificación de integridad pueden ver el problema con esta implementación, si bien no es posible modificar la información de un bloque intermedio, teóricamente es posible “hackear” la información del ultimo bloque antes de que agreguen nuevos nodos a la cadena.

Este precisamente es el problema que se aborda en el primer paper de Bitcoin por Satoshi Nakamoto: Bitcoin: A Peer-to-Peer Electronic Cash System

Sin entrar en detalles, en implementaciones reales la cadena de bloques no se encuentra centralizada en una sola maquina, en lugar de eso es una red distribuida y todas las computadoras de la red contienen una copia completa de la cadena, entonces cada vez que alguien va a agregar un nuevo bloque toda la red tiene que consentir y finalmente ese bloque se almacena en las cadenas de todas las maquinas, sin embargo esta solución abre la posibilidad a nuevos tipos de ataques como por ejemplo el double spend attack, aun así, teóricamente sigue siendo posible “hackear” la BlockChain pero para eso tendrías que modificar los últimos bloques de todas las maquinas de la red lo cual requiere una cantidad inmensa de recursos y por lo tanto no es factible.

Ejemplo de BlockChain para votaciones

Habiendo aprendido los conceptos básicos ahora podemos pensar en como usar BlockChain para almacenar información referente a un sistema de votaciones, vamos a escribir unas cuantas pruebas en Javascript para probar nuestras dos clases, Block y BlockChain.

  it('Generate genesis block', () => {
    voteChain = new BlockChain();
    assert.lengthOf(voteChain.chain, 1);
    assert.equal(voteChain.chain[0].data, 'Genesis block');
  });

Con este test probamos que la cadena se inicializa y el bloque génesis es generado correctamente (la longitud de la cadena es 1 y data del primer bloque contiene el string ‘Genesis block’)

Ahora vamos a agregar unos cuantos bloques a la cadena

  it('Add some blocks', () => {
    voteChain.addBlock(new Block(1, new Date(), { user: 'Manuel', voted: 'PRI' }));
    voteChain.addBlock(new Block(2, new Date(), { user: 'Andres', voted: 'PAN' }));
    voteChain.addBlock(new Block(3, new Date(), { user: 'Julio', voted: 'PRD' }));
    voteChain.addBlock(new Block(4, new Date(), { user: 'Carlos', voted: 'PRI' }));
    voteChain.addBlock(new Block(5, new Date(), { user: 'Ruben', voted: 'PAN' }));
    voteChain.addBlock(new Block(6, new Date(), { user: 'Laura', voted: 'PRD' }));
    assert.lengthOf(voteChain.chain, 7);
  });

Estamos almacenando nombres de personas y el partido político mexicano por el que votaron, un bloque a la vez y al final verificamos que la longitud de la cadena es 7 (incluyendo el bloque génesis). En la vida real esto es mucho mas complicado ya que la gente no podría agregar bloques “solo por que si”, al igual que con Bitcoin se utilizaría una tecnología de PKI (Infraestructura de llave publica) en donde cada transacción de voto deberá ser firmada usando la llave privada (como con la FIEL del SAT) de la persona que emite su voto, de esa manera nadie podría votar a nombre de alguien mas.

Ahora tenemos nuestro test para verificar la integridad de la BlockChain, si la cadena es valida esperaríamos que la función isChainValid nos devolviera true.

  it('Validate chain integrity', () => {
    assert.isOk(voteChain.isChainValid(), 'Block hashes are incorrect'); // this should return true
  });

Observen como en cada uno de los bloques el valor de previousHash es identico al hash del bloque anterior

En la ultima prueba simulamos que alguien modifico el voto de alguien mas, para eso tomamos de forma aleatoria un bloque y cambiamos el valor de su data por el nombre de otro partido político.

  it('Changing random data in the BlockChain', () => {
    const min = 0; // first block id
    const max = 5; // for academic purpose this cannot be 6 (the last block id) due to double spend attack
    const blockId = Math.floor(Math.random() * (max - min + 1) + min); // https://stackoverflow.com/questions/4959975/generate-random-number-between-two-numbers-in-javascript
    const block = voteChain.chain[blockId];
    block.data = { user: block.data.user, voted: 'MORENA' }; // Changing block value
    block.hash = block.calculateHash(); // Re calculate the current block hash so no one notices the hack
    assert.isNotOk(voteChain.isChainValid(), 'Block hashes are incorrect'); // this should return false
  });

El test, de forma aleatoria, tomo el bloque con index 2 y cambio los valores que tenia en data y eso hizo que el hash resultante de ese bloque cambiara completamente.

hash antes del cambio:
9ecbe54e3e6b3f22a522bbee7f399002f1de2d653c15a74d2d321f27cdfe116b

hash después del cambio:
3e6c8f5c0a734db4bb19483a11022081250171621e5c5c17c21a302d1d9d14d0

Por lo tanto el previousHash del bloque index 3 ya no coincide con el del bloque index 2.

Debido a este cambio la validación de integridad de la cadena fallara (siempre y cuando no modifiquemos los datos del ultimo bloque) y isChainValid() nos devolverá false.

Y eso es todo por ahora, finalmente si quieren descargar este sencillo código para verlo mas a detalle o simplemente para tenerlo lo pueden hacer desde el siguiente repositorio de github alevsk blockchain javascript con los siguientes comandos

$ git clone https://github.com/Alevsk/blockchain-javascript
$ cd blockchain-javascript
$ npm install
$ mocha index.test.js

Resumen

BlockChain nos ofrece ante todo integridad de la información, nos asegura que la información no puede ser cambiada ni eliminada sin que nos demos cuenta, ademas por su naturaleza de ser un sistema distribuido es virtualmente imposible hackear la red, esta tecnología aplicada a un sistema de votaciones nos garantiza que algo como el robo de votos no puede ocurrir y tendríamos total transparencia en las votaciones.

Si quieren aprender mas sobre esta tecnología les recomiendo ver este video en donde se explica con mucho mas detalle como funciona Bitcoin y la BlockChain en general, se abordan muchísimos mas conceptos de los que mencione en este articulo.

Happy hacking 🙂

Introducción a GraphQL, Queries y Mutations

Como algunos de ustedes sabrán llevo poco mas de 1 año trabajando con una startup (si, deje Oracle XD) cuyo stack esta conformado en su mayoría por tecnologías de Javascript (NodeJS, ReactJS, Redux, Apollo, GraphQL, React-native, etc). y en esta ocasión quiero compartir con ustedes el material de la platica que di en el GDLJS del mes de octubre en Guadalajara, se trata de una breve introducción a GraphQL y cual ha sido mi experiencia con esta tecnología.

¿Que es GraphQL?

Primero lo primero, GraphQL es un lenguaje de consultas para tu API creado por Facebook en 2012, es decir, es un intermediario comúnmente utilizado entre un cliente y algún orm de tu elección, es importante mencionar que GraphQL no se conecta directamente a tu base de datos, en lugar de eso ayuda a que el cliente defina el formato de la respuesta que desea obtener del servidor, mas adelante veremos algunos ejemplos.

¿Cual es la diferencia?

Ya existen bastantes frameworks para desarrollar apis ¿Por que quisiera usar GraphQL?

Bueno una de las principales diferencias con apis basadas en REST simple que tienen múltiples endpoints es que en tu api basada en GraphQL solo tendras uno.

Ademas de eso las apis comunes utilizan varios métodos HTTP (GET, POST, DELETE, PUT, OPTIONS, etc) según la operación que vayan a realizar, mientras que con GraphQL usaras solamente POST si así lo deseas, un endpoint para gobernarlos a todos 😉

Todo bien hasta aquí, pero no me haz dicho realmente cual es el beneficio de usar esta tecnología

Tranquilo pequeño saltamontes, consideremos el caso siguiente:

Del lado izquierdo tenemos un cliente que hace una petición GET a un endpoint de álbumes pasando un id para obtener sus assets, posteriormente por cada uno de esos assets solicita los comentarios (múltiples peticiones al servidor), adicionalmente los objetos JSON que reciba en las respuestas siempre tendrán los mismos atributos.

Del lado derecho vemos la petición POST equivalente para un endpoint basado en GraphQL, como podemos observar en el mismo payload de nuestra petición estamos indicando el formato de respuesta que queremos que el servidor nos regrese, atributos en los objetos, etc.

Habra quien diga que puede ingeniárselas para que la petición defina la respuesta del servidor, regresar atributos dinámicamente, etc. y le creo pero buena suerte manteniendo algo como esto 🙂

GET /albums/1/assets/comments/?include=asset.name,comment.author,comment.text

Este es precisamente el problema que GraphQL resuelve, GraphQL nos permite definir relaciones entre las entidades de nuestra aplicación e inyectar esos objetos relacionados en las respuestas cada vez que el cliente lo pida.

El siguiente ejemplo de código esta basado en Javascript utilizando expressJS, supongamos que el cliente necesita desplegar en su frontend un objeto como el siguiente:

Un objeto película con datos como su nombre, el año y la calificación de la critica, adicionalmente también queremos los datos de los actores involucrados y los comentarios de los visitantes que han visto esa pelicula.

Manos a la obra, vamos a iniciar un nuevo proyecto con NodeJS

$ npm init
$ npm install --save express express-graphql graphiql graphql

Adicionalmente me gusta definir algunos comandos e instalar algunas dependencias para tener soporte es6, aquí pueden ver como queda mi package.json al final.

La estructura del proyecto es mas o menos la siguiente (demo-server)

Los archivos y carpetas mas importantes son:

  • app.js es nuestro entry point
  • graphql es la carpeta donde guardaremos nuestros “objetos QL”
  • data es la carpeta donde tendremos algunos objetos de ejemplo que simulan registros de la base de datos

Vamos a comenzar con el objeto Movie (película), en la carpeta graphql creamos un nuevo archivo llamado movieQL.js

import {
  GraphQLObjectType,
  GraphQLInt,
  GraphQLString,
  GraphQLList,
  GraphQLBoolean,
  GraphQLNonNull,
  GraphQLFloat,
} from 'graphql';

import actorQL from './actorQL';
import commentQL from './commentQL';

const movieQL = new GraphQLObjectType({
  name: 'movieQL',
  description: 'This is a movie QL object',
  fields: () => {
    return {
      name: {
        type: GraphQLString,
        resolve(movie) {
          return movie.name;
        }
      },
      score: {
        type: GraphQLFloat,
        resolve(movie) {
          return movie.score;
        }
      },
      year: {
        type: GraphQLInt,
        resolve(movie) {
          return movie.year;
        }
      },
      actors: {
        type: new GraphQLList(actorQL),
        resolve(movie) {
          return movie.actors;
        }
      },
      comments: {
        type: new GraphQLList(commentQL),
        resolve(movie) {
          return movie.comments;
        }
      },
    }
  }
});

export default movieQL;

Como podemos observar al inicio estamos haciendo import de varios módulos que representan tipos de datos escalares en graphQL, adicionalmente hacemos import de otras 2 entidades de nuestra aplicación, actorQL.js y commentQL.js, después en el atributo fields de nuestro objeto movieQL definimos varios campos del mismo junto con su tipo y aqui viene lo mas importante, definimos actors como una lista de tipo actorQL y comments como una lista de tipo commentQL, el código de las otras entidades es bastante similar al de movieQL por lo que no lo pondre en el post, pueden revisarlo en el repositorio: actorQL.js y commentQL.js

Queries y mutations

Otro de los conceptos básicos en graphQL son las queries y las mutations, existe toda una teoría detrás pero en resumen:

  • Queries: nos permiten leer datos del servidor (por lo general extraídos de una db)
  • Mutations: Crear / modificar / borrar datos en el servidor

Dentro de la misma carpeta graphql vamos a crear 2 nuevos archivos, queryQL.js y mutationQL.js

import {
  GraphQLObjectType,
  GraphQLList,
  GraphQLString,
  GraphQLInt,
  GraphQLBoolean
} from 'graphql';

import movieQL from './movieQL';
import { movies } from '../data';

const query = new GraphQLObjectType({
    name: 'Query',
    description: 'This is the root Query',
    fields: () => {
      return Object.assign({
        getMovies: {
          type: new GraphQLList(movieQL),
          args: {},
          resolve(root, args, request) {
            // do some db queries
            return movies;
          }
        },
      });
    },
});

export default query;

Para efectos de que esto es un demo no estamos utilizando ningún orm para conectarnos a alguna base de datos, pero ustedes son libres de elegir e implementar el que mas le guste, de la misma forma que en movieQL.js definimos los fields aquí estamos definiendo nuestros “endpoints”, por ejemplo estamos diciendo que getMovies es una query que nos regresara una lista de movieQL y estamos haciendo return del objeto movies (que es un objeto de ejemplo que importamos de la carpeta data).

De la misma forma dentro de mutationQL.js declaramos una operación llamada createMovie que nos retornara un objeto tipo movieQL (después de haberlo creado), la parte importante aquí es que por lo general los mutations reciben argumentos (name, year, score, lista de actores, lista de comentarios) y de nuevo, para efectos de que esto es un demo no estamos haciendo nada con los datos que nos enviá el usuario, simplemente los regresamos en la respuesta.

import {
  GraphQLObjectType,
  GraphQLInt,
  GraphQLString,
  GraphQLNonNull,
  GraphQLList,
  GraphQLInputObjectType,
  GraphQLBoolean,
  GraphQLFloat,
} from 'graphql';

import movieQL from './movieQL';

const actorInputQL = new GraphQLInputObjectType({
  name: 'actorInputQL',
  fields: {
    name: { type: GraphQLString },
    age: { type: GraphQLInt },
    country: { type: GraphQLString },
  },
});

const commentInputQL = new GraphQLInputObjectType({
  name: 'commentInputQL',
  fields: {
    user: { type: GraphQLString },
    commentary: { type: GraphQLString },
    timestamp: { type: GraphQLString },
  },
});

const mutation = new GraphQLObjectType({
  name: 'Mutation',
  description: 'This is the root Mutation',
  fields: () => {
    return Object.assign({
      createMovie: {
        type: movieQL,
        args: {
          name: {
            type: new GraphQLNonNull(GraphQLString),
          },
          year: {
            type: GraphQLInt,
          },
          score: {
            type: GraphQLFloat,
          },
          actors: {
            type: new GraphQLList(actorInputQL),
          },
          comments: {
            type: new GraphQLList(commentInputQL),
          },
        },
        resolve(root, args, request) {
          // do something here
          return args;
        },
      },
    });
  },
});

export default mutation;

Hasta aquí ya tenemos definidos nuestros queries y mutations de ejemplo, ha llegado el momento de definir un schema de graphQL e integrar todo con express, es bastante sencillo, comenzamos creando un archivo llamado schemaQL.js también dentro de la carpeta graphql

import { GraphQLSchema } from 'graphql';
import queryQL from './queryQL';
import mutationQL from './mutationQL';

const schemaQL = new GraphQLSchema({
  query: queryQL,
  mutation: mutationQL,
});

export default schemaQL;

Como podemos ver, simplemente importamos los modulos de queryQL y mutationQL y finalmente en nuestro entry point (app.js) mandamos llamar a graphQL con el schema recién creado.

import express from 'express';
import GraphHTTP from 'express-graphql';
import schemaQL from './graphql/schemaQL';

var app = express();

app.use('/graphiql', GraphHTTP({
    schema: schemaQL,
    pretty: true,
    graphiql: true
}));

app.use('/graphql', GraphHTTP({
    schema: schemaQL
}));

app.get('/', function (req, res, next) {
  const reponse = {
    message: 'hello world',
  };
  return res.json(reponse);
});

module.exports = app;

Notaran que tenemos definidos 2 endpoints, graphql y graphiql. GraphiQL es una herramienta bastante útil que viene con el modulo de graphQL, se trata de una pequeña interfaz web desde donde podemos probar nuestras queries y mutations y la cual nos genera una documentación con base en los objetos QL de nuestro código, por ejemplo para probar nuestra query de getMovies seria algo como lo siguiente:

Observen que del lado izquierdo estoy definiendo los atributos que quiero que contengan los objetos de la respuesta, puedo solicitar mas o menos dependiendo de lo que el cliente pida, ayudando bastante a, por ejemplo, reducir el tamaño de los mensajes si la petición se hace desde un cliente móvil.

De la misma forma podemos probar nuestro mutation por medio de graphiQL

Observen como desde el cliente podemos pasar directamente el objeto con sus atributos, incluso los objetos relacionados como la lista de actores y comentarios, ya es cuestión de procesar todo eso en nuestro backend y crear los registros en la base de datos.

Todo bien hasta el momento, ya sabemos utilizar graphiQL, ahora como usamos nuestra api ya en un proyecto real, muy sencillo, cada vez que hacemos un request en google developer toolbar podemos observar cual es el payload que se enviá al servidor:

Podemos tomar ese mismo payload y con la ayuda de POSTMAN enviarlo como raw body a nuestro endpoint de graphQL en /graphql

Observa como el POST request va dirigido a /graphql y no /graphiql, por ultimo desde el mismo POSTMAN podemos ver cual seria el HTTP request generado haciendo clic en el boton code

Finalmente lo único que queda es implementar ese request en tu lenguaje de programación / framework favorito, a continuación dejo la presentación que utilice durante el evento por si necesitan revisarla asi como el repositorio de github donde esta alojado el código de este demo: graphql demo server

Código de 50% de descuento para #cpartymx4!

Hola amigos en esta ocasión les traigo un código de 50% de descuento para todos los usuarios de las comunidades afiliadas a Campus Party! El código es:

cpmx4comunidadesmayo

¿Como activo el código?

Accede a tu cuenta de campusparty, si aun no estas registrado corre y registrate

Captura de pantalla 2013-05-09 a la(s) 13.08.36

Una vez dentro de tu cuenta, accede a comprar tu entrada

Captura de pantalla 2013-05-09 a la(s) 13.13.51

Te aparecerá un botón con la leyenda “Comprar con descuento” haz clic en el

Captura de pantalla 2013-05-09 a la(s) 13.16.06

Por ultimo introduce el código de 50% de descuento para asistir a campusparty México

cpmx4comunidadesmayo

Captura de pantalla 2013-05-09 a la(s) 13.18.15

De manera paralela, Campus Party ha habilitado un micrositio para regalar pases gratis en en la siguiente dirección

salu2

@Chopapp para compartir código fuente

Después de un largo descanso …. Chop es una curiosa herramienta desarrollada por ZURB que te permite compartir snippets (trozos de código fuente) y recibir retro alimentación, si quieren saber por que esta app es bastante interesante les recomiendo seguir leyendo :).

chop

La idea es bastante simple y divertida, en el caso de querer mostrar nuestro codigo a alguna otra persona (similar a otros servicios como copypastecode o pastebin) y recibir algun tipo de retroalimentación tan solo tenemos que copiarlo en el formulario, elegir el lenguaje de programación adecuado y usar el botón de Chop It!, ejemplo:

chop_example1

Una vez hecho esto la aplicación nos pedirá un nombre de usuario y a continuación nos dará un link con el cual nuestros amigos podrán ver y opinar sobre nuestro código :), lo mas interesante de esta aplicación a diferencia de muchas otras que existen en el mercado es que nos permite realizar comentarios sobre el código línea por línea y no un comentario general, desde mi punto de vista es una forma bastante interesante de innovar y mejorar respecto a servicios ya existentes. El resultado final es algo como esto:

chop_example_2

Si quieren mantenerse informados sobre el desarrollo de esta aplicación pueden seguir a @chopapp