Skip to content

Commit 368691e

Browse files
Support me-central-1 region for dedicated hosting (#1369)
1 parent 8a1f16f commit 368691e

File tree

16 files changed

+114
-19
lines changed

16 files changed

+114
-19
lines changed

apps/api/lib/api_web/endpoint.ex

+5
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@ defmodule ApiWeb.Endpoint do
3333
plug Plug.RequestId
3434
plug Plug.Telemetry, event_prefix: [:phoenix, :endpoint]
3535

36+
plug Hammer.Plug, [
37+
rate_limit: {"api.global", 60_000, 1000},
38+
by: :ip
39+
]
40+
3641
plug Plug.Parsers,
3742
parsers: [:urlencoded, {:multipart, length: @upload_maximum}, ApiWeb.Parsers.ApplicationJson],
3843
pass: ["*/*"],

apps/api/mix.exs

+1
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ defmodule Api.MixProject do
8080
{:prometheus_ex, "~> 3.0"},
8181
{:prometheus_plugs, "~> 1.1.1"},
8282
{:remote_ip, "~> 0.2.0"},
83+
{:hammer_plug, "~> 3.0"},
8384
{:k8s_traffic_plug, github: "Financial-Times/k8s_traffic_plug"},
8485

8586
{:core, in_umbrella: true},

apps/core/lib/core/schema/console_instance.ex

+8-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,12 @@ defmodule Core.Schema.ConsoleInstance do
1616
stack_deleted: 7
1717

1818
@region_map %{
19-
aws: ~w(us-east-1)
19+
shared: %{
20+
aws: ~w(us-east-1)
21+
},
22+
dedicated: %{
23+
aws: ~w(us-east-1 me-central-1)
24+
}
2025
}
2126

2227
schema "console_instances" do
@@ -134,7 +139,8 @@ defmodule Core.Schema.ConsoleInstance do
134139

135140
defp validate_region(cs) do
136141
cloud = get_field(cs, :cloud)
137-
regions = @region_map[cloud]
142+
type = get_field(cs, :type)
143+
regions = @region_map[type][cloud]
138144
validate_change(cs, :region, fn :region, reg ->
139145
case reg in regions do
140146
true -> []

apps/core/lib/core/schema/user.ex

+2-2
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ defmodule Core.Schema.User do
204204
|> validate_required([:name, :email])
205205
|> validate_length(:email, max: 255)
206206
|> validate_length(:name, max: 255)
207-
|> validate_length(:password, min: 10)
207+
|> validate_length(:password, min: 10, max: 255)
208208
|> validate_format(:email, @email_re)
209209
|> hash_password()
210210
|> generate_uuid(:avatar_id)
@@ -254,7 +254,7 @@ defmodule Core.Schema.User do
254254
|> add_email(model)
255255
|> validate_length(:email, max: 255)
256256
|> validate_length(:name, max: 255)
257-
|> validate_length(:password, min: 10)
257+
|> validate_length(:password, min: 10, max: 255)
258258
|> validate_format(:email, @email_re)
259259
|> unique_constraint(:email)
260260
|> validate_required([:name, :email])

apps/core/lib/core/services/cloud/workflow.ex

-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
defmodule Core.Services.Cloud.Workflow do
22
use Core.Services.Base
33
alias Core.Repo
4-
alias Core.Clients.Console
54
alias Core.Schema.{ConsoleInstance}
65
alias Core.Services.Cloud.Workflow.{Dedicated, Shared}
76

apps/core/lib/core/services/cloud/workflow/shared.ex

+2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ defmodule Core.Services.Cloud.Workflow.Shared do
88
alias Core.Schema.{ConsoleInstance, PostgresCluster, User}
99
alias Core.Repo
1010

11+
require Logger
12+
1113
@behaviour Core.Services.Cloud.Workflow
1214

1315
def sync(%ConsoleInstance{external_id: id} = instance) when is_binary(id) do

apps/core/lib/core/services/users.ex

+2-2
Original file line numberDiff line numberDiff line change
@@ -715,8 +715,8 @@ defmodule Core.Services.Users do
715715
|> when_ok(&delete_eab_key/1)
716716
end
717717

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

722722
defp materialize_eab_key(cluster, provider, %User{id: user_id}) do

apps/graphql/lib/graphql/resolvers/cloud.ex

+6
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@ defmodule GraphQl.Resolvers.Cloud do
22
use GraphQl.Resolvers.Base, model: Core.Schema.ConsoleInstance
33
alias Core.Services.{Cloud, Clusters}
44

5+
def resolve_settings(_, _) do
6+
{:ok, %{
7+
regions: ConsoleInstance.regions()
8+
}}
9+
end
10+
511
def resolve_instance(%{id: id}, %{context: %{current_user: user}}),
612
do: Cloud.visible(id, user)
713

apps/graphql/lib/graphql/schema/cloud.ex

+19
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,28 @@ defmodule GraphQl.Schema.Cloud do
4545
timestamps()
4646
end
4747

48+
object :plural_cloud_settings do
49+
field :regions, :plural_cloud_regions
50+
end
51+
52+
object :plural_cloud_regions do
53+
field :shared, non_null(:cloud_regions)
54+
field :dedicated, non_null(:cloud_regions)
55+
end
56+
57+
object :cloud_regions do
58+
field :aws, list_of(:string)
59+
end
60+
4861
connection node_type: :console_instance
4962

5063
object :cloud_queries do
64+
field :cloud_settings, :plural_cloud_settings do
65+
middleware Authenticated
66+
67+
resolve &Cloud.resolve_settings/2
68+
end
69+
5170
field :console_instance, :console_instance do
5271
middleware Authenticated
5372
arg :id, non_null(:id)

apps/graphql/lib/graphql/schema/user.ex

+2-1
Original file line numberDiff line numberDiff line change
@@ -476,7 +476,7 @@ defmodule GraphQl.Schema.User do
476476
arg :email, non_null(:string)
477477
arg :password, non_null(:string)
478478
arg :device_token, :string
479-
arg :captcha, :string
479+
arg :captcha, non_null(:string)
480480

481481
middleware Captcha
482482

@@ -558,6 +558,7 @@ defmodule GraphQl.Schema.User do
558558

559559
field :update_user, :user do
560560
middleware Authenticated
561+
middleware RateLimit, limit: 10, time: 60_000
561562
arg :id, :id
562563
arg :attributes, non_null(:user_attributes)
563564

apps/graphql/test/mutations/user_mutation_test.exs

+11-6
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,17 @@ defmodule GraphQl.UserMutationTest do
1313
})
1414

