diff --git a/client/app/pages/user-account/user-account.tsx b/client/app/pages/user-account/user-account.tsx index ae28884..473b387 100644 --- a/client/app/pages/user-account/user-account.tsx +++ b/client/app/pages/user-account/user-account.tsx @@ -19,6 +19,7 @@ interface State { selectedAvatarIndex: number; insufficientScope?: boolean; noCharacters: boolean; + region: 'us' | 'eu'; } @inject('userStore') @@ -31,6 +32,7 @@ export class UserAccount extends React.Component { noCharacters: false, selectedCharIndex: 0, selectedAvatarIndex: 0, + region: 'us', // default to US api }; } @@ -48,8 +50,9 @@ export class UserAccount extends React.Component { } async getCharacters() { + const { region } = this.state; try { - const res = await UserService.getCharacters() as any; + const res = await UserService.getCharacters({ region }); if (res.characters) { if (res.characters.length === 0) { this.setState({ noCharacters: true }); @@ -60,6 +63,7 @@ export class UserAccount extends React.Component { characters, selectedRealm: res.characters[0].realm, insufficientScope: false, + noCharacters: false, }); } else { this.setState({ insufficientScope: true }); @@ -92,7 +96,9 @@ export class UserAccount extends React.Component { const { name, guild, realm } = this.selectedCharacter(); const selectedAvatar = this.selectedCharacter().avatarList![this.state.selectedAvatarIndex].title; const charClass = CharacterService.getClass(this.selectedCharacter().class); + const { region } = this.state; const data = { + region, character_name: name, character_class: charClass.name, character_guild: guild, @@ -165,21 +171,17 @@ export class UserAccount extends React.Component { render() { - if (this.state.noCharacters) { - return
You have no WoW characters in your account.
; - } - // user must be logged in to view this page if (!this.props.userStore!.user) { return
; } const { battletag, character_name, character_class, character_guild, character_realm, character_avatar } = this.props.userStore!.user!; - const { insufficientScope } = this.state; + const { insufficientScope, noCharacters } = this.state; return ( - +
{character_avatar && }
@@ -194,6 +196,14 @@ export class UserAccount extends React.Component {
+ {noCharacters && + + } +
{insufficientScope === true ? this.renderScopeError() : this.renderDropDowns()}
diff --git a/client/app/services/user.service.ts b/client/app/services/user.service.ts index dc87f85..c2e474c 100644 --- a/client/app/services/user.service.ts +++ b/client/app/services/user.service.ts @@ -15,9 +15,9 @@ const login = async (username: string, password: string): Promise => { userStore.setUser(res.data.data); }; -const getCharacters = async (): Promise => { +const getCharacters = async (params: any): Promise => { try { - const res = await axios.get('/api/user/characters'); + const res = await axios.get('/api/user/characters', { params }); const characters = res.data.data.characters; if (!!characters) { res.data.data.characters = filterCharacters(characters); diff --git a/lib/myapp/battle_net/user.ex b/lib/myapp/battle_net/user.ex index 8df079b..8a0c8f2 100644 --- a/lib/myapp/battle_net/user.ex +++ b/lib/myapp/battle_net/user.ex @@ -2,18 +2,20 @@ defmodule MyApp.BattleNet.User do @type battle_net_user :: %{"battle_net_id": integer, "battletag": String.t, "access_token": String.t} - def api_url, do: "https://us.api.battle.net" + def api_url(region), do: "https://#{region}.api.battle.net" + + def cache_key(user_id, region), do: "usr_char:#{user_id}:#{region}" # grab user information from battle net api - use token for auth - @spec get_user(String.t | {atom, any}) :: {:ok, battle_net_user} | {:error, any} - def get_user(access_token) when is_binary(access_token) do + @spec get_user(String.t | {atom, any}, String.t) :: {:ok, battle_net_user} | {:error, any} + def get_user(access_token, region) when is_binary(access_token) do access_token - |> resource_url("account/user") + |> resource_url("account/user", region) |> HTTPoison.get |> parse_user_response(access_token) end - def get_user({:ok, access_token}), do: get_user(access_token) - def get_user({:error, error}), do: {:error, error} + def get_user({:ok, access_token}, region), do: get_user(access_token, region) + def get_user({:error, error}, _), do: {:error, error} defp parse_user_response({:error, error}, _), do: {:error, error} defp parse_user_response({:ok, %HTTPoison.Response{body: body}}, access_token) do @@ -28,36 +30,37 @@ defmodule MyApp.BattleNet.User do end end - # end point is cached for one minute per user - @spec get_user_characters(integer, String.t) :: {:ok, map} | {:error, any} - def get_user_characters(user_id, access_token) do - case Cachex.get(:myapp, "usr_char:#{user_id}") do - {:ok, data} -> {:ok, data} + # end point is cached for ten minutes per user + @spec get_user_characters(integer, String.t, String.t) :: {:ok, map} | {:error, any} + def get_user_characters(user_id, access_token, region) do + case Cachex.get(:myapp, cache_key(user_id, region)) do + {:ok, data} -> + {:ok, data} {:missing, _} -> access_token - |> resource_url("wow/user/characters") + |> resource_url("wow/user/characters", region) |> HTTPoison.get - |> parse_character_response(user_id) + |> parse_character_response(user_id, region) end end - defp parse_character_response({:error, error}, _), do: {:error, error} - defp parse_character_response({:ok, %HTTPoison.Response{body: body}}, user_id) do + defp parse_character_response({:error, error}, _, _), do: {:error, error} + defp parse_character_response({:ok, %HTTPoison.Response{body: body}}, user_id, region) do case Poison.decode(body) do {:ok, data} -> # only cache end point if characters return if (!data["characters"]) do {:error, data} else - Cachex.set(:myapp, "usr_char:#{user_id}", data, ttl: :timer.minutes(10)) # 10 minutes + Cachex.set(:myapp, cache_key(user_id, region), data, ttl: :timer.minutes(10)) # 10 minutes end {:ok, data} {:error, error} -> {:error, error} end end - defp resource_url(access_token, path) do - "#{api_url()}/#{path}?access_token=#{access_token}" + defp resource_url(access_token, path, region) do + "#{api_url(region)}/#{path}?access_token=#{access_token}" end end diff --git a/lib/myapp_web/controllers/page_controller.ex b/lib/myapp_web/controllers/page_controller.ex index a771cdc..8dce593 100644 --- a/lib/myapp_web/controllers/page_controller.ex +++ b/lib/myapp_web/controllers/page_controller.ex @@ -8,7 +8,7 @@ defmodule MyAppWeb.PageController do # cache index.html if prod file = case System.get_env("MIX_ENV") do :prod -> - file = Cachex.get(:myapp, "index.html") + Cachex.get(:myapp, "index.html") |> get_file _ -> File.read!(Application.app_dir(:myapp, "priv/static/index.html")) end diff --git a/lib/myapp_web/controllers/thread_controller.ex b/lib/myapp_web/controllers/thread_controller.ex index f723542..642d5c6 100644 --- a/lib/myapp_web/controllers/thread_controller.ex +++ b/lib/myapp_web/controllers/thread_controller.ex @@ -34,22 +34,6 @@ defmodule MyAppWeb.ThreadController do |> Response.json(output) end - @spec update(map, map) :: any - def update(conn, params) do - user_id = conn - |> MyApp.Guardian.Plug.current_claims - |> Map.get("id") - - {output, status} = params - |> Map.put("user_id", user_id) - |> Data.Thread.user_update - |> Response.put_resp - - conn - |> put_status(status) - |> Response.json(output) - end - @spec get_collection(map, map) :: any def get_collection(conn, params) do diff --git a/lib/myapp_web/controllers/user_controller.ex b/lib/myapp_web/controllers/user_controller.ex index 68ef267..0f44518 100644 --- a/lib/myapp_web/controllers/user_controller.ex +++ b/lib/myapp_web/controllers/user_controller.ex @@ -5,8 +5,6 @@ defmodule MyAppWeb.UserController do alias MyApp.Data alias MyApp.Guardian.Auth - # https://us.battle.net/oauth/authorize?redirect_uri=https://localhost/api/battlenet/authorize&scope=wow.profile&client_id=vxqv32fddxsy6cmk6259amtymbuzmfrq&response_type=code - # this is for auth with username/password - currently only for admin def login(conn, params) do {output, status} = params @@ -25,7 +23,11 @@ defmodule MyAppWeb.UserController do {output, status} = code |> BattleNet.Auth.get_access_token - |> BattleNet.User.get_user + # TODO: support for other regions maybe? + # right now a US user can auth with the EU end point + # maybe it works vice versa? Unable to test it out + # because I don't have a test eu account + |> BattleNet.User.get_user("us") |> Data.User.upsert_user |> Auth.Token.add_token_and_map_claims |> Response.put_resp @@ -35,13 +37,15 @@ defmodule MyAppWeb.UserController do |>Response.json(output) end - def characters(conn, _params) do + def characters(conn, params) do + region = Map.get(params, "region") + %{"access_token" => token, "id" => user_id} = conn |> MyApp.Guardian.Plug.current_claims |> Map.take(["access_token", "id"]) {output, status} = user_id - |> BattleNet.User.get_user_characters(token) + |> BattleNet.User.get_user_characters(token, region) |> Response.put_resp conn @@ -55,7 +59,7 @@ defmodule MyAppWeb.UserController do |> Map.take(["id", "access_token"]) # validate the character exists in users WoW profile - {:ok, characterList} = BattleNet.User.get_user_characters(user_id, access_token) + {:ok, characterList} = BattleNet.User.get_user_characters(user_id, access_token, params["region"]) exists = Enum.find(characterList["characters"], fn(char) -> char["name"] == params["character_name"] && char["realm"] == params["character_realm"] end) diff --git a/lib/myapp_web/router.ex b/lib/myapp_web/router.ex index 11e964e..715fd48 100644 --- a/lib/myapp_web/router.ex +++ b/lib/myapp_web/router.ex @@ -38,7 +38,6 @@ defmodule MyAppWeb.Router do # authenticated routes pipe_through [:user_auth] post "/", ThreadController, :insert - put "/", ThreadController, :update pipe_through [:mod_auth] put "/mod", ThreadController, :mod_update