Class: YiffSpace::LogtoManagementClient

Inherits:
Object
  • Object
show all
Defined in:
lib/yiffspace/logto_management_client.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(auth) ⇒ LogtoManagementClient

Returns a new instance of LogtoManagementClient.



10
11
12
# File 'lib/yiffspace/logto_management_client.rb', line 10

def initialize(auth)
  @auth = auth
end

Instance Attribute Details

#authObject (readonly)

Returns the value of attribute auth.



8
9
10
# File 'lib/yiffspace/logto_management_client.rb', line 8

def auth
  @auth
end

Instance Method Details

#create_user(id) ⇒ Object



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/yiffspace/logto_management_client.rb', line 47

def create_user(id)
  details = auth.fetch_discord_user(id)&.data
  raise("invalid discord user: #{id}") if details.blank?

  response = HTTParty.post("#{auth.server_url}/api/users", {
    headers: { "Authorization" => "Bearer #{get_token}", "Content-Type" => "application/json" },
    body:    { avatar: "https://cdn.discordapp.com/avatars/#{details['id']}/#{details['avatar']}", name: details["username"] }.to_json,
  })
  raise("failed to create user: #{response.code} #{response.message}\n#{response.parsed_response.inspect}") if response.code != 200

  response2 = HTTParty.put("#{auth.server_url}/api/users/#{response.parsed_response['id']}/identities/discord", {
    headers: { "Authorization" => "Bearer #{get_token}", "Content-Type" => "application/json" },
    body:    {
      userId:  details["id"],
      details: {
        id:      details["id"],
        name:    details["username"],
        avatar:  "https://cdn.discordapp.com/avatars/#{details['id']}/#{details['avatar']}",
        rawData: details,
      },
    }.to_json,
  })
  raise("failed to add discord identity: #{response2.code} #{response2.message}\n#{response2.parsed_response.inspect}") if response2.code != 201

  Auth::ApiUser.new(response.parsed_response)
end

#get_or_create_user(id) ⇒ Object



74
75
76
# File 'lib/yiffspace/logto_management_client.rb', line 74

def get_or_create_user(id)
  get_user(id) || create_user(id)
end

#get_role_scopes(role_id) ⇒ Object



93
94
95
96
97
98
# File 'lib/yiffspace/logto_management_client.rb', line 93

def get_role_scopes(role_id)
  response = HTTParty.get("#{auth.server_url}/api/roles/#{role_id}/scopes", { headers: { "Authorization" => "Bearer #{get_token}" } })
  raise("failed to get role scopes: #{response.code} #{response.message}\n#{response.parsed_response.inspect}") if response.code != 200

  response.parsed_response
end

#get_tokenObject

rubocop:disable Naming/AccessorMethodName



14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/yiffspace/logto_management_client.rb', line 14

def get_token # rubocop:disable Naming/AccessorMethodName
  if @_cached_token
    return @_cached_token if @_cache_expire_time > Time.current

    @_cached_token = nil
    @_cache_expire_time = nil
  end
  response = HTTParty.post("#{auth.server_url}/oidc/token", {
    body: {
      grant_type:    "client_credentials",
      client_id:     YiffSpace.config.logto_api_client_id,
      client_secret: YiffSpace.config.logto_api_client_secret,
      resource:      YiffSpace.config.logto_api_resource,
      scope:         "all",
    },
  })
  raise("failed to get access token: #{response.to_json}") unless response.key?("access_token")

  @_cached_token = response["access_token"]
  @_cache_expire_time = response["expires_in"].to_i.seconds.from_now
  response["access_token"]
end

#get_user(id) ⇒ Object



37
38
39
40
41
42
43
44
45
# File 'lib/yiffspace/logto_management_client.rb', line 37

def get_user(id)
  response = HTTParty.get("#{auth.server_url}/api/users?discordId=#{id}", { headers: { "Authorization" => "Bearer #{get_token}" } })
  return nil if response.code == 404 || (response.parsed_response.is_a?(Array) && response.parsed_response.empty?)
  raise("failed to get user: #{response.code} #{response.message}\n#{response.parsed_response.inspect}") if response.code != 200 || !response.parsed_response.is_a?(Array)

  Utils::TraceLogger.warn("LogtoManagementClient", "query discordId=#{id} returned more than one user:\n#{response.parsed_response.inspect}") if response.parsed_response.length > 1

  Auth::ApiUser.new(response.parsed_response.first)
end

#get_user_by_id(logto_id) ⇒ Object



78
79
80
81
82
83
84
# File 'lib/yiffspace/logto_management_client.rb', line 78

def get_user_by_id(logto_id)
  response = HTTParty.get("#{auth.server_url}/api/users/#{logto_id}", { headers: { "Authorization" => "Bearer #{get_token}" } })
  return nil if response.code == 404
  raise("failed to get user: #{response.code} #{response.message}\n#{response.parsed_response.inspect}") if response.code != 200

  Auth::ApiUser.new(response.parsed_response)
end

#get_user_roles(logto_id) ⇒ Object



86
87
88
89
90
91
# File 'lib/yiffspace/logto_management_client.rb', line 86

def get_user_roles(logto_id)
  response = HTTParty.get("#{auth.server_url}/api/users/#{logto_id}/roles", { headers: { "Authorization" => "Bearer #{get_token}" } })
  raise("failed to get user roles: #{response.code} #{response.message}\n#{response.parsed_response.inspect}") if response.code != 200

  response.parsed_response
end

#get_users_with_role(role_id) ⇒ Object



100
101
102
103
104
105
# File 'lib/yiffspace/logto_management_client.rb', line 100

def get_users_with_role(role_id)
  response = HTTParty.get("#{auth.server_url}/api/roles/#{role_id}/users", { headers: { "Authorization" => "Bearer #{get_token}" } })
  raise("failed to get users with role: #{response.code} #{response.message}\n#{response.parsed_response.inspect}") if response.code != 200

  response.parsed_response
end