1515
{:ok, %{data: %{"login" => found}}} = run_query("""
16-
mutation Login($email: String!, $password: String!) {
17-
login(email: $email, password: $password) {
16+
mutation Login($email: String!, $password: String!, $captcha: String!) {
17+
login(email: $email, password: $password, captcha: $captcha) {
1818
id
1919
jwt
2020
}
2121
}
22-
""", %{"email" => "[email protected]", "password" => "super strong password"}, %{origin: "https://app.plural.sh"})
22+
""", %{
23+
"email" => "[email protected]",
24+
"password" => "super strong password",
25+
"captcha" => "valid_response"
26+
}, %{origin: "https://app.plural.sh"})
2327

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

114118
{:ok, %{data: %{"login" => found}}} = run_query("""
115-
mutation Login($email: String!, $password: String!, $deviceToken: String) {
116-
login(email: $email, password: $password, deviceToken: $deviceToken) {
119+
mutation Login($email: String!, $password: String!, $deviceToken: String, $captcha: String!) {
120+
login(email: $email, password: $password, deviceToken: $deviceToken, captcha: $captcha) {
117121
id
118122
jwt
119123
}
120124
}
121125
""", %{
122126
"email" => "[email protected]",
123127
"password" => "super strong password",
124-
"deviceToken" => token.token
128+
"deviceToken" => token.token,
129+
"captcha" => "valid_response"
125130
})
126131

127132
assert found["id"] == user.id

apps/graphql/test/queries/cloud_queries_test.exs

+18
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,24 @@ defmodule GraphQl.CloudQueriesTest do
22
use Core.SchemaCase, async: true
33
import GraphQl.TestHelpers
44

5+
describe "cloudSettings" do
6+
test "it can list supported regions" do
7+
{:ok, %{data: %{"cloudSettings" => settings}}} = run_query("""
8+
query {
9+
cloudSettings {
10+
regions {
11+
shared { aws }
12+
dedicated { aws }
13+
}
14+
}
15+
}
16+
""", %{}, %{current_user: insert(:user)})
17+
18+
refute Enum.empty?(settings["regions"]["shared"]["aws"])
19+
refute Enum.empty?(settings["regions"]["dedicated"]["aws"])
20+
end
21+
end
22+
523
describe "consoleInstances" do
624
test "it can fetch the cloud instances in your account" do
725
user = insert(:user)

mix.lock

+1
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@
7676
"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"},
7777
"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"},
7878
"hammer": {:hex, :hammer, "6.1.0", "f263e3c3e9946bd410ea0336b2abe0cb6260af4afb3a221e1027540706e76c55", [:make, :mix], [{:poolboy, "~> 1.5", [hex: :poolboy, repo: "hexpm", optional: false]}], "hexpm", "b47e415a562a6d072392deabcd58090d8a41182cf9044cdd6b0d0faaaf68ba57"},
79+
"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"},
7980
"hpax": {:hex, :hpax, "0.1.2", "09a75600d9d8bbd064cdd741f21fc06fc1f4cf3d0fcc335e5aa19be1a7235c84", [:mix], [], "hexpm", "2c87843d5a23f5f16748ebe77969880e29809580efdaccd615cd3bed628a8c13"},
8081
"httpoison": {:hex, :httpoison, "1.8.2", "9eb9c63ae289296a544842ef816a85d881d4a31f518a0fec089aaa744beae290", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "2bb350d26972e30c96e2ca74a1aaf8293d61d0742ff17f01e0279fef11599921"},
8182
"idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"},

schema/schema.graphql

+16-1
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,8 @@ type RootQueryType {
209209
"Get a list of clusters owned by the current account."
210210
clusters(after: String, first: Int, before: String, last: Int): ClusterConnection
211211

212+
cloudSettings: PluralCloudSettings
213+
212214
consoleInstance(id: ID!): ConsoleInstance
213215

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

221223
type RootMutationType {
222-
login(email: String!, password: String!, deviceToken: String, captcha: String): User
224+
login(email: String!, password: String!, deviceToken: String, captcha: String!): User
223225

224226
deviceLogin: DeviceLogin
225227

@@ -644,6 +646,19 @@ type ConsoleInstance {
644646
updatedAt: DateTime
645647
}
646648

649+
type PluralCloudSettings {
650+
regions: PluralCloudRegions
651+
}
652+
653+
type PluralCloudRegions {
654+
shared: CloudRegions!
655+
dedicated: CloudRegions!
656+
}
657+
658+
type CloudRegions {
659+
aws: [String]
660+
}
661+
647662
type ConsoleInstanceConnection {
648663
pageInfo: PageInfo!
649664
edges: [ConsoleInstanceEdge]

www/src/generated/graphql.ts

+20-3
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,11 @@ export enum CloudProvider {
385385
Aws = 'AWS'
386386
}
387387

388+
export type CloudRegions = {
389+
__typename?: 'CloudRegions';
390+
aws?: Maybe<Array<Maybe<Scalars['String']['output']>>>;
391+
};
392+
388393
export type CloudShell = {
389394
__typename?: 'CloudShell';
390395
aesKey: Scalars['String']['output'];
@@ -2208,6 +2213,17 @@ export type PlatformSubscriptionLineItems = {
22082213
quantity: Scalars['Int']['output'];
22092214
};
22102215

2216+
export type PluralCloudRegions = {
2217+
__typename?: 'PluralCloudRegions';
2218+
dedicated: CloudRegions;
2219+
shared: CloudRegions;
2220+
};
2221+
2222+
export type PluralCloudSettings = {
2223+
__typename?: 'PluralCloudSettings';
2224+
regions?: Maybe<PluralCloudRegions>;
2225+
};
2226+
22112227
export type PluralConfiguration = {
22122228
__typename?: 'PluralConfiguration';
22132229
gitCommit?: Maybe<Scalars['String']['output']>;
@@ -3408,7 +3424,7 @@ export type RootMutationTypeLinkPublisherArgs = {
34083424

34093425

34103426
export type RootMutationTypeLoginArgs = {
3411-
captcha?: InputMaybe<Scalars['String']['input']>;
3427+
captcha: Scalars['String']['input'];
34123428
deviceToken?: InputMaybe<Scalars['String']['input']>;
34133429
email: Scalars['String']['input'];
34143430
password: Scalars['String']['input'];
@@ -3733,6 +3749,7 @@ export type RootQueryType = {
37333749
charts?: Maybe<ChartConnection>;
37343750
chat?: Maybe<ChatMessage>;
37353751
closure?: Maybe<Array<Maybe<ClosureItem>>>;
3752+
cloudSettings?: Maybe<PluralCloudSettings>;
37363753
/** Get a cluster by its ID. */
37373754
cluster?: Maybe<Cluster>;
37383755
/** Get a list of clusters owned by the current account. */
@@ -6022,7 +6039,7 @@ export type LoginMutationVariables = Exact<{
60226039
email: Scalars['String']['input'];
60236040
password: Scalars['String']['input'];
60246041
deviceToken?: InputMaybe<Scalars['String']['input']>;
6025-
captcha?: InputMaybe<Scalars['String']['input']>;
6042+
captcha: Scalars['String']['input'];
60266043
}>;
60276044

60286045

@@ -10789,7 +10806,7 @@ export type DevLoginMutationHookResult = ReturnType<typeof useDevLoginMutation>;
1078910806
export type DevLoginMutationResult = Apollo.MutationResult<DevLoginMutation>;
1079010807
export type DevLoginMutationOptions = Apollo.BaseMutationOptions<DevLoginMutation, DevLoginMutationVariables>;
1079110808
export const LoginDocument = gql`
10792-
mutation Login($email: String!, $password: String!, $deviceToken: String, $captcha: String) {
10809+
mutation Login($email: String!, $password: String!, $deviceToken: String, $captcha: String!) {
1079310810
login(
1079410811
email: $email
1079510812
password: $password

www/src/graph/users.graphql

+1-1
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ mutation Login(
239239
$email: String!
240240
$password: String!
241241
$deviceToken: String
242-
$captcha: String
242+
$captcha: String!
243243
) {
244244
login(
245245
email: $email

0 commit comments

Comments
 (0)