{"id":18989409,"url":"https://github.com/source-academy/backend","last_synced_at":"2026-02-19T14:11:31.492Z","repository":{"id":37825555,"uuid":"118212478","full_name":"source-academy/backend","owner":"source-academy","description":"Backend of Source Academy @ NUS, LMS extension of Source Academy (Elixir, Ecto, Phoenix, PostgreSQL)","archived":false,"fork":false,"pushed_at":"2026-02-12T10:49:38.000Z","size":8038,"stargazers_count":43,"open_issues_count":88,"forks_count":62,"subscribers_count":5,"default_branch":"master","last_synced_at":"2026-02-12T19:19:22.770Z","etag":null,"topics":["backend-api","elixir","hacktoberfest","source-academy"],"latest_commit_sha":null,"homepage":"https://sourceacademy.nus.edu.sg","language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/source-academy.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2018-01-20T05:32:02.000Z","updated_at":"2026-02-12T10:44:12.000Z","dependencies_parsed_at":"2023-11-29T06:27:41.811Z","dependency_job_id":"d6a727ba-b980-4f4a-a0f2-357174e46e4c","html_url":"https://github.com/source-academy/backend","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/source-academy/backend","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/source-academy%2Fbackend","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/source-academy%2Fbackend/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/source-academy%2Fbackend/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/source-academy%2Fbackend/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/source-academy","download_url":"https://codeload.github.com/source-academy/backend/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/source-academy%2Fbackend/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29617024,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-19T13:04:20.082Z","status":"ssl_error","status_checked_at":"2026-02-19T13:03:33.775Z","response_time":117,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["backend-api","elixir","hacktoberfest","source-academy"],"created_at":"2024-11-08T17:06:36.756Z","updated_at":"2026-02-19T14:11:31.475Z","avatar_url":"https://github.com/source-academy.png","language":"Elixir","readme":"# Cadet\n\n[![Build Status](https://travis-ci.org/source-academy/backend.svg?branch=master)](https://travis-ci.org/source-academy/backend)\n[![Coverage Status](https://coveralls.io/repos/github/source-academy/backend/badge.svg?branch=master)](https://coveralls.io/github/source-academy/backend?branch=master)\n[![Inline docs](https://inch-ci.org/github/source-academy/backend.svg)](http://inch-ci.org/github/source-academy/backend)\n[![License](https://img.shields.io/github/license/source-academy/backend)](https://github.com/source-academy/backend/blob/master/LICENSE)\n\nCadet is the web application powering Source Academy.\n\n- `master` is the main development branch, and may be broken, buggy, unstable, etc. It may not work with the frontend, if there are frontend changes that have not yet been merged.\n- `stable` is the stable branch and should work with the stable branch of the frontend. Note that `stable` may not have stable history!\n\n## Developer setup\n\n### System requirements\n\n1. Elixir 1.19+ (current version: 1.19.5)\n2. Erlang/OTP 28+ (current version: 28.3.1)\n3. PostgreSQL 12+ (tested to be working up to 18)\n\nIt is probably okay to use a different version of PostgreSQL or Erlang/OTP, but using a different version of Elixir may result in differences in e.g. `mix format`.\n\n\u003e ## Setting up PostgreSQL\n\u003e\n\u003e The simplest way to get started is to use Docker. Simply [install Docker](https://docs.docker.com/get-docker/) and run the following command:\n\u003e\n\u003e ```bash\n\u003e docker run --name sa-backend-db -e POSTGRES_HOST_AUTH_METHOD=trust -e -p 5432:5432 -d postgres\n\u003e ```\n\u003e\n\u003e This configures PostgreSQL on port 5432. You can then connect to the database using `localhost:5432` as the host and `postgres` as the username. Note: `-e POSTGRES_HOST_AUTH_METHOD=trust` is used to disable password authentication for local development; since we are only accesing the database locally from our own machine, it is safe to do so.\n\n### Setting up your local development environment\n\n1. Set up the development secrets (replace the values appropriately)\n\n   ```bash\n   cp config/dev.secrets.exs.example config/dev.secrets.exs\n   vim config/dev.secrets.exs\n   ```\n\n2. Install Elixir dependencies\n\n   ```bash\n   mix deps.get\n   ```\n\n   If you encounter error message `Fail to fetch record for 'hexpm/mime' from registry(using cache insted)`The following instruction may be useful for you.\n\n   ```bash\n   mix local.hex --force\n   ```\n\n3. Initialise development database\n\n   ```bash\n   mix ecto.setup\n   ```\n\n   By default, the database is populated with 10 students and 5 assessments. Each student will have a submission to the corresponding submission. This can be changed in `priv/repo/seeds.exs` with the variables `number_of_students`, `number_of_assessments` and `number_of_questions`. Save the changes and run:\n\n   ```bash\n   mix ecto.reset\n   ```\n\n4. Run the server on your local machine\n\n   ```bash\n   mix phx.server\n   ```\n\n5. You may now make API calls to the server locally via `localhost:4000`. The API documentation can also be accessed at \u003chttp://localhost:4000/swagger\u003e.\n\nIf you don't need to test MQTT connections for remote execution using [Sling](source-academy/sling), you can stop here. Otherwise, continue to [set up the local development environment with MQTT](#setting-up-a-local-development-environment-with-mqtt-support).\n\n### Setting up a local development environment with MQTT support\n\nIn addition to performing the steps [above](#setting-up-your-local-development-environment), you will need to do the following:\n\n1. Set up a local MQTT server.\n\n   One cross-platform solution is Mosquitto. Follow their [instructions](https://mosquitto.org/download/) on how to install it for your system.\n\n2. Update Mosquitto configurations\n\n   We will require two listeners on two different ports: one for listening to the WebSockets connection from Source Academy Frontend, and one to listen for the regular MQTT connection from the EV3. Locate your `mosquitto.conf` file, and add the following lines:\n\n   ```conf\n   # Default listener\n   listener 1883\n   protocol mqtt\n   allow_anonymous true\n\n   # MQTT over WebSockets\n   listener 9001\n   protocol websockets\n   allow_anonymous true\n   ```\n\n   If necessary, you can change the default port numbers, but it is generally best to stick to the default MQQT/WS ports.\n\n3. Restart the Mosquitto service to apply configuration changes\n\n4. Update configurations in the `config/dev.secrets.exs` file\n   Scroll down to the `remote_execution` section near the bottom of the page, uncomment the two keys below, and update their values. Take note that the port numbers should match what you have defined earlier in `mosquitto.conf`.\n\n   - `endpoint_address`: The address the remote device (EV3) should connect to.\n\n     **Example:** `\"192.168.139.10:1883\"`\n\n   - `ws_endpoint_address`: The address the frontend should connect to.\n\n     **Example:** `\"ws://localhost:9001\"`\n\n     Take note that you need to include the `ws://` prefix.\n\n   \u003e **Sidenote on connecting from the EV3**\n   \u003e\n   \u003e Although this value is returned to the remote device, the EV3 uses a hardcoded endpoint value, and simply discards this return value. Hence, the actual value does not matter. However, we still need to set (uncomment) `endpoint_address` to stop the backend from connecting to AWS.\n\nYour backend is now all set up for remote execution using a local MQTT server. To see how to configure the EV3 to use a local MQTT server, check out the [EV3-Source](https://github.com/source-academy/ev3-source) repository.\n\n### Obtaining `access_token` in dev environment\n\nYou can obtain an `access_token` JWT for a user with a given role by simply running:\n\n```bash\nmix cadet.token \u003crole\u003e\n```\n\nFor more information, run\n\n```bash\nmix help cadet.token\n```\n\n### Style Guide\n\nWe follow this style guide: \u003chttps://github.com/lexmag/elixir-style-guide\u003e and \u003chttps://github.com/christopheradams/elixir_style_guide\u003e\n\nWhere there is a conflict between the two, the first one (lexmag) shall be the one followed.\n\n## Entity-Relationship Diagram\n\nGenerated with [DBeaver](https://dbeaver.io/) on 19 May 2024\n\n![Entity-Relationship Diagram for cadet](schema.png)\n\n## License\n\n[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)\n\nAll sources in this repository are licensed under the [Apache License Version 2][apache2].\n\n[apache2]: https://www.apache.org/licenses/LICENSE-2.0.txt\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsource-academy%2Fbackend","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsource-academy%2Fbackend","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsource-academy%2Fbackend/lists"}