-
Notifications
You must be signed in to change notification settings - Fork 5
Using LCS
The LCS API presents itself, initially, as a user authentication system. So first and foremost, it is that. This means you can:
- Create users
- Log in users for a session.
- Have sessions carry on over time (there's a session token system)
- Update users
- Read user information and aggregate it.
In addition to the above features, there are a few extra things:
- An emailing system
- This is not essential but is really handy to support users forgetting their passwords. This deployment includes it, so it'll be documented. See the deployment stuff for more.
- QR codes.
- Announcement endpoints.
This has a few general ideas, not very many details. This discusses various aspects:
- API Overview with a TL;DR on the API endpoints.
- User Flow with the endpoints, MLH details, and logging out.
- User Privileges outlining the types of users and what they can do.
- The User Object explains the fields to be expected in a user. Also notes who can alter and read it. There is some detail on more advanced updates (forgotten passwords and promotions) too.
- The registration FSM with details on the meaning of each state.
- Relevant Mongo docs outlining the queries that can be made.
Endpoint URL | Use | Docs link |
---|---|---|
/attend-event | check a hacker into an event | Here |
/authorize | Log in a current user - gets a session token | Here |
/create | Create a new user | Here |
/validate | Validate a session token | Here |
/update | Update a user | Here |
/consume | Consume a magic link. Lets users update passwords or promote users | Here |
/createmagiclink | Lets a user make a magic link | Here |
/dayof-events | Read events at the hackathon | Here |
/dayof-slack | Read slack messages at the hackathon | Here |
/link-qr | link a qr to a hacker's account | Here |
/send-emails | Lets users (mostly administrators) send emails | Here |
/read | Can read any user information - depending on privilege | Here |
/resume | get resume upload/download link and see if resume is already uploaded | Here |
/slack-dm | create a slack dm link between self and another LCS user | Here |
/waiver | get waiver upload/download link and see if waiver is already uploaded | Here |
In general, users will go through the following flow:
- Log in
- Read information
- Respond
- Leave
Depending on when they left, they may have a valid session token and not need to login.
Hence, in terms of endpoints, the API would be invoked as:
- /authorize (or /validate if you're checking a token)
- Now you save the session token if you got a new one.
- /read
- /update (may be)
Note that leaving does not require an API call. The token itself will expire in 48 hours - then the user will be "logged out" unless a new session was started. Multiple sessions are OK.
MLH log in is an external source, so we do not have control over certain details. If you want to let people log in through MLH through LCS you need the following HTML:
<a href="https://my.mlh.io/oauth/authorize?client_id=<your client ID here>&redirect_uri=https://<your AWS API URL>/mlhcallback&response_type=code&scope=email+education+birthday"></a>
See the deployment instructions for how to get the client id.
See the MLH callback docs for more - you'll need to handle certain details with redirecting as LCS will re-direct back to you and needs to know how to.
A log in will handle the call to /mlhcallback for you and you'll be returned to with a session token in the URL. This is susceptible, we know, so please read the docs for more about this.
In running the hackathon, we find that users shouldn't be all-powerful: if there is a filtering process, wait-listing, or any case where a user many not be accepted into the hackathon, it would be useful to have different levels of users, so that organizers can use the system to maintain it.
Furthermore, it is nice to have a public API: sponsors have been known to ask for such things (non-identifiable information).
Hence, there are 3 LCS users:
- Public users: who can read parts of the API and don't have an account.
- Hackers: who have an account, but cannot make certain decisions.
- Organizers: who can do anything (from an account, mostly) since they probably have the code-monkey that deployed their LCS among them.
The user object, however, tries to be more general and has the following to role
field denote privilege:
{
"hacker": True,
"volunteer": False,
"judge": False,
"sponsor": False,
"mentor": False,
"organizer": False,
"director": False
}
The three categories are split by the following predicates (for endpoints where this information exists):
- Public: If there is no session token with the request.
- Hacker: If there is a session token with the request and
role.director == role.organizer == False
. - Organizer: If there is a session token with the requestion and
role.director or role.Organizer == True
.
The endpoints' usability varies by the user privilege levels. Create is a weird endpoint: it elevates public users to hacker users, but has no use-case for those who intend to use LCS as public people in no way affiliated to the hackathon. So, generally, the below is based on intent when the predicates above are not applicable (otherwise the predicates above are the guidelines implemented in the code).
Endpoint URL | Public Use | Hacker Use | Organizer Use |
---|---|---|---|
/attend-event | No use | No use | checking a hacker into an event |
/authorize | No use | Every use - logging in | Every use - logging in |
/create | No use | Every use - logging in the first time | No use (there's no way to automatically become an admin) |
/validate | No use | Every use - checking a token | Every use - checking a token |
/update | No use | Limited use - can update certain own information, here is a field-by-field guide | Every use - arbitrary personal and DB updates |
/consume | No use | Every use - can use it to change passwords or gain promotions | Every use - password changes or promotions (technically promotions are not applicable in LCS, but may be to third party apps) |
/createmagiclink | No use | Limited use - can create links for forgotten passwords only if they have a non-MLH account | Can create any creatable link (no password recovery for MLH users - that's an MLH problem) |
/dayof-events | Every use - read events at the hackathon | Every use - read events at the hackathon | Every use - read events at the hackathon |
/dayof-slack | Every use - read slack messages at the hackathon | Every use - read slack messages at the hackathon | Every use - read slack messages at the hackathon |
/link-qr | No use | No Use | Every use - link a qr to someone |
/send-emails | No use | Can send 1 email to themselves | Every use - send emails to a mailing list (either an explicit list or an arbitrary query) with a list of links that can be provided per recipient. |
/read | Limited use - can aggregate or read non-identifiable information, here is a field-by-field guide. | Limited use - can read any personal information and any non-identifiable information | Every use - can read or aggregate anything |
/slack-dm | No use | Every use - can create a slack dm link between self and any other LCS user | Every use - can create a slack dm link between self and any other LCS user |
"Publicly readable" means that anybody can read it and "self-update allowed" means that the user can update it.
Field | Type | What? | Publicly readable | Self-update Allowed |
---|---|---|---|---|
string (in HTML, <input type="email">
|
The user's email, a UID in the DB. | No | No | |
role |
object (more like HashMap<String, Boolean> if you speak Java) |
The user's role (details above). | Yes | No (see below) |
votes | int |
The "votes" that a hacker should be let in to HackRU. | Yes | No |
password |
string (always hashed!) |
The brcypt hash of the password | No | No (see below) |
github | string |
The user's github handle (optional) | Yes | Yes |
major | string |
The user's major (optional) | Yes | Yes |
short_answer | string |
The user's short answer - used for user selection in HackRU | Yes | Yes |
shirt_size | string |
The user's shirt size (optional) | Yes | Yes |
first_name | string |
The user's first name (optional) | No | Yes |
last_name | string |
The user's last name (optional) | No | Yes |
hackathon_count | int |
the amount of hackthons a user has attended | yes | yes |
qrcode | string[] |
qrcodes linked to this user | No | No |
dietary_restrictions | string |
The user's dietary restrictions (optional) | Yes | Yes |
travelling_from | string |
A sub-object that explains the user travel data (optional) | Yes | Yes |
special_needs | string |
The user's special needs (optional) | Yes | Yes |
date_of_birth |
string (formatted YYYY-MM-DD , courtesy of MLH) |
The user's date of birth (optional) | Yes | Yes |
school | string |
The user's school (optional) | Yes | Yes |
grad_year | string |
The user's graduation year (optional) | Yes | Yes |
gender | string |
The user's gender (optional) | Yes | Yes |
registration_status |
string (really an enum) |
The user's registration status with it's own FSM | Yes | Sometimes |
level_of_study | string |
The user's level of study (optional) | Yes | Yes |
mlh | boolean |
Whether the user used mlh | Yes | No |
day_of |
object (like a HashMap<String, Integer> ) |
The day-of details of the user, more details below | Yes | No |
slack_id | string |
The user's unique slack_id | No | Yes |
This is the default object:
doc = { #event is the JSON passed in with all the parameters.
"email": u_email, # this field must be here.
"role": { #we enforce that the user is a hacker.
"hacker": True,
"volunteer": False,
"judge": False,
"sponsor": False,
"mentor": False,
"organizer": False,
"director": False
},
"votes": 0,
"password": password, #this is mandatory and will always be hashed.
"github": event.get("github", ''),
"major": event.get("major", ''),
"short_answer": event.get("short_answer", ''),
"shirt_size": event.get("shirt_size", ''),
"first_name": event.get("first_name", ''),
"last_name": event.get("last_name", ''),
"dietary_restrictions": event.get("dietary_restrictions", ''),
"special_needs": event.get("special_needs", ''),
"date_of_birth": event.get("date_of_birth", ''),
"school": event.get("school", "Rutgers University"),
"grad_year": event.get("grad_year", ''),
"gender": event.get("gender", ''),
"registration_status": event.get("registration_status", "waitlist" if not is_not_day_of else "unregistered"),
"level_of_study": event.get("level_of_study", ""),
"mlh": mlh, #we know this, depending on how the function is called.
"day_of":{
"checkIn": False
}
}
An example data looks somewhat like this:
{
"is_real": true,
"formatted_addr": "New York, NY", //the address, validated by Google
"location": { //might be useful for some APIs
"lat": 42.31415, //the latitude
"lng": -78.2718 //the longitude
},
"mode": "car" //or "train" or "bus"
}
This object is unregulated by LCS to favor some flexibility. This may change so that case conventions and integer values are enforced, but a full list of events may not be provided to favor some flexibility on the backend.
The workaround is a magic link... A link that lets users magically update things that they wouldn't be allowed to by default.
These are two similar procedures and all that changes is who creates the "magic link". We call using a magic link "consumption."
Users create links for only themselves. They are emailed their link. This is a call to /createmagiclink.
If a user is to change role, an organizer (a user with organizer privilege) creates the link. As a convenience, they may make many links. Each link has a recipient and that recipient can consume the link. This is a call to /createmagiclink.
The application using LCS must call /consume to consume a magic link. The consume endpoint assumes the existence of a user. Hence, to really handle every case of a promotion, a separate call to create may be required.
Note: the underscores about are actually dashes in the backend. The naming below is accurate. The dashed edges labelled "Admin only" are updates that only an organizer user can make.
An explanation of the states:
- Unregistered: The user hasn't agreed to our terms and conditions (the MLH ones) and the MLH code of conduct. We cannot accept them.
- Registered: The use has accepted the MLH legal stuff and is awaiting admin review.
- Rejected: The admins have rejected the user.
- Confirmation: The user will be called upon to confirm attendance on a first-come first-serve basis.
- Waitlist: the user is accepted but after capacity has been reached.
- Coming: the user says they are coming (having been called upon to RSVP).
- not-coming: the user says they are not coming (having been called upon to RSVP).
- confirmed: the user confirmed that they're coming and their wave elapsed, so we save them a spot.
- checked-in: the user showed up on the day-of.
Any registered user can check in through an admin so the states are mostly formalities (shh... don't tell the hackers!), but we guarantee hackers who are "confirmed" a spot at HackRU.
When a query is allowed to be arbitrary, it means subtly different things. An arbitrary read is a mongo aggregate and the update allows for any mongo update.
For Users
For Current Implementors
Old Deployment Information