mirror of
https://github.com/discourse/discourse.git
synced 2025-02-25 18:55:32 -06:00
FEATURE: Automatically expire keys if not used for a configurable amount of time. (#6264)
This commit is contained in:
parent
1d913d3204
commit
860c1c3dcd
@ -18,6 +18,7 @@
|
||||
</ul>
|
||||
</p>
|
||||
<p><span>{{i18n "user.api_approved"}}</span> {{bound-date key.created_at}}</p>
|
||||
<p><span>{{i18n "user.api_last_used_at"}}</span> {{bound-date key.last_used_at}}</p>
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
|
15
app/jobs/scheduled/auto_expire_user_api_keys.rb
Normal file
15
app/jobs/scheduled/auto_expire_user_api_keys.rb
Normal file
@ -0,0 +1,15 @@
|
||||
module Jobs
|
||||
|
||||
class AutoExpireUserApiKeys < Jobs::Scheduled
|
||||
every 1.day
|
||||
|
||||
def execute(args)
|
||||
if SiteSetting.expire_user_api_keys_days > 0
|
||||
expire_user_api_keys_days = SiteSetting.expire_user_api_keys_days.days.ago
|
||||
|
||||
UserApiKey.where("last_used_at < ?", expire_user_api_keys_days).update_all(revoked_at: Time.zone.now)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
@ -74,6 +74,7 @@ end
|
||||
# updated_at :datetime not null
|
||||
# revoked_at :datetime
|
||||
# scopes :text default([]), not null, is an Array
|
||||
# last_used_at :datetime not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
|
@ -184,10 +184,12 @@ class UserSerializer < BasicUserSerializer
|
||||
id: k.id,
|
||||
application_name: k.application_name,
|
||||
scopes: k.scopes.map { |s| I18n.t("user_api_key.scopes.#{s}") },
|
||||
created_at: k.created_at
|
||||
created_at: k.created_at,
|
||||
last_used_at: k.last_used_at,
|
||||
}
|
||||
end
|
||||
|
||||
keys.sort! { |a, b| a.last_used_at.to_time > b.last_used_at.to_time }
|
||||
keys.length > 0 ? keys : nil
|
||||
end
|
||||
|
||||
|
@ -704,6 +704,7 @@ en:
|
||||
revoke_access: "Revoke Access"
|
||||
undo_revoke_access: "Undo Revoke Access"
|
||||
api_approved: "Approved:"
|
||||
api_last_used_at: "Last used at:"
|
||||
theme: "Theme"
|
||||
home: "Default Home Page"
|
||||
staged: "Staged"
|
||||
|
@ -1770,6 +1770,7 @@ en:
|
||||
min_trust_level_for_user_api_key: "Trust level required for generation of user API keys"
|
||||
allowed_user_api_auth_redirects: "Allowed URL for authentication redirect for user API keys"
|
||||
allowed_user_api_push_urls: "Allowed URLs for server push to user API"
|
||||
expire_user_api_keys_days: "Number of days before an user API key automatically expires (0 for never)"
|
||||
|
||||
tagging_enabled: "Enable tags on topics?"
|
||||
min_trust_to_create_tag: "The minimum trust level required to create a tag."
|
||||
|
@ -1681,6 +1681,8 @@ user_api:
|
||||
allowed_user_api_auth_redirects:
|
||||
default: 'https://api.discourse.org/api/auth_redirect|discourse://auth_redirect'
|
||||
type: list
|
||||
expire_user_api_keys_days:
|
||||
default: 180
|
||||
|
||||
tags:
|
||||
tagging_enabled:
|
||||
|
@ -0,0 +1,5 @@
|
||||
class AddUserApiKeysLastUsedAt < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
add_column :user_api_keys, :last_used_at, :datetime, null: false, default: -> { 'CURRENT_TIMESTAMP' }
|
||||
end
|
||||
end
|
@ -258,6 +258,7 @@ class Auth::DefaultCurrentUserProvider
|
||||
raise Discourse::InvalidAccess
|
||||
end
|
||||
|
||||
api_key.update_columns(last_used_at: Time.zone.now)
|
||||
if client_id.present? && client_id != api_key.client_id
|
||||
api_key.update_columns(client_id: client_id)
|
||||
end
|
||||
|
16
spec/integration/user_api_keys_spec.rb
Normal file
16
spec/integration/user_api_keys_spec.rb
Normal file
@ -0,0 +1,16 @@
|
||||
require 'rails_helper'
|
||||
|
||||
describe 'user api keys integration' do
|
||||
|
||||
let(:user_api_key) { Fabricate(:readonly_user_api_key) }
|
||||
|
||||
it 'updates last used time on use' do
|
||||
user_api_key.update_columns(last_used_at: 7.days.ago)
|
||||
|
||||
freeze_time
|
||||
get '/session/current.json', headers: {
|
||||
HTTP_USER_API_KEY: user_api_key.key,
|
||||
}
|
||||
expect(user_api_key.reload.last_used_at).to eq(Time.zone.now)
|
||||
end
|
||||
end
|
24
spec/jobs/auto_expire_user_api_keys.rb
Normal file
24
spec/jobs/auto_expire_user_api_keys.rb
Normal file
@ -0,0 +1,24 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Jobs::AutoExpireUserApiKeys do
|
||||
let(:key1) { Fabricate(:readonly_user_api_key) }
|
||||
let(:key2) { Fabricate(:readonly_user_api_key) }
|
||||
|
||||
context 'when user api key is unused in last 1 days' do
|
||||
|
||||
before do
|
||||
SiteSetting.expire_user_api_keys_days = true
|
||||
end
|
||||
|
||||
it 'should revoke the key' do
|
||||
freeze_time
|
||||
|
||||
key1.update!(last_used_at: 2.days.ago)
|
||||
|
||||
described_class.new.execute({})
|
||||
|
||||
expect(key1.reload.revoked_at).to eq(Time.zone.now)
|
||||
expect(key2.reload.revoked_at).to eq(nil)
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue
Block a user