Skip Navigation
Tyrone Williams

CodePair

Summary

CodePair is a site for users to complete coding challenges together. Users are able to take challenges alone, or join a queue to be matched with another user.

Objectives

The main objective with this site was the challenge of running untrusted code safely. After using something like Codewars, I was curious on how other sites were tackling the issue and I enjoyed coding challenges so it seem like a good opportunity. I noticed that on many code challenge sites most of the user to user engagement was done in discussions or forums, so I thought giving the option to pair up with someone would be an interesting twist to explore.

Technologies and Tools

Front-end

  • React for front-end framework with Redux for state management.
  • Socket.io for sending and receiving chat messages and updates to the code editor.
  • Cypress for E2E testing.
  • Codemirror for code editor used in challenges.

Back-end

  • NodeJS for running both API server and code runner server.
  • MongoDB for database.
  • Redis for managing the challenge queues by tracking the number of users in different queues and matching users together.
  • Socket.io for sending and receiving chat and code editor updates between users.
  • Docker for running tests against user submitted code inside containers.
  • RabbitMQ (amqp) for sending messages between the API server and code running server.

Challenges

Several challenges exist when wanting to compile and/or run untrusted code from a user on your server. I wrote an article that describes the process used in this application in more details here, but the overall process is the following:

Flowchart
  1. User submits code to be tested to the client server.
  2. The client server encrypts the code and sends it, along with some other data, to RabbitMQ.
  3. The code runner server receives the message and decodes it. Then attempts to test code by launching a Docker container and running tests as secure as possible depending on language. The results are sent back through RabbitMQ.
  4. The client server receives the message and sends the results back to all clients in the room that request was made from.

By running the code on another server, the primary client server is protected from running any malicious code. The code runner server also times tests to prevent containers from being stuck in infinite looping code.

In order to test the user's code, a docker container is used to run tests safely depending on the language. The method to test the code will depend on the language. An example of this would be running NodeJs code through VM2 to provide a sandbox like environment.

Another challenge was creating a code editor. Initially, I tried to make my own before quickly realizing it would add much more time to the project than I wanted. After doing some research, I came across some discussion from people who worked on Codepen that mentioned they used Codemirror in the past (they might still use it). I decided to use Codemirror instead with the intention to decrease development time.