Shared modpacks routing#815
Conversation
Geometrically
left a comment
There was a problem hiding this comment.
- make the routes internal also
| updated timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP, | ||
| created timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP, | ||
|
|
||
| maximum_users integer NOT NULL, |
|
|
||
| CREATE TABLE shared_profiles_links ( | ||
| id bigint PRIMARY KEY, -- id of the shared profile link (ignored in labrinth, for db use only) | ||
| link varchar(48) NOT NULL UNIQUE, -- extension of the url that identifies this (ie profiles/afgxxczsewq) |
There was a problem hiding this comment.
Why not just make it based on the ID? Like discord's invites, it could be like: https://modrinth/invite/AAdwaDWD
| maximum_users integer NOT NULL, | ||
|
|
||
| loader_id int NOT NULL REFERENCES loaders(id), | ||
| loader_version varchar(255) NOT NULL, |
There was a problem hiding this comment.
I think it would be better for these to not be columns and rather their own column with strings as the id. So it would be like a jsonb metadata column like `{ "game_version": "1.19.2", "loader_version": "47.1.2" } (same with game versions) as games and loader versions can be specific to Minecraft
| #[derive(Clone, Debug, Serialize, Deserialize)] | ||
| pub enum ClientProfileGame { | ||
| Minecraft { | ||
| game_id: GameId, | ||
| game_name: String, | ||
| game_version_id: LoaderFieldEnumValueId, | ||
| game_version: String, | ||
| }, | ||
| Unknown { | ||
| game_id: GameId, | ||
| game_name: String, | ||
| }, | ||
| } |
There was a problem hiding this comment.
Do we need an enum here? Since we already have games dynamically in the database. Couldn't we just add a jsonb metadata field with game metadata (and then remove game_id and game_name fields
There was a problem hiding this comment.
Alternatively we could build this in with the loader fields system... but I don't think it's the best idea bc stuff like loader versions aren't on labrinth
| metadata jsonb NOT NULL DEFAULT '{}'::jsonb, | ||
|
|
||
| game_id int NOT NULL REFERENCES games(id), | ||
| game_version_id int NULL REFERENCES loader_field_enum_values(id) -- Minecraft java |
There was a problem hiding this comment.
why does this exist if the game version is also in the metadata?
| #[derive(Serialize, Deserialize, Clone)] | ||
| pub struct ClientProfileShareLink { | ||
| pub id: ClientProfileLinkId, // The url identifier, encoded as base62 | ||
| pub url: String, // Includes the url identifier, intentionally redundant | ||
| pub profile_id: ClientProfileId, | ||
| pub created: DateTime<Utc>, | ||
| pub expires: DateTime<Utc>, | ||
| } | ||
|
|
||
| impl From<database::models::client_profile_item::ClientProfileLink> for ClientProfileShareLink { | ||
| fn from(link: database::models::client_profile_item::ClientProfileLink) -> Self { | ||
| // Generate URL for easy access | ||
| let profile_id: ClientProfileId = link.shared_profile_id.into(); | ||
| let link_id: ClientProfileLinkId = link.id.into(); | ||
| let url = format!( | ||
| "{}/v3/client/profile/{}/accept/{}", | ||
| dotenvy::var("SELF_ADDR").unwrap(), | ||
| profile_id, | ||
| link_id | ||
| ); | ||
|
|
||
| Self { | ||
| id: link_id, | ||
| url, | ||
| profile_id, | ||
| created: link.created, | ||
| expires: link.expires, | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
The URL shouldn't be returned / parsed here. The frontend will generate it based on the link ID
| /// Modrinth-associated versions | ||
| pub versions: Vec<VersionId>, | ||
| /// Overrides for this profile- only install paths are given, | ||
| /// hashes are looked up in the CDN by the client | ||
| pub override_install_paths: Vec<PathBuf>, |
There was a problem hiding this comment.
What does this mean? IMO we shouldn't have the versions or any install info be returned here. It should be a separate route that is only called when the pack is being installed. And it can only be accessed once a user has accepted the invite.
There was a problem hiding this comment.
Im not sure I agree- I think it could be useful to be able to see the stuff youre going to install on your computer before accepting, or what's 'in/on' the shared modpack, like in the frontend as a snippet of what you're getting in the pack.
All this displays is what the versions are and the 'names' of the overrides. do you think its not worth returning this?
| // Delete a client profile | ||
| pub async fn profile_delete( | ||
| req: HttpRequest, | ||
| info: web::Path<(String,)>, | ||
| pool: web::Data<PgPool>, | ||
| redis: web::Data<RedisPool>, | ||
| session_queue: web::Data<AuthQueue>, | ||
| ) -> Result<HttpResponse, ApiError> { |
There was a problem hiding this comment.
This should delete override files from the CDN as long as they are unused by other shared packs
| version_id bigint NULL REFERENCES versions(id), -- for versions | ||
|
|
||
| -- for cdn links to files we host directly | ||
| file_hash varchar(255) NULL, |
There was a problem hiding this comment.
We should restructure this. Override files should be a separate table which this table refers too IMO. And then it should refer to this here (we could just re-use the files table TBH).
Like other API objects, this would allow us to have SHA1 and SHA512 hashes. Shared modpacks will also share files a ton (ex: if someone has the same exact config file between packs, we shouldn't haave to host it twice or have duplicate database entries)
There was a problem hiding this comment.
I think just using the files table would probably work well enough. It would also allow it so if someone did ever upload their mod to Modrinth, we could "re-link" it to the project dynamically and change it from an override to a Modrinth version ID. If that makes sense
| "{id}/override", | ||
| web::delete().to(client_profile_remove_overrides), | ||
| ) | ||
| .route("{id}/share", web::get().to(profile_share)) |
There was a problem hiding this comment.
IMO this route is kind of pointless. We should just return share links in the main profile body. When would you get a profile and not get its share links?
| .route( | ||
| "{id}/share/{url_identifier}", | ||
| web::get().to(profile_link_get), | ||
| ) | ||
| .route( | ||
| "{id}/accept/{url_identifier}", | ||
| web::post().to(accept_share_link), | ||
| ) |
There was a problem hiding this comment.
These routes are structured wrong. A share link would be like https://modrinth.com/share/aaJJJwwa. You won't know the profile ID. There should be a route to just get a profile from share link and accept a share link
NOTE: DO NOT MERGE until changes noted in the migrations file are reverted.
Fixes MOD-576
Notable deviations from spec:
modrinth://link as we move from testing this with cloudflare to having the theseus implementation.