Add filter for signed test results and related UI
With this patch users can list their own test results. Change-Id: Ie2d944924f6ae966a13d0ca9908810c315ade5ab
This commit is contained in:
parent
217cadd608
commit
2b89f65ad4
@ -26,8 +26,13 @@ refstackApp.config([
|
||||
templateUrl: '/components/capabilities/capabilities.html',
|
||||
controller: 'capabilitiesController'
|
||||
}).
|
||||
state('results', {
|
||||
url: '/results',
|
||||
state('community_results', {
|
||||
url: '/community_results',
|
||||
templateUrl: '/components/results/results.html',
|
||||
controller: 'resultsController'
|
||||
}).
|
||||
state('user_results', {
|
||||
url: '/user_results',
|
||||
templateUrl: '/components/results/results.html',
|
||||
controller: 'resultsController'
|
||||
}).
|
||||
@ -45,19 +50,46 @@ refstackApp.config([
|
||||
]);
|
||||
|
||||
/**
|
||||
* Try to authenticate user
|
||||
* Injections in $rootscope
|
||||
*/
|
||||
|
||||
refstackApp.run(['$http', '$rootScope', 'refstackApiUrl',
|
||||
function($http, $rootScope, refstackApiUrl) {
|
||||
refstackApp.run(['$http', '$rootScope', '$window', 'refstackApiUrl',
|
||||
function($http, $rootScope, $window, refstackApiUrl) {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* This function injects sign in function in all scopes
|
||||
*/
|
||||
|
||||
$rootScope.auth = {};
|
||||
|
||||
var sign_in_url = refstackApiUrl + '/auth/signin';
|
||||
$rootScope.auth.doSignIn = function () {
|
||||
$window.location.href = sign_in_url;
|
||||
};
|
||||
|
||||
/**
|
||||
* This function injects sign out function in all scopes
|
||||
*/
|
||||
var sign_out_url = refstackApiUrl + '/auth/signout';
|
||||
$rootScope.auth.doSignOut = function () {
|
||||
$rootScope.currentUser = null;
|
||||
$rootScope.isAuthenticated = false;
|
||||
$window.location.href = sign_out_url;
|
||||
};
|
||||
|
||||
/**
|
||||
* This block tries to authenticate user
|
||||
*/
|
||||
var profile_url = refstackApiUrl + '/profile';
|
||||
$http.get(profile_url, {withCredentials: true}).
|
||||
success(function(data) {
|
||||
$rootScope.currentUser = data;
|
||||
$rootScope.auth.currentUser = data;
|
||||
$rootScope.auth.isAuthenticated = true;
|
||||
}).
|
||||
error(function() {
|
||||
$rootScope.currentUser = null;
|
||||
$rootScope.auth.currentUser = null;
|
||||
$rootScope.auth.isAuthenticated = false;
|
||||
});
|
||||
}
|
||||
]);
|
||||
|
@ -1,29 +0,0 @@
|
||||
var refstackApp = angular.module('refstackApp');
|
||||
|
||||
/**
|
||||
* Refstack Auth Controller
|
||||
* This controller handles account authentication for users.
|
||||
*/
|
||||
|
||||
refstackApp.controller('authController',
|
||||
['$scope', '$window', '$rootScope', 'refstackApiUrl',
|
||||
function($scope, $window, $rootScope, refstackApiUrl){
|
||||
'use strict';
|
||||
var sign_in_url = refstackApiUrl + '/auth/signin';
|
||||
$scope.doSignIn = function () {
|
||||
$window.location.href = sign_in_url;
|
||||
};
|
||||
|
||||
var sign_out_url = refstackApiUrl + '/auth/signout';
|
||||
$scope.doSignOut = function () {
|
||||
$rootScope.currentUser = null;
|
||||
$window.location.href = sign_out_url;
|
||||
};
|
||||
|
||||
$scope.isAuthenticated = function () {
|
||||
if ($scope.currentUser) {
|
||||
return !!$scope.currentUser.openid;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
}]);
|
@ -58,7 +58,7 @@
|
||||
<div cg-busy="{promise:capsRequest,message:'Loading capabilities'}"></div>
|
||||
|
||||
<!-- Get the version-specific template -->
|
||||
<div ng-include src="detailsTemplate"></header>
|
||||
<div ng-include src="detailsTemplate"></div>
|
||||
|
||||
<div ng-show="showError" class="alert alert-danger" role="alert">
|
||||
<span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
|
||||
|
@ -1,11 +1,11 @@
|
||||
<h3>User profile</h3>
|
||||
|
||||
<div ng-show="user">
|
||||
<table ng-show="user" class="table table-striped table-hover">
|
||||
<div>
|
||||
<table class="table table-striped table-hover">
|
||||
<tbody>
|
||||
<tr> <td>User name</td> <td>{{user.fullname}}</td> </tr>
|
||||
<tr> <td>User OpenId</td> <td>{{user.openid}}</td> </tr>
|
||||
<tr> <td>Email</td> <td>{{user.email}}</td> </tr>
|
||||
<tr> <td>User name</td> <td>{{auth.currentUser.fullname}}</td> </tr>
|
||||
<tr> <td>User OpenId</td> <td>{{auth.currentUser.openid}}</td> </tr>
|
||||
<tr> <td>Email</td> <td>{{auth.currentUser.email}}</td> </tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
@ -22,8 +22,8 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div ng-show="pubkeys">
|
||||
<table ng-show="pubkeys" class="table table-striped table-hover">
|
||||
<div>
|
||||
<table class="table table-striped table-hover">
|
||||
<tbody>
|
||||
<tr ng-repeat="pubKey in pubkeys" ng-click="openShowPubKeyModal(pubKey)">
|
||||
<td>{{pubKey.format}}</td>
|
||||
@ -33,4 +33,3 @@
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
|
@ -19,16 +19,6 @@ refstackApp.controller('profileController',
|
||||
function($scope, $http, refstackApiUrl, $state,
|
||||
PubKeys, $modal, raiseAlert) {
|
||||
'use strict';
|
||||
$scope.updateProfile = function () {
|
||||
var profile_url = refstackApiUrl + '/profile';
|
||||
$http.get(profile_url, {withCredentials: true}).
|
||||
success(function(data) {
|
||||
$scope.user = data;
|
||||
}).
|
||||
error(function() {
|
||||
$state.go('home');
|
||||
});
|
||||
};
|
||||
|
||||
$scope.updatePubKeys = function (){
|
||||
var keys = PubKeys.query(function(){
|
||||
@ -77,7 +67,6 @@ refstackApp.controller('profileController',
|
||||
$scope.showRes = function(pubKey){
|
||||
raiseAlert('success', '', pubKey.key);
|
||||
};
|
||||
$scope.updateProfile();
|
||||
$scope.updatePubKeys();
|
||||
}
|
||||
]);
|
||||
|
@ -1,4 +1,4 @@
|
||||
<h3>Community Results</h3>
|
||||
<h3>{{pageHeader}}</h3>
|
||||
<p>The most recently uploaded community test results are listed here. Currently, these results are anonymous.</p>
|
||||
|
||||
<div class="result-filters">
|
||||
|
@ -6,8 +6,8 @@ var refstackApp = angular.module('refstackApp');
|
||||
* a listing of community uploaded results.
|
||||
*/
|
||||
refstackApp.controller('resultsController',
|
||||
['$scope', '$http', '$filter', 'refstackApiUrl',
|
||||
function ($scope, $http, $filter, refstackApiUrl) {
|
||||
['$scope', '$http', '$filter', '$state', 'refstackApiUrl',
|
||||
function ($scope, $http, $filter, $state, refstackApiUrl) {
|
||||
'use strict';
|
||||
|
||||
/** Initial page to be on. */
|
||||
@ -33,6 +33,9 @@ refstackApp.controller('resultsController',
|
||||
/** The upload date upper limit to be used in filtering results. */
|
||||
$scope.endDate = '';
|
||||
|
||||
$scope.isUserResults = $state.current.name === 'user_results';
|
||||
$scope.pageHeader = $scope.isUserResults ?
|
||||
'Private test results' : 'Community test results';
|
||||
/**
|
||||
* This will contact the Refstack API to get a listing of test run
|
||||
* results.
|
||||
@ -51,7 +54,9 @@ refstackApp.controller('resultsController',
|
||||
if (end) {
|
||||
content_url = content_url + '&end_date=' + end + ' 23:59:59';
|
||||
}
|
||||
|
||||
if ($scope.isUserResults) {
|
||||
content_url = content_url + '&signed';
|
||||
}
|
||||
$scope.resultsRequest =
|
||||
$http.get(content_url).success(function (data) {
|
||||
$scope.data = data;
|
||||
|
@ -38,12 +38,11 @@
|
||||
|
||||
<!-- Controllers -->
|
||||
<script src="shared/header/headerController.js"></script>
|
||||
<script src="shared/alerts/alertModalFactory.js"></script>
|
||||
<script src="components/capabilities/capabilitiesController.js"></script>
|
||||
<script src="components/results/resultsController.js"></script>
|
||||
<script src="components/results-report/resultsReportController.js"></script>
|
||||
<script src="components/profile/profileController.js"></script>
|
||||
<script src="components/auth/authController.js"></script>
|
||||
<script src="components/alerts/alertModalFactory.js"></script>
|
||||
|
||||
<!-- Filters -->
|
||||
<script src="shared/filters.js"></script>
|
||||
|
@ -5,7 +5,7 @@ refstackApp.factory('raiseAlert',
|
||||
'use strict';
|
||||
return function(mode, title, text) {
|
||||
$modal.open({
|
||||
templateUrl: '/components/alerts/alertModal.html',
|
||||
templateUrl: '/shared/alerts/alertModal.html',
|
||||
controller: 'raiseAlertModalController',
|
||||
backdrop: true,
|
||||
keyboard: true,
|
@ -18,14 +18,14 @@ Refstack
|
||||
<li ng-class="{ active: isActive('/')}"><a ui-sref="home">Home</a></li>
|
||||
<li ng-class="{ active: isActive('/about')}"><a ui-sref="about">About</a></li>
|
||||
<li ng-class="{ active: isActive('/capabilities')}"><a ui-sref="capabilities">DefCore Capabilities</a></li>
|
||||
<li ng-class="{ active: isActive('/results')}"><a ui-sref="results">Community Results</a></li>
|
||||
<li ng-class="{ active: isActive('/community_results')}"><a ui-sref="community_results">Community Results</a></li>
|
||||
</ul>
|
||||
<ul ng-controller="authController" class="nav navbar-nav navbar-right">
|
||||
<li ng-class="{ active: isActive('/profile')}" ng-if="isAuthenticated()"><a ui-sref="profile">{{currentUser.fullname}}</a></li>
|
||||
<li ng-if="isAuthenticated()"><a href="" ng-click="doSignOut()">Sign Out</a></li>
|
||||
<li ng-if="!isAuthenticated()"><a href="" ng-click="doSignIn()">Sign In / Sign Up</a></li>
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li ng-class="{ active: isActive('/user_results')}" ng-if="auth.isAuthenticated"><a ui-sref="user_results">My Results</a></li>
|
||||
<li ng-class="{ active: isActive('/profile')}" ng-if="auth.isAuthenticated"><a ui-sref="profile">Profile</a></li>
|
||||
<li ng-if="auth.isAuthenticated"><a href="" ng-click="auth.doSignOut()">Sign Out</a></li>
|
||||
<li ng-if="!auth.isAuthenticated"><a href="" ng-click="auth.doSignIn()">Sign In / Sign Up</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
40
refstack-ui/tests/unit/AuthSpec.js
Normal file
40
refstack-ui/tests/unit/AuthSpec.js
Normal file
@ -0,0 +1,40 @@
|
||||
describe('Auth', function () {
|
||||
'use strict';
|
||||
|
||||
var fakeApiUrl = 'http://foo.bar/v1';
|
||||
var $window;
|
||||
beforeEach(function () {
|
||||
$window = {location: { href: jasmine.createSpy()} };
|
||||
module(function ($provide) {
|
||||
$provide.constant('refstackApiUrl', fakeApiUrl);
|
||||
$provide.value('$window', $window);
|
||||
});
|
||||
module('refstackApp');
|
||||
});
|
||||
|
||||
var $rootScope, $httpBackend;
|
||||
beforeEach(inject(function (_$httpBackend_, _$rootScope_) {
|
||||
$httpBackend = _$httpBackend_;
|
||||
$rootScope = _$rootScope_;
|
||||
}));
|
||||
|
||||
it('should show signin url for signed user', function () {
|
||||
$httpBackend.expectGET(fakeApiUrl +
|
||||
'/profile').respond({'openid': 'foo@bar.com',
|
||||
'email': 'foo@bar.com',
|
||||
'fullname': 'foo' });
|
||||
$httpBackend.flush();
|
||||
$rootScope.auth.doSignIn();
|
||||
expect($window.location.href).toBe(fakeApiUrl + '/auth/signin');
|
||||
expect($rootScope.auth.isAuthenticated).toBe(true);
|
||||
});
|
||||
|
||||
it('should show signout url for not signed user', function () {
|
||||
$httpBackend.expectGET(fakeApiUrl +
|
||||
'/profile').respond(401);
|
||||
$httpBackend.flush();
|
||||
$rootScope.auth.doSignOut();
|
||||
expect($window.location.href).toBe(fakeApiUrl + '/auth/signout');
|
||||
expect($rootScope.auth.isAuthenticated).toBe(false);
|
||||
});
|
||||
});
|
@ -3,11 +3,18 @@ describe('Refstack controllers', function () {
|
||||
'use strict';
|
||||
|
||||
var fakeApiUrl = 'http://foo.bar/v1';
|
||||
var $httpBackend;
|
||||
beforeEach(function () {
|
||||
module(function ($provide) {
|
||||
$provide.constant('refstackApiUrl', fakeApiUrl);
|
||||
});
|
||||
module('refstackApp');
|
||||
inject(function(_$httpBackend_){
|
||||
$httpBackend = _$httpBackend_;
|
||||
});
|
||||
$httpBackend.whenGET(fakeApiUrl + '/profile').respond(401);
|
||||
$httpBackend.whenGET('/components/home/home.html')
|
||||
.respond('<div>mock template</div>');
|
||||
});
|
||||
|
||||
describe('headerController', function () {
|
||||
@ -36,42 +43,10 @@ describe('Refstack controllers', function () {
|
||||
});
|
||||
});
|
||||
|
||||
describe('authController', function () {
|
||||
var scope, $httpBackend, $window;
|
||||
|
||||
beforeEach(inject(function (_$httpBackend_, $rootScope, $controller) {
|
||||
$httpBackend = _$httpBackend_;
|
||||
scope = $rootScope.$new();
|
||||
$window = {location: { href: jasmine.createSpy()} };
|
||||
$controller('authController', {$scope: scope, $window: $window});
|
||||
}));
|
||||
|
||||
it('should show signin url for signed user', function () {
|
||||
$httpBackend.expectGET(fakeApiUrl +
|
||||
'/profile').respond({'openid': 'foo@bar.com',
|
||||
'email': 'foo@bar.com',
|
||||
'fullname': 'foo' });
|
||||
$httpBackend.flush();
|
||||
scope.doSignIn();
|
||||
expect($window.location.href).toBe(fakeApiUrl + '/auth/signin');
|
||||
expect(scope.isAuthenticated()).toBe(true);
|
||||
});
|
||||
|
||||
it('should show signout url for not signed user', function () {
|
||||
$httpBackend.expectGET(fakeApiUrl +
|
||||
'/profile').respond(401);
|
||||
$httpBackend.flush();
|
||||
scope.doSignOut();
|
||||
expect($window.location.href).toBe(fakeApiUrl + '/auth/signout');
|
||||
expect(scope.isAuthenticated()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('capabilitiesController', function () {
|
||||
var scope, $httpBackend;
|
||||
var scope;
|
||||
|
||||
beforeEach(inject(function (_$httpBackend_, $rootScope, $controller) {
|
||||
$httpBackend = _$httpBackend_;
|
||||
beforeEach(inject(function ($rootScope, $controller) {
|
||||
scope = $rootScope.$new();
|
||||
$controller('capabilitiesController', {$scope: scope});
|
||||
}));
|
||||
@ -102,8 +77,6 @@ describe('Refstack controllers', function () {
|
||||
}
|
||||
};
|
||||
|
||||
$httpBackend.expectGET(fakeApiUrl +
|
||||
'/profile').respond(401);
|
||||
$httpBackend.expectGET(fakeApiUrl +
|
||||
'/capabilities').respond(['2015.03.json', '2015.04.json']);
|
||||
// Should call request with latest version.
|
||||
@ -170,7 +143,7 @@ describe('Refstack controllers', function () {
|
||||
});
|
||||
|
||||
describe('resultsController', function () {
|
||||
var scope, $httpBackend;
|
||||
var scope;
|
||||
var fakeResponse = {
|
||||
'pagination': {'current_page': 1, 'total_pages': 2},
|
||||
'results': [{
|
||||
@ -180,8 +153,7 @@ describe('Refstack controllers', function () {
|
||||
}]
|
||||
};
|
||||
|
||||
beforeEach(inject(function (_$httpBackend_, $rootScope, $controller) {
|
||||
$httpBackend = _$httpBackend_;
|
||||
beforeEach(inject(function ($rootScope, $controller) {
|
||||
scope = $rootScope.$new();
|
||||
$controller('resultsController', {$scope: scope});
|
||||
}));
|
||||
@ -189,9 +161,8 @@ describe('Refstack controllers', function () {
|
||||
it('should fetch the first page of results with proper URL args',
|
||||
function () {
|
||||
// Initial results should be page 1 of all results.
|
||||
$httpBackend.expectGET(fakeApiUrl + '/profile').respond(401);
|
||||
$httpBackend.expectGET(fakeApiUrl +
|
||||
'/results?page=1').respond(fakeResponse);
|
||||
$httpBackend.expectGET(fakeApiUrl + '/results?page=1')
|
||||
.respond(fakeResponse);
|
||||
$httpBackend.flush();
|
||||
expect(scope.data).toEqual(fakeResponse);
|
||||
expect(scope.currentPage).toBe(1);
|
||||
@ -211,7 +182,6 @@ describe('Refstack controllers', function () {
|
||||
});
|
||||
|
||||
it('should set an error when results cannot be retrieved', function () {
|
||||
$httpBackend.expectGET(fakeApiUrl + '/profile').respond(401);
|
||||
$httpBackend.expectGET(fakeApiUrl + '/results?page=1').respond(404,
|
||||
{'detail': 'Not Found'});
|
||||
$httpBackend.flush();
|
||||
@ -224,23 +194,16 @@ describe('Refstack controllers', function () {
|
||||
|
||||
it('should have an function to clear filters and update the view',
|
||||
function () {
|
||||
$httpBackend.expectGET(fakeApiUrl + '/profile').respond(401);
|
||||
$httpBackend.expectGET(fakeApiUrl +
|
||||
'/results?page=1').respond(fakeResponse);
|
||||
scope.startDate = 'some date';
|
||||
scope.endDate = 'some other date';
|
||||
scope.clearFilters();
|
||||
expect(scope.startDate).toBe(null);
|
||||
expect(scope.endDate).toBe(null);
|
||||
$httpBackend.expectGET(fakeApiUrl +
|
||||
'/results?page=1').respond(fakeResponse);
|
||||
$httpBackend.flush();
|
||||
expect(scope.data).toEqual(fakeResponse);
|
||||
});
|
||||
});
|
||||
|
||||
describe('resultsReportController', function () {
|
||||
var scope, $httpBackend, stateparams;
|
||||
var scope, stateparams;
|
||||
var fakeResultResponse = {'results': ['test_id_1']};
|
||||
var fakeCapabilityResponse = {
|
||||
'platform': {'required': ['compute']},
|
||||
@ -261,8 +224,7 @@ describe('Refstack controllers', function () {
|
||||
}
|
||||
};
|
||||
|
||||
beforeEach(inject(function (_$httpBackend_, $rootScope, $controller) {
|
||||
$httpBackend = _$httpBackend_;
|
||||
beforeEach(inject(function ($rootScope, $controller) {
|
||||
stateparams = {testID: 1234};
|
||||
scope = $rootScope.$new();
|
||||
$controller('resultsReportController',
|
||||
@ -272,7 +234,6 @@ describe('Refstack controllers', function () {
|
||||
it('should make all necessary API requests to get results ' +
|
||||
'and capabilities',
|
||||
function () {
|
||||
$httpBackend.expectGET(fakeApiUrl + '/profile').respond(401);
|
||||
$httpBackend.expectGET(fakeApiUrl +
|
||||
'/results/1234').respond(fakeResultResponse);
|
||||
$httpBackend.expectGET(fakeApiUrl +
|
||||
|
@ -19,6 +19,7 @@ START_DATE = 'start_date'
|
||||
END_DATE = 'end_date'
|
||||
CPID = 'cpid'
|
||||
PAGE = 'page'
|
||||
SIGNED = 'signed'
|
||||
|
||||
# OpenID parameters
|
||||
OPENID_MODE = 'openid.mode'
|
||||
@ -36,3 +37,6 @@ OPENID_ERROR = 'openid.error'
|
||||
# User session parameters
|
||||
CSRF_TOKEN = 'csrf_token'
|
||||
USER_OPENID = 'user_openid'
|
||||
|
||||
# Test metadata fields
|
||||
PUBLIC_KEY = 'public_key'
|
||||
|
@ -55,7 +55,7 @@ class ResultsController(validation.BaseRestControllerWithValidation):
|
||||
if pecan.request.headers.get('X-Public-Key'):
|
||||
if 'metadata' not in item:
|
||||
item['metadata'] = {}
|
||||
item['metadata']['public_key'] = \
|
||||
item['metadata'][const.PUBLIC_KEY] = \
|
||||
pecan.request.headers.get('X-Public-Key')
|
||||
test_id = db.store_results(item)
|
||||
LOG.debug(item)
|
||||
@ -79,6 +79,7 @@ class ResultsController(validation.BaseRestControllerWithValidation):
|
||||
const.START_DATE,
|
||||
const.END_DATE,
|
||||
const.CPID,
|
||||
const.SIGNED
|
||||
]
|
||||
|
||||
try:
|
||||
@ -88,9 +89,6 @@ class ResultsController(validation.BaseRestControllerWithValidation):
|
||||
api_utils.get_page_number(records_count)
|
||||
except api_utils.ParseInputsError as ex:
|
||||
pecan.abort(400, 'Reason: %s' % ex)
|
||||
except Exception as ex:
|
||||
LOG.debug('An error occurred: %s' % ex)
|
||||
pecan.abort(500)
|
||||
|
||||
try:
|
||||
per_page = CONF.api.results_per_page
|
||||
@ -102,7 +100,8 @@ class ResultsController(validation.BaseRestControllerWithValidation):
|
||||
'test_id': r.id,
|
||||
'created_at': r.created_at,
|
||||
'cpid': r.cpid,
|
||||
'url': CONF.api.test_results_url % r.id
|
||||
'url': parse.urljoin(CONF.ui_url,
|
||||
CONF.api.test_results_url) % r.id
|
||||
})
|
||||
|
||||
page = {'results': results,
|
||||
|
@ -86,6 +86,16 @@ def parse_input_params(expected_input_params):
|
||||
'start': const.START_DATE,
|
||||
'end': const.END_DATE
|
||||
})
|
||||
if const.SIGNED in filters:
|
||||
if is_authenticated():
|
||||
filters['openid'] = get_user_id()
|
||||
filters['pubkeys'] = [
|
||||
' '.join((pk['format'], pk['key']))
|
||||
for pk in db.get_user_pubkeys(filters['openid'])
|
||||
]
|
||||
else:
|
||||
raise ParseInputsError('To see signed test '
|
||||
'results you need to authenticate')
|
||||
return filters
|
||||
|
||||
|
||||
@ -176,6 +186,11 @@ def get_user():
|
||||
return db.user_get(get_user_id())
|
||||
|
||||
|
||||
def get_user_public_keys():
|
||||
"""Return db record for authenticated user."""
|
||||
return db.get_user_pubkeys(get_user_id())
|
||||
|
||||
|
||||
def is_authenticated():
|
||||
"""Return True if user is authenticated."""
|
||||
if get_user_id():
|
||||
|
@ -34,6 +34,7 @@ def upgrade():
|
||||
sa.ForeignKeyConstraint(['openid'], ['user.openid'], ),
|
||||
mysql_charset=MYSQL_CHARSET
|
||||
)
|
||||
op.create_index('indx_meta_value', 'meta', ['value'], mysql_length=32)
|
||||
|
||||
|
||||
def downgrade():
|
||||
|
@ -117,6 +117,19 @@ def _apply_filters_for_query(query, filters):
|
||||
if cpid:
|
||||
query = query.filter(models.Test.cpid == cpid)
|
||||
|
||||
signed = api_const.SIGNED in filters
|
||||
if signed:
|
||||
query = (query
|
||||
.join(models.Test.meta)
|
||||
.filter(models.TestMeta.meta_key == api_const.PUBLIC_KEY)
|
||||
.filter(models.TestMeta.value.in_(filters['pubkeys']))
|
||||
)
|
||||
else:
|
||||
signed_results = (query.session
|
||||
.query(models.TestMeta.test_id)
|
||||
.filter_by(meta_key=api_const.PUBLIC_KEY))
|
||||
query = query.filter(models.Test.id.notin_(signed_results))
|
||||
|
||||
return query
|
||||
|
||||
|
||||
|
@ -134,7 +134,7 @@ class ResultsControllerTestCase(base.BaseTestCase):
|
||||
'url': self.test_results_url % 'fake_test_id'})
|
||||
self.assertEqual(mock_response.status, 201)
|
||||
mock_store_results.assert_called_once_with(
|
||||
{'answer': 42, 'metadata': {'public_key': 'fake-key'}}
|
||||
{'answer': 42, 'metadata': {const.PUBLIC_KEY: 'fake-key'}}
|
||||
)
|
||||
|
||||
@mock.patch('pecan.abort')
|
||||
@ -216,6 +216,7 @@ class ResultsControllerTestCase(base.BaseTestCase):
|
||||
const.START_DATE,
|
||||
const.END_DATE,
|
||||
const.CPID,
|
||||
const.SIGNED
|
||||
]
|
||||
page_number = 1
|
||||
total_pages_number = 10
|
||||
|
@ -193,9 +193,12 @@ class DBBackendTestCase(base.BaseTestCase):
|
||||
self.assertEqual(expected_result, actual_result)
|
||||
|
||||
@mock.patch('refstack.db.sqlalchemy.models.Test')
|
||||
def test_apply_filters_for_query(self, mock_model):
|
||||
@mock.patch('refstack.db.sqlalchemy.models.TestMeta')
|
||||
def test_apply_filters_for_query_unsigned(self, mock_meta,
|
||||
mock_test):
|
||||
query = mock.Mock()
|
||||
mock_model.created_at = six.text_type()
|
||||
mock_test.created_at = six.text_type()
|
||||
mock_meta.test_id = six.text_type()
|
||||
|
||||
filters = {
|
||||
api_const.START_DATE: 'fake1',
|
||||
@ -205,19 +208,30 @@ class DBBackendTestCase(base.BaseTestCase):
|
||||
|
||||
result = api._apply_filters_for_query(query, filters)
|
||||
|
||||
query.filter.assert_called_once_with(mock_model.created_at >=
|
||||
query.filter.assert_called_once_with(mock_test.created_at >=
|
||||
filters[api_const.START_DATE])
|
||||
|
||||
query = query.filter.return_value
|
||||
query.filter.assert_called_once_with(mock_model.created_at <=
|
||||
query.filter.assert_called_once_with(mock_test.created_at <=
|
||||
filters[api_const.END_DATE])
|
||||
|
||||
query = query.filter.return_value
|
||||
query.filter.assert_called_once_with(mock_model.cpid ==
|
||||
query.filter.assert_called_once_with(mock_test.cpid ==
|
||||
filters[api_const.CPID])
|
||||
|
||||
query = query.filter.return_value
|
||||
self.assertEqual(result, query)
|
||||
|
||||
query.session.query.assert_called_once_with(mock_meta.test_id)
|
||||
meta_query = query.session.query.return_value
|
||||
|
||||
meta_query.filter_by.\
|
||||
assert_called_once_with(meta_key=api_const.PUBLIC_KEY)
|
||||
unsigned_test_id_query = meta_query.filter_by.return_value
|
||||
mock_test.id.notin_.assert_called_once_with(unsigned_test_id_query)
|
||||
query.filter.assert_called_once_with(mock_test.id.notin_.return_value)
|
||||
|
||||
filtered_query = query.filter.return_value
|
||||
self.assertEqual(result, filtered_query)
|
||||
|
||||
@mock.patch.object(api, '_apply_filters_for_query')
|
||||
@mock.patch.object(api, 'get_session')
|
||||
|
@ -8,6 +8,5 @@ oslotest>=1.2.0 # Apache-2.0
|
||||
python-subunit>=0.0.18
|
||||
testrepository>=0.0.18
|
||||
testtools>=0.9.34
|
||||
mysqlclient
|
||||
six>=1.7.0
|
||||
pep257>=0.5.0
|
Loading…
Reference in New Issue
Block a user