Skip to content

Commit

Permalink
Allow annonymous read access to operator tables
Browse files Browse the repository at this point in the history
See https://progress.opensuse.org/issues/13858

Concerning tables
* Medium types
* Machines
* Test suites
* Job groups and job templates
* Scheduled products
  • Loading branch information
Martchus committed Feb 8, 2017
1 parent 30fde28 commit 1ddef19
Show file tree
Hide file tree
Showing 6 changed files with 107 additions and 75 deletions.
5 changes: 4 additions & 1 deletion assets/javascripts/job_templates.js
@@ -1,5 +1,6 @@
var job_templates_url;
var job_group_id;
var is_admin;

function setupJobTemplates(url, id) {
job_templates_url = url;
Expand Down Expand Up @@ -135,7 +136,9 @@ function buildMediumGroup(group, media) {
var table = $('<table class="table table-striped mediagroup" id="' + group + '"/>').appendTo(div);
var thead = $('<thead/>').appendTo(table);
var tr = $('<tr/>').appendTo(thead);
var tname = tr.append($('<th class="name">Test <a href="#" class="plus-sign"><i class="fa fa-plus"></i></a></th>'));
var tname = tr.append($('<th class="name">Test'
+ (is_admin ? ' <a href="#" class="plus-sign"><i class="fa fa-plus"></i></a>' : '')
+ '</th>'));
tr.append($('<th class="prio">Prio</th>'));
var archs = {};
var tests = {};
Expand Down
46 changes: 24 additions & 22 deletions lib/OpenQA/WebAPI.pm
Expand Up @@ -244,31 +244,33 @@ sub startup {
#
## Admin area starts here
###
my $admin_auth = $r->under('/admin')->to('session#ensure_admin');
my $admin_r = $admin_auth->route('/')->to(namespace => 'OpenQA::WebAPI::Controller::Admin');
my $op_auth = $r->under('/admin')->to('session#ensure_operator');
my $op_r = $op_auth->route('/')->to(namespace => 'OpenQA::WebAPI::Controller::Admin');
my $admin_auth = $r->under('/admin')->to('session#ensure_admin');
my $admin_r = $admin_auth->route('/')->to(namespace => 'OpenQA::WebAPI::Controller::Admin');
my $op_auth = $r->under('/admin')->to('session#ensure_operator');
my $op_r = $op_auth->route('/')->to(namespace => 'OpenQA::WebAPI::Controller::Admin');
my $pub_admin_r = $r->route('/admin')->to(namespace => 'OpenQA::WebAPI::Controller::Admin');

# operators accessible tables
$op_r->get('/products')->name('admin_products')->to('product#index');
$op_r->get('/machines')->name('admin_machines')->to('machine#index');
$op_r->get('/test_suites')->name('admin_test_suites')->to('test_suite#index');
$pub_admin_r->get('/products')->name('admin_products')->to('product#index');
$pub_admin_r->get('/machines')->name('admin_machines')->to('machine#index');
$pub_admin_r->get('/test_suites')->name('admin_test_suites')->to('test_suite#index');

$op_r->get('/job_templates/:groupid')->name('admin_job_templates')->to('job_template#index');
$pub_admin_r->get('/job_templates/:groupid')->name('admin_job_templates')->to('job_template#index');

$op_r->get('/groups')->name('admin_groups')->to('job_group#index');
$op_r->get('/job_group/:groupid')->name('admin_job_group_row')->to('job_group#job_group_row');
$op_r->get('/parent_group/:groupid')->name('admin_parent_group_row')->to('job_group#parent_group_row');
$op_r->get('/edit_parent_group/:groupid')->name('admin_edit_parent_group')->to('job_group#edit_parent_group');
$op_r->get('/groups/connect/:groupid')->name('job_group_new_media')->to('job_group#connect');
$pub_admin_r->get('/groups')->name('admin_groups')->to('job_group#index');
$pub_admin_r->get('/job_group/:groupid')->name('admin_job_group_row')->to('job_group#job_group_row');
$pub_admin_r->get('/parent_group/:groupid')->name('admin_parent_group_row')->to('job_group#parent_group_row');
$pub_admin_r->get('/edit_parent_group/:groupid')->name('admin_edit_parent_group')
->to('job_group#edit_parent_group');
$pub_admin_r->get('/groups/connect/:groupid')->name('job_group_new_media')->to('job_group#connect');

$op_r->get('/assets')->name('admin_assets')->to('asset#index');

$op_r->get('/workers')->name('admin_workers')->to('workers#index');
$op_r->get('/workers/:worker_id')->name('admin_worker_show')->to('workers#show');
$op_r->get('/workers/:worker_id/ajax')->name('admin_worker_previous_jobs_ajax')->to('workers#previous_jobs_ajax');

$op_r->get('/productlog')->name('admin_product_log')->to('audit_log#productlog');
$pub_admin_r->get('/productlog')->name('admin_product_log')->to('audit_log#productlog');

# admins accessible tables
$admin_r->get('/users')->name('admin_users')->to('user#index');
Expand Down Expand Up @@ -404,33 +406,33 @@ sub startup {
$api_ra->delete('/assets/#type/#name')->name('apiv1_delete_asset_name')->to('asset#delete');

# api/v1/test_suites
$api_ro->get('test_suites')->name('apiv1_test_suites')->to('table#list', table => 'TestSuites');
$api_public_r->get('test_suites')->name('apiv1_test_suites')->to('table#list', table => 'TestSuites');
$api_ra->post('test_suites')->to('table#create', table => 'TestSuites');
$api_ro->get('test_suites/:id')->name('apiv1_test_suite')->to('table#list', table => 'TestSuites');
$api_public_r->get('test_suites/:id')->name('apiv1_test_suite')->to('table#list', table => 'TestSuites');
$api_ra->put('test_suites/:id')->to('table#update', table => 'TestSuites');
$api_ra->post('test_suites/:id')->to('table#update', table => 'TestSuites'); #in case PUT is not supported
$api_ra->delete('test_suites/:id')->to('table#destroy', table => 'TestSuites');

# api/v1/machines
$api_ro->get('machines')->name('apiv1_machines')->to('table#list', table => 'Machines');
$api_public_r->get('machines')->name('apiv1_machines')->to('table#list', table => 'Machines');
$api_ra->post('machines')->to('table#create', table => 'Machines');
$api_ro->get('machines/:id')->name('apiv1_machine')->to('table#list', table => 'Machines');
$api_public_r->get('machines/:id')->name('apiv1_machine')->to('table#list', table => 'Machines');
$api_ra->put('machines/:id')->to('table#update', table => 'Machines');
$api_ra->post('machines/:id')->to('table#update', table => 'Machines'); #in case PUT is not supported
$api_ra->delete('machines/:id')->to('table#destroy', table => 'Machines');

# api/v1/products
$api_ro->get('products')->name('apiv1_products')->to('table#list', table => 'Products');
$api_public_r->get('products')->name('apiv1_products')->to('table#list', table => 'Products');
$api_ra->post('products')->to('table#create', table => 'Products');
$api_ro->get('products/:id')->name('apiv1_product')->to('table#list', table => 'Products');
$api_public_r->get('products/:id')->name('apiv1_product')->to('table#list', table => 'Products');
$api_ra->put('products/:id')->to('table#update', table => 'Products');
$api_ra->post('products/:id')->to('table#update', table => 'Products'); #in case PUT is not supported
$api_ra->delete('products/:id')->to('table#destroy', table => 'Products');

# api/v1/job_templates
$api_ro->get('job_templates')->name('apiv1_job_templates')->to('job_template#list');
$api_public_r->get('job_templates')->name('apiv1_job_templates')->to('job_template#list');
$api_ra->post('job_templates')->to('job_template#create');
$api_ro->get('job_templates/:job_template_id')->name('apiv1_job_template')->to('job_template#list');
$api_public_r->get('job_templates/:job_template_id')->name('apiv1_job_template')->to('job_template#list');
$api_ra->delete('job_templates/:job_template_id')->to('job_template#destroy');

# api/v1/comments
Expand Down
10 changes: 5 additions & 5 deletions t/api/03-auth.t
Expand Up @@ -72,7 +72,7 @@ my $ret;

subtest 'access limiting for non authenticated users' => sub() {
$t->get_ok('/api/v1/jobs')->status_is(200);
$t->get_ok('/api/v1/products')->status_is(403);
$t->get_ok('/api/v1/products')->status_is(200);
my $delete = $t->delete_ok('/api/v1/assets/1')->status_is(403);
is($delete->tx->res->code, 403, 'delete forbidden');
is_deeply(
Expand All @@ -89,7 +89,7 @@ subtest 'access limiting for authenticated users but not operators nor admins' =
$t->ua->apikey('LANCELOTKEY01');
$t->ua->apisecret('MANYPEOPLEKNOW');
$t->get_ok('/api/v1/jobs')->status_is(200);
$t->get_ok('/api/v1/products')->status_is(403);
$t->post_ok('/api/v1/products/1')->status_is(403);
$t->delete_ok('/api/v1/assets/1')->status_is(403);
};

Expand All @@ -113,7 +113,7 @@ subtest 'wrong api key - expired' => sub() {
$t->ua->apikey('EXPIREDKEY01');
$t->ua->apisecret('WHOCARESAFTERALL');
$t->get_ok('/api/v1/jobs')->status_is(200);
$ret = $t->get_ok('/api/v1/products')->status_is(403);
$ret = $t->post_ok('/api/v1/products/1')->status_is(403);
is($ret->tx->res->json->{error}, 'api key expired', 'key expired error');
$t->delete_ok('/api/v1/assets/1')->status_is(403);
is($ret->tx->res->json->{error}, 'api key expired', 'key expired error');
Expand All @@ -123,7 +123,7 @@ subtest 'wrong api key - not maching key + secret' => sub() {
$t->ua->apikey('EXPIREDKEY01');
$t->ua->apisecret('INVALIDSECRET');
$t->get_ok('/api/v1/jobs')->status_is(200);
$ret = $t->get_ok('/api/v1/products')->status_is(403);
$ret = $t->post_ok('/api/v1/products/1')->status_is(403);
$t->delete_ok('/api/v1/assets/1')->status_is(403);
};

Expand Down Expand Up @@ -153,7 +153,7 @@ subtest 'wrong api key - replay attack' => sub() {
}
});
$t->get_ok('/api/v1/jobs')->status_is(200);
$ret = $t->get_ok('/api/v1/products')->status_is(403);
$ret = $t->post_ok('/api/v1/products/1')->status_is(403);
is($ret->tx->res->json->{error}, 'timestamp mismatch', 'timestamp mismatch error');
$t->delete_ok('/api/v1/assets/1')->status_is(403);
is($ret->tx->res->json->{error}, 'timestamp mismatch', 'timestamp mismatch error');
Expand Down
17 changes: 15 additions & 2 deletions templates/admin/group/group_property_editor.html.ep
Expand Up @@ -4,11 +4,21 @@
% }
>
<div class="panel-heading">
<h3 class="panel-title">Edit job group properties</h3>
<h3 class="panel-title">
% if (is_admin) {
Edit job group properties
% }
% else {
Job group properties
% }
</h3>
</div>
<div class="panel-body">
<form action="#" class="form-horizontal" onsubmit="return submitProperties(this);"
data-put-url="<%= url_for(($is_parent ? 'apiv1_put_parent_group' : 'apiv1_put_job_group') => (group_id => $group->id)) %>">
data-put-url="<%= url_for(($is_parent ? 'apiv1_put_parent_group' : 'apiv1_put_job_group') => (group_id => $group->id)) %>">
% if (!is_admin) {
<fieldset disabled>
% }
<div class="form-group">
<label for="editor-name" class="col-sm-2 control-label">Name</label>
<div class="col-sm-10">
Expand Down Expand Up @@ -117,6 +127,9 @@
<p class="properties-status"></p>
</div>
</div>
% if (!is_admin) {
</fieldset>
% }
</form>
</div>
</div>
51 changes: 32 additions & 19 deletions templates/admin/job_template/index.html.ep
Expand Up @@ -3,29 +3,42 @@
% title 'Jobs for ' . $group->name;

% content_for 'ready_function' => begin
setupJobTemplates("<%= url_for('apiv1_job_templates') %>", <%= $group->id %>, <%= is_admin %>);
is_admin = <%= is_admin ? 'true' : 'false' %>;
setupJobTemplates("<%= url_for('apiv1_job_templates') %>", <%= $group->id %>);
% end

<div class="row">
<div class="col-sm-12">
% if (is_admin) {
<form action="<%= url_for('admin_groups') %>" class="corner-buttons">
<button type="button" class="btn btn-default" onclick="toggleEdit();">
<span><span class="glyphicon glyphicon-edit" aria-hidden="true"></span> Edit job group properties</span>
</button>
<button type="submit" class="btn btn-default">
<span><span class="glyphicon glyphicon-th-list" aria-hidden="true"></span> Manage all job groups</span>
</button>
</form>
% }
<form action="<%= url_for('admin_groups') %>" class="corner-buttons">
<button type="button" class="btn btn-default" onclick="toggleEdit();">
<span>
<span class="glyphicon glyphicon-edit" aria-hidden="true"></span>
% if (is_admin) {
Edit job group properties
% }
% else {
Show job group properties
% }
</span>
</button>
<button type="submit" class="btn btn-default">
<span>
<span class="glyphicon glyphicon-th-list" aria-hidden="true"></span>
% if (is_admin) {
Manage all job groups
% }
% else {
Show all job groups
% }
</span>
</button>
</form>
<h2>
Jobs for
<span id="job-group-name"><%= $group->name %></span>
</h2>
%= include 'layouts/info'
% if (is_admin) {
%= include 'admin/group/group_property_editor', group => $group, is_parent => 0
% }
%= include 'admin/group/group_property_editor', group => $group, is_parent => 0
<div id="media">
<p id="loading"><i class="fa fa-spinner fa-spin"></i> Loading…</p>

Expand Down Expand Up @@ -58,11 +71,11 @@
</div>

% if (is_admin) {
<p>
%= link_to url_for('job_group_new_media', groupid => $group->id) => begin
<i class="fa fa-plus-square"></i> Test new medium as part of this group
% end
</p>
<p>
%= link_to url_for('job_group_new_media', groupid => $group->id) => begin
<i class="fa fa-plus-square"></i> Test new medium as part of this group
% end
</p>
% }
</div>

Expand Down
53 changes: 27 additions & 26 deletions templates/layouts/bootstrap.html.ep
Expand Up @@ -85,39 +85,40 @@
</li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li class="dropdown" id="user-action">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false" >Config <span class="caret"></span>
</a>
<ul class="dropdown-menu">
<li class="dropdown-header">Operators Menu</li>
<li><%= link_to('Medium types' => url_for('admin_products')) %></li>
<li><%= link_to('Machines' => url_for('admin_machines')) %></li>
<li><%= link_to('Test suites' => url_for('admin_test_suites')) %></li>
<li><%= link_to('Job groups' => url_for('admin_groups')) %></li>
<li><%= link_to('Scheduled products' => url_for('admin_product_log')) %></li>
% if (is_operator) {
<li><%= link_to('Assets' => url_for('admin_assets')) %></li>
<li><%= link_to('Workers' => url_for('admin_workers')) %></li>
% }
% if (is_admin) {
<li role="separator" class="divider"></li>
<li class="dropdown-header">Administrators Menu</li>
<li><%= link_to('Users' => url_for('admin_users')) %></li>
<li><%= link_to('Needles' => url_for('admin_needles')) %></li>
<li><%= link_to('Audit log' => url_for('audit_log')) %></li>
% }
% if (is_operator) {
<li role="separator" class="divider"></li>
<li><%= link_to('Manage API keys' => url_for('api_keys')) %></li>
% }
</ul>
</li>
% if (current_user) {
<li class="dropdown" id="user-action">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false" >Logged in as
%= current_user->name
<span class="caret"></span>
</a>
<ul class="dropdown-menu">
% if (is_operator) {
<li class="dropdown-header">Operators Menu</li>
<li><%= link_to('Medium types' => url_for('admin_products')) %></li>
<li><%= link_to('Machines' => url_for('admin_machines')) %></li>
<li><%= link_to('Test suites' => url_for('admin_test_suites')) %></li>
<li><%= link_to('Job groups' => url_for('admin_groups')) %></li>
<li><%= link_to('Scheduled products' => url_for('admin_product_log')) %></li>

<li><%= link_to('Assets' => url_for('admin_assets')) %></li>
<!-- Sure this is not the proper place for the workers view,
but the previous one was even more annoying -->
<li><%= link_to('Workers' => url_for('admin_workers')) %></li>

% if (is_admin) {
<li role="separator" class="divider"></li>
<li class="dropdown-header">Administrators Menu</li>
<li><%= link_to('Users' => url_for('admin_users')) %></li>
<li><%= link_to('Needles' => url_for('admin_needles')) %></li>
<li><%= link_to('Audit log' => url_for('audit_log')) %></li>
% }
<li role="separator" class="divider"></li>
<li>
%= link_to "Manage API keys" => url_for('api_keys')
%= link_to "API help" => url_for('api_help')
</li>
% }
<li>
%= link_to('Logout' => url_for('logout') => 'data-method' => 'delete');
</li>
Expand Down

0 comments on commit 1ddef19

Please sign in to comment.