-
-
- - +

Result


 
+

Events

+

+
+
+
+
 
 
diff --git a/testsuite/integration-arquillian/test-apps/photoz/photoz-html5-client/src/main/webapp/js/app.js b/testsuite/integration-arquillian/test-apps/photoz/photoz-html5-client/src/main/webapp/js/app.js
deleted file mode 100755
index f6df2cbf32..0000000000
--- a/testsuite/integration-arquillian/test-apps/photoz/photoz-html5-client/src/main/webapp/js/app.js
+++ /dev/null
@@ -1,256 +0,0 @@
-var module = angular.module('photoz', ['ngRoute', 'ngResource']);
-
-var resourceServerId = 'photoz-restful-api';
-var apiUrl = window.location.origin + '/' + resourceServerId;
-
-angular.element(document).ready(function ($http) {
-    var keycloak = new Keycloak('keycloak.json');
-    keycloak.init({onLoad: 'login-required'}).success(function () {
-        console.log('User is now authenticated.');
-
-        module.factory('Identity', function () {
-            return new Identity(keycloak);
-        });
-
-        angular.bootstrap(document, ["photoz"]);
-    }).error(function () {
-        window.location.reload();
-    });
-});
-
-module.config(function ($httpProvider, $routeProvider) {
-    $httpProvider.interceptors.push('authInterceptor');
-    $routeProvider.when('/', {
-        templateUrl: 'partials/home.html',
-        controller: 'GlobalCtrl'
-    }).when('/album/create', {
-        templateUrl: 'partials/album/create.html',
-        controller: 'AlbumCtrl',
-    }).when('/album/:id', {
-        templateUrl: 'partials/album/detail.html',
-        controller: 'AlbumCtrl',
-    }).when('/admin/album', {
-        templateUrl: 'partials/admin/albums.html',
-        controller: 'AdminAlbumCtrl',
-    }).when('/profile', {
-        templateUrl: 'partials/profile.html',
-        controller: 'ProfileCtrl'
-    });
-});
-
-module.controller('GlobalCtrl', function ($scope, $http, $route, $location, Album, Identity) {
-    Album.query(function (albums) {
-        $scope.albums = albums;
-    });
-
-    $scope.Identity = Identity;
-
-    $scope.deleteAlbum = function (album) {
-        new Album(album).$delete({id: album.id}, function () {
-            $route.reload();
-        });
-    }
-
-    $scope.requestPathWithAnyProtectedScope = function() {
-        $http.get(apiUrl + '/scope-any').success(function (data) {
-        });
-    }
-
-    $scope.requestPathWithAllProtectedScope = function() {
-        $http.get(apiUrl + '/scope-all').success(function (data) {
-        });
-    }
-
-    $scope.getAllResources = function () {
-        Album.getAll(function (albums) {
-            $scope.albums = albums;
-        });
-    }
-});
-
-module.controller('TokenCtrl', function ($scope, Identity) {
-    $scope.showRpt = function () {
-        document.getElementById("output").innerHTML = JSON.stringify(jwt_decode(Identity.authorization.rpt), null, '  ');
-    }
-
-    $scope.showAccessToken = function () {
-        document.getElementById("output").innerHTML = JSON.stringify(jwt_decode(Identity.authc.token), null, '  ');
-    }
-
-    $scope.requestEntitlements = function () {
-        Identity.authorization.entitlement('photoz-restful-api').then(function (rpt) {
-            document.getElementById("output").innerHTML = JSON.stringify(jwt_decode(rpt), null, '  ');
-        });
-    }
-    
-    $scope.requestEntitlement = function () {
-        Identity.authorization.entitlement('photoz-restful-api', {
-            "permissions": [
-                {
-                    "id" : "Album Resource"
-                }
-            ]
-        }).then(function (rpt) {
-            document.getElementById("output").innerHTML = JSON.stringify(jwt_decode(rpt), null, '  ');
-        });
-    }
-
-    $scope.Identity = Identity;
-});
-
-module.controller('AlbumCtrl', function ($scope, $http, $routeParams, $location, Album) {
-    $scope.album = {};
-    if ($routeParams.id) {
-        $scope.album = Album.get({id: $routeParams.id});
-    }
-    $scope.create = function () {
-        var newAlbum = new Album($scope.album);
-        newAlbum.$save({}, function (data) {
-            $location.path('/');
-        });
-    };
-
-    $scope.createManaged = function () {
-        $scope.album.userManaged = true;
-        var newAlbum = new Album($scope.album);
-        newAlbum.$save({}, function (data) {
-            $location.path('/');
-        });
-    };
-
-    $scope.createWithInvalidUser = function () {
-        var newAlbum = new Album($scope.album);
-        newAlbum.$save({user: 'invalidUser'}, function (data) {
-            document.getElementById("output").innerHTML = 'Request was successful'
-        },
-        function (response) {
-            document.getElementById("output").innerHTML = response.data;
-        });
-    };
-});
-
-module.controller('ProfileCtrl', function ($scope, $http, $routeParams, $location, Profile) {
-    $scope.profile = Profile.get();
-});
-
-module.controller('AdminAlbumCtrl', function ($scope, $http, $route, $location, AdminAlbum, Album) {
-    $scope.albums = {};
-    $http.get(apiUrl + '/admin/album').success(function (data) {
-        $scope.albums = data;
-    });
-    $scope.deleteAlbum = function (album) {
-        new Album(album).$delete({id: album.id}, function () {
-            $route.reload();
-        });
-    }
-});
-
-module.factory('Album', ['$resource', function ($resource) {
-    return $resource(apiUrl + '/album/:id', {id: '@id'}, {
-        getAll: {method: 'GET', params: {getAll: true}, isArray: true}
-    });
-}]);
-
-module.factory('Profile', ['$resource', function ($resource) {
-    return $resource(apiUrl + '/profile');
-}]);
-
-module.factory('AdminAlbum', ['$resource', function ($resource) {
-    return $resource(apiUrl + '/admin/album/:id');
-}]);
-
-module.factory('authInterceptor', function ($q, $injector, $timeout, Identity) {
-    return {
-        request: function (request) {
-            document.getElementById("output").innerHTML = '';
-            if (Identity.authorization && Identity.authorization.rpt && request.url.indexOf('/authorize') == -1) {
-                retries = 0;
-                request.headers.Authorization = 'Bearer ' + Identity.authorization.rpt;
-                document.getElementById("bearer").innerHTML = 'rpt: Bearer ' + Identity.authorization.rpt;
-            } else {
-                request.headers.Authorization = 'Bearer ' + Identity.authc.token;
-                document.getElementById("bearer").innerHTML = 'authc: Bearer ' + Identity.authc.token;
-            }
-            return request;
-        },
-        responseError: function (rejection) {
-            var status = rejection.status;
-
-            if (status == 403 || status == 401) {
-                var retry = (!rejection.config.retry ||  rejection.config.retry < 1);
-
-                if (!retry) {
-                    document.getElementById("output").innerHTML = 'You can not access or perform the requested operation on this resource.';
-                    return $q.reject(rejection);
-                }
-
-                if (rejection.config.url.indexOf('/authorize') == -1 && retry) {
-                    // here is the authorization logic, which tries to obtain an authorization token from the server in case the resource server
-                    // returns a 403 or 401.
-                    var wwwAuthenticateHeader = rejection.headers('WWW-Authenticate');
-
-                    // when using UMA, a WWW-Authenticate header should be returned by the resource server
-                    if (!wwwAuthenticateHeader) {
-                        return $q.reject(rejection);
-                    }
-
-                    // when using UMA, a WWW-Authenticate header should contain UMA data
-                    if (wwwAuthenticateHeader.indexOf('UMA') == -1) {
-                        return $q.reject(rejection);
-                    }
-
-                    var deferred = $q.defer();
-
-                    var params = wwwAuthenticateHeader.split(',');
-                    var ticket;
-
-                    // try to extract the permission ticket from the WWW-Authenticate header
-                    for (i = 0; i < params.length; i++) {
-                        var param = params[i].split('=');
-
-                        if (param[0] == 'ticket') {
-                            ticket = param[1].substring(1, param[1].length - 1).trim();
-                            break;
-                        }
-                    }
-
-                    // a permission ticket must exist in order to send an authorization request
-                    if (!ticket) {
-                        return $q.reject(rejection);
-                    }
-
-                    // prepare a authorization request with the permission ticket
-                    var authorizationRequest = {};
-                    authorizationRequest.ticket = ticket;
-
-                    // send the authorization request, if successful retry the request
-                    Identity.authorization.authorize(authorizationRequest).then(function (rpt) {
-                        deferred.resolve(rejection);
-                    }, function () {
-                        document.getElementById("output").innerHTML = 'You can not access or perform the requested operation on this resource.';
-                    }, function () {
-                        document.getElementById("output").innerHTML = 'Unexpected error from server.';
-                    });
-
-                    var promise = deferred.promise;
-
-                    return promise.then(function (res) {
-                        if (!res.config.retry) {
-                            res.config.retry = 1;
-                        } else {
-                            res.config.retry++;
-                        }
-
-                        var $http = $injector.get("$http");
-
-                        return $http(res.config).then(function (response) {
-                            return response;
-                        });
-                    });
-                }
-            }
-
-            return $q.reject(rejection);
-        }
-    };
-});
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/test-apps/photoz/photoz-html5-client/src/main/webapp/js/identity.js b/testsuite/integration-arquillian/test-apps/photoz/photoz-html5-client/src/main/webapp/js/identity.js
deleted file mode 100644
index 3a892b5549..0000000000
--- a/testsuite/integration-arquillian/test-apps/photoz/photoz-html5-client/src/main/webapp/js/identity.js
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- *  Copyright 2016 Red Hat, Inc. and/or its affiliates
- *  and other contributors as indicated by the @author tags.
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- *  you may not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- *
- */
-
-/**
- * Creates an Identity object holding the information obtained from the access token issued by Keycloak, after a successful authentication,
- * and a few utility methods to manage it.
- */
-(function (window, undefined) {
-    var Identity = function (keycloak) {
-        this.loggedIn = true;
-
-        this.claims = {};
-        this.claims.name = keycloak.idTokenParsed.name;
-        this.claims.sub = keycloak.idTokenParsed.sub;
-
-        this.authc = {};
-        this.authc.token = keycloak.token;
-
-        this.logout = function () {
-            keycloak.logout();
-        };
-
-        this.hasRole = function (name) {
-            if (keycloak && keycloak.hasRealmRole(name)) {
-                return true;
-            }
-            return false;
-        };
-
-        this.isAdmin = function () {
-            return this.hasRole("admin");
-        };
-
-        this.account = function () {
-            keycloak.accountManagement();
-        }
-
-        this.authorization = new KeycloakAuthorization(keycloak);
-    }
-
-    if ( typeof module === "object" && module && typeof module.exports === "object" ) {
-        module.exports = Identity;
-    } else {
-        window.Identity = Identity;
-
-        if ( typeof define === "function" && define.amd ) {
-            define( "identity", [], function () { return Identity; } );
-        }
-    }
-})( window );
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/test-apps/photoz/photoz-html5-client/src/main/webapp/lib/angular/angular-resource.min.js b/testsuite/integration-arquillian/test-apps/photoz/photoz-html5-client/src/main/webapp/lib/angular/angular-resource.min.js
deleted file mode 100644
index 3f196c3538..0000000000
--- a/testsuite/integration-arquillian/test-apps/photoz/photoz-html5-client/src/main/webapp/lib/angular/angular-resource.min.js
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- AngularJS v1.3.0-beta.5
- (c) 2010-2014 Google, Inc. http://angularjs.org
- License: MIT
-*/
-(function(H,a,A){'use strict';function D(p,g){g=g||{};a.forEach(g,function(a,c){delete g[c]});for(var c in p)!p.hasOwnProperty(c)||"$"===c.charAt(0)&&"$"===c.charAt(1)||(g[c]=p[c]);return g}var v=a.$$minErr("$resource"),C=/^(\.[a-zA-Z_$][0-9a-zA-Z_$]*)+$/;a.module("ngResource",["ng"]).factory("$resource",["$http","$q",function(p,g){function c(a,c){this.template=a;this.defaults=c||{};this.urlParams={}}function t(n,w,l){function r(h,d){var e={};d=x({},w,d);s(d,function(b,d){u(b)&&(b=b());var k;if(b&&
-b.charAt&&"@"==b.charAt(0)){k=h;var a=b.substr(1);if(null==a||""===a||"hasOwnProperty"===a||!C.test("."+a))throw v("badmember",a);for(var a=a.split("."),f=0,c=a.length;f").append(b).html();try{return 3===b[0].nodeType?I(c):c.match(/^(<[^>]+>)/)[1].replace(/^<([\w\-]+)/,
-function(a,b){return"<"+I(b)})}catch(d){return I(c)}}function $b(b){try{return decodeURIComponent(b)}catch(a){}}function ac(b){var a={},c,d;q((b||"").split("&"),function(b){b&&(c=b.split("="),d=$b(c[0]),B(d)&&(b=B(c[1])?$b(c[1]):!0,a[d]?M(a[d])?a[d].push(b):a[d]=[a[d],b]:a[d]=b))});return a}function bc(b){var a=[];q(b,function(b,d){M(b)?q(b,function(b){a.push(Aa(d,!0)+(!0===b?"":"="+Aa(b,!0)))}):a.push(Aa(d,!0)+(!0===b?"":"="+Aa(b,!0)))});return a.length?a.join("&"):""}function Bb(b){return Aa(b,
-!0).replace(/%26/gi,"&").replace(/%3D/gi,"=").replace(/%2B/gi,"+")}function Aa(b,a){return encodeURIComponent(b).replace(/%40/gi,"@").replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,a?"%20":"+")}function ed(b,a){function c(a){a&&d.push(a)}var d=[b],e,g,f=["ng:app","ng-app","x-ng-app","data-ng-app"],h=/\sng[:\-]app(:\s*([\w\d_]+);?)?\s/;q(f,function(a){f[a]=!0;c(U.getElementById(a));a=a.replace(":","\\:");b.querySelectorAll&&(q(b.querySelectorAll("."+a),c),q(b.querySelectorAll("."+
-a+"\\:"),c),q(b.querySelectorAll("["+a+"]"),c))});q(d,function(a){if(!e){var b=h.exec(" "+a.className+" ");b?(e=a,g=(b[2]||"").replace(/\s+/g,",")):q(a.attributes,function(b){!e&&f[b.name]&&(e=a,g=b.value)})}});e&&a(e,g?[g]:[])}function cc(b,a){var c=function(){b=y(b);if(b.injector()){var c=b[0]===U?"document":ha(b);throw Oa("btstrpd",c);}a=a||[];a.unshift(["$provide",function(a){a.value("$rootElement",b)}]);a.unshift("ng");c=dc(a);c.invoke(["$rootScope","$rootElement","$compile","$injector","$animate",
-function(a,b,c,d,e){a.$apply(function(){b.data("$injector",d);c(b)(a)})}]);return c},d=/^NG_DEFER_BOOTSTRAP!/;if(O&&!d.test(O.name))return c();O.name=O.name.replace(d,"");Qa.resumeBootstrap=function(b){q(b,function(b){a.push(b)});c()}}function ib(b,a){a=a||"_";return b.replace(fd,function(b,d){return(d?a:"")+b.toLowerCase()})}function Cb(b,a,c){if(!b)throw Oa("areq",a||"?",c||"required");return b}function Ra(b,a,c){c&&M(b)&&(b=b[b.length-1]);Cb(P(b),a,"not a function, got "+(b&&"object"==typeof b?
-b.constructor.name||"Object":typeof b));return b}function Ba(b,a){if("hasOwnProperty"===b)throw Oa("badname",a);}function ec(b,a,c){if(!a)return b;a=a.split(".");for(var d,e=b,g=a.length,f=0;f")+d[2];for(d=d[0];d--;)c=c.lastChild;g=g.concat(sa.call(c.childNodes,void 0));c=e.firstChild;c.textContent=""}else g.push(a.createTextNode(b));e.textContent="";e.innerHTML="";q(g,function(a){e.appendChild(a)});return e}function N(b){if(b instanceof
-N)return b;t(b)&&(b=ca(b));if(!(this instanceof N)){if(t(b)&&"<"!=b.charAt(0))throw Hb("nosel");return new N(b)}if(t(b)){var a;a=U;var c;b=(c=ve.exec(b))?[a.createElement(c[1])]:(c=se(b,a))?c.childNodes:[]}kc(this,b)}function Ib(b){return b.cloneNode(!0)}function Ia(b){lc(b);var a=0;for(b=b.childNodes||[];a=T?(c.preventDefault=
-null,c.stopPropagation=null,c.isDefaultPrevented=null):(delete c.preventDefault,delete c.stopPropagation,delete c.isDefaultPrevented)};c.elem=b;return c}function Ja(b){var a=typeof b,c;"object"==a&&null!==b?"function"==typeof(c=b.$$hashKey)?c=b.$$hashKey():c===s&&(c=b.$$hashKey=eb()):c=b;return a+":"+c}function Wa(b){q(b,this.put,this)}function sc(b){var a,c;"function"==typeof b?(a=b.$inject)||(a=[],b.length&&(c=b.toString().replace(ye,""),c=c.match(ze),q(c[1].split(Ae),function(b){b.replace(Be,function(b,
-c,d){a.push(d)})})),b.$inject=a):M(b)?(c=b.length-1,Ra(b[c],"fn"),a=b.slice(0,c)):Ra(b,"fn",!0);return a}function dc(b){function a(a){return function(b,c){if(X(b))q(b,Ub(a));else return a(b,c)}}function c(a,b){Ba(a,"service");if(P(b)||M(b))b=n.instantiate(b);if(!b.$get)throw Xa("pget",a);return l[a+h]=b}function d(a,b){return c(a,{$get:b})}function e(a){var b=[],c,d,g,h;q(a,function(a){if(!k.get(a)){k.put(a,!0);try{if(t(a))for(c=Sa(a),b=b.concat(e(c.requires)).concat(c._runBlocks),d=c._invokeQueue,
-g=0,h=d.length;g 4096 bytes)!"));else{if(m.cookie!==da)for(da=m.cookie,d=da.split("; "),Q={},g=0;gk&&this.remove(p.key),b},get:function(a){if(k<
-Number.MAX_VALUE){var b=l[a];if(!b)return;e(b)}return m[a]},remove:function(a){if(k").parent()[0])});var g=L(a,b,a,c,d,e);ma(a,"ng-scope");return function(b,c,d){Cb(b,"scope");var e=c?Ka.clone.call(a):a;q(d,function(a,b){e.data("$"+b+"Controller",a)});d=0;for(var f=e.length;darguments.length&&(b=a,a=s);A&&(c=da);return p(a,b,c)}var J,x,w,G,R,E,da={},ob;J=c===g?d:Xb(d,new Kb(y(g),
-d.$attr));x=J.$$element;if(Q){var S=/^\s*([@=&])(\??)\s*(\w*)\s*$/;f=y(g);E=e.$new(!0);ia&&ia===Q.$$originalDirective?f.data("$isolateScope",E):f.data("$isolateScopeNoTemplate",E);ma(f,"ng-isolate-scope");q(Q.scope,function(a,c){var d=a.match(S)||[],g=d[3]||c,f="?"==d[2],d=d[1],m,l,n,p;E.$$isolateBindings[c]=d+g;switch(d){case "@":J.$observe(g,function(a){E[c]=a});J.$$observers[g].$$scope=e;J[g]&&(E[c]=b(J[g])(e));break;case "=":if(f&&!J[g])break;l=r(J[g]);p=l.literal?za:function(a,b){return a===
-b};n=l.assign||function(){m=E[c]=l(e);throw ja("nonassign",J[g],Q.name);};m=E[c]=l(e);E.$watch(function(){var a=l(e);p(a,E[c])||(p(a,m)?n(e,a=E[c]):E[c]=a);return m=a},null,l.literal);break;case "&":l=r(J[g]);E[c]=function(a){return l(e,a)};break;default:throw ja("iscp",Q.name,c,a);}})}ob=p&&z;L&&q(L,function(a){var b={$scope:a===Q||a.$$isolateScope?E:e,$element:x,$attrs:J,$transclude:ob},c;R=a.controller;"@"==R&&(R=J[a.name]);c=u(R,b);da[a.name]=c;A||x.data("$"+a.name+"Controller",c);a.controllerAs&&
-(b.$scope[a.controllerAs]=c)});f=0;for(w=m.length;fF.priority)break;if(V=F.scope)G=G||F,F.templateUrl||(I("new/isolated scope",Q,F,Z),X(V)&&(Q=F));v=F.name;!F.templateUrl&&F.controller&&(V=F.controller,L=L||{},I("'"+v+"' controller",L[v],F,Z),L[v]=F);if(V=F.transclude)D=!0,F.$$tlb||(I("transclusion",S,F,Z),S=F),"element"==V?(A=!0,w=F.priority,V=E(c,T,W),Z=d.$$element=y(U.createComment(" "+v+": "+d[v]+" ")),c=Z[0],pb(g,y(sa.call(V,0)),
-c),Ya=x(V,e,w,f&&f.name,{nonTlbTranscludeDirective:S})):(V=y(Ib(c)).contents(),Z.empty(),Ya=x(V,e));if(F.template)if(I("template",ia,F,Z),ia=F,V=P(F.template)?F.template(Z,d):F.template,V=Y(V),F.replace){f=F;V=Gb.test(V)?y(V):[];c=V[0];if(1!=V.length||1!==c.nodeType)throw ja("tplrt",v,"");pb(g,Z,c);oa={$attr:{}};V=da(c,[],oa);var $=a.splice(N+1,a.length-(N+1));Q&&tc(V);a=a.concat(V).concat($);B(d,oa);oa=a.length}else Z.html(V);if(F.templateUrl)I("template",ia,F,Z),ia=F,F.replace&&(f=F),H=C(a.splice(N,
-a.length-N),Z,d,g,Ya,m,n,{controllerDirectives:L,newIsolateScopeDirective:Q,templateDirective:ia,nonTlbTranscludeDirective:S}),oa=a.length;else if(F.compile)try{O=F.compile(Z,d,Ya),P(O)?z(null,O,T,W):O&&z(O.pre,O.post,T,W)}catch(aa){l(aa,ha(Z))}F.terminal&&(H.terminal=!0,w=Math.max(w,F.priority))}H.scope=G&&!0===G.scope;H.transclude=D&&Ya;p.hasElementTranscludeDirective=A;return H}function tc(a){for(var b=0,c=a.length;bp.priority)&&-1!=p.restrict.indexOf(g)&&(n&&(p=Wb(p,{$$start:n,$$end:r})),b.push(p),k=p)}catch(K){l(K)}}return k}function B(a,b){var c=b.$attr,d=a.$attr,e=a.$$element;q(a,function(d,e){"$"!=e.charAt(0)&&(b[e]&&(d+=("style"===e?";":" ")+b[e]),a.$set(e,d,!0,c[e]))});q(b,function(b,g){"class"==g?(ma(e,b),a["class"]=(a["class"]?a["class"]+" ":"")+b):"style"==g?(e.attr("style",e.attr("style")+";"+b),a.style=
-(a.style?a.style+";":"")+b):"$"==g.charAt(0)||a.hasOwnProperty(g)||(a[g]=b,d[g]=c[g])})}function C(a,b,c,d,e,g,f,k){var m=[],l,r,u=b[0],z=a.shift(),K=A({},z,{templateUrl:null,transclude:null,replace:null,$$originalDirective:z}),x=P(z.templateUrl)?z.templateUrl(b,c):z.templateUrl;b.empty();n.get(w.getTrustedResourceUrl(x),{cache:p}).success(function(n){var p,H;n=Y(n);if(z.replace){n=Gb.test(n)?y(n):[];p=n[0];if(1!=n.length||1!==p.nodeType)throw ja("tplrt",z.name,x);n={$attr:{}};pb(d,b,p);var w=da(p,
-[],n);X(z.scope)&&tc(w);a=w.concat(a);B(c,n)}else p=u,b.html(n);a.unshift(K);l=ia(a,p,c,e,b,z,g,f,k);q(d,function(a,c){a==p&&(d[c]=b[0])});for(r=L(b[0].childNodes,e);m.length;){n=m.shift();H=m.shift();var G=m.shift(),R=m.shift(),w=b[0];if(H!==u){var E=H.className;k.hasElementTranscludeDirective&&z.replace||(w=Ib(p));pb(G,y(H),w);ma(y(w),E)}H=l.transclude?Q(n,l.transclude):R;l(r,n,w,d,H)}m=null}).error(function(a,b,c,d){throw ja("tpload",d.url);});return function(a,b,c,d,e){m?(m.push(b),m.push(c),
-m.push(d),m.push(e)):l(r,b,c,d,e)}}function D(a,b){var c=b.priority-a.priority;return 0!==c?c:a.name!==b.name?a.namea.status?b:n.reject(b)}var d={method:"get",
-transformRequest:e.transformRequest,transformResponse:e.transformResponse},g=function(a){function b(a){var c;q(a,function(b,d){P(b)&&(c=b(),null!=c?a[d]=c:delete a[d])})}var c=e.headers,d=A({},a.headers),g,f,c=A({},c.common,c[I(a.method)]);b(c);b(d);a:for(g in c){a=I(g);for(f in d)if(I(f)===a)continue a;d[g]=c[g]}return d}(a);A(d,a);d.headers=g;d.method=Ga(d.method);(a=Lb(d.url)?b.cookies()[d.xsrfCookieName||e.xsrfCookieName]:s)&&(g[d.xsrfHeaderName||e.xsrfHeaderName]=a);var f=[function(a){g=a.headers;
-var b=yc(a.data,xc(g),a.transformRequest);D(a.data)&&q(g,function(a,b){"content-type"===I(b)&&delete g[b]});D(a.withCredentials)&&!D(e.withCredentials)&&(a.withCredentials=e.withCredentials);return u(a,b,g).then(c,c)},s],h=n.when(d);for(q(w,function(a){(a.request||a.requestError)&&f.unshift(a.request,a.requestError);(a.response||a.responseError)&&f.push(a.response,a.responseError)});f.length;){a=f.shift();var k=f.shift(),h=h.then(a,k)}h.success=function(a){h.then(function(b){a(b.data,b.status,b.headers,
-d)});return h};h.error=function(a){h.then(null,function(b){a(b.data,b.status,b.headers,d)});return h};return h}function u(b,c,g){function f(a,b,c,e){w&&(200<=a&&300>a?w.put(s,[a,b,wc(c),e]):w.remove(s));m(b,a,c,e);d.$$phase||d.$apply()}function m(a,c,d,e){c=Math.max(c,0);(200<=c&&300>c?p.resolve:p.reject)({data:a,status:c,headers:xc(d),config:b,statusText:e})}function k(){var a=gb(r.pendingRequests,b);-1!==a&&r.pendingRequests.splice(a,1)}var p=n.defer(),u=p.promise,w,q,s=z(b.url,b.params);r.pendingRequests.push(b);
-u.then(k,k);(b.cache||e.cache)&&(!1!==b.cache&&"GET"==b.method)&&(w=X(b.cache)?b.cache:X(e.cache)?e.cache:K);if(w)if(q=w.get(s),B(q)){if(q.then)return q.then(k,k),q;M(q)?m(q[1],q[0],ba(q[2]),q[3]):m(q,200,{},"OK")}else w.put(s,u);D(q)&&a(b.method,s,c,f,g,b.timeout,b.withCredentials,b.responseType);return u}function z(a,b){if(!b)return a;var c=[];ad(b,function(a,b){null===a||D(a)||(M(a)||(a=[a]),q(a,function(a){X(a)&&(a=ta(a));c.push(Aa(b)+"="+Aa(a))}))});0=T&&(!b.match(/^(get|post|head|put|delete|options)$/i)||!O.XMLHttpRequest))return new O.ActiveXObject("Microsoft.XMLHTTP");if(O.XMLHttpRequest)return new O.XMLHttpRequest;throw v("$httpBackend")("noxhr");}function ce(){this.$get=["$browser","$window","$document",function(b,a,c){return Fe(b,Ee,b.defer,a.angular.callbacks,c[0])}]}function Fe(b,a,c,d,e){function g(a,b,c){var g=e.createElement("script"),f=null;g.type="text/javascript";g.src=a;g.async=
-!0;f=function(a){Ua(g,"load",f);Ua(g,"error",f);e.body.removeChild(g);g=null;var h=-1,u="unknown";a&&("load"!==a.type||d[b].called||(a={type:"error"}),u=a.type,h="error"===a.type?404:200);c&&c(h,u)};qb(g,"load",f);qb(g,"error",f);e.body.appendChild(g);return f}var f=-1;return function(e,m,k,l,n,p,r,u){function z(){w=f;G&&G();x&&x.abort()}function K(a,d,e,g,f){L&&c.cancel(L);G=x=null;0===d&&(d=e?200:"file"==ua(m).protocol?404:0);a(1223===d?204:d,e,g,f||"");b.$$completeOutstandingRequest(C)}var w;b.$$incOutstandingRequestCount();
-m=m||b.url();if("jsonp"==I(e)){var H="_"+(d.counter++).toString(36);d[H]=function(a){d[H].data=a;d[H].called=!0};var G=g(m.replace("JSON_CALLBACK","angular.callbacks."+H),H,function(a,b){K(l,a,d[H].data,"",b);d[H]=C})}else{var x=a(e);x.open(e,m,!0);q(n,function(a,b){B(a)&&x.setRequestHeader(b,a)});x.onreadystatechange=function(){if(x&&4==x.readyState){var a=null,b=null;w!==f&&(a=x.getAllResponseHeaders(),b="response"in x?x.response:x.responseText);K(l,w||x.status,b,a,x.statusText||"")}};r&&(x.withCredentials=
-!0);if(u)try{x.responseType=u}catch(s){if("json"!==u)throw s;}x.send(k||null)}if(0=h&&(n.resolve(r),l(p.$$intervalId),delete e[p.$$intervalId]);u||b.$apply()},f);e[p.$$intervalId]=n;return p}var e={};d.cancel=function(a){return a&&a.$$intervalId in e?(e[a.$$intervalId].reject("canceled"),clearInterval(a.$$intervalId),delete e[a.$$intervalId],
-!0):!1};return d}]}function jd(){this.$get=function(){return{id:"en-us",NUMBER_FORMATS:{DECIMAL_SEP:".",GROUP_SEP:",",PATTERNS:[{minInt:1,minFrac:0,maxFrac:3,posPre:"",posSuf:"",negPre:"-",negSuf:"",gSize:3,lgSize:3},{minInt:1,minFrac:2,maxFrac:2,posPre:"\u00a4",posSuf:"",negPre:"(\u00a4",negSuf:")",gSize:3,lgSize:3}],CURRENCY_SYM:"$"},DATETIME_FORMATS:{MONTH:"January February March April May June July August September October November December".split(" "),SHORTMONTH:"Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" "),
-DAY:"Sunday Monday Tuesday Wednesday Thursday Friday Saturday".split(" "),SHORTDAY:"Sun Mon Tue Wed Thu Fri Sat".split(" "),AMPMS:["AM","PM"],medium:"MMM d, y h:mm:ss a","short":"M/d/yy h:mm a",fullDate:"EEEE, MMMM d, y",longDate:"MMMM d, y",mediumDate:"MMM d, y",shortDate:"M/d/yy",mediumTime:"h:mm:ss a",shortTime:"h:mm a"},pluralCat:function(b){return 1===b?"one":"other"}}}}function Ac(b){b=b.split("/");for(var a=b.length;a--;)b[a]=Bb(b[a]);return b.join("/")}function Bc(b,a,c){b=ua(b,c);a.$$protocol=
-b.protocol;a.$$host=b.hostname;a.$$port=Y(b.port)||Ge[b.protocol]||null}function Cc(b,a,c){var d="/"!==b.charAt(0);d&&(b="/"+b);b=ua(b,c);a.$$path=decodeURIComponent(d&&"/"===b.pathname.charAt(0)?b.pathname.substring(1):b.pathname);a.$$search=ac(b.search);a.$$hash=decodeURIComponent(b.hash);a.$$path&&"/"!=a.$$path.charAt(0)&&(a.$$path="/"+a.$$path)}function pa(b,a){if(0===a.indexOf(b))return a.substr(b.length)}function Za(b){var a=b.indexOf("#");return-1==a?b:b.substr(0,a)}function Mb(b){return b.substr(0,
-Za(b).lastIndexOf("/")+1)}function Dc(b,a){this.$$html5=!0;a=a||"";var c=Mb(b);Bc(b,this,b);this.$$parse=function(a){var e=pa(c,a);if(!t(e))throw Nb("ipthprfx",a,c);Cc(e,this,b);this.$$path||(this.$$path="/");this.$$compose()};this.$$compose=function(){var a=bc(this.$$search),b=this.$$hash?"#"+Bb(this.$$hash):"";this.$$url=Ac(this.$$path)+(a?"?"+a:"")+b;this.$$absUrl=c+this.$$url.substr(1)};this.$$rewrite=function(d){var e;if((e=pa(b,d))!==s)return d=e,(e=pa(a,e))!==s?c+(pa("/",e)||e):b+d;if((e=pa(c,
-d))!==s)return c+e;if(c==d+"/")return c}}function Ob(b,a){var c=Mb(b);Bc(b,this,b);this.$$parse=function(d){var e=pa(b,d)||pa(c,d),e="#"==e.charAt(0)?pa(a,e):this.$$html5?e:"";if(!t(e))throw Nb("ihshprfx",d,a);Cc(e,this,b);d=this.$$path;var g=/^\/?.*?:(\/.*)/;0===e.indexOf(b)&&(e=e.replace(b,""));g.exec(e)||(d=(e=g.exec(d))?e[1]:d);this.$$path=d;this.$$compose()};this.$$compose=function(){var c=bc(this.$$search),e=this.$$hash?"#"+Bb(this.$$hash):"";this.$$url=Ac(this.$$path)+(c?"?"+c:"")+e;this.$$absUrl=
-b+(this.$$url?a+this.$$url:"")};this.$$rewrite=function(a){if(Za(b)==Za(a))return a}}function Ec(b,a){this.$$html5=!0;Ob.apply(this,arguments);var c=Mb(b);this.$$rewrite=function(d){var e;if(b==Za(d))return d;if(e=pa(c,d))return b+a+e;if(c===d+"/")return c}}function rb(b){return function(){return this[b]}}function Fc(b,a){return function(c){if(D(c))return this[b];this[b]=a(c);this.$$compose();return this}}function de(){var b="",a=!1;this.hashPrefix=function(a){return B(a)?(b=a,this):b};this.html5Mode=
-function(b){return B(b)?(a=b,this):a};this.$get=["$rootScope","$browser","$sniffer","$rootElement",function(c,d,e,g){function f(a){c.$broadcast("$locationChangeSuccess",h.absUrl(),a)}var h,m=d.baseHref(),k=d.url();a?(m=k.substring(0,k.indexOf("/",k.indexOf("//")+2))+(m||"/"),e=e.history?Dc:Ec):(m=Za(k),e=Ob);h=new e(m,"#"+b);h.$$parse(h.$$rewrite(k));g.on("click",function(a){if(!a.ctrlKey&&!a.metaKey&&2!=a.which){for(var b=y(a.target);"a"!==I(b[0].nodeName);)if(b[0]===g[0]||!(b=b.parent())[0])return;
-var e=b.prop("href");X(e)&&"[object SVGAnimatedString]"===e.toString()&&(e=ua(e.animVal).href);var f=h.$$rewrite(e);e&&(!b.attr("target")&&f&&!a.isDefaultPrevented())&&(a.preventDefault(),f!=d.url()&&(h.$$parse(f),c.$apply(),O.angular["ff-684208-preventDefault"]=!0))}});h.absUrl()!=k&&d.url(h.absUrl(),!0);d.onUrlChange(function(a){h.absUrl()!=a&&(c.$evalAsync(function(){var b=h.absUrl();h.$$parse(a);c.$broadcast("$locationChangeStart",a,b).defaultPrevented?(h.$$parse(b),d.url(b)):f(b)}),c.$$phase||
-c.$digest())});var l=0;c.$watch(function(){var a=d.url(),b=h.$$replace;l&&a==h.absUrl()||(l++,c.$evalAsync(function(){c.$broadcast("$locationChangeStart",h.absUrl(),a).defaultPrevented?h.$$parse(a):(d.url(h.absUrl(),b),f(a))}));h.$$replace=!1;return l});return h}]}function ee(){var b=!0,a=this;this.debugEnabled=function(a){return B(a)?(b=a,this):b};this.$get=["$window",function(c){function d(a){a instanceof Error&&(a.stack?a=a.message&&-1===a.stack.indexOf(a.message)?"Error: "+a.message+"\n"+a.stack:
-a.stack:a.sourceURL&&(a=a.message+"\n"+a.sourceURL+":"+a.line));return a}function e(a){var b=c.console||{},e=b[a]||b.log||C;a=!1;try{a=!!e.apply}catch(m){}return a?function(){var a=[];q(arguments,function(b){a.push(d(b))});return e.apply(b,a)}:function(a,b){e(a,null==b?"":b)}}return{log:e("log"),info:e("info"),warn:e("warn"),error:e("error"),debug:function(){var c=e("debug");return function(){b&&c.apply(a,arguments)}}()}}]}function fa(b,a){if("constructor"===b)throw Ca("isecfld",a);return b}function $a(b,
-a){if(b){if(b.constructor===b)throw Ca("isecfn",a);if(b.document&&b.location&&b.alert&&b.setInterval)throw Ca("isecwindow",a);if(b.children&&(b.nodeName||b.prop&&b.attr&&b.find))throw Ca("isecdom",a);}return b}function sb(b,a,c,d,e){e=e||{};a=a.split(".");for(var g,f=0;1e?Gc(d[0],d[1],d[2],d[3],d[4],c,a):function(b,g){var f=0,h;do h=Gc(d[f++],d[f++],d[f++],d[f++],d[f++],c,a)(b,g),g=s,b=h;while(fa)for(b in k++,e)e.hasOwnProperty(b)&&!d.hasOwnProperty(b)&&(q--,delete e[b])}else e!==d&&(e=d,k++);return k},function(){p?(p=!1,b(d,d,c)):b(d,f,c);if(h)if(X(d))if(db(d)){f=Array(d.length);for(var a=0;as&&(y=4-s,Q[y]||(Q[y]=[]),E=P(d.exp)?"fn: "+(d.exp.name||d.exp.toString()):d.exp,E+="; newVal: "+ta(g)+"; oldVal: "+ta(f),Q[y].push(E));else if(d===c){x=!1;break a}}catch(t){p.$$phase=
-null,e(t)}if(!(h=L.$$childHead||L!==this&&L.$$nextSibling))for(;L!==this&&!(h=L.$$nextSibling);)L=L.$parent}while(L=h);if((x||k.length)&&!s--)throw p.$$phase=null,a("infdig",b,ta(Q));}while(x||k.length);for(p.$$phase=null;l.length;)try{l.shift()()}catch(S){e(S)}},$destroy:function(){if(!this.$$destroyed){var a=this.$parent;this.$broadcast("$destroy");this.$$destroyed=!0;this!==p&&(q(this.$$listenerCount,hb(null,l,this)),a.$$childHead==this&&(a.$$childHead=this.$$nextSibling),a.$$childTail==this&&
-(a.$$childTail=this.$$prevSibling),this.$$prevSibling&&(this.$$prevSibling.$$nextSibling=this.$$nextSibling),this.$$nextSibling&&(this.$$nextSibling.$$prevSibling=this.$$prevSibling),this.$parent=this.$$nextSibling=this.$$prevSibling=this.$$childHead=this.$$childTail=this.$root=null,this.$$listeners={},this.$$watchers=this.$$asyncQueue=this.$$postDigestQueue=[],this.$destroy=this.$digest=this.$apply=C,this.$on=this.$watch=function(){return C})}},$eval:function(a,b){return g(a)(this,b)},$evalAsync:function(a){p.$$phase||
-p.$$asyncQueue.length||f.defer(function(){p.$$asyncQueue.length&&p.$digest()});this.$$asyncQueue.push({scope:this,expression:a})},$$postDigest:function(a){this.$$postDigestQueue.push(a)},$apply:function(a){try{return m("$apply"),this.$eval(a)}catch(b){e(b)}finally{p.$$phase=null;try{p.$digest()}catch(c){throw e(c),c;}}},$on:function(a,b){var c=this.$$listeners[a];c||(this.$$listeners[a]=c=[]);c.push(b);var d=this;do d.$$listenerCount[a]||(d.$$listenerCount[a]=0),d.$$listenerCount[a]++;while(d=d.$parent);
-var e=this;return function(){c[gb(c,b)]=null;l(e,1,a)}},$emit:function(a,b){var c=[],d,g=this,f=!1,h={name:a,targetScope:g,stopPropagation:function(){f=!0},preventDefault:function(){h.defaultPrevented=!0},defaultPrevented:!1},k=[h].concat(sa.call(arguments,1)),m,l;do{d=g.$$listeners[a]||c;h.currentScope=g;m=0;for(l=d.length;mc.msieDocumentMode)throw wa("iequirks");var e=ba(ga);e.isEnabled=function(){return b};e.trustAs=d.trustAs;e.getTrusted=d.getTrusted;e.valueOf=d.valueOf;b||(e.trustAs=e.getTrusted=function(a,b){return b},e.valueOf=Ea);e.parseAs=function(b,c){var d=a(c);return d.literal&&d.constant?d:function(a,c){return e.getTrusted(b,
-d(a,c))}};var g=e.parseAs,f=e.getTrusted,h=e.trustAs;q(ga,function(a,b){var c=I(b);e[Ta("parse_as_"+c)]=function(b){return g(a,b)};e[Ta("get_trusted_"+c)]=function(b){return f(a,b)};e[Ta("trust_as_"+c)]=function(b){return h(a,b)}});return e}]}function ke(){this.$get=["$window","$document",function(b,a){var c={},d=Y((/android (\d+)/.exec(I((b.navigator||{}).userAgent))||[])[1]),e=/Boxee/i.test((b.navigator||{}).userAgent),g=a[0]||{},f=g.documentMode,h,m=/^(Moz|webkit|O|ms)(?=[A-Z])/,k=g.body&&g.body.style,
-l=!1,n=!1;if(k){for(var p in k)if(l=m.exec(p)){h=l[0];h=h.substr(0,1).toUpperCase()+h.substr(1);break}h||(h="WebkitOpacity"in k&&"webkit");l=!!("transition"in k||h+"Transition"in k);n=!!("animation"in k||h+"Animation"in k);!d||l&&n||(l=t(g.body.style.webkitTransition),n=t(g.body.style.webkitAnimation))}return{history:!(!b.history||!b.history.pushState||4>d||e),hashchange:"onhashchange"in b&&(!f||7b;b=Math.abs(b);var f=b+"",h="",m=[],k=!1;if(-1!==f.indexOf("e")){var l=f.match(/([\d\.]+)e(-?)(\d+)/);l&&"-"==l[2]&&l[3]>e+1?f="0":(h=f,k=!0)}if(k)0b)&&(h=b.toFixed(e));
-else{f=(f.split(Rc)[1]||"").length;D(e)&&(e=Math.min(Math.max(a.minFrac,f),a.maxFrac));f=Math.pow(10,e);b=Math.round(b*f)/f;b=(""+b).split(Rc);f=b[0];b=b[1]||"";var l=0,n=a.lgSize,p=a.gSize;if(f.length>=n+p)for(l=f.length-n,k=0;kb&&(d="-",b=-b);for(b=""+b;b.length-c)e+=c;0===e&&-12==c&&(e=12);return tb(e,a,d)}}function ub(b,a){return function(c,d){var e=c["get"+b](),g=Ga(a?"SHORT"+b:b);return d[g][e]}}function Sc(b){var a=(new Date(b,0,1)).getDay();return new Date(b,0,(4>=a?5:12)-a)}function Tc(b){return function(a){var c=Sc(a.getFullYear());a=+new Date(a.getFullYear(),a.getMonth(),a.getDate()+
-(4-a.getDay()))-+c;a=1+Math.round(a/6048E5);return tb(a,b)}}function Nc(b){function a(a){var b;if(b=a.match(c)){a=new Date(0);var g=0,f=0,h=b[8]?a.setUTCFullYear:a.setFullYear,m=b[8]?a.setUTCHours:a.setHours;b[9]&&(g=Y(b[9]+b[10]),f=Y(b[9]+b[11]));h.call(a,Y(b[1]),Y(b[2])-1,Y(b[3]));g=Y(b[4]||0)-g;f=Y(b[5]||0)-f;h=Y(b[6]||0);b=Math.round(1E3*parseFloat("0."+(b[7]||0)));m.call(a,g,f,h,b)}return a}var c=/^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/;
-return function(c,e){var g="",f=[],h,m;e=e||"mediumDate";e=b.DATETIME_FORMATS[e]||e;t(c)&&(c=Qe.test(c)?Y(c):a(c));Ab(c)&&(c=new Date(c));if(!ra(c))return c;for(;e;)(m=Re.exec(e))?(f=f.concat(sa.call(m,1)),e=f.pop()):(f.push(e),e=null);q(f,function(a){h=Se[a];g+=h?h(c,b.DATETIME_FORMATS):a.replace(/(^'|'$)/g,"").replace(/''/g,"'")});return g}}function Me(){return function(b){return ta(b,!0)}}function Ne(){return function(b,a){if(!M(b)&&!t(b))return b;a=Y(a);if(t(b))return a?0<=a?b.slice(0,a):b.slice(a,
-b.length):"";var c=[],d,e;a>b.length?a=b.length:a<-b.length&&(a=-b.length);0a||37<=a&&40>=a)||l()});if(e.hasEvent("paste"))a.on("paste cut",l)}a.on("change",m);d.$render=function(){a.val(d.$isEmpty(d.$viewValue)?"":d.$viewValue)};var n=c.ngPattern;n&&((e=n.match(/^\/(.*)\/([gim]*)$/))?(n=RegExp(e[1],e[2]),e=function(a){return qa(d,"pattern",d.$isEmpty(a)||n.test(a),a)}):e=function(c){var e=b.$eval(n);if(!e||!e.test)throw v("ngPattern")("noregexp",n,
-e,ha(a));return qa(d,"pattern",d.$isEmpty(c)||e.test(c),c)},d.$formatters.push(e),d.$parsers.push(e));if(c.ngMinlength){var p=Y(c.ngMinlength);e=function(a){return qa(d,"minlength",d.$isEmpty(a)||a.length>=p,a)};d.$parsers.push(e);d.$formatters.push(e)}if(c.ngMaxlength){var r=Y(c.ngMaxlength);e=function(a){return qa(d,"maxlength",d.$isEmpty(a)||a.length<=r,a)};d.$parsers.push(e);d.$formatters.push(e)}}function zb(b,a){return function(c){var d;return ra(c)?c:t(c)&&(b.lastIndex=0,c=b.exec(c))?(c.shift(),
-d={yyyy:0,MM:1,dd:1,HH:0,mm:0},q(c,function(b,c){c=c(f.min);h.$setValidity("min",b);return b?a:
-s},h.$parsers.push(e),h.$formatters.push(e));f.max&&(e=function(a){var b=h.$isEmpty(a)||c(a)<=c(f.max);h.$setValidity("max",b);return b?a:s},h.$parsers.push(e),h.$formatters.push(e))}}function Rb(b,a){b="ngClass"+b;return["$animate",function(c){function d(a,b){var c=[],d=0;a:for(;dT?function(b){b=b.nodeName?b:b[0];return b.scopeName&&"HTML"!=b.scopeName?Ga(b.scopeName+":"+b.nodeName):b.nodeName}:function(b){return b.nodeName?b.nodeName:b[0].nodeName};var fd=/[A-Z]/g,id={full:"1.3.0-beta.5",major:1,minor:3,dot:0,codeName:"chimeric-glitterfication"},Va=N.cache={},jb=N.expando="ng-"+
-(new Date).getTime(),we=1,qb=O.document.addEventListener?function(b,a,c){b.addEventListener(a,c,!1)}:function(b,a,c){b.attachEvent("on"+a,c)},Ua=O.document.removeEventListener?function(b,a,c){b.removeEventListener(a,c,!1)}:function(b,a,c){b.detachEvent("on"+a,c)};N._data=function(b){return this.cache[b[this.expando]]||{}};var qe=/([\:\-\_]+(.))/g,re=/^moz([A-Z])/,Hb=v("jqLite"),ve=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,Gb=/<|&#?\w+;/,te=/<([\w:]+)/,ue=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,
-ea={option:[1,'"],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};ea.optgroup=ea.option;ea.tbody=ea.tfoot=ea.colgroup=ea.caption=ea.thead;ea.th=ea.td;var Ka=N.prototype={ready:function(b){function a(){c||(c=!0,b())}var c=!1;"complete"===U.readyState?setTimeout(a):(this.on("DOMContentLoaded",a),N(O).on("load",a))}, -toString:function(){var b=[];q(this,function(a){b.push(""+a)});return"["+b.join(", ")+"]"},eq:function(b){return 0<=b?y(this[b]):y(this[this.length+b])},length:0,push:Ue,sort:[].sort,splice:[].splice},nb={};q("multiple selected checked disabled readOnly required open".split(" "),function(b){nb[I(b)]=b});var rc={};q("input select option textarea button form details".split(" "),function(b){rc[Ga(b)]=!0});q({data:nc,inheritedData:mb,scope:function(b){return y(b).data("$scope")||mb(b.parentNode||b,["$isolateScope", -"$scope"])},isolateScope:function(b){return y(b).data("$isolateScope")||y(b).data("$isolateScopeNoTemplate")},controller:oc,injector:function(b){return mb(b,"$injector")},removeAttr:function(b,a){b.removeAttribute(a)},hasClass:Jb,css:function(b,a,c){a=Ta(a);if(B(c))b.style[a]=c;else{var d;8>=T&&(d=b.currentStyle&&b.currentStyle[a],""===d&&(d="auto"));d=d||b.style[a];8>=T&&(d=""===d?s:d);return d}},attr:function(b,a,c){var d=I(a);if(nb[d])if(B(c))c?(b[a]=!0,b.setAttribute(a,d)):(b[a]=!1,b.removeAttribute(d)); -else return b[a]||(b.attributes.getNamedItem(a)||C).specified?d:s;else if(B(c))b.setAttribute(a,c);else if(b.getAttribute)return b=b.getAttribute(a,2),null===b?s:b},prop:function(b,a,c){if(B(c))b[a]=c;else return b[a]},text:function(){function b(b,d){var e=a[b.nodeType];if(D(d))return e?b[e]:"";b[e]=d}var a=[];9>T?(a[1]="innerText",a[3]="nodeValue"):a[1]=a[3]="textContent";b.$dv="";return b}(),val:function(b,a){if(D(a)){if("SELECT"===La(b)&&b.multiple){var c=[];q(b.options,function(a){a.selected&& -c.push(a.value||a.text)});return 0===c.length?null:c}return b.value}b.value=a},html:function(b,a){if(D(a))return b.innerHTML;for(var c=0,d=b.childNodes;c":function(a,c,d,e){return d(a,c)>e(a,c)},"<=":function(a,c,d,e){return d(a,c)<=e(a,c)},">=":function(a,c,d,e){return d(a,c)>=e(a,c)},"&&":function(a,c,d,e){return d(a,c)&&e(a,c)},"||":function(a,c,d,e){return d(a,c)||e(a,c)},"&":function(a,c,d,e){return d(a,c)&e(a,c)},"|":function(a,c,d,e){return e(a,c)(a,c,d(a,c))},"!":function(a,c,d){return!d(a,c)}},Xe={n:"\n",f:"\f",r:"\r",t:"\t",v:"\v","'":"'",'"':'"'}, -Qb=function(a){this.options=a};Qb.prototype={constructor:Qb,lex:function(a){this.text=a;this.index=0;this.ch=s;this.lastCh=":";this.tokens=[];var c;for(a=[];this.index=a},isWhitespace:function(a){return" "===a||"\r"===a||"\t"===a||"\n"===a||"\v"===a||"\u00a0"=== -a},isIdent:function(a){return"a"<=a&&"z">=a||"A"<=a&&"Z">=a||"_"===a||"$"===a},isExpOperator:function(a){return"-"===a||"+"===a||this.isNumber(a)},throwError:function(a,c,d){d=d||this.index;c=B(c)?"s "+c+"-"+this.index+" ["+this.text.substring(c,d)+"]":" "+d;throw Ca("lexerr",a,c,this.text);},readNumber:function(){for(var a="",c=this.index;this.index","<=",">="))a=this.binaryFn(a,c.fn,this.relational());return a},additive:function(){for(var a=this.multiplicative(),c;c=this.expect("+","-");)a=this.binaryFn(a,c.fn,this.multiplicative());return a},multiplicative:function(){for(var a=this.unary(),c;c=this.expect("*","/","%");)a=this.binaryFn(a,c.fn,this.unary());return a},unary:function(){var a;return this.expect("+")?this.primary():(a=this.expect("-"))?this.binaryFn(ab.ZERO,a.fn, -this.unary()):(a=this.expect("!"))?this.unaryFn(a.fn,this.unary()):this.primary()},fieldAccess:function(a){var c=this,d=this.expect().text,e=Hc(d,this.options,this.text);return A(function(c,d,h){return e(h||a(c,d))},{assign:function(e,f,h){return sb(a(e,h),d,f,c.text,c.options)}})},objectIndex:function(a){var c=this,d=this.expression();this.consume("]");return A(function(e,g){var f=a(e,g),h=d(e,g),m;if(!f)return s;(f=$a(f[h],c.text))&&(f.then&&c.options.unwrapPromises)&&(m=f,"$$v"in f||(m.$$v=s,m.then(function(a){m.$$v= -a})),f=f.$$v);return f},{assign:function(e,g,f){var h=d(e,f);return $a(a(e,f),c.text)[h]=g}})},functionCall:function(a,c){var d=[];if(")"!==this.peekToken().text){do d.push(this.expression());while(this.expect(","))}this.consume(")");var e=this;return function(g,f){for(var h=[],m=c?c(g,f):g,k=0;ka.getHours()?c.AMPMS[0]:c.AMPMS[1]},Z:function(a){a=-1*a.getTimezoneOffset();return a=(0<=a?"+":"")+(tb(Math[0=T&&(c.href||c.name||c.$set("href",""),a.append(U.createComment("IE fix")));if(!c.href&&!c.xlinkHref&&!c.name)return function(a,c){var g="[object SVGAnimatedString]"===ya.call(c.prop("href"))?"xlink:href":"href";c.on("click",function(a){c.attr(g)||a.preventDefault()})}}}),Eb={};q(nb,function(a,c){if("multiple"!=a){var d=na("ng-"+c);Eb[d]=function(){return{priority:100,link:function(a,g,f){a.$watch(f[d],function(a){f.$set(c, -!!a)})}}}}});q(["src","srcset","href"],function(a){var c=na("ng-"+a);Eb[c]=function(){return{priority:99,link:function(d,e,g){var f=a,h=a;"href"===a&&"[object SVGAnimatedString]"===ya.call(e.prop("href"))&&(h="xlinkHref",g.$attr[h]="xlink:href",f=null);g.$observe(c,function(a){a&&(g.$set(h,a),T&&f&&e.prop(f,g[h]))})}}}});var xb={$addControl:C,$removeControl:C,$setValidity:C,$setDirty:C,$setPristine:C};Uc.$inject=["$element","$attrs","$scope","$animate"];var Vc=function(a){return["$timeout",function(c){return{name:"form", -restrict:a?"EAC":"E",controller:Uc,compile:function(){return{pre:function(a,e,g,f){if(!g.action){var h=function(a){a.preventDefault?a.preventDefault():a.returnValue=!1};qb(e[0],"submit",h);e.on("$destroy",function(){c(function(){Ua(e[0],"submit",h)},0,!1)})}var m=e.parent().controller("form"),k=g.name||g.ngForm;k&&sb(a,k,f,k);if(m)e.on("$destroy",function(){m.$removeControl(f);k&&sb(a,k,s,k);A(f,xb)})}}}}}]},md=Vc(),zd=Vc(!0),Ye=/^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/, -Ze=/^[a-z0-9!#$%&'*+/=?^_`{|}~.-]+@[a-z0-9-]+(\.[a-z0-9-]+)*$/i,$e=/^\s*(\-|\+)?(\d+|(\d*(\.\d*)))\s*$/,Wc=/^(\d{4})-(\d{2})-(\d{2})$/,Xc=/^(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d)$/,Sb=/^(\d{4})-W(\d\d)$/,Yc=/^(\d{4})-(\d\d)$/,Zc=/^(\d\d):(\d\d)$/,$c={text:bb,date:cb("date",Wc,zb(Wc,["yyyy","MM","dd"]),"yyyy-MM-dd"),"datetime-local":cb("datetimelocal",Xc,zb(Xc,["yyyy","MM","dd","HH","mm"]),"yyyy-MM-ddTHH:mm"),time:cb("time",Zc,zb(Zc,["HH","mm"]),"HH:mm"),week:cb("week",Sb,function(a){if(ra(a))return a; -if(t(a)){Sb.lastIndex=0;var c=Sb.exec(a);if(c){a=+c[1];var d=+c[2],c=Sc(a),d=7*(d-1);return new Date(a,0,c.getDate()+d)}}return NaN},"yyyy-Www"),month:cb("month",Yc,zb(Yc,["yyyy","MM"]),"yyyy-MM"),number:function(a,c,d,e,g,f){bb(a,c,d,e,g,f);e.$parsers.push(function(a){var c=e.$isEmpty(a);if(c||$e.test(a))return e.$setValidity("number",!0),""===a?null:c?a:parseFloat(a);e.$setValidity("number",!1);return s});Te(e,"number",c);e.$formatters.push(function(a){return e.$isEmpty(a)?"":""+a});d.min&&(a=function(a){var c= -parseFloat(d.min);return qa(e,"min",e.$isEmpty(a)||a>=c,a)},e.$parsers.push(a),e.$formatters.push(a));d.max&&(a=function(a){var c=parseFloat(d.max);return qa(e,"max",e.$isEmpty(a)||a<=c,a)},e.$parsers.push(a),e.$formatters.push(a));e.$formatters.push(function(a){return qa(e,"number",e.$isEmpty(a)||Ab(a),a)})},url:function(a,c,d,e,g,f){bb(a,c,d,e,g,f);a=function(a){return qa(e,"url",e.$isEmpty(a)||Ye.test(a),a)};e.$formatters.push(a);e.$parsers.push(a)},email:function(a,c,d,e,g,f){bb(a,c,d,e,g,f); -a=function(a){return qa(e,"email",e.$isEmpty(a)||Ze.test(a),a)};e.$formatters.push(a);e.$parsers.push(a)},radio:function(a,c,d,e){D(d.name)&&c.attr("name",eb());c.on("click",function(){c[0].checked&&a.$apply(function(){e.$setViewValue(d.value)})});e.$render=function(){c[0].checked=d.value==e.$viewValue};d.$observe("value",e.$render)},checkbox:function(a,c,d,e){var g=d.ngTrueValue,f=d.ngFalseValue;t(g)||(g=!0);t(f)||(f=!1);c.on("click",function(){a.$apply(function(){e.$setViewValue(c[0].checked)})}); -e.$render=function(){c[0].checked=e.$viewValue};e.$isEmpty=function(a){return a!==g};e.$formatters.push(function(a){return a===g});e.$parsers.push(function(a){return a?g:f})},hidden:C,button:C,submit:C,reset:C,file:C},gc=["$browser","$sniffer","$filter",function(a,c,d){return{restrict:"E",require:"?ngModel",link:function(e,g,f,h){h&&($c[I(f.type)]||$c.text)(e,g,f,h,c,a,d)}}}],wb="ng-valid",vb="ng-invalid",Ma="ng-pristine",yb="ng-dirty",af=["$scope","$exceptionHandler","$attrs","$element","$parse", -"$animate",function(a,c,d,e,g,f){function h(a,c){c=c?"-"+ib(c,"-"):"";f.removeClass(e,(a?vb:wb)+c);f.addClass(e,(a?wb:vb)+c)}this.$modelValue=this.$viewValue=Number.NaN;this.$parsers=[];this.$formatters=[];this.$viewChangeListeners=[];this.$pristine=!0;this.$dirty=!1;this.$valid=!0;this.$invalid=!1;this.$name=d.name;var m=g(d.ngModel),k=m.assign;if(!k)throw v("ngModel")("nonassign",d.ngModel,ha(e));this.$render=C;this.$isEmpty=function(a){return D(a)||""===a||null===a||a!==a};var l=e.inheritedData("$formController")|| -xb,n=0,p=this.$error={};e.addClass(Ma);h(!0);this.$setValidity=function(a,c){p[a]!==!c&&(c?(p[a]&&n--,n||(h(!0),this.$valid=!0,this.$invalid=!1)):(h(!1),this.$invalid=!0,this.$valid=!1,n++),p[a]=!c,h(c,a),l.$setValidity(a,c,this))};this.$setPristine=function(){this.$dirty=!1;this.$pristine=!0;f.removeClass(e,yb);f.addClass(e,Ma)};this.$setViewValue=function(d){this.$viewValue=d;this.$pristine&&(this.$dirty=!0,this.$pristine=!1,f.removeClass(e,Ma),f.addClass(e,yb),l.$setDirty());q(this.$parsers,function(a){d= -a(d)});this.$modelValue!==d&&(this.$modelValue=d,k(a,d),q(this.$viewChangeListeners,function(a){try{a()}catch(d){c(d)}}))};var r=this;a.$watch(function(){var c=m(a);if(r.$modelValue!==c){var d=r.$formatters,e=d.length;for(r.$modelValue=c;e--;)c=d[e](c);r.$viewValue!==c&&(r.$viewValue=c,r.$render())}return c})}],Od=function(){return{require:["ngModel","^?form"],controller:af,link:function(a,c,d,e){var g=e[0],f=e[1]||xb;f.$addControl(g);a.$on("$destroy",function(){f.$removeControl(g)})}}},Qd=aa({require:"ngModel", -link:function(a,c,d,e){e.$viewChangeListeners.push(function(){a.$eval(d.ngChange)})}}),hc=function(){return{require:"?ngModel",link:function(a,c,d,e){if(e){d.required=!0;var g=function(a){if(d.required&&e.$isEmpty(a))e.$setValidity("required",!1);else return e.$setValidity("required",!0),a};e.$formatters.push(g);e.$parsers.unshift(g);d.$observe("required",function(){g(e.$viewValue)})}}}},Pd=function(){return{require:"ngModel",link:function(a,c,d,e){var g=(a=/\/(.*)\//.exec(d.ngList))&&RegExp(a[1])|| -d.ngList||",";e.$parsers.push(function(a){if(!D(a)){var c=[];a&&q(a.split(g),function(a){a&&c.push(ca(a))});return c}});e.$formatters.push(function(a){return M(a)?a.join(", "):s});e.$isEmpty=function(a){return!a||!a.length}}}},bf=/^(true|false|\d+)$/,Rd=function(){return{priority:100,compile:function(a,c){return bf.test(c.ngValue)?function(a,c,g){g.$set("value",a.$eval(g.ngValue))}:function(a,c,g){a.$watch(g.ngValue,function(a){g.$set("value",a)})}}}},rd=xa(function(a,c,d){c.addClass("ng-binding").data("$binding", -d.ngBind);a.$watch(d.ngBind,function(a){c.text(a==s?"":a)})}),td=["$interpolate",function(a){return function(c,d,e){c=a(d.attr(e.$attr.ngBindTemplate));d.addClass("ng-binding").data("$binding",c);e.$observe("ngBindTemplate",function(a){d.text(a)})}}],sd=["$sce","$parse",function(a,c){return function(d,e,g){e.addClass("ng-binding").data("$binding",g.ngBindHtml);var f=c(g.ngBindHtml);d.$watch(function(){return(f(d)||"").toString()},function(c){e.html(a.getTrustedHtml(f(d))||"")})}}],ud=Rb("",!0),wd= -Rb("Odd",0),vd=Rb("Even",1),xd=xa({compile:function(a,c){c.$set("ngCloak",s);a.removeClass("ng-cloak")}}),yd=[function(){return{scope:!0,controller:"@",priority:500}}],ic={};q("click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress submit focus blur copy cut paste".split(" "),function(a){var c=na("ng-"+a);ic[c]=["$parse",function(d){return{compile:function(e,g){var f=d(g[c]);return function(c,d,e){d.on(I(a),function(a){c.$apply(function(){f(c,{$event:a})})})}}}}]}); -var Bd=["$animate",function(a){return{transclude:"element",priority:600,terminal:!0,restrict:"A",$$tlb:!0,link:function(c,d,e,g,f){var h,m,k;c.$watch(e.ngIf,function(g){Pa(g)?m||(m=c.$new(),f(m,function(c){c[c.length++]=U.createComment(" end ngIf: "+e.ngIf+" ");h={clone:c};a.enter(c,d.parent(),d)})):(k&&(k.remove(),k=null),m&&(m.$destroy(),m=null),h&&(k=Db(h.clone),a.leave(k,function(){k=null}),h=null))})}}}],Cd=["$http","$templateCache","$anchorScroll","$animate","$sce",function(a,c,d,e,g){return{restrict:"ECA", -priority:400,terminal:!0,transclude:"element",controller:Qa.noop,compile:function(f,h){var m=h.ngInclude||h.src,k=h.onload||"",l=h.autoscroll;return function(f,h,r,q,z){var s=0,w,y,G,x=function(){y&&(y.remove(),y=null);w&&(w.$destroy(),w=null);G&&(e.leave(G,function(){y=null}),y=G,G=null)};f.$watch(g.parseAsResourceUrl(m),function(g){var m=function(){!B(l)||l&&!f.$eval(l)||d()},r=++s;g?(a.get(g,{cache:c}).success(function(a){if(r===s){var c=f.$new();q.template=a;a=z(c,function(a){x();e.enter(a,null, -h,m)});w=c;G=a;w.$emit("$includeContentLoaded");f.$eval(k)}}).error(function(){r===s&&x()}),f.$emit("$includeContentRequested")):(x(),q.template=null)})}}}}],Sd=["$compile",function(a){return{restrict:"ECA",priority:-400,require:"ngInclude",link:function(c,d,e,g){d.html(g.template);a(d.contents())(c)}}}],Dd=xa({priority:450,compile:function(){return{pre:function(a,c,d){a.$eval(d.ngInit)}}}}),Ed=xa({terminal:!0,priority:1E3}),Fd=["$locale","$interpolate",function(a,c){var d=/{}/g;return{restrict:"EA", -link:function(e,g,f){var h=f.count,m=f.$attr.when&&g.attr(f.$attr.when),k=f.offset||0,l=e.$eval(m)||{},n={},p=c.startSymbol(),r=c.endSymbol(),s=/^when(Minus)?(.+)$/;q(f,function(a,c){s.test(c)&&(l[I(c.replace("when","").replace("Minus","-"))]=g.attr(f.$attr[c]))});q(l,function(a,e){n[e]=c(a.replace(d,p+h+"-"+k+r))});e.$watch(function(){var c=parseFloat(e.$eval(h));if(isNaN(c))return"";c in l||(c=a.pluralCat(c-k));return n[c](e,g,!0)},function(a){g.text(a)})}}}],Gd=["$parse","$animate",function(a, -c){var d=v("ngRepeat");return{transclude:"element",priority:1E3,terminal:!0,$$tlb:!0,link:function(e,g,f,h,m){var k=f.ngRepeat,l=k.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),n,p,r,s,z,B,w={$id:Ja};if(!l)throw d("iexp",k);f=l[1];h=l[2];(l=l[3])?(n=a(l),p=function(a,c,d){B&&(w[B]=a);w[z]=c;w.$index=d;return n(e,w)}):(r=function(a,c){return Ja(c)},s=function(a){return a});l=f.match(/^(?:([\$\w]+)|\(([\$\w]+)\s*,\s*([\$\w]+)\))$/);if(!l)throw d("iidexp",f);z=l[3]||l[1]; -B=l[2];var H={};e.$watchCollection(h,function(a){var f,h,l=g[0],n,w={},E,R,t,C,S,v,D=[];if(db(a))S=a,n=p||r;else{n=p||s;S=[];for(t in a)a.hasOwnProperty(t)&&"$"!=t.charAt(0)&&S.push(t);S.sort()}E=S.length;h=D.length=S.length;for(f=0;fA;)u.pop().element.remove()}for(;x.length>J;)x.pop()[0].element.remove()}var k;if(!(k= -t.match(d)))throw cf("iexp",t,ha(f));var m=c(k[2]||k[1]),l=k[4]||k[6],n=k[5],p=c(k[3]||""),q=c(k[2]?k[1]:l),y=c(k[7]),v=k[8]?c(k[8]):null,x=[[{element:f,label:""}]];z&&(a(z)(e),z.removeClass("ng-scope"),z.remove());f.empty();f.on("change",function(){e.$apply(function(){var a,c=y(e)||[],d={},h,k,m,p,t,w,u;if(r)for(k=[],p=0,w=x.length;p@charset "UTF-8";[ng\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak,.ng-hide{display:none !important;}ng\\:form{display:block;}'); -//# sourceMappingURL=angular.min.js.map diff --git a/testsuite/integration-arquillian/test-apps/photoz/photoz-html5-client/src/main/webapp/partials/admin/albums.html b/testsuite/integration-arquillian/test-apps/photoz/photoz-html5-client/src/main/webapp/partials/admin/albums.html deleted file mode 100644 index 00f52d7018..0000000000 --- a/testsuite/integration-arquillian/test-apps/photoz/photoz-html5-client/src/main/webapp/partials/admin/albums.html +++ /dev/null @@ -1,19 +0,0 @@ -

All Albums

- - - - - - - - - - - -
{{key}}
- -
\ No newline at end of file diff --git a/testsuite/integration-arquillian/test-apps/photoz/photoz-html5-client/src/main/webapp/partials/album/create.html b/testsuite/integration-arquillian/test-apps/photoz/photoz-html5-client/src/main/webapp/partials/album/create.html deleted file mode 100644 index ab65313b69..0000000000 --- a/testsuite/integration-arquillian/test-apps/photoz/photoz-html5-client/src/main/webapp/partials/album/create.html +++ /dev/null @@ -1,9 +0,0 @@ -

Create an Album

- -
- Name: - - - - -
diff --git a/testsuite/integration-arquillian/test-apps/photoz/photoz-html5-client/src/main/webapp/partials/album/detail.html b/testsuite/integration-arquillian/test-apps/photoz/photoz-html5-client/src/main/webapp/partials/album/detail.html deleted file mode 100644 index cf32df1480..0000000000 --- a/testsuite/integration-arquillian/test-apps/photoz/photoz-html5-client/src/main/webapp/partials/album/detail.html +++ /dev/null @@ -1 +0,0 @@ -

{{album.name}}

\ No newline at end of file diff --git a/testsuite/integration-arquillian/test-apps/photoz/photoz-html5-client/src/main/webapp/partials/home.html b/testsuite/integration-arquillian/test-apps/photoz/photoz-html5-client/src/main/webapp/partials/home.html deleted file mode 100644 index b4208bbeec..0000000000 --- a/testsuite/integration-arquillian/test-apps/photoz/photoz-html5-client/src/main/webapp/partials/home.html +++ /dev/null @@ -1,22 +0,0 @@ -

Welcome To Photoz, {{Identity.claims.name}}

-
Administration: [All Albums]
-
-
-
-Create Album | My Profile | Any Scope Access | All Scope Access | Get All Resources -
-
-You don't have any albums, yet. - - - - - - - - - - - -
Your Albums
{{p.name}} - [X]
-
\ No newline at end of file diff --git a/testsuite/integration-arquillian/test-apps/photoz/photoz-html5-client/src/main/webapp/partials/profile.html b/testsuite/integration-arquillian/test-apps/photoz/photoz-html5-client/src/main/webapp/partials/profile.html deleted file mode 100644 index c6f6750a4c..0000000000 --- a/testsuite/integration-arquillian/test-apps/photoz/photoz-html5-client/src/main/webapp/partials/profile.html +++ /dev/null @@ -1,6 +0,0 @@ -

My Profile

- -
-

Name: {{profile.userName}}

-

Total of albums: {{profile.totalAlbums}}

-
diff --git a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api-authz-service.json b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api-authz-service.json index 7327cba332..ffb7126916 100644 --- a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api-authz-service.json +++ b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api-authz-service.json @@ -99,7 +99,7 @@ "decisionStrategy": "UNANIMOUS", "config": { "applyPolicies": "[]", - "code": "var contextAttributes = $evaluation.getContext().getAttributes();\n\nif (contextAttributes.containsValue('kc.client.network.ip_address', '127.0.0.1')) {\n $evaluation.grant();\n}" + "code": "var contextAttributes = $evaluation.getContext().getAttributes();\n\nif (contextAttributes.containsValue('kc.client.network.ip_address', '127.0.0.1') || contextAttributes.containsValue('kc.client.network.ip_address', '0:0:0:0:0:0:0:1')) {\n $evaluation.grant();\n}" } }, { diff --git a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/pom.xml b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/pom.xml index e06fe6425d..5f1c1504d4 100755 --- a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/pom.xml +++ b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/pom.xml @@ -70,6 +70,14 @@ false + + org.apache.maven.plugins + maven-war-plugin + 3.0.0 + + true + + diff --git a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/CustomDatabase.java b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/CustomDatabase.java new file mode 100644 index 0000000000..9c06eff79b --- /dev/null +++ b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/CustomDatabase.java @@ -0,0 +1,88 @@ +package org.keycloak.example.photoz; + +import org.keycloak.example.photoz.entity.Album; +import org.keycloak.example.photoz.entity.Photo; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/** + * @author mhajas + */ +public class CustomDatabase { + + private static final CustomDatabase INSTANCE = new CustomDatabase(); + private List albums; + private List photos; + private Long lastIndex = 0L; + + + public static final CustomDatabase create() { + return INSTANCE; + } + + private CustomDatabase() { + albums = new ArrayList<>(); + } + + public List getAll() { + return albums; + } + + public void addAlbum(Album a) { + a.setId(lastIndex++); + albums.add(a); + } + + public void remove(Album albumToRemove) { + Iterator iter = albums.iterator(); + + while (iter.hasNext()) { + Album a = iter.next(); + if (a.getId().equals(albumToRemove.getId())) { + iter.remove(); + } + } + } + + public Album findById(Long id) { + for (Album a : albums) { + if(a.getId().equals(id)) { + return a; + } + } + + return null; + } + + public Album findByName(String name) { + for (Album a : albums) { + if(a.getName().equals(name)) { + return a; + } + } + + return null; + } + + public List findByUserId(String userId) { + List result = new ArrayList<>(); + + for (Album a : albums) { + if (a.getUserId().equals(userId)) { + result.add(a); + } + } + + return result; + } + + public int cleanAll() { + int result = albums.size() + photos.size(); + albums.clear(); + photos.clear(); + + return result; + } +} diff --git a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/PhotozApplication.java b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/PhotozApplication.java index 5b8377ced6..90e0951515 100644 --- a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/PhotozApplication.java +++ b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/PhotozApplication.java @@ -1,12 +1,27 @@ package org.keycloak.example.photoz; +import org.keycloak.example.photoz.admin.AdminAlbumService; +import org.keycloak.example.photoz.album.AlbumService; +import org.keycloak.example.photoz.album.ProfileService; +import org.keycloak.example.photoz.unsecured.UnsecuredService; + import javax.ws.rs.ApplicationPath; import javax.ws.rs.core.Application; +import java.util.LinkedHashSet; +import java.util.Set; /** * Basic auth app. */ @ApplicationPath("/") public class PhotozApplication extends Application { - + @Override + public Set> getClasses() { + Set> resources = new LinkedHashSet>(); + resources.add(AlbumService.class); + resources.add(AdminAlbumService.class); + resources.add(ProfileService.class); + resources.add(UnsecuredService.class); + return resources; + } } diff --git a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/admin/AdminAlbumService.java b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/admin/AdminAlbumService.java index 22b538814c..dff162ceef 100644 --- a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/admin/AdminAlbumService.java +++ b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/admin/AdminAlbumService.java @@ -17,10 +17,9 @@ */ package org.keycloak.example.photoz.admin; +import org.keycloak.example.photoz.CustomDatabase; import org.keycloak.example.photoz.entity.Album; -import javax.inject.Inject; -import javax.persistence.EntityManager; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; @@ -39,8 +38,7 @@ public class AdminAlbumService { public static final String SCOPE_ADMIN_ALBUM_MANAGE = "admin:manage"; - @Inject - private EntityManager entityManager; + private CustomDatabase entityManager = CustomDatabase.create(); @Context private HttpHeaders headers; @@ -49,7 +47,7 @@ public class AdminAlbumService { @Produces("application/json") public Response findAll() { HashMap> albums = new HashMap<>(); - List result = this.entityManager.createQuery("from Album").getResultList(); + List result = this.entityManager.getAll(); for (Album album : result) { //We need to compile this under JDK7 so we can't use lambdas diff --git a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/album/AlbumService.java b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/album/AlbumService.java index 40b12422ca..4e62e1e9d1 100644 --- a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/album/AlbumService.java +++ b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/album/AlbumService.java @@ -3,14 +3,12 @@ package org.keycloak.example.photoz.album; import org.keycloak.KeycloakSecurityContext; import org.keycloak.authorization.client.AuthzClient; import org.keycloak.authorization.client.ClientAuthorizationContext; +import org.keycloak.example.photoz.CustomDatabase; +import org.keycloak.example.photoz.entity.Album; import org.keycloak.representations.idm.authorization.ResourceRepresentation; import org.keycloak.representations.idm.authorization.ScopeRepresentation; import org.keycloak.authorization.client.resource.ProtectionResource; -import org.keycloak.example.photoz.entity.Album; -import org.keycloak.example.photoz.util.Transaction; -import javax.inject.Inject; -import javax.persistence.EntityManager; import javax.servlet.http.HttpServletRequest; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; @@ -29,7 +27,6 @@ import javax.ws.rs.core.HttpHeaders; import org.jboss.logging.Logger; @Path("/album") -@Transaction public class AlbumService { private final Logger log = Logger.getLogger(AlbumService.class); @@ -37,8 +34,7 @@ public class AlbumService { public static final String SCOPE_ALBUM_VIEW = "album:view"; public static final String SCOPE_ALBUM_DELETE = "album:delete"; - @Inject - private EntityManager entityManager; + private CustomDatabase customDatabase = CustomDatabase.create(); @Context private HttpServletRequest request; @@ -57,28 +53,28 @@ public class AlbumService { newAlbum.setUserId(userId); log.debug("PERSISTING " + newAlbum); - entityManager.persist(newAlbum); + customDatabase.addAlbum(newAlbum); try { createProtectedResource(newAlbum); } catch (RuntimeException e) { log.debug("ERROR " + e); - entityManager.remove(newAlbum); - throw e; + customDatabase.remove(newAlbum); + return Response.status(500).entity(e.getMessage()).build(); // } return Response.ok(newAlbum).build(); } - @Path("{id}") + @Path("{name}") @DELETE - public Response delete(@PathParam("id") String id, @Context HttpHeaders headers) { + public Response delete(@PathParam("name") String name, @Context HttpHeaders headers) { printAuthHeaders(headers); - Album album = this.entityManager.find(Album.class, Long.valueOf(id)); + Album album = this.customDatabase.findByName(name); try { deleteProtectedResource(album); - this.entityManager.remove(album); + this.customDatabase.remove(album); } catch (Exception e) { throw new RuntimeException("Could not delete album.", e); } @@ -90,23 +86,23 @@ public class AlbumService { @Produces("application/json") public Response findAll(@QueryParam("getAll") Boolean getAll) { if (getAll != null && getAll) { - return Response.ok(this.entityManager.createQuery("from Album").getResultList()).build(); + return Response.ok(this.customDatabase.getAll()).build(); } else { - return Response.ok(this.entityManager.createQuery("from Album where userId = '" + request.getUserPrincipal().getName() + "'").getResultList()).build(); + return Response.ok(this.customDatabase.findByUserId(request.getUserPrincipal().getName())).build(); } } @GET - @Path("{id}") + @Path("{name}") @Produces("application/json") - public Response findById(@PathParam("id") String id) { - List result = this.entityManager.createQuery("from Album where id = " + Long.valueOf(id)).getResultList(); + public Response findById(@PathParam("name") String name) { + Album result = this.customDatabase.findByName(name); - if (result.isEmpty()) { + if (result == null) { return Response.status(Status.NOT_FOUND).build(); } - return Response.ok(result.get(0)).build(); + return Response.ok(result).build(); } private void createProtectedResource(Album album) { @@ -117,7 +113,7 @@ public class AlbumService { scopes.add(new ScopeRepresentation(SCOPE_ALBUM_VIEW)); scopes.add(new ScopeRepresentation(SCOPE_ALBUM_DELETE)); - ResourceRepresentation albumResource = new ResourceRepresentation(album.getName(), scopes, "/album/" + album.getId(), "http://photoz.com/album"); + ResourceRepresentation albumResource = new ResourceRepresentation(album.getName(), scopes, "/album/" + album.getName(), "http://photoz.com/album"); albumResource.setOwner(album.getUserId()); @@ -132,7 +128,7 @@ public class AlbumService { } private void deleteProtectedResource(Album album) { - String uri = "/album/" + album.getId(); + String uri = "/album/" + album.getName(); try { ProtectionResource protection = getAuthzClient().protection(); diff --git a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/album/ProfileService.java b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/album/ProfileService.java index 6e3e3b0e12..4d66499815 100644 --- a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/album/ProfileService.java +++ b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/album/ProfileService.java @@ -17,8 +17,8 @@ */ package org.keycloak.example.photoz.album; -import javax.inject.Inject; -import javax.persistence.EntityManager; +import org.keycloak.example.photoz.CustomDatabase; + import javax.servlet.http.HttpServletRequest; import javax.ws.rs.GET; import javax.ws.rs.Path; @@ -36,14 +36,13 @@ public class ProfileService { private static final String PROFILE_VIEW = "profile:view"; - @Inject - private EntityManager entityManager; + private CustomDatabase customDatabase = CustomDatabase.create(); @GET @Produces("application/json") public Response view(@Context HttpServletRequest request) { Principal userPrincipal = request.getUserPrincipal(); - List albums = this.entityManager.createQuery("from Album where userId = '" + userPrincipal.getName() + "'").getResultList(); + List albums = this.customDatabase.findByUserId(userPrincipal.getName()); return Response.ok(new Profile(userPrincipal.getName(), albums.size())).build(); } diff --git a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/unsecured/UnsecuredService.java b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/unsecured/UnsecuredService.java index ff07d37e7a..8991ea9dab 100644 --- a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/unsecured/UnsecuredService.java +++ b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/unsecured/UnsecuredService.java @@ -17,13 +17,12 @@ package org.keycloak.example.photoz.unsecured; -import javax.inject.Inject; -import javax.persistence.EntityManager; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.Response; import javax.ws.rs.GET; import org.jboss.logging.Logger; +import org.keycloak.example.photoz.CustomDatabase; /** * Service used to ensure there is clean DB before test @@ -35,17 +34,15 @@ public class UnsecuredService { private final Logger log = Logger.getLogger(UnsecuredService.class); - @Inject - private EntityManager entityManager; + private CustomDatabase customDatabase = CustomDatabase.create(); @GET @Produces("application/json") public Response cleanAll() { - int deletedAlbums = entityManager.createQuery("delete from Album").executeUpdate(); - int deletedPhotos = entityManager.createQuery("delete from Photo").executeUpdate(); + int deleted = customDatabase.cleanAll(); - if (deletedAlbums != 0 || deletedPhotos != 0) { - log.warnf("Database was not empty. Deleted {0} Albums, {1} Photos", deletedAlbums, deletedPhotos); + if (deleted != 0) { + log.warnf("Database was not empty. Deleted Albums + Photos {0}", deleted); } else { log.debug("Database was clean before test"); } diff --git a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/util/Resources.java b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/util/Resources.java deleted file mode 100644 index c917da24db..0000000000 --- a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/util/Resources.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2016 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.keycloak.example.photoz.util; - -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; -import javax.enterprise.context.ApplicationScoped; -import javax.enterprise.context.RequestScoped; -import javax.enterprise.inject.Produces; -import javax.persistence.EntityManager; -import javax.persistence.EntityManagerFactory; -import javax.persistence.Persistence; - -/** - * @author Pedro Igor - */ -@ApplicationScoped -public class Resources { - - private EntityManagerFactory entityManagerFactory; - - @PostConstruct - public void init() { - entityManagerFactory = Persistence.createEntityManagerFactory("primary"); - } - - @PreDestroy - public void dispose() { - entityManagerFactory.close(); - } - - @RequestScoped - @Produces - public EntityManager createEntityManager() { - return entityManagerFactory.createEntityManager(); - } -} diff --git a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/util/Transaction.java b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/util/Transaction.java deleted file mode 100644 index 6f5d5ec229..0000000000 --- a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/util/Transaction.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2016 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.keycloak.example.photoz.util; - -import javax.interceptor.InterceptorBinding; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -/** - * @author Pedro Igor - */ -@InterceptorBinding -@Target({ TYPE }) -@Retention(RUNTIME) -public @interface Transaction { -} diff --git a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/util/TransactionInterceptor.java b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/util/TransactionInterceptor.java deleted file mode 100644 index be602486aa..0000000000 --- a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/util/TransactionInterceptor.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2016 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.keycloak.example.photoz.util; - -import javax.enterprise.inject.Instance; -import javax.inject.Inject; -import javax.interceptor.AroundInvoke; -import javax.interceptor.Interceptor; -import javax.interceptor.InvocationContext; -import javax.persistence.EntityManager; -import javax.persistence.EntityTransaction; - -/** - * @author Pedro Igor - */ -@Interceptor -@Transaction -public class TransactionInterceptor { - - @Inject - private Instance entityManager; - - @AroundInvoke - public Object aroundInvoke(InvocationContext context) throws Exception { - EntityManager entityManager = this.entityManager.get(); - EntityTransaction transaction = entityManager.getTransaction(); - - try { - transaction.begin(); - Object proceed = context.proceed(); - transaction.commit(); - return proceed; - } catch (Exception cause) { - if (transaction != null && transaction.isActive()) { - transaction.rollback(); - } - throw new RuntimeException(cause); - } finally { - entityManager.close(); - } - } -} diff --git a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/resources/META-INF/persistence.xml b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/resources/META-INF/persistence.xml deleted file mode 100644 index 702554f61c..0000000000 --- a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/resources/META-INF/persistence.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - org.hibernate.jpa.HibernatePersistenceProvider - - org.keycloak.example.photoz.entity.Album - org.keycloak.example.photoz.entity.Photo - - - - - - - - - - - - diff --git a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/webapp/WEB-INF/beans.xml b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/webapp/WEB-INF/beans.xml index fbf2a32edf..cf30c7dd3b 100644 --- a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/webapp/WEB-INF/beans.xml +++ b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/webapp/WEB-INF/beans.xml @@ -3,7 +3,4 @@ xsi:schemaLocation=" http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd"> - - org.keycloak.example.photoz.util.TransactionInterceptor - diff --git a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/webapp/WEB-INF/keycloak.json b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/webapp/WEB-INF/keycloak.json index dd0cab1abf..2b03024a58 100644 --- a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/webapp/WEB-INF/keycloak.json +++ b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/webapp/WEB-INF/keycloak.json @@ -31,7 +31,7 @@ }, { "name" : "Album Resource", - "path" : "/album/{id}", + "path" : "/album/{id}/", "methods" : [ { "method": "DELETE", diff --git a/testsuite/integration-arquillian/tests/base/pom.xml b/testsuite/integration-arquillian/tests/base/pom.xml index db9afcaf4f..768558ec80 100644 --- a/testsuite/integration-arquillian/tests/base/pom.xml +++ b/testsuite/integration-arquillian/tests/base/pom.xml @@ -85,6 +85,12 @@ hamcrest-all compile + + org.assertj + assertj-core + 3.11.1 + test + org.subethamail subethasmtp @@ -139,12 +145,8 @@ org.keycloak.testsuite photoz-restful-api - war ${project.version} - - - org.hibernate - hibernate-c3p0 + classes diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/PhotozClientAuthzTestApp.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/PhotozClientAuthzTestApp.java index 9db6c2576a..0a1a8ee72c 100644 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/PhotozClientAuthzTestApp.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/PhotozClientAuthzTestApp.java @@ -22,10 +22,13 @@ import org.jboss.arquillian.graphene.page.Page; import org.jboss.arquillian.test.api.ArquillianResource; import org.keycloak.testsuite.auth.page.login.OIDCLogin; import org.keycloak.testsuite.page.AbstractPageWithInjectedUrl; -import org.keycloak.testsuite.pages.ConsentPage; import org.keycloak.testsuite.util.JavascriptBrowser; import org.keycloak.testsuite.util.UIUtils; import org.keycloak.testsuite.util.URLUtils; +import org.keycloak.testsuite.util.javascript.JavascriptStateValidator; +import org.keycloak.testsuite.util.javascript.JavascriptTestExecutorWithAuthorization; +import org.keycloak.testsuite.util.javascript.ResponseValidator; +import org.keycloak.testsuite.util.javascript.XMLHttpRequest; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; @@ -33,8 +36,6 @@ import org.openqa.selenium.support.FindBy; import java.net.URL; -import static org.hamcrest.Matchers.containsString; -import static org.junit.Assert.assertThat; import static org.keycloak.testsuite.util.UIUtils.clickLink; import static org.keycloak.testsuite.util.WaitUtils.pause; import static org.keycloak.testsuite.util.WaitUtils.waitForPageToLoad; @@ -61,9 +62,6 @@ public class PhotozClientAuthzTestApp extends AbstractPageWithInjectedUrl { @JavascriptBrowser protected OIDCLogin loginPage; - @Page - @JavascriptBrowser - protected ConsentPage consentPage; @FindBy(xpath = "//a[@ng-click = 'Identity.logout()']") @JavascriptBrowser @@ -85,74 +83,59 @@ public class PhotozClientAuthzTestApp extends AbstractPageWithInjectedUrl { @JavascriptBrowser private WebElement output; + private JavascriptTestExecutorWithAuthorization testExecutor; + private String apiUrl; + + public void setTestExecutorPlayground(JavascriptTestExecutorWithAuthorization executor, String apiUrl) { + testExecutor = executor; + this.apiUrl = apiUrl; + } + public void createAlbum(String name) { createAlbum(name, false); } public void createAlbum(String name, boolean managed) { - if (managed) { - createAlbum(name, "save-managed-album"); - } else { - createAlbum(name, "save-album"); - } + createAlbum(name, managed, false, null); } - public void createAlbum(String name, String buttonId) { - log.debugf("Creating album {0} with buttonId: {1}", name, buttonId); - navigateTo(); - WebElement createAlbum = driver.findElement(By.id("create-album")); - waitUntilElement(createAlbum).is().clickable(); - createAlbum.click(); - WebElement albumNameInput = driver.findElement(By.id("album.name")); - waitUntilElement(albumNameInput).is().present(); - UIUtils.setTextInputValue(albumNameInput, name); - waitUntilElement(albumNameInput).attribute(UIUtils.VALUE_ATTR_NAME).contains(name); - WebElement button = driver.findElement(By.id(buttonId)); - waitUntilElement(button).is().clickable(); - button.click(); - pause(WAIT_AFTER_OPERATION); - if (buttonId.equals("save-album-invalid")) { - waitForPageToLoad(); - assertThat(driver.getPageSource(), containsString("Could not register protected resource.")); - } else { - waitUntilElement(albumNameInput).is().not().present(); - } + public void createAlbum(String name, boolean managed, boolean invalidUser, ResponseValidator validator) { + testExecutor.sendXMLHttpRequest( + XMLHttpRequest.create() + .method("POST") + .url(apiUrl + "/album" + (invalidUser ? "?user=invalidUser" : "")) + .content("JSON.stringify(JSON.parse('{\"name\" : \"" + name + "\", \"userManaged\": " + Boolean.toString(managed) + " }'))") + .addHeader("Content-Type", "application/json; charset=UTF-8") + , validator); } - public void createAlbumWithInvalidUser(String name) { - createAlbum(name, "save-album-invalid"); + + public void createAlbumWithInvalidUser(String name, ResponseValidator validator) { + createAlbum(name, false, true, validator); } + + @Override public URL getInjectedUrl() { return this.url; } - public void deleteAlbum(String name, boolean shouldBeDenied) { - log.debugf("Deleting album {0}", name); - WebElement delete = driver.findElement(By.id("delete-" + name)); - waitUntilElement(delete).is().clickable(); - delete.click(); - pause(WAIT_AFTER_OPERATION); - if (shouldBeDenied) { - waitForDenial(); - } else { - waitUntilElement(delete).is().not().present(); - } + public void deleteAlbum(String name, ResponseValidator validator) { + testExecutor.sendXMLHttpRequest( + XMLHttpRequest.create() + .method("DELETE") + .url(apiUrl + "/album/" + name + "/") // it doesn't work without ending "/" + , validator); } - public void navigateToAdminAlbum(boolean shouldBeDenied) { - log.debug("Navigating to Admin Album"); - URLUtils.navigateToUri(toString() + "/#/admin/album"); - - driver.navigate().refresh(); // This is sometimes necessary for loading the new policy settings - waitForPageToLoad(); - pause(WAIT_AFTER_OPERATION); - if (shouldBeDenied) { - waitForDenial(); - } else { - waitUntilElement(output).text().equalTo(""); - } + public void navigateToAdminAlbum(ResponseValidator validator) { + testExecutor.sendXMLHttpRequest( + XMLHttpRequest.create() + .method("GET") + .addHeader("Accept", "application/json") + .url(apiUrl + "/admin/album") + , validator); } public void logOut() { @@ -161,73 +144,24 @@ public class PhotozClientAuthzTestApp extends AbstractPageWithInjectedUrl { clickLink(signOutButton); } - public void requestEntitlement() { - waitUntilElement(entitlement).is().clickable(); - entitlement.click(); - waitForPageToLoad(); - pause(WAIT_AFTER_OPERATION); - pause(WAIT_AFTER_OPERATION); + public void requestEntitlement(JavascriptStateValidator validator) { + testExecutor.executeAsyncScript("var callback = arguments[arguments.length - 1];" + + "window.authorization.entitlement('photoz-restful-api', {" + + " \"permissions\": [" + + " {" + + " \"id\" : \"Album Resource\"" + + " }" + + " ]" + + "}).then(function (rpt) {" + + " callback(JSON.stringify(jwt_decode(rpt), null, ' '));" + + "});", validator); } - public void requestEntitlements() { - waitUntilElement(entitlements).is().clickable(); - entitlements.click(); - waitForPageToLoad(); - pause(WAIT_AFTER_OPERATION); - pause(WAIT_AFTER_OPERATION); - } - - public void login(String username, String password, String... scopes) throws InterruptedException { - String currentUrl = this.driver.getCurrentUrl(); - - if (scopes.length > 0) { - StringBuilder scopesValue = new StringBuilder(); - - for (String scope : scopes) { - if (scopesValue.length() != 0) { - scopesValue.append(" "); - } - scopesValue.append(scope); - } - - scopesValue.append(" openid"); - - - StringBuilder urlWithScopeParam = new StringBuilder(currentUrl); - - int scopeIndex = currentUrl.indexOf("scope"); - - if (scopeIndex != -1) { - // Remove scope param from url - urlWithScopeParam.delete(scopeIndex, currentUrl.indexOf('&', scopeIndex)); - // Add scope param to the end of query - urlWithScopeParam.append("&").append("scope="); - } - - if (!currentUrl.contains("?")) { - urlWithScopeParam.append("?scope="); - } - - urlWithScopeParam.append(scopesValue); - - URLUtils.navigateToUri(urlWithScopeParam.toString()); - } - - this.loginPage.form().login(username, password); - waitForPageToLoad();//guess - - try { - if (!isCurrent()) { - // simple check if we are at the consent page, if so just click 'Yes' - if (this.consentPage.isCurrent(driver)) { - consentPage.confirm(); - } - } - } catch (Exception ignore) { - // ignore errors when checking consent page, if an error tests will also fail - } - - pause(WAIT_AFTER_OPERATION); + public void requestEntitlements(JavascriptStateValidator validator) { + testExecutor.executeAsyncScript("var callback = arguments[arguments.length - 1];" + + "window.authorization.entitlement('photoz-restful-api').then(function (rpt) {" + + " callback(JSON.stringify(jwt_decode(rpt), null, ' '));" + + "});", validator); } private void waitForDenial() { @@ -243,28 +177,18 @@ public class PhotozClientAuthzTestApp extends AbstractPageWithInjectedUrl { pause(WAIT_AFTER_OPERATION); } - public void viewAlbum(String name, boolean shouldBeDenied) { - WebElement viewalbum = driver.findElement(By.xpath("//a[text() = '" + name + "']")); - waitUntilElement(viewalbum).is().clickable(); - viewalbum.click(); - waitForPageToLoad(); - driver.navigate().refresh(); // This is sometimes necessary for loading the new policy settings - if (shouldBeDenied) { - waitForDenial(); - } else { - waitForNotDenial(); - } - waitForPageToLoad(); - pause(WAIT_AFTER_OPERATION); + public void viewAlbum(String name, ResponseValidator validator) { + testExecutor.sendXMLHttpRequest( + XMLHttpRequest.create() + .method("GET") + .addHeader("Accept", "application/json") + .url(apiUrl + "/album/" + name + "/") + , validator); } public void accountPage() { - navigateTo(); - WebElement myAccount = driver.findElement(By.id("my-account")); - waitUntilElement(myAccount).is().clickable(); - myAccount.click(); + testExecutor.openAccountPage(null); waitForPageToLoad(); - pause(WAIT_AFTER_OPERATION); } public void accountMyResources() { @@ -273,7 +197,6 @@ public class PhotozClientAuthzTestApp extends AbstractPageWithInjectedUrl { waitUntilElement(myResources).is().clickable(); myResources.click(); waitForPageToLoad(); - pause(WAIT_AFTER_OPERATION); } public void accountMyResource(String name) { @@ -282,7 +205,6 @@ public class PhotozClientAuthzTestApp extends AbstractPageWithInjectedUrl { waitUntilElement(myResource).is().clickable(); myResource.click(); waitForPageToLoad(); - pause(WAIT_AFTER_OPERATION); } public void accountGrantResource(String name, String requester) { @@ -291,7 +213,6 @@ public class PhotozClientAuthzTestApp extends AbstractPageWithInjectedUrl { waitUntilElement(grantResource).is().clickable(); grantResource.click(); waitForPageToLoad(); - pause(WAIT_AFTER_OPERATION); } public void accountGrantRemoveScope(String name, String requester, String scope) { @@ -300,7 +221,6 @@ public class PhotozClientAuthzTestApp extends AbstractPageWithInjectedUrl { waitUntilElement(grantRemoveScope).is().clickable(); grantRemoveScope.click(); waitForPageToLoad(); - pause(WAIT_AFTER_OPERATION); } public void accountRevokeResource(String name, String requester) { @@ -309,7 +229,6 @@ public class PhotozClientAuthzTestApp extends AbstractPageWithInjectedUrl { waitUntilElement(revokeResource).is().clickable(); revokeResource.click(); waitForPageToLoad(); - pause(WAIT_AFTER_OPERATION); } public void accountShareResource(String name, String user) { @@ -323,7 +242,6 @@ public class PhotozClientAuthzTestApp extends AbstractPageWithInjectedUrl { waitUntilElement(shareButton).is().clickable(); shareButton.click(); waitForPageToLoad(); - pause(WAIT_AFTER_OPERATION); } public void accountShareRemoveScope(String name, String user, String scope) { @@ -344,7 +262,6 @@ public class PhotozClientAuthzTestApp extends AbstractPageWithInjectedUrl { shareButton.click(); waitForPageToLoad(); - pause(WAIT_AFTER_OPERATION); } public void accountDenyResource(String name) { @@ -353,25 +270,22 @@ public class PhotozClientAuthzTestApp extends AbstractPageWithInjectedUrl { waitUntilElement(denyLink).is().clickable(); denyLink.click(); waitForPageToLoad(); - pause(WAIT_AFTER_OPERATION); } - public void requestResourceProtectedAnyScope(boolean shouldBeDenied) { - navigateTo(); - WebElement requestPathWithAnyProtectedScope = driver.findElement(By.id("requestPathWithAnyProtectedScope")); - waitUntilElement(requestPathWithAnyProtectedScope).is().clickable(); - requestPathWithAnyProtectedScope.click(); - if (shouldBeDenied) waitForDenial(); - pause(WAIT_AFTER_OPERATION); + public void requestResourceProtectedAnyScope(ResponseValidator validator) { + testExecutor.sendXMLHttpRequest( + XMLHttpRequest.create() + .method("GET") + .url(apiUrl + "/scope-any") + , validator); } - public void requestResourceProtectedAllScope(boolean shouldBeDenied) { - navigateTo(); - WebElement requestPathWithAllProtectedScope = driver.findElement(By.id("requestPathWithAllProtectedScope")); - waitUntilElement(requestPathWithAllProtectedScope).is().clickable(); - requestPathWithAllProtectedScope.click(); - if (shouldBeDenied) waitForDenial(); - pause(WAIT_AFTER_OPERATION); + public void requestResourceProtectedAllScope(ResponseValidator validator) { + testExecutor.sendXMLHttpRequest( + XMLHttpRequest.create() + .method("GET") + .url(apiUrl + "/scope-all") + , validator); } public WebElement getOutput() { @@ -380,8 +294,8 @@ public class PhotozClientAuthzTestApp extends AbstractPageWithInjectedUrl { @Override public void navigateTo() { - super.navigateTo(); - pause(WAIT_AFTER_OPERATION); + driver.navigate().to(toString() + "/"); + waitForPageToLoad(); } @Override diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/javascript/JSObjectBuilder.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/javascript/JSObjectBuilder.java similarity index 97% rename from testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/javascript/JSObjectBuilder.java rename to testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/javascript/JSObjectBuilder.java index f0d549b7d5..99a76b13e8 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/javascript/JSObjectBuilder.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/javascript/JSObjectBuilder.java @@ -1,4 +1,4 @@ -package org.keycloak.testsuite.adapter.javascript; +package org.keycloak.testsuite.util.javascript; import java.util.HashMap; import java.util.Map; diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/javascript/JavascriptStateValidator.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/javascript/JavascriptStateValidator.java similarity index 86% rename from testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/javascript/JavascriptStateValidator.java rename to testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/javascript/JavascriptStateValidator.java index 3c9f1ea350..9a5839abae 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/javascript/JavascriptStateValidator.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/javascript/JavascriptStateValidator.java @@ -1,4 +1,4 @@ -package org.keycloak.testsuite.adapter.javascript; +package org.keycloak.testsuite.util.javascript; import org.keycloak.models.KeycloakSession; import org.openqa.selenium.WebDriver; diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/javascript/JavascriptTestExecutor.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/javascript/JavascriptTestExecutor.java similarity index 89% rename from testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/javascript/JavascriptTestExecutor.java rename to testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/javascript/JavascriptTestExecutor.java index 9e6d953542..2194c3b47d 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/javascript/JavascriptTestExecutor.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/javascript/JavascriptTestExecutor.java @@ -1,4 +1,4 @@ -package org.keycloak.testsuite.adapter.javascript; +package org.keycloak.testsuite.util.javascript; import org.keycloak.representations.idm.UserRepresentation; import org.keycloak.testsuite.auth.page.login.OIDCLogin; @@ -9,23 +9,25 @@ import org.openqa.selenium.WebElement; import java.util.concurrent.TimeUnit; +import static org.keycloak.testsuite.util.WaitUtils.waitForPageToLoad; + /** * @author mhajas */ public class JavascriptTestExecutor { - private WebDriver jsDriver; - private JavascriptExecutor jsExecutor; + protected WebDriver jsDriver; + protected JavascriptExecutor jsExecutor; private WebElement output; - private WebElement events; + protected WebElement events; private OIDCLogin loginPage; - private boolean configured; + protected boolean configured; public static JavascriptTestExecutor create(WebDriver driver, OIDCLogin loginPage) { return new JavascriptTestExecutor(driver, loginPage); } - private JavascriptTestExecutor(WebDriver driver, OIDCLogin loginPage) { + protected JavascriptTestExecutor(WebDriver driver, OIDCLogin loginPage) { this.jsDriver = driver; driver.manage().timeouts().setScriptTimeout(10, TimeUnit.SECONDS); jsExecutor = (JavascriptExecutor) driver; @@ -49,6 +51,7 @@ public class JavascriptTestExecutor { else { jsExecutor.executeScript("keycloak.login(" + options + ")"); } + waitForPageToLoad(); if (validator != null) { validator.validate(jsDriver, output, events); @@ -65,6 +68,7 @@ public class JavascriptTestExecutor { public JavascriptTestExecutor loginForm(UserRepresentation user, JavascriptStateValidator validator) { loginPage.form().login(user); + waitForPageToLoad(); if (validator != null) { validator.validate(jsDriver, null, events); @@ -174,6 +178,20 @@ public class JavascriptTestExecutor { return this; } + public JavascriptTestExecutor openAccountPage(JavascriptStateValidator validator) { + jsExecutor.executeScript("window.keycloak.accountManagement()"); + waitForPageToLoad(); + + // Leaving page -> loosing keycloak variable + configured = false; + + if (validator != null) { + validator.validate(jsDriver, null, null); + } + + return this; + } + public JavascriptTestExecutor getProfile() { return getProfile(null); } @@ -235,6 +253,12 @@ public class JavascriptTestExecutor { return this; } + public boolean isLoggedIn() { + return (boolean) jsExecutor.executeScript("if (typeof keycloak !== 'undefined') {" + + "return keycloak.authenticated" + + "} else { return false}"); + } + public JavascriptTestExecutor executeAsyncScript(String script) { return executeAsyncScript(script, null); } diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/javascript/JavascriptTestExecutorWithAuthorization.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/javascript/JavascriptTestExecutorWithAuthorization.java new file mode 100644 index 0000000000..8ccc55465a --- /dev/null +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/javascript/JavascriptTestExecutorWithAuthorization.java @@ -0,0 +1,167 @@ +package org.keycloak.testsuite.util.javascript; + +import org.keycloak.representations.idm.UserRepresentation; +import org.keycloak.testsuite.auth.page.login.OAuthGrant; +import org.keycloak.testsuite.auth.page.login.OIDCLogin; +import org.keycloak.testsuite.pages.ConsentPage; +import org.keycloak.testsuite.util.URLUtils; +import org.openqa.selenium.WebDriver; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.keycloak.testsuite.util.WaitUtils.waitForPageToLoad; + +/** + * @author mhajas + */ +public class JavascriptTestExecutorWithAuthorization extends JavascriptTestExecutor { + + public static JavascriptTestExecutorWithAuthorization create(WebDriver driver, OIDCLogin loginPage) { + return new JavascriptTestExecutorWithAuthorization(driver, loginPage); + } + + private JavascriptTestExecutorWithAuthorization(WebDriver driver, OIDCLogin loginPage) { + super(driver, loginPage); + } + + + @Override + public JavascriptTestExecutorWithAuthorization init(JSObjectBuilder argumentsBuilder, JavascriptStateValidator validator) { + super.init(argumentsBuilder, validator); + Object output = jsExecutor.executeScript( + "var callback = arguments[arguments.length - 1];" + + "window.authorization = new KeycloakAuthorization(window.keycloak);" + + "while (typeof window.authorization === 'undefined') {}" + // Wait until authorization is initialized + "return 'Authz initialized'"); + + assertThat(output, is("Authz initialized")); + return this; + } + + @Override + public JavascriptTestExecutorWithAuthorization login(JavascriptStateValidator validator) { + super.login(validator); + return this; + } + + public JavascriptTestExecutorWithAuthorization loginFormWithScopesWithPossibleConsentPage(UserRepresentation user, JavascriptStateValidator validator, OAuthGrant oAuthGrantPage, String... scopes) { + String currentUrl = jsDriver.getCurrentUrl(); + + if (scopes.length > 0) { + StringBuilder scopesValue = new StringBuilder(); + + for (String scope : scopes) { + if (scopesValue.length() != 0) { + scopesValue.append(" "); + } + scopesValue.append(scope); + } + + scopesValue.append(" openid"); + + + StringBuilder urlWithScopeParam = new StringBuilder(currentUrl); + + int scopeIndex = currentUrl.indexOf("scope"); + + if (scopeIndex != -1) { + // Remove scope param from url + urlWithScopeParam.delete(scopeIndex, currentUrl.indexOf('&', scopeIndex)); + // Add scope param to the end of query + urlWithScopeParam.append("&").append("scope="); + } + + if (!currentUrl.contains("?")) { + urlWithScopeParam.append("?scope="); + } + + urlWithScopeParam.append(scopesValue); + + URLUtils.navigateToUri(urlWithScopeParam.toString()); + waitForPageToLoad(); + } + + loginFormWithPossibleConsentPage(user, oAuthGrantPage, validator); + return this; + } + + public JavascriptTestExecutorWithAuthorization loginFormWithPossibleConsentPage(UserRepresentation user, OAuthGrant oAuthGrantPage, JavascriptStateValidator validator) { + super.loginForm(user); + + try { + // simple check if we are at the consent page, if so just click 'Yes' + if (oAuthGrantPage.isCurrent(jsDriver)) { + oAuthGrantPage.accept(); + waitForPageToLoad(); + } + } catch (Exception ignore) { + // ignore errors when checking consent page, if an error tests will also fail + } + + if (validator != null) { + validator.validate(jsDriver, null, events); + } + + return this; + } + + @Override + public JavascriptTestExecutor sendXMLHttpRequest(XMLHttpRequest request, ResponseValidator validator) { + // Intercept all requests and add rpt or token + + // check if rpt is already present + Object o = jsExecutor.executeScript("if(window.authorization && window.authorization.rpt) return true; else return false;"); + + + + if (o == null || o.equals(false)) { + // RPT is not present yet, lets try to use bearer token + request.includeBearerToken(); + } else { + // RPT token is present so we will use it + request.includeRpt(); + } + + // Try to send request + Map result = request.send(jsExecutor); + + // If request was denied do UMA + if ((Long.valueOf(403).equals(result.get("status")) || Long.valueOf(401).equals(result.get("status")))) { + //extracting ticket from response + String headersString = (String) result.get("responseHeaders"); + + List headersList = Arrays.asList(headersString.split("\r\n")); + String wwwAuthenticate = headersList.stream().filter(s -> s.toLowerCase().startsWith("www-authenticate:")).findFirst().get(); + + if (wwwAuthenticate.contains("UMA") && wwwAuthenticate.contains("ticket")) { + String ticket = Arrays.asList(wwwAuthenticate.split(",")).stream().filter(s -> s.startsWith("ticket")).findFirst().get(); + + ticket = ticket.substring(0, ticket.length() - 1).replaceFirst("ticket=\"", ""); + + // AuthorizationRequest for RPT + o = jsExecutor.executeAsyncScript( + "var callback = arguments[arguments.length - 1];" + + "window.authorization" + + ".authorize(" + JSObjectBuilder.create().add("ticket", ticket).build() + ")" + + ".then(function (rpt) {callback(rpt)}, function() {callback('failed1')}, function() {callback('failed2')});"); + + o = jsExecutor.executeScript("if(window.authorization && window.authorization.rpt) return true; else return false;"); // return window.authorization && window.authorization.rpt doesn't work + + if (o != null && o.equals(true)) { + request.includeRpt(); + result = request.send(jsExecutor); + } + } + } + + if (validator != null) { + validator.validate(result); + } + + return this; + } +} diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/javascript/ResponseValidator.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/javascript/ResponseValidator.java similarity index 83% rename from testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/javascript/ResponseValidator.java rename to testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/javascript/ResponseValidator.java index 8587d25e56..d66598ffc9 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/javascript/ResponseValidator.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/javascript/ResponseValidator.java @@ -1,4 +1,4 @@ -package org.keycloak.testsuite.adapter.javascript; +package org.keycloak.testsuite.util.javascript; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/javascript/XMLHttpRequest.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/javascript/XMLHttpRequest.java similarity index 81% rename from testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/javascript/XMLHttpRequest.java rename to testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/javascript/XMLHttpRequest.java index 1a166119d1..e19779d5a7 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/javascript/XMLHttpRequest.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/javascript/XMLHttpRequest.java @@ -1,4 +1,4 @@ -package org.keycloak.testsuite.adapter.javascript; +package org.keycloak.testsuite.util.javascript; import org.openqa.selenium.JavascriptExecutor; @@ -26,6 +26,10 @@ public class XMLHttpRequest { return this; } + public String getUrl() { + return url; + } + public XMLHttpRequest method(String method) { this.method = method; return this; @@ -46,6 +50,16 @@ public class XMLHttpRequest { return this; } + public XMLHttpRequest includeBearerToken() { + addHeader("Authorization", "Bearer ' + keycloak.token + '"); + return this; + } + + public XMLHttpRequest includeRpt() { + addHeader("Authorization", "Bearer ' + authorization.rpt + '"); + return this; + } + public Map send(JavascriptExecutor jsExecutor) { String requestCode = "var callback = arguments[arguments.length - 1];" + "var req = new XMLHttpRequest();" + @@ -53,7 +67,7 @@ public class XMLHttpRequest { getHeadersString() + " req.onreadystatechange = function () {" + " if (req.readyState == 4) {" + - " callback({\"status\" : req.status, \"reponseText\" : req.reponseText, \"responseHeaders\" : req.getAllResponseHeaders().toLowerCase(), \"res\" : req.response})" + + " callback({\"status\" : req.status, \"responseHeaders\" : req.getAllResponseHeaders(), \"res\" : req.response, \"req\" : req})" + " }" + " };" + " req.send(" + content + ");"; diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/authorization/AbstractPhotozExampleAdapterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/authorization/AbstractPhotozExampleAdapterTest.java index 344d68ef1c..a1edd7f1af 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/authorization/AbstractPhotozExampleAdapterTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/authorization/AbstractPhotozExampleAdapterTest.java @@ -20,25 +20,19 @@ import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.client.LaxRedirectStrategy; +import org.hamcrest.CoreMatchers; import org.jboss.arquillian.container.test.api.Deployer; -import org.jboss.arquillian.drone.api.annotation.Drone; import org.jboss.arquillian.graphene.page.Page; import org.jboss.arquillian.test.api.ArquillianResource; -import org.jboss.shrinkwrap.api.asset.StringAsset; -import org.jboss.shrinkwrap.api.spec.WebArchive; import org.junit.After; import org.junit.Assert; import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Ignore; import org.junit.Test; import org.keycloak.admin.client.resource.AuthorizationResource; import org.keycloak.admin.client.resource.ClientResource; import org.keycloak.admin.client.resource.ClientScopesResource; import org.keycloak.admin.client.resource.ClientsResource; -import org.keycloak.admin.client.resource.ProtocolMappersResource; import org.keycloak.admin.client.resource.RealmResource; -import org.keycloak.admin.client.resource.RealmsResource; import org.keycloak.admin.client.resource.ResourcesResource; import org.keycloak.admin.client.resource.RoleResource; import org.keycloak.admin.client.resource.UserResource; @@ -54,84 +48,89 @@ import org.keycloak.representations.idm.UserRepresentation; import org.keycloak.representations.idm.authorization.PolicyRepresentation; import org.keycloak.representations.idm.authorization.ResourceRepresentation; import org.keycloak.representations.idm.authorization.ResourceServerRepresentation; -import org.keycloak.testsuite.ProfileAssume; -import org.keycloak.testsuite.adapter.AbstractExampleAdapterTest; import org.keycloak.testsuite.adapter.page.PhotozClientAuthzTestApp; import org.keycloak.testsuite.admin.ApiUtil; -import org.keycloak.testsuite.auth.page.login.OIDCLogin; +import org.keycloak.testsuite.arquillian.AppServerTestEnricher; +import org.keycloak.testsuite.auth.page.login.OAuthGrant; import org.keycloak.testsuite.util.ContainerAssume; import org.keycloak.testsuite.util.DroneUtils; import org.keycloak.testsuite.util.JavascriptBrowser; -import org.keycloak.testsuite.utils.io.IOUtil; +import org.keycloak.testsuite.util.javascript.JavascriptTestExecutorWithAuthorization; import org.keycloak.util.JsonSerialization; -import org.openqa.selenium.By; -import org.openqa.selenium.NoSuchElementException; import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.support.FindBy; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; -import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; -import static org.hamcrest.Matchers.empty; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.not; +import static org.assertj.core.api.Assertions.assertThat; import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; -import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlStartsWithLoginUrlOf; +import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlStartsWith; import static org.keycloak.testsuite.utils.io.IOUtil.loadJson; import static org.keycloak.testsuite.utils.io.IOUtil.loadRealm; import static org.keycloak.testsuite.util.WaitUtils.waitForPageToLoad; -import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement; import javax.ws.rs.core.Response; -import org.keycloak.testsuite.arquillian.AppServerTestEnricher; /** * @author Pedro Igor */ -public abstract class AbstractPhotozExampleAdapterTest extends AbstractExampleAdapterTest { +public abstract class AbstractPhotozExampleAdapterTest extends AbstractPhotozJavascriptExecutorTest { - private static final String REALM_NAME = "photoz"; protected static final String RESOURCE_SERVER_ID = "photoz-restful-api"; + protected static final String ALICE_ALBUM_NAME = "Alice-Family-Album"; private static final int TOKEN_LIFESPAN_LEEWAY = 3; // seconds @ArquillianResource private Deployer deployer; - // Javascript browser needed KEYCLOAK-4703 - @Drone - @JavascriptBrowser - protected WebDriver jsDriver; - - @Page - @JavascriptBrowser - protected OIDCLogin jsDriverTestRealmLoginPage; - @Page @JavascriptBrowser private PhotozClientAuthzTestApp clientPage; + @Page + @JavascriptBrowser + private OAuthGrant oAuthGrantPage; + + private JavascriptTestExecutorWithAuthorization testExecutor; + + @FindBy(id = "output") + @JavascriptBrowser + protected WebElement outputArea; + + @FindBy(id = "events") + @JavascriptBrowser + protected WebElement eventsArea; + @Override public void setDefaultPageUriParameters() { super.setDefaultPageUriParameters(); testRealmPage.setAuthRealm(REALM_NAME); + oAuthGrantPage.setAuthRealm(REALM_NAME); } @Before public void beforePhotozExampleAdapterTest() throws Exception { DroneUtils.addWebDriver(jsDriver); - deleteAllCookiesForClientPage(); this.deployer.deploy(RESOURCE_SERVER_ID); - + + clientPage.navigateTo(); + waitForPageToLoad(); + assertCurrentUrlStartsWith(clientPage.toString()); + + testExecutor = JavascriptTestExecutorWithAuthorization.create(jsDriver, jsDriverTestRealmLoginPage); + clientPage.setTestExecutorPlayground(testExecutor, appServerContextRootPage + "/" + RESOURCE_SERVER_ID); + jsDriver.manage().deleteAllCookies(); + try (CloseableHttpClient httpClient = HttpClientBuilder.create().setRedirectStrategy(new LaxRedirectStrategy()).build()) { HttpGet request = new HttpGet(clientPage.toString() + "/unsecured/clean"); httpClient.execute(request).close(); @@ -159,18 +158,6 @@ public abstract class AbstractPhotozExampleAdapterTest extends AbstractExampleAd importResourceServerSettings(); } - //revert provider in persistence.xml for EAP6 backward compatibility - protected static void updatePersistenceXml(WebArchive war) { - //double check app server is eap6 - if (AppServerTestEnricher.isEAP6AppServer()) { - String persistanceXmlPath = "/WEB-INF/classes/META-INF/persistence.xml"; - org.w3c.dom.Document persistenceXml = IOUtil.loadXML(war.get(persistanceXmlPath).getAsset().openStream()); - IOUtil.modifyDocElementValue(persistenceXml, "provider", - "org.hibernate.jpa.HibernatePersistenceProvider", "org.hibernate.ejb.HibernatePersistence"); - war.add(new StringAsset((IOUtil.documentToString(persistenceXml))), persistanceXmlPath); - } - } - private List getResourcesOfUser(String username) throws FileNotFoundException { return getAuthorizationResource().resources().resources().stream().filter(resource -> resource.getOwner().getName().equals(username)).collect(Collectors.toList()); } @@ -178,50 +165,62 @@ public abstract class AbstractPhotozExampleAdapterTest extends AbstractExampleAd private void printUpdatedPolicies() throws FileNotFoundException { log.debug("Check updated policies"); for (PolicyRepresentation policy : getAuthorizationResource().policies().policies()) { - log.debugf("Policy: {0}", policy.getName()); + log.debugf("Policy: %s", policy.getName()); for (String key : policy.getConfig().keySet()) { - log.debugf("-- key: {0}, value: {1}", key, policy.getConfig().get(key)); + log.debugf("-- key: %s, value: %s", key, policy.getConfig().get(key)); } } log.debug("------------------------------"); } + + private void assertOnTestAppUrl(WebDriver jsDriver, Object output, WebElement events) { + waitForPageToLoad(); + assertCurrentUrlStartsWith(clientPage.toString(), jsDriver); + } + + private void assertWasDenied(Map response) { + assertThat(response.get("status")).isEqualTo(401L); + } + + private void assertWasNotDenied(Map response) { + assertThat(response.get("status")).isEqualTo(200L); + } @Test public void testUserCanCreateAndDeleteAlbum() throws Exception { - loginToClientPage("alice", "alice"); + loginToClientPage(aliceUser); - clientPage.createAlbum("Alice Family Album"); + clientPage.createAlbum(ALICE_ALBUM_NAME); log.debug("Check if alice has resources stored"); - assertThat(getResourcesOfUser("alice"), is(not(empty()))); + assertThat(getResourcesOfUser("alice")).isNotEmpty(); - clientPage.deleteAlbum("Alice Family Album", false); + clientPage.deleteAlbum(ALICE_ALBUM_NAME, this::assertWasNotDenied); log.debug("Check if alice has resources deleted"); - assertThat(getResourcesOfUser("alice"), is(empty())); + assertThat(getResourcesOfUser("alice")).isEmpty(); } @Test public void createAlbumWithInvalidUser() throws Exception { - loginToClientPage("alice", "alice"); + loginToClientPage(aliceUser); - clientPage.createAlbumWithInvalidUser("Alice Family Album"); - - log.debug("Check if the album was not created."); - waitUntilElement(clientPage.getOutput()).text().not().contains("Request was successful"); - waitUntilElement(clientPage.getOutput()).text().contains("Could not register protected resource"); + clientPage.createAlbumWithInvalidUser(ALICE_ALBUM_NAME, response -> { + assertThat(response.get("status")).isEqualTo(500L); + assertThat(response.get("res")).isEqualTo("Could not register protected resource."); + }); } @Test public void testOnlyOwnerCanDeleteAlbum() throws Exception { - ContainerAssume.assumeNotAuthServerUndertow(); + ContainerAssume.assumeNotAppServerUndertow(); - loginToClientPage("alice", "alice"); - clientPage.createAlbum("Alice-Family-Album"); + loginToClientPage(aliceUser); + clientPage.createAlbum(ALICE_ALBUM_NAME); - loginToClientPage("admin", "admin"); - clientPage.navigateToAdminAlbum(false); + loginToClientPage(adminUser); + clientPage.navigateToAdminAlbum(this::assertWasNotDenied); log.debug("Check if alice has resources stored"); - assertThat(getResourcesOfUser("alice"), is(not(empty()))); + assertThat(getResourcesOfUser("alice")).isNotEmpty(); log.debug("Adding applyPolicies \"Only Owner Policy\" to \"Delete Album Permission\" policies."); for (PolicyRepresentation policy : getAuthorizationResource().policies().policies()) { @@ -232,13 +231,13 @@ public abstract class AbstractPhotozExampleAdapterTest extends AbstractExampleAd } printUpdatedPolicies(); - loginToClientPage("admin", "admin"); + loginToClientPage(adminUser); - clientPage.navigateToAdminAlbum(false); - clientPage.deleteAlbum("Alice-Family-Album", true); + clientPage.navigateToAdminAlbum(this::assertWasNotDenied); + clientPage.deleteAlbum(ALICE_ALBUM_NAME, this::assertWasDenied); log.debug("Check if alice has resources stored"); - assertThat(getResourcesOfUser("alice"), is(not(empty()))); + assertThat(getResourcesOfUser("alice")).isNotEmpty(); log.debug("Adding applyPolicies \"Only Owner and Administrators Policy\" to \"Delete Album Permission\" policies."); for (PolicyRepresentation policy : getAuthorizationResource().policies().policies()) { @@ -249,51 +248,52 @@ public abstract class AbstractPhotozExampleAdapterTest extends AbstractExampleAd } printUpdatedPolicies(); - clientPage.navigateToAdminAlbum(false); - clientPage.deleteAlbum("Alice-Family-Album", false); + clientPage.navigateToAdminAlbum(this::assertWasNotDenied); + clientPage.deleteAlbum(ALICE_ALBUM_NAME, this::assertWasNotDenied); log.debug("Check if alice has resources deleted"); - assertThat(getResourcesOfUser("alice"), is(empty())); + assertThat(getResourcesOfUser("alice")).isEmpty(); } @Test public void testRegularUserCanNotAccessAdminResources() throws Exception { - loginToClientPage("alice", "alice"); - clientPage.navigateToAdminAlbum(true); + loginToClientPage(aliceUser); + clientPage.navigateToAdminAlbum(this::assertWasDenied); } @Test public void testAdminOnlyFromSpecificAddress() throws Exception { - ContainerAssume.assumeNotAuthServerUndertow(); - - loginToClientPage("admin", "admin"); - clientPage.navigateToAdminAlbum(false); + loginToClientPage(adminUser); + clientPage.navigateToAdminAlbum(this::assertWasNotDenied); log.debug("Changing codes \"127.0.0.1\" to \"127.3.3.3\" of \"Only From a Specific Client Address\" policies."); for (PolicyRepresentation policy : getAuthorizationResource().policies().policies()) { if ("Only From a Specific Client Address".equals(policy.getName())) { - String code = policy.getConfig().get("code"); - policy.getConfig().put("code", code.replaceAll("127.0.0.1", "127.3.3.3")); + String code = policy.getConfig().get("code") + .replaceAll("127.0.0.1", "127.3.3.3") + .replaceAll("0:0:0:0:0:0:0:1", "0:0:0:0:0:ffff:7f03:303"); + policy.getConfig().put("code", code); getAuthorizationResource().policies().policy(policy.getId()).update(policy); } } printUpdatedPolicies(); - clientPage.navigateToAdminAlbum(true); + loginToClientPage(adminUser); + clientPage.navigateToAdminAlbum(this::assertWasDenied); } @Test public void testAdminWithoutPermissionsToTypedResource() throws Exception { - ContainerAssume.assumeNotAuthServerUndertow(); + ContainerAssume.assumeNotAppServerUndertow(); - loginToClientPage("alice", "alice"); - clientPage.createAlbum("Alice Family Album"); + loginToClientPage(aliceUser); + clientPage.createAlbum(ALICE_ALBUM_NAME); - loginToClientPage("admin", "admin"); - clientPage.navigateToAdminAlbum(false); + loginToClientPage(adminUser); + clientPage.navigateToAdminAlbum(this::assertWasNotDenied); - clientPage.viewAlbum("Alice Family Album", false); + clientPage.viewAlbum(ALICE_ALBUM_NAME, this::assertWasNotDenied); for (PolicyRepresentation policy : getAuthorizationResource().policies().policies()) { if ("Album Resource Permission".equals(policy.getName())) { @@ -315,11 +315,13 @@ public abstract class AbstractPhotozExampleAdapterTest extends AbstractExampleAd } printUpdatedPolicies(); - clientPage.navigateToAdminAlbum(false); + loginToClientPage(adminUser); // Clear cache - clientPage.viewAlbum("Alice Family Album", true); - clientPage.navigateToAdminAlbum(false); - clientPage.deleteAlbum("Alice Family Album", true); + clientPage.navigateToAdminAlbum(this::assertWasNotDenied); + + clientPage.viewAlbum(ALICE_ALBUM_NAME, this::assertWasDenied); + clientPage.navigateToAdminAlbum(this::assertWasNotDenied); + clientPage.deleteAlbum(ALICE_ALBUM_NAME, this::assertWasDenied); for (PolicyRepresentation policy : getAuthorizationResource().policies().policies()) { if ("Album Resource Permission".equals(policy.getName())) { @@ -329,26 +331,27 @@ public abstract class AbstractPhotozExampleAdapterTest extends AbstractExampleAd } printUpdatedPolicies(); - clientPage.navigateToAdminAlbum(false); - clientPage.viewAlbum("Alice Family Album", false); + loginToClientPage(adminUser); // Clear cache - clientPage.navigateToAdminAlbum(false); - clientPage.deleteAlbum("Alice Family Album", false); - assertThat(getResourcesOfUser("alice"), is(empty())); + clientPage.navigateToAdminAlbum(this::assertWasNotDenied); + clientPage.viewAlbum(ALICE_ALBUM_NAME, this::assertWasNotDenied); + + clientPage.navigateToAdminAlbum(this::assertWasNotDenied); + clientPage.deleteAlbum(ALICE_ALBUM_NAME, this::assertWasNotDenied); + assertThat(getResourcesOfUser("alice")).isEmpty(); } @Test public void testAdminWithoutPermissionsToDeleteAlbum() throws Exception { - ContainerAssume.assumeNotAuthServerUndertow(); + loginToClientPage(aliceUser); + clientPage.createAlbum(ALICE_ALBUM_NAME); - loginToClientPage("alice", "alice"); - clientPage.createAlbum("Alice Family Album"); + loginToClientPage(adminUser); + clientPage.navigateToAdminAlbum(this::assertWasNotDenied); + clientPage.viewAlbum(ALICE_ALBUM_NAME, this::assertWasNotDenied); - loginToClientPage("admin", "admin"); - clientPage.navigateToAdminAlbum(false); - - clientPage.deleteAlbum("Alice Family Album", false); - assertThat(getResourcesOfUser("alice"), is(empty())); + clientPage.deleteAlbum(ALICE_ALBUM_NAME, this::assertWasNotDenied); + assertThat(getResourcesOfUser("alice")).isEmpty(); for (PolicyRepresentation policy : getAuthorizationResource().policies().policies()) { if ("Delete Album Permission".equals(policy.getName())) { @@ -358,16 +361,16 @@ public abstract class AbstractPhotozExampleAdapterTest extends AbstractExampleAd } printUpdatedPolicies(); - loginToClientPage("alice", "alice"); - clientPage.createAlbum("Alice Family Album"); + loginToClientPage(aliceUser); + clientPage.createAlbum(ALICE_ALBUM_NAME); - loginToClientPage("admin", "admin"); - clientPage.navigateToAdminAlbum(false); - clientPage.viewAlbum("Alice Family Album", false); - assertThat(getResourcesOfUser("alice"), is(not(empty()))); + loginToClientPage(adminUser); + clientPage.navigateToAdminAlbum(this::assertWasNotDenied); + clientPage.viewAlbum(ALICE_ALBUM_NAME, this::assertWasNotDenied); + assertThat(getResourcesOfUser("alice")).isNotEmpty(); - clientPage.navigateToAdminAlbum(false); - clientPage.deleteAlbum("Alice Family Album", true); + clientPage.navigateToAdminAlbum(this::assertWasNotDenied); + clientPage.deleteAlbum(ALICE_ALBUM_NAME, this::assertWasDenied); for (PolicyRepresentation policy : getAuthorizationResource().policies().policies()) { if ("Delete Album Permission".equals(policy.getName())) { @@ -377,18 +380,18 @@ public abstract class AbstractPhotozExampleAdapterTest extends AbstractExampleAd } printUpdatedPolicies(); - clientPage.navigateToAdminAlbum(false); - clientPage.deleteAlbum("Alice Family Album", false); - assertThat(getResourcesOfUser("alice"), is(empty())); + loginToClientPage(adminUser); // Clear cache + + clientPage.navigateToAdminAlbum(this::assertWasNotDenied); + clientPage.deleteAlbum(ALICE_ALBUM_NAME, this::assertWasNotDenied); + assertThat(getResourcesOfUser("alice")).isEmpty(); } @Test public void testClientRoleRepresentingUserConsent() throws Exception { - ContainerAssume.assumeNotAuthServerUndertow(); - - loginToClientPage("alice", "alice"); - clientPage.createAlbum("Alice Family Album"); - clientPage.viewAlbum("Alice Family Album", false); + loginToClientPage(aliceUser); + clientPage.createAlbum(ALICE_ALBUM_NAME); + clientPage.viewAlbum(ALICE_ALBUM_NAME, this::assertWasNotDenied); RealmResource realmResource = realmsResouce().realm(REALM_NAME); UsersResource usersResource = realmResource.users(); @@ -406,19 +409,19 @@ public abstract class AbstractPhotozExampleAdapterTest extends AbstractExampleAd setManageAlbumScopeRequired(); - loginToClientPage("alice", "alice"); - clientPage.viewAlbum("Alice Family Album", true); + loginToClientPage(aliceUser); + clientPage.viewAlbum(ALICE_ALBUM_NAME, this::assertWasDenied); - loginToClientPage("alice", "alice", "manage-albums"); - clientPage.viewAlbum("Alice Family Album", false); + loginToClientPage(aliceUser, "manage-albums"); + clientPage.viewAlbum(ALICE_ALBUM_NAME, this::assertWasNotDenied); } @Test public void testClientRoleNotRequired() throws Exception { - loginToClientPage("alice", "alice"); + loginToClientPage(aliceUser); - clientPage.createAlbum("Alice Family Album"); - clientPage.viewAlbum("Alice Family Album", false); + clientPage.createAlbum(ALICE_ALBUM_NAME); + clientPage.viewAlbum(ALICE_ALBUM_NAME, this::assertWasNotDenied); UsersResource usersResource = realmsResouce().realm(REALM_NAME).users(); List users = usersResource.search("alice", null, null, null, null, null); @@ -440,8 +443,8 @@ public abstract class AbstractPhotozExampleAdapterTest extends AbstractExampleAd manageAlbumRole.update(roleRepresentation); - loginToClientPage("alice", "alice"); - clientPage.viewAlbum("Alice Family Album", true); + loginToClientPage(aliceUser); + clientPage.viewAlbum(ALICE_ALBUM_NAME, this::assertWasDenied); for (PolicyRepresentation policy : getAuthorizationResource().policies().policies()) { if ("Any User Policy".equals(policy.getName())) { @@ -460,34 +463,28 @@ public abstract class AbstractPhotozExampleAdapterTest extends AbstractExampleAd } printUpdatedPolicies(); - loginToClientPage("alice", "alice"); - clientPage.viewAlbum("Alice Family Album", false); + loginToClientPage(aliceUser); + clientPage.viewAlbum(ALICE_ALBUM_NAME, this::assertWasNotDenied); } @Test public void testOverridePermissionFromResourceParent() throws Exception { - ContainerAssume.assumeNotAuthServerUndertow(); - - loginToClientPage("alice", "alice"); - String resourceName = "My Resource Instance"; + loginToClientPage(aliceUser); + String resourceName = "My-Resource-Instance"; clientPage.createAlbum(resourceName); - clientPage.viewAlbum(resourceName, false); - - clientPage.navigateTo(); - clientPage.deleteAlbum(resourceName, false); + clientPage.viewAlbum(resourceName, this::assertWasNotDenied); + clientPage.deleteAlbum(resourceName, this::assertWasNotDenied); clientPage.createAlbum(resourceName); - loginToClientPage("admin", "admin"); + loginToClientPage(adminUser); - clientPage.navigateToAdminAlbum(false); - clientPage.viewAlbum(resourceName, false); + clientPage.navigateToAdminAlbum(this::assertWasNotDenied); + clientPage.viewAlbum(resourceName, this::assertWasNotDenied); + clientPage.deleteAlbum(resourceName, this::assertWasNotDenied); - clientPage.navigateToAdminAlbum(false); - clientPage.deleteAlbum(resourceName, false); - - loginToClientPage("alice", "alice"); + loginToClientPage(aliceUser); clientPage.createAlbum(resourceName); getAuthorizationResource().resources().resources().forEach(resource -> { @@ -512,54 +509,45 @@ public abstract class AbstractPhotozExampleAdapterTest extends AbstractExampleAd }); printUpdatedPolicies(); - loginToClientPage("admin", "admin"); + loginToClientPage(adminUser); - clientPage.navigateToAdminAlbum(false); - clientPage.viewAlbum(resourceName, true); + clientPage.navigateToAdminAlbum(this::assertWasNotDenied); + clientPage.viewAlbum(resourceName, this::assertWasDenied); + clientPage.deleteAlbum(resourceName, this::assertWasDenied); - clientPage.navigateToAdminAlbum(false); - clientPage.deleteAlbum(resourceName, true); - - loginToClientPage("alice", "alice"); - clientPage.deleteAlbum(resourceName, false); - - assertThat(getResourcesOfUser("alice"), is(empty())); + loginToClientPage(aliceUser); + clientPage.deleteAlbum(resourceName, this::assertWasNotDenied); + assertThat(getResourcesOfUser("alice")).isEmpty(); } @Test public void testInheritPermissionFromResourceParent() throws Exception { - ContainerAssume.assumeNotAuthServerUndertow(); + ContainerAssume.assumeNotAppServerUndertow(); - loginToClientPage("alice", "alice"); + loginToClientPage(aliceUser); - String resourceName = "My Resource Instance"; - clientPage.createAlbum(resourceName); + final String RESOURCE_NAME = "My-Resource-Instance"; + clientPage.createAlbum(RESOURCE_NAME); + clientPage.viewAlbum(RESOURCE_NAME, this::assertWasNotDenied); + clientPage.deleteAlbum(RESOURCE_NAME, this::assertWasNotDenied); - clientPage.viewAlbum(resourceName, false); + clientPage.createAlbum(RESOURCE_NAME); - clientPage.navigateTo(); - clientPage.deleteAlbum(resourceName, false); + loginToClientPage(adminUser); + clientPage.navigateToAdminAlbum(this::assertWasNotDenied); + clientPage.viewAlbum(RESOURCE_NAME, this::assertWasNotDenied); + clientPage.deleteAlbum(RESOURCE_NAME, this::assertWasNotDenied); - clientPage.createAlbum(resourceName); - - loginToClientPage("admin", "admin"); - - clientPage.navigateToAdminAlbum(false); - clientPage.viewAlbum(resourceName, false); - - clientPage.navigateToAdminAlbum(false); - clientPage.deleteAlbum(resourceName, false); - - loginToClientPage("alice", "alice"); - clientPage.createAlbum(resourceName); + loginToClientPage(aliceUser); + clientPage.createAlbum(RESOURCE_NAME); ResourcesResource resourcesResource = getAuthorizationResource().resources(); resourcesResource.resources().forEach(resource -> { - if (resource.getName().equals(resourceName)) { + if (resource.getName().equals(RESOURCE_NAME)) { try { PolicyRepresentation resourceInstancePermission = new PolicyRepresentation(); - resourceInstancePermission.setName(resourceName + "Permission"); + resourceInstancePermission.setName(RESOURCE_NAME + "Permission"); resourceInstancePermission.setType("resource"); Map config = new HashMap<>(); @@ -575,140 +563,151 @@ public abstract class AbstractPhotozExampleAdapterTest extends AbstractExampleAd } }); - loginToClientPage("admin", "admin"); + loginToClientPage(adminUser); - clientPage.navigateToAdminAlbum(false); - clientPage.viewAlbum(resourceName, true); - - clientPage.navigateToAdminAlbum(false); - clientPage.deleteAlbum(resourceName, true); + clientPage.navigateToAdminAlbum(this::assertWasNotDenied); + clientPage.viewAlbum(RESOURCE_NAME, this::assertWasDenied); + clientPage.deleteAlbum(RESOURCE_NAME, this::assertWasDenied); resourcesResource.resources().forEach(resource -> { - if (resource.getName().equals(resourceName)) { + if (resource.getName().equals(RESOURCE_NAME)) { resource.setScopes(resource.getScopes().stream().filter(scope -> !scope.getName().equals("album:view")).collect(Collectors.toSet())); resourcesResource.resource(resource.getId()).update(resource); } }); - loginToClientPage("admin", "admin"); + loginToClientPage(adminUser); - clientPage.navigateToAdminAlbum(false); - clientPage.viewAlbum(resourceName, false); + clientPage.navigateToAdminAlbum(this::assertWasNotDenied); + clientPage.viewAlbum(RESOURCE_NAME, this::assertWasNotDenied); + clientPage.deleteAlbum(RESOURCE_NAME, this::assertWasDenied); - clientPage.navigateToAdminAlbum(false); - clientPage.deleteAlbum(resourceName, true); - - loginToClientPage("alice", "alice"); - clientPage.deleteAlbum(resourceName, false); + loginToClientPage(aliceUser); + clientPage.deleteAlbum(RESOURCE_NAME, this::assertWasNotDenied); List resources = resourcesResource.resources(); assertTrue(resources.stream().filter(resource -> resource.getOwner().getName().equals("alice")).collect(Collectors.toList()).isEmpty()); - - resourcesResource.resources().forEach(resource -> { - if (resource.getName().equals(resourceName)) { - resource.setScopes(Collections.emptySet()); - resourcesResource.resource(resource.getId()).update(resource); - } - }); } //KEYCLOAK-3777 @Test public void testEntitlementRequest() throws Exception { - ContainerAssume.assumeNotAuthServerUndertow(); + loginToClientPage(adminUser); - clientPage.navigateTo(); - loginToClientPage("admin", "admin"); + clientPage.requestEntitlements((driver1, output, events) -> assertThat((String)output).contains("admin:manage")); - clientPage.requestEntitlements(); - assertTrue(jsDriver.getPageSource().contains("admin:manage")); - - clientPage.requestEntitlement(); - String pageSource = jsDriver.getPageSource(); - assertTrue(pageSource.contains("album:view")); - assertTrue(pageSource.contains("album:delete")); + loginToClientPage(adminUser); + clientPage.requestEntitlement((driver1, output, events) -> assertThat((String)output) + .doesNotContain("admin:manage") + .contains("album:view") + .contains("album:delete") + ); } + @Test public void testResourceProtectedWithAnyScope() throws Exception { - loginToClientPage("alice", "alice"); - clientPage.requestResourceProtectedAllScope(true); - clientPage.requestResourceProtectedAnyScope(false); + loginToClientPage(aliceUser); + + clientPage.requestResourceProtectedAllScope(this::assertWasDenied); + clientPage.requestResourceProtectedAnyScope(response -> { + assertThat(response.get("status")).isIn(404L, 0L); // PhantomJS returns 0 and chrome 404 + }); } + @Test public void testRequestResourceToOwner() throws Exception { - loginToClientPage("alice", "alice"); - clientPage.createAlbum("Alice-Family-Album", true); + loginToClientPage(aliceUser); + clientPage.createAlbum(ALICE_ALBUM_NAME, true); - loginToClientPage("jdoe", "jdoe"); - clientPage.viewAllAlbums(); - clientPage.viewAlbum("Alice-Family-Album", true); + loginToClientPage(jdoeUser); + clientPage.viewAlbum(ALICE_ALBUM_NAME, this::assertWasDenied); + clientPage.deleteAlbum(ALICE_ALBUM_NAME, this::assertWasDenied); + + loginToClientPage(aliceUser); + clientPage.accountGrantResource(ALICE_ALBUM_NAME, "jdoe"); + + // get back to clientPage and init javascript adapter in order to log out correctly clientPage.navigateTo(); - clientPage.viewAllAlbums(); - clientPage.deleteAlbum("Alice-Family-Album", true); - loginToClientPage("alice", "alice"); - clientPage.accountGrantResource("Alice-Family-Album", "jdoe"); + testExecutor.init(defaultArguments(), this::assertInitNotAuth) + .login() + .init(defaultArguments(), this::assertSuccessfullyLoggedIn); - loginToClientPage("jdoe", "jdoe"); - clientPage.viewAllAlbums(); - clientPage.viewAlbum("Alice-Family-Album", false); + loginToClientPage(jdoeUser); + clientPage.viewAlbum(ALICE_ALBUM_NAME, this::assertWasNotDenied); + clientPage.deleteAlbum(ALICE_ALBUM_NAME, this::assertWasNotDenied); + + loginToClientPage(aliceUser); + clientPage.createAlbum(ALICE_ALBUM_NAME, true); + + loginToClientPage(jdoeUser); + clientPage.viewAlbum(ALICE_ALBUM_NAME, this::assertWasDenied); + clientPage.deleteAlbum(ALICE_ALBUM_NAME, this::assertWasDenied); + + loginToClientPage(aliceUser); + clientPage.accountGrantRemoveScope(ALICE_ALBUM_NAME, "jdoe", "album:delete"); + + // get back to clientPage and init javascript adapter in order to navigate to accountPage again clientPage.navigateTo(); - clientPage.viewAllAlbums(); - clientPage.deleteAlbum("Alice-Family-Album", false); + testExecutor.init(defaultArguments(), this::assertInitNotAuth) + .login(this::assertOnTestAppUrl) + .init(defaultArguments(), this::assertSuccessfullyLoggedIn); + clientPage.accountGrantResource(ALICE_ALBUM_NAME, "jdoe"); - loginToClientPage("alice", "alice"); - clientPage.createAlbum("Alice-Family-Album", true); - - loginToClientPage("jdoe", "jdoe"); - clientPage.viewAllAlbums(); - clientPage.viewAlbum("Alice-Family-Album", true); + // get back to clientPage and init javascript adapter in order to log out correctly clientPage.navigateTo(); - clientPage.viewAllAlbums(); - clientPage.deleteAlbum("Alice-Family-Album", true); + testExecutor.init(defaultArguments(), this::assertInitNotAuth) + .login() + .init(defaultArguments(), this::assertSuccessfullyLoggedIn); - loginToClientPage("alice", "alice"); - clientPage.accountGrantRemoveScope("Alice-Family-Album", "jdoe", "album:delete"); - clientPage.accountGrantResource("Alice-Family-Album", "jdoe"); - loginToClientPage("jdoe", "jdoe"); - clientPage.viewAllAlbums(); - clientPage.viewAlbum("Alice-Family-Album", false); - clientPage.navigateTo(); - clientPage.viewAllAlbums(); - clientPage.deleteAlbum("Alice-Family-Album", true); + loginToClientPage(jdoeUser); + clientPage.viewAlbum(ALICE_ALBUM_NAME, this::assertWasNotDenied); + clientPage.deleteAlbum(ALICE_ALBUM_NAME, this::assertWasDenied); } @Test public void testOwnerSharingResource() throws Exception { - loginToClientPage("alice", "alice"); - clientPage.createAlbum("Alice-Family-Album", true); - clientPage.accountShareResource("Alice-Family-Album", "jdoe"); + loginToClientPage(aliceUser); + clientPage.createAlbum(ALICE_ALBUM_NAME, true); + clientPage.accountShareResource(ALICE_ALBUM_NAME, "jdoe"); - loginToClientPage("jdoe", "jdoe"); - clientPage.viewAllAlbums(); - clientPage.viewAlbum("Alice-Family-Album", false); + // get back to clientPage and init javascript adapter in order to log out correctly clientPage.navigateTo(); - clientPage.viewAllAlbums(); - clientPage.deleteAlbum("Alice-Family-Album", false); + testExecutor.init(defaultArguments(), this::assertInitNotAuth) + .login() + .init(defaultArguments(), this::assertSuccessfullyLoggedIn); - loginToClientPage("alice", "alice"); - clientPage.createAlbum("Alice-Family-Album", true); - clientPage.accountShareRemoveScope("Alice-Family-Album", "jdoe", "album:delete"); + loginToClientPage(jdoeUser); + clientPage.viewAlbum(ALICE_ALBUM_NAME, this::assertWasNotDenied); + clientPage.deleteAlbum(ALICE_ALBUM_NAME, this::assertWasNotDenied); - loginToClientPage("jdoe", "jdoe"); - clientPage.viewAllAlbums(); - clientPage.viewAlbum("Alice-Family-Album", false); + loginToClientPage(aliceUser); + clientPage.createAlbum(ALICE_ALBUM_NAME, true); + clientPage.accountShareRemoveScope(ALICE_ALBUM_NAME, "jdoe", "album:delete"); + + // get back to clientPage and init javascript adapter in order to log out correctly clientPage.navigateTo(); - clientPage.viewAllAlbums(); - clientPage.deleteAlbum("Alice-Family-Album", true); + testExecutor.init(defaultArguments(), this::assertInitNotAuth) + .login(this::assertOnTestAppUrl) + .init(defaultArguments(), this::assertSuccessfullyLoggedIn); - loginToClientPage("alice", "alice"); - clientPage.accountRevokeResource("Alice-Family-Album", "jdoe"); + loginToClientPage(jdoeUser); + clientPage.viewAlbum(ALICE_ALBUM_NAME, this::assertWasNotDenied); + clientPage.deleteAlbum(ALICE_ALBUM_NAME, this::assertWasDenied); - loginToClientPage("jdoe", "jdoe"); - clientPage.viewAllAlbums(); - clientPage.viewAlbum("Alice-Family-Album", true); + loginToClientPage(aliceUser); + clientPage.accountRevokeResource(ALICE_ALBUM_NAME, "jdoe"); + + // get back to clientPage and init javascript adapter in order to log out correctly + clientPage.navigateTo(); + testExecutor.init(defaultArguments(), this::assertInitNotAuth) + .login() + .init(defaultArguments(), this::assertSuccessfullyLoggedIn); + + loginToClientPage(jdoeUser); + clientPage.viewAlbum(ALICE_ALBUM_NAME, this::assertWasDenied); } private void importResourceServerSettings() throws FileNotFoundException { @@ -731,41 +730,23 @@ public abstract class AbstractPhotozExampleAdapterTest extends AbstractExampleAd return clients.get(resourceServer.getId()); } - private void deleteAllCookiesForClientPage() { - jsDriver.manage().deleteAllCookies(); - } + private void loginToClientPage(UserRepresentation user, String... scopes) throws InterruptedException { + log.debugf("--logging in as {0} with password: {1}; scopes: {2}", user.getUsername(), user.getCredentials().get(0).getValue(), Arrays.toString(scopes)); - private void loginToClientPage(String username, String password, String... scopes) throws InterruptedException { - log.debugf("--logging in as {0} with password: {1}; scopes: {2}", username, password, Arrays.toString(scopes)); + if (testExecutor.isLoggedIn()) { + testExecutor.logout(this::assertOnTestAppUrl); + jsDriver.manage().deleteAllCookies(); - clientPage.navigateTo(); - if (jsDriver.getCurrentUrl().startsWith(clientPage.toString())) { - try { - clientPage.logOut(); - } catch (NoSuchElementException ex) { - if ("phantomjs".equals(System.getProperty("js.browser"))) { - // PhantomJS is broken, it can't logout using sign out button sometimes, we have to clean sessions and remove cookies - adminClient.realm(REALM_NAME).logoutAll(); - - jsDriverTestRealmLoginPage.navigateTo(); - driver.manage().deleteAllCookies(); - - clientPage.navigateTo(); - driver.manage().deleteAllCookies(); - - clientPage.navigateTo(); - // Check for correct logout - assertCurrentUrlStartsWithLoginUrlOf(jsDriverTestRealmLoginPage); - } else { - throw ex; - } - } + jsDriver.navigate().to(testRealmLoginPage.toString()); + waitForPageToLoad(); + jsDriver.manage().deleteAllCookies(); } clientPage.navigateTo(); - waitForPageToLoad(); - clientPage.login(username, password, scopes); - waitUntilElement(By.linkText("Sign Out")).is().clickable(); + testExecutor.init(defaultArguments(), this::assertInitNotAuth) + .login(this::assertOnLoginPage) + .loginFormWithScopesWithPossibleConsentPage(user, this::assertOnTestAppUrl, oAuthGrantPage, scopes) + .init(defaultArguments(), this::assertSuccessfullyLoggedIn); } private void setManageAlbumScopeRequired() { diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/authorization/AbstractPhotozJavascriptExecutorTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/authorization/AbstractPhotozJavascriptExecutorTest.java new file mode 100644 index 0000000000..030ad7243e --- /dev/null +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/authorization/AbstractPhotozJavascriptExecutorTest.java @@ -0,0 +1,108 @@ +package org.keycloak.testsuite.adapter.example.authorization; + +import org.jboss.arquillian.drone.api.annotation.Drone; +import org.jboss.arquillian.graphene.page.Page; +import org.junit.Before; +import org.keycloak.representations.idm.UserRepresentation; +import org.keycloak.testsuite.Assert; +import org.keycloak.testsuite.adapter.AbstractExampleAdapterTest; +import org.keycloak.testsuite.adapter.javascript.AbstractJavascriptTest; +import org.keycloak.testsuite.auth.page.login.OAuthGrant; +import org.keycloak.testsuite.auth.page.login.OIDCLogin; +import org.keycloak.testsuite.util.JavascriptBrowser; +import org.keycloak.testsuite.util.UserBuilder; +import org.keycloak.testsuite.util.javascript.JSObjectBuilder; +import org.keycloak.testsuite.util.javascript.JavascriptStateValidator; +import org.keycloak.testsuite.util.javascript.ResponseValidator; +import org.openqa.selenium.By; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; + +import static org.hamcrest.CoreMatchers.containsString; +import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlStartsWith; +import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement; + +/** + * @author mhajas + */ +public abstract class AbstractPhotozJavascriptExecutorTest extends AbstractExampleAdapterTest { + + @FunctionalInterface + interface QuadFunction { + void apply(T a, U b, V c, W d); + } + + protected static final String REALM_NAME = "photoz"; + + @Page + @JavascriptBrowser + protected OIDCLogin jsDriverTestRealmLoginPage; + + @Page + @JavascriptBrowser + private OAuthGrant oAuthGrantPage; + + @Drone + @JavascriptBrowser + protected WebDriver jsDriver; + + protected UserRepresentation aliceUser = UserBuilder.create().username("alice").password("alice").build(); + + protected UserRepresentation adminUser = UserBuilder.create().username("admin").password("admin").build(); + + protected UserRepresentation jdoeUser = UserBuilder.create().username("jdoe").password("jdoe").build(); + + @Before + public void setDefaultValues() { + jsDriverTestRealmLoginPage.setAuthRealm(REALM_NAME); + } + + protected JavascriptStateValidator buildFunction(QuadFunction f, T x) { + return (y,z,w) -> f.apply(x, y, z, w); + } + + public void assertOutputContains(String value, WebDriver driver1, Object output, WebElement events) { + if (output instanceof WebElement) { + waitUntilElement((WebElement) output).text().contains(value); + } else { + Assert.assertThat((String) output, containsString(value)); + } + } + + protected JSObjectBuilder defaultArguments() { + return JSObjectBuilder.create().defaultSettings(); + } + + protected void assertSuccessfullyLoggedIn(WebDriver driver1, Object output, WebElement events) { + buildFunction(this::assertOutputContains, "Init Success (Authenticated)").validate(driver1, output, events); + } + + protected void assertInitNotAuth(WebDriver driver1, Object output, WebElement events) { + buildFunction(this::assertOutputContains, "Init Success (Not Authenticated)").validate(driver1, output, events); + } + + protected void assertOnLoginPage(WebDriver driver1, Object output, WebElement events) { + waitUntilElement(By.tagName("body")).is().present(); + try { + assertCurrentUrlStartsWith(jsDriverTestRealmLoginPage, driver1); + } catch (AssertionError e) { + System.out.println("Test"); + throw e; + } + } + + protected JavascriptStateValidator all(JavascriptStateValidator[] toValidate) { + return ((driver1, output, events) -> { + for (JavascriptStateValidator val : toValidate) { + val.validate(driver1, output, events); + } + }); + } + protected ResponseValidator all(ResponseValidator[] toValidate) { + return ((response) -> { + for (ResponseValidator val : toValidate) { + val.validate(response); + } + }); + } +} diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/authorization/PhotozExampleLazyLoadPathsAdapterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/authorization/PhotozExampleLazyLoadPathsAdapterTest.java index 0b8f51dc76..df41c8bcf7 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/authorization/PhotozExampleLazyLoadPathsAdapterTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/authorization/PhotozExampleLazyLoadPathsAdapterTest.java @@ -34,6 +34,7 @@ import org.keycloak.testsuite.arquillian.containers.ContainerConstants; @AppServerContainer(ContainerConstants.APP_SERVER_EAP) @AppServerContainer(ContainerConstants.APP_SERVER_EAP6) @AppServerContainer(ContainerConstants.APP_SERVER_EAP71) +@AppServerContainer(ContainerConstants.APP_SERVER_UNDERTOW) public class PhotozExampleLazyLoadPathsAdapterTest extends AbstractPhotozExampleAdapterTest { @Deployment(name = PhotozClientAuthzTestApp.DEPLOYMENT_NAME) @@ -43,15 +44,7 @@ public class PhotozExampleLazyLoadPathsAdapterTest extends AbstractPhotozExample @Deployment(name = RESOURCE_SERVER_ID, managed = false, testable = false) public static WebArchive deploymentResourceServer() throws IOException { - WebArchive war = exampleDeployment(RESOURCE_SERVER_ID) + return exampleDeployment(RESOURCE_SERVER_ID) .addAsWebInfResource(new File(TEST_APPS_HOME_DIR + "/photoz/keycloak-lazy-load-path-authz-service.json"), "keycloak.json"); - - // cannot use EAP6DeploymentArchiveProcessor because the deployment is marked - // as non managed by arquillian - if (AppServerTestEnricher.isEAP6AppServer()) { - updatePersistenceXml(war); - } - return war; } - } \ No newline at end of file diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/authorization/PhotozExampleNoLazyLoadPathsAdapterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/authorization/PhotozExampleNoLazyLoadPathsAdapterTest.java index b416d99049..36443c0b6a 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/authorization/PhotozExampleNoLazyLoadPathsAdapterTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/authorization/PhotozExampleNoLazyLoadPathsAdapterTest.java @@ -33,6 +33,7 @@ import org.keycloak.testsuite.arquillian.containers.ContainerConstants; @AppServerContainer(ContainerConstants.APP_SERVER_EAP) @AppServerContainer(ContainerConstants.APP_SERVER_EAP6) @AppServerContainer(ContainerConstants.APP_SERVER_EAP71) +@AppServerContainer(ContainerConstants.APP_SERVER_UNDERTOW) public class PhotozExampleNoLazyLoadPathsAdapterTest extends AbstractPhotozExampleAdapterTest { @Deployment(name = PhotozClientAuthzTestApp.DEPLOYMENT_NAME) @@ -42,14 +43,7 @@ public class PhotozExampleNoLazyLoadPathsAdapterTest extends AbstractPhotozExamp @Deployment(name = RESOURCE_SERVER_ID, managed = false, testable = false) public static WebArchive deploymentResourceServer() throws IOException { - WebArchive war = exampleDeployment(RESOURCE_SERVER_ID); - - // cannot use EAP6DeploymentArchiveProcessor because the deployment is marked - // as non managed by arquillian - if (AppServerTestEnricher.isEAP6AppServer()) { - updatePersistenceXml(war); - } - return war; + return exampleDeployment(RESOURCE_SERVER_ID); } } \ No newline at end of file diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/javascript/AbstractJavascriptTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/javascript/AbstractJavascriptTest.java index 789bebfcc0..a649840900 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/javascript/AbstractJavascriptTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/javascript/AbstractJavascriptTest.java @@ -17,6 +17,8 @@ import org.keycloak.testsuite.util.JavascriptBrowser; import org.keycloak.testsuite.util.RealmBuilder; import org.keycloak.testsuite.util.RolesBuilder; import org.keycloak.testsuite.util.UserBuilder; +import org.keycloak.testsuite.util.javascript.JavascriptStateValidator; +import org.keycloak.testsuite.util.javascript.ResponseValidator; import org.openqa.selenium.By; import org.openqa.selenium.Cookie; import org.openqa.selenium.JavascriptExecutor; diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/javascript/JavascriptAdapterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/javascript/JavascriptAdapterTest.java index 8d62b28887..e4a05c1568 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/javascript/JavascriptAdapterTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/javascript/JavascriptAdapterTest.java @@ -24,6 +24,9 @@ import org.keycloak.testsuite.util.JavascriptBrowser; import org.keycloak.testsuite.util.OAuthClient; import org.keycloak.testsuite.util.RealmBuilder; import org.keycloak.testsuite.util.UserBuilder; +import org.keycloak.testsuite.util.javascript.JSObjectBuilder; +import org.keycloak.testsuite.util.javascript.JavascriptTestExecutor; +import org.keycloak.testsuite.util.javascript.XMLHttpRequest; import org.openqa.selenium.TimeoutException; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebDriverException; @@ -83,10 +86,10 @@ public class JavascriptAdapterTest extends AbstractJavascriptTest { applicationsPage.setAuthRealm(REALM_NAME); jsDriver.navigate().to(testAppUrl); - testExecutor = JavascriptTestExecutor.create(jsDriver, jsDriverTestRealmLoginPage); waitUntilElement(outputArea).is().present(); assertCurrentUrlStartsWith(testAppUrl, jsDriver); + testExecutor = JavascriptTestExecutor.create(jsDriver, jsDriverTestRealmLoginPage); jsDriver.manage().deleteAllCookies(); @@ -168,6 +171,8 @@ public class JavascriptAdapterTest extends AbstractJavascriptTest { @Test public void grantBrowserBasedApp() { + Assume.assumeTrue("This test doesn't work with phantomjs", !"phantomjs".equals(System.getProperty("js.browser"))); + ClientResource clientResource = ApiUtil.findClientResourceByClientId(adminClient.realm(REALM_NAME), CLIENT_ID); ClientRepresentation client = clientResource.toRepresentation(); client.setConsentRequired(true); @@ -403,7 +408,7 @@ public class JavascriptAdapterTest extends AbstractJavascriptTest { List users = adminClient.realm(REALM_NAME).users().search("mhajas", 0, 1); assertEquals("There should be created user mhajas", 1, users.size()); - assertThat((String) response.get("responseHeaders"), containsString("location: " + authServerContextRootPage.toString() + "/auth/admin/realms/" + REALM_NAME + "/users/" + users.get(0).getId())); + assertThat(((String) response.get("responseHeaders")).toLowerCase(), containsString("location: " + authServerContextRootPage.toString() + "/auth/admin/realms/" + REALM_NAME + "/users/" + users.get(0).getId())); }); } diff --git a/testsuite/integration-arquillian/util/src/main/java/org/keycloak/testsuite/utils/undertow/UndertowDeployerHelper.java b/testsuite/integration-arquillian/util/src/main/java/org/keycloak/testsuite/utils/undertow/UndertowDeployerHelper.java index cb91e398de..a4f11eeb64 100644 --- a/testsuite/integration-arquillian/util/src/main/java/org/keycloak/testsuite/utils/undertow/UndertowDeployerHelper.java +++ b/testsuite/integration-arquillian/util/src/main/java/org/keycloak/testsuite/utils/undertow/UndertowDeployerHelper.java @@ -75,7 +75,7 @@ public class UndertowDeployerHelper { di = new DeploymentInfo(); } - UndertowWarClassLoader classLoader = new UndertowWarClassLoader(UndertowDeployerHelper.class.getClassLoader(), archive); + UndertowWarClassLoader classLoader = new UndertowWarClassLoader(Thread.currentThread().getContextClassLoader(), archive); di.setClassLoader(classLoader); di.setDeploymentName(archiveName);