FEATURE: basic UI to view user api keys
This commit is contained in:
parent
b7cea24d76
commit
416e7e0d1e
|
@ -73,6 +73,46 @@ const User = RestModel.extend({
|
|||
return Discourse.getURL(`/users/${this.get('username_lower')}`);
|
||||
},
|
||||
|
||||
@computed()
|
||||
userApiKeys() {
|
||||
const keys = this.get('user_api_keys');
|
||||
if (keys) {
|
||||
return keys.map((raw)=>{
|
||||
let obj = Em.Object.create(
|
||||
raw
|
||||
);
|
||||
|
||||
obj.revoke = () => {
|
||||
this.revokeApiKey(obj);
|
||||
};
|
||||
|
||||
obj.undoRevoke = () => {
|
||||
this.undoRevokeApiKey(obj);
|
||||
};
|
||||
|
||||
return obj;
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
revokeApiKey(key) {
|
||||
return ajax("/user-api-key/revoke", {
|
||||
type: 'POST',
|
||||
data: { id: key.get('id') }
|
||||
}).then(()=>{
|
||||
key.set('revoked', true);
|
||||
});
|
||||
},
|
||||
|
||||
undoRevokeApiKey(key){
|
||||
return ajax("/user-api-key/undo-revoke", {
|
||||
type: 'POST',
|
||||
data: { id: key.get('id') }
|
||||
}).then(()=>{
|
||||
key.set('revoked', false);
|
||||
});
|
||||
},
|
||||
|
||||
pmPath(topic) {
|
||||
const userId = this.get('id');
|
||||
const username = this.get('username_lower');
|
||||
|
|
|
@ -19,7 +19,15 @@ export default Discourse.Route.extend({
|
|||
const isIndexStream = INDEX_STREAM_ROUTES.indexOf(transition.targetName) !== -1;
|
||||
this.controllerFor('user').set('indexStream', isIndexStream);
|
||||
return true;
|
||||
}
|
||||
},
|
||||
|
||||
undoRevokeApiKey(key) {
|
||||
key.undoRevoke();
|
||||
},
|
||||
|
||||
revokeApiKey(key) {
|
||||
key.revoke();
|
||||
},
|
||||
},
|
||||
|
||||
beforeModel() {
|
||||
|
|
|
@ -319,6 +319,26 @@
|
|||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{#if model.userApiKeys}}
|
||||
<div class="control-group apps">
|
||||
<label class="control-label">{{i18n 'user.apps'}}</label>
|
||||
<div class="controls">
|
||||
{{#each model.userApiKeys as |key|}}
|
||||
<div>
|
||||
<span>{{key.application_name}}</span>
|
||||
{{#if key.revoked}}
|
||||
{{d-button action="undoRevokeApiKey" actionParam=key class="btn" label="user.undo_revoke_access"}}
|
||||
{{else}}
|
||||
{{d-button action="revokeApiKey" actionParam=key class="btn" label="user.revoke_access"}}
|
||||
{{/if}}
|
||||
<p><span>{{i18n "user.api_permissions"}}</span> {{#if key.write}}{{i18n "user.api_read_write"}}{{else}}{{i18n "user.api_read"}}{{/if}}</p>
|
||||
<p><span>{{i18n "user.api_approved"}}</span> {{bound-date key.created_at}}</p>
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{plugin-outlet "user-custom-controls"}}
|
||||
|
||||
<div class="control-group save-button">
|
||||
|
|
|
@ -4,7 +4,7 @@ class UserApiKeysController < ApplicationController
|
|||
|
||||
skip_before_filter :redirect_to_login_if_required, only: [:new]
|
||||
skip_before_filter :check_xhr, :preload_json
|
||||
before_filter :ensure_logged_in, only: [:create]
|
||||
before_filter :ensure_logged_in, only: [:create, :revoke, :undo_revoke]
|
||||
|
||||
def new
|
||||
require_params
|
||||
|
@ -47,6 +47,9 @@ class UserApiKeysController < ApplicationController
|
|||
|
||||
validate_params
|
||||
|
||||
# destroy any old keys we had
|
||||
UserApiKey.where(user_id: current_user.id, client_id: params[:client_id]).destroy_all
|
||||
|
||||
key = UserApiKey.create!(
|
||||
application_name: params[:application_name],
|
||||
client_id: params[:client_id],
|
||||
|
@ -72,6 +75,22 @@ class UserApiKeysController < ApplicationController
|
|||
redirect_to "#{params[:auth_redirect]}?payload=#{CGI.escape(payload)}"
|
||||
end
|
||||
|
||||
def revoke
|
||||
find_key.update_columns(revoked_at: Time.zone.now)
|
||||
render json: success_json
|
||||
end
|
||||
|
||||
def undo_revoke
|
||||
find_key.update_columns(revoked_at: nil)
|
||||
render json: success_json
|
||||
end
|
||||
|
||||
def find_key
|
||||
key = UserApiKey.find(params[:id])
|
||||
raise Discourse::InvalidAccess unless current_user.admin || key.user_id = current_user.id
|
||||
key
|
||||
end
|
||||
|
||||
def require_params
|
||||
[
|
||||
:public_key,
|
||||
|
|
|
@ -19,6 +19,7 @@ class User < ActiveRecord::Base
|
|||
has_many :topic_users, dependent: :destroy
|
||||
has_many :category_users, dependent: :destroy
|
||||
has_many :tag_users, dependent: :destroy
|
||||
has_many :user_api_keys, dependent: :destroy
|
||||
has_many :topics
|
||||
has_many :user_open_ids, dependent: :destroy
|
||||
has_many :user_actions, dependent: :destroy
|
||||
|
|
|
@ -102,7 +102,8 @@ class UserSerializer < BasicUserSerializer
|
|||
:card_image_badge_id,
|
||||
:muted_usernames,
|
||||
:mailing_list_posts_per_day,
|
||||
:can_change_bio
|
||||
:can_change_bio,
|
||||
:user_api_keys
|
||||
|
||||
untrusted_attributes :bio_raw,
|
||||
:bio_cooked,
|
||||
|
@ -137,6 +138,21 @@ class UserSerializer < BasicUserSerializer
|
|||
!(SiteSetting.enable_sso && SiteSetting.sso_overrides_bio)
|
||||
end
|
||||
|
||||
|
||||
def user_api_keys
|
||||
keys = object.user_api_keys.where(revoked_at: nil).map do |k|
|
||||
{
|
||||
id: k.id,
|
||||
application_name: k.application_name,
|
||||
read: k.read,
|
||||
write: k.write,
|
||||
created_at: k.created_at
|
||||
}
|
||||
end
|
||||
|
||||
keys.length > 0 ? keys : nil
|
||||
end
|
||||
|
||||
def card_badge
|
||||
object.user_profile.card_image_badge
|
||||
end
|
||||
|
|
|
@ -571,6 +571,13 @@ en:
|
|||
muted_topics_link: "Show muted topics"
|
||||
watched_topics_link: "Show watched topics"
|
||||
automatically_unpin_topics: "Automatically unpin topics when I reach the bottom."
|
||||
apps: "Apps"
|
||||
revoke_access: "Revoke Access"
|
||||
undo_revoke_access: "Undo Revoke Access"
|
||||
api_permissions: "Permissions:"
|
||||
api_approved: "Approved:"
|
||||
api_read: "read"
|
||||
api_read_write: "read and write"
|
||||
|
||||
staff_counters:
|
||||
flags_given: "helpful flags"
|
||||
|
|
|
@ -664,6 +664,8 @@ Discourse::Application.routes.draw do
|
|||
|
||||
get "/user-api-key/new" => "user_api_keys#new"
|
||||
post "/user-api-key" => "user_api_keys#create"
|
||||
post "/user-api-key/revoke" => "user_api_keys#revoke"
|
||||
post "/user-api-key/undo-revoke" => "user_api_keys#undo_revoke"
|
||||
|
||||
get "*url", to: 'permalinks#show', constraints: PermalinkConstraint.new
|
||||
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
class UserApiClientIdIsUnique < ActiveRecord::Migration
|
||||
def change
|
||||
remove_index :user_api_keys, [:client_id]
|
||||
add_index :user_api_keys, [:client_id], unique: true
|
||||
end
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
class AddRevokedAtToUserApiKeys < ActiveRecord::Migration
|
||||
def change
|
||||
add_column :user_api_keys, :revoked_at, :datetime
|
||||
end
|
||||
end
|
|
@ -177,7 +177,7 @@ class Auth::DefaultCurrentUserProvider
|
|||
protected
|
||||
|
||||
def lookup_user_api_user(user_api_key)
|
||||
if api_key = UserApiKey.where(key: user_api_key).includes(:user).first
|
||||
if api_key = UserApiKey.where(key: user_api_key, revoked_at: nil).includes(:user).first
|
||||
if !api_key.write && @env["REQUEST_METHOD"] != "GET"
|
||||
raise Discourse::InvalidAccess
|
||||
end
|
||||
|
|
|
@ -127,6 +127,11 @@ TXT
|
|||
uri.query = ""
|
||||
expect(uri.to_s).to eq(args[:auth_redirect] + "?")
|
||||
|
||||
# should overwrite if needed
|
||||
args["access"] = "pr"
|
||||
post :create, args
|
||||
|
||||
expect(response.code).to eq("302")
|
||||
end
|
||||
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue