Skip to content

Commit

Permalink
Support me-central-1 region for dedicated hosting (#1369)
Browse files Browse the repository at this point in the history
  • Loading branch information
michaeljguarino authored Sep 30, 2024
1 parent 8a1f16f commit 368691e
Show file tree
Hide file tree
Showing 16 changed files with 114 additions and 19 deletions.
5 changes: 5 additions & 0 deletions apps/api/lib/api_web/endpoint.ex
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ defmodule ApiWeb.Endpoint do
plug Plug.RequestId
plug Plug.Telemetry, event_prefix: [:phoenix, :endpoint]

plug Hammer.Plug, [
rate_limit: {"api.global", 60_000, 1000},
by: :ip
]

plug Plug.Parsers,
parsers: [:urlencoded, {:multipart, length: @upload_maximum}, ApiWeb.Parsers.ApplicationJson],
pass: ["*/*"],
Expand Down
1 change: 1 addition & 0 deletions apps/api/mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ defmodule Api.MixProject do
{:prometheus_ex, "~> 3.0"},
{:prometheus_plugs, "~> 1.1.1"},
{:remote_ip, "~> 0.2.0"},
{:hammer_plug, "~> 3.0"},
{:k8s_traffic_plug, github: "Financial-Times/k8s_traffic_plug"},

{:core, in_umbrella: true},
Expand Down
10 changes: 8 additions & 2 deletions apps/core/lib/core/schema/console_instance.ex
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,12 @@ defmodule Core.Schema.ConsoleInstance do
stack_deleted: 7

@region_map %{
aws: ~w(us-east-1)
shared: %{
aws: ~w(us-east-1)
},
dedicated: %{
aws: ~w(us-east-1 me-central-1)
}
}

schema "console_instances" do
Expand Down Expand Up @@ -134,7 +139,8 @@ defmodule Core.Schema.ConsoleInstance do

defp validate_region(cs) do
cloud = get_field(cs, :cloud)
regions = @region_map[cloud]
type = get_field(cs, :type)
regions = @region_map[type][cloud]
validate_change(cs, :region, fn :region, reg ->
case reg in regions do
true -> []
Expand Down
4 changes: 2 additions & 2 deletions apps/core/lib/core/schema/user.ex
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ defmodule Core.Schema.User do
|> validate_required([:name, :email])
|> validate_length(:email, max: 255)
|> validate_length(:name, max: 255)
|> validate_length(:password, min: 10)
|> validate_length(:password, min: 10, max: 255)
|> validate_format(:email, @email_re)
|> hash_password()
|> generate_uuid(:avatar_id)
Expand Down Expand Up @@ -254,7 +254,7 @@ defmodule Core.Schema.User do
|> add_email(model)
|> validate_length(:email, max: 255)
|> validate_length(:name, max: 255)
|> validate_length(:password, min: 10)
|> validate_length(:password, min: 10, max: 255)
|> validate_format(:email, @email_re)
|> unique_constraint(:email)
|> validate_required([:name, :email])
Expand Down
1 change: 0 additions & 1 deletion apps/core/lib/core/services/cloud/workflow.ex
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
defmodule Core.Services.Cloud.Workflow do
use Core.Services.Base
alias Core.Repo
alias Core.Clients.Console
alias Core.Schema.{ConsoleInstance}
alias Core.Services.Cloud.Workflow.{Dedicated, Shared}

Expand Down
2 changes: 2 additions & 0 deletions apps/core/lib/core/services/cloud/workflow/shared.ex
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ defmodule Core.Services.Cloud.Workflow.Shared do
alias Core.Schema.{ConsoleInstance, PostgresCluster, User}
alias Core.Repo

require Logger

@behaviour Core.Services.Cloud.Workflow

def sync(%ConsoleInstance{external_id: id} = instance) when is_binary(id) do
Expand Down
4 changes: 2 additions & 2 deletions apps/core/lib/core/services/users.ex
Original file line number Diff line number Diff line change
Expand Up @@ -715,8 +715,8 @@ defmodule Core.Services.Users do
|> when_ok(&delete_eab_key/1)
end

@decorate cache_evict(cache: Core.Cache, keys: [{:eab, c, p, u}])
def delete_eab_key(%EabCredential{user_id: u, cluster: c, provider: p} = eab),
@decorate cache_evict(cache: Core.Cache, keys: [{:eab, eab.user_id, eab.cluster, eab.provider}])
def delete_eab_key(%EabCredential{} = eab),
do: Core.Repo.delete(eab)

defp materialize_eab_key(cluster, provider, %User{id: user_id}) do
Expand Down
6 changes: 6 additions & 0 deletions apps/graphql/lib/graphql/resolvers/cloud.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@ defmodule GraphQl.Resolvers.Cloud do
use GraphQl.Resolvers.Base, model: Core.Schema.ConsoleInstance
alias Core.Services.{Cloud, Clusters}

def resolve_settings(_, _) do
{:ok, %{
regions: ConsoleInstance.regions()
}}
end

def resolve_instance(%{id: id}, %{context: %{current_user: user}}),
do: Cloud.visible(id, user)

Expand Down
19 changes: 19 additions & 0 deletions apps/graphql/lib/graphql/schema/cloud.ex
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,28 @@ defmodule GraphQl.Schema.Cloud do
timestamps()
end

object :plural_cloud_settings do
field :regions, :plural_cloud_regions
end

object :plural_cloud_regions do
field :shared, non_null(:cloud_regions)
field :dedicated, non_null(:cloud_regions)
end

object :cloud_regions do
field :aws, list_of(:string)
end

connection node_type: :console_instance

object :cloud_queries do
field :cloud_settings, :plural_cloud_settings do
middleware Authenticated

resolve &Cloud.resolve_settings/2
end

field :console_instance, :console_instance do
middleware Authenticated
arg :id, non_null(:id)
Expand Down
3 changes: 2 additions & 1 deletion apps/graphql/lib/graphql/schema/user.ex
Original file line number Diff line number Diff line change
Expand Up @@ -476,7 +476,7 @@ defmodule GraphQl.Schema.User do
arg :email, non_null(:string)
arg :password, non_null(:string)
arg :device_token, :string
arg :captcha, :string
arg :captcha, non_null(:string)

middleware Captcha

Expand Down Expand Up @@ -558,6 +558,7 @@ defmodule GraphQl.Schema.User do

field :update_user, :user do
middleware Authenticated
middleware RateLimit, limit: 10, time: 60_000
arg :id, :id
arg :attributes, non_null(:user_attributes)

Expand Down
17 changes: 11 additions & 6 deletions apps/graphql/test/mutations/user_mutation_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,17 @@ defmodule GraphQl.UserMutationTest do
})

