Read our contributing guidelines
testaustime / testaustime-backend Goto Github PK
View Code? Open in Web Editor NEWHome Page: https://api.testaustime.fi
License: MIT License
Home Page: https://api.testaustime.fi
License: MIT License
Read our contributing guidelines
This endpoint is also undocumented 😡 which I trust @DrVilepis fixes while fixing this issue.
If I do curl --request POST "https://api.testaustime.fi/leaderboards/[redacted]/regenerate" --header "Authorization: Bearer [redacted]"
it will return 400 Bad Request, even though the API spec says that that is okay.
I must instead do curl --request POST "https://api.testaustime.fi/leaderboards/[redacted]/regenerate" --header "Authorization: Bearer [redacted]" -H "Content-Type: application/json" --data-raw ""
to get it to regenerate the token.
We should ideally not require any body, or at least update the API spec to include this requirement.
This would most likely have the same authentication (password + token) with /auth/changepassword
The Server-Timing
header allows us to send more detailed information about timing (e.g. how long database access took, some long calculation after that, etc…) in the response.
Generating it should probably be determined based on a build-time environment variable.
See more: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Server-Timing
The API specification says that the /auth/changepassword
endpoint requires a secured access token but in reality it doesn't. We should either remove the requirement from the API documentation, or change the logic to require it.
I'd recommend just removing it from the API docs and keeping the implementation as is, because the endpoint requires the same values as the secure access token generation endpoint, so requiring SAT for changing password doesn't really provide any benefits.
It would be nice to have an OpenAPI schema for the API, it would allow us to generate the types for the frontend automatically.
One possible library: https://github.com/juhaku/utoipa
Not sure what is the best way to distribute the schema, here are some ideas:
Ratelimits for normal requests are too restricted
We need an endpoint for getting leaderboard metadata by an invite code for Testaustime/testaustime-frontend#270
The metadata should include at least:
The endpoint could for example be GET /leaderboards/invite-code/ttlic_xyz123
. The endpoint should not require authentication, because the links should be shareable to anonymous users and we should show them the metadata and prompt them to register to Testaustime in order to join the leaderboard.
Headers such as x-ratelimit-limit
, x-ratelimit-remaining
and x-ratelimit-reset
would be useful for client libraries to queue http request and not get ratelimited.
There should be a route that returns the list of all the leaderboards the user is a member of, AND it should include basic info about the leaderboard, such as the top coder and the user's rank on it.
This is currently a problem because /users/@me/leaderboards
only returns a list of leaderboard names. The client will then have to do another request for each of those leaderboards to /leaderboards/{name}
, leading to an n+1 problem.
The new route would simplify client code and also prevent users from hitting rate limits if they are a member of many leaderboards.
Update the API documentation.
If feeling extra fancy, create a new tool which auto generates the documentation from comments in the code and just write a doc comment above the endpoint in the code when implementing new features.
Currently it only returns a list of usernames: ["friend1", "friend2"]
It should return data about how much the user has coded, because the leaderboard and friend list need that data.
The new format could be this, for example:
[
{
"username": "friend1",
"timeCoded": {
"allTime": 77533,
"lastMonth": 53290,
"lastWeek": 1863
}
},
{
"username": "friend2",
"timeCoded": {
"allTime": 181932,
"lastMonth": 83912,
"lastWeek": 27184
}
}
]
Currently if I send the following request
curl 'https://api.testaustime.fi/auth/login' -X POST -H 'Authorization: Bearer' -H 'Content-Type: application/json' --data-raw '{"username":"Eldemarkki","password":"[REDACTED]"}'
I get a response You are not authorized
, because it tries to find a user with that Authorization
header.
I should instead get a login success/error response.
Fetching data for a public profile requires authentication (just any valid token) even though it should be public.
If the last admin of a leaderboard deletes their account, the leaderboard will be left dangling in the database. Same error as #24
I can think of 2 possible solutions:
It's stored as a VARCHAR(32)
but that is not enforced by the endpoint instead the endpoint will just explode if a name of an invalid length is provided.
For example I have a leaderboard with users A, B and C in it. Then I try to promote/demote/kick user D on that leaderboard, it responds with error You're not a member
. The error should instead say User D is not a member of this leaderboard
, or something similar.
There should be an easy way to initialize the database with some seed data. This would make it easier for new people to start contributing to this project.
The documentation specifies that the GET request to /users/{username}/activity/current
always specifies that the started
field is in UTC time (by including the Z
at the end):
{
"started": "YYYY-MM-DDTHH:MM:SS.ssssssZ",
"duration": "10",
"heartbeat": {
"language": "c",
"hostname": "hostname1",
"editor_name": "Neovim",
"project_name": "cool_project22"
}
}
However, in reality that "Z" is not included. Here is an example response that I got:
{
"started": "2023-12-17T12:03:20.938417739",
"duration": 240,
"heartbeat": {
"project_name": "testaustime-frontend",
"language": "typescript",
"editor_name": "vscode",
"hostname": "ideapad"
}
}
I believe the same problem exists for all other timestamps that are returned from any endpoint. We already have an issue in the frontend for this, but I think it would be best to fix in the backend.
Also, it seems that the duration
field is a number instead of a string.
Ways to recreate:
This issue will fill up the database with empty leaderboards
For example, curl -X GET https://api.testaustime.fi/auth/login -v
should return status 405. Currently it returns 404.
Currently, a Testaustime client embedded as an add-on in a code editor (such as Neovim or Micro) is authenticated using the authentication token of the account. This is sub-optimal, to put it nicely. There is no way to distinguish between the user performing actions on the front-end (or, if they are particularly based, with direct API calls) and a Testaustime client performing the same actions.
As Testaustime does not have many security-critical endpoints, this is mostly a non-issue. Moreover, the endpoint to delete the current user (/users/@me/delete
) requires the username and password anyway, presumably for this very reason. That being said, endpoints related to leaderboard administration or user management (joining and leaving leaderboards, removing and adding friends) are wholly unprotected. This lack of protection is concerning, and should be changed.
I propose a second layer of authentication reserved for administrative and management tasks. Endpoints that are not considered security-critical (in practice, all read-only endpoints as well as activity updates) would be placed on the primary layer, which would use the traditional and current form of authentication. Endpoints that are considered security-critical, i.e. ones that an attacker could use to cause significant distress to the end-user, would be guarded using the new secured layer.
Endpoints guarded by the secured layer are only accessible by special, temporary tokens. A secured layer authentication token can be generated using a primary layer endpoint (e.g. /auth/securedaccess
). This endpoint would require both the username and password of the user, as well as the traditional authentication token. It would then respond with a temporary token to be used in place of the traditional authentication token, as well as metadata about the lifetime of the token.
Secured endpoints such as leaderboard, friends list and user management would then be accessed using this temporary token instead of the traditional one. This way, endpoints of the secured layer are essentially guarded by an additional login step (like "sudo mode" in GitHub).
I'd like to hear your thoughts on the issue. Crucially, I'd like feedback on whether the Testaustime developers actually think this change is necessary. The likelihood of tokens being compromised is quite low, especially as Testaustime's target audience is mostly one of programmers who are (or, at least, ought to be) familiar with token authentication, and probably wouldn't go about their day handing tokens out to anyone who asks. That being said, I still think this change is justified in the name of correctness if not that of security.
The authentication here should be similar to #34
If a user doesn't have a current activity, but their current activity is requested at /users/USERNAME/activity/current
, it will just return null
with status 200.
$ curl 'https://api.testaustime.fi/users/Antti/activity/current' -H 'Authorization: Bearer REDACTED'
null
(sorry Antti for exposing your inactivity)
I suggest we return some JSON (e.g. {"error":"User doesn't have an active session"}
) with status code 404.
There is no mention of the GET /search/users
in the API spec, we should add it there along with all the parameters it requires and the response format
The info could be, for example
The privacy implications of this should be considered as well. Should this for example be only opt-in?
For the people who might self-host Testaustime (not sure if there are any at the moment), it should also be possible for the admins to disable these data routes via e.g. an environment variable.
Leaderboard codes are returned with the ttlic_
prefix but friend codes are not returned with the ttfc_
prefix.
There is no mention of the /account/settings
endpoint in the API specification
It would be useful if the GET /leaderboards/{name}
response included the current activity status of each member of the leaderboard. The information is needed so that we can display the coding status on the leaderboard page in the frontend, similar to what we already do on the friends list page.
Currently it throws a Diesel error if trying to log in with a non-existent user:
curl 'https://api.testaustime.fi/auth/login' -X POST -H 'Content-Type: application/json' --data-raw '{"username":"thisuserdoesntexist","password":"thisuserdoesntexist"}'
returns {"error":"Diesel transaction failed `Record not found`"}
. It should instead return a generic error, such as {"error":"Invalid credentials"}
Note that those specific credentials may start working if someone creates that user after seeing this issue. This can be bypassed by purchasing a cat and making it run over your keyboard to generate a new, hopefully non-existent user.
Partially fixes Testaustime/testaustime-frontend#63 also.
Currently if a leaderboard only has user X in it, and X is an admin, they can leave the leaderboard. Then the leaderboard won't have any admins, and so no one can delete it and it will stay in the database forever.
I propose that an admin should only be allowed to leave a leaderboard if there are other admins left. If there aren't any, the last admin should only be able to delete the leaderboard.
We could allow the user to store one (or multiple?) emails in their profile, so that in case they forget their password, we can send a password-reset link to their email.
We should probably still use username-password auth, as changing that would be quite a big change.
We'd need some API to send the emails, we could ask if Testausserveri ry could pay for it. For local development, MailHog looks like a very useful tool.
Drawing a graph in the frontend requires requesting all activities related to the user, which for me is around 1mb, which is not ideal.
This should be fixed
Let's say one would make a similar thing to ganmol098/waka-readme-stats, but with Testaustime.
It uses a similar endpoint that seems to exist in Testaustime(https://github.com/anmol098/waka-readme-stats/blob/master/main.py#L328), but it would be great if the data was structured more nicely from the endpoint. It should include editors, OS, and of course programming language and project.
The API spec says that POST /auth/changeusername
returns status 403 if username is taken, but in reality it returns 409. We should change the docs to say it returns 409 in those cases.
To ease the development of extra functionality such as the Testaustime Discord bot there could be a seperate API where such bot could access user data if they have consented to it in some settings. Would be a nicer alternative to using an user account with a private leaderboard and a ton of friends.
HaveIBeenPwned has a big database which can be downloaded for offline use with this tool, it would be nice if we could check that a user's password is secure before allowing them to register with it.
Governor Just seems like a better way to ratelimit stuff.
Actix-ratelimiter was shit, we make our own.
Currently it only returns the name
Currently there is a max_registers_per_day
field in the example settings, but it's not used anywhere in the code.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.