GithubHelp home page GithubHelp logo

uclaacm / teach-la-go-backend Goto Github PK

View Code? Open in Web Editor NEW
8.0 12.0 6.0 438 KB

๐ŸŒฑ Go Backend for Teach LA's Editor

Home Page: https://documenter.getpostman.com/view/10224331/TW6xmnn2

License: MIT License

Go 99.60% Makefile 0.37% Procfile 0.03%
backend go golang education teach-la

teach-la-go-backend's People

Contributors

alyssamw avatar andrewpan07 avatar anvig25 avatar arshmalik02 avatar dependabot[bot] avatar jason2020 avatar jonathanbcarlson avatar joshsi avatar joycechen721 avatar krashanoff avatar mattxwang avatar megang33 avatar mizlan avatar reginawang3495 avatar samarthupadhyaya27 avatar tfukaza avatar timothycpoon avatar trevorong avatar victorwen avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

teach-la-go-backend's Issues

Add test code for classes and hashing

Currently class.go lacks a dedicated, comprehensive test code. We need test code to ensure functions like JoinClass works properly. Similarly, alias_manager only has a single test case - ideally there should be more, not only to test the functionality, but to test how much load it can withstand.

DB#JoinCollab Endpoint

Following creation of a collaborative session as described in #30, an user must be able to join the session and work on the code together. This endpoint should match the route GET /collab/join/:sid, where :sid is the Session ID of the collaborative session.

Following initiation of a websocket connection, the client shall be considered to have joined.

Additional language support

This is a largely freeform issue. We would like to add more languages to the backend. For example, compiled languages. This is a moonshot goal, though.

Assigned to @lumisphere902.

DB#CreateCollab Endpoint

To start a collaborative coding session, we're going to need to create an endpoint that will set up a session's websocket, and arbitrate the editor events between the two.

All this endpoint needs to do that's special is forward editor events from one client to the others, and handle save events for the program they are all working on.

For more reading, take a look at echo's documentation on websockets.

For some starter code, please review the collab branch.

Add transaction to CreateProgram

Whenever we create a program, we want to ensure that it is associated to a user profile. Currently, the CreateProgram function in handler/db.go does both operations separately. To do this, we should create a new function in db/db.go which both creates a program and associates it with a user. For inspiration, you can look at ForkProgram in db/program.go.

CLI prep

Right now, the extent of our backend's CLI is a single line that the user can run. Errors are reported to stdout, but past that, the backend executable is pretty slim. This isn't good for people who aren't looking to build the backend themselves or dig down into the code to understand how it works. It also doesn't make our lives phenomenal as it absconds verbosity changes, port number, networking behavior behind a complete rebuild process. To address this, we should create a proper CLI.

This issue will track the prep work for this.

CLI Library

The first issue is which library to use. Go has a ton of great CLI libraries out there, but I'd like to use urfave's cli. This one is a more feature-rich alternative to the stdlib. It is also under active development, which is always nice. Great guide on its manual page.

How to implement

  • Modularize the portion of our current main routine that calls the server. Make it into another function that takes relevant args that we extract from our CLI lib.
  • Create the basic app
  • Register our core flags to the app (with defaults).
    • Port
    • Verbosity
  • Read flags in main routine (via cli#Context) and apply to echo instance accordingly.

The below information are future features


CLI Options

Next thing to tackle is which options to give the user. Here are a few that come to mind, and will spawn their own tickets in due time.

    --no-cors, -n: Disable CORS middleware.
    --creds, -c: Provide a path to the database credentials being used (defaults to `.env` and `*.json`, in that order).
    --verbose, -v: Change the log level used by echo's logger middleware.
    --port, -p: Change the port number.
    --logfile, -l: Change the file logged to

Fix deleting a user created program from the page

Description of the bug

When a user creates a new program and then tries to delete it, the program is not removed from the page. Essentially, nothing visible happens on the page. However, on refreshing the page, the program is removed.

Add an API for submitting sketches to a class

This would involve adding an API(s) to handler/class.go for submissions. This API would take in two PIDs (program IDs), a CID (class ID), and a UID (ID of the submitting user). For now, this API can call a mock function of the DB class which does nothing. The two PIDs correspond to the submission (student's program), and the assignment (teacher's program). The schema should match that of #97, but with the addition of the CID.

Your code should look similar to JoinClass up to line 192 or so, but with the correct inputs. The rest of the function can just be a comment or a dummy function call.

DB#AddComment Endpoint

Before we actually add anything in terms of collaborative coding to the editor, we're going to want to add something a bit simpler. Let's start with Google Docs-style comments on programs.

For the backend, this should be pretty straightforward, just add a new property to our Program struct that updates the comments on it.

The description of a comment is still a little freeform, but here's my intuition as to what it should have:

type Comment struct {
    Author string `json:"author" firebase:"author"`
    Start int `json:"start" firebase:"start"`
    End int `json:"end" firebase:"end"`
}

Since we store program contents as a single string, we can just bind the comment to a range of characters in the sketch. The frontend will be in charge of updating the comments.

This new type would be nested within our Program type:

type Program struct {
    // ...
    Comments []Comment `json:"comments" firebase:"comments"`
}

JoinClass failing

I tried running the JoinClass (/class/join endpoint) and I think it's breaking because wid is mixed up with cid in the req struct. I think this also might be part of why Class tests are breaking

response: 404 Not Found: alias does not correspond to a class ID

DB#CreateCollab Extensions

As a follow-up to the changes made in #32, we should futureproof and extend the interface with a way to create a session with a specific name, failing if the session already exists. This would be a good feature for teachers who want to keep their collaborative session IDs readable. For example:

POST .../collab/create
{
    "name": "my session", // Optional field, defaults to random UUID.
    "uid": "..."
}

Then, the response would be 201 Created if the session was created with the name, and 400 Bad Request if the request failed (and the session already existed).

Binary release prep

It's no mystery that installing and configuring a Go development environment is a nontrivial task for new developers who are unfamiliar with the command line. One of the great parts of Go (or awful parts, if you aren't a fan of slightly larger binaries) is that all binaries are statically linked. I'm sure you can see where I'm going with this.

