Compare commits

..
1246 Commits
Author SHA1 Message Date
Marek Posolda 5e51204114 Merge pull request #686 from mposolda/master
KEYCLOAK-674 Reduce info level logging in adapters
2014-09-10 16:04:48 +02:00
mposolda 4c0751c1a0 KEYCLOAK-674 Reduce info level logging in adapters 2014-09-10 16:02:22 +02:00
Marek Posolda ec1434c65e Merge pull request #685 from mposolda/master
Support for cors in PublicRealmResource
2014-09-10 13:16:21 +02:00
mposolda aa7bbeb11b Support for cors in PublicRealmResource 2014-09-10 13:05:53 +02:00
Marek Posolda 88a39dbaf7 Merge pull request #683 from mposolda/master
KEYCLOAK-670 allow ServerInfo to be available with cors
2014-09-10 10:52:33 +02:00
mposolda 52920119bd Ensure that ServerInfo request is authorized and add CORS support to it 2014-09-10 10:42:05 +02:00
mposolda 47ac358bb6 Fix timeouts in cors example 2014-09-10 10:42:04 +02:00
Stian Thorgersen 62aa2d7f65 Merge pull request #684 from stianst/master
Fix CRSF protection on Chrome, and add check if 'Referer' header
2014-09-10 10:34:49 +02:00
Stian Thorgersen 557de7690e Fix CRSF protection on Chrome, and add check if 'Referer' header 2014-09-10 10:32:56 +02:00
Bill Burke 4c8da3d614 Merge pull request #682 from patriot1burke/master
version bump
2014-09-09 13:35:39 -04:00
Bill Burke 3f539c6d5c version bump 2014-09-09 13:34:56 -04:00
Bill Burke 5b1d67f17d Merge pull request #681 from patriot1burke/master
change CSRF to random value
2014-09-09 13:27:59 -04:00
Bill Burke e3e32982a0 change CSRF to random value 2014-09-09 13:27:34 -04:00
Bill Burke b771cd30e7 Merge pull request #680 from patriot1burke/master
nolog CORS exception
2014-09-09 12:54:55 -04:00
Bill Burke ac29db51e5 nolog CORS exception 2014-09-09 12:51:55 -04:00
Bill Burke 6e3770f04a Merge pull request #679 from patriot1burke/master
CSRF
2014-09-09 12:07:29 -04:00
Bill Burke d0a3a04d34 CSRF 2014-09-09 12:06:48 -04:00
Stian Thorgersen c5662020d8 Merge pull request #678 from stianst/master
Moved logo-example themes to examples/themes
2014-09-09 14:09:58 +02:00
Stian Thorgersen fea0d1af66 Moved logo-example themes to examples/themes 2014-09-09 14:09:32 +02:00
Stian Thorgersen 30cd28d288 Merge pull request #677 from stianst/master
KEYCLOAK-668 Make sure keycloak.js doesn't send multiple concurrent requ...
2014-09-09 13:46:21 +02:00
Stian Thorgersen c475721dab KEYCLOAK-668 Make sure keycloak.js doesn't send multiple concurrent requests to refresh the token 2014-09-09 13:45:55 +02:00
Stian Thorgersen 839069ca15 Merge pull request #676 from stianst/master
Fixes to admin console random logout
2014-09-09 11:02:19 +02:00
Stian Thorgersen 09860f1ee1 Fix test 2014-09-09 11:01:24 +02:00
Stian Thorgersen a1b6378bef KEYCLOAK-667 Remove client-side idle timeout from admin console - with sso idle timeout we have a server-side mechanism for this 2014-09-09 11:01:24 +02:00
Stian Thorgersen 3530fa6259 KEYCLOAK-666 Update session last refreshed on every token refresh 2014-09-09 11:01:24 +02:00
Bill Burke d22afd78e6 Merge pull request #675 from patriot1burke/master
doc update
2014-09-08 09:09:07 -04:00
Bill Burke f1986093e6 doc update 2014-09-08 09:07:51 -04:00
Stian Thorgersen 6c5477bc02 Merge pull request #674 from stianst/master
Minor fixes to theme docs
2014-09-08 14:59:34 +02:00
Stian Thorgersen ae6fd458e8 Minor fixes to theme docs 2014-09-08 14:59:09 +02:00
Stian Thorgersen cdda48d895 Merge pull request #673 from stianst/master
Typo fix in docs
2014-09-08 10:25:18 +02:00
Stian Thorgersen 556314ae15 Typo fix in docs 2014-09-08 10:24:47 +02:00
Stian Thorgersen a2845fa0b4 Merge pull request #672 from stianst/master
Added instruction to manually configure and deploy the unconfigured demo
2014-09-03 13:32:33 +02:00
Stian Thorgersen 8c4a3374d3 Added instruction to manually configure and deploy the unconfigured demo 2014-09-03 13:20:58 +02:00
Stian Thorgersen b97106b750 Adding changes to examples overview readme 2014-09-03 13:18:14 +02:00
Stian Thorgersen 7907abd206 Merge pull request #671 from stianst/master
Added README.md with Overview of all examples
2014-09-03 11:22:42 +02:00
Stian Thorgersen 090871f8b9 Added README.md with Overview of all examples 2014-09-03 11:22:08 +02:00
Stian Thorgersen 0baf12c0ef Merge pull request #670 from stianst/master
Updates to server-installation docs
2014-09-03 10:13:36 +02:00
Stian Thorgersen 1599371ee5 Updates to server-installation docs 2014-09-03 10:13:05 +02:00
Stian Thorgersen 3bc27ef366 Merge pull request #669 from stianst/master
Fix AccountTest.viewLog test
2014-09-03 08:53:56 +02:00
Stian Thorgersen d5c5cc8321 Fix AccountTest.viewLog test 2014-09-03 08:53:02 +02:00
Bill Burke aea00fc574 Merge pull request #668 from patriot1burke/master
admin theme refactor
2014-09-02 11:37:32 -04:00
Bill Burke e9dc8b2460 refactor admin theme 2014-09-02 11:36:59 -04:00
Bill Burke eaed199b20 add logo example theme 2014-09-02 11:11:26 -04:00
Marek Posolda f7fcefc11c Merge pull request #667 from mposolda/master
KEYCLOAK-659 Export current version number during export
2014-09-02 17:09:10 +02:00
mposolda 1f0dcbddbe KEYCLOAK-659 Export current version number during export 2014-09-02 17:06:58 +02:00
Stian Thorgersen 9af0743883 Merge pull request #666 from stianst/master
Updated docs to inherit project version from keycloak-parent
2014-09-02 14:07:24 +02:00
Stian Thorgersen 7d4863783c Use keycloak-parent in docbook to inherit project version 2014-09-02 13:57:23 +02:00
Stian Thorgersen d87718f768 Inject project version from pom 2014-09-02 13:22:15 +02:00
Stian Thorgersen c7ba6159b5 Merge pull request #665 from stianst/master
Doc fix
2014-09-02 12:52:42 +02:00
Stian Thorgersen b43909aff1 Doc fix 2014-09-02 12:52:22 +02:00
Marek Posolda 87d9a5422d Merge pull request #664 from mposolda/master
Use stronger passwords in LDAP tests due to password policy on MSAD2012
2014-09-02 12:49:34 +02:00
mposolda 44937d33ad Use stronger passwords in LDAP tests due to password policy on MSAD2012 2014-09-02 12:43:14 +02:00
Stian Thorgersen b561080f3a Merge pull request #663 from stianst/master
Fix search for users by attribute on mongo
2014-09-02 11:52:15 +02:00
Stian Thorgersen d905ce12e3 Fix search for users by attribute on mongo 2014-09-02 11:51:29 +02:00
Marek Posolda 7040bd1c51 Merge pull request #662 from mposolda/master
Fix SyncProvidersTest with ActiveDirectory
2014-09-02 11:12:43 +02:00
mposolda cd91a29a89 Fix SyncProvidersTest with ActiveDirectory 2014-09-02 11:06:31 +02:00
Stian Thorgersen b1b452815a Merge pull request #661 from stianst/master
KEYCLOAK-656 Remove login-status-iframe from dist
2014-09-02 10:54:52 +02:00
Stian Thorgersen 59d66dd20e KEYCLOAK-656 Remove login-status-iframe from dist 2014-09-02 10:54:26 +02:00
Stian Thorgersen 0763d0d9d6 Merge pull request #660 from stianst/master
KEYCLOAK-658 Fix searching for users
2014-09-02 10:02:08 +02:00
Stian Thorgersen 8c8c44e50f KEYCLOAK-658 Fix searching for users 2014-09-02 10:01:44 +02:00
Marek Posolda 14b1941454 Merge pull request #659 from mposolda/master
Added more props to LDAPEmbeddedServer to allow automated test with Acti...
2014-09-01 20:54:49 +02:00
mposolda e52811ac28 Added more props to LDAPEmbeddedServer to allow automated test with ActiveDirectory 2014-09-01 20:43:14 +02:00
Stian Thorgersen 4f3a980f8b Merge pull request #658 from stianst/master
Version bump
2014-09-01 10:17:31 +02:00
Stian Thorgersen 05a1fc1ded Version bump 2014-09-01 10:17:00 +02:00
Stian Thorgersen ff74d1ddc0 Merge pull request #657 from stianst/master
Various fixes
2014-08-29 17:11:53 +02:00
Stian Thorgersen 31b0f5543f Fixes 2014-08-29 17:11:18 +02:00
Stian Thorgersen 39c0be5d99 KEYCLOAK-652
Social user can't set password
2014-08-29 16:51:10 +02:00
Stian Thorgersen fb18789b05 KEYCLOAK-650
Server error while trying to download keycloak.json for oauth client
2014-08-29 16:08:42 +02:00
Stian Thorgersen bcbf5da4b8 KEYCLOAK-651
Page not found trying to save changes to brute force
2014-08-29 16:04:37 +02:00
Stian Thorgersen e1b9dfe65d KEYCLOAK-649 Invalidate realm if app name or client clientId is changed 2014-08-29 15:49:17 +02:00
Stian Thorgersen 52f86f2293 Merge pull request #656 from stianst/master
Fixes to event-store-mem example
2014-08-29 14:56:09 +02:00
Stian Thorgersen e413694cf5 Fixes to event-store-mem example 2014-08-29 14:55:45 +02:00
Stian Thorgersen 20ce36dc64 Merge pull request #655 from stianst/master
Clean user credential management form
2014-08-29 11:06:11 +02:00
Stian Thorgersen a3c982a630 Clean user credential management form 2014-08-29 11:05:37 +02:00
Stian Thorgersen e0542b5260 Merge pull request #654 from stianst/master
KEYCLOAK-648 Fix removing role from composite role
2014-08-29 10:27:29 +02:00
Stian Thorgersen 7c7025a83d KEYCLOAK-648 Fix removing role from composite role 2014-08-29 10:18:00 +02:00
Stian Thorgersen 3e6a1f47ec Merge pull request #653 from stianst/master
Fix test
2014-08-29 09:10:41 +02:00
Stian Thorgersen 32703d19a0 Fix test 2014-08-29 08:59:57 +02:00
Stian Thorgersen cdc6588ac1 Merge branch 'ungarida-master' 2014-08-28 14:30:29 +02:00
Stian Thorgersen 57aea9b51c Merge branch 'master' of https://github.com/ungarida/keycloak into ungarida-master
Conflicts:
	integration/tomcat7/adapter/src/main/java/org/keycloak/adapters/tomcat7/AuthenticatedActionsValve.java
2014-08-28 14:29:07 +02:00
Stian Thorgersen a2171bf777 Merge pull request #652 from stianst/master
Password token
2014-08-28 14:22:51 +02:00
Stian Thorgersen b9d0f64f74 Added password token to use inplace of plain-text password for totp 2014-08-28 13:51:55 +02:00
Stian Thorgersen 55d614fce8 Reduce log in UserFederationResource 2014-08-28 11:26:55 +02:00
Stian Thorgersen 46d118207a Merge pull request #651 from stianst/master
Rename audit to events
2014-08-28 11:07:02 +02:00
Stian Thorgersen 3bfe3d256e Rename audit to events 2014-08-28 10:56:37 +02:00
Marek Posolda b50ab14a0a Merge pull request #650 from mposolda/master
More Federation & LDAP fixes
2014-08-27 12:41:38 +02:00
mposolda 08c58cf2f2 Upgrade picketlink to 2.7.0.Beta1 2014-08-27 12:22:15 +02:00
mposolda d26543360b KEYCLOAK-646 Fix LDAP authentication when there are commas in the value of bindingProperty 2014-08-27 12:19:23 +02:00
mposolda fb18004c1d KEYCLOAK-643 Handle flows with adding user with existing username or email in federation providers 2014-08-27 12:19:23 +02:00
Stian Thorgersen 49fb452a79 Merge pull request #649 from stianst/master
KEYCLOAK-531 Reduce info level logging
2014-08-27 11:17:56 +02:00
Stian Thorgersen 55bd889a0f KEYCLOAK-531 Reduce info level logging 2014-08-27 11:17:24 +02:00
Stian Thorgersen 269a0dbec1 Merge pull request #643 from ssilvert/KEYCLOAK-642-subsys-wfcontroller
KEYCLOAK-642 Latest WildFly breaks Keycloak Subsystem
2014-08-27 08:19:20 +02:00
Marek Posolda cf51db88e7 Merge pull request #648 from mposolda/master
Federation & LDAP related fixes
2014-08-26 20:43:23 +02:00
mposolda fc0889cd2e KEYCLOAK-644 Searching by email from LDAP doesn't work 2014-08-26 20:24:25 +02:00
mposolda b3b480c25f Display proper error message if LDAP-linked user couldn't be deleted due to read-only mode 2014-08-26 19:10:48 +02:00
mposolda 892fa04130 KEYCLOAK-645 Disable username field when editing user in admin console 2014-08-26 18:04:26 +02:00
Marek Posolda 8d3e51c236 Merge pull request #647 from mposolda/master
Handle exceptions and UI errors when user is read only. Minor sync issue
2014-08-26 13:02:11 +02:00
mposolda fd9d2ba4d5 Handle exceptions and UI errors when user is read only. Some sync issues 2014-08-26 12:54:05 +02:00
Marek Posolda 75bc633a33 Merge pull request #645 from mposolda/master
Fix pagination of searching users
2014-08-25 21:14:56 +02:00
mposolda 3fdb22cb05 Fix pagination of searching users 2014-08-25 21:13:50 +02:00
Marek Posolda f51ba1cb8a Merge pull request #644 from mposolda/master
Docs about sync. Tooltips and minor fixes
2014-08-25 17:19:02 +02:00
mposolda 688f4a07a3 Added docs about sync of users 2014-08-25 17:17:32 +02:00
mposolda 6c7d0f27a7 More tooltips for LDAP and generic federation. Minor fixes 2014-08-25 16:28:52 +02:00
Stan Silvert 1e5ca3062c KEYCLOAK-642 Latest WildFly breaks Keycloak Subsystem 2014-08-22 13:49:57 -04:00
Bill Burke ca97e7ba35 Merge pull request #642 from patriot1burke/master
import console from export
2014-08-21 17:25:16 -04:00
Bill Burke e99afec7ec import console from export 2014-08-21 17:17:09 -04:00
Bill Burke a23853a6bc Merge pull request #641 from patriot1burke/master
bump pom
2014-08-21 10:47:22 -04:00
Bill Burke 7c8edb5d11 bump pom 2014-08-21 10:46:49 -04:00
Bill Burke 83ad045410 Merge pull request #640 from patriot1burke/master
last fixes for rc1
2014-08-20 14:51:14 -04:00
Bill Burke e5d5276135 race 2014-08-20 14:50:28 -04:00
Bill Burke 6f38a02aaa SSL mode docs 2014-08-20 14:37:15 -04:00
Bill Burke 5dd84f1d9a fix AccountService referrer problems 2014-08-20 14:20:59 -04:00
Bill Burke 30147ce25a import doc 2014-08-20 13:32:14 -04:00
Bill Burke dd011f043d fix cors demo 2014-08-20 13:29:09 -04:00
Bill Burke 7dec0319b6 doc ix 2014-08-20 13:26:57 -04:00
Bill Burke 06c14df0f3 Merge pull request #639 from patriot1burke/master
enhancements
2014-08-20 11:56:29 -04:00
Bill Burke 041d0be990 add notification messages 2014-08-20 11:55:59 -04:00
Bill Burke f6a76e673c add federation breadcrums 2014-08-20 11:40:48 -04:00
Bill Burke 47f361a4ab nocache for fed provider list 2014-08-20 11:29:45 -04:00
Bill Burke 6e7924da76 demo fixes 2014-08-20 11:08:40 -04:00
Bill Burke df1a0c03b6 Merge pull request #638 from patriot1burke/master
readme
2014-08-20 08:51:03 -04:00
Bill Burke 971bea8a24 readme again 2014-08-20 08:50:24 -04:00
Bill Burke c8f0a1ab5a readme 2014-08-20 08:49:42 -04:00
Bill Burke 0ae9ac0848 Merge pull request #637 from patriot1burke/master
doc touchup
2014-08-19 15:10:52 -04:00
Bill Burke 3dd52e8b28 doc touchup 2014-08-19 15:10:32 -04:00
Bill Burke 0f6915c615 Merge pull request #636 from patriot1burke/master
fix mongo
2014-08-19 14:49:35 -04:00
Bill Burke 74cd23b331 fix mongo 2014-08-19 14:49:15 -04:00
Bill Burke cc17895ef3 Merge pull request #635 from patriot1burke/master
more minor screen changes
2014-08-19 12:13:24 -04:00
Bill Burke 09ada81b27 more minor screen changes 2014-08-19 12:12:58 -04:00
Bill Burke 75e0fa87c3 Merge pull request #632 from ssilvert/master
Add web-console and http-endpoint default configurations for WildFly
2014-08-18 18:56:02 -04:00
Bill Burke 6628e226e4 Merge pull request #631 from ssilvert/Use-KeycloakDS
By default, the datasource should be KeycloakDS instead of ExampleDS.
2014-08-18 18:55:53 -04:00
Bill Burke 89d47a392b Merge pull request #634 from patriot1burke/master
buncho fixes
2014-08-18 18:55:18 -04:00
Bill Burke c38abb2cfe ? 2014-08-18 18:52:51 -04:00
Bill Burke faf18dfdfd fix cookie parsing problem 2014-08-18 18:36:36 -04:00
Bill Burke 2dc32fb8c9 fix menu error 2014-08-18 18:06:23 -04:00
Bill Burke 2ec029e8e0 Merge pull request #633 from patriot1burke/master
social fixes
2014-08-18 11:56:14 -04:00
Bill Burke 80904209b3 KEYCLOAK-627 2014-08-18 11:55:27 -04:00
Bill Burke 8b1483d7ef docs 2014-08-18 10:48:28 -04:00
Bill Burke bbeff1ef22 Merge remote-tracking branch 'upstream/master' 2014-08-18 10:40:55 -04:00
Stan Silvert aac3c2e0ee Don't block server artifact from being pushed to the repo. 2014-08-15 14:51:38 -04:00
Stan Silvert a240a00983 Add web-console and http-endpoint default configurations for WildFly
build.
2014-08-15 13:43:18 -04:00
Bill Burke c86a6ba3f3 fix admin reset email 2014-08-15 11:46:38 -04:00
Stan Silvert bc301baa1f By default, the datasource should be KeycloakDS instead of ExampleDS. 2014-08-15 08:55:04 -04:00
Bill Burke edbf26f007 Merge pull request #630 from patriot1burke/master
expanded token service coverage
2014-08-14 21:01:26 -04:00
Bill Burke 5dca2a3588 expanded token service coverage 2014-08-14 21:01:05 -04:00
Bill Burke cf5a7d228b Merge pull request #629 from patriot1burke/master
add some breadcrumbs, add app role
2014-08-14 18:47:15 -04:00
Bill Burke f7a7c3ca7b add some breadcrumbs, add app role 2014-08-14 18:46:53 -04:00
Bill Burke 28fcdf0b8f Merge pull request #628 from patriot1burke/master
relative uri problem
2014-08-14 12:00:03 -04:00
Bill Burke c38ec33881 tooltip fixes 2014-08-14 11:59:03 -04:00
Bill Burke cfee00d4c5 fix relative uri problem 2014-08-14 11:01:04 -04:00
Bill Burke 46bf0d78fa Merge pull request #627 from patriot1burke/master
more tooltips
2014-08-13 15:11:28 -04:00
Bill Burke a14be592de more tooltips 2014-08-13 15:11:05 -04:00
Bill Burke 29691a3167 Merge pull request #626 from patriot1burke/master
more tooltips, change password
2014-08-13 12:17:48 -04:00
Bill Burke 517a2b99d7 more tooltips 2014-08-13 12:17:20 -04:00
Bill Burke edf73af508 change password 2014-08-13 10:35:49 -04:00
Bill Burke 4a5ea08a2a Merge pull request #625 from patriot1burke/master
tooltips
2014-08-13 09:42:09 -04:00
Bill Burke 7b86cca649 better tooltip user 2014-08-13 09:40:43 -04:00
Bill Burke c77b7cd7d6 fix required user tooltip 2014-08-13 09:38:56 -04:00
Bill Burke 6b0a87c57a Merge pull request #624 from patriot1burke/master
add js adapter to dist
2014-08-12 18:25:03 -04:00
Bill Burke b1c331c5f3 add js adapter to dist 2014-08-12 18:24:40 -04:00
Bill Burke 7ae342452e Merge pull request #623 from patriot1burke/master
tooltips
2014-08-12 16:31:25 -04:00
Bill Burke 4438aa6606 tooltips 2014-08-12 16:22:26 -04:00
Marek Posolda 8cd8472003 Merge pull request #622 from mposolda/master
Sync admin UI and fixes.
2014-08-12 19:13:50 +02:00
mposolda 687aa78567 Fix issue in sync admin UI 2014-08-12 19:12:05 +02:00
mposolda 8419e5883d Ensure that transaction.isActive() is false after commit or rollback 2014-08-12 18:58:37 +02:00
mposolda 4bac0474c6 Sync UI for generic providers 2014-08-12 18:12:28 +02:00
mposolda f0b66a2241 Admin console UI for sync of users from LDAP. Sync fixes 2014-08-12 18:12:27 +02:00
Bill Burke 51b71e8f20 Merge pull request #621 from patriot1burke/master
refactor UI screens, remove breadcrumbs
2014-08-12 11:09:50 -04:00
Bill Burke 8615515b9a refactor UI screens, remove breadcrumbs 2014-08-12 11:07:39 -04:00
Bill Burke 10cf486d26 Merge pull request #620 from ssilvert/KEYCLOAK-331-ear
KEYCLOAK-331 Fixed NPE when user specifies EAR name instead of WAR in subsystem.
2014-08-12 10:29:46 -04:00
Bill Burke abb1647672 Merge pull request #619 from patriot1burke/master
fix logout
2014-08-12 10:06:44 -04:00
Bill Burke 114c1b95fa fix logout 2014-08-12 10:06:19 -04:00
Stan Silvert 4e88bbc811 KEYCLOAK-331 Fixed NPE when user specifies EAR name instead of WAR in standalone.xml. Also, fixed EAR deployment in general and added EAR example. 2014-08-12 10:03:20 -04:00
Stan Silvert 504a41aec4 KEYCLOAK-331 Fixed NPE when user specifies EAR name instead of WAR in
standalone.xml.  Also, fixed EAR deployment in general and added EAR
example.
2014-08-12 09:58:54 -04:00
Stian Thorgersen e9bf1ef618 Merge pull request #618 from stianst/master
Fix test
2014-08-12 12:14:32 +01:00
Stian Thorgersen 9d6e450c05 Fix test 2014-08-12 12:13:59 +01:00
Stian Thorgersen fb7e95f1e4 Merge pull request #617 from stianst/master
KEYCLOAK-592 Display login form with error message if trying to login wi...
2014-08-12 12:06:39 +01:00
Stian Thorgersen f95418dfc9 KEYCLOAK-592 Display login form with error message if trying to login with social provider where email already exists 2014-08-12 12:06:13 +01:00
Bill Burke 94be235a0f Merge pull request #616 from patriot1burke/master
menu
2014-08-11 17:48:52 -04:00
Bill Burke 100de5a55e menu 2014-08-11 17:47:55 -04:00
Bill Burke 26570de4cd Merge pull request #615 from patriot1burke/master
X-Frame-Options, Content-Security-Policy
2014-08-11 17:45:26 -04:00
Bill Burke 7c97e02715 X-Frame-Options, Content-Security-Policy 2014-08-11 17:45:01 -04:00
Bill Burke e73bdf9d8c Merge pull request #614 from patriot1burke/master
add jpa realm attributes
2014-08-11 12:33:36 -04:00
Bill Burke 8d1ff1d49c add jpa realm attributes 2014-08-11 12:33:17 -04:00
Stian Thorgersen de770d2881 Merge pull request #613 from stianst/master
Added tooltip to realm enabled button
2014-08-11 16:14:14 +01:00
Stian Thorgersen 7f96770089 Added tooltip to realm enabled button 2014-08-11 16:13:38 +01:00
Stian Thorgersen 3f83538fc1 Merge pull request #612 from stianst/master
KEYCLOAK-616 Not require registration to add a new social user
2014-08-11 15:35:54 +01:00
Stian Thorgersen 3040f4e89f KEYCLOAK-616 Not require registration to add a new social user 2014-08-11 15:34:57 +01:00
Marek Posolda c57c264d91 Merge pull request #611 from mposolda/master
Fix transaction handling in KeycloakModelUtils.runJobInTransaction. Star...
2014-08-11 13:53:04 +02:00
mposolda 8ba7559cac Fix transaction handling in KeycloakModelUtils.runJobInTransaction. Start sync tasks for configured federation providers at startup 2014-08-11 13:51:44 +02:00
Marek Posolda c4d5a4138c Merge pull request #610 from mposolda/master
Support for users sync
2014-08-10 23:40:23 +02:00
mposolda d699404ce7 Support for periodic users sync 2014-08-10 23:23:50 +02:00
mposolda ee79747cb6 Sync - first iteration 2014-08-10 23:22:35 +02:00
mposolda 5cb6c4e77c Improve TimerSPI to support cancelling of previously scheduled tasks 2014-08-10 23:17:39 +02:00
Bill Burke 05638a8953 Merge pull request #609 from patriot1burke/master
fixes
2014-08-10 12:29:07 -04:00
Bill Burke 48f7efc97f @NoCache where appropriate 2014-08-10 12:28:43 -04:00
Bill Burke 9aa6b4cbfa optimize imports 2014-08-10 12:17:45 -04:00
Bill Burke cae0a7628d use SecureRandom for totp 2014-08-10 12:12:24 -04:00
Bill Burke 82e29dfcb3 Merge pull request #608 from patriot1burke/master
jiras
2014-08-10 11:50:42 -04:00
Bill Burke ad94b94833 enlarge URL html input 2014-08-10 11:49:58 -04:00
Bill Burke 687e497455 test searchForUserByAttributes 2014-08-10 11:36:02 -04:00
Bill Burke 67f31648a6 Merge pull request #572 from vibe13/duplicated-version
Remove warning from Maven log4j:log4j:jar -> duplicate declaration
2014-08-10 11:04:51 -04:00
Bill Burke d332851a75 Merge pull request #606 from alarikmyrin/KEYCLOAK-621
KEYCLOAK-621 fix searchForUserByAttributes method
2014-08-10 11:02:08 -04:00
Bill Burke 4a18a32cfc Merge pull request #607 from patriot1burke/master
change logout behavior
2014-08-10 09:09:32 -04:00
Alarik Myrin 428cd54a81 KEYCLOAK-621 fix searchForUserByAttributes method so that it works and is not subject to SQL injection 2014-08-09 13:59:20 -04:00
Bill Burke dc4e8603d7 change logout behavior 2014-08-08 18:33:37 -04:00
Marek Posolda b96f8aef6d Merge pull request #605 from mposolda/master
LDAP testing and improvements
2014-08-08 12:24:39 +02:00
mposolda dc50c312cb Configurable if pagination and connectionPooling are supported in LDAP 2014-08-08 12:09:08 +02:00
mposolda 1f12a2d67b Adding LDAPUtils. Bit refactoring LDAP test for easier testing with various servers 2014-08-08 10:40:34 +02:00
Marek Posolda a2bef7dbbe Merge pull request #604 from mposolda/master
Fix testsuite hangs on MySQL and PostgreSQL due to uncommited transactio...
2014-08-07 20:40:12 +02:00
mposolda c6af13c8cc Fix testsuite hangs on MySQL and PostgreSQL due to uncommited transactions 2014-08-07 20:38:20 +02:00
Marek Posolda 5be5f6475f Merge pull request #603 from mposolda/master
Fix adding social link in mongo. Fixed export/import of federationProvid...
2014-08-07 17:39:56 +02:00
mposolda 5673fb34b1 Fix adding social link in mongo. Fixed export/import of federationProviders. Enhanced ExportImportTest 2014-08-07 17:33:48 +02:00
Marek Posolda 5214fe2a55 Merge pull request #602 from mposolda/master
Users not registered with FederationProvider during import, Update docs for database setup
2014-08-07 13:05:23 +02:00
mposolda 76db33829b KEYCLOAK-600 Users shouldn't be registered with Federation Provider on an import 2014-08-07 12:38:56 +02:00
mposolda 746da8f270 Possibility to specify hibernate dialect even if datasource is used 2014-08-07 12:27:12 +02:00
mposolda f8667cdb38 Update documentations for JPA and Mongo 2014-08-07 12:23:46 +02:00
Marek Posolda 1ec4fe921d Merge pull request #601 from mposolda/master
KEYCLOAK-618 Remove org.bouncycastle from jboss-modules-structure.xml as...
2014-08-07 10:34:48 +02:00
mposolda 915701106c KEYCLOAK-618 Remove org.bouncycastle from jboss-modules-structure.xml as it's in auth-server.war 2014-08-07 10:32:26 +02:00
Bill Burke 2309e6f040 Merge pull request #600 from patriot1burke/master
delete fed provider
2014-08-06 20:49:25 -04:00
Bill Burke 839d823edd change delete msg 2014-08-06 20:48:48 -04:00
Bill Burke 99e6f0edad delete fed provider 2014-08-06 20:38:30 -04:00
Bill Burke bb138bd6e4 Merge pull request #599 from patriot1burke/master
KEYCLOAK-547
2014-08-06 19:16:19 -04:00
Bill Burke 32a19563a5 KEYCLOAK-547 2014-08-06 19:15:52 -04:00
Bill Burke 3b65127399 Merge pull request #598 from patriot1burke/master
cookie cache off
2014-08-06 18:04:36 -04:00
Bill Burke c17a5823e9 cookie cache off 2014-08-06 18:01:16 -04:00
Bill Burke c9e88c944a Merge pull request #597 from patriot1burke/master
pom description
2014-08-06 17:50:25 -04:00
Bill Burke b93cf4868c pom description 2014-08-06 17:50:01 -04:00
Bill Burke 53ac88ca26 Merge pull request #596 from patriot1burke/master
version
2014-08-06 15:45:15 -04:00
Bill Burke aff32f69bb version 2014-08-06 15:44:50 -04:00
Bill Burke 4fcf11d0db Merge pull request #595 from patriot1burke/master
bump version
2014-08-06 09:00:47 -04:00
Bill Burke e04af84ac0 bump version 2014-08-06 09:00:23 -04:00
Bill Burke 965c44a43d Merge pull request #594 from patriot1burke/master
beta-4 fixes
2014-08-05 20:58:28 -04:00
Bill Burke 905061e2b7 bump version 2014-08-05 20:52:50 -04:00
Bill Burke 45df3087f2 fix aerogear 2014-08-05 20:45:31 -04:00
Bill Burke f9f53a3355 docbook change 2014-08-05 20:31:20 -04:00
Bill Burke ab08ac8ad4 Merge remote-tracking branch 'upstream/master' 2014-08-05 20:29:02 -04:00
Bill Burke 12c9475bfc general settings split up 2014-08-05 20:26:29 -04:00
Bill Burke a0d7fc12db all claims for app 2014-08-05 19:46:55 -04:00
Bill Burke 5b5fea347a improved oauth login/grant 2014-08-05 19:36:19 -04:00
Bill Burke d049007412 delete app/realm/client buttons 2014-08-05 17:34:23 -04:00
Bill Burke cc14a3b288 rename token settings menu to timeout settings 2014-08-05 17:28:20 -04:00
Bill Burke bcd3eeda49 product-portal example logout fix 2014-08-05 17:20:01 -04:00
Bill Burke 992b365eab choose realm 2014-08-05 17:18:11 -04:00
Bill Burke 3882cc4aa8 fix console session logoutAll 2014-08-05 17:16:46 -04:00
Bill Burke 38bd79ab88 filter out unconfigured example files 2014-08-05 16:53:10 -04:00
Bill Burke 790fd1d94d fix cors example 2014-08-05 16:45:21 -04:00
Bill Burke 19e1ddff1d logging 2014-08-05 16:04:13 -04:00
Marek Posolda 0bbc26bd0b Merge pull request #593 from mposolda/db-fix
Updating documentation for export/import
2014-08-05 20:30:05 +02:00
mposolda 1f3db436d8 Updating documentation for export/import 2014-08-05 20:28:53 +02:00
Marek Posolda 7ac663bd5f Merge pull request #592 from mposolda/db-fix
Fixing mssql
2014-08-05 18:30:55 +02:00
mposolda 53fbceb49a Fixing mssql 2014-08-05 18:25:54 +02:00
Marek Posolda 1159dc091d Merge pull request #591 from mposolda/db-fix
Fixing oracle
2014-08-05 15:55:53 +02:00
mposolda 38c0b4ad65 Fixing oracle 2014-08-05 15:45:28 +02:00
Marek Posolda f4f563d570 Merge pull request #590 from mposolda/master
Fix typo in UserFederationProvider
2014-08-05 15:07:42 +02:00
mposolda 550ba16a09 Fix deleting users on mongo 2014-08-05 14:36:53 +02:00
mposolda 0289f5dff9 Fix typo in UserFederationProvider 2014-08-05 13:31:35 +02:00
Bill Burke ea0ceeb65d Merge pull request #589 from patriot1burke/master
app full scope
2014-08-04 16:26:51 -04:00
Bill Burke 3746bf28a1 migration doc 2014-08-04 16:26:13 -04:00
Bill Burke a497c69758 relative logout 2014-08-04 16:17:35 -04:00
Bill Burke 731d75c756 app full scope by default 2014-08-04 16:04:10 -04:00
Marek Posolda 982ba5ab90 Merge pull request #588 from mposolda/master
Adding property to configure if userAccountControls should be updated in...
2014-08-04 21:35:02 +02:00
mposolda c2e2a46025 Adding property to configure if userAccountControls should be updated in Active Directory after user set his password 2014-08-04 21:32:56 +02:00
Bill Burke 8430fb0ed3 Merge pull request #587 from patriot1burke/master
docs
2014-08-04 12:28:32 -04:00
Bill Burke 9a829a38b1 edti migration docs 2014-08-04 12:28:07 -04:00
Bill Burke 04ec750157 federation docs 2014-08-04 12:25:11 -04:00
Marek Posolda 3655db2a30 Merge pull request #586 from mposolda/master
Ensure that displayName is persisted. Add 'user' to ActiveDirectory clas...
2014-08-04 16:43:41 +02:00
mposolda 5edb84ccfb Ensure that displayName is persisted. Add 'user' to ActiveDirectory classes 2014-08-04 16:42:48 +02:00
Marek Posolda 95e2da9c9e Merge pull request #585 from mposolda/master
Upgrade to latest picketlink. Fix LDAP configuration according to that
2014-08-04 14:58:29 +02:00
mposolda 6cb1eb41cf Update mongo entities 2014-08-04 14:51:08 +02:00
mposolda 46a0caf2e0 Upgrade to latest picketlink. Fix LDAP configuration according to that 2014-08-04 13:58:52 +02:00
Bill Burke d96b660686 Merge pull request #584 from patriot1burke/master
fix fed example
2014-08-03 11:04:21 -04:00
Bill Burke ae66b1b88e fix view all users 2014-08-03 11:03:39 -04:00
Bill Burke 60a564dcfd fix fed example 2014-08-03 10:53:37 -04:00
Bill Burke 69656d2775 Merge pull request #583 from patriot1burke/master
delete auth prov example
2014-08-02 22:19:59 -04:00
Bill Burke 24415f2186 delete auth prov example 2014-08-02 22:19:19 -04:00
Bill Burke 0ae3eafe10 Merge pull request #582 from patriot1burke/master
fed example
2014-08-02 22:18:47 -04:00
Bill Burke 6cf708f6e1 fed exampe 2014-08-02 22:18:17 -04:00
Bill Burke f5a626006c Merge pull request #581 from patriot1burke/master
remove AuthenticationProvider/Link
2014-08-01 18:06:18 -04:00
Bill Burke 101a72cd65 remove AuthenticationProvider/Link 2014-08-01 18:03:48 -04:00
Bill Burke 312429cb88 Merge pull request #580 from patriot1burke/master
add HttpServletRequest.authenticate() test
2014-08-01 15:50:40 -04:00
Bill Burke c9851f1c05 add HttpServletRequest.authenticate() test 2014-08-01 15:50:20 -04:00
Bill Burke 73b7fe6169 Merge pull request #579 from patriot1burke/master
remote token validation
2014-08-01 13:34:11 -04:00
Bill Burke d1c5c55a61 switch to a get 2014-08-01 13:28:17 -04:00
Bill Burke bdc31d9459 Merge remote-tracking branch 'upstream/master' 2014-08-01 13:18:46 -04:00
Bill Burke f08c42a37e token validation 2014-08-01 13:18:32 -04:00
Stian Thorgersen 8fbd39934f Merge pull request #578 from stianst/master
Allow private addresses to use http with ssl-required=external
2014-08-01 15:06:15 +01:00
Stian Thorgersen c460630cf8 Allow private addresses to use http with ssl-required=external 2014-08-01 15:05:45 +01:00
Stian Thorgersen 335bc87ad8 Merge pull request #577 from stianst/master
KEYCLOAK-591 Require SSL for all external requests by default
2014-08-01 13:53:04 +01:00
Stian Thorgersen 6cbeeb1b1a KEYCLOAK-591 Require SSL for all external requests by default 2014-08-01 13:52:04 +01:00
Bill Burke 47c9f1439d Merge pull request #576 from patriot1burke/master
maxResults
2014-07-31 17:41:58 -04:00
Bill Burke 64589bc807 maxResults 2014-07-31 17:41:38 -04:00
Bill Burke 2eae9c17a4 Merge pull request #575 from patriot1burke/master
ldap edit mode
2014-07-31 17:31:46 -04:00
Bill Burke 9f6c206078 ldap edit mode 2014-07-31 17:28:48 -04:00
Bill Burke 2460eecd75 Merge pull request #574 from patriot1burke/master
federation registeration
2014-07-31 16:02:52 -04:00
Bill Burke a084695978 support registration ldap 2014-07-31 15:22:20 -04:00
Bill Burke 705da88daa fix cache setup 2014-07-31 14:05:23 -04:00
Bill Burke ce85a42ecf Merge pull request #573 from patriot1burke/master
fed ui
2014-07-31 13:14:45 -04:00
Bill Burke 2990b75faa Merge remote-tracking branch 'upstream/master' 2014-07-31 13:14:05 -04:00
Bill Burke 94c06f3f5d fed ui 2014-07-31 13:13:48 -04:00
Bill Burke b72a7db6fe federation display name 2014-07-31 10:51:04 -04:00
Andrea Vibelli 9e4086e501 Remove warning from Maven log4j:log4j:jar -> duplicate declaration 2014-07-31 11:06:24 +02:00
Bill Burke b960f18f4e Merge pull request #571 from patriot1burke/master
federation ui
2014-07-30 22:53:10 -04:00
Bill Burke d0dc75c06f federation ui 2014-07-30 22:52:39 -04:00
Bill Burke 13a5eccaf8 Merge pull request #570 from patriot1burke/master
federation refactor
2014-07-30 16:06:57 -04:00
Bill Burke 898195e1da Merge remote-tracking branch 'upstream/master' 2014-07-30 16:02:09 -04:00
Bill Burke 8ea0d19d2f federation refactor 2014-07-30 16:01:54 -04:00
Stian Thorgersen 465318b352 Merge pull request #569 from stianst/master
KEYCLOAK-545 Stop NPE if no client_secret is specified or bearer-only ap...
2014-07-30 16:42:26 +01:00
Stian Thorgersen fa01d53f9e KEYCLOAK-545 Stop NPE if no client_secret is specified or bearer-only application is used for grants/access 2014-07-30 16:41:07 +01:00
Stian Thorgersen ba8fe1ddaf Merge pull request #568 from stianst/master
KEYCLOAK-562 Cache theme instances
2014-07-30 16:10:41 +01:00
Stian Thorgersen 50bc53d673 KEYCLOAK-562 Cache theme instances 2014-07-30 16:06:08 +01:00
Stian Thorgersen d682701232 Merge pull request #567 from stianst/master
Added login_hint to keycloak.js
2014-07-30 14:27:40 +01:00
Stian Thorgersen 544883ca9f Added login_hint to keycloak.js 2014-07-30 14:27:14 +01:00
Stian Thorgersen 54a7761e15 Merge pull request #566 from stianst/master
Updated admin endpoints and console to use oauth client name/clientId
2014-07-30 14:18:45 +01:00
Stian Thorgersen ed51b4e1ea Deleted old hybrid model 2014-07-30 14:13:16 +01:00
Stian Thorgersen fcc4781e3a Updated admin endpoints and console to use oauth client name/clientId to retrieve a oauth client 2014-07-30 14:10:25 +01:00
Stian Thorgersen 24b5bd6862 Merge pull request #565 from stianst/master
KEYCLOAK-581 Add login_hint query param to login
2014-07-30 13:48:17 +01:00
Stian Thorgersen 614c718304 KEYCLOAK-581 Add login_hint query param to login 2014-07-30 13:43:46 +01:00
Stian Thorgersen e2ce33a86a Merge pull request #564 from stianst/master
Admin REST client
2014-07-30 13:26:04 +01:00
Rodrigo Sasaki e338f1af15 Admin REST client 2014-07-30 13:24:44 +01:00
Stian Thorgersen eefc5ed1d7 Merge pull request #563 from lfryc/KEYCLOAK-588
KEYCLOAK-588 retrieve window.location.origin in InternetExplorer-compatible way
2014-07-30 12:15:16 +01:00
Lukas Fryc 7694b130e6 KEYCLOAK-588 retrieve window.location.origin in InternetExplorer-compatible way 2014-07-30 12:47:52 +02:00
Stian Thorgersen 32ad7271f3 Merge pull request #562 from stianst/access-code
Fix test
2014-07-30 09:47:35 +01:00
Stian Thorgersen 2b012ff238 Fix test 2014-07-30 09:47:16 +01:00
Stian Thorgersen 1bd219ed40 Merge pull request #561 from stianst/access-code
Added ClientSessionModel to UserSessionProvider
2014-07-29 16:18:28 +01:00
Stian Thorgersen 02a59812e6 Added ClientSessionModel to UserSessionProvider 2014-07-29 16:10:41 +01:00
Stian Thorgersen 7f4849e165 Merge pull request #560 from stianst/demo-non-localhost
KEYCLOAK-579 Use relative urls in examples
2014-07-28 10:48:30 +01:00
Stian Thorgersen 628c7dd92a KEYCLOAK-579 Use relative urls in examples 2014-07-28 10:41:21 +01:00
Davide Ungari 5764ad84e9 Fix equals huge error, too much Javascript lately 2014-07-27 10:02:41 +02:00
Davide Ungari f3fde4a8df Upgrade to tomcat.7.0.54 2014-07-27 10:01:02 +02:00
Davide Ungari 983ccdd121 Merge remote-tracking branch 'upstream/master' 2014-07-26 11:27:08 +02:00
Davide Ungari 73ed22c52c logout 2014-07-26 11:25:27 +02:00
Bill Burke bace16bac6 Merge pull request #559 from patriot1burke/master
federation iteration 2
2014-07-25 21:06:04 -04:00
Bill Burke 3bb0842eae federation iteration 2 2014-07-25 21:05:45 -04:00
Bill Burke a6b38397ea Merge pull request #558 from patriot1burke/master
rename classes
2014-07-25 10:45:22 -04:00
Bill Burke c63467c79f Merge remote-tracking branch 'upstream/master' 2014-07-25 10:41:06 -04:00
Bill Burke b1cd37814a rename 2014-07-25 10:40:46 -04:00
Stian Thorgersen 07d10ee583 Merge pull request #557 from stianst/access-code
KEYCLOAK-570 Add use-resource-role-mappings to WildFly installation
2014-07-25 11:54:10 +01:00
Stian Thorgersen 614bee3061 KEYCLOAK-570 Add use-resource-role-mappings to WildFly installation 2014-07-25 11:53:10 +01:00
Bill Burke 81dfea4052 Merge pull request #556 from patriot1burke/master
rename FederationProvider to UserFederationProvider
2014-07-24 11:11:45 -04:00
Bill Burke 1b14444eba rename FederationProvider to UserFederationProvider 2014-07-24 11:11:21 -04:00
Stian Thorgersen 245d83adce Merge pull request #555 from stianst/master
Added test to make sure password is verified with totp login
2014-07-24 14:15:34 +01:00
Stian Thorgersen b5835fc232 Added test to make sure password is verified with totp login 2014-07-24 14:15:02 +01:00
Stian Thorgersen 8a54f133ba Merge pull request #554 from stianst/master
Moved audit/tests and model/tests to testsuite
2014-07-24 13:50:15 +01:00
Stian Thorgersen 511cc483cb Moved audit/tests and model/tests to testsuite 2014-07-24 13:49:15 +01:00
Bill Burke 6e18a16f78 Merge pull request #553 from patriot1burke/master
Federation iteration 1
2014-07-23 17:08:00 -04:00
Bill Burke 43d08f2d05 federation iteration 1 complete 2014-07-23 17:05:49 -04:00
Bill Burke 171e9b1ce9 Merge remote-tracking branch 'upstream/master' 2014-07-23 15:10:48 -04:00
Bill Burke eec582e704 merge 2014-07-23 15:10:36 -04:00
Stian Thorgersen 4b05feb6d6 Merge pull request #552 from stianst/access-code
Updates to AccessCode
2014-07-23 16:01:38 +01:00
Stian Thorgersen d6f5bf6cde Moved rememberMe, usernameUsed fields from AccessCode to UserSessions. Change AccessCode to have a single action instead of a list of required actions, also used action for codes that needs user to grant permissions first. Finally removed expiration time on access code and use timestamp directly 2014-07-23 15:58:09 +01:00
Bill Burke f1d72d0b6d fed 2 2014-07-23 10:42:18 -04:00
Bill Burke 148d494905 federation iteration 2014-07-23 10:21:25 -04:00
Stian Thorgersen 38b575d91b Merge pull request #550 from mposolda/master
README update
2014-07-23 13:31:41 +01:00
mposolda baf99a2280 README update 2014-07-23 14:01:24 +02:00
Stian Thorgersen 1d80b87bcc Merge pull request #549 from stianst/master
Fix parent relative-path in server-all and server-min
2014-07-22 16:55:51 +01:00
Stian Thorgersen 84754c47d3 Fix parent relative-path in server-all and server-min 2014-07-22 16:55:33 +01:00
Stian Thorgersen 64b8a990f9 Merge pull request #548 from stianst/master
KEYCLOAK-567 Added server-dep-min and server-dep-all poms
2014-07-22 14:11:05 +01:00
Stian Thorgersen 0580c2223b KEYCLOAK-567 Added server-dep-min and server-dep-all poms 2014-07-22 14:10:38 +01:00
Stian Thorgersen 824aed773b Merge pull request #547 from stianst/jpa-fix
Add jboss.as.jpa.managed=false to persistence.xml
2014-07-22 10:08:24 +01:00
Stian Thorgersen 9164e69d49 Add jboss.as.jpa.managed=false to persistence.xml 2014-07-22 09:40:52 +01:00
Stian Thorgersen 670dc39d4f Merge pull request #546 from stianst/access-code
Remove access token from access code, and create token when code is exchanged for token
2014-07-22 09:37:54 +01:00
Stian Thorgersen b196d0dded Remove access token from access code, and create token when code is exchanged for token 2014-07-22 09:37:21 +01:00
Stian Thorgersen bfd62b0807 Merge pull request #545 from mposolda/master
Fix MySQL and PostgreSQL. More DB schema refactoring
2014-07-22 09:10:52 +01:00
mposolda 3514d5cd78 Fix MySQL and PostgreSQL testsuite (was caused by uncommited transaction) 2014-07-22 07:53:05 +02:00
mposolda b3b46339a4 More DB schema refactoring. Ensure that all columns are named in code 2014-07-22 07:53:05 +02:00
Stian Thorgersen 9ff4947abd Merge pull request #540 from mposolda/master
Update DB profiles. Fix ExportImportTest to not clash with other tests
2014-07-21 14:18:04 +01:00
Stian Thorgersen 469eb77486 Merge pull request #544 from stianst/master
KEYCLOAK-569 Check application roles for scope
2014-07-21 13:52:43 +01:00
Stian Thorgersen 213b685b43 KEYCLOAK-569 Check application roles for scope 2014-07-21 13:50:27 +01:00
mposolda 42df327104 Update DB profiles. Fix ExportImportTest to not clash with other tests 2014-07-21 08:48:25 +02:00
Bill Burke d2b42e3843 Merge pull request #542 from patriot1burke/master
remove hack comment
2014-07-18 12:07:51 -04:00
Bill Burke b999c1e5b1 remove hack comment 2014-07-18 12:07:30 -04:00
Bill Burke 2ecf696a12 Merge pull request #541 from patriot1burke/master
cache config and cache docs
2014-07-18 11:48:54 -04:00
Bill Burke 063a63445a keycloak-json fix 2014-07-18 11:45:47 -04:00
Bill Burke b84bdcf464 cache config 2014-07-18 11:43:44 -04:00
Bill Burke f275ecf6d5 cache settings 2014-07-18 11:30:10 -04:00
Stian Thorgersen b241920802 Merge pull request #539 from stianst/master
Updated aerogear-ups integration readme
2014-07-18 12:14:53 +01:00
Stian Thorgersen dcd1406a27 Updated aerogear-ups integration readme 2014-07-18 12:14:29 +01:00
Stian Thorgersen d2d408e223 Merge pull request #538 from stianst/master
Added profile for building AeroGear project-integrations for WildFly
2014-07-18 12:10:27 +01:00
Stian Thorgersen 9699d8aa82 Added profile for building AeroGear project-integrations for WildFly 2014-07-18 12:09:54 +01:00
Stian Thorgersen 6d8d9107c6 Merge pull request #537 from stianst/master
Configure db in keycloak-server.json
2014-07-18 11:35:33 +01:00
Stian Thorgersen fb8483dc56 Added support to specify dialect for JPA 2014-07-18 11:32:09 +01:00
Stian Thorgersen 85621bdd9f KEYCLOAK-566 Configure db in keycloak-server.json instead of persistence.xml 2014-07-18 11:21:52 +01:00
Bill Burke 573f7fc1fb Merge pull request #535 from mposolda/master
Export/import improvements and fixes
2014-07-17 16:34:39 -04:00
Bill Burke 14af840c3a Merge pull request #536 from patriot1burke/master
realmId and rroleId
2014-07-17 16:34:27 -04:00
Bill Burke aa2d1bcc93 db schema 2014-07-17 16:32:36 -04:00
Bill Burke 20cde9cd00 realmId and roleId used in User and user relationships 2014-07-17 15:41:02 -04:00
mposolda 3dff4afe83 Export/import improvements and fixes 2014-07-17 21:31:33 +02:00
Bill Burke 3edce7f580 named queries and roleId in RoleMapping 2014-07-17 15:20:56 -04:00
Stian Thorgersen 35d601d795 Merge pull request #534 from stianst/master
Removed long ids and replaced with composite ids
2014-07-17 11:57:56 +01:00
Stian Thorgersen f00957ec3a Commented out test in ExportImportTest that breakes the other tests 2014-07-17 11:57:33 +01:00
Stian Thorgersen 46c04561ff Removed long ids and replaced with composite ids 2014-07-17 11:16:15 +01:00
Stian Thorgersen 9abe357754 Merge pull request #533 from mposolda/master
Added method UserProvider.getUsersCount(). Refactor export-import witth users pagination
2014-07-17 10:50:52 +01:00
mposolda 3c99350247 Fix testsuite to use mongo for realms,users and audit when keycloak.realm.provider=mongo 2014-07-17 11:05:51 +02:00
mposolda b041f2a857 Added method UserProvider.getUsersCount(). Refactor export-import with users pagination available 2014-07-17 10:15:13 +02:00
mposolda 0a15f873af Minor improvement in AbstractKeycloakRule.stopServer() 2014-07-17 10:14:35 +02:00
Bill Burke 08b0aebe03 Merge pull request #532 from patriot1burke/master
jpa schema changes
2014-07-16 19:38:01 -04:00
Bill Burke a323fe7992 schema changes 2014-07-16 19:34:54 -04:00
Bill Burke 1963e94e33 use long for primary key 2014-07-16 17:11:59 -04:00
Bill Burke 7437af0131 Merge pull request #530 from ssilvert/master
Rename and update XSD to comply with WildFly testsuite.
2014-07-16 15:31:56 -04:00
Bill Burke 60a1fc3020 Merge pull request #531 from mposolda/master
Fix ExportImportTest on som envs like windows
2014-07-16 15:31:45 -04:00
mposolda 8714193c97 Fix ExportImportTest to pass on windows 2014-07-16 20:00:18 +02:00
Stan Silvert a61733cf47 Rename and update XSD to comply with WildFly testsuite. 2014-07-16 13:44:57 -04:00
mposolda 1aff8af336 Enable ExportImportTest 2014-07-16 19:43:47 +02:00
Stian Thorgersen c21be01e97 Merge pull request #529 from stianst/master
KEYCLOAK-435 Added pagination support for users
2014-07-16 18:04:36 +01:00
Stian Thorgersen 72d240a57e KEYCLOAK-435 Added pagination support for users 2014-07-16 17:54:11 +01:00
Stian Thorgersen 83769b3d52 Merge pull request #528 from stianst/master
Fix redirect-loop in keycloak.js
2014-07-16 17:39:15 +01:00
Stian Thorgersen 1a5c2365a1 Fix redirect-loop in keycloak.js 2014-07-16 17:38:56 +01:00
Bill Burke 87e40f1820 Merge pull request #527 from patriot1burke/master
move credential validation to UserProvider
2014-07-16 12:08:50 -04:00
Bill Burke 8fbfba907b Merge remote-tracking branch 'upstream/master' 2014-07-16 12:05:31 -04:00
Bill Burke f342a8c7a3 move credential validation to UserProvider 2014-07-16 12:05:15 -04:00
Stian Thorgersen 866715b752 Merge pull request #526 from stianst/master
KEYCLOAK-559 If session iframe is enabled, check this before doing a log...
2014-07-16 10:48:14 +01:00
Stian Thorgersen e0ec121012 KEYCLOAK-559 If session iframe is enabled, check this before doing a login if onload is check-sso 2014-07-16 10:47:42 +01:00
Stian Thorgersen 63ff5736a2 Merge pull request #525 from stianst/mysql-5.1-fix
KEYCLOAK-554 Fix for MySQL 5.1. Set length of keys to 36 for uuid's or 200 for others
2014-07-16 09:52:18 +01:00
Stian Thorgersen 3451778f48 KEYCLOAK-554 Fix for MySQL 5.1. Set length of keys to 36 for uuid's or 200 for others 2014-07-16 09:51:31 +01:00
Bill Burke e4b3007ce2 Merge pull request #524 from patriot1burke/master
user provider split
2014-07-15 15:45:30 -04:00
Bill Burke a5593469ae rename ModelProvider->RealmProvider 2014-07-15 15:44:50 -04:00
Bill Burke 484a4c1454 user provider refactor complete 2014-07-15 15:25:06 -04:00
Bill Burke 09a336c708 Merge pull request #523 from mposolda/master
Export/import into representations
2014-07-15 12:14:11 -04:00
Bill Burke 4ac5fb08e3 Merge remote-tracking branch 'upstream/master' 2014-07-15 12:11:24 -04:00
Bill Burke ff86bdc35f userprovider split 2014-07-15 12:11:12 -04:00
mposolda 726ce08700 More cleanup and removed export-import-impl module 2014-07-15 16:43:55 +02:00
mposolda c14840a4c0 More cleanup after rebase 2014-07-15 14:44:38 +02:00
mposolda 24a492ffe0 Export/import refactoring to use same representation as admin endpoints 2014-07-15 05:35:24 +02:00
Stian Thorgersen c4ff4e030a Merge pull request #522 from stianst/master
Removed dep on model-jpa from export-import-impl
2014-07-14 17:31:55 +01:00
Stian Thorgersen 7244944879 Removed dep on model-jpa from export-import-impl 2014-07-14 17:31:35 +01:00
Stian Thorgersen 1f2db2c049 Merge pull request #521 from stianst/master
KEYCLOAK-556 NullPointerException in project-integrations example on Wil...
2014-07-14 17:08:30 +01:00
Stian Thorgersen d6e8b1ba2c KEYCLOAK-556 NullPointerException in project-integrations example on WildFly 2014-07-14 17:07:38 +01:00
Stian Thorgersen 7f0a3eebfb Merge pull request #520 from stianst/master
Fix project-integrations/aerogear-ups
2014-07-14 16:38:58 +01:00
Stian Thorgersen 5d0345c922 Fix project-integrations/aerogear-ups 2014-07-14 16:38:39 +01:00
Bill Burke 99a041158c Merge pull request #519 from patriot1burke/master
TM.enlistAfterCompletion
2014-07-14 11:37:16 -04:00
Bill Burke 8f7efd5b67 merge 2014-07-14 11:36:57 -04:00
Bill Burke d2c27daa16 changes 2014-07-14 11:31:25 -04:00
Stian Thorgersen 2d2041db5e Merge pull request #518 from stianst/master
Lazy load connections
2014-07-14 16:29:12 +01:00
Stian Thorgersen e3f260c57f Added lazy load to connection factories, to make sure we only try to connect to JPA/Mongo when used 2014-07-14 16:28:47 +01:00
Stian Thorgersen 8113c3f05e Fixes to persistence.xml 2014-07-14 15:55:26 +01:00
Stian Thorgersen e3bc15a4d9 Merge pull request #516 from stianst/master
KEYCLOAK-512 Pagination support for sessions
2014-07-14 12:01:56 +01:00
Stian Thorgersen 3f68180ee7 KEYCLOAK-512 Pagination support for sessions 2014-07-14 11:49:59 +01:00
Stian Thorgersen 6bb6dc0aaf Merge pull request #515 from stianst/master
Added JPA connection provider and added basic support for multiple trans...
2014-07-14 10:13:45 +01:00
Stian Thorgersen d625fb014c Added JPA connection provider and added basic support for multiple transactions to KeycloakSession 2014-07-14 10:10:03 +01:00
Bill Burke 8cc7676335 Merge pull request #514 from patriot1burke/master
enlist
2014-07-11 19:44:01 -04:00
Bill Burke 626cecba95 enlist 2014-07-11 19:43:37 -04:00
Bill Burke 65348cd5e7 Merge pull request #513 from patriot1burke/master
session transaction
2014-07-11 19:38:58 -04:00
Bill Burke 5f5316fbdc session transaction 2014-07-11 19:29:11 -04:00
Stian Thorgersen 011bac7a1e Merge pull request #512 from stianst/master
Started UserSessionProvider
2014-07-10 16:50:54 +01:00
Stian Thorgersen 86671a2354 Started UserSessionProvider 2014-07-10 16:48:25 +01:00
Bill Burke 8fac39fffa Merge pull request #511 from ssilvert/master
In WF subsystem, make WildFly dependencies provided scope.
2014-07-09 13:54:24 -04:00
Stan Silvert a2710e01da In WF subsystem, make WildFly dependencies provided scope. 2014-07-09 13:33:14 -04:00
Stian Thorgersen 38abcd4a90 Merge pull request #510 from stianst/master
Revert JPA model provider
2014-07-09 15:44:05 +01:00
Stian Thorgersen 62dd6fbc6b Revert JPA model provider 2014-07-09 15:40:23 +01:00
Stian Thorgersen 75c56a2a7c Merge pull request #509 from stianst/master
KEYCLOAK-553 Added minified keycloak.js
2014-07-09 14:17:36 +01:00
Stian Thorgersen 7491b1c369 KEYCLOAK-553 Added minified keycloak.js 2014-07-09 12:23:29 +01:00
Stian Thorgersen a3cca7424a Merge pull request #508 from stianst/master
Removed JPA model provider
2014-07-08 15:36:33 +01:00
Stian Thorgersen 387aed6269 Removed JPA model provider 2014-07-08 15:35:49 +01:00
Stian Thorgersen 20bf888d73 Merge pull request #507 from stianst/master
Removed model methods from KeycloakSession
2014-07-08 15:28:13 +01:00
Stian Thorgersen ad6d52cb0f Removed model methods from KeycloakSession 2014-07-08 15:27:42 +01:00
Stian Thorgersen 8dc293f629 Removed removeAllData from model 2014-07-08 15:27:42 +01:00
Bill Burke de8819aae3 Merge pull request #506 from ssilvert/master
KEYCLOAK-555 Subsystem needs template for new WildFly build.
2014-07-08 10:02:10 -04:00
Stan Silvert e98ced5d0f KEYCLOAK-555 Subsystem needs template for new WildFly build. 2014-07-08 09:39:44 -04:00
Stian Thorgersen 6775af302a Merge pull request #505 from stianst/master
Added hybrid model provider with jpa stores
2014-07-08 12:04:36 +01:00
Stian Thorgersen 621cae61b6 Added hybrid model provider with jpa stores 2014-07-08 12:04:09 +01:00
Bill Burke 922a8f7eef Merge pull request #504 from patriot1burke/master
fix json file
2014-07-07 18:51:59 -04:00
Bill Burke 48a0e564b9 fix json file 2014-07-07 18:51:38 -04:00
Bill Burke 0758d89a59 Merge pull request #502 from mposolda/master
Changes in representations - adding role mappings under user representat...
2014-07-07 18:41:42 -04:00
Bill Burke e94b6acd02 Merge pull request #503 from patriot1burke/master
admin rest api test
2014-07-07 18:38:08 -04:00
Bill Burke a1beff7d3d admin rest api test 2014-07-07 18:37:30 -04:00
mposolda ffc30b4c03 Changes in representations - adding role mappings under user representation 2014-07-07 22:48:53 +02:00
Bill Burke 6d824231e9 Merge pull request #501 from patriot1burke/master
fix delete when cache is on
2014-07-07 15:04:18 -04:00
Bill Burke 060a90197e Merge remote-tracking branch 'upstream/master' 2014-07-07 15:00:05 -04:00
Bill Burke df7aac01dd fix delete realm 2014-07-07 14:59:51 -04:00
Bill Burke 69b00d859b Merge pull request #497 from mposolda/performance
More performance testing stuff
2014-07-07 14:59:41 -04:00
mposolda 9c88979040 Added UsersJob for generic job related to users. Support for sync/async jobs. Configurable host/port 2014-07-07 20:31:43 +02:00
Bill Burke bda218af07 Merge pull request #500 from patriot1burke/master
configurable hash iterations
2014-07-07 12:12:25 -04:00
Bill Burke 15d7568792 configurable hash iterations 2014-07-07 12:11:45 -04:00
Stian Thorgersen 18b14b54f4 Merge pull request #499 from stianst/master
Remove notBefore from users
2014-07-07 16:26:31 +01:00
Stian Thorgersen 38857cf2e6 Remove notBefore from users 2014-07-07 16:23:53 +01:00
Stian Thorgersen 0647590170 Merge pull request #498 from stianst/master
Rename loginName to username
2014-07-07 15:58:26 +01:00
Stian Thorgersen 099743d448 Rename loginName to username 2014-07-07 15:56:21 +01:00
Bill Burke 4cbc423d67 Merge pull request #496 from patriot1burke/master
turn on cache for testsuite
2014-07-03 15:30:05 -04:00
Bill Burke e37b5613ed turn on cache 2014-07-03 15:29:31 -04:00
Bill Burke f92ad89a6c Merge pull request #495 from patriot1burke/master
HttpServletRequest.logout()
2014-07-03 14:08:43 -04:00
Bill Burke e99a675c50 HttpServletRequest.logout() 2014-07-03 14:08:19 -04:00
Stian Thorgersen 4593bff76f Merge pull request #494 from vibe13/master
Alignment of dependencies to other JBoss projects
2014-07-03 09:18:34 +01:00
Andrea Vibelli 81d6590544 Removed unused property resteasy.version.eap.6.3, resteasy.version has the same value and it is the one used for consuming 2.3.7.Final version 2014-07-02 15:10:24 +02:00
Andrea Vibelli 2f9597cf51 Alignment of com.h2database:h2 to version 1.3.168 (was 1.3.161) 2014-07-02 14:53:57 +02:00
Andrea Vibelli 8a246a6444 Extraction of hardcoded version of org.jboss.logging:jboss-logging into properties; alignment of org.jboss.logging:jboss-logging to a unique version 3.1.4.GA (was 3.1.1.GA and 3.1.2.GA) 2014-07-02 14:35:57 +02:00
Stian Thorgersen 876d493458 Merge pull request #491 from jpkrohling/JPK-LocationSearchInsteadHref
Changed window.location.href to search.
2014-07-01 10:10:21 +01:00
Stian Thorgersen 6f023fcae4 Merge pull request #490 from mposolda/performance
Added module performance-web for testing Keycloak endpoints with JMeter
2014-07-01 09:50:15 +01:00
Bill Burke 0abd93417a Merge pull request #492 from patriot1burke/master
model fix for caching
2014-06-30 13:13:16 -04:00
Bill Burke b4f5fe9977 model fix for caching 2014-06-30 13:12:42 -04:00
Juraci Paixão Kröhling e15b0c7d90 Changed window.location.href to search. 2014-06-30 17:56:53 +02:00
Stian Thorgersen 3cf52b018c Merge pull request #489 from smysnk/master
Add AMD support to keycloak javascript adapter
2014-06-30 10:22:55 +01:00
mposolda cb9f159091 Added JMeter. Added KeycloakPerfServer into maven. 2014-06-30 09:45:20 +02:00
Joshua Bellamy-Henn 64cea5f25a Add AMD support to keycloak javascript adapter 2014-06-27 11:24:29 -06:00
mposolda b6fd58e644 Support for configuring number of worker threads in undertow 2014-06-27 17:25:47 +02:00
mposolda de774a3058 Add classes classifier to performance-tools war, so classes can be reused in performance-web module 2014-06-27 15:51:02 +02:00
mposolda 9ebe2ff45e Added support for get-users-count and create-available-users into PerfTools 2014-06-27 15:51:02 +02:00
mposolda 4ebc575afc Change perf test to parse accessToken and refreshToken in Servlet. Support for logout 2014-06-27 15:51:01 +02:00
mposolda a1d4d8e13f Work in progress... 2014-06-27 15:51:01 +02:00
mposolda 69f7dfbb47 Added performance-web module 2014-06-27 15:51:01 +02:00
mposolda 99ce0a36e6 Refactoring current performance test 2014-06-27 15:51:01 +02:00
Stian Thorgersen 67c34554db Merge pull request #488 from stianst/master
Fix reset password test
2014-06-27 14:49:57 +01:00
Stian Thorgersen 9ba61af83b Fix reset password test 2014-06-27 14:48:36 +01:00
Stian Thorgersen 436f5f6229 Merge pull request #487 from stianst/master
KEYCLOAK-501 Check if old session for browser exists and delete before c...
2014-06-27 13:58:23 +01:00
Stian Thorgersen 270d6108ca KEYCLOAK-501 Check if old session for browser exists and delete before creating a new 2014-06-27 12:55:33 +01:00
Stian Thorgersen 18094370a6 Merge pull request #486 from stianst/master
Bug fixes
2014-06-27 12:21:39 +01:00
Stian Thorgersen 26eac398e0 KEYCLOAK-541 Create session after resetting password through email 2014-06-27 12:20:32 +01:00
Stian Thorgersen 93c896b4f7 KEYCLOAK-543 Set sent date on emails 2014-06-27 12:19:56 +01:00
Stian Thorgersen 6b29202f1f Merge pull request #485 from stianst/master
Added mail server to test tools
2014-06-27 11:11:52 +01:00
Stian Thorgersen 3b1d8fd8fe Added mail server to test tools 2014-06-27 11:11:33 +01:00
Stian Thorgersen 630d62f014 Merge pull request #484 from stianst/master
Refactor to KeycloakSession
2014-06-27 09:54:31 +01:00
Stian Thorgersen 711b8ca747 Return null for selected provider if empty string 2014-06-27 09:39:21 +01:00
Stian Thorgersen 34a1923d18 Refactor to prepar for splitting model 2014-06-27 09:39:06 +01:00
Stian Thorgersen 6291936ce9 Disable cache as it's not working
Conflicts:
	project-integrations/aerogear-ups/auth-server/src/main/webapp/WEB-INF/keycloak-server.json
	server/src/main/resources/META-INF/keycloak-server.json
	testsuite/tools/src/main/resources/META-INF/keycloak-server.json
2014-06-27 09:38:13 +01:00
Stian Thorgersen 5220c6c288 Merge pull request #483 from mposolda/master
KEYCLOAK-540 Broken project-integrations/aerogear-ups. Move keycloak-ser...
2014-06-25 14:41:56 +01:00
mposolda 532c82f752 KEYCLOAK-540 Broken project-integrations/aerogear-ups. Move keycloak-server.json to correct location, so it's used instead of SystemPropertiesConfigProvider 2014-06-25 15:27:38 +02:00
Stian Thorgersen 61218715af Merge pull request #482 from mposolda/master
LDAP: configurable LDAP Object Classes for User
2014-06-25 09:46:17 +01:00
mposolda 8dce5a90bb LDAP: configurable LDAP Object Classes for User 2014-06-25 07:59:58 +02:00
Stian Thorgersen 8d794b8151 Merge pull request #481 from mposolda/ldap
Ldap improvements and fixes
2014-06-24 09:37:47 +01:00
mposolda b1cfab34fd Support for test of LDAP connection and authentication 2014-06-24 10:03:14 +02:00
mposolda 159a5e20bf Possibility to configure ldap attribute, which is mapped to username, through admin console 2014-06-23 17:54:11 +02:00
mposolda aea4fd8e30 Upgrade to picketlink 2.6.0.CR5. Support for sync whole UserModel into AuthenticationProvider 2014-06-23 15:29:00 +02:00
mposolda 767e6a9783 Add ActiveDirectory fix to properly support sAMAccountName as username 2014-06-23 15:29:00 +02:00
Stian Thorgersen bb8ac0000e Merge pull request #480 from stianst/master
Started test tools module
2014-06-23 11:45:21 +01:00
Stian Thorgersen d73d2e0788 Started test tools module 2014-06-23 11:37:03 +01:00
Bill Burke 714e83198e Merge pull request #479 from patriot1burke/master
perf test fix
2014-06-20 17:15:35 -04:00
Bill Burke c780918501 perf test fix 2014-06-20 17:15:16 -04:00
Bill Burke 8bcb01fadb Merge pull request #478 from patriot1burke/master
user cache
2014-06-20 17:08:16 -04:00
Bill Burke f78f5366cf Merge remote-tracking branch 'upstream/master' 2014-06-20 17:07:50 -04:00
Bill Burke f0d02f24b1 user cache 2014-06-20 17:06:56 -04:00
Bill Burke 15bc33f8e6 Merge pull request #477 from patriot1burke/master
stateless access codes
2014-06-20 10:38:46 -04:00
Bill Burke d21a19925b stateless access codes 2014-06-20 10:37:27 -04:00
Bill Burke a1e9d99d3e Merge remote-tracking branch 'upstream/master' 2014-06-19 08:50:34 -04:00
Bill Burke 094cf675c7 user cache 2014-06-19 08:50:19 -04:00
Stian Thorgersen efcb7ee110 Merge pull request #476 from mposolda/beta-3-testing
Improvement for AD integration to avoid exception when mulitple users wi...
2014-06-19 13:02:36 +01:00
mposolda c8321fc96e Improvement for AD integration to avoid exception when mulitple users without email are synced to Keycloak DB 2014-06-19 13:43:44 +02:00
Stian Thorgersen 56ea29e899 Merge pull request #475 from stianst/master
Bumped version to 1.0-beta-4-SNAPSHOT
2014-06-19 10:20:13 +01:00
Stian Thorgersen df2305eb02 Bumped version to 1.0-beta-4-SNAPSHOT 2014-06-19 10:19:10 +01:00
Stian Thorgersen 5281793078 Merge pull request #474 from mposolda/beta-3-testing
fix javascript error when click on 'Show Expires' and token is not activ...
2014-06-18 17:11:49 +01:00
mposolda 9beb210c23 fix javascript error when click on 'Show Expires' and token is not active 2014-06-18 18:08:05 +02:00
Stian Thorgersen d1c890db18 Merge pull request #472 from mposolda/db-fixes
KEYCLOAK-534 Fix MS-SQL, Oracle and Sybase
2014-06-18 13:32:57 +01:00
Stian Thorgersen 0be4a4b71d Merge pull request #473 from stianst/master
Documentation to reverse proxy config
2014-06-18 13:13:11 +01:00
mposolda 19a545049b KEYCLOAK-536 Fix Sybase - role can't be used as column name as it's keyword in sybase 2014-06-18 12:31:55 +02:00
Stian Thorgersen 34eb34c5fc Added documentation to specify https redirect port 2014-06-18 11:08:06 +01:00
Stian Thorgersen 28adc28a56 Add instructions to configure a reverse proxy with KC 2014-06-18 09:59:23 +01:00
mposolda 5d8c803da6 Remove duplicite dependency declarations to remove maven warnings 2014-06-18 10:31:56 +02:00
mposolda 2fd7fdaa74 KEYCLOAK-535 Fix Keycloak with Oracle 2014-06-18 10:29:57 +02:00
mposolda f9cb99a1ee KEYCLOAK-534 Fix MS-SQL 2014-06-17 19:41:19 +02:00
Stian Thorgersen 37bfb2c594 Merge pull request #471 from stianst/master
KEYCLOAK-533
2014-06-17 15:38:16 +01:00
Stian Thorgersen 3b55248e6c KEYCLOAK-533 2014-06-17 15:30:50 +01:00
Stian Thorgersen b35bccdad2 Merge pull request #470 from stianst/master
KEYCLOAK-530
2014-06-17 14:11:48 +01:00
Stian Thorgersen 6cabf3e57d KEYCLOAK-530 2014-06-17 14:11:31 +01:00
Stian Thorgersen b31b54e17c Merge pull request #469 from stianst/master
KEYCLOAK-532
2014-06-17 14:07:26 +01:00
Stian Thorgersen 469d044254 KEYCLOAK-532 2014-06-17 14:07:07 +01:00
Stian Thorgersen 9a26d7078f Merge pull request #468 from stianst/master
KEYCLOAK-520
2014-06-17 11:21:54 +01:00
Stian Thorgersen 896c32a660 KEYCLOAK-520 2014-06-17 11:21:36 +01:00
Stian Thorgersen 6e23613b9e Merge pull request #467 from stianst/master
Disable cache provider for beta-3 release
2014-06-17 11:07:27 +01:00
Stian Thorgersen d15324110e Disable cache provider for beta-3 release 2014-06-17 11:06:08 +01:00
Stian Thorgersen 153de54fe8 Merge pull request #466 from stianst/master
KEYCLOAK-526 Fix iframe origin when auth server url is relative
2014-06-16 17:55:27 +01:00
Stian Thorgersen 2866f6fc23 KEYCLOAK-526 Fix iframe origin when auth server url is relative 2014-06-16 17:55:03 +01:00
Bill Burke 9228f0c076 Merge pull request #465 from patriot1burke/master
keycloak-521
2014-06-16 11:59:52 -04:00
Bill Burke 1eafb01c8d keycloak-521 2014-06-16 11:59:27 -04:00
Bill Burke 44f446e745 Merge pull request #464 from patriot1burke/master
keycloak-518
2014-06-16 10:48:34 -04:00
Bill Burke c71fdc72c7 keycloak-518 2014-06-16 10:43:50 -04:00
Bill Burke bbf944a225 Merge pull request #463 from patriot1burke/master
oops show-sql=false
2014-06-16 10:28:28 -04:00
Bill Burke dbc5641144 oops show-sql=false 2014-06-16 10:28:06 -04:00
Bill Burke 9080a64fcd Merge pull request #462 from patriot1burke/master
better fetch for role mappings
2014-06-16 10:16:22 -04:00
Bill Burke f50177996d better fetch for role mappings 2014-06-16 10:15:53 -04:00
Bill Burke b649dd39d9 Merge pull request #461 from patriot1burke/master
caching
2014-06-13 20:09:03 -04:00
Bill Burke ab87c03732 cache 1st iteration finished 2014-06-13 19:39:20 -04:00
Bill Burke 8eaf77b3c1 cache impl again 2014-06-13 19:05:05 -04:00
Bill Burke cbea141a54 cache impl 2014-06-13 17:17:45 -04:00
Bill Burke 60a040a141 Merge pull request #460 from patriot1burke/master
refactor for caching
2014-06-13 09:49:08 -04:00
Bill Burke 4a518c964b mongo refactor for caching 2014-06-12 16:51:19 -04:00
Bill Burke bb2ad656a3 cache implement 2014-06-12 11:45:50 -04:00
Bill Burke 30b95e0a57 Merge remote-tracking branch 'upstream/master' 2014-06-12 11:12:22 -04:00
Bill Burke 852c631eff Merge pull request #459 from ssilvert/master
KEYCLOAK-522 Refactor Undertow Adapter so that it can optionally be used without the Servlet API.
2014-06-12 11:12:07 -04:00
Bill Burke 211a279248 Merge remote-tracking branch 'upstream/master' 2014-06-12 11:11:27 -04:00
Bill Burke 2ae2067841 refactor for caching again 2014-06-12 11:11:14 -04:00
Bill Burke 0dd06e3343 model refactor for caching 2014-06-10 18:50:08 -04:00
Stan Silvert 4e9bec69e4 Add Apache 2.0 license 2014-06-09 16:43:45 -04:00
Stan Silvert 70392d9f1a KEYCLOAK-522 Refactor Undertow Adapter so that it can optionally be used
without the Servlet API.
2014-06-09 16:43:44 -04:00
Bill Burke 9a3abf6a6a Merge pull request #458 from mposolda/master
Support for Active Directory and RHDS
2014-06-09 15:15:15 -04:00
mposolda 0bfcbdb359 Support for Active Directory and RHDS 2014-06-09 16:20:19 +02:00
Bill Burke 2f3c8bf079 cache refactor 2014-06-06 15:12:58 -04:00
Stian Thorgersen e7bde986aa Merge pull request #457 from stianst/master
KEYCLOAK-504 Using https results in RuntimeException if sslRequired is set to false
2014-06-06 14:54:40 +01:00
Stian Thorgersen f3211bf34d KEYCLOAK-504
Using https results in RuntimeException if sslRequired is set to false
2014-06-06 14:54:11 +01:00
Stian Thorgersen c086e0a502 Merge pull request #456 from stianst/master
KEYCLOAK-500
2014-06-06 09:53:08 +01:00
Stian Thorgersen 80f4b668b2 KEYCLOAK-500
Redundant condition in keycloak.js
2014-06-06 09:52:25 +01:00
Stian Thorgersen 01606ab5e0 Merge pull request #455 from stianst/master
KEYCLOAK-496 Dependency jira alignments with other JBoss projects
2014-06-05 15:25:37 +01:00
Stian Thorgersen 91e29d9710 KEYCLOAK-496 Dependency jira alignments with other JBoss projects 2014-06-05 13:33:48 +01:00
Stian Thorgersen 23d101f8fa Merge pull request #454 from rodrigopsasaki/issue-keycloak-519
Issue KEYCLOAK-519
2014-06-05 13:30:00 +01:00
Rodrigo Sasaki e08b3e7dec flipped comparison operands to avoid NPE 2014-06-05 09:24:06 -03:00
Stian Thorgersen c4e32b7c45 Merge pull request #453 from stianst/stateless-social
Fix
2014-06-05 11:13:38 +01:00
Stian Thorgersen 14ece40054 Removed file that shouldn't have been committed 2014-06-05 11:12:47 +01:00
Stian Thorgersen eaa6be55d7 KEYCLOAK-496 Removed commons-io 2014-06-05 10:41:37 +01:00
Stian Thorgersen 2ae714aea2 Merge pull request #452 from stianst/stateless-social
KEYCLOAK-244 Social should be stateless
2014-06-05 10:40:07 +01:00
Stian Thorgersen 5f6687ec62 KEYCLOAK-244 Social should be stateless 2014-06-05 10:09:17 +01:00
Stian Thorgersen 06053fad85 Merge pull request #451 from stianst/master
KEYCLOAK-510
2014-06-04 12:34:29 +01:00
Stian Thorgersen d0c06ab0ce KEYCLOAK-510
NPE in ExtendingThemeManager
2014-06-04 12:26:24 +01:00
Stian Thorgersen cfb6f927b2 Merge pull request #450 from jimbo1007/jsfix
add missing initPromise.setSuccess()
2014-06-03 15:02:18 +01:00
unknown 8d33894989 add missing initPromise.setSuccess() 2014-06-03 09:28:01 -04:00
Bill Burke ba13cbe004 Merge pull request #449 from patriot1burke/master
fix deadlocks
2014-06-02 21:34:43 -04:00
Bill Burke 9410adf9ce fix deadlocks 2014-06-02 21:33:43 -04:00
Bill Burke 7443c78087 Merge pull request #448 from patriot1burke/master
bump version again
2014-06-02 14:22:10 -04:00
Bill Burke d5b34a0b41 bump version again 2014-06-02 13:12:04 -04:00
Bill Burke 0cd64e297a Merge pull request #447 from patriot1burke/master
bump version
2014-06-02 12:22:40 -04:00
Bill Burke 0fcf80dd6e bump version 2014-06-02 12:21:58 -04:00
Bill Burke 56e9e0b4f9 Merge pull request #446 from patriot1burke/master
NPE in as7 adapter logout
2014-06-02 12:03:09 -04:00
Bill Burke dfcd3267e4 NPE in as7 adapter logout 2014-06-02 12:02:42 -04:00
Bill Burke f689747fd6 Merge pull request #445 from patriot1burke/master
wildfly ssl fixes
2014-06-02 11:22:51 -04:00
Bill Burke bb11165568 wildfly ssl fixes 2014-06-02 11:22:19 -04:00
Bill Burke a180c6b896 Merge remote-tracking branch 'upstream/master' 2014-06-02 09:37:30 -04:00
Bill Burke 34d3be244d bump undertow version 2014-06-02 09:37:18 -04:00
Stian Thorgersen 4662781213 Merge pull request #443 from lnewson/master
Fixed an integer overflow that caused the token to be refreshed too often
2014-06-02 09:35:11 +01:00
Stian Thorgersen 5bd12a708f Merge pull request #444 from lnewson/social-fix
Fixed an NPE when the social users name is null
2014-06-02 09:34:32 +01:00
Bill Burke e39149c954 Merge remote-tracking branch 'upstream/master' 2014-06-01 18:03:49 -04:00
Bill Burke b925a97b5d bump wildfly version 2014-06-01 18:03:39 -04:00
Lee Newson 3bcf2c81da Fixed an NPE when the users name is null 2014-05-31 10:39:34 +10:00
Lee Newson b52801de25 Fixed an integer overflow that caused the token to always be refreshed 2014-05-31 10:26:06 +10:00
Stian Thorgersen 4d8c3d7d73 Merge pull request #442 from stianst/master
Cache for FreeMarker templates and set cache-control for static resources from themes
2014-05-30 17:03:37 +01:00
Stian Thorgersen ea1f10361a Cache FreeMarker templates 2014-05-30 16:59:25 +01:00
Stian Thorgersen 5dafad71ac Set cache-control on static resources from themes 2014-05-30 16:59:25 +01:00
Bill Burke df28fb97ed Merge pull request #440 from stianst/master
Bump version to 1.0.beta2-SNAPSHOT
2014-05-30 08:56:00 -04:00
Stian Thorgersen 5600018a56 Merge pull request #441 from mposolda/master
Basic fix of performance tests and added README. Still requires work...
2014-05-30 10:37:05 +01:00
mposolda 441c00c06f Basic fix of performance tests and added README. Still requires work... 2014-05-30 11:03:16 +02:00
Stian Thorgersen 9533bbc47d Merge pull request #439 from mposolda/master
Fix js-console on FF
2014-05-30 08:55:33 +01:00
Stian Thorgersen 2025d314ec Bump version to 1.0.beta2-SNAPSHOT 2014-05-30 08:52:03 +01:00
mposolda 772f991545 Fix js-console on FF 2014-05-29 18:56:34 +02:00
Bill Burke f6b59b03bb Merge pull request #438 from patriot1burke/master
bump version
2014-05-29 12:16:30 -04:00
Bill Burke 2ae3775841 bump version 2014-05-29 12:12:33 -04:00
Stian Thorgersen 8573c13b8c Merge pull request #437 from mposolda/master
Improve PropertiesAuthenticationProvider to support retrieving user pass...
2014-05-29 16:10:11 +01:00
mposolda db1c6e9afd Improve PropertiesAuthenticationProvider to support retrieving user passwords from custom location and persisting password updates 2014-05-29 16:55:41 +02:00
Stian Thorgersen 429f003578 Merge pull request #436 from stianst/master
Fix audit provider example
2014-05-29 15:08:48 +01:00
Stian Thorgersen dd684858f2 Fix audit provider example 2014-05-29 15:08:27 +01:00
Stian Thorgersen 2e82d56634 Merge pull request #435 from stianst/master
Demo fixes
2014-05-29 14:04:40 +01:00
Stian Thorgersen 1ede6e70b7 Fix customer-portal-cli example 2014-05-29 14:04:10 +01:00
Stian Thorgersen 8908fbef58 Fix instructions for deploying demo to use jboss-as:deploy or wildfly:deploy 2014-05-29 14:03:50 +01:00
Stian Thorgersen 09a96b3a2b Merge pull request #434 from stianst/master
Added sunrise theme to examples, including instructions on how to deploy
2014-05-29 13:15:14 +01:00
Stian Thorgersen 5b7c8b6920 Added sunrise theme to examples, including instructions on how to deploy 2014-05-29 13:14:39 +01:00
Stian Thorgersen 409b46963e Merge pull request #433 from mposolda/master
Add more scopes into testrealm.json to ensure that admin is able to acce...
2014-05-29 13:03:04 +01:00
mposolda 53cf574735 Add more scopes into testrealm.json to ensure that admin is able to access all things he needs 2014-05-29 13:06:47 +02:00
Stian Thorgersen fe236cabd3 Merge pull request #431 from mposolda/master
Change default timeouts for testrealm.json bundled in examples, Fix admin-access-app example
2014-05-29 10:55:35 +01:00
Stian Thorgersen d25536569a Merge pull request #430 from PatrickMadden/master
Added bindIp support to embedmongo-maven-plugin configuration. Solves is...
2014-05-29 10:54:46 +01:00
mposolda 06b9499805 Fixing typo in admin console causing errors when change passwordCredentialsGrant 2014-05-29 11:42:54 +02:00
Stian Thorgersen 2a2e57467d Merge pull request #432 from stianst/master
Fix themes displayed multiple times in admin console
2014-05-29 10:28:22 +01:00
Stian Thorgersen 24ac6cbbac Fix themes displayed multiple times in admin console 2014-05-29 10:28:05 +01:00
Stian Thorgersen 0b68e52b83 Fix Cannot read property 'realm' of undefined 2014-05-29 10:20:49 +01:00
Stian Thorgersen cf1393ffe1 Updated sunrise theme example 2014-05-29 09:42:17 +01:00
mposolda c4808a3e61 Fix admin-App example 2014-05-29 10:29:06 +02:00
mposolda f0d37b19e2 Fix typo in docs 2014-05-29 10:28:54 +02:00
mposolda 65206a72b2 Change default timeouts for testrealm.json bundled in examples 2014-05-29 09:30:22 +02:00
Stian Thorgersen a91d4c06ee Merge pull request #429 from mposolda/master
Fixes in JS examples
2014-05-29 07:52:46 +01:00
PatrickMadden e8ad08bd28 Reuse bindIp of model for audit in integration test suite. 2014-05-28 20:02:42 -05:00
PatrickMadden 7a3b1ddd18 Added bindIp support to embedmongo-maven-plugin configuration. Solves issue of firewall pop-ups consistently displaying on every Microsoft Windows build. 2014-05-28 19:14:23 -05:00
mposolda db939ee076 Fix angular-product example 2014-05-28 23:30:34 +02:00
mposolda 5ede17d8b8 Replace innerText with innerHTML as innerText doesn't work on FF 2014-05-28 21:50:23 +02:00
Bill Burke 0ff992e04e Merge pull request #428 from patriot1burke/master
docs
2014-05-28 12:34:11 -04:00
Bill Burke 34a579821a docs 2014-05-28 12:33:49 -04:00
Stian Thorgersen dd30a35e1e Disable session iframe in Corodova 2014-05-28 17:29:13 +01:00
Stian Thorgersen 2074e1423f Fixes for example/cordova 2014-05-28 17:10:28 +01:00
Stian Thorgersen d5476b78ec Merge pull request #427 from stianst/master
Deploy server war and dist bundles to Maven repo. Also added '-parent' to some parent poms where this was missing
2014-05-28 15:32:58 +01:00
Stian Thorgersen df19700f69 Deploy server war and dist bundles to Maven repo. Also added '-parent' to some parent poms where this was missing 2014-05-28 15:32:20 +01:00
Bill Burke 3c605a7740 Merge pull request #426 from patriot1burke/master
docs and master realm rename
2014-05-28 09:51:56 -04:00
Bill Burke a64b35d72f doc merge 2014-05-28 09:33:42 -04:00
Bill Burke e880b77692 update docs 2014-05-28 09:31:33 -04:00
Stian Thorgersen e8fe26ff1c Merge pull request #425 from stianst/master
Fix for WildFly 8.1.0.CR2
2014-05-28 14:20:53 +01:00
Stian Thorgersen 108ccd98d0 Fix for WildFly 8.1.0.CR2 2014-05-28 14:20:29 +01:00
Stian Thorgersen 5fddc28cd6 Updated jboss maven plugin and added wildfly maven plugin. Both are skipped by default, so only needs to be specified in modules that should be deployed 2014-05-28 11:00:36 +01:00
Stian Thorgersen 63001d5e16 Merge pull request #424 from mposolda/master
Fix configuration of maven plugins in authentication-properties example
2014-05-28 09:59:36 +01:00
mposolda caccf76ea4 Fix configuration of maven plugins in authentication-properties example 2014-05-28 10:56:00 +02:00
Stian Thorgersen 5120549005 Merge pull request #423 from mposolda/master
Updated documentation and added example for Authentication SPI
2014-05-28 09:12:01 +01:00
mposolda e67032a9d7 Documentation about Authentication SPI, LDAP and Export/import 2014-05-27 22:37:25 +02:00
mposolda a903eb7605 Added example for AuthenticationProvider SPI 2014-05-27 22:37:25 +02:00
Bill Burke 5b431338c2 Merge pull request #422 from patriot1burke/master
admin console mistake
2014-05-27 14:56:14 -04:00
Bill Burke c20d488648 admin console mistake 2014-05-27 14:38:03 -04:00
Stian Thorgersen 57a8f3f5ee Added to migration guid for beta1 2014-05-27 15:29:04 +01:00
Stian Thorgersen 6dda7fc356 Added example providers for audit listener and audit provider 2014-05-27 15:11:52 +01:00
Stian Thorgersen 9261c1608f Fix missing @Path in admin console 2014-05-27 13:40:32 +01:00
Stian Thorgersen 80cd43390b Added doc for audit 2014-05-27 13:40:23 +01:00
Stian Thorgersen c196849574 Updated doc for themes 2014-05-27 13:08:00 +01:00
Stian Thorgersen 1007d19860 Updated instructions to configure Mongo through keycloak-server.json 2014-05-27 12:05:35 +01:00
Stian Thorgersen 374a7b8848 Updated url for OpenShift cartridge 2014-05-27 12:05:22 +01:00
Stian Thorgersen 8ae57fd117 Include all themes in configuration/themes to make it easy to modify/create themes 2014-05-27 12:05:09 +01:00
Bill Burke 5a2fd16b92 Merge pull request #421 from patriot1burke/master
jaxrs-doclet, more javadocs
2014-05-26 20:51:53 -04:00
Bill Burke 3545ac130b jax-doclet 2014-05-26 20:50:42 -04:00
Bill Burke 199c786e22 jaxrs-doclet support 2014-05-26 20:41:33 -04:00
Bill Burke 38b52283a5 Merge remote-tracking branch 'upstream/master' 2014-05-26 12:50:09 -04:00
Bill Burke 1f8b2d4c7b stuff 2014-05-26 12:49:56 -04:00
Bill Burke 9c0fa93510 Merge pull request #420 from patriot1burke/master
admin rest example, default origins, effect roles
2014-05-23 19:03:25 -04:00
Bill Burke ab2932f75e effective roles to oauth 2014-05-23 19:01:09 -04:00
Bill Burke 81083ef470 Merge remote-tracking branch 'upstream/master' 2014-05-23 18:22:34 -04:00
Bill Burke e4232c73c6 admin rest api example 2014-05-23 18:20:55 -04:00
Bill Burke 29070cec77 add KeycloakSecurityContext to principal 2014-05-23 16:26:44 -04:00
Bill Burke fbef9f7691 default web origins 2014-05-23 16:15:00 -04:00
Bill Burke 97f3a3feef Merge pull request #419 from patriot1burke/master
admin cors
2014-05-23 16:12:08 -04:00
Bill Burke 54cc095ff5 admin cors support 2014-05-23 16:02:14 -04:00
Stian Thorgersen 0ad4d5cc47 Change 'Composite roles' to 'Effective roles' on role mapping/scope pages 2014-05-23 16:44:55 +01:00
Bill Burke 236f3ab768 admin cors 2014-05-23 09:37:07 -04:00
Stian Thorgersen 6de7c42ac9 Merge pull request #418 from mposolda/master
Fixing typo
2014-05-23 10:21:44 +01:00
mposolda bb7a809ab5 Fixing typo 2014-05-23 11:19:17 +02:00
Stian Thorgersen 142b155460 Merge pull request #417 from mposolda/master
At least one redirect_uri must be available for oauthClients and applica...
2014-05-23 10:11:06 +01:00
Stian Thorgersen 0f6bc9c5c7 KEYCLOAK-492
Can't add scope on application role to application
2014-05-23 10:10:19 +01:00
mposolda e600d7c449 At least one redirect_uri must be available for oauthClients and applications, which are not bearer-only 2014-05-23 10:55:43 +02:00
Stian Thorgersen 37327be521 KEYCLOAK-482
Cannot read property 'realm' of undefined
2014-05-23 09:36:14 +01:00
Stian Thorgersen 07d2bf988a Merge pull request #416 from mposolda/master
Fix logging typo when importing roles
2014-05-23 09:14:10 +01:00
mposolda df06a0c878 Fix logging typo when importing roles 2014-05-23 09:46:50 +02:00
Stian Thorgersen cee3fea98f Merge pull request #415 from mposolda/master
Invalid active tab when on token-settings page
2014-05-23 08:39:49 +01:00
mposolda 5c378cbd9d Invalid active tab when on token-settings page 2014-05-23 08:51:06 +02:00
Stian Thorgersen 37099f3177 KEYCLOAK-494
Session state iframe uses first redirect uri for a client
2014-05-22 17:51:51 +01:00
Stian Thorgersen 128cc7eadb Fixes to js-console example 2014-05-22 17:07:40 +01:00
Stian Thorgersen de36973716 Redirect to login form automatically in keycloak.js if login-required is set 2014-05-22 16:59:38 +01:00
Stian Thorgersen 08b1996149 Removed jboss.as.jpa.managed property from persistence.xml as it's causing problems on AS 7.1 2014-05-22 16:01:05 +01:00
Stian Thorgersen 0574302840 Fix dialog for resetting user password 2014-05-22 15:39:31 +01:00
Stian Thorgersen fad0a7728c Make add redirect-uri and web-origin use same l&f 2014-05-22 15:10:22 +01:00
Stian Thorgersen 86ad7292af Fix updating sessions after logout session 2014-05-22 14:51:36 +01:00
Stian Thorgersen 74e2bfd9bd Merge pull request #414 from mposolda/master
Extract some version numbers into properties
2014-05-22 11:21:55 +01:00
mposolda 0c60bd80df Extract some versions into properties 2014-05-22 12:04:13 +02:00
Stian Thorgersen 46f81a331a Merge pull request #413 from mposolda/master
Fixing location of folder for FolderThemeProvider
2014-05-22 08:54:22 +01:00
mposolda b0ba7ed188 Fixing location of FolderThemeProvider 2014-05-22 09:21:42 +02:00
Bill Burke 0d9e14d4c7 Merge remote-tracking branch 'upstream/master' 2014-05-21 10:56:21 -04:00
Stian Thorgersen 10ae457237 Fixes to admin console 2014-05-21 14:10:59 +01:00
Stian Thorgersen 73f59417bd Remove index.html from redirect on '/auth/admin/' 2014-05-21 12:47:07 +01:00
Stian Thorgersen 6814230193 Fix NPE in account service 2014-05-21 12:13:00 +01:00
Stian Thorgersen d68131ac00 KEYCLOAK-475
Log is shown in menu when audit is disabled for realm
2014-05-21 12:05:32 +01:00
Stian Thorgersen 952f098440 KEYCLOAK-483
Remove 'index.html' from console url
2014-05-21 11:16:48 +01:00
Stian Thorgersen f08477ea66 Run import before creating default realm 2014-05-21 11:16:47 +01:00
Stian Thorgersen 8544dd66d8 Merge pull request #412 from mposolda/master
Mongo related fixes
2014-05-21 10:50:31 +01:00
Stian Thorgersen a5a2848251 KEYCLOAK-476
theme/account/patternfly/img/icon-sidebar-active.svg not found
2014-05-21 10:40:15 +01:00
mposolda 7232535729 More mongo fixes 2014-05-21 11:34:27 +02:00
mposolda 271292dbd4 Mongo related fixes 2014-05-21 11:34:27 +02:00
Stian Thorgersen eb47d43497 For installed app urn redirect to a page instead of returning the html, this is to prevent NPE if page is refreshed 2014-05-21 10:32:03 +01:00
Stian Thorgersen fd9317a295 KEYCLOAK-474
Code not visible for urn:ietf:wg:oauth:2.0:oob
2014-05-21 09:52:02 +01:00
Stian Thorgersen 11fc6d5321 KEYCLOAK-477
Remove keycloak.js debug statements
2014-05-21 09:39:02 +01:00
Stian Thorgersen 64a36aee03 Merge pull request #411 from stianst/master
Twitter fix and read keycloak-sever.json from standalone/configuration
2014-05-21 09:35:49 +01:00
Stian Thorgersen 59440840fe Read keycloak-sever.json from <JBOSS_HOME>/standalone/configuration if it exists 2014-05-21 09:35:01 +01:00
Stian Thorgersen c2075af7f7 Fix Twitter for localhost 2014-05-21 08:47:58 +01:00
Stian Thorgersen ab85f09608 Merge pull request #410 from ssilvert/master
Make UndertowUserSessionManagement class usable without the Servlet API.
2014-05-21 07:56:17 +01:00
Stan Silvert da799b18c3 Make UndertowUserSessionManagement class usable without the Servlet API. 2014-05-20 19:58:08 -04:00
Bill Burke ca6de3e486 simpler applicaiton create page 2014-05-20 17:45:14 -04:00
Bill Burke ae3c4e8459 default web origin is redirect uris 2014-05-20 17:40:45 -04:00
Bill Burke 8e79f550b0 Merge remote-tracking branch 'upstream/master' 2014-05-20 16:49:28 -04:00
Bill Burke 0137918701 urn 2014-05-20 16:49:25 -04:00
Bill Burke 79828ddc78 Merge pull request #409 from patriot1burke/master
fix urn redirect uri
2014-05-20 16:15:40 -04:00
Bill Burke fcca9dd90a fix urn redirect uri 2014-05-20 16:15:13 -04:00
Stian Thorgersen 1b4b537043 Merge pull request #408 from stianst/email-events
Email audit listener
2014-05-20 17:29:45 +01:00
Stian Thorgersen b09e2f697e Email audit listener 2014-05-20 17:04:17 +01:00
Bill Burke 2855baecef Merge pull request #407 from patriot1burke/master
check redirect uri exists in token service
2014-05-20 11:39:22 -04:00
Bill Burke b7cf1bb215 Merge remote-tracking branch 'upstream/master' 2014-05-20 11:38:50 -04:00
Bill Burke b3dd349342 check redirect uri exists in token service 2014-05-20 11:38:35 -04:00
Stian Thorgersen 357337047b Merge pull request #406 from stianst/master
Fix config for folder theme provider£
2014-05-20 14:42:39 +01:00
Stian Thorgersen 5496f043a5 Fix config for folder theme provider£ 2014-05-20 14:42:07 +01:00
Bill Burke a22aa8055f Merge pull request #405 from patriot1burke/master
redirect uris not required with bearer only
2014-05-20 09:31:23 -04:00
Bill Burke 57f0ea0638 Merge remote-tracking branch 'upstream/master' 2014-05-20 09:27:18 -04:00
Bill Burke f723ac79d1 redirect not required with bearer only 2014-05-20 09:19:04 -04:00
Stian Thorgersen 3a15b416a9 Merge pull request #404 from stianst/master
Add realm option to enable/disable Resource Owner Password Credentials G...
2014-05-20 11:33:07 +01:00
Stian Thorgersen cc97265c06 Add realm option to enable/disable Resource Owner Password Credentials Grant 2014-05-20 11:32:22 +01:00
Stian Thorgersen 665038d0ce Merge pull request #403 from stianst/master
Add email theme config for realm
2014-05-20 11:01:07 +01:00
Stian Thorgersen 8d1149dc07 Add email theme config for realm 2014-05-20 11:00:43 +01:00
Bill Burke ebea9e9270 Merge pull request #402 from patriot1burke/master
fix remove expired token
2014-05-19 18:53:54 -04:00
Bill Burke b5aa9efefb fix remove expired sessions 2014-05-19 18:53:28 -04:00
Bill Burke 95f56e2e62 fix removeexpired sessions 2014-05-19 18:33:54 -04:00
Bill Burke 273775d848 Merge pull request #401 from patriot1burke/master
fix aerogear again
2014-05-19 18:14:16 -04:00
Bill Burke 8606f344a8 fix aerogear again 2014-05-19 18:13:54 -04:00
Bill Burke 53c3696cbb Merge pull request #400 from patriot1burke/master
aerogear fix
2014-05-19 18:09:54 -04:00
Bill Burke 7203d9ba12 aerogear fix 2014-05-19 18:09:36 -04:00
Bill Burke 26d3e48555 Merge pull request #399 from patriot1burke/master
don't allow bearer-only to login
2014-05-19 15:09:18 -04:00
Bill Burke a53206995a stuff 2014-05-19 15:08:38 -04:00
Bill Burke b2c8f48af9 Merge pull request #398 from patriot1burke/master
require redirect
2014-05-19 14:54:31 -04:00
Bill Burke 11c23a7945 require redirect 2014-05-19 14:44:36 -04:00
Stian Thorgersen 3be4579204 Merge pull request #397 from stianst/email-themes
Email themes
2014-05-19 17:40:52 +01:00
Stian Thorgersen a3d08e7191 Added theme support to emails 2014-05-19 17:34:58 +01:00
Bill Burke 7e8b16f975 acct svc + sessions 2014-05-19 17:34:48 +01:00
Bill Burke 966eb2fe47 Merge pull request #396 from patriot1burke/master
acct svc + sessions
2014-05-19 11:46:04 -04:00
Bill Burke 5826f02ebe acct svc + sessions 2014-05-19 11:45:42 -04:00
Bill Burke 2b525c6016 Merge pull request #395 from patriot1burke/master
fix brute shutdown
2014-05-19 10:35:49 -04:00
Bill Burke dc7923c436 fix brute shutdown 2014-05-19 10:33:49 -04:00
Stian Thorgersen 00a64eeb89 Merge pull request #394 from stianst/master
Added keycloak-server.json for project-integrations/aerogear-ups
2014-05-19 10:47:15 +01:00
Stian Thorgersen 76c9f2c4ec Added keycloak-server.json for project-integrations/aerogear-ups 2014-05-19 10:46:33 +01:00
Bill Burke dafa52ea93 Merge pull request #393 from patriot1burke/master
user-session client association
2014-05-17 14:32:46 -04:00
Bill Burke c2bf6c3822 Merge remote-tracking branch 'upstream/master' 2014-05-17 14:24:37 -04:00
Bill Burke ab8de6ba25 client user-session association 2014-05-17 14:24:32 -04:00
Stian Thorgersen 6714e2b87f Merge pull request #392 from stianst/master
Server config
2014-05-16 17:34:13 +01:00
Stian Thorgersen 855269f35d Added 'keycloak-server.json' for configuring the server
Added SPI interface to detect SPI's
Converted Model to SPI/Provider to be loaded through ProviderSessionFactory
2014-05-16 17:33:22 +01:00
Stian Thorgersen a3ed02ea16 Merge pull request #391 from jeroenr/master
CORS improvements and clean up
2014-05-16 16:06:43 +01:00
Jeroen Rosenberg 84f13eadc1 * Possibility to add exposed headers
* Default allow headers
* Fix warnings, unused import, redundancies
2014-05-16 16:39:17 +02:00
Jeroen Rosenberg cedf43c084 Refactored joining of allowed headers to be more efficient 2014-05-16 14:28:49 +02:00
Jeroen Rosenberg 4c281a39bb Unused import 2014-05-16 14:10:13 +02:00
Jeroen Rosenberg 5533357c46 Added HEAD as default allowed method for Cors 2014-05-16 14:09:50 +02:00
Stian Thorgersen ae4d83107a Merge pull request #390 from jeroenr/master
Fixed URI encoding for clientId and parse optional client secret from config file
2014-05-16 13:02:41 +01:00
Jeroen Rosenberg b92494f023 Refactored to use switch with fall through for readability 2014-05-16 13:52:59 +02:00
Jeroen Rosenberg d3a2617d3c Read optional client secret configuration to ensure we can use Basic auth as well 2014-05-16 13:49:28 +02:00
Jeroen Rosenberg 740943290c URI encode clientId for referrer parameter 2014-05-16 13:46:46 +02:00
Bill Burke c51c7fe189 Merge pull request #389 from jeroenr/master
Improved exception handling. Don't swallow exception
2014-05-16 06:34:18 -04:00
Bill Burke 610eaaaaff Merge pull request #387 from cardosogabriel/POLISHING_UI
UI POLISHING: design styles and content
2014-05-16 06:34:09 -04:00
Jeroen Rosenberg bde9944449 Improved exception handling. Don't swallow exception 2014-05-16 09:35:19 +02:00
Bill Burke 1318ea85be Merge pull request #388 from patriot1burke/master
session idle and max lifespan
2014-05-15 23:18:43 -04:00
Bill Burke 67e3e60f28 test sso idle, logout on idle 2014-05-15 23:10:14 -04:00
Bill Burke bc2360e985 sso session idle and max lifespan 2014-05-15 17:25:57 -04:00
Gabriel Cardoso 8e7b0022a6 UI POLISHING: design styles and content 2014-05-15 15:22:38 -03:00
Bill Burke 27efd3c0a4 ssoSessionIdleTimeout refactor 2014-05-15 13:53:28 -04:00
Bill Burke 07a31d3f35 Merge pull request #386 from patriot1burke/master
check ssl required in adapter
2014-05-14 15:24:22 -04:00
Bill Burke 07dbb7d7b7 check ssl required in adapter 2014-05-14 15:23:45 -04:00
Bill Burke 26f6da10dd Merge pull request #385 from patriot1burke/master
Improved role and scope mapping screens
2014-05-14 14:50:52 -04:00
Bill Burke 7ba8e09aef improved scope screen 2014-05-14 14:50:11 -04:00
Stian Thorgersen d95372c993 Merge pull request #384 from stianst/master
Updated session status iframe for JavaScript adapter
2014-05-14 17:54:58 +01:00
Stian Thorgersen 643daadf60 Updated session status iframe for JavaScript adapter to be created automatically, and to invoke onAuthLogout callback if user is logged out 2014-05-14 17:46:30 +01:00
Stian Thorgersen 7bea4af6c9 Redirect to login page if logged out and submitting forms in acct mngmt 2014-05-14 17:46:30 +01:00
Stian Thorgersen b27776b3c6 Merge pull request #383 from matzew/master
removing java7 ctor usage of runtimeexception
2014-05-14 16:48:15 +01:00
Matthias Wessendorf d9c8dedcfb removing JavaSE6 incompatible ctor 2014-05-14 17:43:36 +02:00
Matthias Wessendorf 9e0bf9e7dc Removing exception ctor that does not work w/ java 6 2014-05-14 17:40:27 +02:00
Bill Burke 0e0dfb60e0 composite role mapping listing 2014-05-14 10:37:50 -04:00
Stian Thorgersen b95fd0d0b0 Merge pull request #382 from stianst/master
KEYCLOAK-431 View open sessions, and logout all sessions, through accoun...
2014-05-14 11:56:52 +01:00
Stian Thorgersen f4f9b1e323 KEYCLOAK-431 View open sessions, and logout all sessions, through account management 2014-05-14 11:56:28 +01:00
Bill Burke f7c3373f75 Merge pull request #381 from patriot1burke/master
IE fixes
2014-05-13 22:47:46 -04:00
Bill Burke 639b7c5610 fix IE problems 2014-05-13 22:33:46 -04:00
Bill Burke b30809d681 httponly, ie keycloak.js fix 2014-05-13 22:06:32 -04:00
Bill Burke 0731f9977b Merge pull request #380 from patriot1burke/master
cors example
2014-05-13 17:17:51 -04:00
Bill Burke e8f8829a76 cors example 2014-05-13 17:17:27 -04:00
Bill Burke 663ff30eae Merge pull request #379 from patriot1burke/master
angular example
2014-05-13 12:07:59 -04:00
Bill Burke 01d22c3aab angular example 2014-05-13 12:07:28 -04:00
Bill Burke 9b24369b92 Merge pull request #378 from patriot1burke/master
update ups writeup
2014-05-12 19:45:24 -04:00
Bill Burke f6645eea92 update ups writeup 2014-05-12 19:45:01 -04:00
Bill Burke 634f61281d Merge pull request #377 from patriot1burke/master
aerogear template
2014-05-12 19:40:00 -04:00
Bill Burke c560a739b1 aerogear readme 2014-05-12 19:39:29 -04:00
Bill Burke ea672e36ae rename realm management app 2014-05-12 19:28:34 -04:00
Bill Burke eb9335f706 aerogear 2014-05-12 18:34:17 -04:00
Bill Burke d429525620 Merge pull request #376 from patriot1burke/master
fix create realm
2014-05-12 15:42:42 -04:00
Bill Burke b1a480c20d fix create realm 2014-05-12 15:42:10 -04:00
Bill Burke 0fcebb8670 remove bundled app 2014-05-12 15:38:15 -04:00
Bill Burke 3e32bd116b aerogear demo update 2014-05-12 15:35:54 -04:00
Bill Burke a4cb268703 Merge pull request #375 from patriot1burke/master
per-realm admin console
2014-05-12 10:13:18 -04:00
Bill Burke 06b98589eb Merge remote-tracking branch 'upstream/master' 2014-05-12 10:12:42 -04:00
Bill Burke 1e1991e285 per-realm admin 2014-05-12 10:12:31 -04:00
Bill Burke b0446fab0c Merge pull request #374 from patriot1burke/master
iframe check login
2014-05-10 11:28:24 -04:00
Bill Burke 1194e40ef2 iframe check login 2014-05-10 11:23:44 -04:00
Stian Thorgersen 2a820c73b1 Merge pull request #373 from stianst/master
KEYCLOAK-421 Set realm admin apps to bearer-only
2014-05-09 12:03:56 +01:00
Stian Thorgersen 624fcf6197 KEYCLOAK-421 Set realm admin apps to bearer-only 2014-05-09 12:03:39 +01:00
Stian Thorgersen 59747500aa Merge pull request #372 from stianst/login-session
KEYCLOAK-432 Added user sessions
2014-05-09 11:53:23 +01:00
Stian Thorgersen 6f0b12174c KEYCLOAK-432 Added user sessions 2014-05-09 11:52:45 +01:00
Bill Burke 5568c8dc7d Merge pull request #371 from patriot1burke/master
keycloak.js admin login
2014-05-08 20:08:52 -04:00
Bill Burke d957cc4883 Merge remote-tracking branch 'upstream/master' 2014-05-08 20:03:20 -04:00
Bill Burke 2d949b63b5 keycloak.js login for admin 2014-05-08 19:55:57 -04:00
Stian Thorgersen abdbef6a51 Merge pull request #370 from mposolda/master
Social fixes and improvements
2014-05-07 16:50:19 +01:00
mposolda c51011acef KEYCLOAK-354 Possibility for admin to see social links of some user in admin console 2014-05-07 17:28:13 +02:00
mposolda 6b1e0401ba KEYCLOAK-361 it shouldn't be possible to remove last social link if user don't have password 2014-05-07 17:28:13 +02:00
Stian Thorgersen d523242dbb Merge pull request #368 from mposolda/master
A bit more cleanup of dependencies
2014-05-07 12:52:22 +01:00
Stian Thorgersen 92058b16c9 Merge pull request #369 from abstractj/cleanup
Little code clean up
2014-05-07 12:52:09 +01:00
Bruno Oliveira 4424c425a6 Redundant initialization 2014-05-07 08:15:31 -03:00
Bruno Oliveira 5f7b0aae06 Variables will be never used 2014-05-07 08:15:02 -03:00
Bruno Oliveira f77e3b5532 Unused imports 2014-05-07 08:14:32 -03:00
Bruno Oliveira 334b981741 notBefore wasn't being assigned 2014-05-07 08:10:03 -03:00
Bruno Oliveira 957ff7d206 Make it final 2014-05-07 08:05:57 -03:00
Bruno Oliveira 5973ccd522 Scope can be private 2014-05-07 08:03:21 -03:00
Bruno Oliveira 1ea1f0af96 Removing redundant local variable 2014-05-07 07:49:45 -03:00
Bruno Oliveira f5ac81db41 Return not necessary here 2014-05-07 07:48:42 -03:00
Bruno Oliveira 9e7f52ccda extends Object isn't necessary 2014-05-07 07:47:39 -03:00
mposolda f8173e6a5a A bit more cleanup of dependencies 2014-05-07 11:08:47 +02:00
Bill Burke 5edf05d569 Merge pull request #366 from mposolda/export-import-rebased
Full export-import implemented. Remove dependency of mongo on picketlink...
2014-05-06 21:17:51 -04:00
Bill Burke 4666bcbfb2 Merge pull request #367 from patriot1burke/master
remove /rest from RealmsResource - pom fixes
2014-05-06 21:09:11 -04:00
Bill Burke a374e52ea5 /rest removal web.xml fixes 2014-05-06 21:08:27 -04:00
Bill Burke f987d331b7 /rest removal and pom fixes 2014-05-06 20:43:01 -04:00
Bill Burke 314f177fe7 Merge remote-tracking branch 'upstream/master' 2014-05-06 20:21:59 -04:00
Bill Burke 64f591769a remove /rest from RealmsResource 2014-05-06 20:21:49 -04:00
mposolda 0801c9c120 Full export-import implemented. Remove dependency of mongo on picketlink-common 2014-05-06 22:15:57 +02:00
Bill Burke e4e02a2615 Merge pull request #365 from patriot1burke/master
aerogear fix
2014-05-06 10:41:42 -04:00
Bill Burke ff69607f52 aerogear fix 2014-05-06 10:41:17 -04:00
Bill Burke a23b213736 Merge pull request #362 from matzew/JSP-Error
Removing JSP code, adding simple text for a simple demo...
2014-05-06 10:33:27 -04:00
Bill Burke 36ce4e04d9 Merge pull request #364 from patriot1burke/master
add aerogear stuff
2014-05-06 10:10:45 -04:00
Bill Burke 3b6593b476 add aerogear stuff 2014-05-06 10:10:17 -04:00
Bill Burke 6ef3102cd1 Merge pull request #361 from patriot1burke/master
remove ups social dependencies
2014-05-06 10:08:08 -04:00
Bill Burke 39381c104c merge fixes 2014-05-06 10:07:48 -04:00
Bill Burke c04b490f29 port fix 2014-05-06 09:59:52 -04:00
Stian Thorgersen e1f2d296bf Merge pull request #363 from stianst/master
Removed org.json
2014-05-06 13:05:30 +01:00
Stian Thorgersen 1d760388de KEYCLOAK-441 Remove org.json 2014-05-06 12:32:29 +01:00
Stian Thorgersen 8286d1ce34 Fix breadcrumb for audit pages£ 2014-05-06 12:26:17 +01:00
Matthias Wessendorf 7b14d29dee Removing JSP code, adding simple text for a simple demo... 2014-05-06 11:29:08 +02:00
Bill Burke 75224d25b0 remove picketlink dependencies 2014-05-05 18:50:41 -04:00
Bill Burke 3a3ae742a4 Merge pull request #360 from patriot1burke/master
adatper deployment context fixes, picketlink abstraction
2014-05-05 18:21:45 -04:00
Bill Burke e7c64b7812 adatper deployment context fixes, picketlink abstraction 2014-05-05 18:20:52 -04:00
Bill Burke e55eb73fb9 Merge pull request #359 from patriot1burke/master
fix tomcat7 build
2014-05-02 13:00:32 -04:00
Bill Burke 201b35be54 fix tomcat7 build 2014-05-02 13:00:12 -04:00
Bill Burke e25b2b05ae Merge pull request #352 from ungarida/master
Tomcat7 adapter
2014-05-02 12:36:06 -04:00
Bill Burke 6b470f826e Merge pull request #358 from patriot1burke/master
dynamic key lookup, relative uris
2014-05-02 12:34:18 -04:00
Bill Burke 4517d9d707 Merge remote-tracking branch 'upstream/master' 2014-05-02 12:30:31 -04:00
Bill Burke 7ff2c77a82 relative uri tests and fixes 2014-05-02 12:30:08 -04:00
Bill Burke e5e43173bc relative redirect uris 2014-05-02 10:58:29 -04:00
Bill Burke 6f3822e6ea relative adapter urls 2014-05-02 10:17:40 -04:00
Bill Burke 95bafc416d Merge pull request #357 from patriot1burke/master
fix mime type
2014-04-30 14:26:12 -04:00
Bill Burke 2576975988 fix mimetype 2014-04-30 14:25:23 -04:00
Bill Burke 8c5ae9d052 fix mimetype 2014-04-30 14:24:37 -04:00
Stian Thorgersen 8ed5282da5 Merge pull request #356 from stianst/master
Documentation
2014-04-30 14:38:27 +01:00
Stian Thorgersen 9b6d9fda43 Updated documentation for js adapter 2014-04-30 14:38:02 +01:00
Stian Thorgersen 77c6b391c4 Document how to enable social only login 2014-04-30 14:07:03 +01:00
Stian Thorgersen c8432f74f6 Merge pull request #355 from stianst/master
KEYCLOAK-211 Enable social only login
2014-04-30 13:36:25 +01:00
Stian Thorgersen 8fa3425886 KEYCLOAK-211 Enable social only login 2014-04-30 11:57:44 +01:00
Stian Thorgersen 84396d0da1 Merge pull request #354 from stianst/master
KEYCLOAK-333 Removed use of RestEasy's Logger
2014-04-30 11:06:51 +01:00
Stian Thorgersen 38e6bde07e KEYCLOAK-415 Make sure query params are included when navigating in acct mngmt 2014-04-30 11:03:13 +01:00
Stian Thorgersen 9811aaeecc KEYCLOAK-333 Removed use of RestEasy's Logger 2014-04-30 10:13:53 +01:00
Stian Thorgersen 7284aae4df Merge pull request #353 from stianst/constraints
Ensure role name unique within realm/app
2014-04-30 09:50:58 +01:00
Stian Thorgersen 316431c4d1 Ensure role name unique within realm/app 2014-04-30 09:50:29 +01:00
Stian Thorgersen bb039576d4 Merge pull request #351 from stianst/constraints
Ensure application and client names are unique within realm
2014-04-29 17:16:25 +01:00
Stian Thorgersen 646e762cbe Ensure user loginName and email unique within realm 2014-04-29 17:15:28 +01:00
Stian Thorgersen 1d94649b96 Ensure application and client names are unique within realm 2014-04-29 12:03:09 +01:00
Stian Thorgersen 1fa019e9dd Merge pull request #350 from stianst/constraints
Enforce that realm name is unique in model
2014-04-29 10:44:42 +01:00
Stian Thorgersen 364998b34b Enforce that realm name is unique in model 2014-04-29 10:43:27 +01:00
Stian Thorgersen 6778fbfa3b Merge pull request #349 from mposolda/master
Fix testsuite with mongo. Upgrade picketlink and enable connection pooling for LDAP
2014-04-29 10:23:22 +01:00
mposolda bb11ad2ec1 KEYCLOAK-419 Upgrade picketlink dependency and enable ldap connection pooling 2014-04-29 11:10:10 +02:00
mposolda b6386630fb Fix testsuite with mongo 2014-04-29 10:37:43 +02:00
Bill Burke 363e5cdf64 Merge pull request #348 from patriot1burke/master
KeycloakApplication refactor
2014-04-28 18:05:59 -04:00
Bill Burke 7594be8014 merge 2014-04-28 18:05:03 -04:00
Bill Burke 62f8811a46 Merge remote-tracking branch 'upstream/master'
Conflicts:
	bundled-war-example/src/main/java/org/keycloak/server/KeycloakServerApplication.java
	bundled-war-example/src/main/webapp/WEB-INF/web.xml
2014-04-28 18:04:50 -04:00
Bill Burke 2d1dc4a874 application refactor 2014-04-28 17:34:06 -04:00
Stian Thorgersen 0546aebc84 More fixes to bundled war example 2014-04-28 14:32:25 +01:00
Stian Thorgersen c06009d5fb KEYCLOAK-430 Fix bundled war example 2014-04-28 13:36:34 +01:00
Stian Thorgersen 3d02fd5d0e KEYCLOAK-429 Remove role from composite roles when deleted 2014-04-28 12:55:04 +01:00
Bill Burke 562f6703b6 Merge remote-tracking branch 'upstream/master' 2014-04-25 13:15:00 -04:00
Stian Thorgersen 573c88564b Temporarily disabled unique constraint on Realm names as it breakes tests 2014-04-25 17:58:49 +01:00
Stian Thorgersen dabf101d96 Merge pull request #347 from stianst/master
Ensure Realm names are unique
2014-04-25 17:02:29 +01:00
Stian Thorgersen 292089cee8 Ensure Realm names are unique 2014-04-25 17:02:03 +01:00
Bill Burke 5594c73ceb Merge remote-tracking branch 'upstream/master' 2014-04-25 10:34:35 -04:00
Stian Thorgersen ce6652efb1 Merge pull request #346 from stianst/master
KEYCLOAK-347 Link realm and realm-permissions application
2014-04-25 15:32:47 +01:00
Stian Thorgersen f64f55a4c6 KEYCLOAK-347 Link realm and realm-permissions application 2014-04-25 15:32:28 +01:00
Bill Burke 9a3a8c39f4 merge 2014-04-25 10:03:56 -04:00
Bill Burke 1de4c31750 wtf 2014-04-25 10:02:49 -04:00
Bill Burke bda85f700a Merge pull request #343 from matzew/master
Adding simple CDI injection into resources
2014-04-25 09:58:59 -04:00
Stian Thorgersen 3471ce6c63 Merge pull request #345 from stianst/master
KEYCLOAK-385 Add CORS support to refresh token
2014-04-25 14:09:56 +01:00
Stian Thorgersen b8dfac391a KEYCLOAK-385 Add CORS support to refresh token 2014-04-25 14:09:39 +01:00
Stian Thorgersen 28546ad031 Merge pull request #344 from stianst/master
Theme support for admin
2014-04-25 13:59:41 +01:00
Stian Thorgersen d6e5e376bf Theme support for admin 2014-04-25 13:58:58 +01:00
Matthias Wessendorf 9b055c6ad6 Adding simple CDI injection into resources 2014-04-25 13:24:21 +02:00
Stian Thorgersen a3c17d1071 Merge pull request #342 from stianst/master
Added support for common resources to themes
2014-04-24 09:27:02 +01:00
Stian Thorgersen d57cd1aa91 Added support for common resources to themes 2014-04-24 09:26:19 +01:00
Bill Burke 3405330d92 Merge pull request #341 from patriot1burke/master
brute force fixes
2014-04-23 17:56:34 -04:00
Bill Burke 541e865fe8 brute force fixes 2014-04-23 17:55:13 -04:00
Davide Ungari c03b97d2d4 #cfg update version 2014-04-20 12:06:31 +02:00
Davide Ungari 5d275de8b2 #dev integrated adapter tomcat7 2014-04-18 08:32:42 +02:00
Bill Burke 80f3a3152c Merge pull request #340 from patriot1burke/master
brute force settings
2014-04-15 11:37:49 -04:00
Bill Burke 54abfb670c brute force settings 2014-04-15 11:37:27 -04:00
Bill Burke b41bf9f231 Merge pull request #339 from patriot1burke/master
more brute force detection
2014-04-14 18:59:09 -04:00
Bill Burke 2b8d2288fb more brute force detection 2014-04-14 18:58:45 -04:00
Bill Burke b556ff8a83 Merge pull request #338 from patriot1burke/master
move things around
2014-04-14 16:53:51 -04:00
Bill Burke 4c8471ef43 move things around 2014-04-14 16:51:53 -04:00
Bill Burke 1aa58ec580 Merge pull request #337 from patriot1burke/master
app/keycloak self bootstrapping bundle
2014-04-11 13:26:22 -04:00
Bill Burke 272806a3f3 app/keycloak self bootstrapping bundle 2014-04-11 13:24:07 -04:00
Bill Burke 51a718f337 Merge pull request #336 from patriot1burke/master
workarounds for resteasy 2.3.7 bugs
2014-04-10 22:34:19 -04:00
Bill Burke cc982cf246 workarounds for resteasy 2.3.7 bugs 2014-04-11 10:33:53 -04:00
Bill Burke 0896808625 Merge pull request #334 from mposolda/master
Reenable AuthProvidersIntegrationTest.registerUserLdapSuccess. Add varia...
2014-04-10 12:16:08 -04:00
Bill Burke c562e88e75 Merge pull request #335 from patriot1burke/master
fix server jboss-deployment-structure
2014-04-10 12:15:57 -04:00
Bill Burke abd7163205 fix server jboss-deployment-structure 2014-04-11 00:15:35 -04:00
mposolda 1701afb6d4 Fix standalone KeycloakServer 2014-04-10 14:59:54 +02:00
mposolda d8937b11cf Reenable AuthProvidersIntegrationTest.registerUserLdapSuccess. Add variable sleep after undertow stop in testsuite (some windows envs have issues when server is not fully stopped) 2014-04-10 10:29:13 +02:00
Bill Burke de871585e0 Merge pull request #333 from patriot1burke/master
remove transitive dependencies
2014-04-09 23:30:16 -04:00
Bill Burke b41c45d40a remove transitive dependencies 2014-04-10 11:29:47 -04:00
Bill Burke ecaa0d1401 use resteasy 2.3.7 2014-04-10 05:21:07 -04:00
Bill Burke cdc35d99bc cleanup 2014-04-09 22:34:36 -04:00
Bill Burke f5f96c5021 Merge pull request #332 from patriot1burke/master
use resteasy 2.3.7
2014-04-09 17:21:37 -04:00
Bill Burke 29a139f56b Merge pull request #331 from patriot1burke/master
cleanup
2014-04-09 14:00:19 -04:00
Stian Thorgersen daf1f2ed45 Merge pull request #330 from mposolda/master
Fix LDAP test on windows. Ensure that directory with data for embedded A...
2014-04-09 18:44:57 +01:00
mposolda eb37890924 Fix LDAP test on windows. Ensure that directory with data for embedded ApacheDS is deleted 2014-04-09 18:56:36 +02:00
Stian Thorgersen eb3e69d5d7 Updated audit timer 2014-04-09 06:40:15 +01:00
mposolda 5aefe52ccc Refactoring of Authentication SPI and Picketlink to use ProviderSessions
Refactoring of ProviderSessionFactory to support dependencies between components
Calling lifecycle methods
Removing KeycloakRegistry
2014-04-09 00:34:01 +02:00
mposolda 0d00db281a Fix the case when user is directly deleted in LDAP server 2014-04-09 00:06:04 +02:00
mposolda c8c4cfbaae Restructure of authentication module and packages 2014-04-09 00:06:04 +02:00
Bill Burke d5be56fa21 Merge pull request #328 from patriot1burke/master
fix broken build
2014-04-08 11:33:38 -04:00
Bill Burke 1d55a4f1e9 fix broken build 2014-04-08 23:32:26 -04:00
Stian Thorgersen 83bc115b63 Merge pull request #327 from stianst/master
Add timer jars to server
2014-04-08 13:09:26 +01:00
Stian Thorgersen e952ff142d Add timer jars to server 2014-04-08 13:09:06 +01:00
Stian Thorgersen b94bad7f58 Merge pull request #326 from stianst/master
Clearing audit events through admin console and through timer
2014-04-08 12:43:52 +01:00
Stian Thorgersen 354cf02aaa Fix audit mongo tests 2014-04-08 12:43:01 +01:00
Stian Thorgersen 7f0cf3eda8 Allow clearing audit events through admin console, and added timer to clear expired events 2014-04-08 11:32:20 +01:00
Stian Thorgersen 9bc0bd452d Merge pull request #325 from mposolda/master
Logging message during ldap bootstrap
2014-04-08 09:43:05 +01:00
mposolda d124f43423 Logging message during ldap bootstrap 2014-04-07 19:40:02 +02:00
Stian Thorgersen a197bda363 Merge pull request #324 from stianst/master
Audit configurable through admin console
2014-04-07 18:06:43 +01:00
Stian Thorgersen 8ca46fa35d Audit configurable through admin console 2014-04-07 17:58:52 +01:00
Stian Thorgersen aec8feab49 Merge pull request #323 from stianst/master
Move setting cors properties
2014-04-07 13:59:39 +01:00
Stian Thorgersen e7c30fff48 Move setting cors properties 2014-04-07 13:58:35 +01:00
Stian Thorgersen 2916cce6fb Merge pull request #322 from stianst/master
KEYCLOAK-411 Set cors properties in KeycloakDeployment
2014-04-07 13:39:53 +01:00
Stian Thorgersen bf95c2ba85 KEYCLOAK-411 Set cors properties in KeycloakDeployment 2014-04-07 13:39:32 +01:00
Stian Thorgersen 6081572179 Merge pull request #321 from stianst/master
Fix testsuite for mongo
2014-04-07 13:38:01 +01:00
Stian Thorgersen bbf5fee320 Fix testsuite for mongo 2014-04-07 13:35:26 +01:00
Stian Thorgersen d66862fd26 Merge pull request #320 from matzew/master
Adding JPA-Audit PU
2014-04-07 13:21:26 +01:00
Matthias Wessendorf 1c0ef4621e Adding JPA-Audit PU 2014-04-07 14:01:31 +02:00
Stian Thorgersen 323e032287 Merge pull request #319 from stianst/master
Update admin console to allow changing context-path for KC
2014-04-07 11:21:48 +01:00
Stian Thorgersen 948960f33f Allow changing base url for Keycloak 2014-04-07 10:54:27 +01:00
Stian Thorgersen abde247e14 Moved admin-ui-styles into admin-ui 2014-04-07 10:37:21 +01:00
Stian Thorgersen a0cd2bf5a7 Merge pull request #318 from mposolda/ldap
Basic support for registration of new users in AuthenticationProvider (like LDAP). Other improvements in auth SPI
2014-04-07 09:35:35 +01:00
mposolda 58083fbb96 Hide password tab in acct management if passwordUpdate not supported 2014-04-04 23:47:12 +02:00
mposolda ad068a300b Basic support for registration of new users in AuthenticationProvider 2014-04-04 19:53:02 +02:00
mposolda be320e11a5 Improve handling of exceptions thrown from picketlink 2014-04-04 16:35:26 +02:00
Stian Thorgersen b7826be103 Merged humanfriendly filter with capitalize 2014-04-04 15:30:06 +01:00
Stian Thorgersen 216e24864a Merge branch 'ldap' of https://github.com/mposolda/keycloak into mposolda-ldap
Conflicts:
	admin-ui/src/main/resources/META-INF/resources/admin/js/app.js
	admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/realm.js
2014-04-04 15:29:03 +01:00
Stian Thorgersen afea032322 Merge pull request #317 from stianst/master
Added audit to admin console
2014-04-04 15:19:40 +01:00
Stian Thorgersen 88ddc8ebca Added audit to admin console 2014-04-04 15:16:08 +01:00
mposolda 2aac603fad Added configuration of authentication providers into admin console 2014-04-04 13:20:12 +02:00
Stian Thorgersen 8caf3fa83a Added details to log view in acct mngmt 2014-04-04 11:01:18 +01:00
Stian Thorgersen 42975f0edf Merge pull request #315 from stianst/master
Added audit log to account mngmt
2014-04-03 18:24:11 +01:00
Stian Thorgersen 3433227fa7 Added audit log to account mngmt 2014-04-03 16:27:31 +01:00
Stian Thorgersen e6067c915d Added ProviderSession to requests 2014-04-03 16:27:31 +01:00
Stian Thorgersen fcfbf156ce Merge pull request #314 from mposolda/ldap
Fixing testsuite failures with mongo model
2014-04-03 10:26:54 +01:00
mposolda d564955cab Fixing testsuite failures with mongo model 2014-04-03 10:58:39 +02:00
Bill Burke 30d523a5c2 Merge pull request #313 from patriot1burke/master
brute force protection
2014-04-02 20:27:15 -04:00
Bill Burke 126b444d77 brute force merge 2014-04-02 20:26:33 -04:00
Bill Burke d58870545f brute force protection 2014-04-02 20:09:14 -04:00
Bill Burke 231e8895a5 Merge pull request #309 from vibe13/master
Cleaning of pom.xml files
2014-04-02 11:39:04 -04:00
Bill Burke 7d7b9e5b73 Merge pull request #312 from mposolda/ldap
Refactoring of AuthenticationProvider SPI. Add Ldap settings into admin console
2014-04-02 11:37:11 -04:00
mposolda 25bf6d63b4 Refactoring of AuthenticationProvider SPI 2014-04-02 17:27:07 +02:00
mposolda 05cd8a82e5 Storing default AuthenticationProvider at the realm creation time 2014-04-02 17:17:33 +02:00
mposolda 1c218c8e9b Add Ldap settings into admin console 2014-04-02 17:17:32 +02:00
Stian Thorgersen 8af81cd290 Merge pull request #311 from stianst/master
Added JPA and Mongo audit providers. Add audit deps to server war.
2014-04-02 14:05:07 +01:00
Stian Thorgersen 869601d041 Added audit deps to server war 2014-04-02 11:37:22 +01:00
Stian Thorgersen 21239fbab9 Added Mongo audit provider 2014-04-01 18:00:35 +01:00
Stian Thorgersen 722a077de7 Added JPA audit provider£ 2014-04-01 15:13:53 +01:00
Stian Thorgersen 1e15e97d17 Merge pull request #310 from stianst/audit
Started audit
2014-03-31 17:43:42 +01:00
Stian Thorgersen 225307e855 KEYCLOAK-389 Added AuditListener SPI
KEYCLOAK-390 Added JBoss Logging AuditListener
KEYCLOAK-391 Audit Token events
2014-03-31 17:35:14 +01:00
Andrea Vibelli 84f1e1b56e Extraction into properties of maven-compiler-plugin source and target 2014-03-31 11:17:16 +02:00
Andrea Vibelli bdf1c1f495 Remove unnecessary version declaration and insertion of groupId 2014-03-31 10:45:11 +02:00
Andrea Vibelli 5e1da96177 Remove unnecessary version declarations 2014-03-31 10:44:59 +02:00
Andrea Vibelli 3ddb2084cd Remove duplicated dead code 2014-03-31 10:44:47 +02:00
Andrea Vibelli d831e25366 Remove unnecessary groupId declarations 2014-03-31 10:44:34 +02:00
Andrea Vibelli 37fdc50fb4 Remove warnings about no schema definition in pom.xml files 2014-03-31 10:44:22 +02:00
Bill Burke d8a3025ea1 Merge remote-tracking branch 'upstream/master' 2014-03-27 14:10:01 -04:00
Bill Burke 911cf2ae45 Merge pull request #307 from jpkrohling/JavascriptCharset
Fixed charset issue while decoding token with atob
2014-03-27 11:40:48 -04:00
Bill Burke 60ba41e82f Merge pull request #308 from mposolda/ldap
Fix LDAP tests and teststuite on windows. Set initial password directly ...
2014-03-27 11:40:28 -04:00
mposolda 129eb6a3be Fix LDAP tests and teststuite on windows. Set initial password directly in code as import from LDIF is problematic on windows 2014-03-27 16:20:03 +01:00
Juraci Paixão Kröhling 34fbdf4358 Fixed charset issue while decoding token with atob 2014-03-27 09:48:16 +01:00
Bill Burke 51b3de7383 unfix uribuilder 2014-03-26 10:19:56 -04:00
Bill Burke 0ec19c9ec9 uribuilder fix 2014-03-26 10:09:41 -04:00
Bill Burke 4711dd083f Merge pull request #306 from mposolda/master
Remove unfinished ldap-settings tab, which I've added accidentally in pr...
2014-03-26 09:42:57 -04:00
mposolda bcc0bcd219 Remove unfinished ldap-settings tab, which I've added accidentally in previous PR 2014-03-26 14:38:11 +01:00
Stian Thorgersen 00aaefb926 Merge pull request #305 from mposolda/master
Added Authentication SPI dependencies to auth-server.war
2014-03-26 12:45:51 +00:00
mposolda 3302c54c43 Added Authentication SPI dependencies to auth-server.war 2014-03-26 12:57:11 +01:00
Stian Thorgersen 434dec2318 Merge pull request #304 from mposolda/ldap
KEYCLOAK-388 - Auth SPI should be able to differentiate between the INVA...
2014-03-26 11:55:34 +00:00
mposolda 96a05a9b77 Console: work in progress 2014-03-26 12:25:46 +01:00
mposolda 77a44751a6 KEYCLOAK-388 - Auth SPI should be able to differentiate between the INVALID_USERNAME and INVALID_CREDENTIALS 2014-03-26 09:49:47 +01:00
Stian Thorgersen 51b95b1b91 Merge pull request #303 from mposolda/ldap
Fixes in AuthenticationProvider. Fixing testsuite
2014-03-25 14:17:31 +00:00
mposolda ab02dea902 Fixes in AuthenticationProvider. Fixing testsuite 2014-03-25 15:05:08 +01:00
Bill Burke 28a1bd8535 Merge pull request #302 from mposolda/ldap
Authentication SPI. Implementations based on Picketlink+LDAP, model and ...
2014-03-25 08:42:27 -04:00
Stian Thorgersen a2a8e72e20 Merge pull request #301 from stianst/master
Fixes to JS sdk
2014-03-25 10:37:48 +00:00
Stian Thorgersen 4788dd8bd2 Fixes to JS sdk 2014-03-25 10:37:20 +00:00
mposolda 793f69d4b6 Authentication SPI. Implementations based on Picketlink+LDAP, model and external model (other realm). Added KeycloakRegistry 2014-03-24 23:11:11 +01:00
Stian Thorgersen 0879013a90 Merge pull request #300 from corinnekrych/readme.instructions.improvement
fix typos and formatting
2014-03-24 09:36:35 +00:00
corinnekrych 877a552f3b fix typos and formatting 2014-03-21 17:34:24 +01:00
Stian Thorgersen 2403e1f465 Merge pull request #299 from stianst/master
Added support for Cordova to keycloak.js
2014-03-19 17:02:05 +00:00
Stian Thorgersen 119423895d Removed files that shouldn't have been committed 2014-03-19 16:54:20 +00:00
Stian Thorgersen 702ae0307e Fixes to account referrer to allow configurable referrer uri based on app redirect uri 2014-03-19 16:52:41 +00:00
Stian Thorgersen b5bdeae2a2 Updates to keycloak.js, including adding support for Cordova
Conflicts:
	examples/cordova/example-realm.json
	examples/js-console/src/main/webapp/index.html
	integration/js/src/main/resources/META-INF/resources/js/keycloak.js
2014-03-19 16:52:41 +00:00
Stian Thorgersen 4159a97881 Merge pull request #298 from stianst/master
Updates to keycloak.js
2014-03-18 14:44:42 +00:00
Stian Thorgersen 2d5e6520db Updates to keycloak.js 2014-03-18 14:43:48 +00:00
Stian Thorgersen 331ab71427 KEYCLOAK-380 Added OAuth2Constants 2014-03-15 10:43:52 +00:00
Stian Thorgersen f9aaa16cfe KEYCLOAK-378 KEYCLOAK-379 KEYCLOAK-381 Fix refresh token if token contains app roles. Changed long time fields in AccessCode and AccessToken to int 2014-03-15 10:15:10 +00:00
Stian Thorgersen 2ebc32793a Started installed application adapter 2014-03-14 17:01:08 +00:00
Bill Burke cec948ffb4 Merge pull request #297 from patriot1burke/master
further adapter tests
2014-03-14 11:21:53 -04:00
Bill Burke 466b6762d9 further adapter tests 2014-03-14 11:21:32 -04:00
Bill Burke e03737c665 Merge pull request #296 from patriot1burke/master
adapter testing
2014-03-13 21:48:14 -04:00
Bill Burke 3f1b7a0335 adapter testing 2014-03-13 21:47:46 -04:00
Bill Burke f26f2faa72 Merge pull request #295 from patriot1burke/master
bump version to beta-1 snapshot
2014-03-13 11:25:01 -04:00
Bill Burke 7763da1273 bump version to beta-1 snapshot 2014-03-13 11:24:38 -04:00
Bill Burke bb6791d6eb Merge pull request #294 from patriot1burke/master
bump version
2014-03-13 10:58:48 -04:00
Bill Burke 1c6b867079 bump version 2014-03-13 10:58:22 -04:00
Bill Burke 6b57684c52 Merge pull request #293 from patriot1burke/master
NPE in create user
2014-03-13 10:57:13 -04:00
Bill Burke 08769a2daa NPE in create user 2014-03-13 10:56:09 -04:00
Stian Thorgersen 7fff2588b2 Merge pull request #292 from stianst/master
Set next version
2014-03-13 09:12:18 +00:00
Stian Thorgersen ee5cab04e0 Set next version 2014-03-13 09:10:42 +00:00
Bill Burke 9f429e4150 Merge pull request #291 from patriot1burke/master
bump
2014-03-12 17:07:24 -04:00
Bill Burke 9528dbc4dc realm name in OTP 2014-03-12 17:05:57 -04:00
Bill Burke 3ff8d0fd1f bump version 2014-03-12 16:48:12 -04:00
Bill Burke 7b64d9975e Merge pull request #286 from secondsun/KEYCLOAK-355
Fixing java 8 build
2014-03-12 16:43:03 -04:00
Bill Burke ba60a0c04b Merge pull request #289 from stianst/master
Added a README.md in the root of examples to describe the difference bet...
2014-03-12 16:42:48 -04:00
Bill Burke 6926f02cc3 Merge pull request #290 from patriot1burke/master
buncha stuff
2014-03-12 15:58:22 -04:00
Bill Burke 52018b1f81 revoke on logoutAll 2014-03-12 15:57:43 -04:00
Bill Burke fcc95ef99b fix delete realm 2014-03-12 15:00:31 -04:00
Stian Thorgersen 2f29fab931 Added a README.md in the root of examples to describe the difference between preconfigured-demo and unconfigured-demo 2014-03-12 17:15:54 +00:00
Stian Thorgersen 0c2767afd7 Minor updates to docs 2014-03-12 17:15:04 +00:00
Stian Thorgersen 4a90133d29 Added customer-portal-js and customer-portal-cli to example testrealm.js and added instructions for customer-portal-cli to README.md 2014-03-12 17:14:40 +00:00
Stian Thorgersen 3c40e9694f Merge pull request #287 from stianst/master
Added subject in token changed to user id to migration doc
2014-03-12 15:59:27 +00:00
Stian Thorgersen 30358a7582 Added subject in token changed to user id to migration doc 2014-03-12 15:59:04 +00:00
Summers Pittman 20880ffd71 Fixing java 8 build 2014-03-12 10:40:47 -04:00
Bill Burke e48cc006f6 Merge remote-tracking branch 'upstream/master' 2014-03-12 10:17:24 -04:00
Bill Burke accb56be7f user import fix 2014-03-12 10:17:09 -04:00
Stian Thorgersen a1ea79e382 Revert changes to lib until it works on 7 and 8 2014-03-12 14:11:05 +00:00
Stian Thorgersen a1f10ef54b Merge pull request #285 from stianst/master
Add user friendly username for social links. Show access denied if social login is cancelled
2014-03-12 13:52:28 +00:00
Stian Thorgersen fbc39e82a1 KEYCLOAK-365 Add IDToken properties to JS SDK 2014-03-12 11:31:59 +00:00
Stian Thorgersen 0214827492 KEYCLOAK-364 Show access denied if social login is cancelled 2014-03-12 09:21:11 +00:00
Stian Thorgersen 6dc156712e KEYCLOAK-359 Add user friendly username for social links 2014-03-12 08:52:47 +00:00
Bill Burke 53f671e8af Merge pull request #283 from patriot1burke/master
adapter security context propagation
2014-03-11 18:08:23 -04:00
Bill Burke a15e7d1f6e add security domain docs 2014-03-11 17:57:35 -04:00
Bill Burke e836371887 security context propagation 2014-03-11 17:40:53 -04:00
Viliam Rockai 53b596d435 KEYCLOAK-336 removed non-working pagination from role list 2014-03-11 17:54:20 +00:00
Viliam Rockai 0dbd4417af KEYCLOAK-360 fixed account template menu 2014-03-11 18:24:10 +01:00
Viliam Rockai d1b1a98a0a KEYCLOAK-356 added autofocus to the new passwd field 2014-03-11 18:24:10 +01:00
Viliam Rockai ccc4f5a114 KEYCLOAK-362 - fixing the select2 with req user actions 2014-03-11 18:24:10 +01:00
Stian Thorgersen 03a0cce119 Merge pull request #281 from stianst/master
KEYCLOAK-357 KEYCLOAK-358 Set enabled default to true when creating appl...
2014-03-11 13:53:42 +00:00
Stian Thorgersen 26b3ec0b2a KEYCLOAK-357 KEYCLOAK-358 Set enabled default to true when creating applications, clients and users 2014-03-11 13:53:15 +00:00
Stian Thorgersen 7992509fde Merge pull request #280 from stianst/master
KEYCLOAK-355 Fix distribution build on JDK8
2014-03-11 09:52:52 +00:00
Stian Thorgersen b208cae333 KEYCLOAK-355 Fix distribution build on JDK8 2014-03-11 09:52:22 +00:00
Bill Burke 9749c65065 Merge pull request #278 from cardosogabriel/master
Adjustments on headers (top bar)
2014-03-10 20:08:14 -04:00
Bill Burke 9109642821 Merge pull request #279 from patriot1burke/master
refactor adapters complete
2014-03-10 20:08:06 -04:00
Gabriel Cardoso b6503748ca Adjusting headers to make them horizontally aligned to the content 2014-03-10 20:59:57 -03:00
Bill Burke 0284d040dc refactor adapters complete 2014-03-10 18:52:57 -04:00
Stian Thorgersen d8c13c9ac2 Merge pull request #277 from stianst/master
Remove clientSecret required in JS lib, and removed storing token to ses...
2014-03-10 17:28:38 +00:00
Stian Thorgersen be7008f253 Remove clientSecret required in JS lib, and removed storing token to sessionStore 2014-03-10 17:27:05 +00:00
Stian Thorgersen 63bc2d6dbb Merge pull request #276 from mposolda/account-social
KEYCLOAK-26 Linking social providers to existing account
2014-03-10 11:43:01 +00:00
mposolda 3d0d130622 KEYCLOAK-26 Linking social providers to existing account 2014-03-10 11:31:59 +01:00
Bill Burke 8c3225914c Merge pull request #273 from cardosogabriel/master
Improvements in the console header, content area background, favicon and logos
2014-03-07 18:48:45 -05:00
Bill Burke 798e3ce86b Merge pull request #274 from patriot1burke/master
adapter refactoring
2014-03-07 18:48:31 -05:00
Bill Burke 49c79f156a adapter refactoring 2014-03-07 18:48:02 -05:00
Gabriel Cardoso d3634c1180 Updated FavIcon and Keycloak Logos
- more attractive favicon
- updated keycloak logos (bigger distance between the symbol and text)
2014-03-07 18:51:10 -03:00
Gabriel Cardoso c345ee9e5a Fixing Content Area Background
- Now there is no vertical scroll when the content does not occupy the
full height;
- The background area / borders go until the bottom for longer pages
2014-03-07 15:05:22 -03:00
Gabriel Cardoso 12f080e803 Full width header 2014-03-07 14:49:55 -03:00
Bill Burke 2b01de5ecf remove transaction 2014-03-07 08:35:41 -05:00
Stian Thorgersen 61102845ed Merge pull request #271 from mposolda/mongo
Fix mongo to pass with testsuite. Other improvements
2014-03-07 13:01:26 +00:00
Stian Thorgersen ca3b28fda7 Merge pull request #272 from stianst/master
Added docs for installed applications
2014-03-07 13:00:59 +00:00
Stian Thorgersen 854158a9c2 Added docs for installed applications 2014-03-07 13:00:20 +00:00
mposolda 11bcd84738 Added MongoClientProvider. Possibility to configure mongo from external source 2014-03-07 13:39:43 +01:00
mposolda da3f1a21a2 Fix testsuite with Mongo. Added ClientAdapter and ClientEntity to mongo model to improve inheritance 2014-03-07 12:24:41 +01:00
Stian Thorgersen 2edb93ef54 Merge pull request #270 from stianst/master
Added documentation for admin access control
2014-03-07 09:11:00 +00:00
Stian Thorgersen 0f0353674d Added documentation for admin access control 2014-03-07 09:10:16 +00:00
Bill Burke 62b0789e5f Merge pull request #269 from patriot1burke/master
refactor adapters
2014-03-06 21:16:30 -05:00
Bill Burke 26d0f993ba formating for oauth client 2014-03-06 21:16:07 -05:00
Bill Burke a653e5a406 refactor adapters 2014-03-06 21:13:55 -05:00
Bill Burke 0fd0240be7 Merge pull request #268 from cardosogabriel/master
Adjusting font-sizes, margins and a few design details
2014-03-06 15:15:27 -05:00
Gabriel Cardoso 3ea9df89a9 Adjusting font-sizes, margins and a few design details 2014-03-06 16:05:19 -03:00
Bill Burke 3c463419ca Merge pull request #267 from patriot1burke/master
client type selection, remove scope param support
2014-03-06 10:27:10 -05:00
Bill Burke dd292c1d52 remove scope support for now part 2 2014-03-06 10:26:46 -05:00
Bill Burke 801ef3281a remove scope support for now 2014-03-06 09:59:27 -05:00
Bill Burke 8f29bf0a5a client type selection 2014-03-06 09:48:52 -05:00
Stian Thorgersen 6f752e68c8 Merge pull request #266 from stianst/master
Added basic command-line example
2014-03-06 12:09:22 +00:00
Stian Thorgersen 12978a4343 Added basic command-line example 2014-03-06 12:08:44 +00:00
Bill Burke b543e22eee Merge pull request #265 from patriot1burke/master
public clients
2014-03-05 20:26:52 -05:00
Bill Burke 599faa3cb5 public clients 2014-03-05 20:26:27 -05:00
Bill Burke d7b616773a Merge pull request #264 from patriot1burke/master
session mgmt as7
2014-03-05 15:00:37 -05:00
Bill Burke 633ddb70e7 session mgmt as7 2014-03-05 15:00:21 -05:00
Stian Thorgersen d0a6a8ae3b Merge pull request #263 from stianst/master
Added support for any port with http://localhost redirect uri. Added Config to centralize system properties used to configure KC
2014-03-05 15:23:29 +00:00
Stian Thorgersen 60bb05e6ca Added Config to centralize system properties used to configure KC 2014-03-05 15:20:53 +00:00
Stian Thorgersen 0219aa1e4c Added support for any port with http://localhost redirect uri 2014-03-05 12:54:57 +00:00
Bill Burke 34260b7428 Merge pull request #262 from patriot1burke/master
session mgmt
2014-03-04 22:25:56 -05:00
Bill Burke d6bd02ea7d session mgmt 2014-03-04 22:25:33 -05:00
Bill Burke 7699dd2701 Merge remote-tracking branch 'upstream/master' 2014-03-04 15:52:40 -05:00
Bill Burke 2d86b29b6c session stats 2014-03-04 15:52:27 -05:00
Stian Thorgersen 67db515fe1 Fix for small height 2014-03-04 15:41:06 +00:00
Stian Thorgersen df61879fb1 Merge pull request #261 from stianst/master
Fixes to cors for js. Improvements to login form for small screens. Fix ng-disabled with kc-read-only forms
2014-03-04 15:28:51 +00:00
Stian Thorgersen 77259320cf Fix js for cors requests 2014-03-04 15:27:13 +00:00
Stian Thorgersen e0dff8104d Fix ng-disabled when used with kc-read-only forms 2014-03-04 15:25:55 +00:00
Stian Thorgersen 9816fdd842 Improvements to login forms for small screen 2014-03-04 15:25:55 +00:00
Bill Burke 9d4cc19e62 Merge pull request #260 from patriot1burke/master
revocation app level
2014-03-03 17:10:34 -05:00
Bill Burke 06288fa07b revocation app level 2014-03-03 17:10:15 -05:00
Bill Burke 735486c36e Merge pull request #259 from patriot1burke/master
revocation and fix login.ftl
2014-03-03 16:32:22 -05:00
Bill Burke d783c6200e fix login.ftl page 2014-03-03 16:30:09 -05:00
Bill Burke e307916233 revocation ui 2014-03-03 16:01:22 -05:00
Bill Burke 01154f18dd Merge remote-tracking branch 'upstream/master' 2014-03-03 15:50:21 -05:00
Bill Burke 716972347d revocation 2014-03-03 15:50:10 -05:00
Stian Thorgersen 4b8c6f338a Merge pull request #258 from stianst/master
Fix social tab, and minor fixes to xs screens
2014-03-03 13:43:51 +00:00
Stian Thorgersen 170afedd19 Minor fixes for login forms on xs screens 2014-03-03 13:43:05 +00:00
Stian Thorgersen 8881ba2d72 Fix social tab not showing 2014-03-03 13:42:40 +00:00
Stian Thorgersen 1cff76922b Merge pull request #257 from stianst/master
Fixes to login forms, and started support for installed applications (for Cordova)
2014-03-03 13:00:18 +00:00
Stian Thorgersen c0f49763f1 Updates to login form styles 2014-03-03 12:58:57 +00:00
Stian Thorgersen 87aaaf0b06 Started support for installed applications 2014-03-03 12:58:16 +00:00
Bill Burke ec309e7e02 Merge pull request #256 from patriot1burke/master
refactor getRoleById, fix bugs
2014-03-02 20:41:48 -05:00
Bill Burke 22b25a0d9e KEYCLOAK-341 2014-03-02 20:40:34 -05:00
Bill Burke 8126110312 refactor getRoleById 2014-03-02 20:28:58 -05:00
Bill Burke f8eb56d6b7 Merge remote-tracking branch 'upstream/master' 2014-03-02 18:09:55 -05:00
Bill Burke 21b1ad5e0a remove application sessions tab 2014-03-02 17:56:22 -05:00
Bill Burke 5eddacfee9 Merge pull request #255 from patriot1burke/master
revocation
2014-03-02 17:46:49 -05:00
Bill Burke c8023c6651 revocation next phase: undertow complete 2014-03-02 17:32:25 -05:00
Bill Burke 7b30cc59b8 revocation phase 1 2014-02-28 19:47:05 -05:00
Bill Burke 581d64614e Merge pull request #254 from patriot1burke/master
add claims to grant page
2014-02-28 10:45:54 -05:00
Bill Burke 0d309d058c add claims to grant page 2014-02-28 10:45:12 -05:00
Bill Burke 11559cba50 public realm info update 2014-02-28 09:52:53 -05:00
Bill Burke e02d3748a9 Merge pull request #253 from patriot1burke/master
fix NPE
2014-02-28 09:20:09 -05:00
Bill Burke 236d67f78d Merge remote-tracking branch 'upstream/master' 2014-02-28 09:19:45 -05:00
Bill Burke 4dc4c56921 fix NPE 2014-02-28 09:19:26 -05:00
Stian Thorgersen cec3df71ca Merge pull request #252 from stianst/master
Fix form sometimes read-only on refresh
2014-02-28 10:36:30 +00:00
Stian Thorgersen 63aa303673 Fix form sometimes read-only on refresh 2014-02-28 10:35:34 +00:00
Bill Burke 3e68cc601a Merge pull request #250 from vrockai/FORMDIS
AngularJS update and directives refactoring
2014-02-27 16:50:10 -05:00
Bill Burke 918e3d17f6 Merge pull request #251 from patriot1burke/master
refactor out clientmodel.getAgent()
2014-02-27 16:49:30 -05:00
Bill Burke c78d1c90e4 remove clientmodel.getAgent() 2014-02-27 16:48:34 -05:00
Bill Burke 3fc273070e remove clientmodel.agent phase1 2014-02-27 13:55:04 -05:00
Viliam Rockai 7aa7df43aa KEYCLOAK-276 select2 lib update 2014-02-27 18:22:29 +01:00
Viliam Rockai d65926f3b8 KEYCLOAK-340 custom selectors on realm detail replaced with standard one 2014-02-27 17:41:00 +01:00
Viliam Rockai 5881ef3e11 KEYCLOAK-276 AngularJS upgraded to v1.2.13 2014-02-27 17:08:01 +01:00
Bill Burke f8da693fd0 move secret to clientmodel 2014-02-27 10:59:47 -05:00
Viliam Rockai b413636bf5 KEYCLOAK-340 refactoring of on/off switch 2014-02-27 16:33:16 +01:00
Stian Thorgersen a1dca73ad3 Merge pull request #249 from stianst/master
Added create-realm role
2014-02-27 11:08:24 +00:00
Stian Thorgersen 32b7c464c7 Added create-realm role 2014-02-27 11:07:48 +00:00
Stian Thorgersen d5e0e73369 Merge pull request #248 from stianst/master
Fixed permissions not updated when realm is imported
2014-02-27 10:23:51 +00:00
Stian Thorgersen b3375d4279 Fixed permissions not updated when realm is imported 2014-02-27 10:23:27 +00:00
Bill Burke 4f56170b4c Merge pull request #247 from patriot1burke/master
rename scope rep username to client
2014-02-26 22:23:30 -05:00
Bill Burke 42d30a5a70 rename scope rep username to client 2014-02-26 22:23:04 -05:00
Bill Burke 9dbd19f715 Merge pull request #246 from patriot1burke/master
Use ClientModel wherever possible
2014-02-26 22:05:22 -05:00
Bill Burke 48d39bf977 Use ClientModel wherever possible 2014-02-26 22:04:57 -05:00
Bill Burke a8e588216b Merge pull request #245 from patriot1burke/master
IDToken and claims
2014-02-26 19:30:26 -05:00
Bill Burke c02d532001 refactor model 2014-02-26 19:25:42 -05:00
Bill Burke 0f67feb9dd IDToken setup 2014-02-26 19:04:42 -05:00
Bill Burke b2719ff40a claims UI 2014-02-26 16:41:31 -05:00
Bill Burke 8613452f4f Merge remote-tracking branch 'upstream/master' 2014-02-26 15:29:31 -05:00
Bill Burke b249809d2e claims backend 2014-02-26 15:29:17 -05:00
Stian Thorgersen 4ea7808d5f Merge pull request #244 from stianst/master
Added view roles, including updating console to make forms read-only
2014-02-26 17:39:51 +00:00
Stian Thorgersen ae1b98e38f Added view roles, including updating console to make forms read-only 2014-02-26 17:38:42 +00:00
Stian Thorgersen d0ca9a655d Merge pull request #243 from stianst/admin-access
Started directive to make form read-only
2014-02-26 10:56:22 +00:00
Stian Thorgersen 8d5d786452 Started directive to make form read-only 2014-02-26 10:55:40 +00:00
Bill Burke deaf2f9273 Merge pull request #242 from patriot1burke/master
cors docs
2014-02-25 16:23:54 -05:00
Bill Burke db37053f58 cors docs 2014-02-25 16:23:29 -05:00
Stian Thorgersen dd75864749 Merge pull request #241 from stianst/admin-access
Fixes to permissions in admin console
2014-02-25 15:42:08 +00:00
Stian Thorgersen 98629ac6f8 Fixes to permissions in admin console 2014-02-25 15:41:42 +00:00
Stian Thorgersen fa39ec1c98 Merge pull request #240 from stianst/admin-access
KEYCLOAK-292 Fine-grained admin control
2014-02-25 12:59:31 +00:00
Stian Thorgersen 9a73936002 KEYCLOAK-292 Fine-grained admin control 2014-02-25 12:53:36 +00:00
Bill Burke 7f33593931 Merge pull request #239 from patriot1burke/master
token docs
2014-02-24 20:20:51 -05:00
Bill Burke 88fb1ec747 token docs 2014-02-24 20:20:29 -05:00
Bill Burke a3e437f82a Merge pull request #238 from patriot1burke/master
javascript refresh token
2014-02-24 19:59:22 -05:00
Bill Burke 64065a4573 javascript refresh token 2014-02-24 19:58:54 -05:00
Bill Burke 1acfe1502a Merge pull request #237 from patriot1burke/master
remember me
2014-02-24 17:19:53 -05:00
Bill Burke 4b78857b51 as7 adapter refresh token support 2014-02-24 17:16:45 -05:00
Bill Burke 735009cdd7 Merge remote-tracking branch 'upstream/master' 2014-02-24 09:49:01 -05:00
Bill Burke 166e00f2e8 remember me 2014-02-23 11:30:32 -05:00
Bill Burke 3552f9e4aa Merge pull request #236 from patriot1burke/master
central login timeouts, rememberme framework
2014-02-22 21:52:54 -05:00
Bill Burke 01ddafa83a central login timeouts, rememberme framework 2014-02-22 21:52:29 -05:00
Bill Burke 1bfad2e198 Merge pull request #235 from patriot1burke/master
refresh tokens
2014-02-22 20:41:01 -05:00
Bill Burke 3e88cb3b76 logout 2014-02-22 20:40:06 -05:00
Bill Burke 273e706a42 undertow refresh token support 2014-02-22 17:24:04 -05:00
Bill Burke baa0e453b6 Merge remote-tracking branch 'upstream/master' 2014-02-21 17:37:29 -05:00
Bill Burke 898fcf8fd5 Merge pull request #234 from mposolda/master
Fix testsuite with mongo. Fix RealmModel.get**ById(). Added new unit tests
2014-02-21 17:37:06 -05:00
Bill Burke 3b59bd92fc Merge remote-tracking branch 'upstream/master' 2014-02-21 17:37:00 -05:00
Bill Burke 0a9b82a6f4 refresh tokens server side 2014-02-21 17:36:39 -05:00
mposolda 8a4ef40e9e Added new unit tests. Change get***ById() to find just entities from this realm/application 2014-02-21 23:16:06 +01:00
mposolda e85c2c9826 Fix testsuite with Mongo 2014-02-21 23:16:06 +01:00
Bill Burke 15968e9783 Merge pull request #233 from patriot1burke/master
refactor token creation
2014-02-21 12:13:26 -05:00
Bill Burke 97dd7470ce rename tokenLifespan to accessTokenLifespan 2014-02-21 12:12:54 -05:00
Bill Burke e583dc60ae Merge remote-tracking branch 'upstream/master' 2014-02-21 12:02:36 -05:00
Bill Burke 9607acdb6a refactor token creation 2014-02-21 12:02:24 -05:00
Stian Thorgersen 0ee71b09cd Merge pull request #232 from stianst/master
KEYCLOAK-286 Allow login with username or email. KEYCLOAK-287 Remove recover username as we now support login with email
2014-02-21 15:28:39 +00:00
Stian Thorgersen 05bd92d765 KEYCLOAK-286 Allow login with username or email. KEYCLOAK-287 Remove recover username as we now support login with email 2014-02-21 15:25:55 +00:00
Bill Burke cd68462cf3 Merge pull request #231 from patriot1burke/master
rename same classes/attributes
2014-02-21 10:17:02 -05:00
Bill Burke 9442601e42 rename some classes 2014-02-21 10:16:12 -05:00
Bill Burke 4b1fc788cf Merge remote-tracking branch 'upstream/master' 2014-02-21 09:49:08 -05:00
Bill Burke 94d8dbeeee issuedFor has OpenID claim now 2014-02-21 09:48:48 -05:00
Stian Thorgersen 3cb7e7c1bf Merge pull request #230 from stianst/master
KEYCLOAK-284 Subject in token is now user id instead of username
2014-02-21 10:55:25 +00:00
Stian Thorgersen 9ce8e16063 KEYCLOAK-284 Subject in token is now user id instead of username 2014-02-21 09:48:43 +00:00
Stian Thorgersen c2ca1b2731 Merge pull request #227 from matzew/master
Remove outdated references to alpha-1
2014-02-21 09:46:29 +00:00
Stian Thorgersen d47bf103b0 Merge pull request #228 from cardosogabriel/master
Refinements in the logo
2014-02-21 09:46:08 +00:00
Bill Burke dfacae9beb Merge pull request #229 from patriot1burke/master
tokens/access/codes now uses basic auth
2014-02-20 17:20:06 -05:00
Bill Burke 6794166b58 tokens/access/codes now uses basic auth 2014-02-20 17:19:51 -05:00
Gabriel Cardoso 8583d35153 Refinements in the logo 2014-02-20 15:30:21 -03:00
Matthias Wessendorf 2cb37827a8 Remove outdated references to alpha-1 2014-02-20 12:20:40 +01:00
Bill Burke 158eec7999 Merge pull request #226 from patriot1burke/master
alpha 3 version bump
2014-02-19 23:22:53 -05:00
Bill Burke 00043423c2 alpha 3 version bump 2014-02-19 23:22:34 -05:00
1616 changed files with 266128 additions and 94603 deletions

No files matched your search

+32 -1
View File
@@ -1,4 +1,35 @@
keycloak
========
SSO Service for web apps and REST services.
Please visit [http://keycloak.org](http://keycloak.org) for more information on Keycloak including how to download, documentation,
and video tutorials.
Keycloak is an SSO Service for web apps and REST services.
It can be used for social applications as well as enterprise applications. It is based on OpenID Connect with SAML support in the works.
Here's some of the features:
* SSO and Single Log Out for browser applications
* Social Broker. Enable Google, Facebook, Yahoo, Twitter social login with no code required.
* Optional LDAP/Active Directory integration
* Optional User Registration
* Password and TOTP support (via Google Authenticator). Client cert auth coming soon.
* User session management from both admin and user perspective
* Customizable themes for user facing pages: login, grant pages, account management, emails, and admin console all customizable!
* OAuth Bearer token auth for REST Services
* Integrated Browser App to REST Service token propagation
* Admin REST API
* OAuth 2.0 Grant requests
* CORS Support
* CORS Web Origin management and validation
* Completely centrally managed user and role mapping metadata. Minimal configuration at the application side
* Admin Console for managing users, roles, role mappings, applications, user sessions, allowed CORS web origins, and OAuth clients.
* Deployable as a WAR, appliance, or an Openshift cloud service (SaaS).
* Supports JBoss AS7, EAP 6.x, and Wildfly applications. Plans to support Node.js, RAILS, GRAILS, and other non-Java applications.
* Javascript/HTML 5 adapter for pure Javascript apps
* Session management from admin console
* Revocation policies
* Password policies
* OpenID Connect Support
Please visit [http://keycloak.org](http://keycloak.org) for more information on Keycloak including how to download, documentation,
and video tutorials.
-31
View File
@@ -1,31 +0,0 @@
<?xml version="1.0"?>
<project>
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.0-alpha-2</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>keycloak-admin-ui-styles</artifactId>
<name>Keycloak Admin UI Styles</name>
<description />
<dependencies>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
@@ -1,71 +0,0 @@
/* http://meyerweb.com/eric/tools/css/reset/
v2.0 | 20110126
License: none (public domain)
*/
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display: block;
}
body {
line-height: 1;
}
ol, ul {
list-style: none;
}
blockquote, q {
quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
content: '';
content: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
/* Clearfix */
.clearfix:after {
content: ".";
display: block;
clear: both;
visibility: hidden;
line-height: 0;
height: 0;
}
.clearfix {
display: inline-block;
}
html[xmlns] .clearfix {
display: block;
}
* html .clearfix {
height: 1%;
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

@@ -1,7 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="23px" height="14px" viewBox="0 0 23 14" enable-background="new 0 0 23 14" xml:space="preserve">
<polyline fill="none" stroke="#009AD8" stroke-miterlimit="10" points="1,13 7,7 1,1 "/>
</svg>

Before

Width:  |  Height:  |  Size: 573 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="22px" height="52px" viewBox="0 0 22 52" enable-background="new 0 0 22 52" xml:space="preserve">
<polygon fill="#828487" points="11,16 6.818,11.818 7.525,11.111 11,14.586 14.475,11.111 15.182,11.818 "/>
<polygon fill="#DBDADA" points="11,42 6.818,37.818 7.525,37.111 11,40.586 14.475,37.111 15.182,37.818 "/>
</svg>

Before

Width:  |  Height:  |  Size: 699 B

File diff suppressed because it is too large. Load diff

Before

Width:  |  Height:  |  Size: 250 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 269 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 268 KiB

@@ -1,5 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<web-fragment version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-fragment_3_0.xsd ">
</web-fragment>
-31
View File
@@ -1,31 +0,0 @@
<?xml version="1.0"?>
<project>
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.0-alpha-2</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>keycloak-admin-ui</artifactId>
<name>Keycloak Admin UI</name>
<description />
<dependencies>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
@@ -1,191 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<style>
.mock_view {
padding: 2em 2em;
}
</style>
<meta charset="utf-8">
<title>Keycloak Admin Console</title>
<link rel="icon" href="/auth/admin-ui/img/favicon.ico">
<!-- Frameworks -->
<!--link rel="stylesheet" href="/auth/admin-ui/bootstrap/css/bootstrap.css"-->
<link rel="stylesheet" href="/auth/admin-ui/patternfly/css/patternfly.css">
<!-- Page styles -->
<link rel="stylesheet" href="/auth/admin-ui/css/admin-console.css">
<link href="lib/select2-3.4.1/select2.css" rel="stylesheet">
<script src="lib/jquery/jquery-1.10.2.js" type="text/javascript"></script>
<script src="lib/select2-3.4.1/select2.js" type="text/javascript"></script>
<script src="lib/angular/angular.js"></script>
<script src="lib/angular/angular-resource.js"></script>
<script src="lib/angular/ui-bootstrap-tpls-0.4.0.js"></script>
<script src="lib/jquery/jquery.idletimer.js" type="text/javascript"></script>
<script src="lib/jquery/jquery.idletimeout.js" type="text/javascript"></script>
<script src="lib/angular/select2.js" type="text/javascript"></script>
<script src="lib/fileupload/angular-file-upload.min.js"></script> <!--
<script src="/auth/admin-ui/bootstrap-3.0.0-wip/js/dropdown.js"></script>
<script src="/auth/admin-ui/bootstrap-3.0.0-wip/js/tooltip.js"></script>
-->
<script src="/auth/admin-ui/js/bootstrap-tokenfield.js"></script>
<script src="/auth/admin-ui/bootstrap/js/bootstrap.js"></script>
<script src="js/app.js"></script>
<script src="js/controllers/realm.js"></script>
<script src="js/controllers/applications.js"></script>
<script src="js/controllers/oauth-clients.js"></script>
<script src="js/controllers/users.js"></script>
<script src="js/loaders.js"></script>
<script src="js/services.js"></script>
<style>
[ng\:cloak], [ng-cloak], .ng-cloak {
display: none !important;
}
</style>
</head>
<body class="admin-console" data-ng-controller="GlobalCtrl" ng-cloak>
<div id="idletimeout">
You will be logged off in <strong><span></span> seconds</strong> due to inactivity.
<a id="idletimeout-resume" href="#">Click here to continue using this web page</a>.
</div>
<div class="feedback-aligner" data-ng-show="notification" data-ng-click="notification = null">
<div class="alert alert-{{notification.type}}"><strong>{{notification.header}}</strong> {{notification.message}}</div>
</div>
<header class="navbar navbar-default navbar-pf navbar-main header">
<div class="container">
<nav id="kc-navigation" class="navbar" role="navigation">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse-1">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<h1 class="navbar-title"><Strong>KeyCloak</Strong> Central Login</h1>
</div>
<div class="collapse navbar-collapse navbar-collapse-1">
<ul class="nav navbar-nav navbar-utility" data-ng-show="auth.loggedIn">
<li class="dropdown">
<a data-toggle="dropdown" class="dropdown-toggle" href="#">
<span class="pficon pficon-user"></span>
{{auth.user.displayName}}<b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li><a href="/auth/rest/realms/keycloak-admin/account?referrer=admin-console">Manage Account</a></li>
<li class="separator"><a href="/auth/rest/admin/logout">Sign Out</a></li>
</ul>
</li>
</ul>
<ul class="nav navbar-nav navbar-primary persistent-secondary" data-ng-controller="RealmDropdownCtrl">
<li class="dropdown context" data-ng-show="showNav()">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
Realm: {{current.realm.id}}
<b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li data-ng-repeat="realm in current.realms">
<a href="" ng-click="changeRealm(realm.id)" >{{realm.id}}</a>
</li>
</ul>
</li>
<!--------------------------------------->
<li class="active">
<a href="#">Settings</a>
<ul class="nav navbar-nav navbar-persistent">
<li class="active">
<a href="#">General</a>
</li>
<li>
<a href="#">Roles</a>
</li>
<li>
<a href="#">Default Roles</a>
</li>
<li>
<a href="#">Credentials</a>
</li>
<li>
<a href="#">Token</a>
</li>
<li>
<a href="#">Keys</a>
</li>
<li>
<a href="#">Email</a>
</li>
</ul>
</li>
<li>
<a href="#">User</a>
</li>
<li>
<a href="#">Applications</a>
</li>
<li>
<a href="#">OAuth Clients</a>
</li>
<!--------------------------------------->
<li class="active pull-right" data-ng-show="auth.loggedIn">
<a class="button primary" href="#/create/realm" data-ng-class="path[0] == 'create' && path[1] == 'realm' && 'active'"
data-ng-show="auth.loggedIn">Add Realm</a>
</li>
</ul>
</div>
</nav>
</div>
</header>
<div class="container">
<div class="mock_view" data-ng-view id="view"></div>
<div id="loading" class="loading-backdrop">
<div class="loading">
<span>Loading...</span>
</div>
</div>
</div>
<script type="text/javascript">
$.idleTimeout('#idletimeout', '#idletimeout a', {
idleAfter: 300,
pollingInterval: 60,
keepAliveURL: '/auth/rest/admin/keepalive',
serverResponseEquals: '',
failedRequests: 1,
onTimeout: function(){
$(this).slideUp();
window.location = "/auth/rest/admin/logout";
},
onIdle: function(){
$(this).slideDown(); // show the warning bar
},
onCountdown: function( counter ){
$(this).find("span").html( counter ); // update the counter
},
onResume: function(){
$(this).slideUp(); // hide the warning bar
}
});
</script>
</body>
</html>
@@ -1,352 +0,0 @@
module.controller('ApplicationRoleListCtrl', function($scope, $location, realm, application, roles) {
$scope.realm = realm;
$scope.roles = roles;
$scope.application = application;
$scope.$watch(function() {
return $location.path();
}, function() {
$scope.path = $location.path().substring(1).split("/");
});
});
module.controller('ApplicationCredentialsCtrl', function($scope, $location, realm, application, ApplicationCredentials, Notifications) {
$scope.realm = realm;
$scope.application = application;
var secret = ApplicationCredentials.get({ realm : realm.realm, application : application.name },
function() {
$scope.secret = secret.value;
}
);
$scope.changePassword = function() {
var secret = ApplicationCredentials.update({ realm : realm.realm, application : application.name },
function() {
Notifications.success('The secret has been changed.');
$scope.secret = secret.value;
},
function() {
Notifications.error("The secret was not changed due to a problem.");
$scope.secret = "error";
}
);
};
$scope.$watch(function() {
return $location.path();
}, function() {
$scope.path = $location.path().substring(1).split("/");
});
});
module.controller('ApplicationSessionsCtrl', function($scope, $location, realm, application) {
$scope.realm = realm;
$scope.application = application;
});
module.controller('ApplicationRoleDetailCtrl', function($scope, realm, application, role, roles, applications,
Role, ApplicationRole, RoleById, RoleRealmComposites, RoleApplicationComposites,
$http, $location, Dialog, Notifications) {
$scope.realm = realm;
$scope.application = application;
$scope.role = angular.copy(role);
$scope.create = !role.name;
$scope.changed = $scope.create;
$scope.save = function() {
if ($scope.create) {
ApplicationRole.save({
realm: realm.realm,
application : application.name
}, $scope.role, function (data, headers) {
$scope.changed = false;
role = angular.copy($scope.role);
var l = headers().location;
var id = l.substring(l.lastIndexOf("/") + 1);
$location.url("/realms/" + realm.realm + "/applications/" + application.name + "/roles/" + id);
Notifications.success("The role has been created.");
});
} else {
$scope.update();
}
};
$scope.remove = function() {
Dialog.confirmDelete($scope.role.name, 'role', function() {
$scope.role.$remove({
realm : realm.realm,
application : application.name,
role : $scope.role.name
}, function() {
$location.url("/realms/" + realm.realm + "/applications/" + application.name + "/roles");
Notifications.success("The role has been deleted.");
});
});
};
$scope.cancel = function () {
$location.url("/realms/" + realm.realm + "/applications/" + application.name + "/roles");
};
roleControl($scope, realm, role, roles, applications,
ApplicationRole, RoleById, RoleRealmComposites, RoleApplicationComposites,
$http, $location, Notifications, Dialog);
});
module.controller('ApplicationListCtrl', function($scope, realm, applications, Application, $location) {
console.log('ApplicationListCtrl');
$scope.realm = realm;
$scope.applications = applications;
$scope.$watch(function() {
return $location.path();
}, function() {
$scope.path = $location.path().substring(1).split("/");
});
});
module.controller('ApplicationInstallationCtrl', function($scope, realm, application, ApplicationInstallation,ApplicationInstallationJBoss, $http, $routeParams) {
console.log('ApplicationInstallationCtrl');
$scope.realm = realm;
$scope.application = application;
$scope.installation = null;
$scope.download = null;
$scope.configFormat = null;
$scope.configFormats = [
"keycloak.json",
"Wildfly/JBoss Subsystem XML"
];
$scope.changeFormat = function() {
if ($scope.configFormat == "keycloak.json") {
var url = ApplicationInstallation.url({ realm: $routeParams.realm, application: $routeParams.application });
var installation = $http.get(url).success(function(data) {
var tmp = angular.fromJson(data);
$scope.installation = angular.toJson(tmp, true);
})
$scope.download = url;
} else if ($scope.configFormat == "Wildfly/JBoss Subsystem XML") {
var url = ApplicationInstallationJBoss.url({ realm: $routeParams.realm, application: $routeParams.application });
var installation = $http.get(url).success(function(data) {
$scope.installation = data;
})
$scope.download = url;
}
};
});
module.controller('ApplicationDetailCtrl', function($scope, realm, application, Application, $location, Dialog, Notifications) {
console.log('ApplicationDetailCtrl');
$scope.realm = realm;
$scope.create = !application.name;
if (!$scope.create) {
$scope.application= angular.copy(application);
} else {
$scope.application = {};
$scope.application.webOrigins = [];
$scope.application.redirectUris = [];
}
$scope.$watch(function() {
return $location.path();
}, function() {
$scope.path = $location.path().substring(1).split("/");
});
$scope.$watch('application', function() {
if (!angular.equals($scope.application, application)) {
$scope.changed = true;
}
}, true);
$scope.deleteWebOrigin = function(index) {
$scope.application.webOrigins.splice(index, 1);
}
$scope.addWebOrigin = function() {
$scope.application.webOrigins.push($scope.newWebOrigin);
$scope.newWebOrigin = "";
}
$scope.deleteRedirectUri = function(index) {
$scope.application.redirectUris.splice(index, 1);
}
$scope.addRedirectUri = function() {
$scope.application.redirectUris.push($scope.newRedirectUri);
$scope.newRedirectUri = "";
}
$scope.save = function() {
if ($scope.create) {
Application.save({
realm: realm.realm,
application: ''
}, $scope.application, function (data, headers) {
$scope.changed = false;
var l = headers().location;
var id = l.substring(l.lastIndexOf("/") + 1);
$location.url("/realms/" + realm.realm + "/applications/" + id);
Notifications.success("The application has been created.");
});
} else {
Application.update({
realm : realm.realm,
application : application.name
}, $scope.application, function() {
$scope.changed = false;
application = angular.copy($scope.application);
Notifications.success("Your changes have been saved to the application.");
});
}
};
$scope.reset = function() {
$scope.application = angular.copy(application);
$scope.changed = false;
};
$scope.cancel = function() {
$location.url("/realms/" + realm.realm + "/applications");
};
$scope.remove = function() {
Dialog.confirmDelete($scope.application.name, 'application', function() {
$scope.application.$remove({
realm : realm.realm,
application : $scope.application.name
}, function() {
$location.url("/realms/" + realm.realm + "/applications");
Notifications.success("The application has been deleted.");
});
});
};
});
module.controller('ApplicationScopeMappingCtrl', function($scope, $http, realm, application, roles, applications, ApplicationRealmScopeMapping, ApplicationApplicationScopeMapping, ApplicationRole) {
$scope.realm = realm;
$scope.application = application;
$scope.realmRoles = angular.copy(roles);
$scope.selectedRealmRoles = [];
$scope.selectedRealmMappings = [];
$scope.realmMappings = [];
$scope.applications = applications;
$scope.applicationRoles = [];
$scope.selectedApplicationRoles = [];
$scope.selectedApplicationMappings = [];
$scope.applicationMappings = [];
$scope.realmMappings = ApplicationRealmScopeMapping.query({realm : realm.realm, application : application.name}, function(){
for (var i = 0; i < $scope.realmMappings.length; i++) {
var role = $scope.realmMappings[i];
for (var j = 0; j < $scope.realmRoles.length; j++) {
var realmRole = $scope.realmRoles[j];
if (realmRole.id == role.id) {
var idx = $scope.realmRoles.indexOf(realmRole);
if (idx != -1) {
$scope.realmRoles.splice(idx, 1);
break;
}
}
}
}
});
$scope.addRealmRole = function() {
$http.post('/auth/rest/admin/realms/' + realm.realm + '/applications/' + application.name + '/scope-mappings/realm',
$scope.selectedRealmRoles).success(function() {
for (var i = 0; i < $scope.selectedRealmRoles.length; i++) {
var role = $scope.selectedRealmRoles[i];
var idx = $scope.realmRoles.indexOf($scope.selectedRealmRoles[i]);
if (idx != -1) {
$scope.realmRoles.splice(idx, 1);
$scope.realmMappings.push(role);
}
}
$scope.selectRealmRoles = [];
});
};
$scope.deleteRealmRole = function() {
$http.delete('/auth/rest/admin/realms/' + realm.realm + '/applications/' + application.name + '/scope-mappings/realm',
{data : $scope.selectedRealmMappings, headers : {"content-type" : "application/json"}}).success(function() {
for (var i = 0; i < $scope.selectedRealmMappings.length; i++) {
var role = $scope.selectedRealmMappings[i];
var idx = $scope.realmMappings.indexOf($scope.selectedRealmMappings[i]);
if (idx != -1) {
$scope.realmMappings.splice(idx, 1);
$scope.realmRoles.push(role);
}
}
$scope.selectedRealmMappings = [];
});
};
$scope.addApplicationRole = function() {
$http.post('/auth/rest/admin/realms/' + realm.realm + '/applications/' + application.name + '/scope-mappings/applications/' + $scope.targetApp.name,
$scope.selectedApplicationRoles).success(function() {
for (var i = 0; i < $scope.selectedApplicationRoles.length; i++) {
var role = $scope.selectedApplicationRoles[i];
var idx = $scope.applicationRoles.indexOf($scope.selectedApplicationRoles[i]);
if (idx != -1) {
$scope.applicationRoles.splice(idx, 1);
$scope.applicationMappings.push(role);
}
}
$scope.selectedApplicationRoles = [];
});
};
$scope.deleteApplicationRole = function() {
$http.delete('/auth/rest/admin/realms/' + realm.realm + '/applications/' + application.name + '/scope-mappings/applications/' + $scope.targetApp.name,
{data : $scope.selectedApplicationMappings, headers : {"content-type" : "application/json"}}).success(function() {
for (var i = 0; i < $scope.selectedApplicationMappings.length; i++) {
var role = $scope.selectedApplicationMappings[i];
var idx = $scope.applicationMappings.indexOf($scope.selectedApplicationMappings[i]);
if (idx != -1) {
$scope.applicationMappings.splice(idx, 1);
$scope.applicationRoles.push(role);
}
}
$scope.selectedApplicationMappings = [];
});
};
$scope.changeApplication = function() {
if ($scope.targetApp) {
$scope.applicationRoles = ApplicationRole.query({realm : realm.realm, application : $scope.targetApp.name}, function() {
$scope.applicationMappings = ApplicationApplicationScopeMapping.query({realm : realm.realm, application : application.name, targetApp : $scope.targetApp.name}, function(){
for (var i = 0; i < $scope.applicationMappings.length; i++) {
var role = $scope.applicationMappings[i];
for (var j = 0; j < $scope.applicationRoles.length; j++) {
var realmRole = $scope.applicationRoles[j];
if (realmRole.id == role.id) {
var idx = $scope.applicationRoles.indexOf(realmRole);
if (idx != -1) {
$scope.applicationRoles.splice(idx, 1);
break;
}
}
}
}
});
}
);
} else {
$scope.applicationRoles = null;
}
};
});
@@ -1,255 +0,0 @@
module.controller('OAuthClientCredentialsCtrl', function($scope, $location, realm, oauth, OAuthClientCredentials, Notifications) {
$scope.realm = realm;
$scope.oauth = oauth;
var secret = OAuthClientCredentials.get({ realm : realm.realm, oauth : oauth.id },
function() {
$scope.secret = secret.value;
}
);
$scope.changePassword = function() {
var secret = OAuthClientCredentials.update({ realm : realm.realm, oauth : oauth.id },
function() {
Notifications.success('The secret has been changed.');
$scope.secret = secret.value;
},
function() {
Notifications.error("The secret was not changed due to a problem.");
$scope.secret = "error";
}
);
};
$scope.$watch(function() {
return $location.path();
}, function() {
$scope.path = $location.path().substring(1).split("/");
});
});
module.controller('OAuthClientListCtrl', function($scope, realm, oauthClients, OAuthClient, $location) {
$scope.realm = realm;
$scope.oauthClients = oauthClients;
$scope.$watch(function() {
return $location.path();
}, function() {
$scope.path = $location.path().substring(1).split("/");
});
});
module.controller('OAuthClientDetailCtrl', function($scope, realm, oauth, OAuthClient, $location, Dialog, Notifications) {
$scope.realm = realm;
$scope.create = !oauth.id;
if (!$scope.create) {
$scope.oauth= angular.copy(oauth);
} else {
$scope.oauth = {};
$scope.oauth.webOrigins = [];
$scope.oauth.redirectUris = [];
}
$scope.$watch(function() {
return $location.path();
}, function() {
$scope.path = $location.path().substring(1).split("/");
});
$scope.$watch('oauth', function() {
if (!angular.equals($scope.oauth, oauth)) {
$scope.changed = true;
}
}, true);
$scope.deleteWebOrigin = function(index) {
$scope.oauth.webOrigins.splice(index, 1);
}
$scope.addWebOrigin = function() {
$scope.oauth.webOrigins.push($scope.newWebOrigin);
$scope.newWebOrigin = "";
}
$scope.deleteRedirectUri = function(index) {
$scope.oauth.redirectUris.splice(index, 1);
}
$scope.addRedirectUri = function() {
$scope.oauth.redirectUris.push($scope.newRedirectUri);
$scope.newRedirectUri = "";
}
$scope.save = function() {
if ($scope.create) {
OAuthClient.save({
realm: realm.realm
}, $scope.oauth, function (data, headers) {
$scope.changed = false;
var l = headers().location;
var id = l.substring(l.lastIndexOf("/") + 1);
$location.url("/realms/" + realm.realm + "/oauth-clients/" + id);
Notifications.success("The oauth client has been created.");
});
} else {
OAuthClient.update({
realm : realm.realm,
id : oauth.id
}, $scope.oauth, function() {
$scope.changed = false;
oauth = angular.copy($scope.oauth);
Notifications.success("Your changes have been saved to the oauth client.");
});
}
};
$scope.reset = function() {
$scope.oauth = angular.copy(oauth);
$scope.changed = false;
};
$scope.cancel = function() {
$location.url("/realms/" + realm.realm + "/oauth-clients");
};
$scope.remove = function() {
Dialog.confirmDelete($scope.oauth.name, 'oauth', function() {
$scope.oauth.$remove({
realm : realm.realm,
id : $scope.oauth.id
}, function() {
$location.url("/realms/" + realm.realm + "/oauth-clients");
Notifications.success("The oauth client has been deleted.");
});
});
};
});
module.controller('OAuthClientScopeMappingCtrl', function($scope, $http, realm, oauth, roles, applications, OAuthClientRealmScopeMapping, OAuthClientApplicationScopeMapping, ApplicationRole) {
$scope.realm = realm;
$scope.oauth = oauth;
$scope.realmRoles = angular.copy(roles);
$scope.selectedRealmRoles = [];
$scope.selectedRealmMappings = [];
$scope.realmMappings = [];
$scope.applications = applications;
$scope.applicationRoles = [];
$scope.selectedApplicationRoles = [];
$scope.selectedApplicationMappings = [];
$scope.applicationMappings = [];
$scope.realmMappings = OAuthClientRealmScopeMapping.query({realm : realm.realm, oauth : oauth.id}, function(){
for (var i = 0; i < $scope.realmMappings.length; i++) {
var role = $scope.realmMappings[i];
for (var j = 0; j < $scope.realmRoles.length; j++) {
var realmRole = $scope.realmRoles[j];
if (realmRole.id == role.id) {
var idx = $scope.realmRoles.indexOf(realmRole);
if (idx != -1) {
$scope.realmRoles.splice(idx, 1);
break;
}
}
}
}
});
$scope.addRealmRole = function() {
$http.post('/auth/rest/admin/realms/' + realm.realm + '/oauth-clients/' + oauth.id + '/scope-mappings/realm',
$scope.selectedRealmRoles).success(function() {
for (var i = 0; i < $scope.selectedRealmRoles.length; i++) {
var role = $scope.selectedRealmRoles[i];
var idx = $scope.realmRoles.indexOf($scope.selectedRealmRoles[i]);
if (idx != -1) {
$scope.realmRoles.splice(idx, 1);
$scope.realmMappings.push(role);
}
}
$scope.selectRealmRoles = [];
});
};
$scope.deleteRealmRole = function() {
$http.delete('/auth/rest/admin/realms/' + realm.realm + '/oauth-clients/' + oauth.id + '/scope-mappings/realm',
{data : $scope.selectedRealmMappings, headers : {"content-type" : "application/json"}}).success(function() {
for (var i = 0; i < $scope.selectedRealmMappings.length; i++) {
var role = $scope.selectedRealmMappings[i];
var idx = $scope.realmMappings.indexOf($scope.selectedRealmMappings[i]);
if (idx != -1) {
$scope.realmMappings.splice(idx, 1);
$scope.realmRoles.push(role);
}
}
$scope.selectedRealmMappings = [];
});
};
$scope.addApplicationRole = function() {
$http.post('/auth/rest/admin/realms/' + realm.realm + '/oauth-clients/' + oauth.id + '/scope-mappings/applications/' + $scope.targetApp.name,
$scope.selectedApplicationRoles).success(function() {
for (var i = 0; i < $scope.selectedApplicationRoles.length; i++) {
var role = $scope.selectedApplicationRoles[i];
var idx = $scope.applicationRoles.indexOf($scope.selectedApplicationRoles[i]);
if (idx != -1) {
$scope.applicationRoles.splice(idx, 1);
$scope.applicationMappings.push(role);
}
}
$scope.selectedApplicationRoles = [];
});
};
$scope.deleteApplicationRole = function() {
$http.delete('/auth/rest/admin/realms/' + realm.realm + '/oauth-clients/' + oauth.id + '/scope-mappings/applications/' + $scope.targetApp.name,
{data : $scope.selectedApplicationMappings, headers : {"content-type" : "application/json"}}).success(function() {
for (var i = 0; i < $scope.selectedApplicationMappings.length; i++) {
var role = $scope.selectedApplicationMappings[i];
var idx = $scope.applicationMappings.indexOf($scope.selectedApplicationMappings[i]);
if (idx != -1) {
$scope.applicationMappings.splice(idx, 1);
$scope.applicationRoles.push(role);
}
}
$scope.selectedApplicationMappings = [];
});
};
$scope.changeApplication = function() {
if ($scope.targetApp) {
$scope.applicationRoles = ApplicationRole.query({realm : realm.realm, application : $scope.targetApp.name}, function() {
$scope.applicationMappings = OAuthClientApplicationScopeMapping.query({realm : realm.realm, oauth : oauth.id, targetApp : $scope.targetApp.name}, function(){
for (var i = 0; i < $scope.applicationMappings.length; i++) {
var role = $scope.applicationMappings[i];
for (var j = 0; j < $scope.applicationRoles.length; j++) {
var realmRole = $scope.applicationRoles[j];
if (realmRole.id == role.id) {
var idx = $scope.applicationRoles.indexOf(realmRole);
if (idx != -1) {
$scope.applicationRoles.splice(idx, 1);
break;
}
}
}
}
});
}
);
} else {
$scope.targetApp = null;
}
};
});
module.controller('OAuthClientInstallationCtrl', function($scope, realm, installation, oauth, OAuthClientInstallation, $routeParams) {
$scope.realm = realm;
$scope.oauth = oauth;
$scope.installation = installation;
$scope.download = OAuthClientInstallation.url({ realm: $routeParams.realm, oauth: $routeParams.oauth });
});
@@ -1,367 +0,0 @@
module.controller('UserRoleMappingCtrl', function($scope, $http, realm, user, roles, applications, RealmRoleMapping, ApplicationRoleMapping, ApplicationRole) {
$scope.realm = realm;
$scope.user = user;
$scope.realmRoles = angular.copy(roles);
$scope.selectedRealmRoles = [];
$scope.selectedRealmMappings = [];
$scope.realmMappings = [];
$scope.applications = applications;
$scope.applicationRoles = [];
$scope.selectedApplicationRoles = [];
$scope.selectedApplicationMappings = [];
$scope.applicationMappings = [];
$scope.realmMappings = RealmRoleMapping.query({realm : realm.realm, userId : user.username}, function(){
for (var i = 0; i < $scope.realmMappings.length; i++) {
var role = $scope.realmMappings[i];
for (var j = 0; j < $scope.realmRoles.length; j++) {
var realmRole = $scope.realmRoles[j];
if (realmRole.id == role.id) {
var idx = $scope.realmRoles.indexOf(realmRole);
if (idx != -1) {
$scope.realmRoles.splice(idx, 1);
break;
}
}
}
}
});
$scope.addRealmRole = function() {
$http.post('/auth/rest/admin/realms/' + realm.realm + '/users/' + user.username + '/role-mappings/realm',
$scope.selectedRealmRoles).success(function() {
for (var i = 0; i < $scope.selectedRealmRoles.length; i++) {
var role = $scope.selectedRealmRoles[i];
var idx = $scope.realmRoles.indexOf($scope.selectedRealmRoles[i]);
if (idx != -1) {
$scope.realmRoles.splice(idx, 1);
$scope.realmMappings.push(role);
}
}
$scope.selectRealmRoles = [];
});
};
$scope.deleteRealmRole = function() {
$http.delete('/auth/rest/admin/realms/' + realm.realm + '/users/' + user.username + '/role-mappings/realm',
{data : $scope.selectedRealmMappings, headers : {"content-type" : "application/json"}}).success(function() {
for (var i = 0; i < $scope.selectedRealmMappings.length; i++) {
var role = $scope.selectedRealmMappings[i];
var idx = $scope.realmMappings.indexOf($scope.selectedRealmMappings[i]);
if (idx != -1) {
$scope.realmMappings.splice(idx, 1);
$scope.realmRoles.push(role);
}
}
$scope.selectedRealmMappings = [];
});
};
$scope.addApplicationRole = function() {
$http.post('/auth/rest/admin/realms/' + realm.realm + '/users/' + user.username + '/role-mappings/applications/' + $scope.application.name,
$scope.selectedApplicationRoles).success(function() {
for (var i = 0; i < $scope.selectedApplicationRoles.length; i++) {
var role = $scope.selectedApplicationRoles[i];
var idx = $scope.applicationRoles.indexOf($scope.selectedApplicationRoles[i]);
if (idx != -1) {
$scope.applicationRoles.splice(idx, 1);
$scope.applicationMappings.push(role);
}
}
$scope.selectedApplicationRoles = [];
});
};
$scope.deleteApplicationRole = function() {
$http.delete('/auth/rest/admin/realms/' + realm.realm + '/users/' + user.username + '/role-mappings/applications/' + $scope.application.name,
{data : $scope.selectedApplicationMappings, headers : {"content-type" : "application/json"}}).success(function() {
for (var i = 0; i < $scope.selectedApplicationMappings.length; i++) {
var role = $scope.selectedApplicationMappings[i];
var idx = $scope.applicationMappings.indexOf($scope.selectedApplicationMappings[i]);
if (idx != -1) {
$scope.applicationMappings.splice(idx, 1);
$scope.applicationRoles.push(role);
}
}
$scope.selectedApplicationMappings = [];
});
};
$scope.changeApplication = function() {
if ($scope.application) {
$scope.applicationRoles = ApplicationRole.query({realm : realm.realm, userId : user.username, application : $scope.application.name}, function() {
$scope.applicationMappings = ApplicationRoleMapping.query({realm : realm.realm, userId : user.username, application : $scope.application.name}, function(){
for (var i = 0; i < $scope.applicationMappings.length; i++) {
var role = $scope.applicationMappings[i];
for (var j = 0; j < $scope.applicationRoles.length; j++) {
var realmRole = $scope.applicationRoles[j];
if (realmRole.id == role.id) {
var idx = $scope.applicationRoles.indexOf(realmRole);
if (idx != -1) {
$scope.applicationRoles.splice(idx, 1);
break;
}
}
}
}
});
}
);
} else {
$scope.applicationRoles = null;
}
};
});
module.controller('UserListCtrl', function($scope, realm, User) {
$scope.realm = realm;
$scope.searchQuery = function() {
$scope.searchLoaded = false;
$scope.currentSearch = $scope.search;
var params = { realm: realm.realm };
if ($scope.search) {
params.search = $scope.search;
}
$scope.users = User.query(params, function() {
$scope.searchLoaded = true;
$scope.lastSearch = params.search;
});
};
});
module.controller('UserDetailCtrl', function($scope, realm, user, User, $location, Dialog, Notifications) {
$scope.realm = realm;
$scope.user = angular.copy(user);
$scope.create = !user.username;
$scope.changed = false; // $scope.create;
// ID - Name map for required actions. IDs are enum names.
var userReqActionList = [
{id: "VERIFY_EMAIL", text: "Verify Email"},
{id: "UPDATE_PROFILE", text: "Update Profile"},
{id: "CONFIGURE_TOTP", text: "Configure Totp"},
{id: "UPDATE_PASSWORD", text: "Update Password"}
];
// Options for the req actions tag selector
$scope.userReqActionsOptions = {
'multiple' : true,
'tags' : userReqActionList
};
// Model for the req actions tag selector
$scope.userActions = [];
for (var i = 0; i < userReqActionList.length; i++){
var action = userReqActionList[i];
if ($scope.user.requiredActions && $scope.user.requiredActions.indexOf(action.id) > -1){
$scope.userActions.push({id: action.id, text: action.text});
}
}
// Watching ui-select2 model to properly format the req actions for user
$scope.$watch("userActions", function(newValue, oldValue) {
$scope.user.requiredActions = [];
for (var i=0; i < newValue.length; i++){
var action = newValue[i];
$scope.user.requiredActions.push(action.id);
}
});
$scope.$watch('user', function() {
if (!angular.equals($scope.user, user)) {
$scope.changed = true;
}
}, true);
$scope.save = function() {
if ($scope.create) {
User.save({
realm: realm.realm
}, $scope.user, function () {
$scope.changed = false;
user = angular.copy($scope.user);
$location.url("/realms/" + realm.realm + "/users/" + $scope.user.username);
Notifications.success("The user has been created.");
});
} else {
User.update({
realm: realm.realm,
userId: $scope.user.username
}, $scope.user, function () {
$scope.changed = false;
user = angular.copy($scope.user);
Notifications.success("Your changes have been saved to the user.");
});
}
};
$scope.reset = function() {
$scope.user = angular.copy(user);
$scope.changed = false;
};
$scope.cancel = function() {
$location.url("/realms/" + realm.realm + "/users");
};
$scope.remove = function() {
Dialog.confirmDelete($scope.user.username, 'user', function() {
$scope.user.$remove({
realm : realm.realm,
userId : $scope.user.username
}, function() {
$location.url("/realms/" + realm.realm + "/users");
Notifications.success("The user has been deleted.");
});
});
};
});
module.controller('UserCredentialsCtrl', function($scope, realm, user, User, UserCredentials, Notifications, Dialog) {
console.log('UserCredentialsCtrl');
$scope.realm = realm;
$scope.user = angular.copy(user);
$scope.isTotp = false;
if(!!user.totp){
$scope.isTotp = user.totp;
}
$scope.resetPassword = function() {
if ($scope.pwdChange) {
if ($scope.password != $scope.confirmPassword) {
Notifications.error("Password and confirmation does not match.");
return;
}
}
Dialog.confirm('Reset password', 'Are you sure you want to reset the users password?', function() {
UserCredentials.resetPassword({ realm: realm.realm, userId: user.username }, { type : "password", value : $scope.password }, function() {
Notifications.success("The password has been reset");
$scope.password = null;
$scope.confirmPassword = null;
}, function() {
Notifications.error("Failed to reset user password");
});
}, function() {
$scope.password = null;
$scope.confirmPassword = null;
});
};
$scope.removeTotp = function() {
Dialog.confirm('Remove totp', 'Are you sure you want to remove the users totp configuration?', function() {
UserCredentials.removeTotp({ realm: realm.realm, userId: user.username }, { }, function() {
Notifications.success("The users totp configuration has been removed");
$scope.user.totp = false;
}, function() {
Notifications.error("Failed to remove the users totp configuration");
});
});
};
$scope.resetPasswordEmail = function() {
Dialog.confirm('Reset password email', 'Are you sure you want to send password reset email to user?', function() {
UserCredentials.resetPasswordEmail({ realm: realm.realm, userId: user.username }, { }, function() {
Notifications.success("Password reset email sent to user");
}, function() {
Notifications.error("Failed to send password reset mail to user");
});
});
};
$scope.$watch('user', function() {
if (!angular.equals($scope.user, user)) {
$scope.userChange = true;
} else {
$scope.userChange = false;
}
}, true);
$scope.$watch('password', function() {
if (!!$scope.password){
$scope.pwdChange = true;
} else {
$scope.pwdChange = false;
}
}, true);
$scope.reset = function() {
$scope.password = "";
$scope.confirmPassword = "";
$scope.user = angular.copy(user);
$scope.isTotp = false;
if(!!user.totp){
$scope.isTotp = user.totp;
}
$scope.pwdChange = false;
$scope.userChange = false;
};
});
module.controller('RoleMappingCtrl', function($scope, realm, User, users, role, RoleMapping, Notifications) {
$scope.realm = realm;
$scope.realmId = realm.realm || realm.realm;
$scope.allUsers = User.query({ realm : $scope.realmId });
$scope.users = users;
$scope.role = role;
$scope.addUser = function() {
var user = $scope.newUser;
$scope.newUser = null;
for ( var i = 0; i < $scope.allUsers.length; i++) {
if ($scope.allUsers[i].userId == user) {
user = $scope.allUsers[i];
RoleMapping.save({
realm : $scope.realmId,
role : role
}, user, function() {
$scope.users = RoleMapping.query({
realm : $scope.realmId,
role : role
});
Notifications.success("The role mapping has been added for the user.");
});
}
}
}
$scope.removeUser = function(userId) {
for (var i = 0; i < $scope.users.length; i++) {
var user = $scope.users[i];
if ($scope.users[i].userId == userId) {
RoleMapping.delete({
realm : $scope.realmId,
role : role
}, user, function() {
$scope.users = RoleMapping.query({
realm : $scope.realmId,
role : role
});
Notifications.success("The role mapping has been removed for the user.");
});
}
}
}
});
@@ -1,457 +0,0 @@
/**
* @license AngularJS v1.0.7
* (c) 2010-2012 Google, Inc. http://angularjs.org
* License: MIT
*/
(function(window, angular, undefined) {
'use strict';
/**
* @ngdoc overview
* @name ngResource
* @description
*/
/**
* @ngdoc object
* @name ngResource.$resource
* @requires $http
*
* @description
* A factory which creates a resource object that lets you interact with
* [RESTful](http://en.wikipedia.org/wiki/Representational_State_Transfer) server-side data sources.
*
* The returned resource object has action methods which provide high-level behaviors without
* the need to interact with the low level {@link ng.$http $http} service.
*
* # Installation
* To use $resource make sure you have included the `angular-resource.js` that comes in Angular
* package. You can also find this file on Google CDN, bower as well as at
* {@link http://code.angularjs.org/ code.angularjs.org}.
*
* Finally load the module in your application:
*
* angular.module('app', ['ngResource']);
*
* and you are ready to get started!
*
* @param {string} url A parameterized URL template with parameters prefixed by `:` as in
* `/user/:username`. If you are using a URL with a port number (e.g.
* `http://example.com:8080/api`), you'll need to escape the colon character before the port
* number, like this: `$resource('http://example.com\\:8080/api')`.
*
* @param {Object=} paramDefaults Default values for `url` parameters. These can be overridden in
* `actions` methods.
*
* Each key value in the parameter object is first bound to url template if present and then any
* excess keys are appended to the url search query after the `?`.
*
* Given a template `/path/:verb` and parameter `{verb:'greet', salutation:'Hello'}` results in
* URL `/path/greet?salutation=Hello`.
*
* If the parameter value is prefixed with `@` then the value of that parameter is extracted from
* the data object (useful for non-GET operations).
*
* @param {Object.<Object>=} actions Hash with declaration of custom action that should extend the
* default set of resource actions. The declaration should be created in the following format:
*
* {action1: {method:?, params:?, isArray:?},
* action2: {method:?, params:?, isArray:?},
* ...}
*
* Where:
*
* - `action` – {string} – The name of action. This name becomes the name of the method on your
* resource object.
* - `method` – {string} – HTTP request method. Valid methods are: `GET`, `POST`, `PUT`, `DELETE`,
* and `JSONP`
* - `params` – {object=} – Optional set of pre-bound parameters for this action.
* - isArray – {boolean=} – If true then the returned object for this action is an array, see
* `returns` section.
*
* @returns {Object} A resource "class" object with methods for the default set of resource actions
* optionally extended with custom `actions`. The default set contains these actions:
*
* { 'get': {method:'GET'},
* 'save': {method:'POST'},
* 'query': {method:'GET', isArray:true},
* 'remove': {method:'DELETE'},
* 'delete': {method:'DELETE'} };
*
* Calling these methods invoke an {@link ng.$http} with the specified http method,
* destination and parameters. When the data is returned from the server then the object is an
* instance of the resource class. The actions `save`, `remove` and `delete` are available on it
* as methods with the `$` prefix. This allows you to easily perform CRUD operations (create,
* read, update, delete) on server-side data like this:
* <pre>
var User = $resource('/user/:userId', {userId:'@id'});
var user = User.get({userId:123}, function() {
user.abc = true;
user.$save();
});
</pre>
*
* It is important to realize that invoking a $resource object method immediately returns an
* empty reference (object or array depending on `isArray`). Once the data is returned from the
* server the existing reference is populated with the actual data. This is a useful trick since
* usually the resource is assigned to a model which is then rendered by the view. Having an empty
* object results in no rendering, once the data arrives from the server then the object is
* populated with the data and the view automatically re-renders itself showing the new data. This
* means that in most case one never has to write a callback function for the action methods.
*
* The action methods on the class object or instance object can be invoked with the following
* parameters:
*
* - HTTP GET "class" actions: `Resource.action([parameters], [success], [error])`
* - non-GET "class" actions: `Resource.action([parameters], postData, [success], [error])`
* - non-GET instance actions: `instance.$action([parameters], [success], [error])`
*
*
* @example
*
* # Credit card resource
*
* <pre>
// Define CreditCard class
var CreditCard = $resource('/user/:userId/card/:cardId',
{userId:123, cardId:'@id'}, {
charge: {method:'POST', params:{charge:true}}
});
// We can retrieve a collection from the server
var cards = CreditCard.query(function() {
// GET: /user/123/card
// server returns: [ {id:456, number:'1234', name:'Smith'} ];
var card = cards[0];
// each item is an instance of CreditCard
expect(card instanceof CreditCard).toEqual(true);
card.name = "J. Smith";
// non GET methods are mapped onto the instances
card.$save();
// POST: /user/123/card/456 {id:456, number:'1234', name:'J. Smith'}
// server returns: {id:456, number:'1234', name: 'J. Smith'};
// our custom method is mapped as well.
card.$charge({amount:9.99});
// POST: /user/123/card/456?amount=9.99&charge=true {id:456, number:'1234', name:'J. Smith'}
});
// we can create an instance as well
var newCard = new CreditCard({number:'0123'});
newCard.name = "Mike Smith";
newCard.$save();
// POST: /user/123/card {number:'0123', name:'Mike Smith'}
// server returns: {id:789, number:'01234', name: 'Mike Smith'};
expect(newCard.id).toEqual(789);
* </pre>
*
* The object returned from this function execution is a resource "class" which has "static" method
* for each action in the definition.
*
* Calling these methods invoke `$http` on the `url` template with the given `method` and `params`.
* When the data is returned from the server then the object is an instance of the resource type and
* all of the non-GET methods are available with `$` prefix. This allows you to easily support CRUD
* operations (create, read, update, delete) on server-side data.
<pre>
var User = $resource('/user/:userId', {userId:'@id'});
var user = User.get({userId:123}, function() {
user.abc = true;
user.$save();
});
</pre>
*
* It's worth noting that the success callback for `get`, `query` and other method gets passed
* in the response that came from the server as well as $http header getter function, so one
* could rewrite the above example and get access to http headers as:
*
<pre>
var User = $resource('/user/:userId', {userId:'@id'});
User.get({userId:123}, function(u, getResponseHeaders){
u.abc = true;
u.$save(function(u, putResponseHeaders) {
//u => saved user object
//putResponseHeaders => $http header getter
});
});
</pre>
* # Buzz client
Let's look at what a buzz client created with the `$resource` service looks like:
<doc:example>
<doc:source jsfiddle="false">
<script>
function BuzzController($resource) {
this.userId = 'googlebuzz';
this.Activity = $resource(
'https://www.googleapis.com/buzz/v1/activities/:userId/:visibility/:activityId/:comments',
{alt:'json', callback:'JSON_CALLBACK'},
{get:{method:'JSONP', params:{visibility:'@self'}}, replies: {method:'JSONP', params:{visibility:'@self', comments:'@comments'}}}
);
}
BuzzController.prototype = {
fetch: function() {
this.activities = this.Activity.get({userId:this.userId});
},
expandReplies: function(activity) {
activity.replies = this.Activity.replies({userId:this.userId, activityId:activity.id});
}
};
BuzzController.$inject = ['$resource'];
</script>
<div ng-controller="BuzzController">
<input ng-model="userId"/>
<button ng-click="fetch()">fetch</button>
<hr/>
<div ng-repeat="item in activities.data.items">
<h1 style="font-size: 15px;">
<img src="{{item.actor.thumbnailUrl}}" style="max-height:30px;max-width:30px;"/>
<a href="{{item.actor.profileUrl}}">{{item.actor.name}}</a>
<a href ng-click="expandReplies(item)" style="float: right;">Expand replies: {{item.links.replies[0].count}}</a>
</h1>
{{item.object.content | html}}
<div ng-repeat="reply in item.replies.data.items" style="margin-left: 20px;">
<img src="{{reply.actor.thumbnailUrl}}" style="max-height:30px;max-width:30px;"/>
<a href="{{reply.actor.profileUrl}}">{{reply.actor.name}}</a>: {{reply.content | html}}
</div>
</div>
</div>
</doc:source>
<doc:scenario>
</doc:scenario>
</doc:example>
*/
angular.module('ngResource', ['ng']).
factory('$resource', ['$http', '$parse', function($http, $parse) {
var DEFAULT_ACTIONS = {
'get': {method:'GET'},
'save': {method:'POST'},
'query': {method:'GET', isArray:true},
'remove': {method:'DELETE'},
'delete': {method:'DELETE'}
};
var noop = angular.noop,
forEach = angular.forEach,
extend = angular.extend,
copy = angular.copy,
isFunction = angular.isFunction,
getter = function(obj, path) {
return $parse(path)(obj);
};
/**
* We need our custom method because encodeURIComponent is too aggressive and doesn't follow
* http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path
* segments:
* segment = *pchar
* pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
* pct-encoded = "%" HEXDIG HEXDIG
* unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
* sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
* / "*" / "+" / "," / ";" / "="
*/
function encodeUriSegment(val) {
return encodeUriQuery(val, true).
replace(/%26/gi, '&').
replace(/%3D/gi, '=').
replace(/%2B/gi, '+');
}
/**
* This method is intended for encoding *key* or *value* parts of query component. We need a custom
* method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be
* encoded per http://tools.ietf.org/html/rfc3986:
* query = *( pchar / "/" / "?" )
* pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
* unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
* pct-encoded = "%" HEXDIG HEXDIG
* sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
* / "*" / "+" / "," / ";" / "="
*/
function encodeUriQuery(val, pctEncodeSpaces) {
return encodeURIComponent(val).
replace(/%40/gi, '@').
replace(/%3A/gi, ':').
replace(/%24/g, '$').
replace(/%2C/gi, ',').
replace(/%20/g, (pctEncodeSpaces ? '%20' : '+'));
}
function Route(template, defaults) {
this.template = template = template + '#';
this.defaults = defaults || {};
var urlParams = this.urlParams = {};
forEach(template.split(/\W/), function(param){
if (param && (new RegExp("(^|[^\\\\]):" + param + "\\W").test(template))) {
urlParams[param] = true;
}
});
this.template = template.replace(/\\:/g, ':');
}
Route.prototype = {
url: function(params) {
var self = this,
url = this.template,
val,
encodedVal;
params = params || {};
forEach(this.urlParams, function(_, urlParam){
val = params.hasOwnProperty(urlParam) ? params[urlParam] : self.defaults[urlParam];
if (angular.isDefined(val) && val !== null) {
encodedVal = encodeUriSegment(val);
url = url.replace(new RegExp(":" + urlParam + "(\\W)", "g"), encodedVal + "$1");
} else {
url = url.replace(new RegExp("(\/?):" + urlParam + "(\\W)", "g"), function(match,
leadingSlashes, tail) {
if (tail.charAt(0) == '/') {
return tail;
} else {
return leadingSlashes + tail;
}
});
}
});
url = url.replace(/\/?#$/, '');
var query = [];
forEach(params, function(value, key){
if (!self.urlParams[key]) {
query.push(encodeUriQuery(key) + '=' + encodeUriQuery(value));
}
});
query.sort();
url = url.replace(/\/*$/, '');
return url + (query.length ? '?' + query.join('&') : '');
}
};
function ResourceFactory(url, paramDefaults, actions) {
var route = new Route(url);
actions = extend({}, DEFAULT_ACTIONS, actions);
function extractParams(data, actionParams){
var ids = {};
actionParams = extend({}, paramDefaults, actionParams);
forEach(actionParams, function(value, key){
ids[key] = value.charAt && value.charAt(0) == '@' ? getter(data, value.substr(1)) : value;
});
return ids;
}
function Resource(value){
copy(value || {}, this);
}
forEach(actions, function(action, name) {
action.method = angular.uppercase(action.method);
var hasBody = action.method == 'POST' || action.method == 'PUT' || action.method == 'PATCH';
Resource[name] = function(a1, a2, a3, a4) {
var params = {};
var data;
var success = noop;
var error = null;
switch(arguments.length) {
case 4:
error = a4;
success = a3;
//fallthrough
case 3:
case 2:
if (isFunction(a2)) {
if (isFunction(a1)) {
success = a1;
error = a2;
break;
}
success = a2;
error = a3;
//fallthrough
} else {
params = a1;
data = a2;
success = a3;
break;
}
case 1:
if (isFunction(a1)) success = a1;
else if (hasBody) data = a1;
else params = a1;
break;
case 0: break;
default:
throw "Expected between 0-4 arguments [params, data, success, error], got " +
arguments.length + " arguments.";
}
var value = this instanceof Resource ? this : (action.isArray ? [] : new Resource(data));
$http({
method: action.method,
url: route.url(extend({}, extractParams(data, action.params || {}), params)),
data: data
}).then(function(response) {
var data = response.data;
if (data) {
if (action.isArray) {
value.length = 0;
forEach(data, function(item) {
value.push(new Resource(item));
});
} else {
copy(data, value);
}
}
(success||noop)(value, response.headers);
}, error);
return value;
};
Resource.prototype['$' + name] = function(a1, a2, a3) {
var params = extractParams(this),
success = noop,
error;
switch(arguments.length) {
case 3: params = a1; success = a2; error = a3; break;
case 2:
case 1:
if (isFunction(a1)) {
success = a1;
error = a2;
} else {
params = a1;
success = a2 || noop;
}
case 0: break;
default:
throw "Expected between 1-3 arguments [params, success, error], got " +
arguments.length + " arguments.";
}
var data = hasBody ? this : undefined;
Resource[name].call(this, params, data, success, error);
};
});
Resource.bind = function(additionalParamDefaults){
return ResourceFactory(url, extend({}, paramDefaults, additionalParamDefaults), actions);
};
return Resource;
}
return ResourceFactory;
}]);
})(window, window.angular);
@@ -1,537 +0,0 @@
/**
* @license AngularJS v1.0.7
* (c) 2010-2012 Google, Inc. http://angularjs.org
* License: MIT
*/
(function(window, angular, undefined) {
'use strict';
/**
* @ngdoc overview
* @name ngSanitize
* @description
*/
/*
* HTML Parser By Misko Hevery (misko@hevery.com)
* based on: HTML Parser By John Resig (ejohn.org)
* Original code by Erik Arvidsson, Mozilla Public License
* http://erik.eae.net/simplehtmlparser/simplehtmlparser.js
*
* // Use like so:
* htmlParser(htmlString, {
* start: function(tag, attrs, unary) {},
* end: function(tag) {},
* chars: function(text) {},
* comment: function(text) {}
* });
*
*/
/**
* @ngdoc service
* @name ngSanitize.$sanitize
* @function
*
* @description
* The input is sanitized by parsing the html into tokens. All safe tokens (from a whitelist) are
* then serialized back to properly escaped html string. This means that no unsafe input can make
* it into the returned string, however, since our parser is more strict than a typical browser
* parser, it's possible that some obscure input, which would be recognized as valid HTML by a
* browser, won't make it through the sanitizer.
*
* @param {string} html Html input.
* @returns {string} Sanitized html.
*
* @example
<doc:example module="ngSanitize">
<doc:source>
<script>
function Ctrl($scope) {
$scope.snippet =
'<p style="color:blue">an html\n' +
'<em onmouseover="this.textContent=\'PWN3D!\'">click here</em>\n' +
'snippet</p>';
}
</script>
<div ng-controller="Ctrl">
Snippet: <textarea ng-model="snippet" cols="60" rows="3"></textarea>
<table>
<tr>
<td>Filter</td>
<td>Source</td>
<td>Rendered</td>
</tr>
<tr id="html-filter">
<td>html filter</td>
<td>
<pre>&lt;div ng-bind-html="snippet"&gt;<br/>&lt;/div&gt;</pre>
</td>
<td>
<div ng-bind-html="snippet"></div>
</td>
</tr>
<tr id="escaped-html">
<td>no filter</td>
<td><pre>&lt;div ng-bind="snippet"&gt;<br/>&lt;/div&gt;</pre></td>
<td><div ng-bind="snippet"></div></td>
</tr>
<tr id="html-unsafe-filter">
<td>unsafe html filter</td>
<td><pre>&lt;div ng-bind-html-unsafe="snippet"&gt;<br/>&lt;/div&gt;</pre></td>
<td><div ng-bind-html-unsafe="snippet"></div></td>
</tr>
</table>
</div>
</doc:source>
<doc:scenario>
it('should sanitize the html snippet ', function() {
expect(using('#html-filter').element('div').html()).
toBe('<p>an html\n<em>click here</em>\nsnippet</p>');
});
it('should escape snippet without any filter', function() {
expect(using('#escaped-html').element('div').html()).
toBe("&lt;p style=\"color:blue\"&gt;an html\n" +
"&lt;em onmouseover=\"this.textContent='PWN3D!'\"&gt;click here&lt;/em&gt;\n" +
"snippet&lt;/p&gt;");
});
it('should inline raw snippet if filtered as unsafe', function() {
expect(using('#html-unsafe-filter').element("div").html()).
toBe("<p style=\"color:blue\">an html\n" +
"<em onmouseover=\"this.textContent='PWN3D!'\">click here</em>\n" +
"snippet</p>");
});
it('should update', function() {
input('snippet').enter('new <b>text</b>');
expect(using('#html-filter').binding('snippet')).toBe('new <b>text</b>');
expect(using('#escaped-html').element('div').html()).toBe("new &lt;b&gt;text&lt;/b&gt;");
expect(using('#html-unsafe-filter').binding("snippet")).toBe('new <b>text</b>');
});
</doc:scenario>
</doc:example>
*/
var $sanitize = function(html) {
var buf = [];
htmlParser(html, htmlSanitizeWriter(buf));
return buf.join('');
};
// Regular Expressions for parsing tags and attributes
var START_TAG_REGEXP = /^<\s*([\w:-]+)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)\s*>/,
END_TAG_REGEXP = /^<\s*\/\s*([\w:-]+)[^>]*>/,
ATTR_REGEXP = /([\w:-]+)(?:\s*=\s*(?:(?:"((?:[^"])*)")|(?:'((?:[^'])*)')|([^>\s]+)))?/g,
BEGIN_TAG_REGEXP = /^</,
BEGING_END_TAGE_REGEXP = /^<\s*\//,
COMMENT_REGEXP = /<!--(.*?)-->/g,
CDATA_REGEXP = /<!\[CDATA\[(.*?)]]>/g,
URI_REGEXP = /^((ftp|https?):\/\/|mailto:|#)/,
NON_ALPHANUMERIC_REGEXP = /([^\#-~| |!])/g; // Match everything outside of normal chars and " (quote character)
// Good source of info about elements and attributes
// http://dev.w3.org/html5/spec/Overview.html#semantics
// http://simon.html5.org/html-elements
// Safe Void Elements - HTML5
// http://dev.w3.org/html5/spec/Overview.html#void-elements
var voidElements = makeMap("area,br,col,hr,img,wbr");
// Elements that you can, intentionally, leave open (and which close themselves)
// http://dev.w3.org/html5/spec/Overview.html#optional-tags
var optionalEndTagBlockElements = makeMap("colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr"),
optionalEndTagInlineElements = makeMap("rp,rt"),
optionalEndTagElements = angular.extend({}, optionalEndTagInlineElements, optionalEndTagBlockElements);
// Safe Block Elements - HTML5
var blockElements = angular.extend({}, optionalEndTagBlockElements, makeMap("address,article,aside," +
"blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5,h6," +
"header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul"));
// Inline Elements - HTML5
var inlineElements = angular.extend({}, optionalEndTagInlineElements, makeMap("a,abbr,acronym,b,bdi,bdo," +
"big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s,samp,small," +
"span,strike,strong,sub,sup,time,tt,u,var"));
// Special Elements (can contain anything)
var specialElements = makeMap("script,style");
var validElements = angular.extend({}, voidElements, blockElements, inlineElements, optionalEndTagElements);
//Attributes that have href and hence need to be sanitized
var uriAttrs = makeMap("background,cite,href,longdesc,src,usemap");
var validAttrs = angular.extend({}, uriAttrs, makeMap(
'abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,'+
'color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,'+
'ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,'+
'scope,scrolling,shape,span,start,summary,target,title,type,'+
'valign,value,vspace,width'));
function makeMap(str) {
var obj = {}, items = str.split(','), i;
for (i = 0; i < items.length; i++) obj[items[i]] = true;
return obj;
}
/**
* @example
* htmlParser(htmlString, {
* start: function(tag, attrs, unary) {},
* end: function(tag) {},
* chars: function(text) {},
* comment: function(text) {}
* });
*
* @param {string} html string
* @param {object} handler
*/
function htmlParser( html, handler ) {
var index, chars, match, stack = [], last = html;
stack.last = function() { return stack[ stack.length - 1 ]; };
while ( html ) {
chars = true;
// Make sure we're not in a script or style element
if ( !stack.last() || !specialElements[ stack.last() ] ) {
// Comment
if ( html.indexOf("<!--") === 0 ) {
index = html.indexOf("-->");
if ( index >= 0 ) {
if (handler.comment) handler.comment( html.substring( 4, index ) );
html = html.substring( index + 3 );
chars = false;
}
// end tag
} else if ( BEGING_END_TAGE_REGEXP.test(html) ) {
match = html.match( END_TAG_REGEXP );
if ( match ) {
html = html.substring( match[0].length );
match[0].replace( END_TAG_REGEXP, parseEndTag );
chars = false;
}
// start tag
} else if ( BEGIN_TAG_REGEXP.test(html) ) {
match = html.match( START_TAG_REGEXP );
if ( match ) {
html = html.substring( match[0].length );
match[0].replace( START_TAG_REGEXP, parseStartTag );
chars = false;
}
}
if ( chars ) {
index = html.indexOf("<");
var text = index < 0 ? html : html.substring( 0, index );
html = index < 0 ? "" : html.substring( index );
if (handler.chars) handler.chars( decodeEntities(text) );
}
} else {
html = html.replace(new RegExp("(.*)<\\s*\\/\\s*" + stack.last() + "[^>]*>", 'i'), function(all, text){
text = text.
replace(COMMENT_REGEXP, "$1").
replace(CDATA_REGEXP, "$1");
if (handler.chars) handler.chars( decodeEntities(text) );
return "";
});
parseEndTag( "", stack.last() );
}
if ( html == last ) {
throw "Parse Error: " + html;
}
last = html;
}
// Clean up any remaining tags
parseEndTag();
function parseStartTag( tag, tagName, rest, unary ) {
tagName = angular.lowercase(tagName);
if ( blockElements[ tagName ] ) {
while ( stack.last() && inlineElements[ stack.last() ] ) {
parseEndTag( "", stack.last() );
}
}
if ( optionalEndTagElements[ tagName ] && stack.last() == tagName ) {
parseEndTag( "", tagName );
}
unary = voidElements[ tagName ] || !!unary;
if ( !unary )
stack.push( tagName );
var attrs = {};
rest.replace(ATTR_REGEXP, function(match, name, doubleQuotedValue, singleQoutedValue, unqoutedValue) {
var value = doubleQuotedValue
|| singleQoutedValue
|| unqoutedValue
|| '';
attrs[name] = decodeEntities(value);
});
if (handler.start) handler.start( tagName, attrs, unary );
}
function parseEndTag( tag, tagName ) {
var pos = 0, i;
tagName = angular.lowercase(tagName);
if ( tagName )
// Find the closest opened tag of the same type
for ( pos = stack.length - 1; pos >= 0; pos-- )
if ( stack[ pos ] == tagName )
break;
if ( pos >= 0 ) {
// Close all the open elements, up the stack
for ( i = stack.length - 1; i >= pos; i-- )
if (handler.end) handler.end( stack[ i ] );
// Remove the open elements from the stack
stack.length = pos;
}
}
}
/**
* decodes all entities into regular string
* @param value
* @returns {string} A string with decoded entities.
*/
var hiddenPre=document.createElement("pre");
function decodeEntities(value) {
hiddenPre.innerHTML=value.replace(/</g,"&lt;");
return hiddenPre.innerText || hiddenPre.textContent || '';
}
/**
* Escapes all potentially dangerous characters, so that the
* resulting string can be safely inserted into attribute or
* element text.
* @param value
* @returns escaped text
*/
function encodeEntities(value) {
return value.
replace(/&/g, '&amp;').
replace(NON_ALPHANUMERIC_REGEXP, function(value){
return '&#' + value.charCodeAt(0) + ';';
}).
replace(/</g, '&lt;').
replace(/>/g, '&gt;');
}
/**
* create an HTML/XML writer which writes to buffer
* @param {Array} buf use buf.jain('') to get out sanitized html string
* @returns {object} in the form of {
* start: function(tag, attrs, unary) {},
* end: function(tag) {},
* chars: function(text) {},
* comment: function(text) {}
* }
*/
function htmlSanitizeWriter(buf){
var ignore = false;
var out = angular.bind(buf, buf.push);
return {
start: function(tag, attrs, unary){
tag = angular.lowercase(tag);
if (!ignore && specialElements[tag]) {
ignore = tag;
}
if (!ignore && validElements[tag] == true) {
out('<');
out(tag);
angular.forEach(attrs, function(value, key){
var lkey=angular.lowercase(key);
if (validAttrs[lkey]==true && (uriAttrs[lkey]!==true || value.match(URI_REGEXP))) {
out(' ');
out(key);
out('="');
out(encodeEntities(value));
out('"');
}
});
out(unary ? '/>' : '>');
}
},
end: function(tag){
tag = angular.lowercase(tag);
if (!ignore && validElements[tag] == true) {
out('</');
out(tag);
out('>');
}
if (tag == ignore) {
ignore = false;
}
},
chars: function(chars){
if (!ignore) {
out(encodeEntities(chars));
}
}
};
}
// define ngSanitize module and register $sanitize service
angular.module('ngSanitize', []).value('$sanitize', $sanitize);
/**
* @ngdoc directive
* @name ngSanitize.directive:ngBindHtml
*
* @description
* Creates a binding that will sanitize the result of evaluating the `expression` with the
* {@link ngSanitize.$sanitize $sanitize} service and innerHTML the result into the current element.
*
* See {@link ngSanitize.$sanitize $sanitize} docs for examples.
*
* @element ANY
* @param {expression} ngBindHtml {@link guide/expression Expression} to evaluate.
*/
angular.module('ngSanitize').directive('ngBindHtml', ['$sanitize', function($sanitize) {
return function(scope, element, attr) {
element.addClass('ng-binding').data('$binding', attr.ngBindHtml);
scope.$watch(attr.ngBindHtml, function ngBindHtmlWatchAction(value) {
value = $sanitize(value);
element.html(value || '');
});
};
}]);
/**
* @ngdoc filter
* @name ngSanitize.filter:linky
* @function
*
* @description
* Finds links in text input and turns them into html links. Supports http/https/ftp/mailto and
* plain email address links.
*
* @param {string} text Input text.
* @returns {string} Html-linkified text.
*
* @usage
<span ng-bind-html="linky_expression | linky"></span>
*
* @example
<doc:example module="ngSanitize">
<doc:source>
<script>
function Ctrl($scope) {
$scope.snippet =
'Pretty text with some links:\n'+
'http://angularjs.org/,\n'+
'mailto:us@somewhere.org,\n'+
'another@somewhere.org,\n'+
'and one more: ftp://127.0.0.1/.';
}
</script>
<div ng-controller="Ctrl">
Snippet: <textarea ng-model="snippet" cols="60" rows="3"></textarea>
<table>
<tr>
<td>Filter</td>
<td>Source</td>
<td>Rendered</td>
</tr>
<tr id="linky-filter">
<td>linky filter</td>
<td>
<pre>&lt;div ng-bind-html="snippet | linky"&gt;<br>&lt;/div&gt;</pre>
</td>
<td>
<div ng-bind-html="snippet | linky"></div>
</td>
</tr>
<tr id="escaped-html">
<td>no filter</td>
<td><pre>&lt;div ng-bind="snippet"&gt;<br>&lt;/div&gt;</pre></td>
<td><div ng-bind="snippet"></div></td>
</tr>
</table>
</doc:source>
<doc:scenario>
it('should linkify the snippet with urls', function() {
expect(using('#linky-filter').binding('snippet | linky')).
toBe('Pretty text with some links:&#10;' +
'<a href="http://angularjs.org/">http://angularjs.org/</a>,&#10;' +
'<a href="mailto:us@somewhere.org">us@somewhere.org</a>,&#10;' +
'<a href="mailto:another@somewhere.org">another@somewhere.org</a>,&#10;' +
'and one more: <a href="ftp://127.0.0.1/">ftp://127.0.0.1/</a>.');
});
it ('should not linkify snippet without the linky filter', function() {
expect(using('#escaped-html').binding('snippet')).
toBe("Pretty text with some links:\n" +
"http://angularjs.org/,\n" +
"mailto:us@somewhere.org,\n" +
"another@somewhere.org,\n" +
"and one more: ftp://127.0.0.1/.");
});
it('should update', function() {
input('snippet').enter('new http://link.');
expect(using('#linky-filter').binding('snippet | linky')).
toBe('new <a href="http://link">http://link</a>.');
expect(using('#escaped-html').binding('snippet')).toBe('new http://link.');
});
</doc:scenario>
</doc:example>
*/
angular.module('ngSanitize').filter('linky', function() {
var LINKY_URL_REGEXP = /((ftp|https?):\/\/|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s\.\;\,\(\)\{\}\<\>]/,
MAILTO_REGEXP = /^mailto:/;
return function(text) {
if (!text) return text;
var match;
var raw = text;
var html = [];
// TODO(vojta): use $sanitize instead
var writer = htmlSanitizeWriter(html);
var url;
var i;
while ((match = raw.match(LINKY_URL_REGEXP))) {
// We can not end in these as they are sometimes found at the end of the sentence
url = match[0];
// if we did not match ftp/http/mailto then assume mailto
if (match[2] == match[3]) url = 'mailto:' + url;
i = match.index;
writer.chars(raw.substr(0, i));
writer.start('a', {href:url});
writer.chars(match[0].replace(MAILTO_REGEXP, ''));
writer.end('a');
raw = raw.substring(i + match[0].length);
}
writer.chars(raw);
return html.join('');
};
});
})(window, window.angular);
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
@@ -1,195 +0,0 @@
/**
* Enhanced Select2 Dropmenus
*
* @AJAX Mode - When in this mode, your value will be an object (or array of objects) of the data used by Select2
* This change is so that you do not have to do an additional query yourself on top of Select2's own query
* @params [options] {object} The configuration options passed to $.fn.select2(). Refer to the documentation
*/
angular.module('ui.select2', []).value('uiSelect2Config', {}).directive('uiSelect2', ['uiSelect2Config', '$timeout', function (uiSelect2Config, $timeout) {
var options = {};
if (uiSelect2Config) {
angular.extend(options, uiSelect2Config);
}
return {
require: 'ngModel',
compile: function (tElm, tAttrs) {
var watch,
repeatOption,
repeatAttr,
isSelect = tElm.is('select'),
isMultiple = (tAttrs.multiple !== undefined);
// Enable watching of the options dataset if in use
if (tElm.is('select')) {
repeatOption = tElm.find('option[ng-repeat], option[data-ng-repeat]');
if (repeatOption.length) {
repeatAttr = repeatOption.attr('ng-repeat') || repeatOption.attr('data-ng-repeat');
watch = jQuery.trim(repeatAttr.split('|')[0]).split(' ').pop();
}
}
return function (scope, elm, attrs, controller) {
// instance-specific options
var opts = angular.extend({}, options, scope.$eval(attrs.uiSelect2));
/*
Convert from Select2 view-model to Angular view-model.
*/
var convertToAngularModel = function(select2_data) {
var model;
if (opts.simple_tags) {
model = []
angular.forEach(select2_data, function(value, index) {
model.push(value.id)
})
} else {
model = select2_data
}
return model
}
/*
Convert from Angular view-model to Select2 view-model.
*/
var convertToSelect2Model = function(angular_data) {
var model = []
if (!angular_data) {
return model;
}
if (opts.simple_tags) {
model = [];
angular.forEach(
angular_data,
function(value, index) {
model.push({'id': value, 'text': value});
})
} else {
model = angular_data;
}
return model
}
if (isSelect) {
// Use <select multiple> instead
delete opts.multiple;
delete opts.initSelection;
} else if (isMultiple) {
opts.multiple = true;
}
if (controller) {
// Watch the model for programmatic changes
scope.$watch(tAttrs.ngModel, function(current, old) {
if (!current) {
return
}
if (current == old) {
return
}
controller.$render()
}, true)
controller.$render = function () {
if (isSelect) {
elm.select2('val', controller.$viewValue);
} else {
if (opts.multiple) {
elm.select2(
'data', convertToSelect2Model(controller.$viewValue));
} else {
if (angular.isObject(controller.$viewValue)) {
elm.select2('data', controller.$viewValue);
} else if (!controller.$viewValue) {
elm.select2('data', null);
} else {
elm.select2('val', controller.$viewValue);
}
}
}
};
// Watch the options dataset for changes
if (watch) {
scope.$watch(watch, function (newVal, oldVal, scope) {
if (!newVal) return;
// Delayed so that the options have time to be rendered
$timeout(function () {
elm.select2('val', controller.$viewValue);
// Refresh angular to remove the superfluous option
elm.trigger('change');
});
});
}
// Update valid and dirty statuses
controller.$parsers.push(function (value) {
var div = elm.prev()
div
.toggleClass('ng-invalid', !controller.$valid)
.toggleClass('ng-valid', controller.$valid)
.toggleClass('ng-invalid-required', !controller.$valid)
.toggleClass('ng-valid-required', controller.$valid)
.toggleClass('ng-dirty', controller.$dirty)
.toggleClass('ng-pristine', controller.$pristine);
return value;
});
if (!isSelect) {
// Set the view and model value and update the angular template manually for the ajax/multiple select2.
elm.bind("change", function () {
if (scope.$$phase) return;
scope.$apply(function () {
controller.$setViewValue(
convertToAngularModel(elm.select2('data')));
});
});
if (opts.initSelection) {
var initSelection = opts.initSelection;
opts.initSelection = function (element, callback) {
initSelection(element, function (value) {
controller.$setViewValue(convertToAngularModel(value));
callback(value);
});
};
}
}
}
elm.bind("$destroy", function() {
elm.select2("destroy");
});
attrs.$observe('disabled', function (value) {
elm.select2('enable', !value);
});
attrs.$observe('readonly', function (value) {
elm.select2('readonly', !!value);
});
if (attrs.ngMultiple) {
scope.$watch(attrs.ngMultiple, function(newVal) {
elm.select2(opts);
});
}
// Initialize the plugin late so that the injected DOM does not disrupt the template compiler
$timeout(function () {
elm.select2(opts);
// Set initial value - I'm not sure about this but it seems to need to be there
elm.val(controller.$viewValue);
// important!
controller.$render();
// Not sure if I should just check for !isSelect OR if I should check for 'tags' key
if (!opts.initSelection && !isSelect)
controller.$setViewValue(
convertToAngularModel(elm.select2('data')));
});
};
}
};
}]);
@@ -1,185 +0,0 @@
/*
* jQuery Idle Timeout 1.1
* Copyright (c) 2011 Eric Hynds
*
* http://www.erichynds.com/jquery/a-new-and-improved-jquery-idle-timeout-plugin/
*
* Depends:
* - jQuery 1.4.2+
* - jQuery Idle Timer (by Paul Irish, http://paulirish.com/2009/jquery-idletimer-plugin/)
*
* Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
*
*/
(function($, win){
var idleTimeout = {
init: function( element, resume, options ){
var self = this, elem;
this.warning = elem = $(element);
this.resume = $(resume);
this.options = options;
this.countdownOpen = false;
this.failedRequests = options.failedRequests;
this._startTimer();
// expose obj to data cache so peeps can call internal methods
$.data( elem[0], 'idletimout', this );
// start the idle timer
$.idleTimer(options.idleAfter * 1000);
// once the user becomes idle
$(document).bind("idle.idleTimer", function(){
// if the user is idle and a countdown isn't already running
if( $.data(document, 'idleTimer') === 'idle' && !self.countdownOpen ){
self._stopTimer();
self.countdownOpen = true;
self._idle();
}
});
// bind continue link
this.resume.bind("click", function(e){
e.preventDefault();
win.clearInterval(self.countdown); // stop the countdown
self.countdownOpen = false; // stop countdown
self._startTimer(); // start up the timer again
self._keepAlive( false ); // ping server
options.onResume.call( self.warning ); // call the resume callback
});
},
_idle: function(){
var self = this,
options = this.options,
warning = this.warning[0],
counter = options.warningLength;
// fire the onIdle function
options.onIdle.call(warning);
// set inital value in the countdown placeholder
options.onCountdown.call(warning, counter);
// create a timer that runs every second
this.countdown = win.setInterval(function(){
if(--counter === 0){
window.clearInterval(self.countdown);
options.onTimeout.call(warning);
} else {
options.onCountdown.call(warning, counter);
}
}, 1000);
},
_startTimer: function(){
var self = this;
if (this.options.pollingInterval > 0) {
this.timer = win.setTimeout(function () {
self._keepAlive();
}, this.options.pollingInterval * 1000);
}
},
_stopTimer: function(){
// reset the failed requests counter
this.failedRequests = this.options.failedRequests;
win.clearTimeout(this.timer);
},
_keepAlive: function( recurse ){
var self = this,
options = this.options;
if( typeof recurse === "undefined" ){
recurse = true;
}
// if too many requests failed, abort
if( !this.failedRequests ){
console.log('aborting...');
this._stopTimer();
options.onAbort.call( this.warning[0] );
return;
}
$.ajax({
timeout: options.AJAXTimeout,
url: options.keepAliveURL,
error: function(){
console.log('failure for keepalive');
self.failedRequests--;
},
success: function(response){
console.log('success for keepalive');
/* if($.trim(response) !== options.serverResponseEquals){
self.failedRequests--;
}*/
},
complete: function(){
if( recurse ){
self._startTimer();
}
}
});
}
};
// expose
$.idleTimeout = function(element, resume, options){
idleTimeout.init( element, resume, $.extend($.idleTimeout.options, options) );
return this;
};
// options
$.idleTimeout.options = {
// number of seconds after user is idle to show the warning
warningLength: 30,
// url to call to keep the session alive while the user is active
keepAliveURL: "",
// the response from keepAliveURL must equal this text:
serverResponseEquals: "OK",
// user is considered idle after this many seconds. 10 minutes default
idleAfter: 600,
// a polling request will be sent to the server every X seconds
pollingInterval: 60,
// number of failed polling requests until we abort this script
failedRequests: 5,
// the $.ajax timeout in MILLISECONDS!
AJAXTimeout: 250,
/*
Callbacks
"this" refers to the element found by the first selector passed to $.idleTimeout.
*/
// callback to fire when the session times out
onTimeout: $.noop,
// fires when the user becomes idle
onIdle: $.noop,
// fires during each second of warningLength
onCountdown: $.noop,
// fires when the user resumes the session
onResume: $.noop,
// callback to fire when the script is aborted due to too many failed requests
onAbort: $.noop
};
})(jQuery, window);
@@ -1,116 +0,0 @@
(function($){
$.idleTimer = function f(newTimeout){
//$.idleTimer.tId = -1 //timeout ID
var idle = false, //indicates if the user is idle
enabled = true, //indicates if the idle timer is enabled
timeout = 30000, //the amount of time (ms) before the user is considered idle
events = 'mousemove keydown DOMMouseScroll mousewheel mousedown', // activity is one of these events
//f.olddate = undefined, // olddate used for getElapsedTime. stored on the function
/* (intentionally not documented)
* Toggles the idle state and fires an appropriate event.
* @return {void}
*/
toggleIdleState = function(){
//toggle the state
idle = !idle;
// reset timeout counter
f.olddate = +new Date;
//fire appropriate event
$(document).trigger( $.data(document,'idleTimer', idle ? "idle" : "active" ) + '.idleTimer');
},
/**
* Stops the idle timer. This removes appropriate event handlers
* and cancels any pending timeouts.
* @return {void}
* @method stop
* @static
*/
stop = function(){
//set to disabled
enabled = false;
//clear any pending timeouts
clearTimeout($.idleTimer.tId);
//detach the event handlers
$(document).unbind('.idleTimer');
},
/* (intentionally not documented)
* Handles a user event indicating that the user isn't idle.
* @param {Event} event A DOM2-normalized event object.
* @return {void}
*/
handleUserEvent = function(){
//clear any existing timeout
clearTimeout($.idleTimer.tId);
//if the idle timer is enabled
if (enabled){
//if it's idle, that means the user is no longer idle
if (idle){
toggleIdleState();
}
//set a new timeout
$.idleTimer.tId = setTimeout(toggleIdleState, timeout);
}
};
/**
* Starts the idle timer. This adds appropriate event handlers
* and starts the first timeout.
* @param {int} newTimeout (Optional) A new value for the timeout period in ms.
* @return {void}
* @method $.idleTimer
* @static
*/
f.olddate = f.olddate || +new Date;
//assign a new timeout if necessary
if (typeof newTimeout == "number"){
timeout = newTimeout;
} else if (newTimeout === 'destroy') {
stop();
return this;
} else if (newTimeout === 'getElapsedTime'){
return (+new Date) - f.olddate;
}
//assign appropriate event handlers
$(document).bind($.trim((events+' ').split(' ').join('.idleTimer ')),handleUserEvent);
//set a timeout to toggle state
$.idleTimer.tId = setTimeout(toggleIdleState, timeout);
// assume the user is active for the first x seconds.
$.data(document,'idleTimer',"active");
}; // end of $.idleTimer()
})(jQuery);
@@ -1,122 +0,0 @@
<div class="bs-sidebar col-md-3 clearfix" data-ng-include data-src="'partials/realm-menu.html'"></div>
<div id="content-area" class="col-md-9" role="main">
<ul class="nav nav-tabs nav-tabs-pf" data-ng-show="!create">
<li class="active"><a href="#/realms/{{realm.realm}}/applications/{{application.name}}">Settings</a></li>
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/credentials">Credentials</a></li>
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/installation">Installation</a></li>
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/roles">Roles</a></li>
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/scope-mappings">Scope</a></li>
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/sessions">Sessions</a></li>
</ul>
<div id="content">
<ol class="breadcrumb" data-ng-show="create">
<li><a href="#/realms/{{realm.realm}}">{{realm.realm}}</a></li>
<li><a href="#/realms/{{realm.realm}}/applications">Applications</a></li>
<li class="active">Add Application</li>
</ol>
<h2 data-ng-show="create"><span>{{realm.realm}}</span> Add Application</h2>
<p class="subtitle" data-ng-show="create"><span class="required">*</span> Required fields</p>
<ol class="breadcrumb" data-ng-hide="create">
<li><a href="#/realms/{{realm.realm}}">{{realm.realm}}</a></li>
<li><a href="#/realms/{{realm.realm}}/applications">Applications</a></li>
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}">{{application.name}}</a></li>
<li class="active">Settings</li>
</ol>
<h2 data-ng-hide="create"><span>{{application.name}}</span> Settings</h2>
<form class="form-horizontal" name="applicationForm" novalidate>
<fieldset class="border-top">
<div class="form-group">
<label class="col-sm-2 control-label" for="name">Name <span class="required" data-ng-show="create">*</span></label>
<div class="col-sm-4">
<input class="form-control" type="text" id="name" name="name" data-ng-model="application.name" autofocus required>
</div>
</div>
<div class="form-group clearfix block">
<label class="col-sm-2 control-label" for="enabled">Enabled</label>
<div class="col-sm-4">
<input ng-model="application.enabled" name="enabled" id="enabled" onoffswitch />
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label" for="baseUrl">Base URL</label>
<div class="col-sm-4">
<input class="form-control" type="text" name="baseUrl" id="baseUrl"
data-ng-model="application.baseUrl">
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label" for="adminUrl">Admin URL</label>
<div class="col-sm-4">
<input class="form-control" type="text" name="adminUrl" id="adminUrl"
data-ng-model="application.adminUrl">
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label" for="newWebOrigin">Web Origin</label>
<div class="col-sm-4">
<div ng-repeat="webOrigin in application.webOrigins" class="row kc-item-deletable">
<div class="col-sm-9">
<input class="form-control kc-button-control"
type="text" data-ng-class="{'input-below':!$first}"
name="webOrigin" id="webOrigin"
data-ng-model="webOrigin" readonly/>
</div>
<div class="col-sm-2">
<button class="btn btn-danger"
type="button" data-ng-click="deleteWebOrigin($index)">Delete</button>
</div>
</div>
<div class="row">
<div class="col-sm-9">
<input class="form-control kc-button-control"
type="text" name="newWebOrigin" id="newWebOrigin"
placeholder="New Web Origin..." data-ng-model="newWebOrigin"
data-ng-class="{'input-below':application.webOrigins.length}"/>
</div>
<div class="col-sm-2">
<button class="btn btn-primary"
data-ng-click="addWebOrigin()" ng-show="newWebOrigin.length > 0">Add</button>
</div>
</div>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label" for="newRedirectUri">Redirect URI</label>
<div class="col-sm-4">
<div ng-repeat="redirectUri in application.redirectUris" class="row kc-item-deletable">
<div class="col-sm-9">
<input class="form-control" type="text" data-ng-class="{'input-below':!$first}"
name="redirectUri" id="redirectUri" data-ng-model="redirectUri" readonly />
</div>
<div class="col-sm-2">
<button class="btn btn-danger" type="button" data-ng-click="deleteRedirectUri($index)">
Delete</button>
</div>
</div>
<div class="row">
<div class="col-sm-9">
<input class="form-control" type="text" name="newRedirectUri" id="newRedirectUri"
placeholder="New Redirect URI..." data-ng-model="newRedirectUri"
data-ng-class="{'input-below':application.redirectUris.length}" />
</div>
<div class="col-sm-2">
<button class="btn btn-primary" data-ng-click="addRedirectUri()" ng-show="newRedirectUri.length > 0">Add</button>
</div>
</div>
</div>
</div>
</fieldset>
<div class="pull-right form-actions" data-ng-show="create">
<button kc-cancel data-ng-click="cancel()">Cancel</button>
<button kc-save data-ng-show="changed">Save</button>
</div>
<div class="pull-right form-actions" data-ng-show="!create">
<button kc-reset data-ng-show="changed">Clear changes</button>
<button kc-save data-ng-show="changed">Save</button>
<button kc-delete data-ng-click="remove()" data-ng-hide="changed">Delete</button>
</div>
</form>
</div>
</div>
@@ -1,48 +0,0 @@
<nav id="kc-navigation" class="navbar" role="navigation">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse-1">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<h1 class="navbar-title"></h1>
</div>
<div class="collapse navbar-collapse navbar-collapse-1">
<ul class="nav navbar-nav navbar-utility" data-ng-show="auth.loggedIn">
<li class="dropdown">
<a data-toggle="dropdown" class="dropdown-toggle" href="#">
<span class="pficon pficon-user"></span>
{{auth.user.displayName}}<b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li><a href="/auth/rest/realms/keycloak-admin/account?referrer=admin-console">Manage Account</a></li>
<li class="separator"><a href="/auth/rest/admin/logout">Sign Out</a></li>
</ul>
</li>
</ul>
<ul class="nav navbar-nav navbar-primary persistent-secondary" data-ng-controller="RealmDropdownCtrl">
<li class="dropdown context" data-ng-show="showNav()">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
{{current.realm.realm}}
<b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li data-ng-repeat="realm in current.realms">
<a href="" ng-click="changeRealm(realm.realm)">{{realm.realm}}</a>
</li>
</ul>
</li>
<li class="active pull-right" data-ng-show="auth.loggedIn">
<a class="button primary" href="#/create/realm" data-ng-class="path[0] == 'create' && path[1] == 'realm' && 'active'"
data-ng-show="auth.loggedIn">Add Realm</a>
</li>
</ul>
</div>
</nav>
<!-- TODO remove once this page is properly styled -->
<style type="text/css">
.icon-spinner6 {
cursor: pointer;
}
</style>
@@ -1,104 +0,0 @@
<div class="bs-sidebar col-md-3 clearfix" data-ng-include data-src="'partials/realm-menu.html'"></div>
<div id="content-area" class="col-md-9" role="main">
<ul class="nav nav-tabs nav-tabs-pf" data-ng-show="!create">
<li class="active"><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}">Settings</a></li>
<li><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}/credentials">Credentials</a></li>
<li><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}/scope-mappings">Scope</a></li>
<li><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}/installation">Installation</a></li>
</ul>
<div id="content">
<ol class="breadcrumb" data-ng-show="create">
<li><a href="#/realms/{{realm.realm}}">{{realm.realm}}</a></li>
<li><a href="#/realms/{{realm.realm}}/oauth-clients">OAuth Clients</a></li>
<li class="active">Add OAuth Client</li>
</ol>
<h2 data-ng-show="create"><span>{{realm.realm}}</span> Add OAuth Client</h2>
<p class="subtitle" data-ng-show="create"><span class="required">*</span> Required fields</p>
<ol class="breadcrumb" data-ng-hide="create">
<li><a href="#/realms/{{realm.realm}}">{{realm.realm}}</a></li>
<li><a href="#/realms/{{realm.realm}}/oauth-clients">OAuth Clients</a></li>
<li><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}">{{oauth.name}}</a></li>
<li class="active">Settings</li>
</ol>
<h2 data-ng-hide="create"><span>{{oauth.name}}</span> Settings</h2>
<form class="form-horizontal" name="oauthForm" novalidate>
<fieldset class="border-top">
<div class="form-group">
<label class="col-sm-2 control-label" for="name">Name <span class="required" data-ng-show="create">*</span></label>
<div class="col-sm-4">
<input class="form-control" type="text" id="name" name="name" data-ng-model="oauth.name" autofocus
required>
</div>
</div>
<div class="form-group clearfix block">
<label class="col-sm-2 control-label" for="enabled">Enabled</label>
<div class="col-sm-4">
<input ng-model="oauth.enabled" name="enabled" id="enabled" onoffswitch />
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label" for="newWebOrigin">Web Origin</label>
<div class="col-sm-4">
<div ng-repeat="webOrigin in oauth.webOrigins" class="kc-item-deletable row">
<div class="col-sm-9">
<input class="form-control" type="text" data-ng-class="{'input-below':!$first}"
name="webOrigin" id="webOrigin" data-ng-model="webOrigin" readonly />
</div>
<div class="col-sm-2">
<button class="btn btn-danger" type="button" data-ng-click="deleteWebOrigin($index)">
Delete</button>
</div>
</div>
<div class="row">
<div class="col-sm-9">
<input class="form-control" type="text" name="newWebOrigin" id="newWebOrigin"
placeholder="New Web Origin..." data-ng-model="newWebOrigin"
data-ng-class="{'input-below':oauth.webOrigins.length}" />
</div>
<div class="col-sm-2">
<button class="btn btn-primary" data-ng-click="addWebOrigin()" ng-show="newWebOrigin.length > 0">Add</button>
</div>
</div>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label" for="newRedirectUri">Redirect URI</label>
<div class="col-sm-4">
<div ng-repeat="redirectUri in oauth.redirectUris" class="kc-item-deletable row">
<div class="col-sm-9">
<input class="form-control" type="text" data-ng-class="{'input-below':!$first}"
name="redirectUri" id="redirectUri" data-ng-model="redirectUri" readonly />
</div>
<div class="col-sm-2">
<button class="btn btn-danger" type="button" data-ng-click="deleteRedirectUri($index)">
Delete</button>
</div>
</div>
<div class="row">
<div class="col-sm-9">
<input class="form-control" type="text" name="newRedirectUri" id="newRedirectUri"
placeholder="New Redirect URI..." data-ng-model="newRedirectUri"
data-ng-class="{'input-below':oauth.redirectUris.length}" />
</div>
<div class="col-sm-2">
<button class="btn btn-primary" data-ng-click="addRedirectUri()" ng-show="newRedirectUri.length > 0">Add</button>
</div>
</div>
</div>
</div>
</fieldset>
<div class="pull-right form-actions" data-ng-show="create">
<button kc-cancel data-ng-click="cancel()">Cancel</button>
<button kc-save data-ng-show="changed">Save</button>
</div>
<div class="pull-right form-actions" data-ng-show="!create">
<button kc-reset data-ng-show="changed">Clear changes</button>
<button kc-save data-ng-show="changed">Save</button>
<button kc-delete data-ng-click="remove()" data-ng-hide="changed">Delete</button>
</div>
</form>
</div>
</div>
@@ -1,26 +0,0 @@
<div class="bs-sidebar col-sm-3" data-ng-include data-src="'partials/realm-menu.html'"></div>
<div id="content-area" class="col-md-9" role="main">
<ul class="nav nav-tabs nav-tabs-pf" data-ng-show="!create">
<li><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}">Settings</a></li>
<li><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}/credentials">Credentials</a></li>
<li><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}/scope-mappings">Scope</a></li>
<li class="active"><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}/installation">Installation</a></li>
</ul>
<div id="content">
<h2>OAuth Client Installation</h2>
<form class="form-horizontal" name="realmForm" novalidate>
<fieldset>
<div class="form-group">
<div class="col-sm-12">
<textarea class="form-control" rows="20" kc-select-action="click">{{installation | json}}</textarea>
</div>
</div>
</fieldset>
</form>
<div class="pull-right form-actions">
<a class="btn btn-primary btn-lg" href="{{download}}" download="keycloak.json" type="submit">Download</a>
</div>
</div>
</div>
@@ -1,98 +0,0 @@
<div class="bs-sidebar col-md-3 clearfix" data-ng-include data-src="'partials/realm-menu.html'"></div>
<div id="content-area" class="col-md-9" role="main">
<ul class="nav nav-tabs nav-tabs-pf" data-ng-show="!create">
<li><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}">Settings</a></li>
<li><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}/credentials">Credentials</a></li>
<li class="active"><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}/scope-mappings">Scope</a></li>
<li><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}/installation">Installation</a></li>
</ul>
<div id="content">
<ol class="breadcrumb" data-ng-hide="create">
<li><a href="#/realms/{{realm.realm}}">{{realm.realm}}</a></li>
<li><a href="#/realms/{{realm.realm}}/oauth-clients">OAuth Clients</a></li>
<li><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}">{{oauth.name}}</a></li>
<li class="active">Scope</li>
</ol>
<h2><span>{{oauth.name}}</span> Scope Mappings</h2>
<p class="subtitle"></p>
<form class="form-horizontal" name="realmForm" novalidate>
<fieldset>
<legend><span class="text">Realm Roles</span></legend>
<div class="form-group col-sm-10">
<div class="controls changing-selectors">
<div class="select-title">
<label class="control-label" for="available">Available Roles</label>
<select id="available" class="form-control" multiple size="5"
ng-multiple="true"
ng-model="selectedRealmRoles"
ng-options="r.name for r in realmRoles">
</select>
</div>
<div class="middle-buttons kc-vertical">
<button class="kc-button" type="submit" ng-click="addRealmRole()" tooltip="Move right" tooltip-placement="right">
<span class="kc-icon-arrow-right">Move right</span>
</button>
<button class="kc-button" type="submit" ng-click="deleteRealmRole()" tooltip="Move left" tooltip-placement="right">
<span class="kc-icon-arrow-left">Move left</span>
</button>
</div>
<div class="select-title">
<label class="control-label" for="assigned">Assigned Roles</label>
<select id="assigned" class="form-control" multiple size=5
ng-multiple="true"
ng-model="selectedRealmMappings"
ng-options="r.name for r in realmMappings">
</select>
</div>
</div>
</div>
</fieldset>
<fieldset ng-show="applications.length > 0">
<legend><span class="text">Application Roles</span> </legend>
<div class="form-group input-select">
<label class="col-sm-2 control-label" for="applications">Application</label>
<div class="col-sm-4">
<div class="input-group">
<div class="select-kc">
<select id="applications" name="applications" ng-change="changeApplication()" ng-model="targetApp" ng-options="a.name for a in (applications)">
<option value="" selected> Select an Application </option>
</select>
</div>
</div>
</div>
</div>
<div class="form-group" data-ng-show="targetApp">
<div class="controls changing-selectors col-sm-10">
<div class="select-title">
<label class="control-label" for="app-available">Available Roles</label>
<select id="app-available" class="form-control" multiple size="5"
ng-multiple="true"
ng-model="selectedApplicationRoles"
ng-options="r.name for r in applicationRoles">
</select>
</div>
<div class="middle-buttons kc-vertical">
<button class="kc-button" type="submit" ng-click="addApplicationRole()" tooltip="Move right" tooltip-placement="right">
<span class="kc-icon-arrow-right">Move right</span>
</button>
<button class="kc-button" type="submit" ng-click="deleteApplicationRole()" tooltip="Move left" tooltip-placement="right">
<span class="kc-icon-arrow-left">Move left</span>
</button>
</div>
<div class="select-title">
<label class="control-label" for="app-assigned">Assigned Roles</label>
<select id="app-assigned" class="form-control" multiple size=5
ng-multiple="true"
ng-model="selectedApplicationMappings"
ng-options="r.name for r in applicationMappings">
</select>
</div>
</div>
</div>
</fieldset>
</form>
</div>
</div>
@@ -1,104 +0,0 @@
<div class="bs-sidebar col-sm-3 " data-ng-include data-src="'partials/realm-menu.html'"></div>
<div id="content-area" class="col-sm-9" role="main">
<kc-navigation data-kc-current="general" data-kc-realm="realm.realm" data-kc-social="social"></kc-navigation>
<div id="content">
<ol class="breadcrumb" data-ng-hide="createRealm">
<li><a href="#/realms/{{realm.realm}}">{{realm.realm}}</a></li>
<li><a href="#/realms/{{realm.realm}}">Settings</a></li>
<li class="active">General</li>
</ol>
<h2 class="pull-left" data-ng-show="createRealm">Add Realm</h2>
<h2 data-ng-hide="createRealm"><span>{{realm.realm}}</span> General Settings</h2>
<p class="subtitle" data-ng-show="createRealm"><span class="required">*</span> Required fields</p>
<form class="form-horizontal" name="realmForm" novalidate>
<fieldset>
<legend class="aj-collapse open"><span class="text">Required Settings</span></legend>
<div class="form-group">
<label class="col-sm-2 control-label" for="name">Name <span class="required" data-ng-show="createRealm">*</span></label>
<div class="col-sm-4">
<input class="form-control" type="text" id="name" name="name" data-ng-model="realm.realm" autofocus required>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label" for="enabled">Enabled</label>
<div class="col-sm-4">
<input ng-model="realm.enabled" name="enabled" id="enabled" onoffswitch />
</div>
</div>
</fieldset>
<fieldset>
<legend><span class="text">Login Options</span></legend>
<div class="form-group">
<label class="col-sm-2 control-label" for="social">Social login</label>
<div class="col-sm-4">
<input ng-model="realm.social" name="social" id="social" onoffswitch />
</div>
</div>
<div class="form-group" data-ng-show="realm.social">
<label class="col-sm-2 control-label" for="updateProfileOnInitialSocialLogin">Update profile on first social login</label>
<div class="col-sm-4">
<input ng-model="realm.updateProfileOnInitialSocialLogin" name="updateProfileOnInitialSocialLogin" id="updateProfileOnInitialSocialLogin" onoffswitch />
</div>
</div>
<div class="form-group">
<label for="registrationAllowed" class="col-sm-2 control-label">User registration</label>
<div class="col-sm-4">
<input ng-model="realm.registrationAllowed" name="registrationAllowed" id="registrationAllowed" onoffswitch />
</div>
</div>
<div class="form-group">
<label for="resetPasswordAllowed" class="col-sm-2 control-label">Reset password</label>
<div class="col-sm-4">
<input ng-model="realm.resetPasswordAllowed" name="resetPasswordAllowed" id="resetPasswordAllowed" onoffswitch />
</div>
</div>
<div class="form-group">
<label for="verifyEmail" class="col-sm-2 control-label">Verify email</label>
<div class="col-sm-4">
<input ng-model="realm.verifyEmail" name="verifyEmail" id="verifyEmail" onoffswitch />
</div>
</div>
<div class="form-group">
<label for="requireSsl" class="col-sm-2 control-label">Require SSL</label>
<div class="col-sm-4">
<input ng-model="realm.requireSsl" name="requireSsl" id="requireSsl" onoffswitch />
</div>
</div>
</fieldset>
<fieldset>
<legend><span class="text">Optional Settings</span></legend>
<div class="form-group">
<label class="col-sm-2 control-label" for="loginTheme">Login Theme</label>
<div class="col-sm-4">
<select kc-select id="loginTheme"
data-kc-placeholder="Select one..."
data-kc-model="realm.loginTheme"
data-kc-options="serverInfo.themes.login">
</select>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label" for="accountTheme">Account Theme</label>
<div class="col-sm-4">
<select kc-select id="accountTheme"
data-kc-placeholder="Select one..."
data-kc-model="realm.accountTheme"
data-kc-options="serverInfo.themes.account">
</select>
</div>
</div>
</fieldset>
<div class="pull-right form-actions" data-ng-show="createRealm">
<button kc-cancel data-ng-click="cancel()">Cancel</button>
<button kc-save data-ng-show="changed">Save</button>
</div>
<div class="pull-right form-actions" data-ng-show="!createRealm">
<button kc-reset data-ng-show="changed">Clear changes</button>
<button kc-save data-ng-show="changed">Save</button>
<button kc-delete data-ng-click="remove()" data-ng-hide="changed">Delete</button>
</div>
</form>
</div>
</div>
@@ -1,34 +0,0 @@
<div id="wrapper" class="container">
<div class="row">
<div class="bs-sidebar col-md-3 clearfix">
<ul data-ng-hide="createRealm">
<li class="active"><a href="#/realms">Realms</a></li>
</ul>
</div>
<div id="content-area" class="col-md-9" role="main">
<div class="top-nav" data-ng-hide="createRealm">
<ul class="rcue-tabs">
</ul>
</div>
<div id="content">
<h1>
<span class="gray">Realms</span>
</h1>
<table class="table table-striped table-bordered">
<thead>
<tr>
<th>Realm</th>
</tr>
</thead>
<tr data-ng-repeat="r in realms">
<td><a href="#/realms/{{r.realm}}">{{r.realm}}</a></td>
</tr>
</table>
</div>
</div>
<div id="container-right-bg"></div>
</div>
</div>
@@ -1,10 +0,0 @@
<ul data-ng-hide="createRealm">
<li data-ng-class="((!path[2] || path[1] == 'role' || path[2] == 'roles' || path[2] == 'token-settings' ||
path[2] == 'social-settings' || path[2] == 'required-credentials' || path[2] == 'default-roles' || path[2] == 'registration-settings' ||
path[2] == 'keys-settings' || path[2] == 'smtp-settings') && path[3] != 'applications') && 'active'"><a href="#/realms/{{realm.realm}}">Settings</a></li>
<li data-ng-class="(path[2] == 'users' || path[1] == 'user') && 'active'"><a href="#/realms/{{realm.realm}}/users">Users</a>
</li>
<li data-ng-class="(path[2] == 'applications' || path[1] == 'application' || path[3] == 'applications') && 'active'"><a href="#/realms/{{realm.realm}}/applications">Applications</a></li>
<li data-ng-class="(path[2] == 'oauth-clients' || path[1] == 'oauth-client') && 'active'"><a href="#/realms/{{realm.realm}}/oauth-clients">OAuth Clients</a></li>
</ul>
@@ -1,76 +0,0 @@
<div class="bs-sidebar col-sm-3 " data-ng-include data-src="'partials/realm-menu.html'"></div>
<div id="content-area" class="col-sm-9" role="main">
<data-kc-navigation data-kc-current="token" data-kc-realm="realm.realm" data-kc-social="realm.social"></data-kc-navigation>
<div id="content">
<ol class="breadcrumb">
<li><a href="#/realms/{{realm.realm}}">{{realm.realm}}</a></li>
<li><a href="#/realms/{{realm.realm}}">Settings</a></li>
<li class="active">Token</li>
</ol>
<h2><span>{{realm.realm}}</span> Token Settings</h2>
<form class="form-horizontal" name="realmForm" novalidate>
<fieldset class="border-top">
<div class="form-group input-select">
<label class="col-sm-2 control-label" for="tokenLifespan">Token lifespan</label>
<div class="col-sm-10">
<div class="row">
<div class="col-sm-2">
<input class="form-control" type="number" required min="1"
max="31536000" data-ng-model="realm.tokenLifespan"
id="tokenLifespan" name="tokenLifespan"/>
</div>
<div class="col-sm-2 select-kc">
<select name="tokenLifespanUnit" data-ng-model="realm.tokenLifespanUnit" >
<option data-ng-selected="!realm.tokenLifespanUnit">Seconds</option>
<option>Minutes</option>
<option>Hours</option>
<option>Days</option>
</select>
</div>
</div>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label" for="accessCodeLifespan">Access code lifespan</label>
<div class="col-sm-10">
<div class="row">
<div class="col-sm-2">
<input class="form-control" type="number" required min="1" max="31536000" data-ng-model="realm.accessCodeLifespan" id="accessCodeLifespan" name="accessCodeLifespan">
</div>
<div class="col-sm-2 select-kc">
<select name="accessCodeLifespanUnit" data-ng-model="realm.accessCodeLifespanUnit">
<option data-ng-selected="!realm.accessCodeLifespanUnit">Seconds</option>
<option>Minutes</option>
<option>Hours</option>
<option>Days</option>
</select>
</div>
</div>
</div>
</div>
<div class="form-group input-select">
<label class="col-sm-2 control-label" for="accessCodeLifespanUserAction" class="two-lines">Access code user action lifespan</label>
<div class="col-sm-10">
<div class="row">
<div class="col-sm-2">
<input class="form-control" type="number" required min="1" max="31536000" data-ng-model="realm.accessCodeLifespanUserAction" id="accessCodeLifespanUserAction" name="accessCodeLifespanUserAction">
</div>
<div class="col-sm-2 select-kc">
<select name="accessCodeLifespanUserActionUnit" data-ng-model="realm.accessCodeLifespanUserActionUnit">
<option data-ng-selected="!realm.accessCodeLifespanUserActionUnit">Seconds</option>
<option>Minutes</option>
<option>Hours</option>
<option>Days</option>
</select>
</div>
</div>
</div>
</div>
</fieldset>
<div class="pull-right form-actions">
<button kc-reset data-ng-show="changed">Clear changes</button>
<button kc-save data-ng-show="changed">Save</button>
</div>
</form>
</div>
</div>
@@ -1,46 +0,0 @@
<div class="bs-sidebar col-md-3 clearfix" data-ng-include data-src="'partials/realm-menu.html'"></div>
<div id="content-area" class="col-md-9" role="main">
<ul class="nav nav-tabs nav-tabs-pf" data-ng-show="!create">
<li><a href="#/realms/{{realm.realm}}/users/{{user.username}}">Attributes</a></li>
<li class="active"><a href="#/realms/{{realm.realm}}/users/{{user.username}}/user-credentials">Credentials</a></li>
<li><a href="#/realms/{{realm.realm}}/users/{{user.username}}/role-mappings">Role Mappings</a></li>
</ul>
<div id="content">
<ol class="breadcrumb">
<li><a href="#/realms/{{realm.realm}}">{{realm.realm}}</a></li>
<li class="active">Users</li>
</ol>
<h2><span>{{user.username}}'s</span> Credentials</h2>
<form class="form-horizontal" name="userForm" novalidate>
<fieldset class="border-top">
<legend><span class="text">Credential Management</span></legend>
<div class="form-group">
<label class="col-sm-2 control-label" for="password">Reset password</label>
<div class="col-sm-4 kc-multiline">
<input class="form-control" type="password" id="password" name="password" data-ng-model="password" placeholder="Temporary password" required>
<input class="form-control" type="password" id="confirmPassword" name="confirmPassword" data-ng-model="confirmPassword" placeholder="Password confirmation" required>
<button class="btn btn-danger" type="submit" data-ng-click="resetPassword()" data-ng-show="password">Reset Password</button>
</div>
</div>
<div class="form-group" data-ng-show="user.email">
<label class="col-sm-2 control-label" for="password">Reset password email</label>
<div class="col-sm-4">
<button class="btn btn-danger" type="submit" data-ng-click="resetPasswordEmail()" >Send Email</button>
</div>
</div>
<div class="form-group" data-ng-show="user.totp">
<label class="col-sm-2 control-label" for="password">Remove totp</label>
<div class="col-sm-4" data-ng-show="user.totp">
<button class="btn btn-danger" type="submit" data-ng-click="removeTotp()">Remove TOTP</button>
</div>
</div>
</fieldset>
</form>
</div>
</div>
@@ -1,14 +0,0 @@
<div class="modal-dialog" tabindex="-1" role="dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">
<span class="pficon pficon-close"></span>
</button>
<h4 class="modal-title" id="myModalLabel">{{ title }}</h4>
</div>
<div class="modal-body"><p ng-bind-html-unsafe="message"></p></div>
<div class="modal-footer">
<button ng-repeat="btn in buttons" ng-click="close(btn.result)" class="" ng-class="btn.cssClass">{{ btn.label }}</button>
</div>
</div>
</div>
@@ -1,10 +0,0 @@
<ul class="nav nav-tabs nav-tabs-pf">
<li ng-class="{active: kcCurrent == 'general'}"><a href="#/realms/{{kcRealm}}">General</a></li>
<li ng-class="{active: kcCurrent == 'social'}" data-ng-show="kcSocial"><a href="#/realms/{{kcRealm}}/social-settings">Social</a></li>
<li ng-class="{active: kcCurrent == 'roles'}"><a href="#/realms/{{kcRealm}}/roles">Roles</a></li>
<li ng-class="{active: kcCurrent == 'defRoles'}"><a href="#/realms/{{kcRealm}}/default-roles">Default Roles</a></li>
<li ng-class="{active: kcCurrent == 'credentials'}"><a href="#/realms/{{kcRealm}}/required-credentials">Credentials</a></li>
<li ng-class="{active: kcCurrent == 'token'}"><a href="#/realms/{{kcRealm}}/token-settings">Token</a></li>
<li ng-class="{active: kcCurrent == 'keys'}"><a href="#/realms/{{kcRealm}}/keys-settings">Keys</a></li>
<li ng-class="{active: kcCurrent == 'email'}"><a href="#/realms/{{kcRealm}}/smtp-settings">Email</a></li>
</ul>
@@ -1,5 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<web-fragment version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-fragment_3_0.xsd ">
</web-fragment>
+39
View File
@@ -0,0 +1,39 @@
<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.0-final</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>keycloak-connections-jpa</artifactId>
<name>Keycloak Connections JPA</name>
<description/>
<dependencies>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-model-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.0-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${hibernate.entitymanager.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,26 @@
package org.keycloak.connections.jpa;
import javax.persistence.EntityManager;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class DefaultJpaConnectionProvider implements JpaConnectionProvider {
private final EntityManager em;
public DefaultJpaConnectionProvider(EntityManager em) {
this.em = em;
}
@Override
public EntityManager getEntityManager() {
return em;
}
@Override
public void close() {
em.close();
}
}
@@ -0,0 +1,101 @@
package org.keycloak.connections.jpa;
import org.hibernate.ejb.AvailableSettings;
import org.keycloak.Config;
import org.keycloak.models.KeycloakSession;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import java.util.HashMap;
import java.util.Map;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class DefaultJpaConnectionProviderFactory implements JpaConnectionProviderFactory {
private volatile EntityManagerFactory emf;
private Config.Scope config;
@Override
public JpaConnectionProvider create(KeycloakSession session) {
lazyInit();
EntityManager em = emf.createEntityManager();
em = PersistenceExceptionConverter.create(em);
session.getTransaction().enlist(new JpaKeycloakTransaction(em));
return new DefaultJpaConnectionProvider(em);
}
@Override
public void close() {
if (emf != null) {
emf.close();
}
}
@Override
public String getId() {
return "default";
}
@Override
public void init(Config.Scope config) {
this.config = config;
}
private void lazyInit() {
if (emf == null) {
synchronized (this) {
if (emf == null) {
String unitName = config.get("unitName");
Map<String, Object> properties = new HashMap<String, Object>();
// Only load config from keycloak-server.json if unitName is not specified
if (unitName == null) {
unitName = "keycloak-default";
String dataSource = config.get("dataSource");
if (dataSource != null) {
if (config.getBoolean("jta", false)) {
properties.put(AvailableSettings.JTA_DATASOURCE, dataSource);
} else {
properties.put(AvailableSettings.NON_JTA_DATASOURCE, dataSource);
}
} else {
properties.put(AvailableSettings.JDBC_URL, config.get("url"));
properties.put(AvailableSettings.JDBC_DRIVER, config.get("driver"));
String user = config.get("user");
if (user != null) {
properties.put(AvailableSettings.JDBC_USER, user);
}
String password = config.get("password");
if (password != null) {
properties.put(AvailableSettings.JDBC_PASSWORD, password);
}
}
String driverDialect = config.get("driverDialect");
if (driverDialect != null && driverDialect.length() > 0) {
properties.put("hibernate.dialect", driverDialect);
}
String databaseSchema = config.get("databaseSchema", "validate");
if (databaseSchema != null) {
properties.put("hibernate.hbm2ddl.auto", databaseSchema);
}
properties.put("hibernate.show_sql", config.getBoolean("showSql", false));
properties.put("hibernate.format_sql", config.getBoolean("formatSql", true));
}
emf = Persistence.createEntityManagerFactory(unitName, properties);
}
}
}
}
}
@@ -0,0 +1,14 @@
package org.keycloak.connections.jpa;
import org.keycloak.provider.Provider;
import javax.persistence.EntityManager;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public interface JpaConnectionProvider extends Provider {
EntityManager getEntityManager();
}
@@ -0,0 +1,9 @@
package org.keycloak.connections.jpa;
import org.keycloak.provider.ProviderFactory;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public interface JpaConnectionProviderFactory extends ProviderFactory<JpaConnectionProvider> {
}
@@ -0,0 +1,27 @@
package org.keycloak.connections.jpa;
import org.keycloak.provider.Provider;
import org.keycloak.provider.ProviderFactory;
import org.keycloak.provider.Spi;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class JpaConnectionSpi implements Spi {
@Override
public String getName() {
return "connectionsJpa";
}
@Override
public Class<? extends Provider> getProviderClass() {
return JpaConnectionProvider.class;
}
@Override
public Class<? extends ProviderFactory> getProviderFactoryClass() {
return JpaConnectionProviderFactory.class;
}
}
@@ -0,0 +1,53 @@
package org.keycloak.connections.jpa;
import org.keycloak.models.KeycloakTransaction;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceException;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class JpaKeycloakTransaction implements KeycloakTransaction {
protected EntityManager em;
public JpaKeycloakTransaction(EntityManager em) {
this.em = em;
}
@Override
public void begin() {
em.getTransaction().begin();
}
@Override
public void commit() {
try {
em.getTransaction().commit();
} catch (PersistenceException e) {
throw PersistenceExceptionConverter.convert(e.getCause() != null ? e.getCause() : e);
}
}
@Override
public void rollback() {
em.getTransaction().rollback();
}
@Override
public void setRollbackOnly() {
em.getTransaction().setRollbackOnly();
}
@Override
public boolean getRollbackOnly() {
return em.getTransaction().getRollbackOnly();
}
@Override
public boolean isActive() {
return em.getTransaction().isActive();
}
}
@@ -0,0 +1,48 @@
package org.keycloak.connections.jpa;
import org.hibernate.exception.ConstraintViolationException;
import org.keycloak.models.ModelDuplicateException;
import org.keycloak.models.ModelException;
import javax.persistence.EntityExistsException;
import javax.persistence.EntityManager;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class PersistenceExceptionConverter implements InvocationHandler {
private EntityManager em;
public static EntityManager create(EntityManager em) {
return (EntityManager) Proxy.newProxyInstance(EntityManager.class.getClassLoader(), new Class[]{EntityManager.class}, new PersistenceExceptionConverter(em));
}
private PersistenceExceptionConverter(EntityManager em) {
this.em = em;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
return method.invoke(em, args);
} catch (InvocationTargetException e) {
throw convert(e.getCause());
}
}
public static ModelException convert(Throwable t) {
if (t.getCause() != null && t.getCause() instanceof ConstraintViolationException) {
throw new ModelDuplicateException(t);
} if (t instanceof EntityExistsException) {
throw new ModelDuplicateException(t);
} else {
throw new ModelException(t);
}
}
}
@@ -0,0 +1,36 @@
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
version="1.0">
<persistence-unit name="keycloak-default" transaction-type="RESOURCE_LOCAL">
<class>org.keycloak.models.jpa.entities.ApplicationEntity</class>
<class>org.keycloak.models.jpa.entities.CredentialEntity</class>
<class>org.keycloak.models.jpa.entities.OAuthClientEntity</class>
<class>org.keycloak.models.jpa.entities.RealmEntity</class>
<class>org.keycloak.models.jpa.entities.RealmAttributeEntity</class>
<class>org.keycloak.models.jpa.entities.RequiredCredentialEntity</class>
<class>org.keycloak.models.jpa.entities.UserFederationProviderEntity</class>
<class>org.keycloak.models.jpa.entities.RoleEntity</class>
<class>org.keycloak.models.jpa.entities.SocialLinkEntity</class>
<class>org.keycloak.models.jpa.entities.UserEntity</class>
<class>org.keycloak.models.jpa.entities.UserRequiredActionEntity</class>
<class>org.keycloak.models.jpa.entities.UserAttributeEntity</class>
<class>org.keycloak.models.jpa.entities.UserRoleMappingEntity</class>
<class>org.keycloak.models.jpa.entities.ScopeMappingEntity</class>
<!-- JpaUserSessionProvider -->
<class>org.keycloak.models.sessions.jpa.entities.ClientSessionEntity</class>
<class>org.keycloak.models.sessions.jpa.entities.ClientSessionRoleEntity</class>
<class>org.keycloak.models.sessions.jpa.entities.UserSessionEntity</class>
<class>org.keycloak.models.sessions.jpa.entities.UsernameLoginFailureEntity</class>
<!-- JpaAuditProvider -->
<class>org.keycloak.events.jpa.EventEntity</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="jboss.as.jpa.managed" value="false"/>
</properties>
</persistence-unit>
</persistence>
@@ -0,0 +1 @@
org.keycloak.connections.jpa.DefaultJpaConnectionProviderFactory
@@ -0,0 +1 @@
org.keycloak.connections.jpa.JpaConnectionSpi
+37
View File
@@ -0,0 +1,37 @@
<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.0-final</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>keycloak-connections-mongo</artifactId>
<name>Keycloak Connections Mongo</name>
<description/>
<dependencies>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-model-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,111 @@
package org.keycloak.connections.mongo;
import com.mongodb.DB;
import com.mongodb.MongoClient;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;
import org.jboss.logging.Logger;
import org.keycloak.Config;
import org.keycloak.connections.mongo.api.MongoStore;
import org.keycloak.connections.mongo.impl.MongoStoreImpl;
import org.keycloak.connections.mongo.impl.context.TransactionMongoStoreInvocationContext;
import org.keycloak.models.KeycloakSession;
import java.util.Collections;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class DefaultMongoConnectionFactoryProvider implements MongoConnectionProviderFactory {
// TODO Make configurable
private String[] entities = new String[]{
"org.keycloak.models.mongo.keycloak.entities.MongoRealmEntity",
"org.keycloak.models.mongo.keycloak.entities.MongoUserEntity",
"org.keycloak.models.mongo.keycloak.entities.MongoRoleEntity",
"org.keycloak.models.entities.RequiredCredentialEntity",
"org.keycloak.models.entities.CredentialEntity",
"org.keycloak.models.entities.SocialLinkEntity",
"org.keycloak.models.mongo.keycloak.entities.MongoApplicationEntity",
"org.keycloak.models.mongo.keycloak.entities.MongoOAuthClientEntity",
"org.keycloak.models.sessions.mongo.entities.MongoUsernameLoginFailureEntity",
"org.keycloak.models.sessions.mongo.entities.MongoUserSessionEntity",
"org.keycloak.models.sessions.mongo.entities.MongoClientSessionEntity",
"org.keycloak.models.entities.UserFederationProviderEntity"
};
private static final Logger logger = Logger.getLogger(DefaultMongoConnectionFactoryProvider.class);
private volatile MongoClient client;
private MongoStore mongoStore;
private DB db;
private Config.Scope config;
@Override
public MongoConnectionProvider create(KeycloakSession session) {
lazyInit();
TransactionMongoStoreInvocationContext invocationContext = new TransactionMongoStoreInvocationContext(mongoStore);
session.getTransaction().enlist(new MongoKeycloakTransaction(invocationContext));
return new DefaultMongoConnectionProvider(db, mongoStore, invocationContext);
}
@Override
public void init(Config.Scope config) {
this.config = config;
}
private void lazyInit() {
if (client == null) {
synchronized (this) {
if (client == null) {
try {
String host = config.get("host", ServerAddress.defaultHost());
int port = config.getInt("port", ServerAddress.defaultPort());
String dbName = config.get("db", "keycloak");
boolean clearOnStartup = config.getBoolean("clearOnStartup", false);
String user = config.get("user");
String password = config.get("password");
if (user != null && password != null) {
MongoCredential credential = MongoCredential.createMongoCRCredential(user, dbName, password.toCharArray());
client = new MongoClient(new ServerAddress(host, port), Collections.singletonList(credential));
} else {
client = new MongoClient(host, port);
}
this.db = client.getDB(dbName);
this.mongoStore = new MongoStoreImpl(db, clearOnStartup, getManagedEntities());
logger.infof("Initialized mongo model. host: %s, port: %d, db: %s, clearOnStartup: %b", host, port, dbName, clearOnStartup);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
}
}
private Class[] getManagedEntities() throws ClassNotFoundException {
Class[] entityClasses = new Class[entities.length];
for (int i = 0; i < entities.length; i++) {
entityClasses[i] = Thread.currentThread().getContextClassLoader().loadClass(entities[i]);
}
return entityClasses;
}
@Override
public void close() {
if (client != null) {
client.close();
}
}
@Override
public String getId() {
return "default";
}
}
@@ -0,0 +1,41 @@
package org.keycloak.connections.mongo;
import com.mongodb.DB;
import org.keycloak.connections.mongo.api.MongoStore;
import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class DefaultMongoConnectionProvider implements MongoConnectionProvider {
private DB db;
private MongoStore mongoStore;
private MongoStoreInvocationContext invocationContext;
public DefaultMongoConnectionProvider(DB db, MongoStore mongoStore, MongoStoreInvocationContext invocationContext) {
this.db = db;
this.mongoStore = mongoStore;
this.invocationContext = invocationContext;
}
@Override
public DB getDB() {
return db;
}
@Override
public MongoStore getMongoStore() {
return mongoStore;
}
@Override
public MongoStoreInvocationContext getInvocationContext() {
return invocationContext;
}
@Override
public void close() {
}
}
@@ -0,0 +1,19 @@
package org.keycloak.connections.mongo;
import com.mongodb.DB;
import org.keycloak.connections.mongo.api.MongoStore;
import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
import org.keycloak.provider.Provider;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public interface MongoConnectionProvider extends Provider {
DB getDB();
MongoStore getMongoStore();
MongoStoreInvocationContext getInvocationContext();
}
@@ -0,0 +1,9 @@
package org.keycloak.connections.mongo;
import org.keycloak.provider.ProviderFactory;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public interface MongoConnectionProviderFactory extends ProviderFactory<MongoConnectionProvider> {
}
@@ -0,0 +1,27 @@
package org.keycloak.connections.mongo;
import org.keycloak.provider.Provider;
import org.keycloak.provider.ProviderFactory;
import org.keycloak.provider.Spi;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class MongoConnectionSpi implements Spi {
@Override
public String getName() {
return "connectionsMongo";
}
@Override
public Class<? extends Provider> getProviderClass() {
return MongoConnectionProvider.class;
}
@Override
public Class<? extends ProviderFactory> getProviderFactoryClass() {
return MongoConnectionProviderFactory.class;
}
}
@@ -1,7 +1,9 @@
package org.keycloak.models.mongo.keycloak.adapters;
package org.keycloak.connections.mongo;
import com.mongodb.MongoException;
import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
import org.keycloak.connections.mongo.impl.MongoStoreImpl;
import org.keycloak.models.KeycloakTransaction;
import org.keycloak.models.mongo.api.context.MongoStoreInvocationContext;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
@@ -35,12 +37,18 @@ public class MongoKeycloakTransaction implements KeycloakTransaction {
throw new IllegalStateException("Can't commit as transaction marked for rollback");
}
invocationContext.commit();
try {
invocationContext.commit();
} catch (MongoException e) {
throw MongoStoreImpl.convertException(e);
}
started = false;
}
@Override
public void rollback() {
invocationContext.rollback();
started = false;
}
@Override
@@ -1,4 +1,4 @@
package org.keycloak.models.mongo.api;
package org.keycloak.connections.mongo.api;
import java.lang.annotation.Documented;
import java.lang.annotation.Inherited;
@@ -1,6 +1,4 @@
package org.keycloak.models.mongo.api;
import org.keycloak.models.mongo.api.context.MongoStoreInvocationContext;
package org.keycloak.connections.mongo.api;
/**
* Base interface for object, which is persisted in Mongo
@@ -1,4 +1,4 @@
package org.keycloak.models.mongo.api;
package org.keycloak.connections.mongo.api;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
@@ -1,6 +1,6 @@
package org.keycloak.models.mongo.api;
package org.keycloak.connections.mongo.api;
import org.keycloak.models.mongo.api.context.MongoStoreInvocationContext;
import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
/**
* Entity with Id
@@ -0,0 +1,26 @@
package org.keycloak.connections.mongo.api;
import java.lang.annotation.Documented;
import java.lang.annotation.Inherited;
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 <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
@Target({TYPE})
@Documented
@Retention(RUNTIME)
@Inherited
public @interface MongoIndex {
String[] fields();
boolean unique() default false;
boolean sparse() default false;
}
@@ -0,0 +1,22 @@
package org.keycloak.connections.mongo.api;
import java.lang.annotation.Documented;
import java.lang.annotation.Inherited;
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 <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
@Target({TYPE})
@Documented
@Retention(RUNTIME)
@Inherited
public @interface MongoIndexes {
MongoIndex[] value();
}
@@ -1,43 +1,48 @@
package org.keycloak.models.mongo.api;
import com.mongodb.DBObject;
import org.keycloak.models.mongo.api.context.MongoStoreInvocationContext;
import java.util.List;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public interface MongoStore {
/**
* Insert new entity
*
* @param entity to insert
*/
void insertEntity(MongoIdentifiableEntity entity, MongoStoreInvocationContext context);
/**
* Update existing entity
*
* @param entity to update
*/
void updateEntity(MongoIdentifiableEntity entity, MongoStoreInvocationContext context);
<T extends MongoIdentifiableEntity> T loadEntity(Class<T> type, String id, MongoStoreInvocationContext context);
<T extends MongoIdentifiableEntity> T loadSingleEntity(Class<T> type, DBObject query, MongoStoreInvocationContext context);
<T extends MongoIdentifiableEntity> List<T> loadEntities(Class<T> type, DBObject query, MongoStoreInvocationContext context);
boolean removeEntity(MongoIdentifiableEntity entity, MongoStoreInvocationContext context);
boolean removeEntity(Class<? extends MongoIdentifiableEntity> type, String id, MongoStoreInvocationContext context);
boolean removeEntities(Class<? extends MongoIdentifiableEntity> type, DBObject query, MongoStoreInvocationContext context);
<S> boolean pushItemToList(MongoIdentifiableEntity entity, String listPropertyName, S itemToPush, boolean skipIfAlreadyPresent, MongoStoreInvocationContext context);
<S> boolean pullItemFromList(MongoIdentifiableEntity entity, String listPropertyName, S itemToPull, MongoStoreInvocationContext context);
}
package org.keycloak.connections.mongo.api;
import com.mongodb.DBObject;
import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
import java.util.List;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public interface MongoStore {
/**
* Insert new entity
*
* @param entity to insert
*/
void insertEntity(MongoIdentifiableEntity entity, MongoStoreInvocationContext context);
/**
* Update existing entity
*
* @param entity to update
*/
void updateEntity(MongoIdentifiableEntity entity, MongoStoreInvocationContext context);
<T extends MongoIdentifiableEntity> T loadEntity(Class<T> type, String id, MongoStoreInvocationContext context);
<T extends MongoIdentifiableEntity> T loadSingleEntity(Class<T> type, DBObject query, MongoStoreInvocationContext context);
<T extends MongoIdentifiableEntity> List<T> loadEntities(Class<T> type, DBObject query, MongoStoreInvocationContext context);
<T extends MongoIdentifiableEntity> List<T> loadEntities(Class<T> type, DBObject query, DBObject sort, int firstResult, int maxResults, MongoStoreInvocationContext context);
<T extends MongoIdentifiableEntity> int countEntities(Class<T> type, DBObject query, MongoStoreInvocationContext context);
boolean removeEntity(MongoIdentifiableEntity entity, MongoStoreInvocationContext context);
boolean removeEntity(Class<? extends MongoIdentifiableEntity> type, String id, MongoStoreInvocationContext context);
boolean removeEntities(Class<? extends MongoIdentifiableEntity> type, DBObject query, MongoStoreInvocationContext context);
<S> boolean pushItemToList(MongoIdentifiableEntity entity, String listPropertyName, S itemToPush, boolean skipIfAlreadyPresent, MongoStoreInvocationContext context);
<S> boolean pullItemFromList(MongoIdentifiableEntity entity, String listPropertyName, S itemToPull, MongoStoreInvocationContext context);
}
@@ -1,7 +1,7 @@
package org.keycloak.models.mongo.api.context;
package org.keycloak.connections.mongo.api.context;
import org.keycloak.models.mongo.api.MongoIdentifiableEntity;
import org.keycloak.models.mongo.api.MongoStore;
import org.keycloak.connections.mongo.api.MongoIdentifiableEntity;
import org.keycloak.connections.mongo.api.MongoStore;
/**
* Context, which provides callback methods to be invoked by MongoStore
@@ -1,4 +1,4 @@
package org.keycloak.models.mongo.api.context;
package org.keycloak.connections.mongo.api.context;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
@@ -1,4 +1,4 @@
package org.keycloak.models.mongo.api.types;
package org.keycloak.connections.mongo.api.types;
/**
* SPI object to convert object from application type to database type and vice versa. Shouldn't be directly used by application.
@@ -1,4 +1,4 @@
package org.keycloak.models.mongo.api.types;
package org.keycloak.connections.mongo.api.types;
import java.util.List;
@@ -1,111 +1,111 @@
package org.keycloak.models.mongo.api.types;
import java.util.HashMap;
import java.util.Map;
/**
* Registry of mappers, which allow to convert application object to database objects. MapperRegistry is main entry point to be used by application.
* Application can create instance of MapperRegistry and then register required Mapper objects.
*
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class MapperRegistry {
// TODO: Thread-safety support (maybe...)
// Mappers of Application objects to DB objects
private Map<Class<?>, Mapper<?, ?>> appObjectMappers = new HashMap<Class<?>, Mapper<?, ?>>();
// Mappers of DB objects to Application objects
private Map<Class<?>, Map<Class<?>, Mapper<?, ?>>> dbObjectMappers = new HashMap<Class<?>, Map<Class<?>, Mapper<?,?>>>();
/**
* Add mapper for converting application objects to DB objects
*
* @param mapper
*/
public void addAppObjectMapper(Mapper<?, ?> mapper) {
appObjectMappers.put(mapper.getTypeOfObjectToConvert(), mapper);
}
/**
* Add mapper for converting DB objects to application objects
*
* @param mapper
*/
public void addDBObjectMapper(Mapper<?, ?> mapper) {
Class<?> dbObjectType = mapper.getTypeOfObjectToConvert();
Class<?> appObjectType = mapper.getExpectedReturnType();
Map<Class<?>, Mapper<?, ?>> appObjects = dbObjectMappers.get(dbObjectType);
if (appObjects == null) {
appObjects = new HashMap<Class<?>, Mapper<?, ?>>();
dbObjectMappers.put(dbObjectType, appObjects);
}
appObjects.put(appObjectType, mapper);
}
public <S> S convertDBObjectToApplicationObject(MapperContext<Object, S> context) {
Object dbObject = context.getObjectToConvert();
Class<?> expectedApplicationObjectType = context.getExpectedReturnType();
Class<?> dbObjectType = dbObject.getClass();
Mapper<Object, S> mapper;
Map<Class<?>, Mapper<?, ?>> appObjects = dbObjectMappers.get(dbObjectType);
if (appObjects == null) {
throw new IllegalArgumentException("Not found any mappers for type " + dbObjectType);
} else {
if (appObjects.size() == 1) {
mapper = (Mapper<Object, S>)appObjects.values().iterator().next();
} else {
// Try to find converter for requested application type
mapper = (Mapper<Object, S>)getAppConverterForType(context.getExpectedReturnType(), appObjects);
}
}
if (mapper == null) {
throw new IllegalArgumentException("Can't found mapper for type " + dbObjectType + " and expectedApplicationType " + expectedApplicationObjectType);
}
return mapper.convertObject(context);
}
public <S> S convertApplicationObjectToDBObject(Object applicationObject, Class<S> expectedDBObjectType) {
Class<?> appObjectType = applicationObject.getClass();
Mapper<Object, S> mapper = (Mapper<Object, S>)getAppConverterForType(appObjectType, appObjectMappers);
if (mapper == null) {
throw new IllegalArgumentException("Can't found converter for type " + appObjectType + " in registered appObjectMappers");
}
if (!expectedDBObjectType.isAssignableFrom(mapper.getExpectedReturnType())) {
throw new IllegalArgumentException("Converter " + mapper + " has return type " + mapper.getExpectedReturnType() +
" but we need type " + expectedDBObjectType);
}
return mapper.convertObject(new MapperContext<Object, S>(applicationObject, expectedDBObjectType, null));
}
// Try to find converter for given type or all it's supertypes
private static Mapper<Object, ?> getAppConverterForType(Class<?> appObjectType, Map<Class<?>, Mapper<?, ?>> appObjectConverters) {
Mapper<Object, ?> mapper = (Mapper<Object, ?>)appObjectConverters.get(appObjectType);
if (mapper != null) {
return mapper;
} else {
Class<?>[] interfaces = appObjectType.getInterfaces();
for (Class<?> interface1 : interfaces) {
mapper = getAppConverterForType(interface1, appObjectConverters);
if (mapper != null) {
return mapper;
}
}
Class<?> superType = appObjectType.getSuperclass();
if (superType != null) {
return getAppConverterForType(superType, appObjectConverters);
} else {
return null;
}
}
}
}
package org.keycloak.connections.mongo.api.types;
import java.util.HashMap;
import java.util.Map;
/**
* Registry of mappers, which allow to convert application object to database objects. MapperRegistry is main entry point to be used by application.
* Application can create instance of MapperRegistry and then register required Mapper objects.
*
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class MapperRegistry {
// TODO: Thread-safety support (maybe...)
// Mappers of Application objects to DB objects
private Map<Class<?>, Mapper<?, ?>> appObjectMappers = new HashMap<Class<?>, Mapper<?, ?>>();
// Mappers of DB objects to Application objects
private Map<Class<?>, Map<Class<?>, Mapper<?, ?>>> dbObjectMappers = new HashMap<Class<?>, Map<Class<?>, Mapper<?,?>>>();
/**
* Add mapper for converting application objects to DB objects
*
* @param mapper
*/
public void addAppObjectMapper(Mapper<?, ?> mapper) {
appObjectMappers.put(mapper.getTypeOfObjectToConvert(), mapper);
}
/**
* Add mapper for converting DB objects to application objects
*
* @param mapper
*/
public void addDBObjectMapper(Mapper<?, ?> mapper) {
Class<?> dbObjectType = mapper.getTypeOfObjectToConvert();
Class<?> appObjectType = mapper.getExpectedReturnType();
Map<Class<?>, Mapper<?, ?>> appObjects = dbObjectMappers.get(dbObjectType);
if (appObjects == null) {
appObjects = new HashMap<Class<?>, Mapper<?, ?>>();
dbObjectMappers.put(dbObjectType, appObjects);
}
appObjects.put(appObjectType, mapper);
}
public <S> S convertDBObjectToApplicationObject(MapperContext<Object, S> context) {
Object dbObject = context.getObjectToConvert();
Class<?> expectedApplicationObjectType = context.getExpectedReturnType();
Class<?> dbObjectType = dbObject.getClass();
Mapper<Object, S> mapper;
Map<Class<?>, Mapper<?, ?>> appObjects = dbObjectMappers.get(dbObjectType);
if (appObjects == null) {
throw new IllegalArgumentException("Not found any mappers for type " + dbObjectType);
} else {
if (appObjects.size() == 1) {
mapper = (Mapper<Object, S>)appObjects.values().iterator().next();
} else {
// Try to find converter for requested application type
mapper = (Mapper<Object, S>)getAppConverterForType(context.getExpectedReturnType(), appObjects);
}
}
if (mapper == null) {
throw new IllegalArgumentException("Can't found mapper for type " + dbObjectType + " and expectedApplicationType " + expectedApplicationObjectType);
}
return mapper.convertObject(context);
}
public <S> S convertApplicationObjectToDBObject(Object applicationObject, Class<S> expectedDBObjectType) {
Class<?> appObjectType = applicationObject.getClass();
Mapper<Object, S> mapper = (Mapper<Object, S>)getAppConverterForType(appObjectType, appObjectMappers);
if (mapper == null) {
throw new IllegalArgumentException("Can't found converter for type " + appObjectType + " in registered appObjectMappers");
}
if (!expectedDBObjectType.isAssignableFrom(mapper.getExpectedReturnType())) {
throw new IllegalArgumentException("Converter " + mapper + " has return type " + mapper.getExpectedReturnType() +
" but we need type " + expectedDBObjectType);
}
return mapper.convertObject(new MapperContext<Object, S>(applicationObject, expectedDBObjectType, null));
}
// Try to find converter for given type or all it's supertypes
private static Mapper<Object, ?> getAppConverterForType(Class<?> appObjectType, Map<Class<?>, Mapper<?, ?>> appObjectConverters) {
Mapper<Object, ?> mapper = (Mapper<Object, ?>)appObjectConverters.get(appObjectType);
if (mapper != null) {
return mapper;
} else {
Class<?>[] interfaces = appObjectType.getInterfaces();
for (Class<?> interface1 : interfaces) {
mapper = getAppConverterForType(interface1, appObjectConverters);
if (mapper != null) {
return mapper;
}
}
Class<?> superType = appObjectType.getSuperclass();
if (superType != null) {
return getAppConverterForType(superType, appObjectConverters);
} else {
return null;
}
}
}
}
@@ -0,0 +1,40 @@
package org.keycloak.connections.mongo.impl;
import org.keycloak.models.utils.reflection.Property;
import java.util.Collection;
import java.util.Map;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class EntityInfo {
private final Class<?> entityClass;
private final String dbCollectionName;
private final Map<String, Property<Object>> properties;
public EntityInfo(Class<?> entityClass, String dbCollectionName, Map<String, Property<Object>> properties) {
this.entityClass = entityClass;
this.dbCollectionName = dbCollectionName;
this.properties = properties;
}
public Class<?> getEntityClass() {
return entityClass;
}
public String getDbCollectionName() {
return dbCollectionName;
}
public Collection<Property<Object>> getProperties() {
return properties.values();
}
public Property<Object> getPropertyByName(String propertyName) {
return properties.get(propertyName);
}
}
@@ -1,416 +1,508 @@
package org.keycloak.models.mongo.impl;
import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
import org.jboss.logging.Logger;
import org.keycloak.models.mongo.api.MongoCollection;
import org.keycloak.models.mongo.api.MongoEntity;
import org.keycloak.models.mongo.api.MongoField;
import org.keycloak.models.mongo.api.MongoIdentifiableEntity;
import org.keycloak.models.mongo.api.MongoStore;
import org.keycloak.models.mongo.api.context.MongoStoreInvocationContext;
import org.keycloak.models.mongo.api.context.MongoTask;
import org.keycloak.models.mongo.api.types.Mapper;
import org.keycloak.models.mongo.api.types.MapperContext;
import org.keycloak.models.mongo.api.types.MapperRegistry;
import org.keycloak.models.mongo.impl.types.BasicDBListMapper;
import org.keycloak.models.mongo.impl.types.BasicDBObjectMapper;
import org.keycloak.models.mongo.impl.types.BasicDBObjectToMapMapper;
import org.keycloak.models.mongo.impl.types.EnumToStringMapper;
import org.keycloak.models.mongo.impl.types.ListMapper;
import org.keycloak.models.mongo.impl.types.MapMapper;
import org.keycloak.models.mongo.impl.types.MongoEntityMapper;
import org.keycloak.models.mongo.impl.types.SimpleMapper;
import org.keycloak.models.mongo.impl.types.StringToEnumMapper;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.picketlink.common.properties.Property;
import org.picketlink.common.properties.query.AnnotatedPropertyCriteria;
import org.picketlink.common.properties.query.PropertyQueries;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class MongoStoreImpl implements MongoStore {
private static final Class<?>[] SIMPLE_TYPES = { String.class, Integer.class, Boolean.class, Long.class, Double.class, Character.class, Date.class, byte[].class };
private final DB database;
private static final Logger logger = Logger.getLogger(MongoStoreImpl.class);
private final MapperRegistry mapperRegistry;
private ConcurrentMap<Class<? extends MongoEntity>, EntityInfo> entityInfoCache =
new ConcurrentHashMap<Class<? extends MongoEntity>, EntityInfo>();
public MongoStoreImpl(DB database, boolean clearCollectionsOnStartup, Class<? extends MongoEntity>[] managedEntityTypes) {
this.database = database;
mapperRegistry = new MapperRegistry();
for (Class<?> simpleConverterClass : SIMPLE_TYPES) {
SimpleMapper converter = new SimpleMapper(simpleConverterClass);
mapperRegistry.addAppObjectMapper(converter);
mapperRegistry.addDBObjectMapper(converter);
}
// Specific converter for ArrayList is added just for performance purposes to avoid recursive converter lookup (most of list impl will be ArrayList)
mapperRegistry.addAppObjectMapper(new ListMapper(mapperRegistry, ArrayList.class));
mapperRegistry.addAppObjectMapper(new ListMapper(mapperRegistry, List.class));
mapperRegistry.addDBObjectMapper(new BasicDBListMapper(mapperRegistry));
mapperRegistry.addAppObjectMapper(new MapMapper(HashMap.class));
mapperRegistry.addAppObjectMapper(new MapMapper(Map.class));
mapperRegistry.addDBObjectMapper(new BasicDBObjectToMapMapper());
// Enum converters
mapperRegistry.addAppObjectMapper(new EnumToStringMapper());
mapperRegistry.addDBObjectMapper(new StringToEnumMapper());
for (Class<? extends MongoEntity> type : managedEntityTypes) {
getEntityInfo(type);
mapperRegistry.addAppObjectMapper(new MongoEntityMapper(this, mapperRegistry, type));
mapperRegistry.addDBObjectMapper(new BasicDBObjectMapper(this, mapperRegistry, type));
}
if (clearCollectionsOnStartup) {
// dropDatabase();
clearManagedCollections(managedEntityTypes);
}
}
protected void dropDatabase() {
this.database.dropDatabase();
logger.info("Database " + this.database.getName() + " dropped in MongoDB");
}
// Don't drop database, but just clear all data in managed collections (useful for development)
protected void clearManagedCollections(Class<? extends MongoEntity>[] managedEntityTypes) {
for (Class<? extends MongoEntity> clazz : managedEntityTypes) {
DBCollection dbCollection = getDBCollectionForType(clazz);
if (dbCollection != null) {
dbCollection.remove(new BasicDBObject());
logger.debug("Collection " + dbCollection.getName() + " cleared from " + this.database.getName());
}
}
}
@Override
public void insertEntity(MongoIdentifiableEntity entity, MongoStoreInvocationContext context) {
Class<? extends MongoEntity> clazz = entity.getClass();
// Find annotations for ID, for all the properties and for the name of the collection.
EntityInfo entityInfo = getEntityInfo(clazz);
// Create instance of BasicDBObject and add all declared properties to it (properties with null value probably should be skipped)
BasicDBObject dbObject = mapperRegistry.convertApplicationObjectToDBObject(entity, BasicDBObject.class);
DBCollection dbCollection = database.getCollection(entityInfo.getDbCollectionName());
String currentId = entity.getId();
// Generate random ID if not set already
if (currentId == null) {
currentId = KeycloakModelUtils.generateId();
entity.setId(currentId);
}
// Adding "_id"
dbObject.put("_id", currentId);
dbCollection.insert(dbObject);
// Treat object as created in this transaction (It is already submited to transaction)
context.addCreatedEntity(entity);
}
@Override
public void updateEntity(final MongoIdentifiableEntity entity, MongoStoreInvocationContext context) {
MongoTask fullUpdateTask = new MongoTask() {
@Override
public void execute() {
Class<? extends MongoEntity> clazz = entity.getClass();
EntityInfo entityInfo = getEntityInfo(clazz);
BasicDBObject dbObject = mapperRegistry.convertApplicationObjectToDBObject(entity, BasicDBObject.class);
DBCollection dbCollection = database.getCollection(entityInfo.getDbCollectionName());
String currentId = entity.getId();
if (currentId == null) {
throw new IllegalStateException("Can't update entity without id: " + entity);
} else {
BasicDBObject query = new BasicDBObject("_id", currentId);
dbCollection.update(query, dbObject);
}
}
@Override
public boolean isFullUpdate() {
return true;
}
};
// update is just added to context and postponed
context.addUpdateTask(entity, fullUpdateTask);
}
@Override
public <T extends MongoIdentifiableEntity> T loadEntity(Class<T> type, String id, MongoStoreInvocationContext context) {
// First look if we already read the object with this oid and type during this transaction. If yes, use it instead of DB lookup
T cached = context.getLoadedEntity(type, id);
if (cached != null) return cached;
DBCollection dbCollection = getDBCollectionForType(type);
BasicDBObject idQuery = new BasicDBObject("_id", id);
DBObject dbObject = dbCollection.findOne(idQuery);
if (dbObject == null) return null;
MapperContext<Object, T> mapperContext = new MapperContext<Object, T>(dbObject, type, null);
T converted = mapperRegistry.convertDBObjectToApplicationObject(mapperContext);
// Now add it to loaded objects
context.addLoadedEntity(converted);
return converted;
}
@Override
public <T extends MongoIdentifiableEntity> T loadSingleEntity(Class<T> type, DBObject query, MongoStoreInvocationContext context) {
// First we should execute all pending tasks before searching DB
context.beforeDBSearch(type);
DBCollection dbCollection = getDBCollectionForType(type);
DBObject dbObject = dbCollection.findOne(query);
if (dbObject == null) {
return null;
} else {
return convertDBObjectToEntity(type, dbObject, context);
}
}
@Override
public <T extends MongoIdentifiableEntity> List<T> loadEntities(Class<T> type, DBObject query, MongoStoreInvocationContext context) {
// First we should execute all pending tasks before searching DB
context.beforeDBSearch(type);
DBCollection dbCollection = getDBCollectionForType(type);
DBCursor cursor = dbCollection.find(query);
return convertCursor(type, cursor, context);
}
@Override
public boolean removeEntity(MongoIdentifiableEntity entity, MongoStoreInvocationContext context) {
return removeEntity(entity.getClass(), entity.getId(), context);
}
@Override
public boolean removeEntity(Class<? extends MongoIdentifiableEntity> type, String id, MongoStoreInvocationContext context) {
MongoIdentifiableEntity found = loadEntity(type, id, context);
if (found == null) {
return false;
} else {
DBCollection dbCollection = getDBCollectionForType(type);
BasicDBObject dbQuery = new BasicDBObject("_id", id);
dbCollection.remove(dbQuery);
logger.info("Entity of type: " + type + ", id: " + id + " removed from MongoDB.");
context.addRemovedEntity(found);
return true;
}
}
@Override
public boolean removeEntities(Class<? extends MongoIdentifiableEntity> type, DBObject query, MongoStoreInvocationContext context) {
List<? extends MongoIdentifiableEntity> foundObjects = loadEntities(type, query, context);
if (foundObjects.size() == 0) {
return false;
} else {
DBCollection dbCollection = getDBCollectionForType(type);
dbCollection.remove(query);
logger.info("Removed " + foundObjects.size() + " entities of type: " + type + ", query: " + query);
for (MongoIdentifiableEntity found : foundObjects) {
context.addRemovedEntity(found);;
}
return true;
}
}
@Override
public <S> boolean pushItemToList(final MongoIdentifiableEntity entity, final String listPropertyName, S itemToPush, boolean skipIfAlreadyPresent, MongoStoreInvocationContext context) {
final Class<? extends MongoEntity> type = entity.getClass();
EntityInfo entityInfo = getEntityInfo(type);
// Add item to list directly in this object
Property<Object> listProperty = entityInfo.getPropertyByName(listPropertyName);
if (listProperty == null) {
throw new IllegalArgumentException("Property " + listPropertyName + " doesn't exist on object " + entity);
}
List<S> list = (List<S>)listProperty.getValue(entity);
if (list == null) {
list = new ArrayList<S>();
listProperty.setValue(entity, list);
}
// Skip if item is already in list
if (skipIfAlreadyPresent && list.contains(itemToPush)) {
return false;
}
// Update java object
list.add(itemToPush);
// Add update of list to pending tasks
final List<S> listt = list;
context.addUpdateTask(entity, new MongoTask() {
@Override
public void execute() {
// Now DB update of new list with usage of $set
BasicDBList dbList = mapperRegistry.convertApplicationObjectToDBObject(listt, BasicDBList.class);
BasicDBObject query = new BasicDBObject("_id", entity.getId());
BasicDBObject listObject = new BasicDBObject(listPropertyName, dbList);
BasicDBObject setCommand = new BasicDBObject("$set", listObject);
getDBCollectionForType(type).update(query, setCommand);
}
@Override
public boolean isFullUpdate() {
return false;
}
});
return true;
}
@Override
public <S> boolean pullItemFromList(final MongoIdentifiableEntity entity, final String listPropertyName, final S itemToPull, MongoStoreInvocationContext context) {
final Class<? extends MongoEntity> type = entity.getClass();
EntityInfo entityInfo = getEntityInfo(type);
// Remove item from list directly in this object
Property<Object> listProperty = entityInfo.getPropertyByName(listPropertyName);
if (listProperty == null) {
throw new IllegalArgumentException("Property " + listPropertyName + " doesn't exist on object " + entity);
}
List<S> list = (List<S>)listProperty.getValue(entity);
// If list is null, we skip both object and DB update
if (list == null || !list.contains(itemToPull)) {
return false;
} else {
// Update java object
list.remove(itemToPull);
// Add update of list to pending tasks
context.addUpdateTask(entity, new MongoTask() {
@Override
public void execute() {
// Pull item from DB
Object dbItemToPull = mapperRegistry.convertApplicationObjectToDBObject(itemToPull, Object.class);
BasicDBObject query = new BasicDBObject("_id", entity.getId());
BasicDBObject pullObject = new BasicDBObject(listPropertyName, dbItemToPull);
BasicDBObject pullCommand = new BasicDBObject("$pull", pullObject);
getDBCollectionForType(type).update(query, pullCommand);
}
@Override
public boolean isFullUpdate() {
return false;
}
});
return true;
}
}
// Possibility to add user-defined mappers
public void addAppObjectConverter(Mapper<?, ?> mapper) {
mapperRegistry.addAppObjectMapper(mapper);
}
public void addDBObjectConverter(Mapper<?, ?> mapper) {
mapperRegistry.addDBObjectMapper(mapper);
}
public EntityInfo getEntityInfo(Class<? extends MongoEntity> entityClass) {
EntityInfo entityInfo = entityInfoCache.get(entityClass);
if (entityInfo == null) {
List<Property<Object>> properties = PropertyQueries.createQuery(entityClass).addCriteria(new AnnotatedPropertyCriteria(MongoField.class)).getResultList();
MongoCollection classAnnotation = entityClass.getAnnotation(MongoCollection.class);
String dbCollectionName = classAnnotation==null ? null : classAnnotation.collectionName();
entityInfo = new EntityInfo(entityClass, dbCollectionName, properties);
EntityInfo existing = entityInfoCache.putIfAbsent(entityClass, entityInfo);
if (existing != null) {
entityInfo = existing;
}
}
return entityInfo;
}
protected <T extends MongoIdentifiableEntity> List<T> convertCursor(Class<T> type, DBCursor cursor, MongoStoreInvocationContext context) {
List<T> result = new ArrayList<T>();
try {
for (DBObject dbObject : cursor) {
T entity = convertDBObjectToEntity(type, dbObject, context);
result.add(entity);
}
} finally {
cursor.close();
}
return result;
}
protected <T extends MongoIdentifiableEntity> T convertDBObjectToEntity(Class<T> type, DBObject dbObject, MongoStoreInvocationContext context) {
// First look if we already have loaded object cached. If yes, we will use cached instance
String id = dbObject.get("_id").toString();
T object = context.getLoadedEntity(type, id);
if (object == null) {
// So convert and use fresh instance from DB
MapperContext<Object, T> mapperContext = new MapperContext<Object, T>(dbObject, type, null);
object = mapperRegistry.convertDBObjectToApplicationObject(mapperContext);
context.addLoadedEntity(object);
}
return object;
}
protected DBCollection getDBCollectionForType(Class<? extends MongoEntity> type) {
EntityInfo entityInfo = getEntityInfo(type);
String dbCollectionName = entityInfo.getDbCollectionName();
return dbCollectionName==null ? null : database.getCollection(dbCollectionName);
}
}
package org.keycloak.connections.mongo.impl;
import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
import com.mongodb.MongoException;
import org.jboss.logging.Logger;
import org.keycloak.connections.mongo.api.MongoCollection;
import org.keycloak.connections.mongo.api.MongoEntity;
import org.keycloak.connections.mongo.api.MongoIdentifiableEntity;
import org.keycloak.connections.mongo.api.MongoIndex;
import org.keycloak.connections.mongo.api.MongoIndexes;
import org.keycloak.connections.mongo.api.MongoStore;
import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
import org.keycloak.connections.mongo.api.context.MongoTask;
import org.keycloak.connections.mongo.api.types.Mapper;
import org.keycloak.connections.mongo.api.types.MapperContext;
import org.keycloak.connections.mongo.api.types.MapperRegistry;
import org.keycloak.connections.mongo.impl.types.BasicDBListMapper;
import org.keycloak.connections.mongo.impl.types.BasicDBObjectMapper;
import org.keycloak.connections.mongo.impl.types.BasicDBObjectToMapMapper;
import org.keycloak.connections.mongo.impl.types.EnumToStringMapper;
import org.keycloak.connections.mongo.impl.types.ListMapper;
import org.keycloak.connections.mongo.impl.types.MapMapper;
import org.keycloak.connections.mongo.impl.types.MongoEntityMapper;
import org.keycloak.connections.mongo.impl.types.SimpleMapper;
import org.keycloak.connections.mongo.impl.types.StringToEnumMapper;
import org.keycloak.models.ModelDuplicateException;
import org.keycloak.models.ModelException;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.models.utils.reflection.Property;
import org.keycloak.models.utils.reflection.PropertyQueries;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class MongoStoreImpl implements MongoStore {
private static final Class<?>[] SIMPLE_TYPES = { String.class, Integer.class, Boolean.class, Long.class, Double.class, Character.class, Date.class, byte[].class };
private final DB database;
private static final Logger logger = Logger.getLogger(MongoStoreImpl.class);
private final MapperRegistry mapperRegistry;
private ConcurrentMap<Class<?>, EntityInfo> entityInfoCache =
new ConcurrentHashMap<Class<?>, EntityInfo>();
public MongoStoreImpl(DB database, boolean clearCollectionsOnStartup, Class<?>[] managedEntityTypes) {
this.database = database;
mapperRegistry = new MapperRegistry();
for (Class<?> simpleMapperClass : SIMPLE_TYPES) {
SimpleMapper mapper = new SimpleMapper(simpleMapperClass);
mapperRegistry.addAppObjectMapper(mapper);
mapperRegistry.addDBObjectMapper(mapper);
}
// Specific converter for ArrayList is added just for performance purposes to avoid recursive converter lookup (most of list idm will be ArrayList)
mapperRegistry.addAppObjectMapper(new ListMapper(mapperRegistry, ArrayList.class));
mapperRegistry.addAppObjectMapper(new ListMapper(mapperRegistry, List.class));
mapperRegistry.addDBObjectMapper(new BasicDBListMapper(mapperRegistry));
mapperRegistry.addAppObjectMapper(new MapMapper(HashMap.class));
mapperRegistry.addAppObjectMapper(new MapMapper(Map.class));
mapperRegistry.addDBObjectMapper(new BasicDBObjectToMapMapper());
// Enum converters
mapperRegistry.addAppObjectMapper(new EnumToStringMapper());
mapperRegistry.addDBObjectMapper(new StringToEnumMapper());
for (Class<?> type : managedEntityTypes) {
getEntityInfo(type);
mapperRegistry.addAppObjectMapper(new MongoEntityMapper(this, mapperRegistry, type));
mapperRegistry.addDBObjectMapper(new BasicDBObjectMapper(this, mapperRegistry, type));
}
if (clearCollectionsOnStartup) {
// dropDatabase();
clearManagedCollections(managedEntityTypes);
}
initManagedCollections(managedEntityTypes);
}
protected void dropDatabase() {
this.database.dropDatabase();
logger.info("Database " + this.database.getName() + " dropped in MongoDB");
}
// Don't drop database, but just clear all data in managed collections (useful for export/import or during development)
protected void clearManagedCollections(Class<?>[] managedEntityTypes) {
for (Class<?> clazz : managedEntityTypes) {
DBCollection dbCollection = getDBCollectionForType(clazz);
if (dbCollection != null) {
dbCollection.remove(new BasicDBObject());
logger.debug("Collection " + dbCollection.getName() + " cleared from " + this.database.getName());
}
}
}
protected void initManagedCollections(Class<?>[] managedEntityTypes) {
for (Class<?> clazz : managedEntityTypes) {
EntityInfo entityInfo = getEntityInfo(clazz);
String dbCollectionName = entityInfo.getDbCollectionName();
if (dbCollectionName != null && !database.collectionExists(dbCollectionName)) {
DBCollection dbCollection = database.getCollection(dbCollectionName);
logger.debug("Created collection " + dbCollection.getName() + " in " + this.database.getName());
MongoIndex index = clazz.getAnnotation(MongoIndex.class);
if (index != null) {
createIndex(dbCollection, index);
}
MongoIndexes indexes = clazz.getAnnotation(MongoIndexes.class);
if (indexes != null) {
for (MongoIndex i : indexes.value()) {
createIndex(dbCollection, i);
}
}
}
}
}
protected void createIndex(DBCollection dbCollection, MongoIndex index) {
BasicDBObject fields = new BasicDBObject();
for (String f : index.fields()) {
fields.put(f, 1);
}
boolean unique = index.unique();
boolean sparse = index.sparse();
BasicDBObject options = new BasicDBObject();
if (unique) {
options.put("unique", unique);
}
if (sparse) {
options.put("sparse", sparse);
}
dbCollection.ensureIndex(fields, options);
logger.debug("Created index " + fields + "(options: " + options + ") on " + dbCollection.getName() + " in " + this.database.getName());
}
@Override
public void insertEntity(MongoIdentifiableEntity entity, MongoStoreInvocationContext context) {
Class<? extends MongoEntity> clazz = entity.getClass();
// Find annotations for ID, for all the properties and for the name of the collection.
EntityInfo entityInfo = getEntityInfo(clazz);
// Create instance of BasicDBObject and add all declared properties to it (properties with null value probably should be skipped)
BasicDBObject dbObject = mapperRegistry.convertApplicationObjectToDBObject(entity, BasicDBObject.class);
DBCollection dbCollection = database.getCollection(entityInfo.getDbCollectionName());
String currentId = entity.getId();
// Generate random ID if not set already
if (currentId == null) {
currentId = KeycloakModelUtils.generateId();
entity.setId(currentId);
}
// Adding "_id"
dbObject.put("_id", currentId);
try {
dbCollection.insert(dbObject);
} catch (MongoException e) {
throw convertException(e);
}
// Treat object as created in this transaction (It is already submited to transaction)
context.addCreatedEntity(entity);
}
public static ModelException convertException(MongoException e) {
if (e instanceof MongoException.DuplicateKey) {
return new ModelDuplicateException(e);
} else {
return new ModelException(e);
}
}
@Override
public void updateEntity(final MongoIdentifiableEntity entity, MongoStoreInvocationContext context) {
MongoTask fullUpdateTask = new MongoTask() {
@Override
public void execute() {
Class<? extends MongoEntity> clazz = entity.getClass();
EntityInfo entityInfo = getEntityInfo(clazz);
BasicDBObject dbObject = mapperRegistry.convertApplicationObjectToDBObject(entity, BasicDBObject.class);
DBCollection dbCollection = database.getCollection(entityInfo.getDbCollectionName());
String currentId = entity.getId();
if (currentId == null) {
throw new IllegalStateException("Can't update entity without id: " + entity);
} else {
BasicDBObject query = new BasicDBObject("_id", currentId);
dbCollection.update(query, dbObject);
}
}
@Override
public boolean isFullUpdate() {
return true;
}
};
// update is just added to context and postponed
context.addUpdateTask(entity, fullUpdateTask);
}
@Override
public <T extends MongoIdentifiableEntity> T loadEntity(Class<T> type, String id, MongoStoreInvocationContext context) {
// First look if we already read the object with this oid and type during this transaction. If yes, use it instead of DB lookup
T cached = context.getLoadedEntity(type, id);
if (cached != null && type.isAssignableFrom(cached.getClass())) return cached;
DBCollection dbCollection = getDBCollectionForType(type);
BasicDBObject idQuery = new BasicDBObject("_id", id);
DBObject dbObject = dbCollection.findOne(idQuery);
if (dbObject == null) return null;
MapperContext<Object, T> mapperContext = new MapperContext<Object, T>(dbObject, type, null);
T converted = mapperRegistry.convertDBObjectToApplicationObject(mapperContext);
// Now add it to loaded objects
context.addLoadedEntity(converted);
return converted;
}
@Override
public <T extends MongoIdentifiableEntity> T loadSingleEntity(Class<T> type, DBObject query, MongoStoreInvocationContext context) {
// First we should execute all pending tasks before searching DB
context.beforeDBSearch(type);
DBCollection dbCollection = getDBCollectionForType(type);
DBObject dbObject = dbCollection.findOne(query);
if (dbObject == null) {
return null;
} else {
return convertDBObjectToEntity(type, dbObject, context);
}
}
@Override
public <T extends MongoIdentifiableEntity> List<T> loadEntities(Class<T> type, DBObject query, MongoStoreInvocationContext context) {
// First we should execute all pending tasks before searching DB
context.beforeDBSearch(type);
DBCollection dbCollection = getDBCollectionForType(type);
DBCursor cursor = dbCollection.find(query);
return convertCursor(type, cursor, context);
}
@Override
public <T extends MongoIdentifiableEntity> List<T> loadEntities(Class<T> type, DBObject query, DBObject sort, int firstResult, int maxResults, MongoStoreInvocationContext context) {
// First we should execute all pending tasks before searching DB
context.beforeDBSearch(type);
DBCollection dbCollection = getDBCollectionForType(type);
DBCursor cursor = dbCollection.find(query);
if (firstResult != -1) {
cursor.skip(firstResult);
}
if (maxResults != -1) {
cursor.limit(maxResults);
}
if (sort != null) {
cursor.sort(sort);
}
return convertCursor(type, cursor, context);
}
public <T extends MongoIdentifiableEntity> int countEntities(Class<T> type, DBObject query, MongoStoreInvocationContext context) {
context.beforeDBSearch(type);
DBCollection dbCollection = getDBCollectionForType(type);
Long count = dbCollection.count(query);
// For now, assume that int is sufficient
return count.intValue();
}
@Override
public boolean removeEntity(MongoIdentifiableEntity entity, MongoStoreInvocationContext context) {
return removeEntity(entity.getClass(), entity.getId(), context);
}
@Override
public boolean removeEntity(Class<? extends MongoIdentifiableEntity> type, String id, MongoStoreInvocationContext context) {
MongoIdentifiableEntity found = loadEntity(type, id, context);
if (found == null) {
return false;
} else {
DBCollection dbCollection = getDBCollectionForType(type);
BasicDBObject dbQuery = new BasicDBObject("_id", id);
dbCollection.remove(dbQuery);
logger.info("Entity of type: " + type + ", id: " + id + " removed from MongoDB.");
context.addRemovedEntity(found);
return true;
}
}
@Override
public boolean removeEntities(Class<? extends MongoIdentifiableEntity> type, DBObject query, MongoStoreInvocationContext context) {
List<? extends MongoIdentifiableEntity> foundObjects = loadEntities(type, query, context);
if (foundObjects.size() == 0) {
return false;
} else {
DBCollection dbCollection = getDBCollectionForType(type);
dbCollection.remove(query);
logger.info("Removed " + foundObjects.size() + " entities of type: " + type + ", query: " + query);
for (MongoIdentifiableEntity found : foundObjects) {
context.addRemovedEntity(found);;
}
return true;
}
}
@Override
public <S> boolean pushItemToList(final MongoIdentifiableEntity entity, final String listPropertyName, S itemToPush, boolean skipIfAlreadyPresent, MongoStoreInvocationContext context) {
final Class<? extends MongoEntity> type = entity.getClass();
EntityInfo entityInfo = getEntityInfo(type);
// Add item to list directly in this object
Property<Object> listProperty = entityInfo.getPropertyByName(listPropertyName);
if (listProperty == null) {
throw new IllegalArgumentException("Property " + listPropertyName + " doesn't exist on object " + entity);
}
List<S> list = (List<S>)listProperty.getValue(entity);
if (list == null) {
list = new ArrayList<S>();
listProperty.setValue(entity, list);
}
// Skip if item is already in list
if (skipIfAlreadyPresent && list.contains(itemToPush)) {
return false;
}
// Update java object
list.add(itemToPush);
// Add update of list to pending tasks
final List<S> listt = list;
context.addUpdateTask(entity, new MongoTask() {
@Override
public void execute() {
// Now DB update of new list with usage of $set
BasicDBList dbList = mapperRegistry.convertApplicationObjectToDBObject(listt, BasicDBList.class);
BasicDBObject query = new BasicDBObject("_id", entity.getId());
BasicDBObject listObject = new BasicDBObject(listPropertyName, dbList);
BasicDBObject setCommand = new BasicDBObject("$set", listObject);
getDBCollectionForType(type).update(query, setCommand);
}
@Override
public boolean isFullUpdate() {
return false;
}
});
return true;
}
@Override
public <S> boolean pullItemFromList(final MongoIdentifiableEntity entity, final String listPropertyName, final S itemToPull, MongoStoreInvocationContext context) {
final Class<? extends MongoEntity> type = entity.getClass();
EntityInfo entityInfo = getEntityInfo(type);
// Remove item from list directly in this object
Property<Object> listProperty = entityInfo.getPropertyByName(listPropertyName);
if (listProperty == null) {
throw new IllegalArgumentException("Property " + listPropertyName + " doesn't exist on object " + entity);
}
List<S> list = (List<S>)listProperty.getValue(entity);
// If list is null, we skip both object and DB update
if (list == null || !list.contains(itemToPull)) {
return false;
} else {
// Update java object
list.remove(itemToPull);
// Add update of list to pending tasks
context.addUpdateTask(entity, new MongoTask() {
@Override
public void execute() {
// Pull item from DB
Object dbItemToPull = mapperRegistry.convertApplicationObjectToDBObject(itemToPull, Object.class);
BasicDBObject query = new BasicDBObject("_id", entity.getId());
BasicDBObject pullObject = new BasicDBObject(listPropertyName, dbItemToPull);
BasicDBObject pullCommand = new BasicDBObject("$pull", pullObject);
getDBCollectionForType(type).update(query, pullCommand);
}
@Override
public boolean isFullUpdate() {
return false;
}
});
return true;
}
}
// Possibility to add user-defined mappers
public void addAppObjectConverter(Mapper<?, ?> mapper) {
mapperRegistry.addAppObjectMapper(mapper);
}
public void addDBObjectConverter(Mapper<?, ?> mapper) {
mapperRegistry.addDBObjectMapper(mapper);
}
public EntityInfo getEntityInfo(Class<?> entityClass) {
EntityInfo entityInfo = entityInfoCache.get(entityClass);
if (entityInfo == null) {
Map<String, Property<Object>> properties = PropertyQueries.createQuery(entityClass).getWritableResultList();
MongoCollection classAnnotation = entityClass.getAnnotation(MongoCollection.class);
String dbCollectionName = classAnnotation==null ? null : classAnnotation.collectionName();
entityInfo = new EntityInfo(entityClass, dbCollectionName, properties);
EntityInfo existing = entityInfoCache.putIfAbsent(entityClass, entityInfo);
if (existing != null) {
entityInfo = existing;
}
}
return entityInfo;
}
protected <T extends MongoIdentifiableEntity> List<T> convertCursor(Class<T> type, DBCursor cursor, MongoStoreInvocationContext context) {
List<T> result = new ArrayList<T>();
try {
for (DBObject dbObject : cursor) {
T entity = convertDBObjectToEntity(type, dbObject, context);
result.add(entity);
}
} finally {
cursor.close();
}
return result;
}
protected <T extends MongoIdentifiableEntity> T convertDBObjectToEntity(Class<T> type, DBObject dbObject, MongoStoreInvocationContext context) {
// First look if we already have loaded object cached. If yes, we will use cached instance
String id = dbObject.get("_id").toString();
T object = context.getLoadedEntity(type, id);
if (object == null) {
// So convert and use fresh instance from DB
MapperContext<Object, T> mapperContext = new MapperContext<Object, T>(dbObject, type, null);
object = mapperRegistry.convertDBObjectToApplicationObject(mapperContext);
context.addLoadedEntity(object);
}
return object;
}
protected DBCollection getDBCollectionForType(Class<?> type) {
EntityInfo entityInfo = getEntityInfo(type);
String dbCollectionName = entityInfo.getDbCollectionName();
return dbCollectionName==null ? null : database.getCollection(dbCollectionName);
}
}
@@ -1,10 +1,9 @@
package org.keycloak.models.mongo.impl.context;
package org.keycloak.connections.mongo.impl.context;
import org.keycloak.models.mongo.api.MongoEntity;
import org.keycloak.models.mongo.api.MongoIdentifiableEntity;
import org.keycloak.models.mongo.api.MongoStore;
import org.keycloak.models.mongo.api.context.MongoStoreInvocationContext;
import org.keycloak.models.mongo.api.context.MongoTask;
import org.keycloak.connections.mongo.api.MongoIdentifiableEntity;
import org.keycloak.connections.mongo.api.MongoStore;
import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
import org.keycloak.connections.mongo.api.context.MongoTask;
/**
* Context, which is not doing any postponing of tasks and does not cache anything
@@ -1,4 +1,9 @@
package org.keycloak.models.mongo.impl.context;
package org.keycloak.connections.mongo.impl.context;
import org.keycloak.connections.mongo.api.MongoIdentifiableEntity;
import org.keycloak.connections.mongo.api.MongoStore;
import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
import org.keycloak.connections.mongo.api.context.MongoTask;
import java.util.HashMap;
import java.util.HashSet;
@@ -6,11 +11,6 @@ import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import org.keycloak.models.mongo.api.MongoIdentifiableEntity;
import org.keycloak.models.mongo.api.MongoStore;
import org.keycloak.models.mongo.api.context.MongoStoreInvocationContext;
import org.keycloak.models.mongo.api.context.MongoTask;
/**
* Invocation context, which has some very basic support for transactions, and is able to cache loaded objects.
* It always execute all pending update tasks before start searching for other objects
@@ -1,44 +1,44 @@
package org.keycloak.models.mongo.impl.types;
import com.mongodb.BasicDBList;
import org.keycloak.models.mongo.api.types.Mapper;
import org.keycloak.models.mongo.api.types.MapperContext;
import org.keycloak.models.mongo.api.types.MapperRegistry;
import java.util.ArrayList;
import java.util.List;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class BasicDBListMapper implements Mapper<BasicDBList, List> {
private final MapperRegistry mapperRegistry;
public BasicDBListMapper(MapperRegistry mapperRegistry) {
this.mapperRegistry = mapperRegistry;
}
@Override
public List convertObject(MapperContext<BasicDBList, List> context) {
BasicDBList dbList = context.getObjectToConvert();
ArrayList<Object> appObjects = new ArrayList<Object>();
Class<?> expectedListElementType = context.getGenericTypes().get(0);
for (Object dbObject : dbList) {
MapperContext<Object, Object> newContext = new MapperContext<Object, Object>(dbObject, expectedListElementType, null);
appObjects.add(mapperRegistry.convertDBObjectToApplicationObject(newContext));
}
return appObjects;
}
@Override
public Class<? extends BasicDBList> getTypeOfObjectToConvert() {
return BasicDBList.class;
}
@Override
public Class<List> getExpectedReturnType() {
return List.class;
}
}
package org.keycloak.connections.mongo.impl.types;
import com.mongodb.BasicDBList;
import org.keycloak.connections.mongo.api.types.Mapper;
import org.keycloak.connections.mongo.api.types.MapperContext;
import org.keycloak.connections.mongo.api.types.MapperRegistry;
import java.util.ArrayList;
import java.util.List;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class BasicDBListMapper implements Mapper<BasicDBList, List> {
private final MapperRegistry mapperRegistry;
public BasicDBListMapper(MapperRegistry mapperRegistry) {
this.mapperRegistry = mapperRegistry;
}
@Override
public List convertObject(MapperContext<BasicDBList, List> context) {
BasicDBList dbList = context.getObjectToConvert();
ArrayList<Object> appObjects = new ArrayList<Object>();
Class<?> expectedListElementType = context.getGenericTypes().get(0);
for (Object dbObject : dbList) {
MapperContext<Object, Object> newContext = new MapperContext<Object, Object>(dbObject, expectedListElementType, null);
appObjects.add(mapperRegistry.convertDBObjectToApplicationObject(newContext));
}
return appObjects;
}
@Override
public Class<? extends BasicDBList> getTypeOfObjectToConvert() {
return BasicDBList.class;
}
@Override
public Class<List> getExpectedReturnType() {
return List.class;
}
}
@@ -1,26 +1,25 @@
package org.keycloak.models.mongo.impl.types;
package org.keycloak.connections.mongo.impl.types;
import com.mongodb.BasicDBObject;
import org.jboss.logging.Logger;
import org.keycloak.connections.mongo.api.MongoIdentifiableEntity;
import org.keycloak.connections.mongo.api.types.Mapper;
import org.keycloak.connections.mongo.api.types.MapperContext;
import org.keycloak.connections.mongo.api.types.MapperRegistry;
import org.keycloak.connections.mongo.impl.EntityInfo;
import org.keycloak.connections.mongo.impl.MongoStoreImpl;
import org.keycloak.models.utils.reflection.Property;
import org.keycloak.models.utils.reflection.Types;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import com.mongodb.BasicDBObject;
import org.jboss.logging.Logger;
import org.keycloak.models.mongo.api.MongoEntity;
import org.keycloak.models.mongo.api.MongoIdentifiableEntity;
import org.keycloak.models.mongo.api.types.Mapper;
import org.keycloak.models.mongo.api.types.MapperContext;
import org.keycloak.models.mongo.api.types.MapperRegistry;
import org.keycloak.models.mongo.impl.MongoStoreImpl;
import org.keycloak.models.mongo.impl.EntityInfo;
import org.picketlink.common.properties.Property;
import org.picketlink.common.reflection.Types;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class BasicDBObjectMapper<S extends MongoEntity> implements Mapper<BasicDBObject, S> {
public class BasicDBObjectMapper<S> implements Mapper<BasicDBObject, S> {
private static final Logger logger = Logger.getLogger(BasicDBObjectMapper.class);
@@ -73,7 +72,7 @@ public class BasicDBObjectMapper<S extends MongoEntity> implements Mapper<BasicD
return entity;
}
private void setPropertyValue(MongoEntity entity, Object valueFromDB, Property property) {
private void setPropertyValue(Object entity, Object valueFromDB, Property property) {
if (valueFromDB == null) {
property.setValue(entity, null);
return;
@@ -1,12 +1,12 @@
package org.keycloak.models.mongo.impl.types;
package org.keycloak.connections.mongo.impl.types;
import com.mongodb.BasicDBObject;
import org.keycloak.connections.mongo.api.types.Mapper;
import org.keycloak.connections.mongo.api.types.MapperContext;
import java.util.HashMap;
import java.util.Map;
import com.mongodb.BasicDBObject;
import org.keycloak.models.mongo.api.types.Mapper;
import org.keycloak.models.mongo.api.types.MapperContext;
/**
* For now, there is support just for convert to Map<String, String>
*
@@ -1,7 +1,7 @@
package org.keycloak.models.mongo.impl.types;
package org.keycloak.connections.mongo.impl.types;
import org.keycloak.models.mongo.api.types.Mapper;
import org.keycloak.models.mongo.api.types.MapperContext;
import org.keycloak.connections.mongo.api.types.Mapper;
import org.keycloak.connections.mongo.api.types.MapperContext;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
@@ -1,45 +1,45 @@
package org.keycloak.models.mongo.impl.types;
import com.mongodb.BasicDBList;
import org.keycloak.models.mongo.api.types.Mapper;
import org.keycloak.models.mongo.api.types.MapperContext;
import org.keycloak.models.mongo.api.types.MapperRegistry;
import java.util.List;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class ListMapper<T extends List> implements Mapper<T, BasicDBList> {
private final MapperRegistry mapperRegistry;
private final Class<T> listType;
public ListMapper(MapperRegistry mapperRegistry, Class<T> listType) {
this.mapperRegistry = mapperRegistry;
this.listType = listType;
}
@Override
public BasicDBList convertObject(MapperContext<T, BasicDBList> context) {
T appObjectsList = context.getObjectToConvert();
BasicDBList dbObjects = new BasicDBList();
for (Object appObject : appObjectsList) {
Object dbObject = mapperRegistry.convertApplicationObjectToDBObject(appObject, Object.class);
dbObjects.add(dbObject);
}
return dbObjects;
}
@Override
public Class<? extends T> getTypeOfObjectToConvert() {
return listType;
}
@Override
public Class<BasicDBList> getExpectedReturnType() {
return BasicDBList.class;
}
}
package org.keycloak.connections.mongo.impl.types;
import com.mongodb.BasicDBList;
import org.keycloak.connections.mongo.api.types.Mapper;
import org.keycloak.connections.mongo.api.types.MapperContext;
import org.keycloak.connections.mongo.api.types.MapperRegistry;
import java.util.List;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class ListMapper<T extends List> implements Mapper<T, BasicDBList> {
private final MapperRegistry mapperRegistry;
private final Class<T> listType;
public ListMapper(MapperRegistry mapperRegistry, Class<T> listType) {
this.mapperRegistry = mapperRegistry;
this.listType = listType;
}
@Override
public BasicDBList convertObject(MapperContext<T, BasicDBList> context) {
T appObjectsList = context.getObjectToConvert();
BasicDBList dbObjects = new BasicDBList();
for (Object appObject : appObjectsList) {
Object dbObject = mapperRegistry.convertApplicationObjectToDBObject(appObject, Object.class);
dbObjects.add(dbObject);
}
return dbObjects;
}
@Override
public Class<? extends T> getTypeOfObjectToConvert() {
return listType;
}
@Override
public Class<BasicDBList> getExpectedReturnType() {
return BasicDBList.class;
}
}
@@ -1,12 +1,12 @@
package org.keycloak.models.mongo.impl.types;
package org.keycloak.connections.mongo.impl.types;
import com.mongodb.BasicDBObject;
import org.keycloak.connections.mongo.api.types.Mapper;
import org.keycloak.connections.mongo.api.types.MapperContext;
import java.util.Map;
import java.util.Set;
import com.mongodb.BasicDBObject;
import org.keycloak.models.mongo.api.types.Mapper;
import org.keycloak.models.mongo.api.types.MapperContext;
/**
* For now, we support just convert from Map<String, String>
*
@@ -1,58 +1,63 @@
package org.keycloak.models.mongo.impl.types;
import com.mongodb.BasicDBObject;
import org.keycloak.models.mongo.api.MongoEntity;
import org.keycloak.models.mongo.api.types.Mapper;
import org.keycloak.models.mongo.api.types.MapperContext;
import org.keycloak.models.mongo.api.types.MapperRegistry;
import org.keycloak.models.mongo.impl.MongoStoreImpl;
import org.keycloak.models.mongo.impl.EntityInfo;
import org.picketlink.common.properties.Property;
import java.util.Collection;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class MongoEntityMapper<T extends MongoEntity> implements Mapper<T, BasicDBObject> {
private final MongoStoreImpl mongoStoreImpl;
private final MapperRegistry mapperRegistry;
private final Class<T> expectedMongoEntityType;
public MongoEntityMapper(MongoStoreImpl mongoStoreImpl, MapperRegistry mapperRegistry, Class<T> expectedMongoEntityType) {
this.mongoStoreImpl = mongoStoreImpl;
this.mapperRegistry = mapperRegistry;
this.expectedMongoEntityType = expectedMongoEntityType;
}
@Override
public BasicDBObject convertObject(MapperContext<T, BasicDBObject> context) {
T applicationObject = context.getObjectToConvert();
EntityInfo entityInfo = mongoStoreImpl.getEntityInfo(applicationObject.getClass());
// Create instance of BasicDBObject and add all declared properties to it
BasicDBObject dbObject = new BasicDBObject();
Collection<Property<Object>> props = entityInfo.getProperties();
for (Property<Object> property : props) {
String propName = property.getName();
Object propValue = property.getValue(applicationObject);
Object dbValue = propValue == null ? null : mapperRegistry.convertApplicationObjectToDBObject(propValue, Object.class);
dbObject.put(propName, dbValue);
}
return dbObject;
}
@Override
public Class<? extends T> getTypeOfObjectToConvert() {
return expectedMongoEntityType;
}
@Override
public Class<BasicDBObject> getExpectedReturnType() {
return BasicDBObject.class;
}
}
package org.keycloak.connections.mongo.impl.types;
import com.mongodb.BasicDBObject;
import org.keycloak.connections.mongo.api.MongoIdentifiableEntity;
import org.keycloak.connections.mongo.api.types.Mapper;
import org.keycloak.connections.mongo.api.types.MapperContext;
import org.keycloak.connections.mongo.api.types.MapperRegistry;
import org.keycloak.connections.mongo.impl.EntityInfo;
import org.keycloak.connections.mongo.impl.MongoStoreImpl;
import org.keycloak.models.utils.reflection.Property;
import java.util.Collection;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class MongoEntityMapper<T> implements Mapper<T, BasicDBObject> {
private final MongoStoreImpl mongoStoreImpl;
private final MapperRegistry mapperRegistry;
private final Class<T> expectedMongoEntityType;
public MongoEntityMapper(MongoStoreImpl mongoStoreImpl, MapperRegistry mapperRegistry, Class<T> expectedMongoEntityType) {
this.mongoStoreImpl = mongoStoreImpl;
this.mapperRegistry = mapperRegistry;
this.expectedMongoEntityType = expectedMongoEntityType;
}
@Override
public BasicDBObject convertObject(MapperContext<T, BasicDBObject> context) {
T applicationObject = context.getObjectToConvert();
EntityInfo entityInfo = mongoStoreImpl.getEntityInfo(applicationObject.getClass());
// Create instance of BasicDBObject and add all declared properties to it
BasicDBObject dbObject = new BasicDBObject();
Collection<Property<Object>> props = entityInfo.getProperties();
for (Property<Object> property : props) {
String propName = property.getName();
// Ignore "id" property
if (!"id".equals(propName) || !(applicationObject instanceof MongoIdentifiableEntity)) {
Object propValue = property.getValue(applicationObject);
if (propValue != null) {
Object dbValue = propValue == null ? null : mapperRegistry.convertApplicationObjectToDBObject(propValue, Object.class);
dbObject.put(propName, dbValue);
}
}
}
return dbObject;
}
@Override
public Class<? extends T> getTypeOfObjectToConvert() {
return expectedMongoEntityType;
}
@Override
public Class<BasicDBObject> getExpectedReturnType() {
return BasicDBObject.class;
}
}
@@ -1,7 +1,7 @@
package org.keycloak.models.mongo.impl.types;
package org.keycloak.connections.mongo.impl.types;
import org.keycloak.models.mongo.api.types.Mapper;
import org.keycloak.models.mongo.api.types.MapperContext;
import org.keycloak.connections.mongo.api.types.Mapper;
import org.keycloak.connections.mongo.api.types.MapperContext;
/**
* Just returns input
@@ -1,7 +1,7 @@
package org.keycloak.models.mongo.impl.types;
package org.keycloak.connections.mongo.impl.types;
import org.keycloak.models.mongo.api.types.Mapper;
import org.keycloak.models.mongo.api.types.MapperContext;
import org.keycloak.connections.mongo.api.types.Mapper;
import org.keycloak.connections.mongo.api.types.MapperContext;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
@@ -0,0 +1 @@
org.keycloak.connections.mongo.DefaultMongoConnectionFactoryProvider
@@ -0,0 +1 @@
org.keycloak.connections.mongo.MongoConnectionSpi
+31
View File
@@ -0,0 +1,31 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.0-final</version>
</parent>
<name>Connections Parent</name>
<description/>
<modelVersion>4.0.0</modelVersion>
<artifactId>keycloak-connections-pom</artifactId>
<packaging>pom</packaging>
<modules>
<module>jpa</module>
<module>mongo</module>
</modules>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
</project>
+5 -9
View File
@@ -1,9 +1,10 @@
<?xml version="1.0"?>
<project>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.0-alpha-2</version>
<version>1.0-final</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -18,11 +19,6 @@
<artifactId>resteasy-jaxrs</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-client</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-core</artifactId>
@@ -61,8 +57,8 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
</configuration>
</plugin>
</plugins>
@@ -18,11 +18,11 @@ public class SkeletonKeyContextResolver implements ContextResolver<ObjectMapper>
protected ObjectMapper mapper = new ObjectMapper();
public SkeletonKeyContextResolver() {
mapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_DEFAULT);
mapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_NULL);
}
public SkeletonKeyContextResolver(boolean indent) {
mapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_DEFAULT);
mapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_NULL);
if (indent) {
mapper.enable(SerializationConfig.Feature.INDENT_OUTPUT);
}
+15 -4
View File
@@ -1,9 +1,10 @@
<?xml version="1.0"?>
<project>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.0-alpha-2</version>
<version>1.0-final</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -12,6 +13,10 @@
<name>Keycloak Core</name>
<description/>
<properties>
<timestamp>${maven.build.timestamp}</timestamp>
<maven.build.timestamp.format>yyyy-MM-dd HH:mm</maven.build.timestamp.format>
</properties>
<dependencies>
<dependency>
<groupId>org.bouncycastle</groupId>
@@ -40,13 +45,19 @@
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
</configuration>
</plugin>
</plugins>
@@ -2,7 +2,6 @@ package org.keycloak;
import org.keycloak.util.KeycloakUriBuilder;
import java.security.KeyStore;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicLong;
@@ -12,18 +11,20 @@ import java.util.concurrent.atomic.AtomicLong;
* @version $Revision: 1 $
*/
public class AbstractOAuthClient {
public static final String OAUTH_TOKEN_REQUEST_STATE = "OAuth_Token_Request_State";
private static final String OAUTH_TOKEN_REQUEST_STATE = "OAuth_Token_Request_State";
private final AtomicLong counter = new AtomicLong();
protected String clientId;
protected Map<String, String> credentials;
protected KeyStore truststore;
protected String authUrl;
protected String codeUrl;
protected String refreshUrl;
protected boolean relativeUrls;
protected String scope;
protected String stateCookieName = OAUTH_TOKEN_REQUEST_STATE;
protected String stateCookiePath;
protected boolean isSecure;
protected final AtomicLong counter = new AtomicLong();
protected boolean publicClient;
protected String getStateCode() {
return counter.getAndIncrement() + "/" + UUID.randomUUID().toString();
}
@@ -44,20 +45,10 @@ public class AbstractOAuthClient {
this.credentials = credentials;
}
public KeyStore getTruststore() {
return truststore;
}
public void setTruststore(KeyStore truststore) {
this.truststore = truststore;
}
public String getAuthUrl() {
return authUrl;
}
public void setAuthUrl(String authUrl) {
this.authUrl = authUrl;
}
@@ -70,6 +61,14 @@ public class AbstractOAuthClient {
this.codeUrl = codeUrl;
}
public String getRefreshUrl() {
return refreshUrl;
}
public void setRefreshUrl(String refreshUrl) {
this.refreshUrl = refreshUrl;
}
public String getScope() {
return scope;
}
@@ -94,10 +93,26 @@ public class AbstractOAuthClient {
this.stateCookiePath = stateCookiePath;
}
public boolean isPublicClient() {
return publicClient;
}
public void setPublicClient(boolean publicClient) {
this.publicClient = publicClient;
}
public boolean isRelativeUrls() {
return relativeUrls;
}
public void setRelativeUrls(boolean relativeUrls) {
this.relativeUrls = relativeUrls;
}
protected String stripOauthParametersFromRedirect(String uri) {
KeycloakUriBuilder builder = KeycloakUriBuilder.fromUri(uri)
.replaceQueryParam("code", null)
.replaceQueryParam("state", null);
.replaceQueryParam(OAuth2Constants.CODE, null)
.replaceQueryParam(OAuth2Constants.STATE, null);
return builder.build().toString();
}
+13
View File
@@ -0,0 +1,13 @@
package org.keycloak;
/**
* Information about the client connection
*
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public interface ClientConnection {
String getRemoteAddr();
String getRemoteHost();
int getReportPort();
}
+150
View File
@@ -0,0 +1,150 @@
package org.keycloak;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class Config {
private static ConfigProvider configProvider = new SystemPropertiesConfigProvider();
public static void init(ConfigProvider configProvider) {
Config.configProvider = configProvider;
}
public static String getAdminRealm() {
return configProvider.scope("admin").get("realm", "master");
}
public static String getProvider(String spi) {
String provider = configProvider.getProvider(spi);
if (provider == null || provider.trim().equals("")) {
return null;
} else {
return provider;
}
}
public static Scope scope(String... scope) {
return configProvider.scope(scope);
}
public static interface ConfigProvider {
String getProvider(String spi);
Scope scope(String... scope);
}
public static class SystemPropertiesConfigProvider implements ConfigProvider {
@Override
public String getProvider(String spi) {
return System.getProperties().getProperty("keycloak." + spi + ".provider");
}
@Override
public Scope scope(String... scope) {
StringBuilder sb = new StringBuilder();
sb.append("keycloak.");
for (String s : scope) {
sb.append(s);
sb.append(".");
}
return new SystemPropertiesScope(sb.toString());
}
}
public static class SystemPropertiesScope implements Scope {
private String prefix;
public SystemPropertiesScope(String prefix) {
this.prefix = prefix;
}
@Override
public String get(String key) {
return get(key, null);
}
@Override
public String get(String key, String defaultValue) {
return System.getProperty(prefix + key, defaultValue);
}
@Override
public String[] getArray(String key) {
String value = get(key);
if (value != null) {
String[] a = value.split(",");
for (int i = 0; i < a.length; i++) {
a[i] = a[i].trim();
}
return a;
} else {
return null;
}
}
@Override
public Integer getInt(String key) {
return getInt(key, null);
}
@Override
public Integer getInt(String key, Integer defaultValue) {
String v = get(key, null);
return v != null ? Integer.parseInt(v) : defaultValue;
}
@Override
public Long getLong(String key) {
return getLong(key, null);
}
@Override
public Long getLong(String key, Long defaultValue) {
String v = get(key, null);
return v != null ? Long.parseLong(v) : defaultValue;
}
@Override
public Boolean getBoolean(String key) {
return getBoolean(key, null);
}
@Override
public Boolean getBoolean(String key, Boolean defaultValue) {
String v = get(key, null);
return v != null ? Boolean.parseBoolean(v) : defaultValue;
}
}
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public static interface Scope {
String get(String key);
String get(String key, String defaultValue);
String[] getArray(String key);
Integer getInt(String key);
Integer getInt(String key, Integer defaultValue);
Long getLong(String key);
Long getLong(String key, Long defaultValue);
Boolean getBoolean(String key);
Boolean getBoolean(String key, Boolean defaultValue);
}
}
+49
View File
@@ -0,0 +1,49 @@
package org.keycloak;
import java.io.Serializable;
import java.security.Principal;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class KeycloakPrincipal implements Principal, Serializable {
protected final String name;
protected final KeycloakSecurityContext context;
public KeycloakPrincipal(String name, KeycloakSecurityContext context) {
this.name = name;
this.context = context;
}
public KeycloakSecurityContext getKeycloakSecurityContext() {
return context;
}
@Override
public String getName() {
return name;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
KeycloakPrincipal that = (KeycloakPrincipal) o;
if (!name.equals(that.name)) return false;
return true;
}
@Override
public int hashCode() {
return name.hashCode();
}
@Override
public String toString() {
return name;
}
}
@@ -0,0 +1,43 @@
package org.keycloak;
import org.keycloak.representations.AccessToken;
import org.keycloak.representations.IDToken;
import java.io.Serializable;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class KeycloakSecurityContext implements Serializable {
protected String tokenString;
protected AccessToken token;
protected IDToken idToken;
protected String idTokenString;
public KeycloakSecurityContext() {
}
public KeycloakSecurityContext(String tokenString, AccessToken token, String idTokenString, IDToken idToken) {
this.tokenString = tokenString;
this.token = token;
this.idToken = idToken;
this.idTokenString = idTokenString;
}
public AccessToken getToken() {
return token;
}
public String getTokenString() {
return tokenString;
}
public IDToken getIdToken() {
return idToken;
}
public String getIdTokenString() {
return idTokenString;
}
}
@@ -0,0 +1,30 @@
package org.keycloak;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public interface OAuth2Constants {
String CODE = "code";
String CLIENT_ID = "client_id";
String ERROR = "error";
String ERROR_DESCRIPTION = "error_description";
String REDIRECT_URI = "redirect_uri";
String SCOPE = "scope";
String STATE = "state";
String GRANT_TYPE = "grant_type";
String RESPONSE_TYPE = "response_type";
String REFRESH_TOKEN = "refresh_token";
}
+64
View File
@@ -0,0 +1,64 @@
package org.keycloak;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class OAuthErrorException extends Exception {
public static final String INVALID_REQUEST = "invalid_request";
public static final String INVALID_CLIENT = "invalid_client";
public static final String INVALID_GRANT = "invalid_grant";
public static final String INVALID_SCOPE = "invalid_grant";
public static final String UNAUTHORIZED_CLIENT = "unauthorized_client";
public static final String UNSUPPORTED_GRANT_TYPE = "unsupported_grant_type";
public OAuthErrorException(String error, String description, String message, Throwable cause) {
super(message, cause);
this.error = error;
this.description = description;
}
public OAuthErrorException(String error, String description, String message) {
super(message);
this.error = error;
this.description = description;
}
public OAuthErrorException(String error, String description) {
super(description);
this.error = error;
this.description = description;
}
public OAuthErrorException(String error, String description, Throwable cause) {
super(description, cause);
this.error = error;
this.description = description;
}
public OAuthErrorException(String error) {
super(error);
this.error = error;
}
public OAuthErrorException(String error, Throwable cause) {
super(error, cause);
this.error = error;
}
protected String error;
protected String description;
public String getError() {
return error;
}
public void setError(String error) {
this.error = error;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
@@ -2,7 +2,7 @@ package org.keycloak;
import org.keycloak.jose.jws.JWSInput;
import org.keycloak.jose.jws.crypto.RSAProvider;
import org.keycloak.representations.SkeletonKeyToken;
import org.keycloak.representations.AccessToken;
import java.io.IOException;
import java.security.PublicKey;
@@ -12,34 +12,45 @@ import java.security.PublicKey;
* @version $Revision: 1 $
*/
public class RSATokenVerifier {
public static AccessToken verifyToken(String tokenString, PublicKey realmKey, String realm) throws VerificationException {
return verifyToken(tokenString, realmKey, realm, true);
}
public static SkeletonKeyToken verifyToken(String tokenString, PublicKey realmKey, String realm) throws VerificationException {
JWSInput input = new JWSInput(tokenString);
boolean verified = false;
public static AccessToken verifyToken(String tokenString, PublicKey realmKey, String realm, boolean checkActive) throws VerificationException {
JWSInput input = null;
try {
verified = RSAProvider.verify(input, realmKey);
} catch (Exception ignore) {
input = new JWSInput(tokenString);
} catch (Exception e) {
throw new VerificationException("Couldn't parse token", e);
}
if (!verified) throw new VerificationException("Token signature not validated");
if (!isPublicKeyValid(input, realmKey)) throw new VerificationException("Invalid token signature.");
SkeletonKeyToken token = null;
AccessToken token;
try {
token = input.readJsonContent(SkeletonKeyToken.class);
token = input.readJsonContent(AccessToken.class);
} catch (IOException e) {
throw new VerificationException(e);
}
if (!token.isActive()) {
throw new VerificationException("Token is not active.");
throw new VerificationException("Couldn't parse token signature", e);
}
String user = token.getSubject();
if (user == null) {
throw new VerificationException("Token user was null");
throw new VerificationException("Token user was null.");
}
if (!realm.equals(token.getAudience())) {
throw new VerificationException("Token audience doesn't match domain");
throw new VerificationException("Token audience doesn't match domain.");
}
if (checkActive && !token.isActive()) {
throw new VerificationException("Token is not active.");
}
return token;
}
private static boolean isPublicKeyValid(JWSInput input, PublicKey realmKey) throws VerificationException {
try {
return RSAProvider.verify(input, realmKey);
} catch (Exception e) {
throw new VerificationException("Token signature not validated.", e);
}
}
}
@@ -6,6 +6,12 @@ package org.keycloak;
*/
public interface ServiceUrlConstants {
public static final String TOKEN_SERVICE_LOGIN_PATH = "/rest/realms/{realm-name}/tokens/login";
public static final String TOKEN_SERVICE_ACCESS_CODE_PATH = "/rest/realms/{realm-name}/tokens/access/codes";
public static final String TOKEN_SERVICE_LOGIN_PATH = "/realms/{realm-name}/tokens/login";
public static final String TOKEN_SERVICE_ACCESS_CODE_PATH = "/realms/{realm-name}/tokens/access/codes";
public static final String TOKEN_SERVICE_REFRESH_PATH = "/realms/{realm-name}/tokens/refresh";
public static final String TOKEN_SERVICE_LOGOUT_PATH = "/realms/{realm-name}/tokens/logout";
public static final String TOKEN_SERVICE_DIRECT_GRANT_PATH = "/realms/{realm-name}/tokens/grants/access";
public static final String ACCOUNT_SERVICE_PATH = "/realms/{realm-name}/account";
public static final String REALM_INFO_PATH = "/realms/{realm-name}";
}
@@ -1,51 +0,0 @@
package org.keycloak;
import java.security.Principal;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class SkeletonKeyPrincipal implements Principal {
protected String name;
protected String surrogate;
public SkeletonKeyPrincipal(String name, String surrogate) {
this.name = name;
this.surrogate = surrogate;
}
@Override
public String getName() {
return name;
}
public String getSurrogate() {
return surrogate;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
SkeletonKeyPrincipal that = (SkeletonKeyPrincipal) o;
if (!name.equals(that.name)) return false;
if (surrogate != null ? !surrogate.equals(that.surrogate) : that.surrogate != null) return false;
return true;
}
@Override
public int hashCode() {
int result = name.hashCode();
result = 31 * result + (surrogate != null ? surrogate.hashCode() : 0);
return result;
}
@Override
public String toString() {
return name;
}
}
@@ -1,38 +0,0 @@
package org.keycloak;
import org.keycloak.adapters.ResourceMetadata;
import org.keycloak.representations.SkeletonKeyToken;
import java.io.Serializable;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class SkeletonKeySession implements Serializable {
protected String tokenString;
protected SkeletonKeyToken token;
protected transient ResourceMetadata metadata;
public SkeletonKeySession() {
}
public SkeletonKeySession(String tokenString, SkeletonKeyToken token, ResourceMetadata metadata) {
this.tokenString = tokenString;
this.token = token;
this.metadata = metadata;
}
public SkeletonKeyToken getToken() {
return token;
}
public String getTokenString() {
return tokenString;
}
public ResourceMetadata getMetadata() {
return metadata;
}
}
+46
View File
@@ -0,0 +1,46 @@
package org.keycloak;
import org.codehaus.jackson.annotate.JsonProperty;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class Version {
public static String VERSION;
public static String BUILD_TIME;
public static final String UNKNOWN = "UNKNOWN";
public static final Version SINGLETON;
private final String version = VERSION;
private final String buildTime = BUILD_TIME;
static {
Properties props = new Properties();
InputStream is = Version.class.getResourceAsStream("/keycloak-version.properties");
try {
props.load(is);
VERSION = props.getProperty("version");
BUILD_TIME = props.getProperty("build-time");
} catch (IOException e) {
VERSION=UNKNOWN;
BUILD_TIME=UNKNOWN;
}
SINGLETON = new Version();
}
@JsonProperty("version")
public String getVersion() {
return version;
}
@JsonProperty("build-time")
public String getBuildTime() {
return buildTime;
}
}
@@ -8,6 +8,10 @@ public interface AdapterConstants {
// URL endpoints
public static final String K_LOGOUT = "k_logout";
public static final String K_VERSION = "k_version";
public static final String K_PUSH_NOT_BEFORE = "k_push_not_before";
public static final String K_GET_USER_STATS = "k_get_user_stats";
public static final String K_GET_SESSION_STATS = "k_get_session_stats";
public static final String K_QUERY_BEARER_TOKEN = "k_query_bearer_token";
// This param name is defined again in Keycloak Subsystem class
Loaded 100 of 1616 files, more files were not shown because too many files have changed in this diff. Show more