{:ok, %{data: %{"login" => found}}} = run_query("""
mutation Login($email: String!, $password: String!) {
login(email: $email, password: $password) {
mutation Login($email: String!, $password: String!, $captcha: String!) {
login(email: $email, password: $password, captcha: $captcha) {
id
jwt
}
}
""", %{"email" => "mjg@plural.sh", "password" => "super strong password"}, %{origin: "https://app.plural.sh"})
""", %{
"email" => "mjg@plural.sh",
"password" => "super strong password",
"captcha" => "valid_response"
}, %{origin: "https://app.plural.sh"})

assert found["id"] == user.id
assert found["jwt"]
Expand Down Expand Up @@ -112,16 +116,17 @@ defmodule GraphQl.UserMutationTest do
token = insert(:login_token)

{:ok, %{data: %{"login" => found}}} = run_query("""
mutation Login($email: String!, $password: String!, $deviceToken: String) {
login(email: $email, password: $password, deviceToken: $deviceToken) {
mutation Login($email: String!, $password: String!, $deviceToken: String, $captcha: String!) {
login(email: $email, password: $password, deviceToken: $deviceToken, captcha: $captcha) {
id
jwt
}
}
""", %{
"email" => "mjg@plural.sh",
"password" => "super strong password",
"deviceToken" => token.token
"deviceToken" => token.token,
"captcha" => "valid_response"
})

assert found["id"] == user.id
Expand Down
18 changes: 18 additions & 0 deletions apps/graphql/test/queries/cloud_queries_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,24 @@ defmodule GraphQl.CloudQueriesTest do
use Core.SchemaCase, async: true
import GraphQl.TestHelpers

describe "cloudSettings" do
test "it can list supported regions" do
{:ok, %{data: %{"cloudSettings" => settings}}} = run_query("""
query {
cloudSettings {
regions {
shared { aws }
dedicated { aws }
}
}
}
""", %{}, %{current_user: insert(:user)})

refute Enum.empty?(settings["regions"]["shared"]["aws"])
refute Enum.empty?(settings["regions"]["dedicated"]["aws"])
end
end

describe "consoleInstances" do
test "it can fetch the cloud instances in your account" do
user = insert(:user)
Expand Down
1 change: 1 addition & 0 deletions mix.lock
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
"guardian": {:hex, :guardian, "1.2.1", "bdc8dd3dbf0fb7216cb6f91c11831faa1a64d39cdaed9a611e37f2413e584983", [:mix], [{:jose, "~> 1.8", [hex: :jose, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.3", [hex: :phoenix, repo: "hexpm", optional: true]}, {:plug, "~> 1.3.3 or ~> 1.4", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "723fc404edfb7bd5cba4cd83329b352037f102aa97468f44e58ac7f47c136a98"},
"hackney": {:hex, :hackney, "1.18.2", "d7ff544ddae5e1cb49e9cf7fa4e356d7f41b283989a1c304bfc47a8cc1cf966f", [:rebar3], [{:certifi, "~> 2.12.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~> 6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~> 1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~> 1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.4.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~> 1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "af94d5c9f97857db257090a4a10e5426ecb6f4918aa5cc666798566ae14b65fd"},
"hammer": {:hex, :hammer, "6.1.0", "f263e3c3e9946bd410ea0336b2abe0cb6260af4afb3a221e1027540706e76c55", [:make, :mix], [{:poolboy, "~> 1.5", [hex: :poolboy, repo: "hexpm", optional: false]}], "hexpm", "b47e415a562a6d072392deabcd58090d8a41182cf9044cdd6b0d0faaaf68ba57"},
"hammer_plug": {:hex, :hammer_plug, "3.0.0", "7b1d000021e3ccc92cc6405c5537d3ec22f8f8f1274a1ae9351a8d98c32a2803", [:mix], [{:hammer, "~> 6.0", [hex: :hammer, repo: "hexpm", optional: false]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "35275f98f887bef8d84a8e0a3021ba1cd14d0e15c11221f6f8c833a3d43f35d8"},
"hpax": {:hex, :hpax, "0.1.2", "09a75600d9d8bbd064cdd741f21fc06fc1f4cf3d0fcc335e5aa19be1a7235c84", [:mix], [], "hexpm", "2c87843d5a23f5f16748ebe77969880e29809580efdaccd615cd3bed628a8c13"},
"httpoison": {:hex, :httpoison, "1.8.2", "9eb9c63ae289296a544842ef816a85d881d4a31f518a0fec089aaa744beae290", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "2bb350d26972e30c96e2ca74a1aaf8293d61d0742ff17f01e0279fef11599921"},
"idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"},
Expand Down
17 changes: 16 additions & 1 deletion schema/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,8 @@ type RootQueryType {
"Get a list of clusters owned by the current account."
clusters(after: String, first: Int, before: String, last: Int): ClusterConnection

cloudSettings: PluralCloudSettings

consoleInstance(id: ID!): ConsoleInstance

consoleInstances(after: String, first: Int, before: String, last: Int): ConsoleInstanceConnection
Expand All @@ -219,7 +221,7 @@ type RootQueryType {
}

type RootMutationType {
login(email: String!, password: String!, deviceToken: String, captcha: String): User
login(email: String!, password: String!, deviceToken: String, captcha: String!): User

deviceLogin: DeviceLogin

Expand Down Expand Up @@ -644,6 +646,19 @@ type ConsoleInstance {
updatedAt: DateTime
}

type PluralCloudSettings {
regions: PluralCloudRegions
}

type PluralCloudRegions {
shared: CloudRegions!
dedicated: CloudRegions!
}

type CloudRegions {
aws: [String]
}

type ConsoleInstanceConnection {
pageInfo: PageInfo!
edges: [ConsoleInstanceEdge]
Expand Down
23 changes: 20 additions & 3 deletions www/src/generated/graphql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,11 @@ export enum CloudProvider {
Aws = 'AWS'
}

export type CloudRegions = {
__typename?: 'CloudRegions';
aws?: Maybe<Array<Maybe<Scalars['String']['output']>>>;
};

export type CloudShell = {
__typename?: 'CloudShell';
aesKey: Scalars['String']['output'];
Expand Down Expand Up @@ -2208,6 +2213,17 @@ export type PlatformSubscriptionLineItems = {
quantity: Scalars['Int']['output'];
};

export type PluralCloudRegions = {
__typename?: 'PluralCloudRegions';
dedicated: CloudRegions;
shared: CloudRegions;
};

export type PluralCloudSettings = {
__typename?: 'PluralCloudSettings';
regions?: Maybe<PluralCloudRegions>;
};

export type PluralConfiguration = {
__typename?: 'PluralConfiguration';
gitCommit?: Maybe<Scalars['String']['output']>;
Expand Down Expand Up @@ -3408,7 +3424,7 @@ export type RootMutationTypeLinkPublisherArgs = {


export type RootMutationTypeLoginArgs = {
captcha?: InputMaybe<Scalars['String']['input']>;
captcha: Scalars['String']['input'];
deviceToken?: InputMaybe<Scalars['String']['input']>;
email: Scalars['String']['input'];
password: Scalars['String']['input'];
Expand Down Expand Up @@ -3733,6 +3749,7 @@ export type RootQueryType = {
charts?: Maybe<ChartConnection>;
chat?: Maybe<ChatMessage>;
closure?: Maybe<Array<Maybe<ClosureItem>>>;
cloudSettings?: Maybe<PluralCloudSettings>;
/** Get a cluster by its ID. */
cluster?: Maybe<Cluster>;
/** Get a list of clusters owned by the current account. */
Expand Down Expand Up @@ -6022,7 +6039,7 @@ export type LoginMutationVariables = Exact<{
email: Scalars['String']['input'];
password: Scalars['String']['input'];
deviceToken?: InputMaybe<Scalars['String']['input']>;
captcha?: InputMaybe<Scalars['String']['input']>;
captcha: Scalars['String']['input'];
}>;


Expand Down Expand Up @@ -10789,7 +10806,7 @@ export type DevLoginMutationHookResult = ReturnType<typeof useDevLoginMutation>;
export type DevLoginMutationResult = Apollo.MutationResult<DevLoginMutation>;
export type DevLoginMutationOptions = Apollo.BaseMutationOptions<DevLoginMutation, DevLoginMutationVariables>;
export const LoginDocument = gql`
mutation Login($email: String!, $password: String!, $deviceToken: String, $captcha: String) {
mutation Login($email: String!, $password: String!, $deviceToken: String, $captcha: String!) {
login(
email: $email
password: $password
Expand Down
2 changes: 1 addition & 1 deletion www/src/graph/users.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ mutation Login(
$email: String!
$password: String!
$deviceToken: String
$captcha: String
$captcha: String!
) {
login(
email: $email
Expand Down

0 comments on commit 368691e

Please sign in to comment.