Binary Releases

I'd like for us to release the backend in semver'd binaries. It means that frontend devs don't have to worry about setting up a working Go environment, installing our dependencies, building the project, and doing anything extra. Instead, they can just download a precompiled binary with our staging credentials.

What needs to be done?

  • Add a Makefile to build the backend for all relevant targets. The process of creating this should be pretty straightforward, and is a good way for new devs to familiarize themselves with the Go toolchain. Find a good resource on how to build for alternative targets here, and a good Go template Makefile here.
  • Change our README to reflect the new changes.

This will be part of a larger focus on improving the backend's CLI and beginner-friendliness.

Add a "submissions" field to the class object

To allow student to submit their programs to the instructors, we need to store these submissions somewhere, such as an array within the class object. Each submission in the array should include:

{
  submissionPID: string,  // PID of the program being submitted
  assignmentPID: string, // PID of the program/assignment this is being submitted to. Potentially optional
  uid: string, // UID of the submitting user
}

Additionally, submissions should only be retrieved by the GetClass function if the requesting user is an instructor, or was the one who submitted it (this can be done at a later time). One potential way of storing these submissions within the class object would be to add a subcollection (see this). Another way would be to use a simple array. This should be less scalable but have less overhead, which may be preferable for our use case

Overall, the important part of this ticket would be to create the struct within db/class.go and to modify the LoadClass and function in db/db.go to load the subcollection as well. Instead of modifying the existing functions for modifying the subcollection, you can add new functions which only interact with the submissions (e.g. AddClassSubmission, DeleteClassSubmission, etc.)

New endpoint DB#GetClassMembers

Teachers and students should be able to view their class' members. We can facilitate this through a new endpoint, POST /class/members. The class CID should be passed in the request body, along with the UID of the user requesting it. We validate this UID is in the class, then provide the requester with the user IDs and display names of each member in said class. For example:

// POST /class/members
{
  "cid": "SOME_CID",
  "uid": "SOME_UID",
}

This will return:

{
  "USER_ID0": {
    "userField0": "...",
    "userField1": "..."
  },
  "USER_ID1": {
    ...
  }
}

Teacher message passing

Teachers should be able to request to view the latest version of their student's work, and receive live updates. To do this, they should send a message of the form:

{
  "type": "READ",
  "target": "some_uid"
}

This will cause the backend to enter a state of propagating packets from the given target to the owner, and forwarding packets from the owner to the given target. For example, consider the following pseudocode:

out := read(someSocket)

if someSocket == owner {
    // forward all packets from owner to target.
    // receive packets from target, forward to owner.
}

This issue depends on #42, and may spawn another issue to abstract client connections on top of Go's websockets (for improved routing behavior).

Add a new "assignment" object associated with classes

The assignment object should contain a reference to a program, as well as potential metadata. For the initial iteration, just a list of program IDs should be sufficient. I believe the most appropriate data structure would be a sub-collection of class documents, but an argument can also be made for a new root-level collection. In this case, a reference to a class would also be needed.

Assignment {
  PID: string
  submissions: string[]
}

Refactor DB type to an echo.Context.

This is a tracking issue.

If you take a look over at my work on krashanoff/db-context, you can see that we are refactoring our endpoints to be detached from our database operations. We do this by wrapping a connection to the database in a custom echo context (read more here) we pass to our handlers via custom middleware.

At present, the interface is fairly stable. We just need to concern ourselves with rewriting handlers to use the new context rather than making them member functions of the db#DB type.

Right now, only the GetUser handler has been modified.

Fix TestCreateProgram/AddToClass

In its current state, the AddToClass functionality of CreateProgram appears to be broken. We know that this is not the case through manual tests, but checking on our test output, we can see it has to do with using a pointer rather than its dereference:

pointer is not contained in some UID

Should be a quick fix.

Gate users; developer accounts.

For the User struct, a new field should be added that checks whether the User is a developer account or not. This can be a simple bool for the data type.

The code you would want to look at is here.

I suggest a change like this:

// User is a struct representation of a user document.
// It provides functions for converting the struct
// to firebase-digestible types.
type User struct {
	Classes           []string `firestore:"classes" json:"classes"`
	DisplayName       string   `firestore:"displayName" json:"displayName"`
	MostRecentProgram string   `firestore:"mostRecentProgram" json:"mostRecentProgram"`
	PhotoName         string   `firestore:"photoName" json:"photoName"`
	Programs          []string `firestore:"programs" json:"programs"`
	UID               string   `json:"uid"`
        DeveloperAcc    bool    `firestore:"developerAcc" json:"developerAcc"`
}

Collaborative session ownership.

Each collaborative session should have an owner, who we will denote the teacher. This teacher will have an editor that is viewable by all members in the session (via sending a packet to the server). The teacher will also be able to edit their students' editors by sending packets.

However, prior to all of this, we must establish who is the owner of the session. I'm thinking we add the following to our session struct:

type Session struct {
	// Map UIDs to their websocket.Conn
	Conns map[string]*websocket.Conn
        Teacher string
	Lock  sync.Mutex
}

The first person who joins a session can be made the owner, or the creation request can be modified to accommodate the new field. I leave this at the discretion of the implementer.

Following this, we can start forwarding packets between teacher and student, and roll from there.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.