Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions errors/game/env-not-found.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
name = "GAME_ENVIRONMENT_NOT_FOUND"
description = "Environment not found."
http_status = 400
---

# Environment Not Found

The requested environment was not found.
2 changes: 1 addition & 1 deletion proto/backend/ds.proto
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ message Server {
reserved 8;

rivet.common.Uuid server_id = 1;
rivet.common.Uuid game_id = 2;
rivet.common.Uuid env_id = 2;
rivet.common.Uuid datacenter_id = 3;
rivet.common.Uuid cluster_id = 4;
map<string, string> tags = 5;
Expand Down
20 changes: 17 additions & 3 deletions svc/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion svc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ members = [
"pkg/ds/ops/server-create",
"pkg/ds/ops/server-delete",
"pkg/ds/ops/server-get",
"pkg/ds/ops/server-list-for-game",
"pkg/ds/ops/server-list-for-env",
"pkg/ds/worker",
"pkg/email-verification/ops/complete",
"pkg/email-verification/ops/create",
Expand Down
4 changes: 2 additions & 2 deletions svc/api/servers/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,14 @@ uuid = { version = "1", features = ["v4"] }

build-create = { path = "../../pkg/build/ops/create" }
build-get = { path = "../../pkg/build/ops/get" }
build-list-for-game = { path = "../../pkg/build/ops/list-for-game" }
build-list-for-env = { path = "../../pkg/build/ops/list-for-env" }
cluster = { path = "../../pkg/cluster" }
build = { path = "../../pkg/build" }
ds-log-read = { path = "../../pkg/ds-log/ops/read" }
ds-server-create = { path = "../../pkg/ds/ops/server-create" }
ds-server-delete = { path = "../../pkg/ds/ops/server-delete" }
ds-server-get = { path = "../../pkg/ds/ops/server-get" }
ds-server-list-for-game = { path = "../../pkg/ds/ops/server-list-for-game" }
ds-server-list-for-env = { path = "../../pkg/ds/ops/server-list-for-env" }
game-get = { path = "../../pkg/game/ops/get" }
game-namespace-get = { path = "../../pkg/game/ops/namespace-get" }
game-version-get = { path = "../../pkg/game/ops/version-get" }
Expand Down
15 changes: 15 additions & 0 deletions svc/api/servers/src/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,25 @@ impl Auth {
&self,
ctx: &OperationContext<()>,
game_id: Uuid,
env_id: Uuid,
allow_service: bool,
) -> GlobalResult<()> {
let claims = self.claims()?;

// Get the game this env belongs to
let ns_res = op!([ctx] game_namespace_get {
namespace_ids: vec![env_id.into()],
})
.await?;
let env = unwrap!(ns_res.namespaces.first(), GAME_ENVIRONMENT_NOT_FOUND);

// Ensure belongs to game
ensure_with!(
unwrap!(env.game_id).as_uuid() == game_id,
GAME_ENVIRONMENT_NOT_FOUND
);

// Validate token
if let Ok(cloud_ent) = claims.as_game_cloud() {
ensure_with!(
cloud_ent.game_id == game_id,
Expand Down
47 changes: 33 additions & 14 deletions svc/api/servers/src/route/builds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,27 @@ use util::timestamp;

use crate::auth::Auth;

// MARK: GET /games/{}/builds/{}
// MARK: GET /games/{}/environments/{}/builds/{}
pub async fn get(
ctx: Ctx<Auth>,
game_id: Uuid,
env_id: Uuid,
build_id: Uuid,
_watch_index: WatchIndexQuery,
) -> GlobalResult<models::ServersGetBuildResponse> {
ctx.auth().check_game(ctx.op_ctx(), game_id, true).await?;
ctx.auth()
.check_game(ctx.op_ctx(), game_id, env_id, true)
.await?;

let builds_res = op!([ctx] build_get {
build_ids: vec![build_id.into()],
})
.await?;
let build = unwrap!(builds_res.builds.first());
let build = unwrap!(builds_res.builds.first(), BUILDS_BUILD_NOT_FOUND);
ensure_with!(
unwrap!(build.env_id).as_uuid() == env_id,
BUILDS_BUILD_NOT_FOUND
);

let uploads_res = op!([ctx] upload_get {
upload_ids: builds_res
Expand All @@ -49,7 +56,7 @@ pub async fn get(
})
}

// MARK: GET /games/{}/builds
// MARK: GET /games/{}/environments/{}/builds
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GetQuery {
tags_json: Option<String>,
Expand All @@ -58,13 +65,16 @@ pub struct GetQuery {
pub async fn list(
ctx: Ctx<Auth>,
game_id: Uuid,
env_id: Uuid,
_watch_index: WatchIndexQuery,
query: GetQuery,
) -> GlobalResult<models::ServersListBuildsResponse> {
ctx.auth().check_game(ctx.op_ctx(), game_id, true).await?;
ctx.auth()
.check_game(ctx.op_ctx(), game_id, env_id, true)
.await?;

let list_res = op!([ctx] build_list_for_game {
game_id: Some(game_id.into()),
let list_res = op!([ctx] build_list_for_env {
env_id: Some(env_id.into()),
tags: query.tags_json.as_deref().map_or(Ok(HashMap::new()), serde_json::from_str)?,
})
.await?;
Expand Down Expand Up @@ -121,14 +131,17 @@ pub async fn list(
})
}

// MARK: PATCH /games/{}/builds/{}/tags
// MARK: PATCH /games/{}/environments/{}/builds/{}/tags
pub async fn patch_tags(
ctx: Ctx<Auth>,
game_id: Uuid,
env_id: Uuid,
build_id: Uuid,
body: models::ServersPatchBuildTagsRequest,
) -> GlobalResult<serde_json::Value> {
ctx.auth().check_game(ctx.op_ctx(), game_id, false).await?;
ctx.auth()
.check_game(ctx.op_ctx(), game_id, env_id, false)
.await?;

let tags: HashMap<String, String> =
serde_json::from_value::<HashMap<String, String>>(unwrap!(body.tags))?;
Expand All @@ -148,13 +161,16 @@ pub async fn patch_tags(
Ok(json!({}))
}

// MARK: POST /games/{}/builds/prepare
// MARK: POST /games/{}/environments/{}/builds/prepare
pub async fn create_build(
ctx: Ctx<Auth>,
game_id: Uuid,
env_id: Uuid,
body: models::ServersCreateBuildRequest,
) -> GlobalResult<models::ServersCreateBuildResponse> {
ctx.auth().check_game(ctx.op_ctx(), game_id, false).await?;
ctx.auth()
.check_game(ctx.op_ctx(), game_id, env_id, false)
.await?;

// TODO: Read and validate image file

Expand All @@ -175,7 +191,7 @@ pub async fn create_build(
};

let create_res = op!([ctx] build_create {
game_id: Some(game_id.into()),
env_id: Some(env_id.into()),
display_name: body.name,
image_tag: Some(body.image_tag),
image_file: Some((*body.image_file).api_try_into()?),
Expand Down Expand Up @@ -220,10 +236,13 @@ pub async fn create_build(
pub async fn complete_build(
ctx: Ctx<Auth>,
game_id: Uuid,
env_id: Uuid,
build_id: Uuid,
_body: serde_json::Value,
) -> GlobalResult<serde_json::Value> {
ctx.auth().check_game(ctx.op_ctx(), game_id, false).await?;
ctx.auth()
.check_game(ctx.op_ctx(), game_id, env_id, false)
.await?;

let build_res = op!([ctx] build_get {
build_ids: vec![build_id.into()],
Expand All @@ -232,7 +251,7 @@ pub async fn complete_build(
let build = unwrap_with!(build_res.builds.first(), BUILDS_BUILD_NOT_FOUND);

ensure_with!(
unwrap!(build.game_id).as_uuid() == game_id,
unwrap!(build.env_id).as_uuid() == env_id,
BUILDS_BUILD_NOT_FOUND
);

Expand Down
7 changes: 5 additions & 2 deletions svc/api/servers/src/route/logs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use std::time::Duration;

use crate::{assert, auth::Auth};

// MARK: GET /games/{}/servers/{}/logs
// MARK: GET /games/{}/environments/{}/servers/{}/logs
#[derive(Debug, Deserialize)]
pub struct GetServerLogsQuery {
pub stream: models::CloudGamesLogStream,
Expand All @@ -19,11 +19,14 @@ pub struct GetServerLogsQuery {
pub async fn get_logs(
ctx: Ctx<Auth>,
game_id: Uuid,
env_id: Uuid,
server_id: Uuid,
watch_index: WatchIndexQuery,
query: GetServerLogsQuery,
) -> GlobalResult<models::ServersGetServerLogsResponse> {
ctx.auth().check_game(ctx.op_ctx(), game_id, false).await?;
ctx.auth()
.check_game(ctx.op_ctx(), game_id, env_id, false)
.await?;

// Validate server belongs to game
assert::server_for_game(&ctx, server_id, game_id).await?;
Expand Down
16 changes: 8 additions & 8 deletions svc/api/servers/src/route/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ pub async fn handle(
define_router! {
cors: CorsConfigBuilder::hub().build(),
routes: {
"games" / Uuid / "servers": {
"games" / Uuid / "environments" / Uuid / "servers": {
GET: servers::list_servers(
query: servers::ListQuery,
),
Expand All @@ -32,38 +32,38 @@ define_router! {
),
},

"games" / Uuid / "servers" / Uuid: {
"games" / Uuid / "environments" / Uuid / "servers" / Uuid: {
GET: servers::get(),
DELETE: servers::destroy(
query: servers::DeleteQuery,
),
},

"games" / Uuid / "servers" / Uuid / "logs" : {
"games" / Uuid / "environments" / Uuid / "servers" / Uuid / "logs" : {
GET: logs::get_logs(
query: logs::GetServerLogsQuery,
),
},

"games" / Uuid / "builds": {
"games" / Uuid / "environments" / Uuid / "builds": {
GET: builds::list(
query: builds::GetQuery,
),
},

"games" / Uuid / "builds" / Uuid: {
"games" / Uuid / "environments" / Uuid / "builds" / Uuid: {
GET: builds::get(),
},

"games" / Uuid / "builds" / Uuid / "tags": {
"games" / Uuid / "environments" / Uuid / "builds" / Uuid / "tags": {
PATCH: builds::patch_tags(body: models::ServersPatchBuildTagsRequest),
},

"games" / Uuid / "builds" / "prepare": {
"games" / Uuid / "environments" / Uuid / "builds" / "prepare": {
POST: builds::create_build(body: models::ServersCreateBuildRequest),
},

"games" / Uuid / "builds" / Uuid / "complete": {
"games" / Uuid / "environments" / Uuid / "builds" / Uuid / "complete": {
POST: builds::complete_build(body: serde_json::Value),
},
},
Expand Down
Loading