Added token attributes last_used_at and expires_at.

This commit is contained in:
Thorsten Eckel 2016-08-30 16:26:27 +02:00
parent 105fca030d
commit fa4e953423
10 changed files with 101 additions and 15 deletions

View file

@ -81,9 +81,14 @@ class Create extends App.ControllerModal
shown: true
content: ->
App.view('profile/token_access_create')(
content = $(App.view('profile/token_access_create')(
permissions: @permissions
))
datepicker = App.UiElement.date.render(
name: 'expires_at',
)
content.find('.js-date').html(datepicker)
content
onSubmit: (e) =>
e.preventDefault()

View file

@ -16,27 +16,23 @@
<th><%- @T('Name') %></th>
<th><%- @T('Permission') %></th>
<th><%- @T('Created') %></th>
<!--
<th><%- @T('Expires') %></th>
<th><%- @T('Last used') %></th>
-->
<th><%- @T('Delete') %></th>
</tr>
</thead>
<tbody>
<% if _.isEmpty(@tokens): %>
<tr>
<td colspan="3"><%- @T('none') %>
<td colspan="6"><%- @T('none') %>
<% else: %>
<% for token in @tokens: %>
<tr>
<td><%= token.label %></td>
<td><% if token.preferences && token.preferences.permission: %><%= token.preferences.permission.join(', ') %><% end %></td>
<td><%- @humanTime(token.created_at) %></td>
<!--
<td><%- @humanTime(token.expired_at) %></td>
<td><%- @Tdate(token.expires_at) %></td>
<td><%- @humanTime(token.last_used_at) %></td>
-->
<td class="settings-list-controls">
<div>
<a class="settings-list-control js-delete" href="#" data-token-id="<%- token.id %>" title="<%- @Ti('Delete') %>"><%- @Icon('trash') %></a>

View file

@ -5,6 +5,13 @@
<div class="controls"><input id="token-label" type="text" name="label" value="" class="form-control js-input" required></div>
</div>
<div class="input form-group">
<div class="formGroup-label">
<label for="token-label"><%- @T('Expires') %></label>
</div>
<div class="controls js-date"></div>
</div>
<div class="permission form-group checkbox">
<div class="checkbox">
<% for permission in @permissions: %>

View file

@ -260,27 +260,40 @@ class ApplicationController < ActionController::Base
end
# check http token based authentication
authenticate_with_http_token do |token, _options|
logger.debug "http token auth check '#{token}'"
authenticate_with_http_token do |token_string, _options|
logger.debug "http token auth check '#{token_string}'"
request.session_options[:skip] = true # do not send a session cookie
if Setting.get('api_token_access') == false
raise Exceptions::NotAuthorized, 'API token access disabled!'
end
user = Token.check(
action: 'api',
name: token,
name: token_string,
inactive_user: true,
)
if user && auth_param[:permission]
user = Token.check(
action: 'api',
name: token,
name: token_string,
permission: auth_param[:permission],
inactive_user: true,
)
raise Exceptions::NotAuthorized, 'Not authorized (token)!' if !user
end
@_token_auth = token # remember for permission_check
if user
token = Token.find_by(name: token_string)
token.last_used_at = Time.zone.now
token.save!
if token.expires_at &&
Time.zone.today >= token.expires_at
raise Exceptions::NotAuthorized, 'Not authorized (token expired)!'
end
end
@_token_auth = token_string # remember for permission_check
return authentication_check_prerequesits(user, 'token_auth', auth_param) if user
end

View file

@ -53,6 +53,7 @@ class UserAccessTokenController < ApplicationController
label: params[:label],
persistent: true,
user_id: current_user.id,
expires_at: params[:expires_at],
preferences: {
permission: params[:permission]
}

View file

@ -40,11 +40,11 @@ returns
check token
user = Token.check(action: 'PasswordReset', name: 'TheTokenItSelf')
user = Token.check(action: 'PasswordReset', name: '123abc12qweads')
check api token with permissions
user = Token.check(action: 'api', name: 'TheTokenItSelf', permission: 'admin.session')
user = Token.check(action: 'api', name: '123abc12qweads', permission: 'admin.session')
returns
@ -70,7 +70,7 @@ returns
user = token.user
# persistent token not valid if user is inative
# persistent token not valid if user is inactive
if !data[:inactive_user]
return if token.persistent && user.active == false
end

View file

@ -205,6 +205,8 @@ class CreateBase < ActiveRecord::Migration
t.string :action, limit: 40, null: false
t.string :label, limit: 255, null: true
t.text :preferences, limit: 500.kilobytes + 1, null: true
t.timestamp :last_used_at, null: true
t.date :expires_at, null: true
t.timestamps null: false
end
add_index :tokens, :user_id

View file

@ -0,0 +1,9 @@
class TokenAttributes < ActiveRecord::Migration
def up
# return if it's a new setup
return if !Setting.find_by(name: 'system_init_done')
add_column :tokens, :last_used_at, :datetime, null: true
add_column :tokens, :expires_at, :date, null: true
end
end

View file

@ -417,6 +417,11 @@ class PreferencesTest < TestCase
css: '#content .modal .js-input',
value: 'Some App#1',
)
set(
css: '#content .modal .js-datepicker',
value: '05/15/2022',
)
sendkey(value: :tab)
click(css: '#content .modal input[value="ticket.agent"] ~ .label-text')
click(css: '#content .modal .js-submit')
watch_for(
@ -428,6 +433,10 @@ class PreferencesTest < TestCase
css: '#content .js-tokenList',
value: 'Some App#1'
)
watch_for(
css: '#content .js-tokenList',
value: '05/15/2022'
)
click(css: '#content .js-create')
watch_for(

View file

@ -270,4 +270,48 @@ class ApiAuthControllerTest < ActionDispatch::IntegrationTest
assert_equal('User is inactive!', result['error'])
end
test 'token auth - expired' do
Setting.set('api_token_access', true)
admin_token = Token.create(
action: 'api',
persistent: true,
user_id: @admin.id,
expires_at: Time.zone.today
)
admin_credentials = "Token token=#{admin_token.name}"
get '/api/v1/tickets', {}, @headers.merge('Authorization' => admin_credentials)
assert_response(401)
result = JSON.parse(@response.body)
assert_equal(Hash, result.class)
assert_equal('Not authorized (token expired)!', result['error'])
admin_token.reload
assert_in_delta(admin_token.last_used_at, Time.zone.now, 1.second)
end
test 'token auth - not expired' do
Setting.set('api_token_access', true)
admin_token = Token.create(
action: 'api',
persistent: true,
user_id: @admin.id,
expires_at: Time.zone.tomorrow
)
admin_credentials = "Token token=#{admin_token.name}"
get '/api/v1/tickets', {}, @headers.merge('Authorization' => admin_credentials)
assert_response(200)
result = JSON.parse(@response.body)
assert_equal(Array, result.class)
assert(result)
admin_token.reload
assert_in_delta(admin_token.last_used_at, Time.zone.now, 1.second)
end
end