Week 1 & 2- CircuitVerse@GSOC'23

Week 1 & 2- CircuitVerse@GSOC'23

CircuitVerse X GSoC - Coding period report - Arnab Das

·

7 min read

Hello, everyone this is my first blog for GSoC 23 coding period.

Community Bonding Period

The community bonding period starts from the day when we receive the acceptance email from Google. During the community bonding period, all the members and contributors had meets to introduce each other and their projects. next, we had individual meets with our mentors to know each other better and also discuss about the project. we had discussions about any changes in the timeline and also about any better ways to implement the project.

my tasks during the community bonding period were:

  • gaining a deeper knowledge of the codebase

  • some research about other possible alternatives for some parts of project implementation.

After the community bonding period, the official coding period begins on 29th May 2023


Goal of first two weeks:

  1. Integration of Vue simulator with main repository

  2. Creation of new API endpoints for Vue simulator


Week 1: integration of Vue simulator repo with the main repository

due to timeline changes during the community bonding period, I decided to start working on week 1 and week 2 tasks together. but I am writing both separately for better understanding.

preface: currently the semi-developed vue simulator is kept in a separate repository isolated from the main repository. So, the first task is to connect both of them in order for the Vue simulator to be functional and get deployed.

constraints: there were multiple ways to integrate the vue simulator with the main repository but our target was to keep the vue simulator code independent of the main repository so that it can be developed in isolation in the future.

implementation: keeping the above constraints in mind we decided to use git submodules for the integration.

step 1: git submodule add https://github.com/CircuitVerse/cv-frontend-vue.git
this adds the vue simulator repository to the main repo as a submodule.
we see two new files

  • cv-frontend-vue directory: this is where we would get the code of Vue simulator

  • .gitmodules this file is like a config file for the git submodules we add to our repo

step 2: git submodule set-branch -b main cv-frontend-vue
with this, we set the submodule to track the branch main for cv-frontend-vue

step 3: git submodule update --init --remote
with this command, we initialize the submodule, set the submodule head to the latest commit on the main branch and clone the cv-frontend-vue repo.

Step 4: Finally we commit and push the changes.

setup for the development and build of the vue simulator with the main repository:

for the build of the simulator, I configured vite to put the static build files of the vue simulator in the public/simulatorvue directory of the main repository.

step 1: update the vite.config.js by adding the following:

base: '/simulatorvue/',
    build: {
        outDir: '../public/simulatorvue',
        assetsDir: 'assets',
        chunkSizeWarningLimit: 1600,
    },

step 2: define a route for the simulator:

get "/simulatorvue/*path", to: "vuesimulator#simulatorvue" # change to /simulator later define a new controller at app/controllers/vuesimulator_controller.rb for handling the route.
now we can access the Vue simulator once build.

for dev environment I decided to have two ways:

  1. using vite build --watch along with the current setup to run the project from a single dev server.

    here I updated the esbuild.config.js file to fetch all the updates in the submodule, do npm install and npm run build when we start the dev server with bin/dev. I added one environment variable BUILD_VUE to set either to build or not build the vue simulator when you start the dev server.

    • all changes can be found in pr 3774

    • maybe modified or changed in the future after the GSoC projects regarding dev and production improvements finish.

  2. using vite proxy to proxy all requests from other paths than the vue simulator's path, to the rails dev server.

    although the development of the Vue simulator is possible with the previous implementation, we lose Vite's HMR (hot module replacement). for this, we have the second development approach where we run the main dev server and the Vite dev server together but proxy non-vue simulator requests to the main server.

    • to implement this we add proxy settings in vite.config.js as

        // ... no changes
        const proxyUrl:string = 'http://localhost:3000';
      
        export default defineConfig({
        // ... no changes in between
        server: {
                port: 4000,
                proxy: {
                        '^/(?!(simulatorvue)).*': {
                            target: proxyUrl,
                            changeOrigin: true,
                            headers: {
                                origin: proxyUrl,
                          },
                     },
                },
            },
      

      with this, we set up Vite proxy all requests other than the path /simualtorvue/(catch_all*) to the set proxyUrl.

      also, we define the port for the Vite server to start at 4000 by default instead of 3000 to not interfere with rails server.

    • for now, only one path is added to not be proxied but in future, more might be added so always refer to the latest vite config.

other miscellaneous changes:

  • update the docker-compose.yml and procfile.dev for the first implementation of dev server.

Week 2: creation of new API endpoints and implementation of JWT in the CircuitVerse site.

preface: as our current target is of making the new simulator independent of the rails counterpart we move toward a fully API-driven application, and for authentication, we move from the current cookie-based system to JWT.

implementation: creating new API endpoints in the api/v1 format:

step 1: Create a new simulator_controller.rb in app/controllers/api/v1 directory.
step 2: add the new api methods in the file as in here
step 3: add the required helper in app/helpers/api/v1/simulator_helper.rb as in here
step 4: finally adding new routes to routes.rb as in here

  • the created new api endpoints in api/v1 format:

  • GET api/v1/simulator/:id/edit use: check project edit access and load simulator in edit mode accordingly

  • GET api/v1/simulator/:id/data use: get project circuit data only if project viewing access is there

  • PATCH api/v1/simulator/update use: update circuit data for a project with edit access

  • POST api/v1/simulator/create use: create a new project with circuit data and provided name

  • POST api/v1/simulator/post_issue use: post user issues and send to slack (as per current implimentation)

  • POST api/v1/simulator/verilogcv use: send post request to yoyos server and get circuit data from verilog code

  • any other API endpoints would be added later as per requirement for latest APIs check CircuitVerse api docs

Adding JWT authentication to circuitverse web:

Circuitverse uses devise to handle the authentication so to generate and save JWT it is implemented along with the current devise authentication methods.
for the encoding and stroing jwt during sign_in we update the session_controller.rb as

  # POST /resource/sign_in
  def create
    super do |user|
      # Check if 'Remember me' is selected
      remember_me = params.dig(:user, :remember_me) == "1"

      # Generate JWT token
      token = JsonWebToken.encode(
        { user_id: user.id, username: user.name, email: user.email },
        remember_me: remember_me
      )

      cookie_options = {
        value: token,
        httponly: true,
        secure: Rails.env.production?,
        same_site: :strict
      }

      # Set cookie expiration
      cookie_options[:expires] = 2.weeks.from_now if remember_me

      # Set JWT token as cookie
      cookies[:cvt] = cookie_options
    end
  end

and for sign_up we update registrations_controller.rb as:

  # POST /resource
  def create
    super do |user|
      if user.persisted?
        # Generate JWT token
        token = JsonWebToken.encode({ user_id: user.id, username: user.name, email: user.email }, remember_me: false)

        # Set JWT token as cookie
        cookies[:cvt] = {
          value: token,
          httponly: true,
          secure: Rails.env.production?,
          same_site: :strict
        }
      end
    end
  end

for handling sign_out we simply delete the jwt token from cookies as of now which would be improved in future

  # DELETE /resource/sign_out
  def destroy
    super do
      # Remove the JWT token cookie
      cookies.delete(:cvt)
    end
  end

the JWT handling in browser is described below:

  • create and save JWT as cookie on:

    • sign_up (1-day validity)

    • sign_in (1-day validity if not remember me / if remember me then 2 weeks validity)

  • destroy/delete saved cookie:

    • sign_out ( all cases )

    • browser close (when not remember me JWT gets deleted as session-based cookie)

for the JWT token configuration & changes, we add the length of the token expiry to be decided based on whether the user checked 'remember me' or not during login. changes can be found here

These are still under review so there might be further changes.